From 108f76ea5fd7d5bab795b80b5637fec33f3cf0d9 Mon Sep 17 00:00:00 2001 From: zueuk Date: Thu, 2 Mar 2006 17:34:04 +0000 Subject: [PATCH] part 2... hope all this MT stuff will work ;-) --- 2.10/Source/Main.pas | 123 +++++++++-------- 2.10/Source/Render64.pas | 258 +++++++++++++++++++++++++----------- 2.10/Source/Render64MT.pas | 56 +++++++- 2.10/Source/RenderMM.pas | 188 +++++++++++++++++--------- 2.10/Source/RenderMM_MT.pas | 228 +++++++++++++++++++++---------- 2.10/Source/RndFlame.pas | 3 + 2.10/Source/XForm.pas | 66 ++++++++- 2.10/Source/XFormMan.pas | 7 +- 8 files changed, 645 insertions(+), 284 deletions(-) diff --git a/2.10/Source/Main.pas b/2.10/Source/Main.pas index 8e8f751..a94363c 100644 --- a/2.10/Source/Main.pas +++ b/2.10/Source/Main.pas @@ -1,5 +1,6 @@ { Apophysis Copyright (C) 2001-2004 Mark Townsend + Apophysis Copyright (C) 2005-2006 Ronald Hordijk, Piotr Boris, Peter Sdobnov This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,7 +37,7 @@ const RS_XO = 2; RS_VO = 3; - AppVersionString = 'Apophysis 2.03c'; + AppVersionString = 'Apophysis 2.03d pre-release 1'; type TMouseMoveState = (msUsual, msZoomWindow, msZoomOutWindow, msZoomWindowMove, msZoomOutWindowMove, msDrag, msDragMove, msRotate, msRotateMove); @@ -358,6 +359,7 @@ var MainForm: TMainForm; pname, ptime: string; nxform: integer; + FinalXformLoaded: boolean; ParseCp: TControlPoint; // For parsing; MainCp: TControlPoint; @@ -1312,10 +1314,11 @@ begin Result := ' '; end; @@ -1375,33 +1378,15 @@ begin { Write transform parameters } t := NumXForms(cp1); - for i := 0 to t - 1 do begin + for i := 0 to t - 1 do FileList.Add(cp1.xform[i].ToXMLString); -// with cp1.xform[i] do -// begin -// a := c[0][0]; -// b := c[1][0]; -// cc := c[0][1]; -// d := c[1][1]; -// e := c[2][0]; -// f := c[2][1]; -// varlist := ''; -// for j := 0 to NRVAR - 1 do -// begin -// if vars[j] <> 0 then -// begin -// varlist := varlist + varnames(j) + format('="%f" ', [vars[j]]); -// end; -// end; -// FileList.Add(Format(' ', [a, cc, b, d, e, f])); -// end; - end; +// if cp1.HasFinalXForm then FileList.Add(cp1.finalxform.FinalToXMLString(cp1.finalXformEnabled)); + if cp1.HasFinalXForm then FileList.Add(cp1.xform[t].FinalToXMLString(cp1.finalXformEnabled)); { Write palette data } if not sheep then begin - if not compact then - FileList.Add(ColorToXml(cp1)); - FileList.Add(ColorToXmlcompact(cp1)); + if compact then // say no to duplicated data! (?) + FileList.Add(ColorToXmlCompact(cp1)) + else FileList.Add(ColorToXml(cp1)); end; FileList.Add(''); @@ -1562,7 +1547,7 @@ begin until (Pos('<' + Tag + '>', FileList[FileList.count - 1]) <> 0) or (Pos('', FileList[FileList.count - 1]) <> 0); - FileList.Add(Trim(FlameToXML(cp1, false))); + FileList.Add(Trim(FlameToXML(cp1, false, true))); FileList.Add(''); FileList.SaveToFile(filename); @@ -1576,7 +1561,7 @@ begin AssignFile(IFile, filename); ReWrite(IFile); Writeln(IFile, ''); - Write(IFile, FlameToXML(cp1, false)); + Write(IFile, FlameToXML(cp1, false, true)); Writeln(IFile, ''); CloseFile(IFile); end; @@ -1894,7 +1879,7 @@ begin *) MainCp.name := RandomPrefix + RandomDate + '-' + IntToStr(RandomIndex); - Write(F, FlameToXML(MainCp, False)); + Write(F, FlameToXML(MainCp, False, true)); // Write(F, FlameToString(Title)); // WriteLn(F, ' '); end; @@ -2619,6 +2604,7 @@ begin time := -1; FileStrings := TStringList.Create; ParamStrings := TStringList.Create; + if pos('*untitled', name) <> 0 then begin Tokens := TStringList.Create; @@ -2684,7 +2670,7 @@ begin RedrawTimer.Enabled := True; Application.ProcessMessages; - EditForm.SelectedTriangle := 1; // --Z-- + EditForm.SelectedTriangle := 0; // (?) UpdateWindows; finally @@ -3578,8 +3564,10 @@ begin ScriptEditor.Stopped := True; StopThread; nxform := 0; + FinalXformLoaded := false; Parsecp.cmapindex := -2; // generate pallet from cmapindex and hue (apo 1 and earlier) ParseCp.symmetry := 0; + ParseCP.finalXformEnabled := false; XMLScanner.LoadFromBuffer(params); XMLScanner.Execute; cp1.copy(ParseCp); @@ -3600,6 +3588,11 @@ begin end; end; + if FinalXformLoaded = false then begin + MainCP.xform[nxform].Clear; + MainCP.xform[nxform].symmetry := 1; + end; + if nxform < NXFORMS then for i := nxform to NXFORMS - 1 do cp1.xform[i].density := 0; @@ -3987,77 +3980,83 @@ var begin Tokens := TStringList.Create; try - if TagName = 'xform' then + if (TagName = 'xform') or (TagName = 'finalxform') then + if (TagName = 'finalxform') and (FinalXformLoaded) then ShowMessage('ERROR: No xforms allowed after FinalXform!') + else begin - Parsecp.xform[nxform].Clear; + if (TagName = 'finalxform') then FinalXformLoaded := true; + + with ParseCP.xform[nXform] do begin + Clear; v := Attributes.Value('weight'); - if v <> '' then ParseCp.xform[nxform].density := StrToFloat(v); + if (v <> '') and (TagName = 'xform') then density := StrToFloat(v); + if (TagName = 'finalxform') then + begin + v := Attributes.Value('enabled'); + if v <> '' then ParseCP.finalXformEnabled := (StrToInt(v) <> 0) + else ParseCP.finalXformEnabled := false; + end; v := Attributes.Value('color'); - if v <> '' then Parsecp.xform[nxform].color := StrToFloat(v); + if v <> '' then color := StrToFloat(v); v := Attributes.Value('symmetry'); - if v <> '' then Parsecp.xform[nxform].symmetry := StrToFloat(v); + if v <> '' then symmetry := StrToFloat(v); v := Attributes.Value('coefs'); GetTokens(v, tokens); if Tokens.Count < 6 then ShowMessage('Not enough cooeficients...crash?'); - with Parsecp.xform[nxform] do - begin - c[0][0] := StrToFloat(Tokens[0]); - c[0][1] := StrToFloat(Tokens[1]); - c[1][0] := StrToFloat(Tokens[2]); - c[1][1] := StrToFloat(Tokens[3]); - c[2][0] := StrToFloat(Tokens[4]); - c[2][1] := StrToFloat(Tokens[5]); - end; + c[0][0] := StrToFloat(Tokens[0]); + c[0][1] := StrToFloat(Tokens[1]); + c[1][0] := StrToFloat(Tokens[2]); + c[1][1] := StrToFloat(Tokens[3]); + c[2][0] := StrToFloat(Tokens[4]); + c[2][1] := StrToFloat(Tokens[5]); + v := Attributes.Value('post'); if v <> '' then begin GetTokens(v, tokens); if Tokens.Count < 6 then ShowMessage('Not enough post-cooeficients...crash?'); - with Parsecp.xform[nxform] do - begin - p[0][0] := StrToFloat(Tokens[0]); - p[0][1] := StrToFloat(Tokens[1]); - p[1][0] := StrToFloat(Tokens[2]); - p[1][1] := StrToFloat(Tokens[3]); - p[2][0] := StrToFloat(Tokens[4]); - p[2][1] := StrToFloat(Tokens[5]); - end; + p[0][0] := StrToFloat(Tokens[0]); + p[0][1] := StrToFloat(Tokens[1]); + p[1][0] := StrToFloat(Tokens[2]); + p[1][1] := StrToFloat(Tokens[3]); + p[2][0] := StrToFloat(Tokens[4]); + p[2][1] := StrToFloat(Tokens[5]); end; for i := 0 to NRVAR - 1 do begin - Parsecp.xform[nxform].vars[i] := 0; + vars[i] := 0; v := Attributes.Value(varnames(i)); if v <> '' then - Parsecp.xform[nxform].vars[i] := StrToFloat(v); + vars[i] := StrToFloat(v); end; v := Attributes.Value('var1'); if v <> '' then begin for i := 0 to NRVAR - 1 do - Parsecp.xform[nxform].vars[i] := 0; - Parsecp.xform[nxform].vars[StrToInt(v)] := 1; + vars[i] := 0; + vars[StrToInt(v)] := 1; end; v := Attributes.Value('var'); if v <> '' then begin for i := 0 to NRVAR - 1 do - Parsecp.xform[nxform].vars[i] := 0; + vars[i] := 0; GetTokens(v, tokens); if Tokens.Count > NRVAR then ShowMessage('To many vars..crash?'); for i := 0 to Tokens.Count - 1 do - Parsecp.xform[nxform].vars[i] := StrToFloat(Tokens[i]); + vars[i] := StrToFloat(Tokens[i]); end; for i := 0 to GetNrVariableNames - 1 do begin v := Attributes.Value(GetVariableNameAt(i)); if v <> '' then begin d := StrToFloat(v); - Parsecp.xform[nxform].SetVariable(GetVariableNameAt(i), d); + SetVariable(GetVariableNameAt(i), d); end; end; - - inc(nxform); + end; + Inc(nXform); end; if TagName = 'color' then begin diff --git a/2.10/Source/Render64.pas b/2.10/Source/Render64.pas index 82df848..2901742 100644 --- a/2.10/Source/Render64.pas +++ b/2.10/Source/Render64.pas @@ -22,16 +22,16 @@ interface uses Windows, Graphics, ImageMaker, - Render, Controlpoint; + Render, xform, Controlpoint; type TRenderer64 = class(TBaseRenderer) private - oversample: Int64; + oversample: integer; + + BucketWidth, BucketHeight: integer; + BucketSize: integer; - BucketWidth: Int64; - BucketHeight: Int64; - BucketSize: Int64; gutter_width: Integer; max_gutter_width: Integer; @@ -40,8 +40,12 @@ type Buckets: TBucketArray; ColorMap: TColorMapArray; - bounds: array[0..3] of extended; - size: array[0..1] of extended; + FinalXform: ^TXform; + UseFinalXform: boolean; + + camX0, camX1, camY0, camY1, // camera bounds + camW, camH, // camera sizes + bws, bhs, cosa, sina, rcX, rcY: double; ppux, ppuy: extended; FImageMaker: TImageMaker; @@ -53,8 +57,10 @@ type procedure CreateColorMap; procedure CreateCamera; - procedure AddPointsToBuckets(const points: TPointsArray); overload; - procedure AddPointsToBucketsAngle(const points: TPointsArray); overload; + procedure AddPointsToBuckets(const points: TPointsArray); + procedure AddPointsToBucketsAngle(const points: TPointsArray); + procedure AddPointsWithFX(const points: TPointsArray); + procedure AddPointsWithAngleFX(const points: TPointsArray); procedure SetPixels; public @@ -117,7 +123,7 @@ var scale: double; t0, t1: double; t2, t3: double; - corner0, corner1: double; + corner_x, corner_y, Xsize, Ysize: double; shift: Integer; begin scale := power(2, fcp.zoom); @@ -131,20 +137,32 @@ begin t1 := (gutter_width) / (oversample * ppuy); t2 := (2 * max_gutter_width - gutter_width) / (oversample * ppux); t3 := (2 * max_gutter_width - gutter_width) / (oversample * ppuy); - corner0 := fcp.center[0] - fcp.Width / ppux / 2.0; - corner1 := fcp.center[1] - fcp.Height / ppuy / 2.0; - bounds[0] := corner0 - t0; - bounds[1] := corner1 - t1 + shift; - bounds[2] := corner0 + fcp.Width / ppux + t2; - bounds[3] := corner1 + fcp.Height / ppuy + t3; //+ shift; - if abs(bounds[2] - bounds[0]) > 0.01 then - size[0] := 1.0 / (bounds[2] - bounds[0]) + corner_x := fcp.center[0] - fcp.Width / ppux / 2.0; + corner_y := fcp.center[1] - fcp.Height / ppuy / 2.0; + camX0 := corner_x - t0; + camY0 := corner_y - t1 + shift; + camX1 := corner_x + fcp.Width / ppux + t2; + camY1 := corner_y + fcp.Height / ppuy + t3; //+ shift; + camW := camX1 - camX0; + if abs(camW) > 0.01 then + Xsize := 1.0 / camW else - size[0] := 1; - if abs(bounds[3] - bounds[1]) > 0.01 then - size[1] := 1.0 / (bounds[3] - bounds[1]) + Xsize := 1; + camH := camY1 - camY0; + if abs(camH) > 0.01 then + Ysize := 1.0 / camH else - size[1] := 1; + Ysize := 1; + bws := (BucketWidth - 0.5) * Xsize; + bhs := (BucketHeight - 0.5) * Ysize; + + if FCP.FAngle <> 0 then + begin + cosa := cos(FCP.FAngle); + sina := sin(FCP.FAngle); + rcX := FCP.Center[0]*(1 - cosa) - FCP.Center[1]*sina - camX0; + rcY := FCP.Center[1]*(1 - cosa) + FCP.Center[0]*sina - camY0; + end; end; /////////////////////////////////////////////////////////////////////////////// @@ -202,6 +220,9 @@ begin CreateCamera; CreateColorMap; + + FinalXForm := @fcp.xform[fcp.NumXForms]; + UseFinalXForm := fcp.finalXformEnabled and fcp.HasFinalXform; end; /////////////////////////////////////////////////////////////////////////////// @@ -209,32 +230,19 @@ procedure TRenderer64.AddPointsToBuckets(const points: TPointsArray); var i: integer; px, py: double; - bws, bhs: double; - bx, by: double; - wx, wy: double; Bucket: PBucket; MapColor: PColorMapColor; begin - bws := (BucketWidth - 0.5) * size[0]; - bhs := (BucketHeight - 0.5) * size[1]; - bx := bounds[0]; - by := bounds[1]; - wx := bounds[2] - bounds[0]; - wy := bounds[3] - bounds[1]; - for i := SUB_BATCH_SIZE - 1 downto 0 do begin - if FStop then - Exit; +// if FStop then Exit; - px := points[i].x - bx; - py := points[i].y - by; + px := points[i].x - camX0; + if (px < 0) or (px > camW) then continue; + py := points[i].y - camY0; + if (py < 0) or (py > camH) then continue; - if ((px < 0) or (px > wx) or - (py < 0) or (py > wy)) then - continue; - - MapColor := @ColorMap[Round(points[i].c * 255)]; Bucket := @buckets[Round(bws * px) + Round(bhs * py) * BucketWidth]; + MapColor := @ColorMap[Round(points[i].c * 255)]; Inc(Bucket.Red, MapColor.Red); Inc(Bucket.Green, MapColor.Green); @@ -243,49 +251,104 @@ begin end; end; +procedure TRenderer64.AddPointsWithFX(const points: TPointsArray); +const + const255: single = 255; +var + i: integer; + px, py: double; + Bucket: PBucket; + MapColor: PColorMapColor; +begin + try + for i := SUB_BATCH_SIZE - 1 downto 0 do begin +// if FStop then Exit; + + FinalXform.NextPoint(points[i]); + +{$if true} + px := points[i].x - camX0; + if (px < 0) or (px > camW) then continue; + py := points[i].y - camY0; + if (py < 0) or (py > camH) then continue; + + Bucket := @buckets[Round(bws * px) + Round(bhs * py) * BucketWidth]; + MapColor := @ColorMap[Round(points[i].c * 255)]; + + Inc(Bucket.Red, MapColor.Red); + Inc(Bucket.Green, MapColor.Green); + Inc(Bucket.Blue, MapColor.Blue); + Inc(Bucket.Count); +{$else} +asm + mov eax, [points] + lea edx, [eax + edi*8] // assert: "i" in edi +// fld qword ptr [edx + edi*8] // assert: "i" in edi + fld qword ptr [edx] + fsub qword ptr [bx] + fldz + fcomp st(1), st + fnstsw ax + sahf + jb @skip1 + fld qword ptr [wx] + fcomp + fnstsw ax + sahf + jnbe @skip1 + + fld qword ptr [edx + 8] + fsub qword ptr [by] + fldz + fcomp + fnstsw ax + sahf + jb @skip2 + fld qword ptr [wy] + fcomp + fnstsw ax + sahf + jnbe @skip2 + + fmul qword ptr [bhs] + fimul [BucketWidth] + + fld qword ptr [edx + 16] + fmul dword ptr [const255] + sub esp, 4 + fistp dword ptr [esp] + pop eax + +@skip2: + fstp st +@skip1: + fstp st +@continue: +end; +{$ifend} + end + except + end +end; + /////////////////////////////////////////////////////////////////////////////// procedure TRenderer64.AddPointsToBucketsAngle(const points: TPointsArray); var i: integer; px, py: double; - ca,sa: double; - nx, ny: double; - bws, bhs: double; - bx, by: double; - wx, wy: double; Bucket: PBucket; MapColor: PColorMapColor; begin - - bws := (BucketWidth - 0.5) * size[0]; - bhs := (BucketHeight - 0.5) * size[1]; - bx := bounds[0]; - by := bounds[1]; - wx := bounds[2] - bounds[0]; - wy := bounds[3] - bounds[1]; - - ca := cos(FCP.FAngle); - sa := sin(FCP.FAngle); - for i := SUB_BATCH_SIZE - 1 downto 0 do begin - if FStop then - Exit; +// if FStop then Exit; - px := points[i].x - FCP.Center[0]; - py := points[i].y - FCP.Center[1]; + px := points[i].x * cosa + points[i].y * sina + rcX; + if (px < 0) or (px > camW) then continue; + py := points[i].y * cosa - points[i].x * sina + rcY; + if (py < 0) or (py > camH) then continue; - nx := px * ca + py * sa; - ny := -px * sa + py * ca; - - px := nx + FCP.Center[0] - bx; - py := ny + FCP.Center[1] - by; - - if ((px < 0) or (px > wx) or - (py < 0) or (py > wy)) then - continue; - - MapColor := @ColorMap[Round(points[i].c * 255)]; Bucket := @buckets[Round(bws * px) + Round(bhs * py) * BucketWidth]; + MapColor := @ColorMap[Round(points[i].c * 255)]; Inc(Bucket.Red, MapColor.Red); Inc(Bucket.Green, MapColor.Green); @@ -294,6 +357,36 @@ begin end; end; +procedure TRenderer64.AddPointsWithAngleFX(const points: TPointsArray); +var + i: integer; + px, py: double; + Bucket: PBucket; + MapColor: PColorMapColor; +begin + try + for i := SUB_BATCH_SIZE - 1 downto 0 do + begin +// if FStop then Exit; + FinalXform.NextPoint(points[i]); + + px := points[i].x * cosa + points[i].y * sina + rcX; + if (px < 0) or (px > camW) then continue; + py := points[i].y * cosa - points[i].x * sina + rcY; + if (py < 0) or (py > camH) then continue; + + Bucket := @buckets[Round(bws * px) + Round(bhs * py) * BucketWidth]; + MapColor := @ColorMap[Round(points[i].c * 255)]; + + Inc(Bucket.Red, MapColor.Red); + Inc(Bucket.Green, MapColor.Green); + Inc(Bucket.Blue, MapColor.Blue); + Inc(Bucket.Count); + end; + except + end +end; + /////////////////////////////////////////////////////////////////////////////// procedure TRenderer64.SetPixels; var @@ -301,12 +394,25 @@ var nsamples: Int64; nrbatches: Integer; points: TPointsArray; + AddPointsProc: procedure (const points: TPointsArray) of object; begin // if FileExists('c:\temp\flame.txt') then // Deletefile('c:\temp\flame.txt'); // AssignFile(F, 'c:\temp\flame.txt'); // Rewrite(F); + if FCP.FAngle = 0 then begin + if UseFinalXForm then + AddPointsProc := AddPointsWithFX + else + AddPointsProc := AddPointsToBuckets; + end + else begin + if UseFinalXForm then + AddPointsProc := AddPointsWithAngleFX + else + AddPointsProc := AddPointsToBucketsAngle; + end; SetLength(Points, SUB_BATCH_SIZE); @@ -330,19 +436,19 @@ begin // break; fcp.Testiterate(SUB_BATCH_SIZE, points); {$ELSE} +{ case Compatibility of 0: fcp.iterate_Old(SUB_BATCH_SIZE, points); 1: fcp.iterateXYC(SUB_BATCH_SIZE, points); end; +} + fcp.IterateXYC(SUB_BATCH_SIZE, points); {$ENDIF} // for j := SUB_BATCH_SIZE - 1 downto 0 do // Writeln(f, FloatTostr(points[j].x) + #9 + FloatTostr(points[j].y) + #9 + FloatTostr(points[j].c)); - if FCP.FAngle = 0 then - AddPointsToBuckets(points) - else - AddPointsToBucketsAngle(points); + AddPointsProc(points); end; // closefile(f); diff --git a/2.10/Source/Render64MT.pas b/2.10/Source/Render64MT.pas index 5231d26..581cf00 100644 --- a/2.10/Source/Render64MT.pas +++ b/2.10/Source/Render64MT.pas @@ -42,8 +42,15 @@ type Buckets: TBucketArray; ColorMap: TColorMapArray; - bounds: array[0..3] of extended; - size: array[0..1] of extended; + FinalXform: ^TXform; + UseFinalXform: boolean; + + camX0, camX1, camY0, camY1, // camera bounds + camW, camH, // camera sizes + Xsize, Ysize: double; + bws, bhs, cosa, sina, rcX, rcY: double; +// bounds: array[0..3] of extended; +// size: array[0..1] of extended; ppux, ppuy: extended; FNrOfTreads: integer; WorkingThreads: array of TBucketFillerThread; @@ -113,7 +120,7 @@ var scale: double; t0, t1: double; t2, t3: double; - corner0, corner1: double; + corner_x, corner_y: double; shift: Integer; begin scale := power(2, fcp.zoom); @@ -127,8 +134,9 @@ begin t1 := (gutter_width) / (oversample * ppuy); t2 := (2 * max_gutter_width - gutter_width) / (oversample * ppux); t3 := (2 * max_gutter_width - gutter_width) / (oversample * ppuy); - corner0 := fcp.center[0] - fcp.Width / ppux / 2.0; - corner1 := fcp.center[1] - fcp.Height / ppuy / 2.0; + corner_x := fcp.center[0] - fcp.Width / ppux / 2.0; + corner_y := fcp.center[1] - fcp.Height / ppuy / 2.0; +{ bounds[0] := corner0 - t0; bounds[1] := corner1 - t1 + shift; bounds[2] := corner0 + fcp.Width / ppux + t2; @@ -141,6 +149,31 @@ begin size[1] := 1.0 / (bounds[3] - bounds[1]) else size[1] := 1; +} + camX0 := corner_x - t0; + camY0 := corner_y - t1 + shift; + camX1 := corner_x + fcp.Width / ppux + t2; + camY1 := corner_y + fcp.Height / ppuy + t3; //+ shift; + camW := camX1 - camX0; + if abs(camW) > 0.01 then + Xsize := 1.0 / camW + else + Xsize := 1; + camH := camY1 - camY0; + if abs(camH) > 0.01 then + Ysize := 1.0 / camH + else + Ysize := 1; + bws := (BucketWidth - 0.5) * Xsize; + bhs := (BucketHeight - 0.5) * Ysize; + + if FCP.FAngle <> 0 then + begin + cosa := cos(FCP.FAngle); + sina := sin(FCP.FAngle); + rcX := FCP.Center[0]*(1 - cosa) - FCP.Center[1]*sina - camX0; + rcY := FCP.Center[1]*(1 - cosa) + FCP.Center[0]*sina - camY0; + end; end; /////////////////////////////////////////////////////////////////////////////// @@ -317,6 +350,7 @@ begin Result.BucketWidth := BucketWidth; Result.BucketHeight := BucketHeight; Result.Buckets := @Buckets; +{ Result.size[0] := size[0]; Result.size[1] := size[1]; Result.bounds[0] := Bounds[0]; @@ -325,6 +359,18 @@ begin Result.bounds[3] := Bounds[3]; Result.RotationCenter[0] := FCP.Center[0]; Result.RotationCenter[1] := FCP.Center[1]; +} + Result.camX0 := camX0; + Result.camY0 := camY0; + Result.camW := camW; + Result.camH := camH; + Result.bws := bws; + Result.bhs := bhs; + Result.cosa := cosa; + Result.sina := sina; + Result.rcX := rcX; + Result.rcY := rcY; + Result.ColorMap := colorMap; Result.CriticalSection := CriticalSection; Result.Nrbatches := FNrBatches; diff --git a/2.10/Source/RenderMM.pas b/2.10/Source/RenderMM.pas index 6859934..f3e4a3e 100644 --- a/2.10/Source/RenderMM.pas +++ b/2.10/Source/RenderMM.pas @@ -22,7 +22,7 @@ interface uses Windows, Graphics, - Render, Controlpoint, ImageMaker; + Render, Controlpoint, ImageMaker, XForm; type TRendererMM64 = class(TBaseRenderer) @@ -41,9 +41,15 @@ type Buckets: TBucketArray; ColorMap: TColorMapArray; - bounds: array[0..3] of extended; - size: array[0..1] of extended; - FRotationCenter: array[0..1] of extended; + FinalXform: ^TXform; + UseFinalXform: boolean; + + camX0, camX1, camY0, camY1, // camera bounds + camW, camH, // camera sizes + bws, bhs, cosa, sina, rcX, rcY: double; +// bounds: array[0..3] of extended; +// size: array[0..1] of extended; +// FRotationCenter: array[0..1] of extended; ppux, ppuy: extended; nrSlices: int64; Slice: int64; @@ -56,8 +62,10 @@ type procedure CreateColorMap; procedure CreateCamera; - procedure AddPointsToBuckets(const points: TPointsArray); overload; - procedure AddPointsToBucketsAngle(const points: TPointsArray); overload; + procedure AddPointsToBuckets(const points: TPointsArray); + procedure AddPointsToBucketsAngle(const points: TPointsArray); + procedure AddPointsWithFX(const points: TPointsArray); + procedure AddPointsWithAngleFX(const points: TPointsArray); procedure SetPixels; protected @@ -106,7 +114,7 @@ procedure TRendererMM64.CreateCamera; var scale: double; t0, t1: double; - corner0, corner1: double; + corner_x, corner_y, Xsize, Ysize: double; shift: Integer; begin scale := power(2, fcp.zoom); @@ -117,8 +125,9 @@ begin shift := 0; t0 := gutter_width / (oversample * ppux); t1 := gutter_width / (oversample * ppuy); - corner0 := fcp.center[0] - image_width / ppux / 2.0; - corner1 := fcp.center[1] - image_height / ppuy / 2.0; + corner_x := fcp.center[0] - image_width / ppux / 2.0; + corner_y := fcp.center[1] - image_height / ppuy / 2.0; +{ bounds[0] := corner0 - t0; bounds[1] := corner1 - t1 + shift; bounds[2] := corner0 + image_width / ppux + t0; @@ -131,6 +140,31 @@ begin size[1] := 1.0 / (bounds[3] - bounds[1]) else size[1] := 1; +} + camX0 := corner_x - t0; + camY0 := corner_y - t1 + shift; + camX1 := corner_x + image_width / ppux / 2.0; + camY1 := corner_y + image_height / ppuy + t1; //+ shift; + camW := camX1 - camX0; + if abs(camW) > 0.01 then + Xsize := 1.0 / camW + else + Xsize := 1; + camH := camY1 - camY0; + if abs(camH) > 0.01 then + Ysize := 1.0 / camH + else + Ysize := 1; + bws := (BucketWidth - 0.5) * Xsize; + bhs := (BucketHeight - 0.5) * Ysize; + + if FCP.FAngle <> 0 then + begin + cosa := cos(FCP.FAngle); + sina := sin(FCP.FAngle); + rcX := FCP.Center[0]*(1 - cosa) - FCP.Center[1]*sina - camX0; + rcY := FCP.Center[1]*(1 - cosa) + FCP.Center[0]*sina - camY0; + end; end; /////////////////////////////////////////////////////////////////////////////// @@ -188,6 +222,9 @@ begin InitBuffers; CreateColorMap; + + FinalXForm := @fcp.xform[fcp.NumXForms]; + UseFinalXForm := fcp.finalXformEnabled and fcp.HasFinalXform; end; /////////////////////////////////////////////////////////////////////////////// @@ -195,34 +232,21 @@ procedure TRendererMM64.AddPointsToBuckets(const points: TPointsArray); var i: integer; px, py: double; - bws, bhs: double; - bx, by: double; - wx, wy: double; // R: double; // V1, v2, v3: integer; Bucket: PBucket; MapColor: PColorMapColor; begin - bws := (BucketWidth - 0.5) * size[0]; - bhs := (BucketHeight - 0.5) * size[1]; - bx := bounds[0]; - by := bounds[1]; - wx := bounds[2] - bounds[0]; - wy := bounds[3] - bounds[1]; - for i := SUB_BATCH_SIZE - 1 downto 0 do begin - if FStop then - Exit; +// if FStop then Exit; - px := points[i].x - bx; - py := points[i].y - by; + px := points[i].x - camX0; + if (px < 0) or (px > camW) then continue; + py := points[i].y - camY0; + if (py < 0) or (py > camH) then continue; - if ((px < 0) or (px > wx) or - (py < 0) or (py > wy)) then - continue; - - MapColor := @ColorMap[Round(points[i].c * 255)]; Bucket := @buckets[Round(bws * px) + Round(bhs * py) * BucketWidth]; + MapColor := @ColorMap[Round(points[i].c * 255)]; Inc(Bucket.Red, MapColor.Red); Inc(Bucket.Green, MapColor.Green); @@ -231,57 +255,90 @@ begin end; end; -/////////////////////////////////////////////////////////////////////////////// -procedure TRendererMM64.AddPointsToBucketsAngle(const points: TPointsArray); +procedure TRendererMM64.AddPointsWithFX(const points: TPointsArray); var i: integer; px, py: double; - ca,sa: double; - nx, ny: double; - bws, bhs: double; - bx, by: double; - wx, wy: double; -// R: double; -// V1, v2, v3: integer; Bucket: PBucket; MapColor: PColorMapColor; begin - - bws := (BucketWidth - 0.5) * size[0]; - bhs := (BucketHeight - 0.5) * size[1]; - bx := bounds[0]; - by := bounds[1]; - wx := bounds[2] - bounds[0]; - wy := bounds[3] - bounds[1]; - - ca := cos(FCP.FAngle); - sa := sin(FCP.FAngle); - + try for i := SUB_BATCH_SIZE - 1 downto 0 do begin - if FStop then - Exit; +// if FStop then Exit; - px := points[i].x - FRotationCenter[0]; - py := points[i].y - FRotationCenter[1]; + FinalXform.NextPoint(points[i]); - nx := px * ca + py * sa; - ny := -px * sa + py * ca; + px := points[i].x - camX0; + if (px < 0) or (px > camW) then continue; + py := points[i].y - camY0; + if (py < 0) or (py > camH) then continue; - px := nx + FRotationCenter[0] - bx; - py := ny + FRotationCenter[1] - by; - - if ((px < 0) or (px > wx) or - (py < 0) or (py > wy)) then - continue; - - MapColor := @ColorMap[Round(points[i].c * 255)]; Bucket := @buckets[Round(bws * px) + Round(bhs * py) * BucketWidth]; + MapColor := @ColorMap[Round(points[i].c * 255)]; Inc(Bucket.Red, MapColor.Red); Inc(Bucket.Green, MapColor.Green); Inc(Bucket.Blue, MapColor.Blue); Inc(Bucket.Count); end; + except + end +end; + +/////////////////////////////////////////////////////////////////////////////// +procedure TRendererMM64.AddPointsToBucketsAngle(const points: TPointsArray); +var + i: integer; + px, py: double; + Bucket: PBucket; + MapColor: PColorMapColor; +begin + for i := SUB_BATCH_SIZE - 1 downto 0 do begin +// if FStop then Exit; + + px := points[i].x * cosa + points[i].y * sina + rcX; + if (px < 0) or (px > camW) then continue; + py := points[i].y * cosa - points[i].x * sina + rcY; + if (py < 0) or (py > camH) then continue; + + Bucket := @buckets[Round(bws * px) + Round(bhs * py) * BucketWidth]; + MapColor := @ColorMap[Round(points[i].c * 255)]; + + Inc(Bucket.Red, MapColor.Red); + Inc(Bucket.Green, MapColor.Green); + Inc(Bucket.Blue, MapColor.Blue); + Inc(Bucket.Count); + end; +end; + +procedure TRendererMM64.AddPointsWithAngleFX(const points: TPointsArray); +var + i: integer; + px, py: double; + Bucket: PBucket; + MapColor: PColorMapColor; +begin + try + for i := SUB_BATCH_SIZE - 1 downto 0 do + begin +// if FStop then Exit; + FinalXform.NextPoint(points[i]); + + px := points[i].x * cosa + points[i].y * sina + rcX; + if (px < 0) or (px > camW) then continue; + py := points[i].y * cosa - points[i].x * sina + rcY; + if (py < 0) or (py > camH) then continue; + + Bucket := @buckets[Round(bws * px) + Round(bhs * py) * BucketWidth]; + MapColor := @ColorMap[Round(points[i].c * 255)]; + + Inc(Bucket.Red, MapColor.Red); + Inc(Bucket.Green, MapColor.Green); + Inc(Bucket.Blue, MapColor.Blue); + Inc(Bucket.Count); + end; + except + end end; /////////////////////////////////////////////////////////////////////////////// @@ -309,10 +366,13 @@ begin Progress(0); // generate points +{ case Compatibility of 0: fcp.iterate_Old(SUB_BATCH_SIZE, points); 1: fcp.iterateXYC(SUB_BATCH_SIZE, points); end; +} + fcp.IterateXYC(SUB_BATCH_SIZE, points); if FCP.FAngle = 0 then AddPointsToBuckets(points) @@ -343,8 +403,8 @@ var begin FStop := False; - FRotationCenter[0] := fcp.center[0]; - FRotationCenter[1] := fcp.center[1]; +// FRotationCenter[0] := fcp.center[0]; +// FRotationCenter[1] := fcp.center[1]; image_height := fcp.Height; image_Width := fcp.Width; diff --git a/2.10/Source/RenderMM_MT.pas b/2.10/Source/RenderMM_MT.pas index 4f8de76..11de4bc 100644 --- a/2.10/Source/RenderMM_MT.pas +++ b/2.10/Source/RenderMM_MT.pas @@ -22,17 +22,15 @@ interface uses Windows, Graphics, - Render, Controlpoint, ImageMaker, BucketFillerThread; + Render, Controlpoint, ImageMaker, BucketFillerThread, XForm; type TRendererMM64_MT = class(TBaseRenderer) private oversample: Integer; - image_Width: Int64; - image_Height: Int64; - BucketWidth: Integer; - BucketHeight: Integer; + image_Width, image_Height: integer; // we're not going to render images + BucketWidth, BucketHeight: integer; // more then 2^32 pixels wide, are we? :) BucketSize: Integer; gutter_width: Integer; @@ -41,9 +39,16 @@ type Buckets: TBucketArray; ColorMap: TColorMapArray; - bounds: array[0..3] of extended; - size: array[0..1] of extended; - FRotationCenter: array[0..1] of extended; + FinalXform: ^TXform; + UseFinalXform: boolean; + + camX0, camX1, camY0, camY1, // camera bounds + camW, camH, // camera sizes + bws, bhs, cosa, sina, rcX, rcY: double; +// bounds: array[0..3] of extended; +// size: array[0..1] of extended; +// FRotationCenter: array[0..1] of extended; + ppux, ppuy: extended; nrSlices: int64; Slice: int64; @@ -62,8 +67,10 @@ type procedure CreateColorMap; procedure CreateCamera; - procedure AddPointsToBuckets(const points: TPointsArray); overload; - procedure AddPointsToBucketsAngle(const points: TPointsArray); overload; + procedure AddPointsToBuckets(const points: TPointsArray); + procedure AddPointsToBucketsAngle(const points: TPointsArray); + procedure AddPointsWithFX(const points: TPointsArray); + procedure AddPointsWithAngleFX(const points: TPointsArray); procedure SetPixels; procedure SetPixelsMT; @@ -119,7 +126,7 @@ procedure TRendererMM64_MT.CreateCamera; var scale: double; t0, t1: double; - corner0, corner1: double; + corner_x, corner_y, Xsize, Ysize: double; shift: Integer; begin scale := power(2, fcp.zoom); @@ -130,8 +137,9 @@ begin shift := 0; t0 := gutter_width / (oversample * ppux); t1 := gutter_width / (oversample * ppuy); - corner0 := fcp.center[0] - image_width / ppux / 2.0; - corner1 := fcp.center[1] - image_height / ppuy / 2.0; + corner_x := fcp.center[0] - image_width / ppux / 2.0; + corner_y := fcp.center[1] - image_height / ppuy / 2.0; +{ bounds[0] := corner0 - t0; bounds[1] := corner1 - t1 + shift; bounds[2] := corner0 + image_width / ppux + t0; @@ -144,6 +152,31 @@ begin size[1] := 1.0 / (bounds[3] - bounds[1]) else size[1] := 1; +} + camX0 := corner_x - t0; + camY0 := corner_y - t1 + shift; + camX1 := corner_x + image_width / ppux + t0; + camY1 := corner_y + image_height / ppuy + t1; //+ shift; + camW := camX1 - camX0; + if abs(camW) > 0.01 then + Xsize := 1.0 / camW + else + Xsize := 1; + camH := camY1 - camY0; + if abs(camH) > 0.01 then + Ysize := 1.0 / camH + else + Ysize := 1; + bws := (BucketWidth - 0.5) * Xsize; + bhs := (BucketHeight - 0.5) * Ysize; + + if FCP.FAngle <> 0 then + begin + cosa := cos(FCP.FAngle); + sina := sin(FCP.FAngle); + rcX := FCP.Center[0]*(1 - cosa) - FCP.Center[1]*sina - camX0; + rcY := FCP.Center[1]*(1 - cosa) + FCP.Center[0]*sina - camY0; + end; end; /////////////////////////////////////////////////////////////////////////////// @@ -201,6 +234,9 @@ begin InitBuffers; CreateColorMap; + + FinalXForm := @fcp.xform[fcp.NumXForms]; + UseFinalXForm := fcp.finalXformEnabled and fcp.HasFinalXform; end; /////////////////////////////////////////////////////////////////////////////// @@ -208,34 +244,21 @@ procedure TRendererMM64_MT.AddPointsToBuckets(const points: TPointsArray); var i: integer; px, py: double; - bws, bhs: double; - bx, by: double; - wx, wy: double; // R: double; // V1, v2, v3: integer; Bucket: PBucket; MapColor: PColorMapColor; begin - bws := (BucketWidth - 0.5) * size[0]; - bhs := (BucketHeight - 0.5) * size[1]; - bx := bounds[0]; - by := bounds[1]; - wx := bounds[2] - bounds[0]; - wy := bounds[3] - bounds[1]; - for i := SUB_BATCH_SIZE - 1 downto 0 do begin - if FStop then - Exit; +// if FStop then Exit; - px := points[i].x - bx; - py := points[i].y - by; + px := points[i].x - camX0; + if (px < 0) or (px > camW) then continue; + py := points[i].y - camY0; + if (py < 0) or (py > camH) then continue; - if ((px < 0) or (px > wx) or - (py < 0) or (py > wy)) then - continue; - - MapColor := @ColorMap[Round(points[i].c * 255)]; Bucket := @buckets[Round(bws * px) + Round(bhs * py) * BucketWidth]; + MapColor := @ColorMap[Round(points[i].c * 255)]; Inc(Bucket.Red, MapColor.Red); Inc(Bucket.Green, MapColor.Green); @@ -244,57 +267,90 @@ begin end; end; -/////////////////////////////////////////////////////////////////////////////// -procedure TRendererMM64_MT.AddPointsToBucketsAngle(const points: TPointsArray); +procedure TRendererMM64_MT.AddPointsWithFX(const points: TPointsArray); var i: integer; px, py: double; - ca,sa: double; - nx, ny: double; - bws, bhs: double; - bx, by: double; - wx, wy: double; -// R: double; -// V1, v2, v3: integer; Bucket: PBucket; MapColor: PColorMapColor; begin - - bws := (BucketWidth - 0.5) * size[0]; - bhs := (BucketHeight - 0.5) * size[1]; - bx := bounds[0]; - by := bounds[1]; - wx := bounds[2] - bounds[0]; - wy := bounds[3] - bounds[1]; - - ca := cos(FCP.FAngle); - sa := sin(FCP.FAngle); - + try for i := SUB_BATCH_SIZE - 1 downto 0 do begin - if FStop then - Exit; +// if FStop then Exit; - px := points[i].x - FRotationCenter[0]; - py := points[i].y - FRotationCenter[1]; + FinalXform.NextPoint(points[i]); - nx := px * ca + py * sa; - ny := -px * sa + py * ca; + px := points[i].x - camX0; + if (px < 0) or (px > camW) then continue; + py := points[i].y - camY0; + if (py < 0) or (py > camH) then continue; - px := nx + FRotationCenter[0] - bx; - py := ny + FRotationCenter[1] - by; - - if ((px < 0) or (px > wx) or - (py < 0) or (py > wy)) then - continue; - - MapColor := @ColorMap[Round(points[i].c * 255)]; Bucket := @buckets[Round(bws * px) + Round(bhs * py) * BucketWidth]; + MapColor := @ColorMap[Round(points[i].c * 255)]; Inc(Bucket.Red, MapColor.Red); Inc(Bucket.Green, MapColor.Green); Inc(Bucket.Blue, MapColor.Blue); Inc(Bucket.Count); end; + except + end +end; + +/////////////////////////////////////////////////////////////////////////////// +procedure TRendererMM64_MT.AddPointsToBucketsAngle(const points: TPointsArray); +var + i: integer; + px, py: double; + Bucket: PBucket; + MapColor: PColorMapColor; +begin + for i := SUB_BATCH_SIZE - 1 downto 0 do begin +// if FStop then Exit; + + px := points[i].x * cosa + points[i].y * sina + rcX; + if (px < 0) or (px > camW) then continue; + py := points[i].y * cosa - points[i].x * sina + rcY; + if (py < 0) or (py > camH) then continue; + + Bucket := @buckets[Round(bws * px) + Round(bhs * py) * BucketWidth]; + MapColor := @ColorMap[Round(points[i].c * 255)]; + + Inc(Bucket.Red, MapColor.Red); + Inc(Bucket.Green, MapColor.Green); + Inc(Bucket.Blue, MapColor.Blue); + Inc(Bucket.Count); + end; +end; + +procedure TRendererMM64_MT.AddPointsWithAngleFX(const points: TPointsArray); +var + i: integer; + px, py: double; + Bucket: PBucket; + MapColor: PColorMapColor; +begin + try + for i := SUB_BATCH_SIZE - 1 downto 0 do + begin +// if FStop then Exit; + FinalXform.NextPoint(points[i]); + + px := points[i].x * cosa + points[i].y * sina + rcX; + if (px < 0) or (px > camW) then continue; + py := points[i].y * cosa - points[i].x * sina + rcY; + if (py < 0) or (py > camH) then continue; + + Bucket := @buckets[Round(bws * px) + Round(bhs * py) * BucketWidth]; + MapColor := @ColorMap[Round(points[i].c * 255)]; + + Inc(Bucket.Red, MapColor.Red); + Inc(Bucket.Green, MapColor.Green); + Inc(Bucket.Blue, MapColor.Blue); + Inc(Bucket.Count); + end; + except + end end; /////////////////////////////////////////////////////////////////////////////// @@ -304,7 +360,21 @@ var nsamples: Int64; nrbatches: Integer; points: TPointsArray; + AddPointsProc: procedure (const points: TPointsArray) of object; begin + if FCP.FAngle = 0 then begin + if UseFinalXForm then + AddPointsProc := AddPointsWithFX + else + AddPointsProc := AddPointsToBuckets; + end + else begin + if UseFinalXForm then + AddPointsProc := AddPointsWithAngleFX + else + AddPointsProc := AddPointsToBucketsAngle; + end; + SetLength(Points, SUB_BATCH_SIZE); nsamples := Round(sample_density * bucketSize / (oversample * oversample)); @@ -322,15 +392,14 @@ begin Progress(0); // generate points - case Compatibility of +{ case Compatibility of 0: fcp.iterate_Old(SUB_BATCH_SIZE, points); 1: fcp.iterateXYC(SUB_BATCH_SIZE, points); end; +} + fcp.IterateXYC(SUB_BATCH_SIZE, points); - if FCP.FAngle = 0 then - AddPointsToBuckets(points) - else - AddPointsToBucketsAngle(points); + AddPointsProc(points) end; Progress(1); @@ -355,8 +424,8 @@ var begin FStop := False; - FRotationCenter[0] := fcp.center[0]; - FRotationCenter[1] := fcp.center[1]; +// FRotationCenter[0] := fcp.center[0]; +// FRotationCenter[1] := fcp.center[1]; image_height := fcp.Height; image_Width := fcp.Width; @@ -493,6 +562,7 @@ begin Result.BucketWidth := BucketWidth; Result.BucketHeight := BucketHeight; Result.Buckets := @Buckets; +{ Result.size[0] := size[0]; Result.size[1] := size[1]; Result.bounds[0] := Bounds[0]; @@ -501,6 +571,18 @@ begin Result.bounds[3] := Bounds[3]; Result.RotationCenter[0] := FRotationCenter[0]; Result.RotationCenter[1] := FRotationCenter[1]; +} + Result.camX0 := camX0; + Result.camY0 := camY0; + Result.camW := camW; + Result.camH := camH; + Result.bws := bws; + Result.bhs := bhs; + Result.cosa := cosa; + Result.sina := sina; + Result.rcX := rcX; + Result.rcY := rcY; + Result.ColorMap := colorMap; Result.CriticalSection := CriticalSection; Result.Nrbatches := FNrBatches; diff --git a/2.10/Source/RndFlame.pas b/2.10/Source/RndFlame.pas index bb85dd1..323dfe1 100644 --- a/2.10/Source/RndFlame.pas +++ b/2.10/Source/RndFlame.pas @@ -432,6 +432,9 @@ begin Result.zoom := 0; Result.Nick := SheepNick; Result.URl := SheepURL; + + Result.xform[Result.NumXForms].Clear; + Result.xform[Result.NumXForms].symmetry := 1; end; end. diff --git a/2.10/Source/XForm.pas b/2.10/Source/XForm.pas index b06749d..9243e08 100644 --- a/2.10/Source/XForm.pas +++ b/2.10/Source/XForm.pas @@ -78,6 +78,7 @@ type procedure Bubble; // var[24] procedure Cylinder; // var[25] procedure Smoke; // var[26] + procedure Noise; // var[27] function Mul33(const M1, M2: TMatrix): TMatrix; function Identity: TMatrix; @@ -123,6 +124,7 @@ type procedure GetVariable(const name: string; var Value: double); function ToXMLString: string; + function FinalToXMLString(IsEnabled: boolean): string; end; implementation @@ -131,7 +133,7 @@ uses SysUtils, Math; const - EPS: double = 1E-10; + EPS: double = 1E-6; procedure SinCos(const Theta: double; var Sin, Cos: double); // I'm not sure, but maybe it'll help... asm @@ -1488,6 +1490,39 @@ asm {$endif} end; +//--27--/////////////////////////////////////////////////////////////////////// +procedure TXForm.Noise; +{$ifndef _ASM_} +var + r, sinr, cosr: double; +begin + SinCos(random * 2*pi, sinr, cosr); + r := vars[27]*random;//(sqrt(sqr(ftx)+sqr(fty)) + eps); + FPx := FPx + {FTx*}r*cosr; + FPy := FPy + {FTy*}r*sinr; +{$else} +asm + mov edx, [ebx + vars] + fld qword ptr [edx + 27*8] + call System.@RandExt + fmulp + call System.@RandExt + fadd st, st + fldpi + fmulp + fsincos + fmul st, st(2) + fmul qword ptr [ebx + FTx] + fadd qword ptr [ebx + FPx] + fstp qword ptr [ebx + FPx] + fmulp + fmul qword ptr [ebx + FTy] + fadd qword ptr [ebx + FPy] + fstp qword ptr [ebx + FPy] + fwait +{$endif} +end; + //***************************************************************************// procedure TXForm.NextPoint(var px, py, pc: double); @@ -1849,6 +1884,7 @@ begin FFunctionList[24] := Bubble; FFunctionList[25] := Cylinder; FFunctionList[26] := Smoke; + FFunctionList[27] := Noise; //registered for i := 0 to High(FRegVariations) do @@ -1924,6 +1960,34 @@ begin Result := Result + '/>'; end; +function TXForm.FinalToXMLString(IsEnabled: boolean): string; +var + i, j: integer; + Name: string; + Value: double; +begin + result := Format(' 0 then + Result := Result + varnames(i) + format('="%g" ', [vars[i]]); + end; + Result := Result + Format('coefs="%g %g %g %g %g %g" ', [c[0,0], c[0,1], c[1,0], c[1,1], c[2,0], c[2,1]]); + if (p[0,0]<>1) or (p[0,1]<>0) or(p[1,0]<>0) or (p[1,1]<>1) or (p[2,0]<>0) or (p[2,1]<>0) then + Result := Result + Format('post="%g %g %g %g %g %g" ', [p[0,0], p[0,1], p[1,0], p[1,1], p[2,0], p[2,1]]); + + for i := 0 to High(FRegVariations) do begin + if vars[i+NRLOCVAR] <> 0 then + for j:= 0 to FRegVariations[i].GetNrVariables -1 do begin + Name := FRegVariations[i].GetVariableNameAt(j); + FRegVariations[i].GetVariable(Name,Value); + Result := Result + Format('%s="%g" ', [name, value]); + end; + end; + + Result := Result + '/>'; +end; + /////////////////////////////////////////////////////////////////////////////// procedure TXForm.SetVariable(const name: string; var Value: double); var diff --git a/2.10/Source/XFormMan.pas b/2.10/Source/XFormMan.pas index 33a102e..ab22682 100644 --- a/2.10/Source/XFormMan.pas +++ b/2.10/Source/XFormMan.pas @@ -6,7 +6,7 @@ uses BaseVariation; const - NRLOCVAR = 26; + NRLOCVAR = 28; function NrVar: integer; function Varnames(const index: integer): String; @@ -60,8 +60,9 @@ const 'fan', 'eyefish', 'bubble', - 'cylinder' -// 'smoke' - variation disabled... for now :) + 'cylinder', + 'smoke', + 'noise' ); begin if Index < NRLOCVAR then