this slowpoke moves

Image to 3D-Matrix

Der folgende Code ist in der Lage, jedes x-beliebige Image auf eine 3D-Matrix-Grafik zu legen und zu animieren. Das ist in der Demo-Szene sehr gefragt, aber auch bei Herstellern von 3D-Grafikprogrammen.

Es werden nur ein Timer und ein Image benötigt.
Der Timer sollte auf 30 fps gestellt werden.

Unit Graph3d.pas
unit Graph3d;

interface

 uses Graphics,math;

const pi2=6.283185307179586476925286766559   ;
Const FOCUS_KAMERA=300;

 type
BRGB = record
B:byte;
G:byte;
R:byte;
  end;
  TRgb=array[0..4000] of BRGB;
  PRGB=array[0..4000] of ^TRgb;
TVertex3D2D=record
X3DM,Y3DM,Z3DM:double;
X3DP,Y3DP,Z3DP:double; 
X2D,Y2D:double; 
TX,TY:double;
end;

TAngle=Record
Sin,Cos:double;
end;

 Type TFog=record
 R,G,B:byte;
 L:double;
 end;

TTexture=record
Texture:PRGB;
width,height:integer;
end;

TVector=array[1..4] of double;
TMatrix=array[1..4,1..4] of double;
TTriangles=array[1..3] of TVertex3D2D;
TRender3D = class
private
   {$A4}
MatrixOX:TMatrix;
MatrixOY:TMatrix;
MatrixOZ:TMatrix;
MatrixResult:TMatrix;
triangl,trianglr,trianglr1:TTriangles;
ArrayPointer:PRGB; 
Width,Height:integer;
cc1,cc2,cc3,cc4,c1,c2,c3,cc5,cc6:double;
ZBuffer:array of array of double;
fz,dil1:double;
z1,z2,z3:double;
zmin,zmax,zmax1:double;
zz1,zz3,zz5,cz1,cz2,cz3:double;
minxt,minyt:double;
tx1,tx3,tx5,ctx2:double;
ty1,ty3,ty5,cty2:double;
D,dx,dy,D2:double;
il1:double;
ZO,xo,yo:double;
an,bn,cn:double;
   {$A2}
fx,fy:integer;
kp,ko:integer;
 ScaleWidth,ScaleHeight:integer;
vo,vp:array[1..3] of integer;
Kamerax,KameraY,Kameraz:double; 
procedure SortVertex(var Triangle:TTriangles;var xmax,xmin,ymax,ymin:double);
procedure PaintLineT(maxx,minx:double;y:integer;Zmin,Tminx,Tminy:double);
procedure PaintLine(maxx,minx:double;y:integer;Zmax,Zmin:double;R,G,B:byte);
procedure FillT(var Vertex1,Vertex2,vertex3:TVertex3d2d);
procedure Fill(var Vertex1,Vertex2,vertex3:TVertex3d2d;R,G,B:byte);
public
   {$A4}
AngleKameraOX:TAngle;
AngleKameraOY:TAngle;
AngleKameraOZ:TAngle;
Texture:^TTexture;
TextureEnabled:boolean;
Fog:TFog;
NoneFace:boolean;
constructor Create(W,H:integer;Win3d:TBitMap);
procedure FillZBuffer; 
function xyz2D(var Vertex:TVertex3D2D):boolean; 
procedure FillTriangle(var Vertex1,Vertex2,vertex3:TVertex3d2d;R,G,B:byte);
Procedure RotateKamera(OX,OY,OZ:double); 
PRocedure MoveKamera(x,y,z:double); 
Procedure BitMapToPointer(var PointerBitMap:PRgb; Bitmap:TBitMAp);
procedure CreateFog;
procedure SetPointKamera(X,Y,Z:double);
procedure point3d(Vertex:TVertex3d2d;r,g,b:byte);
end;

implementation

constructor TRender3D.Create(W,H:integer;Win3d:TBitMap);
 var
 i:integer;
begin
 Win3d.Width:=W;
  Win3d.Height:=H;
  BitMaptoPointer(ArrayPointer,Win3d);
setlength(ZBuffer,w);
for i:=0 to w-1 do
setlength(zbuffer[i],h);
Width:=w-1;
Height:=h-1;
ScaleWidth:=W div 2;
ScaleHeight:=H div 2;
MatrixOX[1,1]:=1; MatrixOX[1,2]:=0;
MatrixOX[1,3]:=0; MatrixOX[1,4]:=0;
MatrixOX[2,1]:=0; MatrixOX[2,4]:=0;
MatrixOX[3,1]:=0; MatrixOX[3,4]:=0;
MatrixOX[4,1]:=0; MatrixOX[4,2]:=0;
MatrixOX[4,3]:=0; MatrixOX[4,4]:=1;
MatrixOY[1,2]:=0; MatrixOY[1,4]:=0;
MatrixOY[2,1]:=0; MatrixOY[2,2]:=1;
MatrixOY[2,3]:=0; MatrixOY[2,4]:=0;
MatrixOY[3,2]:=0; MatrixOY[3,4]:=0;
MatrixOY[4,1]:=0; MatrixOY[4,2]:=0;
MatrixOY[4,3]:=0; MatrixOY[4,4]:=1;
MatrixOZ[1,3]:=0; MatrixOZ[1,4]:=0;
MatrixOZ[2,3]:=0; MatrixOZ[2,4]:=0;
MatrixOZ[3,1]:=0; MatrixOZ[3,2]:=0;
MatrixOZ[3,3]:=1; MatrixOZ[3,4]:=0;
MatrixOZ[4,1]:=0; MatrixOZ[4,2]:=0;
MatrixOZ[4,3]:=0; MatrixOZ[4,4]:=1;
MatrixResult[1,4]:=0;
MatrixResult[2,4]:=0;
MatrixResult[3,4]:=0;
MatrixResult[4,1]:=0;
MatrixResult[4,2]:=0;
MatrixResult[4,3]:=0;
MatrixResult[4,4]:=1;
fog.R:=255;
fog.g:=255;
fog.b:=255;
fog.l:=1000;
D2:=1/Focus_kamera     ;
inherited Create;
end;

procedure TRender3d.FillZBuffer;
var
i,j:integer;
begin
for i:=0 to width-1 do
 for j:=0 to Height-1 do
     zbuffer[i,j]:=$ffffffff;
end;

function TRender3d.xyz2D(var Vertex:TVertex3D2D):boolean;
var
   {$A4}
Vec:TVector;
begin
result:=false;
Vec[1]:=Vertex.X3DM-KameraX;   
Vec[2]:=Vertex.y3DM-Kameray;
Vec[3]:=Vertex.z3DM-Kameraz;
Vertex.X3DP:= Vec[1]*matrixResult[1,1]+Vec[2]*matrixResult[1,2]+Vec[3]*matrixResult[1,3];
Vertex.Y3DP:= Vec[1]*matrixResult[2,1]+Vec[2]*matrixResult[2,2]+Vec[3]*matrixResult[2,3];
Vertex.Z3DP:= Vec[1]*matrixResult[3,1]+Vec[2]*matrixResult[3,2]+Vec[3]*matrixResult[3,3];
if (FOCUS_KAMERA+Vertex.Z3DP)<>0then
    begin
    Vertex.X2D:=(ScaleWidth+FOCUS_KAMERA*(Vertex.X3DP) /(FOCUS_KAMERA+Vertex.Z3DP));
    Vertex.Y2D:=(ScaleHEight-FOCUS_KAMERA*(Vertex.Y3DP) /(fOCUS_KAMERA+Vertex.Z3DP));
end;
end;

procedure TRender3d.RotateKamera(ox,oy,oz:double);
begin
AngleKameraOX.Sin:=sin(pi2*ox/360);
AngleKameraOX.Cos:=cos(pi2*ox/360);
AngleKameraOy.Sin:=sin(pi2*oy/360);
AngleKameraOy.Cos:=cos(pi2*oy/360);
AngleKameraOz.Sin:=sin(pi2*oz/360);
AngleKameraOz.Cos:=cos(pi2*oz/360);
MatrixOX[3,2]:=-AngleKameraOX.Sin;
MatrixOX[3,3]:=AngleKameraOX.Cos;
MatrixOX[2,2]:=AngleKameraOX.Cos;
MatrixOX[2,3]:=AngleKameraOX.Sin;
MatrixOY[1,1]:=AngleKameraOy.Cos;
MatrixOY[1,3]:=AngleKameraOy.Sin;
MatrixOY[3,1]:=-AngleKameraOy.Sin;
MatrixOY[3,3]:=AngleKameraOy.Cos;
MatrixOZ[2,1]:=-AngleKameraOz.Sin;
MatrixOZ[2,2]:=AngleKameraOz.Cos;
MatrixOZ[1,1]:=AngleKameraOz.Cos;
MatrixOZ[1,2]:=AngleKameraOz.Sin;
MatrixResult[1,1]:=MatrixOZ[1,1]*MatrixOY[1,1]+MatrixOZ[2,1]*MatrixOY[3,1]*MatrixOX[2,3];
MatrixResult[1,2]:=MatrixOZ[2,1]*MatrixOX[2,2];
MatrixResult[1,3]:=MatrixOZ[1,1]*MatrixOY[1,3]+MatrixOZ[2,1]*MatrixOY[3,3]*MatrixOX[2,3];
MatrixResult[2,1]:=MatrixOZ[1,2]*MatrixOY[1,1]+MatrixOZ[2,2]*MatrixOY[3,1]*MatrixOX[2,3];
MatrixResult[2,2]:=MatrixOZ[2,2]*MatrixOX[2,2];
MatrixResult[2,3]:=MatrixOZ[1,2]*MatrixOY[1,3]+MatrixOZ[2,2]*MatrixOY[3,3]*MatrixOX[2,3];
MatrixResult[3,1]:=MatrixOY[3,1]*MatrixOX[3,3];
MatrixResult[3,2]:=MatrixOX[3,2];
MatrixResult[3,3]:=MatrixOY[3,3]*MatrixOX[3,3];
end;

Procedure TRender3D.MoveKamera(x,y,z:double);
begin
Kamerax:=x;
Kameray:=y;
Kameraz:=z;
end;

procedure TRender3d.SortVertex(var Triangle:TTriangles;var xmax,xmin,ymax,ymin:double);
var
M:TVertex3D2D;
i,j:integer;
m1:double;
TX:TTriangles;
begin
tx:=Triangle;
for i:=1 to 3 do
    for j:=1 to i do
        begin
         if Triangle[i].Y2D<=Triangle[j].Y2D then
            begin
            m := Triangle[j] ;
            Triangle[j]:=Triangle[i] ;
            Triangle[i]:=m ;
            end;
        end;
for i:=1 to 3 do
    for j:=1 to i do
        begin
        If tx[i].X2D<= tx[j].X2D Then
            begin
            m1 := tx[j].X2D ;
            tx[j].X2D := tx[i].X2D ;
            tx[i].X2D := m1 ;
            end;
         end;
  XMax:=tx[3].X2D;
  XMIn:=tx[1].X2D;
  yMax:=Triangle[3].Y2D;
  yMIn:=Triangle[1].Y2D
end;

procedure TRender3d.FillTriangle(var Vertex1,Vertex2,vertex3:TVertex3d2d;R,G,B:byte);
begin
 if noneface=true then
 begin
  AN := (Vertex2.y3dp-Vertex1.y3dp)*(vertex3.z3dp-Vertex1.z3dp)-(Vertex2.z3dp-Vertex1.z3dp)*(vertex3.y3dp-Vertex1.y3dp) ;
    BN := (Vertex2.z3dp-Vertex1.z3dp)*(vertex3.x3dp-Vertex1.x3dp)-(Vertex2.x3dp-Vertex1.x3dp)*(vertex3.z3dp-Vertex1.z3dp) ;
    CN :=(Vertex2.x3dp-Vertex1.x3dp)*(vertex3.y3dp-Vertex1.y3dp)-(Vertex2.y3dp-Vertex1.y3dp)*(vertex3.x3dp-Vertex1.x3dp);
    if  cn*focus_kamera+an*Vertex1.x3dp+bn*Vertex1.y3dp+cn*Vertex1.z3dp<0 then
if TextureEnabled=false then fill( Vertex1,Vertex2,vertex3,r,g,b) else fillt( Vertex1,Vertex2,vertex3);
 end
 else
 if TextureEnabled=true then fillt( Vertex1,Vertex2,vertex3) else fill( Vertex1,Vertex2,vertex3,r,g,b);
end;

Procedure Trender3D.PaintLineT(maxx,minx:double;y:integer;zmin,Tminx,Tminy:double);
var
    {$A2}
 max,min,i:integer;
    {$A4}
 raz:double;
begin
if (maxx>minx) then begin max:=trunc(maxx)-1;min:=trunc(minx) end else  begin max:=trunc(minx)-1;min:=trunc(maxx); end ;
if max<0 then max:=0; if max>width then max:=width;
if Min<0 then Min:=0; if Min>width then Min:=width;
 raz:=min-minx ;
zo:=zmin+(raz)*d;
xo:=tminx+(raz)*dx;
yo:=tminy+(raz)*dy;
for i:=min to max do
    begin
         zo:=zo+d;
        xo:=xo+dx;
        yo:=yo+dy;
        fz:=1/(zo) ;
        if (fz-focus_kamera<zbuffer[i,y])  then
        begin
         fx:=round(xo*fz);
         fy:=round(yo*fz);
                 if (fx>=0) and (fx<=texture.width) and (fy>=0) and (fy<=texture.height)  then
            begin
                 if  texture.texture[fy,fx].R<>255 then
            begin
              ArrayPointer[y][i].r:=texture.texture[fy,fx].R ;
                ArrayPointer[y][i].G:= texture.texture[fy,fx].g;
                ArrayPointer[y][i].b:=texture.texture[fy,fx].b;
                ZBuffer[i,y]:=fz-focus_kamera;
                end;
                end;
       end;
    end;
end;

Procedure Trender3d.PaintLine(maxx,minx:double;y:integer;Zmax,Zmin:double;R,G,B:byte);
 var
 max,min,i:integer;
 raz:double;
begin
 if (maxx-minx)<>0 then
 begin
if (maxx>minx) then begin max:=trunc(maxx)-1;min:=trunc(minx) end else  begin max:=trunc(minx)-1;min:=trunc(maxx); end ;
if max<0 then max:=0; if max>width then max:=width;
if Min<0 then Min:=0; if Min>width then Min:=width;
zo:=zmin+(min-minx)*d;
for i:=min to max do
    begin
          zo:=zo+d;
           fz:=1/zo-300;
        if  (fz<ZBuffer[i,y])   then
        begin
       ArrayPointer[y][i].r:=R ;
        ArrayPointer[y][i].G:= g;
        ArrayPointer[y][i].b:=b;
        ZBuffer[i,y]:=fz;
        end;
    end;
    end;
end;

procedure Trender3d.FillT(var Vertex1,Vertex2,vertex3:TVertex3d2d);
var
   {$A4}
Xmin,XMax:double;
Ymin,YMax:double;
MaxX,MinX,MaxX1:double;
i,j:integer;
y1,y2,y3:integer;
 x_start,x_end,z_start,z_end:double ;
 tx_start,tx_end,ty_start,ty_end:double ;
 yraz,yraz1:double;
begin
     kp:=0;
     ko:=0;
    triangl[1]:=vertex1;
    triangl[2]:=vertex2;
    triangl[3]:=vertex3;
     for i:=1 to 3 do
        begin
            if triangl[i].Z3DP<0 then
                begin
                    ko:=ko+1;
                    vo[ko]:=i;
                end
                else
                begin
                kp:=kp+1;
                vp[kp]:=i;
                end;
        end;
if ko=3  then exit;
if ko=2 then
    begin
        trianglr[vp[1]]:= triangl[vp[1]];
        trianglr[vo[1]].Z3DP:=0;
        trianglr[vo[2]].Z3DP:=0;
        trianglr[vo[1]].X3DP:=triangl[vo[1]].X3DP+(triangl[vp[1]].X3DP - triangl[vo[1]].X3DP)*(0-triangl[vo[1]].Z3DP)/(triangl[vp[1]].Z3DP-triangl[vo[1]].Z3DP) ;
        trianglr[vo[1]].Y3DP:=triangl[vo[1]].Y3DP+(triangl[vp[1]].Y3DP - triangl[vo[1]].Y3DP)*(0-triangl[vo[1]].Z3DP)/(triangl[vp[1]].Z3DP-triangl[vo[1]].Z3DP) ;
        trianglr[vo[1]].tx:=triangl[vo[1]].tx+(triangl[vp[1]].tx - triangl[vo[1]].tx)*(0-triangl[vo[1]].Z3DP)/(triangl[vp[1]].Z3DP-triangl[vo[1]].Z3DP) ;
        trianglr[vo[1]].ty:=triangl[vo[1]].ty+(triangl[vp[1]].ty - triangl[vo[1]].ty)*(0-triangl[vo[1]].Z3DP)/(triangl[vp[1]].Z3DP-triangl[vo[1]].Z3DP) ;
        trianglr[vo[1]].X2D:=(ScaleWidth+FOCUS_KAMERA*(trianglr[vo[1]].X3DP) *d2);
        trianglr[vo[1]].Y2D:=(ScaleHEight-FOCUS_KAMERA*(trianglr[vo[1]].Y3DP) *d2);
        trianglr[vo[2]].X3DP:=triangl[vo[2]].X3DP+(triangl[vp[1]].X3DP - triangl[vo[2]].X3DP)*(0-triangl[vo[2]].Z3DP)/(triangl[vp[1]].Z3DP-triangl[vo[2]].Z3DP) ;
        trianglr[vo[2]].Y3DP:=triangl[vo[2]].Y3DP+(triangl[vp[1]].Y3DP - triangl[vo[2]].Y3DP)*(0-triangl[vo[2]].Z3DP)/(triangl[vp[1]].Z3DP-triangl[vo[2]].Z3DP) ;
        trianglr[vo[2]].tx:=triangl[vo[2]].tx+(triangl[vp[1]].tx - triangl[vo[2]].tx)*(0-triangl[vo[2]].Z3DP)/(triangl[vp[1]].Z3DP-triangl[vo[2]].Z3DP) ;
        trianglr[vo[2]].ty:=triangl[vo[2]].ty+(triangl[vp[1]].ty - triangl[vo[2]].ty)*(0-triangl[vo[2]].Z3DP)/(triangl[vp[1]].Z3DP-triangl[vo[2]].Z3DP) ;
        trianglr[vo[2]].X2D:=(ScaleWidth+FOCUS_KAMERA*(trianglr[vo[2]].X3DP) *d2);
        trianglr[vo[2]].Y2D:=(ScaleHEight-FOCUS_KAMERA*(trianglr[vo[2]].Y3DP) *d2);
        fillt(trianglr[1],trianglr[2],trianglr[3]);
        exit;
    end;
if ko=1  then
    begin
    trianglr[1]:=triangl[vp[1]];
    trianglr[2]:=triangl[vp[2]];
    trianglr[3].Z3DP:=0;
    trianglr[3].X3DP :=triangl[vp[1]].X3DP +(triangl[vo[1]].X3DP-triangl[vp[1]].X3DP)*(0-triangl[vp[1]].Z3DP)/(triangl[vo[1]].Z3DP-triangl[vp[1]].Z3DP);
    trianglr[3].y3DP :=triangl[vp[1]].y3DP +(triangl[vo[1]].y3DP-triangl[vp[1]].y3DP)*(0-triangl[vp[1]].Z3DP)/(triangl[vo[1]].Z3DP-triangl[vp[1]].Z3DP);
     trianglr[3].tx :=triangl[vp[1]].tx +(triangl[vo[1]].tx-triangl[vp[1]].tx)*(0-triangl[vp[1]].Z3DP)/(triangl[vo[1]].Z3DP-triangl[vp[1]].Z3DP);
    trianglr[3].ty :=triangl[vp[1]].ty +(triangl[vo[1]].ty-triangl[vp[1]].ty)*(0-triangl[vp[1]].Z3DP)/(triangl[vo[1]].Z3DP-triangl[vp[1]].Z3DP);
     trianglr[3].X2D:=(ScaleWidth+FOCUS_KAMERA*(trianglr[3].X3DP) *d2);
     trianglr[3].Y2D:=(ScaleHEight-FOCUS_KAMERA*(trianglr[3].Y3DP) *d2);
      trianglr1[1]:=triangl[vp[2]];
      trianglr1[2]:=trianglr[3];
        trianglr[3].Z3DP:=0;
    trianglr1[3].X3DP :=triangl[vp[2]].X3DP +(triangl[vo[1]].X3DP-triangl[vp[2]].X3DP)*(0-triangl[vp[2]].Z3DP)/(triangl[vo[1]].Z3DP-triangl[vp[2]].Z3DP);
    trianglr1[3].y3DP :=triangl[vp[2]].y3DP +(triangl[vo[1]].y3DP-triangl[vp[2]].y3DP)*(0-triangl[vp[2]].Z3DP)/(triangl[vo[1]].Z3DP-triangl[vp[2]].Z3DP);
     trianglr1[3].tx :=triangl[vp[2]].tx +(triangl[vo[1]].tx-triangl[vp[2]].tx)*(0-triangl[vp[2]].Z3DP)/(triangl[vo[1]].Z3DP-triangl[vp[2]].Z3DP);
    trianglr1[3].ty :=triangl[vp[2]].ty +(triangl[vo[1]].ty-triangl[vp[2]].ty)*(0-triangl[vp[2]].Z3DP)/(triangl[vo[1]].Z3DP-triangl[vp[2]].Z3DP);
     trianglr1[3].X2D:=(ScaleWidth+FOCUS_KAMERA*(trianglr1[3].X3DP) *d2);
     trianglr1[3].Y2D:=(ScaleHEight-FOCUS_KAMERA*(trianglr1[3].Y3DP) *d2);
        fillt(trianglr[1],trianglr[2],trianglr[3]);
         fillt(trianglr1[1],trianglr1[2],trianglr1[3]);
        exit;
    end;
    SortVertex(triangl,Xmax,xmin,ymax,ymin);
    if ymax<0 then ymax:=0; if ymax>height then ymax:=height;
    if ymin<0 then ymin:=0; if ymin>height then ymin:=height;
    if xmax<0 then xmax:=0; if xmax>width then xmax:=width;
    if xmin<0 then xmin:=0; if xmin>width then xmin:=width;
    if (ymax <> ymin) and (xmax <> xmin) then
        begin
 z1:=(1/(FOCUS_KAMERA+triangl[1].Z3DP));
 z2:=(1/(FOCUS_KAMERA+triangl[2].Z3DP));
 z3:=(1/(FOCUS_KAMERA+triangl[3].Z3DP));
        zz1:=(z2-z1);
        zz3:=(z3-z1);
        zz5:= (z3-z2);
        triangl[1].TX:=triangl[1].TX*z1;
        triangl[2].TX:=triangl[2].TX*z2;
        triangl[3].TX:=triangl[3].TX*z3;
        triangl[1].Ty:=triangl[1].Ty*z1;
        triangl[2].Ty:=triangl[2].Ty*z2;
        triangl[3].Ty:=triangl[3].Ty*z3;
        tx1:=(triangl[2].TX-triangl[1].TX);
        tx3:=(triangl[3].TX-triangl[1].TX);
        tx5:= (triangl[3].TX-triangl[2].TX);
        ty1:=(triangl[2].TY-triangl[1].TY);
        ty3:=(triangl[3].TY-triangl[1].TY);
        ty5:= (triangl[3].TY-triangl[2].TY);
        cc1:=(Triangl[2].x2d-Triangl[1].x2d);
        cc2:=(Triangl[2].y2d-Triangl[1].y2d);
        cc3:=(Triangl[3].x2d-Triangl[1].x2d);
        cc4:=(Triangl[3].y2d-Triangl[1].y2d);
        cc5:=(Triangl[3].x2d-Triangl[2].x2d);
        cc6:=(Triangl[3].y2d-Triangl[2].y2d);
        if (cc2<>0)then begin c1:=cc1/cc2; end;
        if (cc4<>0)then begin c2:=cc3/cc4;cz2:=zz3/cc4;ctx2:=tx3/cc4;cty2:=ty3/cc4; end;
        if (cc6<>0)then begin c3:=cc5/cc6; end;
x_start := Triangl[1].x2d+cc2*c2;
x_end := Triangl[2].x2d;
Z_start := z1+cc2*cz2;
Z_end := z2;
tx_start := Triangl[1].tx+cc2*ctx2;
tx_end := Triangl[2].tx;
ty_start := Triangl[1].ty+cc2*cty2;
ty_end :=Triangl[2].ty;
if (x_start-x_end)<>0 then  dil1:= 1/(x_start-x_end);
d:= (z_start-z_end)*dil1;
dx:= (tx_start-tx_end)*dil1;
dy:= (ty_start-ty_end)*dil1;
        y1:=round(0.5+ymin);
        y2:=round(0.5+Triangl[2].y2d);
        y3:=round(0.5+ymax)-1;
        if y2<0 then y2:=0;
         yraz:=y1-triangl[1].y2d  ;
         yraz1:=y2-triangl[2].y2d ;
         MinX := Triangl[1].x2d+(yraz)*c2;
          maxX :=Triangl[1].x2d+(yraz)*c1;
           maxX1 :=Triangl[2].x2d+(yraz1)*c3;
            MinXt := Triangl[1].tx+(yraz)*ctx2;
              Minyt := Triangl[1].ty+(yraz)*cty2;
         zmin:=z1+(yraz)*cz2;
          for j:=y1 to y3 do
            begin
            if j< y2 then
                begin
                    PaintLineT((MaxX),(MinX),j,zmin,minxt,minyt);
                     maxX :=maxX+c1;
                 end
                 else
                 begin
                         PaintLineT((MaxX1),(MinX),j,zmin,minxt,minyt);
                        maxX1 :=maxX1+c3;
                end;
                MinX := MinX+c2;
                zmin:=zmin+cz2;
                minyt:=minyt+cty2;
                minxt:=minxt+ctx2;
            end;
    end;
end;

procedure tRender3D.Fill(var Vertex1,Vertex2,vertex3:TVertex3d2d;R,G,B:byte);
var
   {$A4}
Xmin,XMax:double;
Ymin,YMax:double;
MaxX,MaxX1,MinX:double;
x_start,x_end,z_start,z_end:double ;
i,j:integer;
y1,y2,y3:integer;
 ko,kp:integer;
begin
    triangl[1]:=vertex1;
    triangl[2]:=vertex2;
    triangl[3]:=vertex3;
         kp:=0;
     ko:=0;
    triangl[1]:=vertex1;
    triangl[2]:=vertex2;
    triangl[3]:=vertex3;
     for i:=1 to 3 do
        begin
            if triangl[i].Z3DP<0 then
                begin
                    ko:=ko+1;
                    vo[ko]:=i;
                end
                else
                begin
                kp:=kp+1;
                vp[kp]:=i;
                end;
        end;
if ko=3  then exit;
if ko=2 then
    begin
        trianglr[vp[1]]:= triangl[vp[1]];
        trianglr[vo[1]].Z3DP:=0;
        trianglr[vo[2]].Z3DP:=0;
        trianglr[vo[1]].X3DP:=triangl[vo[1]].X3DP+(triangl[vp[1]].X3DP - triangl[vo[1]].X3DP)*(0-triangl[vo[1]].Z3DP)/(triangl[vp[1]].Z3DP-triangl[vo[1]].Z3DP) ;
        trianglr[vo[1]].Y3DP:=triangl[vo[1]].Y3DP+(triangl[vp[1]].Y3DP - triangl[vo[1]].Y3DP)*(0-triangl[vo[1]].Z3DP)/(triangl[vp[1]].Z3DP-triangl[vo[1]].Z3DP) ;
        trianglr[vo[1]].X2D:=(ScaleWidth+FOCUS_KAMERA*(trianglr[vo[1]].X3DP) *d2);
        trianglr[vo[1]].Y2D:=(ScaleHEight-FOCUS_KAMERA*(trianglr[vo[1]].Y3DP) *d2);
        trianglr[vo[2]].X3DP:=triangl[vo[2]].X3DP+(triangl[vp[1]].X3DP - triangl[vo[2]].X3DP)*(0-triangl[vo[2]].Z3DP)/(triangl[vp[1]].Z3DP-triangl[vo[2]].Z3DP) ;
        trianglr[vo[2]].Y3DP:=triangl[vo[2]].Y3DP+(triangl[vp[1]].Y3DP - triangl[vo[2]].Y3DP)*(0-triangl[vo[2]].Z3DP)/(triangl[vp[1]].Z3DP-triangl[vo[2]].Z3DP) ;
        trianglr[vo[2]].X2D:=(ScaleWidth+FOCUS_KAMERA*(trianglr[vo[2]].X3DP) *d2);
        trianglr[vo[2]].Y2D:=(ScaleHEight-FOCUS_KAMERA*(trianglr[vo[2]].Y3DP) *d2);
        fill(trianglr[1],trianglr[2],trianglr[3],r,g,b);
        exit;
    end;
if ko=1  then
    begin
    trianglr[1]:=triangl[vp[1]];
    trianglr[2]:=triangl[vp[2]];
    trianglr[3].Z3DP:=0;
    trianglr[3].X3DP :=triangl[vp[1]].X3DP +(triangl[vo[1]].X3DP-triangl[vp[1]].X3DP)*(0-triangl[vp[1]].Z3DP)/(triangl[vo[1]].Z3DP-triangl[vp[1]].Z3DP);
    trianglr[3].y3DP :=triangl[vp[1]].y3DP +(triangl[vo[1]].y3DP-triangl[vp[1]].y3DP)*(0-triangl[vp[1]].Z3DP)/(triangl[vo[1]].Z3DP-triangl[vp[1]].Z3DP);
     trianglr[3].X2D:=(ScaleWidth+FOCUS_KAMERA*(trianglr[3].X3DP) *d2);
     trianglr[3].Y2D:=(ScaleHEight-FOCUS_KAMERA*(trianglr[3].Y3DP) *d2);
      trianglr1[1]:=triangl[vp[2]];
      trianglr1[2]:=trianglr[3];
        trianglr[3].Z3DP:=0;
    trianglr1[3].X3DP :=triangl[vp[2]].X3DP +(triangl[vo[1]].X3DP-triangl[vp[2]].X3DP)*(0-triangl[vp[2]].Z3DP)/(triangl[vo[1]].Z3DP-triangl[vp[2]].Z3DP);
    trianglr1[3].y3DP :=triangl[vp[2]].y3DP +(triangl[vo[1]].y3DP-triangl[vp[2]].y3DP)*(0-triangl[vp[2]].Z3DP)/(triangl[vo[1]].Z3DP-triangl[vp[2]].Z3DP);
     trianglr1[3].X2D:=(ScaleWidth+FOCUS_KAMERA*(trianglr1[3].X3DP) *d2);
     trianglr1[3].Y2D:=(ScaleHEight-FOCUS_KAMERA*(trianglr1[3].Y3DP) *d2);
        fill(trianglr[1],trianglr[2],trianglr[3],r,g,b);
         fill(trianglr1[1],trianglr1[2],trianglr1[3],r,g,b);
        exit;
    end;
    SortVertex(triangl,Xmax,xmin,ymax,ymin);
    if ymax<0 then ymax:=0; if ymax>height then ymax:=height;
    if ymin<0 then ymin:=0; if ymin>height then ymin:=height;
    if xmax<0 then xmax:=0; if xmax>width then xmax:=width;
    if xmin<0 then xmin:=0; if xmin>width then xmin:=width;
    if (ymax <> ymin) and (xmax <> xmin) then
        begin
        if (FOCUS_KAMERA+triangl[1].Z3DP)<>0 then z1:=(1/(FOCUS_KAMERA+triangl[1].Z3DP));
        if (FOCUS_KAMERA+triangl[2].Z3DP)<>0 then z2:=(1/(FOCUS_KAMERA+triangl[2].Z3DP));
        if (FOCUS_KAMERA+triangl[3].Z3DP)<>0 then z3:=(1/(FOCUS_KAMERA+triangl[3].Z3DP));
        zz1:=(z2-z1);
        zz3:=(z3-z1);
        zz5:= (z3-z2);
        cc1:=(Triangl[2].x2d-Triangl[1].x2d);
        cc2:=(Triangl[2].y2d-Triangl[1].y2d);
        cc3:=(Triangl[3].x2d-Triangl[1].x2d);
        cc4:=(Triangl[3].y2d-Triangl[1].y2d);
        cc5:=(Triangl[3].x2d-Triangl[2].x2d);
        cc6:=(Triangl[3].y2d-Triangl[2].y2d);
        if (cc2<>0)then begin c1:=cc1/cc2; cz1:=zz1/cc2; end;
        if (cc4<>0)then begin c2:=cc3/cc4;cz2:=zz3/cc4;end;
        if (cc6<>0)then begin c3:=cc5/cc6;cz3:=zz5/cc6; end;
x_start := Triangl[1].x2d+(Triangl[2].y2d-Triangl[1].y2d)*c2;
x_end := Triangl[2].x2d;
Z_start := z1+(Triangl[2].y2d-Triangl[1].y2d)*cz2;
Z_end := z2;
if (x_start-x_end)<>0 then d:= (z_start-z_end)/(x_start-x_end);
             y1:=round(0.5+ymin);
        y2:=round(0.5+Triangl[2].y2d);
        y3:=round(0.5+ymax)-1;
        if y2<0 then y2:=0;
         MinX := Triangl[1].x2d+(y1-triangl[1].y2d)*c2;
         zmin:=z1+(y1-triangl[1].y2d)*cz2;
         maxX :=Triangl[1].x2d+(y1-triangl[1].y2d)*c1;
         zmax:=z1+(y1-triangl[1].y2d)*cz1 ;
         maxX1 :=Triangl[2].x2d+(y2-triangl[2].y2d)*c3;
         zmax1:=z2+(y2-triangl[2].y2d)*cz3 ;
        for j:=y1 to y3 do
            begin
                if j< y2 then
                    begin
                         PaintLine((MaxX),(MinX),j,zmax,zmin,r,g,b);
                        zmax:=zmax+cz1;
                        maxX :=maxX+c1;
                    end
                    else
                    begin
                    PaintLine((MaxX1),(MinX),j,zmax1,zmin,r,g,b);
                    zmax1:=zmax1+cz3 ;
                    maxX1 :=maxX1+c3;
                end;
                 MinX := MinX+c2;
                zmin:=zmin+cz2;
            end;
    end;
end;

procedure TRender3d.BitMapToPointer(var PointerBitMap:PRgb; Bitmap:TBitMAp);
var i:integer;
H:integer;
begin
 h:=bitmap.height-1 ;
 for i:=0 to h do
PointerBitMap[i]:=Bitmap.ScanLine[i];
end;

procedure TRender3d.CreateFog;
var
   {$A2}
i,j:integer;
    {$A4}
per,per1:double;
begin
 per:=-1/(fog.L);
for i:=0 to width-1 do
    for j:=0 to Height-1 do
        begin
            if (zbuffer[i,j]<>$ffffffff) and (zbuffer[i,j]<fog.L) then
                begin
                    per1:=per*(zbuffer[i,j]-fog.L) ;
                    ArrayPointer[j][i].R:=round(fog.R+(ArrayPointer[j][i].R-fog.R)*per1);
                    ArrayPointer[j][i].g:=round(fog.g+(ArrayPointer[j][i].g-fog.g)*per1);
                    ArrayPointer[j][i].b:=round(fog.b+(ArrayPointer[j][i].b-fog.b)*per1);
                end
                else
                begin
                 ArrayPointer[j][i].R:=fog.R;
                    ArrayPointer[j][i].g:=fog.g;
                    ArrayPointer[j][i].b:=fog.b;
                end;
        end;
end;

Procedure Trender3d.SetPointKamera(x,y,z:double);
var
   {$A4}
vx,vy,vz:double;
begin
 vx:=x-kamerax;
vy:=y-kameray;
vz:=z-kameraz;
AngleKameraOX.cos:=sqrt(vx*vx+vz*vz)/sqrt(vy*vy+vx*vx+vz*vz)   ;
AngleKameraOX.sin:=-vy/sqrt(vy*vy+vx*vx+vz*vz) ;
AngleKameraOY.cos:=  vz/sqrt(vx*vx+vz*vz);
AngleKameraOy.sin:=  -vx/sqrt(vx*vx+vz*vz);
MatrixOX[3,2]:=-AngleKameraOX.Sin;
MatrixOX[3,3]:=AngleKameraOX.Cos;
MatrixOX[2,2]:=AngleKameraOX.Cos;
MatrixOX[2,3]:=AngleKameraOX.Sin;
MatrixOY[1,1]:=AngleKameraOy.Cos;
MatrixOY[1,3]:=AngleKameraOy.Sin;
MatrixOY[3,1]:=-AngleKameraOy.Sin;
MatrixOY[3,3]:=AngleKameraOy.Cos;
MatrixResult[1,1]:=MatrixOZ[1,1]*MatrixOY[1,1]+MatrixOZ[2,1]*MatrixOY[3,1]*MatrixOX[2,3];
MatrixResult[1,2]:=MatrixOZ[2,1]*MatrixOX[2,2];
MatrixResult[1,3]:=MatrixOZ[1,1]*MatrixOY[1,3]+MatrixOZ[2,1]*MatrixOY[3,3]*MatrixOX[2,3];
MatrixResult[2,1]:=MatrixOZ[1,2]*MatrixOY[1,1]+MatrixOZ[2,2]*MatrixOY[3,1]*MatrixOX[2,3];
MatrixResult[2,2]:=MatrixOZ[2,2]*MatrixOX[2,2];
MatrixResult[2,3]:=MatrixOZ[1,2]*MatrixOY[1,3]+MatrixOZ[2,2]*MatrixOY[3,3]*MatrixOX[2,3];
MatrixResult[3,1]:=MatrixOY[3,1]*MatrixOX[3,3];
MatrixResult[3,2]:=MatrixOX[3,2];
MatrixResult[3,3]:=MatrixOY[3,3]*MatrixOX[3,3];
end;

procedure TRender3d.point3d(vertex:TVertex3d2d;r,g,b:byte);
 var
xx,yy:integer;
begin
 xx:=round(0.5+Vertex.X2D);
  yy:=round(0.5+Vertex.y2D);
if (xx>=0) and (xx<=width) and (yy>=0) and (yy<=height) then
   if  (vertex.Z3DP<ZBuffer[xx,yy]) and (vertex.Z3DP>=0)   then
        begin
       ArrayPointer[yy][xx].r:=R ;
        ArrayPointer[yy][xx].G:= g;
        ArrayPointer[yy][xx].b:=b;
        ZBuffer[xx,yy]:=vertex.Z3DP;
        end;
 end;
end.
Unit1 :
uses Graph3d

var
  Form1: TForm1;
  h:Trender3D;
  ii:TbitMap;
  tt,t,t1:double;
  AI:PRGB;
  AB:PRGB;
  i,j:integer;
  B,b1:TBitMap;
  tr:Ttriangles;
  v1,v2:array[0..100,0..100] of TVertex3D2D;
  col:array[0..100,0..100] of byte;
  Tex:TTexture;
  f:boolean;
  
//

procedure DrawTex  ;
  var
 RT:byte;
begin

b1.Canvas.FillRect(rect(0,0,500,500));
 for i:=0 to 499  do begin

    for j:=0 to 499 do begin
           tex.Texture[i][j].r:=ab[i][j].r;
      tex.Texture[i][j].g:=ab[i][j].r;
       tex.Texture[i][j].b:=ab[i][j].r;

        if (ab[i][j].r<tt+3) and (ab[i][j].r>(tt-3)) then
       begin

      tex.Texture[i][j].r:=ab[i][j].r;
      tex.Texture[i][j].g:=ab[i][j].r;
       tex.Texture[i][j].b:=ab[i][j].r;
        end;
         if (ab[i][j].r<tt+3) then
       begin
      tex.Texture[i][j].r:=255;
      tex.Texture[i][j].g:=0;
       tex.Texture[i][j].b:=0;
        end;
       if (ab[i][j].r>tt) and (ab[i][j].r<tt+3) then
       begin
       tex.Texture[i][j].r:=255-ab[i][j].r;
      tex.Texture[i][j].g:=255-ab[i][j].r;
       tex.Texture[i][j].b:=255-ab[i][j].r;
        end;
    if (i mod 20 =0) or (j mod 40 =0) then begin
    tex.Texture[i][j].r:=0;
      tex.Texture[i][j].g:=255-ab[i][j].r;
       tex.Texture[i][j].b:=0;
     end;
    end; 
end;
end;
 
procedure TForm1.Timer1Timer(Sender: TObject);
var
i,j:integer;
c:byte;
begin
if f=true then tt:=tt+1 else tt:=tt-1;
DrawTex;
 h.FillZBuffer;
 t1:=t1+1;
 t:=t+1;
ii.Canvas.FillRect(Rect(0,0,640,480));
h.MoveKamera(700*cos(t/100)*sin(t/300),800*cos(t/200),700*sin(t/100));
 h.SetPointKamera(0,0,0);
  for i:=0 to 50 do
    for j:=0 to 100 do
    begin
    h.xyz2D(v2[i,j]) ;
    end;
  for i:=0 to 49 do
    for j:=0 to 99 do
    begin
    h.FillTriangle(v2[i,j],v2[i,j+1],v2[i+1,j],col[i,j],0,0);
   h.FillTriangle(v2[i,j+1],v2[i+1,j+1],v2[i+1,j],col[i,j],0,0);
    end;
    h.Fog.R:=0;
    h.Fog.g:=0;
    h.Fog.b:=0;
    h.Fog.L:=600;
    //  h.CreateFog;
       Form1.Canvas.stretchDraw(rect(0,0,clientwidth,clientheight),ii);
         if tt>254 then begin;f:=False end;
         if tt<1 then begin ;f:=true end;
end;

procedure TForm1.FormCreate(Sender: TObject);
 var
i,j:integer;
k:integer;
begin
 B:=TBitMap.Create;
B1:=TBitMap.Create;
b1.PixelFormat:=pf24bit;
b1.Width:=500;
b1.Height:=500;
B.Assign(Image1.Picture.Bitmap);
b1.Canvas.Brush.Color:=0;
 image1.Canvas.Pen.Color:=rgb(0,0,0);
 for j:=0 to 499  do begin
       AB[j]:=B.ScanLine[j];
       AI[j]:=b1.ScanLine[j];
end;
  ii:=TBitMAp.Create;
ii.PixelFormat:=pf24bit;
h:=Trender3D.Create(640,480,ii);
h.RotateKamera(0,0,1);
  h.NoneFace:=true;
 ii.Canvas.Brush.Color:=rgb(0,0,0);
Timer1.Enabled :=true;
h.BitMapToPointer(Tex.Texture,b1);
tex.width:=499;
tex.height:=499;
h.Texture:=@tex;
h.TextureEnabled:=true;
k:=0;
for i:=0 to 50 do
    for j:=0 to 100 do
        begin
            v2[i,j].TX:=9.98*i;
            v2[i,j].Ty:=4.99*j;
            v1[i,j].X3DM:=(300+AB[round(4.99*j),round(9.98*i)].g)*sin(pi2*i/100)*cos(pi2*j/100);
            v1[i,j].Y3DM:=500*cos(pi2*i/100);
            v1[i,j].Z3DM:=(300+AB[round(4.99*j),round(9.98*i)].g)*sin(pi2*i/100)*sin(pi2*j/100);
        end;
    for i:=0 to 50 do
    for j:=0 to 100 do
    begin
    v2[i,j].y3DM:=v1[i,j].y3DM;
    v2[i,j].X3DM:=v1[i,j].x3DM;
    v2[i,j].z3DM:=v1[i,j].z3DM;
    end;
end;

Keine Kommentare:

Kommentar veröffentlichen

Beliebte Posts

Translate