Unit Objects; Interface {$DEFINE Bilinear} Uses Matrices,UVector,GTypes; TYPE {----------- [OBJECTS] --------------} PObject = ^TObject; TObject = object Pos : tVec; ID : ObjID; OType : string; Constructor Init; Function ISect(aRay : PRay):float;virtual; Procedure GetNormal(var Norm:TVec;aPos : TVec);virtual; Destructor Done;virtual; end; PFileObj = ^TFileObj; TFileObj = object (TObject) Constructor Init; Constructor Load(var F:FILE); Procedure Save(var F:FILE);virtual; end; PColObj = ^TColObj; TColObj = object (TFileObj) Color : RGB; Constructor Init; end; PSurfObj = ^TSurfObj; TSurfObj = object (TColObj) Surface : PSurfDesc; Texture : PTexture; TexTrans : TTransform; Procedure SetSurf(aKd,aKs,aNs:float); Constructor Init; Destructor Done;virtual; Procedure Transform(tr:TTRANSFORM);virtual; Procedure SetTexture(aPT:PTexture;aR,aLen:real);virtual; Procedure GetColor(var aC : RGB;aV:tVec);virtual; end; CONE_INTER_TYPE = (SIDE_HIT,BASE_HIT,CAP_HIT); tConeInters = array [0..3] of record d : float; t : CONE_INTER_TYPE; end; PCone = ^TCone; TCone = object (TSurfObj) trans,pt : TTRANSFORM; apex,base : tVec; apex_rad,base_rad,dist : float; FlagCyl : boolean; LastInter : CONE_INTER_TYPE; Constructor Init(aApex,aBase:tVec;aBaseRad,aApexRad : float; aCol:RGB); Constructor Load(var F:FILE); Procedure Save(var F:FILE);virtual; Procedure Transform(tr:TTRANSFORM);virtual; Function ISect(aRay : PRay):float;virtual; Function Inside(aP:tVec):boolean; Procedure GetNormal(var Norm:TVec;aPos : TVec);virtual; private Procedure ComputeConeData; Procedure ComputeCylData; Function ISectCone(aRay:tRay;var aI:tConeInters):INTEGER; end; PSphere = ^TSphere; TSphere = object (TSurfObj) Radius : float; Constructor Init(ax,ay,az,arad : float; aCol:RGB); Constructor Load(var F:FILE); Procedure Save(var F:FILE);virtual; Procedure Transform(tr:TTRANSFORM);virtual; Function ISect(aRay : PRay):float;virtual; Function Inside(aP:tVec):boolean; Procedure GetNormal(var Norm:TVec;aPos : TVec);virtual; end; PSurfPlane = ^TSurfPlane; TSurfPLane = object (TSurfObj) Pl : TPlane; Procedure Transform(tr:TTRANSFORM);virtual; Constructor Init(av1,av2,av3 : tVec; aCol:RGB); Constructor Load(var F:FILE); Constructor TriLoad(var F:FILE); Procedure Save(var F:FILE);virtual; Function ISect(aRay:PRay):float;virtual; Function Inside(aP:tVec):boolean; Procedure SetTexture(aPT:PTexture;aR,aLen:real);virtual; Procedure GetNormal(var Norm:TVec; aPos:TVec);virtual; end; PTriangle = ^TTriangle; TTriangle = object (TSurfObj) v1, v2, v3 : tVec; pl : TPlane; Constructor Init(av1,av2,av3 : tVec; aCol:RGB); Constructor Load(var F:FILE); Procedure Save(var F:FILE);virtual; Procedure Transform(tr:TTRANSFORM);virtual; Function ISect(aRay:PRay):float;virtual; Procedure GetNormal(var Norm:TVec; aPos:TVec);virtual; Procedure SetTexture(aPT:PTexture;aR,aLen:real);virtual; end; PQuad = ^TQuad; TQuad = object (TSurfObj) v1, v2, v3, v4 : tVec; pl : TPlane; Constructor Init(av1,av2,av3,aV4 : tVec; aCol:RGB); Procedure Transform(tr:TTRANSFORM);virtual; Constructor Load(var F:FILE); Procedure Save(var F:FILE);virtual; Function ISect(aRay:PRay):float;virtual; Procedure GetNormal(var Norm:TVec; aPos:TVec);virtual; Procedure SetTexture(aPT:PTexture;aR,aLen:real);virtual; end; PInterS = ^TInterS; TInterS = object (TSurfObj) Sp : PSphere; Pl : PSurfPlane; Inv : float; Constructor Load(var F:FILE); Procedure Save(var F:FILE);virtual; Function ISect(aRay:PRay):float;virtual; Procedure GetNormal(var Norm:TVec; aPos:TVec);virtual; Procedure Transform(tr:TTRANSFORM);virtual; end; {------------- [LIGHT] -----------------} PLight = ^TLight; TLight = object (TFileObj) Constructor Init; end; POmni = ^TOmni; TOmni = object (TLight) Color : RGB; Constructor Load(var F:FILE); Procedure Save(var F:FILE);virtual; Constructor Init(ax,ay,az:float;aCol:RGB); end; PSpot = ^TSpot; TSpot = object (TLight) Target : tVec; FOV : float; Color : RGB; Constructor Load(var F:FILE); Procedure Save(var F:FILE);virtual; Constructor Init(ax,ay,az,axo,ayo,azo,aFov:float;aCol:RGB); end; IMPLEMENTATION {TObject} Constructor TObject.Init; begin Pos := ZeroVec; OType := 'OBJ'; end;{TObject.Init} Function TObject.ISect; begin ISect := INF; end;{TObject.ISect} Procedure TObject.GetNormal; begin end;{TObject.GetNormal} Destructor TObject.Done; begin end;{TObject.Done} {TFileObject} Constructor TFileObj.Init; begin Inherited Init; ID := F_NULL; OType:=OType+'_FILE'; end; Constructor TFileObj.Load(var F:FILE); begin end; Procedure TFileObj.Save(var F:FILE); begin; end; {TColObj} Constructor TColObj.Init; begin Inherited Init; OType := OType + '_COL'; end; {TSurfObj} Constructor TSurfObj.Init; begin Inherited Init; Texture := Nil; OType := OType+'_SURF'; New(Surface); With Surface^ do begin Ks := 0; Kd := 0; Ns := 0; end; end; Procedure TSurfObj.SetSurf(aKd,aKs,aNs:float); begin with Surface^ do begin Ks := aKs; Kd := aKd; Ns := aNs; end; end; Procedure TSurfObj.GetColor; var v2:tVec; sx,sy,x,y : word; fx,fy : float; cc,cc1,cc2,cc3 : BRGB; A,B : RGB; begin if Texture = nil then begin aC := Color; end else begin MInvTransPoint(v2,av,TexTrans); sx := Texture^.SizeX; sy:=Texture^.SizeY; while v2.X < 0 do v2.X := v2.X + SX; while v2.Y < 0 do v2.Y := v2.Y + SY; {$IFNDEF Bilinear} x:=round(v2.X);y:=round(v2.Y); CC := Texture^.Bits^[(SY-1-(Y mod SY)) * SX + (X mod SX)]; aC.R := cc.R / 255 * Color.R; aC.G := cc.G / 255 * Color.G; aC.B := cc.B / 255 * Color.B; {$ELSE} fx := frac(v2.X);fy:=frac(v2.y);x:=trunc(v2.X);y:=trunc(v2.Y); CC := Texture^.Bits^[(SY-1-(Y mod SY)) * SX + (X mod SX)]; CC1 := Texture^.Bits^[(SY-1-(Y mod SY)) * SX + ((X+1) mod SX)]; CC2 := Texture^.Bits^[(SY-1-((Y+1) mod SY)) * SX + (X mod SX)]; CC3 := Texture^.Bits^[(SY-1-((Y+1) mod SY)) * SX + ((X+1) mod SX)]; A.R := (CC.R + (CC2.R-CC.R)*fy)/255; A.G := (CC.G + (CC2.G-CC.G)*fy)/255; A.B := (CC.B + (CC2.B-CC.B)*fy)/255; B.R := (CC1.R + (CC3.R-CC1.R)*fy)/255; B.G := (CC1.G + (CC3.G-CC1.G)*fy)/255; B.B := (CC1.B + (CC3.B-CC1.B)*fy)/255; aC.R := (A.R + (B.R-A.R)*fx)*Color.R; aC.G := (A.G + (B.G-A.G)*fx)*Color.G; aC.B := (A.B + (B.B-A.B)*fx)*Color.B; {$ENDIF} end; end; Procedure TSurfObj.Transform; begin MTransPoint(Pos,Pos,tr); Compose_Transforms(TexTrans,tr); end; Procedure TSurfObj.SetTexture; begin Texture := aPT; end; Destructor TSurfObj.Done; begin Dispose(Surface); Inherited Done; end; {-------------------------------------------------------------} {-------------------------------------------------------------} {--------------------- REAL OBJECTS --------------------------} {-------------------------------------------------------------} {-------------------------------------------------------------} {TCone} Constructor TCone.Init; begin Inherited Init; OType := OType + '_CONE'; ID := F_CONE; Apex := aApex;Base:=aBase; Apex_Rad := aApexRad;Base_Rad:=aBaseRad; Color := aCol; ComputeConeData; end; Constructor TCone.Load; begin Inherited Init; OType := OType + '_CONE'; ID := F_CONE; BlockRead(F,Apex,vecsize); BlockRead(F,Base,vecsize); BlockRead(F,Apex_Rad,sizeof(float)); BlockRead(F,Base_Rad,sizeof(float)); LoadRGB(F,Color); BlockRead(F,Surface^,vecsize); ComputeConeData; end; Procedure TCone.Save; begin BlockWrite(F,ID,1); BlockWrite(F,Apex,vecsize); BlockWrite(F,Base,vecsize); BlockWrite(F,Apex_Rad,sizeof(float)); BlockWrite(F,Base_Rad,sizeof(float)); SaveRGB(F,Color); BlockWrite(F,Surface^,vecsize); end; Procedure TCone.ComputeConeData; var tlen,len,tmpf:float; axis,tmpv,origin:tVec; begin if abs(Apex_Rad-Base_Rad) EPS then begin b := p.x*dir.x+p.y*dir.y; c := p.x*p.x+p.y*p.y-1; d := b*b-a*c; if d >= 0 then begin d := sqrt(d); t1 := (-b+d)/a; t2 := (-b-d)/a; z := p.z + t1*dir.z; if (Z>=0) and (z<=1) and (t1>=0) then begin aI[i].d:=t1/len; aI[i].t:=SIDE_HIT; inc(i); end; z := p.z + t2*dir.z; if (Z>=0) and (z<=1) and (t2>=0) then begin aI[i].d:=t2/len; aI[i].t:=SIDE_HIT; inc(i); end; end; end; end else {Solve cone intersections} begin a:=dir.x*dir.x+dir.y*dir.y-dir.z*dir.z; b:=dir.x*p.x+dir.y*p.y-dir.z*p.z; c:=p.x*p.x+p.y*p.y-p.z*p.z; if abs(a) < EPS then begin if abs(b) > EPS then begin t1 := 0.5*c/b; z := p.z + t1*dir.z; if (t1>=0) and (z>=Dist) and (Z<=1) then begin aI[i].d:=t1/len; aI[i].t:=SIDE_HIT; inc(i); end; end; end else begin d := b*b-a*c; if d>=0 then begin d:=sqrt(d); t1 := (-b+d)/a; t2 := (-b-d)/a; z := p.z + t1*dir.z; if (Z>=Dist) and (z<=1) and (t1>=0) then begin aI[i].d:=t1/len; aI[i].t:=SIDE_HIT; inc(i); end; z := p.z + t2*dir.z; if (Z>=Dist) and (z<=1) and (t2>=0) then begin aI[i].d:=t2/len; aI[i].t:=SIDE_HIT; inc(i); end; end; end; end; if abs(Dir.Z) > EPS then begin d:=(1-p.z)/dir.z; a:=p.x+d*dir.x; b:=p.y+d*dir.y; if ((sqr(a)+sqr(b)) <= 1) and (D>=0) then begin aI[i].d:=d/len; aI[i].t:=CAP_HIT; inc(i); end; d := (Dist - p.z)/dir.z; a := p.x+d*dir.x; b := p.y+d*dir.y; if FlagCyl then tmpf:=1 else tmpf := sqr(Dist); if ((sqr(a)+sqr(b)) <= tmpf) and (D>=0) then begin aI[i].d:=d/len; aI[i].t:=BASE_HIT; end; end; ISectCone:=i; end; {ISectCone} Procedure TCone.GetNormal; begin MInvTransPoint(Norm,aPos,Trans); case LastInter of SIDE_HIT: if FlagCyl then Norm.z := 0 else Norm.Z := -Norm.Z; BASE_HIT: VSet(Norm,0,0,-1); CAP_HIT: VSet(Norm,0,0,1); end; MTransNormal(Norm,Norm,Trans); VNorm(Norm,1); end; Function TCone.Inside; var NP : tVec; w2,z2:float; begin MInvTransPoint(NP,aP,Trans); w2 := NP.x*NP.x +NP.y*NP.y; if FlagCyl then begin if (w2 > 1+EPS) or (NP.Z<0-EPS) or (NP.Z > 1 + EPS) then begin Inside := false;exit;end else begin Inside := true;exit;end; end else begin z2 := np.z*np.z; if (w2 > z2+EPS) or (NP.Z 1 + EPS) then begin Inside := false;exit;end else begin Inside := true;exit;end; end; end; {TSphere} Constructor TSphere.Init(ax,ay,az,arad : float; aCol:RGB); begin Inherited Init; OType := OType + '_SPHERE'; ID := F_OBJ_SPHERE; VSet(Pos,ax,ay,az); Radius := aRad; Color := aCol; end;{TSphere.Init} Procedure TSphere.Transform; var vr : tVec; begin vr := Pos; vr.Y := vr.Y + radius; Inherited Transform(tr); MTransPoint(vr,vr,tr); VLinear(vr,vr,Pos,1,-1); Radius := sqrt(VDot(vr,vr)); end; Procedure TSphere.Save; begin BlockWrite(F,ID,sizeof(ObjID)); BlockWrite(F,Pos,sizeof(float)*3); BlockWrite(F,Radius,sizeof(float)); SaveRGB(F,Color); BlockWrite(F,Surface^,vecsize); end; Constructor TSphere.Load; begin Inherited Init; OType := OType + '_SPHERE'; ID := F_OBJ_SPHERE; BlockRead(F,Pos,sizeof(float)*3); BlockRead(F,Radius,sizeof(float)); LoadRGB(F,Color); BlockRead(F,Surface^,vecsize); end; Function TSphere.ISect(aRay : PRay):float; var a,b,c,d,t1,t2 : float; tmp : tvec; begin ISect := INF; a := VDot(aRay^.Dir,aRay^.Dir); VLinear(tmp,aRay^.Org,Pos,1,-1); b := 2*VDot(aRay^.Dir,tmp); c := VDot(tmp,tmp) - Radius*Radius; d := b*b-4*a*c; if d < 0 then exit; d := sqrt(d); t1 := (-b-d) / (2*a); t2 := (-b+d) / (2*a); if t2 < 0 then Exit; if t1 > 0 then ISect:=t1 else Isect:=t2; end;{TSphere.ISect} Function TSphere.Inside; begin VLinear(aP,aP,Pos,1,-1); Inside := VDot(aP,aP) <= Radius*Radius; end; Procedure TSphere.GetNormal(var Norm:TVec;aPos : TVec); begin VLinear(Norm,aPos,Pos,1,-1); VNorm(Norm,1); end;{TSphere.GetNormal} {TTRiangle} Constructor TTriangle.Init; begin Inherited Init; OType := OType + '_TRI'; ID := F_TRI; v1 := aV1; v2 := aV2; v3 := aV3; SetPlane(Pl,v1,v2,v3); Color := aCol; end; Procedure TTriangle.Transform; begin Inherited Transform(tr); MTransPoint(v1,v1,tr); MTransPoint(v2,v2,tr); MTransPoint(v3,v3,tr); SetPlane(Pl,v1,v2,v3); end; Procedure TTriangle.SetTexture(aPT:PTexture;aR,aLen:real); begin Inherited SetTexture(aPT,aR,aLen); CalcTransform(TexTrans,V1,V2,V3,aR,aLen); end; Procedure TTriangle.GetNormal; begin Norm := Pl.N; end; Function TTriangle.ISect; var del, delit : float; P : tVec; p1,p2,p3 : TPlane; begin del := -(VDot(Pl.N,aRay^.Org)+Pl.D); delit := VDot(Pl.N,aRay^.Dir); if abs(del)-p1.D) and (VDot(p2.N,p)>-p2.D) and (VDot(p3.N,p)>-p3.D) ) or ( (VDot(p1.N,p)<-p1.D) and (VDot(p2.N,p)<-p2.D) and (VDot(p3.N,p)<-p3.D) ) then Exit; ISect := INF; end; Constructor TTriangle.Load; begin BlockRead(F,v1,vecsize); BlockRead(F,v2,vecsize); BlockRead(F,v3,vecsize); LoadRGB(F,Color); Init(v1,v2,v3,Color); BlockRead(F,Surface^,vecsize); end; Procedure TTriangle.Save; begin BlockWrite(F,ID,1); BlockWrite(F,v1,vecsize); BlockWrite(F,v2,vecsize); BlockWrite(F,v3,vecsize); SaveRGB(F,Color); BlockWrite(F,Surface^,vecsize); end; {TQuad} Constructor TQuad.Init; begin Inherited Init; OType := OType + '_Quad'; ID := F_QUAD; v1 := aV1; v2 := aV2; v3 := aV3; v4 := aV4; SetPlane(Pl,v1,v2,v3); Color := aCol; end; Procedure TQuad.SetTexture(aPT:PTexture;aR,aLen:real); begin Inherited SetTexture(aPT,aR,aLen); CalcTransform(TexTrans,V1,V2,V3,aR,aLen); end; Procedure TQuad.Transform; begin Inherited Transform(tr); MTransPoint(v1,v1,tr); MTransPoint(v2,v2,tr); MTransPoint(v3,v3,tr); MTransPoint(v4,v4,tr); SetPlane(Pl,v1,v2,v3); end; Procedure TQuad.GetNormal; begin Norm := Pl.N; end; Function TQuad.ISect; var del, delit : float; P : tVec; p1,p2,p3,p4 : TPlane; begin del := -(VDot(Pl.N,aRay^.Org)+Pl.D); delit := VDot(Pl.N,aRay^.Dir); if (abs(delit) < EPS) or (del*delit<0) then exit; ISect := del/delit; VLinear(P,aRay^.Org,aRay^.Dir,1,del/delit); SetPlane(p1,v1,aRay^.Org,v2); SetPlane(p2,v2,aRay^.Org,v3); SetPlane(p3,v3,aRay^.Org,v4); SetPlane(p4,v4,aRay^.Org,v1); if ((VDot(p1.N,p)>-p1.D) and (VDot(p2.N,p)>-p2.D) and (VDot(p3.N,p)>-p3.D) and (VDot(p4.N,p)>-p4.D)) or ((VDot(p1.N,p)<-p1.D) and (VDot(p2.N,p)<-p2.D) and (VDot(p3.N,p)<-p3.D) and (VDot(p4.N,p)<-p4.D)) then Exit; ISect := INF; end; Constructor TQuad.Load; begin BlockRead(F,v1,vecsize); BlockRead(F,v2,vecsize); BlockRead(F,v3,vecsize); BlockRead(F,v4,vecsize); LoadRGB(F,Color); Init(v1,v2,v3,v4,Color); BlockRead(F,Surface^,vecsize); end; Procedure TQuad.Save; begin BlockWrite(F,ID,1); BlockWrite(F,v1,vecsize); BlockWrite(F,v2,vecsize); BlockWrite(F,v3,vecsize); BlockWrite(F,v4,vecsize); SaveRGB(F,Color); BlockWrite(F,Surface^,vecsize); end; {TSurfPlane} Constructor TSurfPlane.Init; begin Inherited Init; OType := OType + '_PLANE'; ID := F_OBJ_SURF_PLANE; SetPlane(Pl,aV1,AV2,aV3); Color := aCol; end;{TSurfPlane.Init} Procedure TSurfPlane.Transform; var v1:tVec; begin if Pl.N.Y <> 0 then VSet(v1,0,-Pl.D/Pl.N.Y,0) else if Pl.N.Z <> 0 then VSet(v1,0,0,-Pl.D/Pl.N.Z) else VSet(v1,-Pl.D/Pl.N.X,0,0); MTransPoint(v1,v1,tr); MTransDirection(Pl.N,Pl.N,tr); Pl.D := -VDot(PL.N,v1); end; Procedure TSurfPlane.Save; begin BlockWrite(F,ID,1); BlockWrite(F,Pl.N,vecsize); BlockWrite(F,Pl.D,sizeof(float)); SaveRGB(F,Color); BlockWrite(F,Surface^,vecsize); end;{TFilePlane.Save} Constructor TSurfPlane.Load; begin Inherited Init; ID := F_OBJ_SURF_PLANE; OType := OType+ '_PLANE'; BlockRead(F,Pl.N,vecsize); BlockRead(F,Pl.D,sizeof(float)); LoadRGB(F,Color); BlockRead(F,Surface^,vecsize); end;{TSurfPlane.Load} Constructor TSurfPlane.TriLoad; var v1,v2,v3 : tVec; ac : RGB; begin BlockRead(F,v1,vecsize); BlockRead(F,v2,vecsize); BlockRead(F,v3,vecsize); LoadRGB(F,aC); Init(v1,v2,v3,aC); BlockRead(F,Surface^,vecsize); end; Function TSurfPlane.Inside; begin Inside := abs(VDot(Pl.N,aP)+Pl.D) < EPS; end; Procedure TSurfPlane.SetTexture(aPT:PTexture;aR,aLen:real); var v1,v2,v3 : tVec; begin Inherited SetTexture(aPT,aR,aLen); if Pl.N.Y <> 0 then VSet(v1,0,-Pl.D/Pl.N.Y,0) else if Pl.N.Z <> 0 then VSet(v1,0,0,-Pl.D/Pl.N.Z) else VSet(v1,-Pl.D/Pl.N.X,0,0); Compute_Coordinate_Transform(TexTrans,V1,Pl.N,aR,aLen); end; Function TSurfPlane.ISect; var del, delit : float; begin ISect := INF; del := -(VDot(Pl.N,aRay^.Org)+Pl.D); delit := VDot(Pl.N,aRay^.Dir); if (abs(delit) < EPS) or (del*delit<0) then exit; ISect := del/delit; end;{TSurfPlane.ISect} Procedure TSurfPlane.GetNormal; begin Norm := Pl.N; end;{TSurfPlane.GetNormal} {----------------------} {TInterS} Constructor TInterS.Load; var m_ID : OBjID; begin Inherited Init; ID := F_INTER_SPHERE; OType := OType+ '_INTERSPHERE'; BlockRead(F,Inv,sizeof(float)); LoadRGB(F,Color); BlockRead(F,Surface^,vecsize); BlockRead(F,m_ID,1); if m_ID = F_OBJ_SPHERE then begin New(Sp,Load(F)); BlockRead(F,m_ID,1); if m_ID = F_TRI_PLANE then New(Pl,TriLoad(F)) else New(Pl,Load(F)) end else begin if m_ID = F_TRI_PLANE then New(Pl,TriLoad(F)) else New(Pl,Load(F)); BlockRead(F,m_ID,1); New(Sp,Load(F)); end; end;{TInterS.Load} {-=-=-=-=-=-=-=-=-=-=-=-} Procedure TInterS.Save; begin BlockWrite(F,ID,1); BlockWrite(F,Inv,sizeof(float)); SaveRGB(F,Color); BlockWrite(F,Surface^,vecsize); Sp^.Save(F); Pl^.Save(F); end;{TInterS.Save} {-=-=-=-=-=-=-=-=-=-=-=-} Function TInterS.ISect; var T : float; P : tVec; begin ISect:=INF; T := Sp^.ISect(aRay); if abs(T-INF) < EPS then exit; aRay^.GetPoint(P,T); if (VDot(PL^.Pl.N,P)+PL^.Pl.D)*Inv >= 0 then ISect := T else begin T := Pl^.ISect(aRay); aRay^.GetPoint(P,T); if Sp^.Inside(P) then ISect := T; end; end; {-=-=-=-=-=-=-=-=-=-=-=-} Procedure TInterS.GetNormal; begin if Not Pl^.Inside(aPos) then Sp^.GetNormal(Norm,aPos) else if Inv > 0 then VLinear(Norm,Pl^.Pl.N,Pl^.Pl.N,0,-1) else Norm := Pl^.Pl.N; end; {-=-=-=-=-=-=-=-=-=-=-=-} Procedure TInterS.Transform; begin Sp^.Transform(tr); Pl^.Transform(tr); end; {---------------------- LIGHTS -----------------------} {TLight} Constructor TLight.Init; begin Inherited Init; OType := OType + '_LIGHT'; end; {TOmni} Constructor TOmni.Init; begin Inherited Init; OType := Otype + '_OMNI'; ID := F_LIGHT_OMNI; VSet(Pos,ax,ay,az); Color := aCol; end; Constructor TOmni.Load; begin Inherited Init; ID := F_LIGHT_OMNI; OType := Otype + '_OMNI'; BlockRead(F,Pos,sizeof(float)*3); LoadRGB(F,Color); end; Procedure TOmni.Save; begin BlockWrite(F,ID,SizeOf(OBjID)); BlockWrite(F,Pos,sizeof(float)*3); SaveRGB(F,Color); end; {---------------------} {TSpot} Constructor TSpot.Init; begin Inherited Init; OType := Otype + '_SPOT'; ID := F_SPOTLIGHT; FOV := aFov; VSet(Target,ax,ay,az); VSet(Pos,axo,ayo,azo); Color := aCol; end; Constructor TSpot.Load; begin Inherited Init; ID := F_LIGHT_OMNI; OType := Otype + '_SPOT'; BlockRead(F,Pos,sizeof(float)*3); BlockRead(F,Target,sizeof(float)*3); BlockRead(F,FOV,sizeof(float)); LoadRGB(F,Color); end; Procedure TSpot.Save; begin BlockWrite(F,ID,SizeOf(OBjID)); BlockWrite(F,Pos,sizeof(float)*3); BlockWrite(F,Target,sizeof(float)*3); BlockWrite(F,FOV,sizeof(float)); SaveRGB(F,Color); end; END.