This repository has been archived on 2024-02-26. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
MyPresenter1.0/bgrabitmap/bgracoordpool3d.pas
2015-02-08 16:52:18 -08:00

140 lines
3.6 KiB
ObjectPascal

unit BGRACoordPool3D;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, BGRABitmapTypes, BGRASSE;
type
PBGRACoordData3D = ^TBGRACoordData3D;
TBGRACoordData3D = packed record
{0} sceneCoord: TPoint3D_128;
{16} viewCoord: TPoint3D_128;
{32} projectedCoord: TPointF;
{40} InvZ: single;
{44} used: longbool;
{48} viewNormal: TPoint3D_128;
end; {64}
{ TBGRACoordPool3D }
TBGRACoordPool3D = class
private
FFirstFree: integer;
FNbCoord,FCapacity: integer;
FPoolData: TMemoryBlockAlign128;
FUsedCapacity : integer;
function GetCoordData(AIndex: integer): PBGRACoordData3D;
procedure SetCapacity(ACapacity: integer);
public
constructor Create(ACapacity: integer);
destructor Destroy; override;
procedure Remove(AIndex: integer);
function Add: integer;
property CoordData[AIndex: integer]: PBGRACoordData3D read GetCoordData;
property Capacity: integer read FCapacity;
property UsedCapacity: integer read FUsedCapacity;
end;
implementation
{ TBGRACoordPool3D }
procedure TBGRACoordPool3D.SetCapacity(ACapacity: integer);
var NewPoolData: TMemoryBlockAlign128;
begin
if FCapacity <> ACapacity then
begin
if ACapacity = 0 then
FreeAndNil(FPoolData)
else
begin
NewPoolData := TMemoryBlockAlign128.Create(ACapacity*sizeof(TBGRACoordData3D));
if FCapacity <> 0 then
begin
//previous block is smaller
if FCapacity < ACapacity then
begin
move(FPoolData.Data^, NewPoolData.Data^, FCapacity*sizeof(TBGRACoordData3D));
//pad with zeros
fillchar((pbyte(NewPoolData.Data)+FCapacity*sizeof(TBGRACoordData3D))^,(ACapacity-FCapacity)*sizeof(TBGRACoordData3D),0);
end
else //previous block is greater or equal
move(FPoolData.Data^, NewPoolData.Data^, ACapacity*sizeof(TBGRACoordData3D));
FreeAndNil(FPoolData);
end else
//clear new block
fillchar(pbyte(NewPoolData.Data)^,ACapacity*sizeof(TBGRACoordData3D),0);
FPoolData := NewPoolData;
end;
FCapacity:= ACapacity;
end;
end;
constructor TBGRACoordPool3D.Create(ACapacity: integer);
begin
FCapacity := 0;
FPoolData := nil;
FNbCoord:= 0;
FFirstFree := 0;
FUsedCapacity := 0;
SetCapacity(ACapacity);
end;
destructor TBGRACoordPool3D.Destroy;
begin
FPoolData.Free;
inherited Destroy;
end;
procedure TBGRACoordPool3D.Remove(AIndex: integer);
begin
if CoordData[AIndex]^.used then
begin
CoordData[AIndex]^.used := false;
if AIndex < FFirstFree then FFirstFree := AIndex;
if AIndex = FUsedCapacity-1 then
begin
while (FUsedCapacity > 0) and not CoordData[FUsedCapacity-1]^.used do
dec(FUsedCapacity);
end;
end;
end;
function TBGRACoordPool3D.Add: integer;
begin
//check for free space
while FFirstFree < FCapacity do
begin
if not CoordData[FFirstFree]^.used then
begin
CoordData[FFirstFree]^.used := false;
result := FFirstFree;
inc(FFirstFree);
if FFirstFree > FUsedCapacity then
FUsedCapacity := FFirstFree;
exit;
end;
inc(FFirstFree);
end;
//no free space
SetCapacity(FCapacity*2+8);
CoordData[FFirstFree]^.used := false;
result := FFirstFree;
inc(FFirstFree);
if FFirstFree > FUsedCapacity then
FUsedCapacity := FFirstFree;
end;
function TBGRACoordPool3D.GetCoordData(AIndex: integer): PBGRACoordData3D;
begin
result := PBGRACoordData3D(FPoolData.Data)+AIndex;
end;
end.