123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 |
- //
- // Graphic Scene Engine, http://glscene.org
- //
- unit GXS.File3DSSceneObjects;
- (* 3ds-specific scene objects *)
- interface
- uses
- Winapi.OpenGL,
- System.Classes,
- System.SysUtils,
- System.Math,
- Stage.VectorGeometry,
- Stage.VectorTypes,
- GXS.Context,
- GXS.Scene,
- GXS.VectorFileObjects,
- GXS.PersistentClasses,
- GXS.Coordinates,
- GXS.RenderContextInfo,
- GXS.State;
- type
- TgxFile3DSLight = class(TgxLightSource)
- private
- FTargetPos: TgxCoordinates;
- FHotSpot: Single;
- FMultipler: Single;
- public
- constructor Create(AOwner: TComponent); override;
- procedure DoRender(var rci: TgxRenderContextInfo; renderSelf, renderChildren: Boolean); override;
- procedure CoordinateChanged(Sender: TgxCustomCoordinates); override;
- destructor Destroy; override;
- published
- property SpotTargetPos: TgxCoordinates read FTargetPos;
- property HotSpot: Single read FHotSpot write FHotSpot;
- property Multipler: Single read FMultipler write FMultipler;
- end;
- TgxFile3DSCamera = class(TgxCamera)
- private
- FTargetPos: TgxCoordinates;
- FQuadCyl: array[0..1] of GLUquadricObj;
- FQuadDisk: array[0..1] of GLUquadricObj;
- public
- constructor Create(AOwner: TComponent); override;
- procedure DoRender(var rci: TgxRenderContextInfo; renderSelf, renderChildren: Boolean); override;
- procedure CoordinateChanged(Sender: TgxCustomCoordinates); override;
- destructor Destroy; override;
- published
- property CameraTargetPos: TgxCoordinates read FTargetPos;
- property RollAngle;
- end;
- TgxFile3DSActor = class(TgxActor)
- private
- procedure ReadMesh(Stream: TStream);
- procedure WriteMesh(Stream: TStream);
- protected
- procedure DefineProperties(Filer: TFiler); override;
- end;
- TgxFile3DSFreeForm = class(TgxFreeForm)
- private
- FTransfMat, FScaleMat, ParentMatrix: TMatrix4f;
- FS_Rot3DS: TgxCoordinates4;
- FRot3DS: TgxCoordinates4;
- FScale3DS: TgxCoordinates4;
- procedure ReadMesh(Stream: TStream);
- procedure WriteMesh(Stream: TStream);
- protected
- procedure DefineProperties(Filer: TFiler); override;
- public
- FRefMat: TMatrix4f;
- constructor Create(AOWner: TComponent); override;
- destructor Destroy; override;
- procedure BuildList(var rci: TgxRenderContextInfo); override;
- procedure CoordinateChanged(Sender: TgxCustomCoordinates); override;
- function AxisAlignedDimensionsUnscaled: TVector4f; override;
- function BarycenterAbsolutePosition: TVector4f; override;
- published
- property S_Rot3DS: TgxCoordinates4 read FS_Rot3DS;
- property Rot3DS: TgxCoordinates4 read FRot3DS;
- property Scale3DS: TgxCoordinates4 read FScale3DS;
- end;
- var
- vFile3DSSceneObjects_RenderCameraAndLights: Boolean = False;
- implementation //------------------------------------------------------------
- function MakeRotationQuaternion(const axis: TAffineVector; angle: Single): TQuaternion;
- var
- v: TVector4f;
- halfAngle, invAxisLengthMult: Single;
- begin
- halfAngle := (angle) / 2;
- invAxisLengthMult := 1 / VectorLength(axis) * sin(halfAngle);
- v.X := axis.X * invAxisLengthMult;
- v.Y := axis.Y * invAxisLengthMult;
- v.Z := axis.Z * invAxisLengthMult;
- v.W := cos(halfAngle);
- Result.ImagPart := AffineVectorMake(v);
- Result.RealPart := v.W;
- end;
- function QuaternionToRotateMatrix(const Quaternion: TQuaternion): TMatrix4f;
- var
- wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2: Single;
- quat: TVector4f;
- m: TMatrix4f;
- begin
- quat := VectorMake(Quaternion.ImagPart);
- quat.W := Quaternion.RealPart;
- x2 := quat.X + quat.X;
- y2 := quat.Y + quat.Y;
- z2 := quat.Z + quat.Z;
- xx := quat.X * x2;
- xy := quat.X * y2;
- xz := quat.X * z2;
- yy := quat.Y * y2;
- yz := quat.Y * z2;
- zz := quat.Z * z2;
- wx := quat.W * x2;
- wy := quat.W * y2;
- wz := quat.W * z2;
- m.X.X := 1.0 - (yy + zz);
- m.X.Y := xy - wz;
- m.X.Z := xz + wy;
- m.Y.X := xy + wz;
- m.Y.Y := 1.0 - (xx + zz);
- m.Y.Z := yz - wx;
- m.Z.X := xz - wy;
- m.Z.Y := yz + wx;
- m.Z.Z := 1.0 - (xx + yy);
- m.X.W := 0;
- m.Y.W := 0;
- m.Z.W := 0;
- m.W.X := 0;
- m.W.Y := 0;
- m.W.Z := 0;
- m.W.W := 1;
- Result := m;
- end;
- constructor TgxFile3DSLight.Create(AOwner: TComponent);
- begin
- inherited;
- FTargetPos := TgxCoordinates.CreateInitialized(self, VectorMake(NullVector), csPoint);
- FHotSpot := 1;
- FMultipler := 1;
- end;
- procedure TgxFile3DSLight.DoRender(var rci: TgxRenderContextInfo; renderSelf, renderChildren: Boolean);
- procedure BuildFace;
- begin
- glBegin(GL_TRIANGLES);
- glVertex3f(0.03, 0, 0);
- glVertex3f(0, 0.03, 0);
- glVertex3f(0, 0, 0.07);
- glEnd;
- end;
- var
- dv: Single;
- begin
- inherited;
- if not vFile3DSSceneObjects_RenderCameraAndLights then
- Exit;
- rci.gxStates.PolygonMode := pmLines;
- glPushMatrix;
- dv := VectorDistance(Position.AsVector, rci.cameraPosition);
- glScalef(dv, dv, dv);
- // Up.
- BuildFace;
- glRotatef(90, 0, 0, 1);
- BuildFace;
- glRotatef(180, 0, 0, 1);
- BuildFace;
- glRotatef(270, 0, 0, 1);
- BuildFace;
- // Down.
- glRotatef(180, 0, 1, 0);
- BuildFace;
- glRotatef(90, 0, 0, 1);
- BuildFace;
- glRotatef(180, 0, 0, 1);
- BuildFace;
- glRotatef(270, 0, 0, 1);
- BuildFace;
- glPopMatrix;
- end;
- procedure TgxFile3DSLight.CoordinateChanged(Sender: TgxCustomCoordinates);
- begin
- inherited;
- if (Sender = FTargetPos) or (Sender = Position) then
- SpotDirection.SetVector(VectorNormalize(VectorSubtract(FTargetPos.AsAffineVector, Position.AsAffineVector)));
- end;
- destructor TgxFile3DSLight.Destroy;
- begin
- FTargetPos.Free;
- inherited;
- end;
- constructor TgxFile3DSCamera.Create(AOwner: TComponent);
- var
- I: Integer;
- begin
- inherited;
- FTargetPos := TgxCoordinates.CreateInitialized(self, VectorMake(NullVector), csPoint);
- for I := 0 to 1 do
- begin
- // FQuadCyl[I] := gluNewQuadric;
- // FQuadDisk[I] := gluNewQuadric;
- // gluQuadricNormals(FQuadCyl[I], GLU_SMOOTH);
- // gluQuadricNormals(FQuadDisk[I], GLU_SMOOTH);
- end;
- end;
- procedure TgxFile3DSCamera.DoRender(var rci: TgxRenderContextInfo; renderSelf, renderChildren: Boolean);
- procedure BuildCyl;
- begin
- // gluCylinder(FQuadCyl[0], 1, 1, 0.5, 6, 1);
- // glTranslatef(0, 0, 0.5);
- // gluDisk(FQuadDisk[0], 0, 1, 6, 1);
- glTranslatef(0, 0, -0.5);
- rci.gxStates.InvertFrontFace;
- // gluDisk(FQuadDisk[0], 0, 1, 6, 1);
- rci.gxStates.InvertFrontFace;
- end;
- procedure BuildFace;
- begin
- glRotatef(-90, 0, 1, 0);
- glRotatef(45, 0, 0, 1);
- glTranslatef(0, -0.5, 1);
- // gluCylinder(FQuadCyl[0], 0.5, 1.3, 2.4, 4, 1);
- glTranslatef(0, 0, 2.4);
- // gluDisk(FQuadDisk[0], 0, 1.3, 4, 1);
- end;
- var
- dv, ang: Single;
- v, v1: TAffineVector;
- begin
- inherited;
- if not vFile3DSSceneObjects_RenderCameraAndLights then
- Exit;
- v := VectorNormalize(VectorSubtract(FTargetPos.AsAffineVector, Position.AsAffineVector));
- v1 := AffineVectorMake(v.X, v.Y, 0);
- NormalizeVector(v1);
- ang := ArcCosine(VectorDotProduct(v, v1));
- rci.gxStates.PolygonMode := pmLines;
- glPushMatrix;
- glRotatef(ang * 180 / pi, 0, 0, 1);
- dv := VectorDistance(Position.AsVector, rci.cameraPosition);
- glScalef(dv / 25, dv / 25, dv / 25);
- glRotateF(90, 0, 1, 0);
- glTranslatef(0, 1, 0);
- BuildCyl;
- glTranslatef(1, -1, 0);
- BuildCyl;
- BuildFace;
- glPopMatrix;
- rci.gxStates.PolygonMode := pmFill;
- end;
- procedure TgxFile3DSCamera.CoordinateChanged(Sender: TgxCustomCoordinates);
- begin
- inherited;
- if (Sender = FTargetPos) or (Sender = Position) then
- begin
- // Up.AsAffineVector := ZVector;
- // Direction.SetVector(VectorNormalize(VectorSubtract(FTargetPos.AsAffineVector, Position.AsAffineVector)));
- end;
- end;
- destructor TgxFile3DSCamera.Destroy;
- var
- I: Integer;
- begin
- inherited;
- FTargetPos.Free;
- for I := 0 to 1 do
- begin
- gluDeleteQuadric(@FQuadCyl[I]);
- gluDeleteQuadric(@FQuadDisk[I]);
- end;
- end;
- procedure TgxFile3DSActor.ReadMesh(Stream: TStream);
- var
- virt: TgxBinaryReader;
- begin
- virt := TgxBinaryReader.Create(Stream);
- MeshOBjects.ReadFromFiler(virt);
- virt.Free;
- end;
- procedure TgxFile3DSActor.WriteMesh(Stream: TStream);
- var
- virt: TgxBinaryWriter;
- begin
- virt := TgxBinaryWriter.Create(Stream);
- MeshOBjects.WriteToFiler(virt);
- virt.Free;
- end;
- procedure TgxFile3DSActor.DefineProperties(Filer: TFiler);
- begin
- Filer.DefineBinaryProperty('MeshObjectsData', ReadMesh, WriteMesh, True);
- end;
- constructor TgxFile3DSFreeForm.Create(AOWner: TComponent);
- begin
- inherited;
- FRefMat := IdentityHmgMatrix;
- FTransfMat := IdentityHmgMatrix;
- FScaleMat := IdentityHmgMatrix;
- FS_Rot3DS := TgxCoordinates4.CreateInitialized(self, VectorMake(1, 0, 0), csVector);
- FRot3DS := TgxCoordinates4.CreateInitialized(self, VectorMake(1, 0, 0), csVector);
- FScale3DS := TgxCoordinates4.CreateInitialized(self, VectorMake(1, 1, 1), csVector);
- ObjectStyle := [osDirectDraw];
- end;
- destructor TgxFile3DSFreeForm.Destroy;
- begin
- FS_Rot3DS.Free;
- FRot3DS.Free;
- FScale3DS.Free;
- inherited;
- end;
- procedure TgxFile3DSFreeForm.ReadMesh(Stream: TStream);
- var
- v: TVector4f;
- virt: TgxBinaryReader;
- begin
- virt := TgxBinaryReader.Create(Stream);
- virt.read(FRefMat, sizeof(FRefMat));
- virt.read(v, sizeof(v));
- S_Rot3DS.SetVector(v);
- virt.read(v, sizeof(v));
- Rot3DS.SetVector(v);
- virt.read(v, sizeof(v));
- Scale3DS.SetVector(v);
- MeshOBjects.ReadFromFiler(virt);
- virt.Free;
- end;
- procedure TgxFile3DSFreeForm.WriteMesh(Stream: TStream);
- var
- virt: TgxBinaryWriter;
- v: TVector4f;
- begin
- virt := TgxBinaryWriter.Create(Stream);
- virt.write(FRefMat, sizeof(FRefMat));
- v := S_Rot3DS.AsVector;
- virt.write(v, sizeof(v));
- v := Rot3DS.AsVector;
- virt.write(v, sizeof(v));
- v := Scale3DS.AsVector;
- virt.write(v, sizeof(v));
- MeshOBjects.WriteToFiler(virt);
- virt.Free;
- end;
- procedure TgxFile3DSFreeForm.DefineProperties(Filer: TFiler);
- begin
- Filer.DefineBinaryProperty('MeshObjectsData', ReadMesh, WriteMesh, True);
- end;
- procedure TgxFile3DSFreeForm.BuildList(var rci: TgxRenderContextInfo);
- begin
- glMultMatrixf(@FTransfMat);
- glMultMatrixf(@FScaleMat);
- glPushMatrix;
- glMultMatrixf(@FRefMat);
- inherited;
- glPopMatrix;
- if parent is TgxFile3DSFreeForm then
- ParentMatrix := (parent as TgxFile3DSFreeForm).ParentMatrix
- else
- ParentMatrix := IdentityHmgMatrix;
- ParentMatrix := MatrixMultiply(FScaleMat, ParentMatrix);
- ParentMatrix := MatrixMultiply(FTransfMat, ParentMatrix);
- end;
- procedure TgxFile3DSFreeForm.CoordinateChanged(Sender: TgxCustomCoordinates);
- var
- quat, quat1, quat2: TQuaternion;
- begin
- inherited;
- if Sender.ClassType = FRot3DS.ClassType then
- begin
- quat1 := MakeRotationQuaternion(FS_Rot3DS.AsAffineVector, FS_Rot3DS.W);
- quat2 := MakeRotationQuaternion(FRot3DS.AsAffineVector, FRot3DS.W);
- quat := QuaternionMultiply(quat1, quat2);
- NormalizeQuaternion(quat);
- FTransfMat := QuaternionToRotateMatrix(quat);
- NormalizeMatrix(FTransfMat);
- end;
- if Sender.ClassType = FScale3DS.ClassType then
- begin
- FScaleMat := CreateScaleMatrix(FScale3DS.AsAffineVector);
- end;
- end;
- function TgxFile3DSFreeForm.AxisAlignedDimensionsUnscaled: TVector4f;
- var
- dMin, dMax: TAffineVector;
- mat: TMatrix4f;
- begin
- MeshObjects.GetExtents(dMin, dMax);
- mat := ParentMatrix;
- mat := MatrixMultiply(FRefMat, mat);
- if not IsInfinite(dMin.X) then
- dMin := VectorTransform(dMin, mat);
- if not IsInfinite(dMax.X) then
- dMax := VectorTransform(dMax, mat);
- Result.X := (dMax.X - dMin.X) / 2;
- Result.Y := (dMax.Y - dMin.Y) / 2;
- Result.Z := (dMax.Z - dMin.Z) / 2;
- Result.W := 0;
- end;
- function TgxFile3DSFreeForm.BarycenterAbsolutePosition: TVector4f;
- var
- dMin, dMax: TAffineVector;
- mat: TMatrix4f;
- begin
- MeshObjects.GetExtents(dMin, dMax);
- mat := ParentMatrix;
- mat := MatrixMultiply(FRefMat, mat);
- if not IsInfinite(dMin.X) then
- dMin := VectorTransform(dMin, mat);
- if not IsInfinite(dMax.X) then
- dMax := VectorTransform(dMax, mat);
- Result.X := (dMax.X + dMin.X) / 2;
- Result.Y := (dMax.Y + dMin.Y) / 2;
- Result.Z := (dMax.Z + dMin.Z) / 2;
- Result.W := 1;
- Result := LocalToAbsolute(Result);
- end;
- //-------------------------------------
- initialization
- //-------------------------------------
- RegisterClasses([TgxFile3DSLight, TgxFile3DSCamera, TgxFile3DSActor, TgxFile3DSFreeForm]);
- end.
|