UNIT Math3D; (* PROCEDURE SetRotAngles(NewAngleX, NewAngleY, NewAngleZ: Word); Prepare three integer values for rotation around the X Y and Z axis respectively. (See also: InitMath3D) PROCEDURE SetDistance(Distance: Word); Prepare the viewpoint distance from 0,0,0 in vectorspace. (See also: InitMath3D) PROCEDURE GenRotAngles; Generate new rotation angles to produce a three-axis arbitary object rotation. PROCEDURE SetPoint(NewPointX3D, NewPointY3D, NewPointZ3D: Integer); Rotates the point around three axis, and projects the result in a 2D matrix. Use the GetPoint??D functions to get the results from this calculation. PROCEDURE InitMath3D; Initializes the Math3D unit. The following default values are set: Rotation angles = 0, Distance from 0,0,0 = 250, 3D and 2D points = 0. This procedure *MUST* be called before any other Math3D procedure or function, otherwise the results will be unpredictable (or you may even get Division by Zero errors) FUNCTION PcSin(Angle: LongInt): Integer; Returns the sinus value of any angle expressed in degrees between -2147483648 and 2147483647. The sinus value has been multiplied by 128 and *MUST* be divided by 128 when used. FUNCTION PcCos(Angle: LongInt): Integer; Returns the cosinus value of any angle expressed in degrees between -2147483648 and 2147483647. The cosinus value has been multiplied by 128 and *MUST* be divided by 128 when used. FUNCTION GetPointX3D: Integer; FUNCTION GetPointY3D: Integer; FUNCTION GetPointZ3D: Integer; In combination, these functions return the 3D point resulting from the SetPoint procedure. FUNCTION GetPointX2D: Word; FUNCTION GetPointY2D: Word; In combination, these functions return the projected 2D equivalent resulting from the SetPoint procedure. EXAMPLE: InitMath3D; {Initialize Math3D unit} SetPoint(10,-20,30); {Calculate 3D vector} PutPixel(GetPointX2D,GetPointY2D); {Plot the 2D result} *) {$G+} INTERFACE procedure movecamera(movex,movey,movez:integer); procedure getrotangles(var anglex,angley,anglez:word); function GetHiddenGrad:integer; PROCEDURE SetRotatespeed(NewXSpeed,NewYSpeed,NewZSpeed:word); PROCEDURE SetRotAngles(NewAngleX, NewAngleY, NewAngleZ: Word); PROCEDURE SetDistance(Distance: Word); PROCEDURE GenRotAngles; PROCEDURE SetPoint(NewPointX3D, NewPointY3D, NewPointZ3D: Integer); PROCEDURE InitMath3D; FUNCTION PcSin(Angle: Integer): Integer; FUNCTION PcCos(Angle: Integer): Integer; FUNCTION GetPointX3D: Integer; FUNCTION GetPointY3D: Integer; FUNCTION GetPointZ3D: Integer; FUNCTION GetPointX2D: integer; FUNCTION GetPointY2D: integer; FUNCTION HIDDEN(X1,Y1,X2,Y2,X3,Y3:INTEGER) :BOOLEAN; IMPLEMENTATION USES Crt; const sinsize = 2880; shls = 3; VAR xSpeed: word; ySpeed: word; zSpeed: word; mathattribute:byte; SinCalced: ARRAY[0..sinsize] OF Integer; CosCalced: ARRAY[0..sinsize] OF Integer; Counter: Word; hiddengrad: Integer; FullTurn: Real; BufferR: Real; BufferW: Integer; RotAngleX: Word; RotAngleY: Word; RotAngleZ: Word; VpDistance: Word; PointX3D: Integer; PointY3D: Integer; PointZ3D: Integer; PointX2D: Integer; PointY2D: Integer; SiX: Integer; SiY: Integer; SiZ: Integer; CoX: Integer; CoY: Integer; CoZ: Integer; camovedx: integer; camovedy: integer; camovedz: integer; procedure movecamera(movex,movey,movez:integer); begin camovedx:=(-vpdistance*movex)div movez; camovedy:=(vpdistance*movey) div movez; camovedz:=movez div vpdistance; end; function GetHiddenGrad:integer; begin GetHiddenGrad:=hiddengrad; end; FUNCTION HIDDEN(X1,Y1,X2,Y2,X3,Y3:INTEGER) :BOOLEAN; BEGIN HIDDEN:=FALSE; hiddengrad:=(x3-x1)*(y2-y1)-(x2-x1)*(y3-y1); if hiddengrad<1 then HIDDEN:=TRUE; END; PROCEDURE SetRotatespeed(NewXSpeed,NewYSpeed,NewZSpeed:word); assembler; asm mov ax,newxspeed mov xspeed,ax mov ax,newyspeed mov yspeed,ax mov ax,newzspeed mov zspeed,ax end; procedure getrotangles(var anglex,angley,anglez:word); begin anglex:=rotanglex div 8; angley:=rotangley div 8; anglez:=rotanglez div 8; end; PROCEDURE SetRotAngles(NewAngleX, NewAngleY, NewAngleZ: Word); BEGIN ASM mov ax, NewAngleX sal ax, shls mov RotAngleX, ax mov ax, NewAngleY sal ax, shls mov RotAngleY, ax mov ax, NewAngleZ sal ax, shls mov RotAngleZ, ax end; SiX:=PcSin(RotAngleX); SiY:=PcSin(RotAngleY); SiZ:=PcSin(RotAngleZ); CoX:=PcCos(RotAngleX); CoY:=PcCos(RotAngleY); CoZ:=PcCos(RotAngleZ); END; PROCEDURE SetDistance(Distance: Word); ASSEMBLER; ASM mov ax, Distance mov VpDistance, ax END; PROCEDURE GenRotAngles; BEGIN ASM xor dx,dx mov ax, RotAngleX mov dx, xspeed add ax, dx {Increase angle around X axis} cmp ax, sinsize {Full rotation yet?} jb @@10 {No, go on} sub ax, sinsize {Yes, subtract 360 degrees} @@10: mov RotAngleX, ax mov dx, yspeed mov ax, RotAngleY add ax, dx {Increase angle around Y axis} cmp ax, sinsize {Full rotation yet?} jb @@20 {No, go on} sub ax, sinsize {Yes, subtract sinsize degrees} @@20: mov RotAngleY, ax mov ax, RotAngleZ mov dx, zspeed add ax, dx {Increase angle around Z axis} cmp ax, sinsize {Full rotation yet?} jb @@30 {No, go on} sub ax, sinsize {Yes, subtract sinsize degrees} @@30: mov RotAngleZ, ax END; SiX:=PcSin(RotAngleX); SiY:=PcSin(RotAngleY); SiZ:=PcSin(RotAngleZ); CoX:=PcCos(RotAngleX); CoY:=PcCos(RotAngleY); CoZ:=PcCos(RotAngleZ); END; PROCEDURE SetPoint(NewPointX3D, NewPointY3D, NewPointZ3D: Integer); ASSEMBLER; ASM { next up : x2d = (x3d*zoom)/(z+dist)} mov ax, NewPointX3D mov PointX3D, ax mov ax, NewPointY3D mov PointY3D, ax mov ax, NewPointZ3D mov PointZ3D, ax mov ax, PointY3D {Do X axis rotation} imul Cox sar ax, 7 mov bx, ax mov ax, PointZ3D imul SiX sar ax, 7 add ax, bx mov cx, ax {cx holds new NY} mov ax, PointZ3D imul CoX sar ax, 7 mov bx, ax mov ax, PointY3D imul SiX sar ax, 7 sub bx, ax {bx holds new NZ} mov PointZ3D, bx mov PointY3D, cx mov ax, PointX3D {Do Y axis rotation} imul CoY sar ax, 7 mov bx, ax mov ax, PointZ3D imul SiY sar ax, 7 sub bx, ax mov cx, bx {cx holds new NX} mov ax, PointX3D imul SiY sar ax, 7 mov bx, ax mov ax, PointZ3D imul CoY sar ax, 7 add ax, bx {ax holds new NZ} mov PointX3D, cx mov PointZ3D, ax mov ax, PointX3D {Do Z axis rotation} imul CoZ sar ax, 7 mov bx, ax mov ax, PointY3D imul SiZ sar ax, 7 add ax, bx mov cx, ax {cx holds new NX} mov ax, PointY3D imul CoZ sar ax, 7 mov bx, ax mov ax, PointX3D imul SiZ sar ax, 7 sub bx, ax {bx holds new NY} mov PointY3D, bx mov PointX3D, cx { asx = (x3d*zoom)/(z+dist)} { neg pointx3d neg pointy2d mov ax,pointx3d mov bx,zoom imul bx mov cx,pointz3d add cx,Vpdistance idiv cx add ax,160 mov pointx2d,ax mov ax,pointy3d mov bx,zoom imul bx mov cx,pointz3d add cx,vpdistance idiv cx add ax,100 mov pointy2d,ax} mov cx, PointZ3D add cx, VpDistance add cx,100 mov ax, PointX3D cmp cx,2 jle @@divzero imul VpDistance idiv cx mov PointY2D, ax mov bx,100 add PointY2D, bx mov ax, PointY3D imul VpDistance cmp cx,2 jle @@divzero idiv cx mov PointX2D, ax mov bx,160 add PointX2D, bx @@divzero: END; PROCEDURE InitMath3D; BEGIN VpDistance:=250; xspeed:=3; yspeed:=6; zspeed:=9; camovedx:=0; camovedy:=0; camovedz:=0; RotAngleX:=0; RotAngleY:=0; RotAngleZ:=0; PointX3D:=0; PointY3D:=0; PointZ3D:=0; PointX2D:=0; PointY2D:=0; FullTurn:=2*Pi; FOR Counter:=0 TO sinsize DO BEGIN BufferR:=Sin((Fullturn*Counter)/sinsize); BufferW:=round(BufferR*128); SinCalced[Counter]:=BufferW; END; FOR Counter:=0 TO sinsize DO BEGIN BufferR:=Cos((Fullturn*Counter)/sinsize); BufferW:=round(BufferR*128); CosCalced[Counter]:=BufferW; END; SiX:=PcSin(RotAngleX shl shls); SiY:=PcSin(RotAngleY shl shls); SiZ:=PcSin(RotAngleZ shl shls); CoX:=PcCos(RotAngleX shl shls); CoY:=PcCos(RotAngleY shl shls); CoZ:=PcCos(RotAngleZ shl shls); END; FUNCTION PcSin(Angle: Integer): Integer; BEGIN asm mov ax,angle cmp ax,sinsize jng @@mindre @@back1: sub ax,sinsize cmp ax,sinsize jg @@back1 jmp @@storre @@mindre: cmp ax,0 jnl @@storre @@back2: add ax,sinsize cmp ax,0 jl @@back2 @@storre: sal ax,1 mov si,offset sincalced add si,ax lodsw mov angle,ax end;{} PcSin:=Angle; END; FUNCTION PcCos(Angle: Integer): Integer; BEGIN asm mov ax,angle cmp ax,sinsize jng @@mindre @@back1: sub ax,sinsize cmp ax,sinsize jg @@back1 jmp @@storre @@mindre: cmp ax,0 jnl @@storre @@back2: add ax,sinsize cmp ax,0 jl @@back2 @@storre: mov angle,ax sal ax,1 mov si,offset coscalced add si,ax lodsw mov angle,ax end;{} PcCos:=Angle; eND; FUNCTION GetPointX3D: Integer; BEGIN GetPointX3D:=PointX3D; END; FUNCTION GetPointY3D: Integer; BEGIN GetPointY3D:=PointY3D; END; FUNCTION GetPointZ3D: Integer; BEGIN GetPointZ3D:=PointZ3D; END; FUNCTION GetPointX2D: integer; BEGIN GetPointX2D:=PointX2D; END; FUNCTION GetPointY2D: integer; BEGIN GetPointY2D:=PointY2D; END; begin end.