719 lines
18 KiB
ObjectPascal
719 lines
18 KiB
ObjectPascal
|
{
|
||
|
Apophysis Copyright (C) 2001-2004 Mark Townsend
|
||
|
Apophysis Copyright (C) 2005-2006 Ronald Hordijk, Piotr Borys, Peter Sdobnov
|
||
|
Apophysis Copyright (C) 2007-2008 Piotr Borys, Peter Sdobnov
|
||
|
|
||
|
Apophysis "3D hack" Copyright (C) 2007-2008 Peter Sdobnov
|
||
|
Apophysis "7X" Copyright (C) 2009-2010 Georg Kiehne
|
||
|
|
||
|
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
|
||
|
the Free Software Foundation; either version 2 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program; if not, write to the Free Software
|
||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||
|
}
|
||
|
unit RenderingImplementation;
|
||
|
|
||
|
{$ifdef Apo7X64}
|
||
|
{$else}
|
||
|
// {$define _ASM_}
|
||
|
{$endif}
|
||
|
|
||
|
interface
|
||
|
|
||
|
uses
|
||
|
{$ifndef _ASM_}
|
||
|
{$else}
|
||
|
AsmRandom,
|
||
|
{$endif}
|
||
|
Windows, Classes, Forms, Graphics, Global,
|
||
|
RenderingInterface, Xform, Math, Translation,
|
||
|
Binary, RenderingCommon, ControlPoint, Sysutils,
|
||
|
BucketFillerThread;
|
||
|
|
||
|
type
|
||
|
TBatchProc = procedure of object;
|
||
|
TRenderWorkerST = class(TBaseRenderer)
|
||
|
|
||
|
protected
|
||
|
PropTable: array[0..PROP_TABLE_SIZE] of TXform;
|
||
|
finalXform: TXform;
|
||
|
UseFinalXform: boolean;
|
||
|
|
||
|
procedure Prepare; override;
|
||
|
procedure SetPixels; override;
|
||
|
|
||
|
protected
|
||
|
procedure IterateBatch;
|
||
|
procedure IterateBatchAngle;
|
||
|
procedure IterateBatchFX;
|
||
|
procedure IterateBatchAngleFX;
|
||
|
end;
|
||
|
|
||
|
type
|
||
|
TRenderWorkerMT = class(TBaseRenderer)
|
||
|
|
||
|
protected
|
||
|
batchcounter: Integer;
|
||
|
WorkingThreads: array of TBucketFillerThread;
|
||
|
CriticalSection: TRTLCriticalSection;
|
||
|
|
||
|
function NewThread: TBucketFillerThread;
|
||
|
procedure Prepare; override;
|
||
|
procedure SetPixels; override;
|
||
|
|
||
|
protected
|
||
|
procedure AddPointsToBuckets(const points: TPointsArray);
|
||
|
procedure AddPointsToBucketsAngle(const points: TPointsArray);
|
||
|
|
||
|
public
|
||
|
procedure Stop; override;
|
||
|
procedure BreakRender; override;
|
||
|
|
||
|
procedure Pause; override;
|
||
|
procedure UnPause; override;
|
||
|
end;
|
||
|
|
||
|
type
|
||
|
TRenderWorkerST_MM = class(TRenderWorkerST)
|
||
|
protected
|
||
|
procedure CalcBufferSize; override;
|
||
|
public
|
||
|
procedure Render; override;
|
||
|
|
||
|
end;
|
||
|
|
||
|
type
|
||
|
TRenderWorkerMT_MM = class(TRenderWorkerMT)
|
||
|
protected
|
||
|
procedure CalcBufferSize; override;
|
||
|
public
|
||
|
procedure Render; override;
|
||
|
end;
|
||
|
|
||
|
// ----------------------------------------------------------------------------
|
||
|
|
||
|
implementation
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
// PREPARE
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
procedure TRenderWorkerST.Prepare;
|
||
|
var
|
||
|
i, n: Integer;
|
||
|
propsum: double;
|
||
|
LoopValue: double;
|
||
|
j: integer;
|
||
|
TotValue: double;
|
||
|
begin
|
||
|
totValue := 0;
|
||
|
n := fcp.NumXforms;
|
||
|
assert(n > 0);
|
||
|
|
||
|
finalXform := fcp.xform[n];
|
||
|
finalXform.Prepare;
|
||
|
useFinalXform := fcp.FinalXformEnabled and fcp.HasFinalXform;
|
||
|
|
||
|
fcp.Prepare;
|
||
|
end;
|
||
|
procedure TRenderWorkerMT.Prepare;
|
||
|
begin
|
||
|
fcp.Prepare;
|
||
|
end;
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
// SETPIXELS
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
procedure TRenderWorkerST.SetPixels;
|
||
|
var
|
||
|
i: integer;
|
||
|
nsamples: int64;
|
||
|
IterateBatchProc: procedure of object;
|
||
|
begin
|
||
|
if FNumSlices > 1 then
|
||
|
TimeTrace(Format(TextByKey('common-trace-rendering-multipleslices'), [FSlice + 1, FNumSlices]))
|
||
|
else
|
||
|
TimeTrace(TextByKey('common-trace-rendering-oneslice'));
|
||
|
|
||
|
Randomize;
|
||
|
|
||
|
if FCP.FAngle = 0 then begin
|
||
|
if UseFinalXform then
|
||
|
IterateBatchProc := IterateBatchFX
|
||
|
else
|
||
|
IterateBatchProc := IterateBatch;
|
||
|
end
|
||
|
else begin
|
||
|
if UseFinalXform then
|
||
|
IterateBatchProc := IterateBatchAngleFX
|
||
|
else
|
||
|
IterateBatchProc := IterateBatchAngle;
|
||
|
end;
|
||
|
|
||
|
NSamples := Round(sample_density * NrSlices * bucketSize / (oversample * oversample));
|
||
|
FNumBatches := Round(nsamples / (fcp.nbatches * SUB_BATCH_SIZE));
|
||
|
if FNumBatches = 0 then FNumBatches := 1;
|
||
|
|
||
|
FMinBatches := Round(FNumBatches * FMinDensity / fcp.sample_density);
|
||
|
if FMinBatches = 0 then FMinBatches := 1;
|
||
|
|
||
|
for i := 0 to FNumBatches-1 do begin
|
||
|
if FStop <> 0 then begin
|
||
|
fcp.actual_density := fcp.actual_density + fcp.sample_density * i / FNumBatches;
|
||
|
FNumBatches := i;
|
||
|
exit;
|
||
|
end;
|
||
|
|
||
|
if ((i and $1F) = 0) then Progress(i / FNumBatches);
|
||
|
|
||
|
IterateBatchProc;
|
||
|
Inc(FBatch);
|
||
|
end;
|
||
|
|
||
|
fcp.actual_density := fcp.actual_density + fcp.sample_density;
|
||
|
|
||
|
Progress(1);
|
||
|
end;
|
||
|
procedure TRenderWorkerMT.SetPixels;
|
||
|
var
|
||
|
i: integer;
|
||
|
nSamples: Int64;
|
||
|
bc : integer;
|
||
|
begin
|
||
|
if FNumSlices > 1 then
|
||
|
TimeTrace(Format(TextByKey('common-trace-rendering-multipleslices'), [FSlice + 1, FNumSlices]))
|
||
|
else
|
||
|
TimeTrace(TextByKey('common-trace-rendering-oneslice'));
|
||
|
|
||
|
nSamples := Round(sample_density * NrSlices * BucketSize / (oversample * oversample));
|
||
|
FNumBatches := Round(nSamples / (fcp.nbatches * SUB_BATCH_SIZE));
|
||
|
if FNumBatches = 0 then FNumBatches := 1;
|
||
|
FMinBatches := Round(FNumBatches * FMinDensity / fcp.sample_density);
|
||
|
|
||
|
batchcounter := 1;
|
||
|
Randomize;
|
||
|
|
||
|
InitializeCriticalSection(CriticalSection);
|
||
|
|
||
|
SetLength(WorkingThreads, NumThreads);
|
||
|
for i := 0 to NumThreads - 1 do
|
||
|
WorkingThreads[i] := NewThread;
|
||
|
|
||
|
for i := 0 to NumThreads - 1 do
|
||
|
WorkingThreads[i].Resume;
|
||
|
|
||
|
bc := 1;
|
||
|
while (FStop = 0) and (bc <= FNumBatches) do begin
|
||
|
sleep(250);
|
||
|
try
|
||
|
EnterCriticalSection(CriticalSection);
|
||
|
|
||
|
Progress(batchcounter / FNumBatches);
|
||
|
bc := batchcounter;
|
||
|
finally
|
||
|
LeaveCriticalSection(CriticalSection);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
for i := 0 to High(WorkingThreads) do begin
|
||
|
WorkingThreads[i].Terminate;
|
||
|
WorkingThreads[i].WaitFor;
|
||
|
WorkingThreads[i].Free;
|
||
|
end;
|
||
|
SetLength(WorkingThreads, 0);
|
||
|
|
||
|
fcp.actual_density := fcp.actual_density +
|
||
|
fcp.sample_density * BatchCounter / FNumBatches; // actual quality of incomplete render
|
||
|
FNumBatches := BatchCounter;
|
||
|
|
||
|
DeleteCriticalSection(CriticalSection);
|
||
|
Progress(1);
|
||
|
end;
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
// MM OVERRIDES
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
procedure TRenderWorkerST_MM.CalcBufferSize;
|
||
|
begin
|
||
|
CalcBufferSizeMM;
|
||
|
end;
|
||
|
procedure TRenderWorkerST_MM.Render;
|
||
|
begin
|
||
|
RenderMM;
|
||
|
end;
|
||
|
procedure TRenderWorkerMT_MM.CalcBufferSize;
|
||
|
begin
|
||
|
CalcBufferSizeMM;
|
||
|
end;
|
||
|
procedure TRenderWorkerMT_MM.Render;
|
||
|
begin
|
||
|
RenderMM;
|
||
|
end;
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
// BATCH ITERATION
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
procedure TRenderWorkerST.IterateBatch;
|
||
|
var
|
||
|
i: integer;
|
||
|
px, py: double;
|
||
|
Bucket: PBucket;
|
||
|
ZBufPos: PDouble;
|
||
|
MapColor: PColorMapColor;
|
||
|
|
||
|
ix, iy: integer;
|
||
|
BmpColor: TColor;
|
||
|
|
||
|
p, q: TCPPoint;
|
||
|
xf: TXForm;
|
||
|
begin
|
||
|
{$ifndef _ASM_}
|
||
|
p.x := 2 * random - 1;
|
||
|
p.y := 2 * random - 1;
|
||
|
p.c := random;
|
||
|
{$else}
|
||
|
asm
|
||
|
fld1
|
||
|
call AsmRandExt
|
||
|
fadd st, st
|
||
|
fsub st, st(1)
|
||
|
fstp qword ptr [p.x]
|
||
|
call AsmRandExt
|
||
|
fadd st, st
|
||
|
fsubrp st(1), st
|
||
|
fstp qword ptr [p.y]
|
||
|
call AsmRandExt
|
||
|
fstp qword ptr [p.c]
|
||
|
end;
|
||
|
{$endif}
|
||
|
|
||
|
try
|
||
|
xf := fcp.xform[0];
|
||
|
for i := 0 to FUSE do begin
|
||
|
xf := xf.PropTable[Random(PROP_TABLE_SIZE)];
|
||
|
xf.NextPoint(p);
|
||
|
end;
|
||
|
|
||
|
for i := 0 to SUB_BATCH_SIZE-1 do begin
|
||
|
xf := xf.PropTable[Random(PROP_TABLE_SIZE)];
|
||
|
xf.NextPoint(p);
|
||
|
|
||
|
if random >= xf.transOpacity then continue;
|
||
|
|
||
|
q := p;
|
||
|
fcp.ProjectionFunc(@q); // 3d hack
|
||
|
|
||
|
px := q.x - camX0;
|
||
|
if (px < 0) or (px > camW) then continue;
|
||
|
py := q.y - camY0;
|
||
|
if (py < 0) or (py > camH) then continue;
|
||
|
|
||
|
Bucket := @buckets[Round(bhs * py)][Round(bws * px)];
|
||
|
MapColor := @ColorMap[Round(p.c * 255)];
|
||
|
{$ifdef ENABLEZBUF}
|
||
|
ZBufPos := @zbuffer[Round(bhs * py)][Round(bws * px)];
|
||
|
if (q.z < ZBufPos^) then
|
||
|
begin
|
||
|
ZBufPos^ := q.z;
|
||
|
Bucket.Red := Bucket.Red + MapColor.Red;
|
||
|
Bucket.Green := Bucket.Green + MapColor.Green;
|
||
|
Bucket.Blue := Bucket.Blue + MapColor.Blue;
|
||
|
Bucket.Count := Bucket.Count + 1;
|
||
|
end;
|
||
|
{$else}
|
||
|
Bucket.Red := Bucket.Red + MapColor.Red;
|
||
|
Bucket.Green := Bucket.Green + MapColor.Green;
|
||
|
Bucket.Blue := Bucket.Blue + MapColor.Blue;
|
||
|
Bucket.Count := Bucket.Count + 1;
|
||
|
{$endif}
|
||
|
end;
|
||
|
|
||
|
except
|
||
|
on EMathError do begin
|
||
|
exit;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
procedure TRenderWorkerST.IterateBatchAngle;
|
||
|
var
|
||
|
i: integer;
|
||
|
px, py: double;
|
||
|
Bucket: PBucket;
|
||
|
MapColor: PColorMapColor;
|
||
|
ZBufPos: PDouble;
|
||
|
ix, iy: integer;
|
||
|
BmpColor: TColor;
|
||
|
|
||
|
p, q: TCPPoint;
|
||
|
xf: TXForm;
|
||
|
begin
|
||
|
{$ifndef _ASM_}
|
||
|
p.x := 2 * random - 1;
|
||
|
p.y := 2 * random - 1;
|
||
|
p.c := random;
|
||
|
{$else}
|
||
|
asm
|
||
|
fld1
|
||
|
call AsmRandExt
|
||
|
fadd st, st
|
||
|
fsub st, st(1)
|
||
|
fstp qword ptr [p.x]
|
||
|
call AsmRandExt
|
||
|
fadd st, st
|
||
|
fsubrp st(1), st
|
||
|
fstp qword ptr [p.y]
|
||
|
call AsmRandExt
|
||
|
fstp qword ptr [p.c]
|
||
|
end;
|
||
|
{$endif}
|
||
|
|
||
|
try
|
||
|
xf := fcp.xform[0];
|
||
|
for i := 0 to FUSE do begin
|
||
|
xf := xf.PropTable[Random(PROP_TABLE_SIZE)];
|
||
|
xf.NextPoint(p);
|
||
|
end;
|
||
|
|
||
|
for i := 0 to SUB_BATCH_SIZE-1 do begin
|
||
|
xf := xf.PropTable[Random(PROP_TABLE_SIZE)];
|
||
|
xf.NextPoint(p);
|
||
|
|
||
|
if random >= xf.transOpacity then continue;
|
||
|
|
||
|
q := p;
|
||
|
fcp.ProjectionFunc(@q);
|
||
|
|
||
|
px := q.x * cosa + q.y * sina + rcX;
|
||
|
if (px < 0) or (px > camW) then continue;
|
||
|
py := q.y * cosa - q.x * sina + rcY;
|
||
|
if (py < 0) or (py > camH) then continue;
|
||
|
|
||
|
Bucket := @buckets[Round(bhs * py)][Round(bws * px)];
|
||
|
MapColor := @ColorMap[Round(p.c * 255)];
|
||
|
|
||
|
{$ifdef ENABLEZBUF}
|
||
|
ZBufPos := @zbuffer[Round(bhs * py)][Round(bws * px)];
|
||
|
if (q.z < ZBufPos^) then
|
||
|
begin
|
||
|
ZBufPos^ := q.z;
|
||
|
Bucket.Red := Bucket.Red + MapColor.Red;
|
||
|
Bucket.Green := Bucket.Green + MapColor.Green;
|
||
|
Bucket.Blue := Bucket.Blue + MapColor.Blue;
|
||
|
Bucket.Count := Bucket.Count + 1;
|
||
|
end;
|
||
|
{$else}
|
||
|
Bucket.Red := Bucket.Red + MapColor.Red;
|
||
|
Bucket.Green := Bucket.Green + MapColor.Green;
|
||
|
Bucket.Blue := Bucket.Blue + MapColor.Blue;
|
||
|
Bucket.Count := Bucket.Count + 1;
|
||
|
{$endif}
|
||
|
end;
|
||
|
|
||
|
except
|
||
|
on EMathError do begin
|
||
|
exit;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
procedure TRenderWorkerST.IterateBatchFX;
|
||
|
var
|
||
|
i: integer;
|
||
|
px, py: double;
|
||
|
Bucket: PBucket;
|
||
|
MapColor: PColorMapColor;
|
||
|
ZbufPos: PDouble;
|
||
|
ix, iy: integer;
|
||
|
BmpColor: TColor;
|
||
|
|
||
|
p, q: TCPPoint;
|
||
|
xf: TXForm;
|
||
|
begin
|
||
|
{$ifndef _ASM_}
|
||
|
p.x := 2 * random - 1;
|
||
|
p.y := 2 * random - 1;
|
||
|
p.c := random;
|
||
|
{$else}
|
||
|
asm
|
||
|
fld1
|
||
|
call AsmRandExt
|
||
|
fadd st, st
|
||
|
fsub st, st(1)
|
||
|
fstp qword ptr [p.x]
|
||
|
call AsmRandExt
|
||
|
fadd st, st
|
||
|
fsubrp st(1), st
|
||
|
fstp qword ptr [p.y]
|
||
|
call AsmRandExt
|
||
|
fstp qword ptr [p.c]
|
||
|
end;
|
||
|
{$endif}
|
||
|
|
||
|
try
|
||
|
xf := fcp.xform[0];
|
||
|
for i := 0 to FUSE do begin
|
||
|
xf := xf.PropTable[Random(PROP_TABLE_SIZE)];
|
||
|
xf.NextPoint(p);
|
||
|
end;
|
||
|
|
||
|
for i := 0 to SUB_BATCH_SIZE-1 do begin
|
||
|
xf := xf.PropTable[Random(PROP_TABLE_SIZE)];
|
||
|
xf.NextPoint(p);
|
||
|
|
||
|
if random >= xf.transOpacity then continue;
|
||
|
|
||
|
finalXform.NextPointTo(p, q);
|
||
|
fcp.ProjectionFunc(@q);
|
||
|
|
||
|
px := q.x - camX0;
|
||
|
if (px < 0) or (px > camW) then continue;
|
||
|
py := q.y - camY0;
|
||
|
if (py < 0) or (py > camH) then continue;
|
||
|
|
||
|
Bucket := @buckets[Round(bhs * py)][Round(bws * px)];
|
||
|
MapColor := @ColorMap[Round(q.c * 255)];
|
||
|
|
||
|
{$ifdef ENABLEZBUF}
|
||
|
ZBufPos := @zbuffer[Round(bhs * py)][Round(bws * px)];
|
||
|
if (q.z < ZBufPos^) then
|
||
|
begin
|
||
|
ZBufPos^ := q.z;
|
||
|
Bucket.Red := Bucket.Red + MapColor.Red;
|
||
|
Bucket.Green := Bucket.Green + MapColor.Green;
|
||
|
Bucket.Blue := Bucket.Blue + MapColor.Blue;
|
||
|
Bucket.Count := Bucket.Count + 1;
|
||
|
end;
|
||
|
{$else}
|
||
|
Bucket.Red := Bucket.Red + MapColor.Red;
|
||
|
Bucket.Green := Bucket.Green + MapColor.Green;
|
||
|
Bucket.Blue := Bucket.Blue + MapColor.Blue;
|
||
|
Bucket.Count := Bucket.Count + 1;
|
||
|
{$endif}
|
||
|
end;
|
||
|
|
||
|
except
|
||
|
on EMathError do begin
|
||
|
exit;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
procedure TRenderWorkerST.IterateBatchAngleFX;
|
||
|
var
|
||
|
i: integer;
|
||
|
px, py: double;
|
||
|
Bucket: PBucket;
|
||
|
MapColor: PColorMapColor;
|
||
|
ZBufPos: PDouble;
|
||
|
ix, iy: integer;
|
||
|
BmpColor: TColor;
|
||
|
|
||
|
p, q: TCPPoint;
|
||
|
xf: TXForm;
|
||
|
begin
|
||
|
{$ifndef _ASM_}
|
||
|
p.x := 2 * random - 1;
|
||
|
p.y := 2 * random - 1;
|
||
|
p.c := random;
|
||
|
{$else}
|
||
|
asm
|
||
|
fld1
|
||
|
call AsmRandExt
|
||
|
fadd st, st
|
||
|
fsub st, st(1)
|
||
|
fstp qword ptr [p.x]
|
||
|
call AsmRandExt
|
||
|
fadd st, st
|
||
|
fsubrp st(1), st
|
||
|
fstp qword ptr [p.y]
|
||
|
call AsmRandExt
|
||
|
fstp qword ptr [p.c]
|
||
|
end;
|
||
|
{$endif}
|
||
|
|
||
|
try
|
||
|
xf := fcp.xform[0];
|
||
|
for i := 0 to FUSE do begin
|
||
|
xf := xf.PropTable[Random(PROP_TABLE_SIZE)];
|
||
|
xf.NextPoint(p);
|
||
|
end;
|
||
|
|
||
|
for i := 0 to SUB_BATCH_SIZE-1 do begin
|
||
|
xf := xf.PropTable[Random(PROP_TABLE_SIZE)];
|
||
|
xf.NextPoint(p);
|
||
|
|
||
|
if random >= xf.transOpacity then continue;
|
||
|
|
||
|
finalXform.NextPointTo(p, q);
|
||
|
fcp.ProjectionFunc(@q);
|
||
|
|
||
|
px := q.x * cosa + q.y * sina + rcX;
|
||
|
if (px < 0) or (px > camW) then continue;
|
||
|
py := q.y * cosa - q.x * sina + rcY;
|
||
|
if (py < 0) or (py > camH) then continue;
|
||
|
|
||
|
Bucket := @buckets[Round(bhs * py)][Round(bws * px)];
|
||
|
MapColor := @ColorMap[Round(q.c * 255)];
|
||
|
|
||
|
{$ifdef ENABLEZBUF}
|
||
|
ZBufPos := @zbuffer[Round(bhs * py)][Round(bws * px)];
|
||
|
if (q.z < ZBufPos^) then
|
||
|
begin
|
||
|
ZBufPos^ := q.z;
|
||
|
Bucket.Red := Bucket.Red + MapColor.Red;
|
||
|
Bucket.Green := Bucket.Green + MapColor.Green;
|
||
|
Bucket.Blue := Bucket.Blue + MapColor.Blue;
|
||
|
Bucket.Count := Bucket.Count + 1;
|
||
|
end;
|
||
|
{$else}
|
||
|
Bucket.Red := Bucket.Red + MapColor.Red;
|
||
|
Bucket.Green := Bucket.Green + MapColor.Green;
|
||
|
Bucket.Blue := Bucket.Blue + MapColor.Blue;
|
||
|
Bucket.Count := Bucket.Count + 1;
|
||
|
{$endif}
|
||
|
end;
|
||
|
|
||
|
except
|
||
|
on EMathError do begin
|
||
|
exit;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
procedure TRenderWorkerMT.AddPointsToBuckets(const points: TPointsArray);
|
||
|
var
|
||
|
i: integer;
|
||
|
px, py: double;
|
||
|
Bucket: PBucket;
|
||
|
ZBufPos: PDouble;
|
||
|
MapColor: PColorMapColor;
|
||
|
begin
|
||
|
for i := SUB_BATCH_SIZE - 1 downto 0 do begin
|
||
|
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(bhs * py)][Round(bws * px)];
|
||
|
MapColor := @ColorMap[Round(points[i].c * 255)];
|
||
|
|
||
|
if random >= points[i].o then continue;
|
||
|
|
||
|
{$ifdef ENABLEZBUF}
|
||
|
ZBufPos := @zbuffer[Round(bhs * py)][Round(bws * px)];
|
||
|
if (points[i].z < ZBufPos^) then
|
||
|
begin
|
||
|
ZBufPos^ := points[i].z;
|
||
|
Bucket.Red := Bucket.Red + MapColor.Red;
|
||
|
Bucket.Green := Bucket.Green + MapColor.Green;
|
||
|
Bucket.Blue := Bucket.Blue + MapColor.Blue;
|
||
|
Bucket.Count := Bucket.Count + 1;
|
||
|
end;
|
||
|
{$else}
|
||
|
Bucket.Red := Bucket.Red + MapColor.Red;
|
||
|
Bucket.Green := Bucket.Green + MapColor.Green;
|
||
|
Bucket.Blue := Bucket.Blue + MapColor.Blue;
|
||
|
Bucket.Count := Bucket.Count + 1;
|
||
|
{$endif}
|
||
|
end;
|
||
|
end;
|
||
|
procedure TRenderWorkerMT.AddPointsToBucketsAngle(const points: TPointsArray);
|
||
|
var
|
||
|
i: integer;
|
||
|
px, py: double;
|
||
|
Bucket: PBucket;
|
||
|
MapColor: PColorMapColor;
|
||
|
ZBufPos: PDouble;
|
||
|
begin
|
||
|
for i := SUB_BATCH_SIZE - 1 downto 0 do begin
|
||
|
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(bhs * py)][Round(bws * px)];
|
||
|
MapColor := @ColorMap[Round(points[i].c * 255)];
|
||
|
|
||
|
if random >= points[i].o then continue;
|
||
|
|
||
|
{$ifdef ENABLEZBUF}
|
||
|
ZBufPos := @zbuffer[Round(bhs * py)][Round(bws * px)];
|
||
|
if (points[i].z < ZBufPos^) then
|
||
|
begin
|
||
|
ZBufPos^ := points[i].z;
|
||
|
Bucket.Red := Bucket.Red + MapColor.Red;
|
||
|
Bucket.Green := Bucket.Green + MapColor.Green;
|
||
|
Bucket.Blue := Bucket.Blue + MapColor.Blue;
|
||
|
Bucket.Count := Bucket.Count + 1;
|
||
|
end;
|
||
|
{$else}
|
||
|
Bucket.Red := Bucket.Red + MapColor.Red;
|
||
|
Bucket.Green := Bucket.Green + MapColor.Green;
|
||
|
Bucket.Blue := Bucket.Blue + MapColor.Blue;
|
||
|
Bucket.Count := Bucket.Count + 1;
|
||
|
{$endif}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
// THREADING
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
procedure TRenderWorkerMT.Stop;
|
||
|
var
|
||
|
i: integer;
|
||
|
begin
|
||
|
for i := 0 to High(WorkingThreads) do
|
||
|
WorkingThreads[i].Terminate;
|
||
|
|
||
|
inherited;
|
||
|
end;
|
||
|
procedure TRenderWorkerMT.BreakRender;
|
||
|
var
|
||
|
i: integer;
|
||
|
begin
|
||
|
inherited;
|
||
|
|
||
|
for i := 0 to High(WorkingThreads) do
|
||
|
WorkingThreads[i].Terminate;
|
||
|
end;
|
||
|
procedure TRenderWorkerMT.Pause;
|
||
|
var
|
||
|
i: integer;
|
||
|
begin
|
||
|
inherited;
|
||
|
|
||
|
for i := 0 to High(WorkingThreads) do
|
||
|
WorkingThreads[i].Suspend;
|
||
|
end;
|
||
|
procedure TRenderWorkerMT.UnPause;
|
||
|
var
|
||
|
i: integer;
|
||
|
begin
|
||
|
inherited;
|
||
|
|
||
|
for i := 0 to High(WorkingThreads) do
|
||
|
WorkingThreads[i].Resume;
|
||
|
end;
|
||
|
function TRenderWorkerMT.NewThread: TBucketFillerThread;
|
||
|
begin
|
||
|
Result := TBucketFillerThread.Create(fcp);
|
||
|
assert(Result<>nil);
|
||
|
|
||
|
if FCP.FAngle = 0 then
|
||
|
Result.AddPointsProc := self.AddPointsToBuckets
|
||
|
else
|
||
|
Result.AddPointsProc := self.AddPointsToBucketsAngle;
|
||
|
|
||
|
Result.CriticalSection := CriticalSection;
|
||
|
Result.Nrbatches := FNumBatches;
|
||
|
Result.batchcounter := @batchcounter;
|
||
|
end;
|
||
|
|
||
|
end.
|
||
|
|