123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649 |
- unit fOdeClothify;
- interface
- uses
- Winapi.OpenGL,
- System.SysUtils,
- System.Classes,
- System.Types,
- System.Math,
- Vcl.Graphics,
- Vcl.Controls,
- Vcl.Forms,
- Vcl.ExtCtrls,
- Vcl.StdCtrls,
- Vcl.ComCtrls,
- GLS.Objects,
- GLS.Scene,
- GLS.PersistentClasses,
- GLS.VectorFileObjects,
- GLS.SceneViewer,
- GLS.FileMS3D,
- GLS.VerletTypes,
- GLS.VerletClothify,
- GLS.VectorTypes,
- GLS.VectorLists,
- GLS.VectorGeometry,
- GLS.Texture,
- GLS.FileSMD,
- GLS.Cadencer,
- GLS.ShadowPlane,
- GLS.File3DS,
- GLS.GeometryBB,
- GLS.SpacePartition,
- GLS.GeomObjects,
- GLS.ShadowVolume,
- GLS.Utils,
- GLS.Material,
- GLS.Coordinates,
- GLS.RenderContextInfo,
- GLS.State,
- GLS.Context,
- GLS.BaseClasses,
- Imports.ODE,
- Physics.ODEUtils;
- type
- TFormClothify = class(TForm)
- GLScene1: TGLScene;
- GLSceneViewer1: TGLSceneViewer;
- GLCamera1: TGLCamera;
- GLActor1: TGLActor;
- GLDummyCube1: TGLDummyCube;
- GLLightSource1: TGLLightSource;
- GLMaterialLibrary1: TGLMaterialLibrary;
- GLCadencer1: TGLCadencer;
- Timer1: TTimer;
- GLSphere1: TGLSphere;
- GLCylinder1: TGLCylinder;
- GLShadowPlane1: TGLShadowPlane;
- GLCube1: TGLCube;
- GLCube_Stair1: TGLCube;
- GLDummyCube_Stairs: TGLDummyCube;
- GLCube_Stair2: TGLCube;
- GLCube_Stair3: TGLCube;
- GLCube_Stair4: TGLCube;
- GLDummyCube2: TGLDummyCube;
- GL_Capsule: TGLCylinder;
- GLSphere2: TGLSphere;
- GLSphere3: TGLSphere;
- GLDummyCube_Light: TGLDummyCube;
- GLActor2: TGLActor;
- GLDirectOpenGL1: TGLDirectOpenGL;
- GroupBox_LoadForm: TGroupBox;
- Label2: TLabel;
- Label4: TLabel;
- Label5: TLabel;
- ComboBox_MeshName: TComboBox;
- ComboBox_ConstraintType: TComboBox;
- ComboBox_Collider: TComboBox;
- Button_LoadMesh: TButton;
- CheckBox_UseOctree: TCheckBox;
- CheckBox_SolidEdges: TCheckBox;
- CheckBox_Weld: TCheckBox;
- Button_CancelLoad: TButton;
- GLShadowVolume1: TGLShadowVolume;
- GLPlane1: TGLPlane;
- Panel1: TPanel;
- Label3: TLabel;
- TrackBar_Slack: TTrackBar;
- Label6: TLabel;
- TrackBar_Iterations: TTrackBar;
- Label7: TLabel;
- TrackBar_Friction: TTrackBar;
- CheckBox_ShowOctree: TCheckBox;
- Button_OpenLoadForm: TButton;
- Label8: TLabel;
- ComboBox_Shadow: TComboBox;
- Label1: TLabel;
- procedure GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
- X, Y: Integer);
- procedure GLCadencer1Progress(Sender: TObject;
- const deltaTime, newTime: Double);
- procedure Timer1Timer(Sender: TObject);
- procedure Button_LoadMeshClick(Sender: TObject);
- procedure FormCreate(Sender: TObject);
- procedure TrackBar_SlackChange(Sender: TObject);
- function GetSlack: single;
- procedure TrackBar_IterationsChange(Sender: TObject);
- procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
- WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
- procedure TrackBar_FrictionChange(Sender: TObject);
- procedure GLDirectOpenGL1Render(Sender: TObject;
- var rci: TGLRenderContextInfo);
- procedure Button_OpenLoadFormClick(Sender: TObject);
- procedure Button_CancelLoadClick(Sender: TObject);
- procedure ComboBox_ShadowChange(Sender: TObject);
- private
- public
- mx, my: Integer;
- VerletWorld: TGLVerletWorld;
- EdgeDetector: TGLEdgeDetector;
- world: PdxWorld;
- space: PdxSpace;
- ODESphere: PdxGeom;
- body: PdxBody;
- contactgroup: TdJointGroupID;
- VCSphere: TGLVerletFricSphere;
- end;
- procedure RecalcMeshNormals(BaseMesh: TGLBaseMesh);
- procedure PrepareMeshForNormalsRecalc(BaseMesh: TGLBaseMesh);
- var
- FormClothify: TFormClothify;
- implementation
- {$R *.dfm}
- procedure TFormClothify.FormCreate(Sender: TObject);
- begin
- SetGLSceneMediaDir();
- ComboBox_MeshName.ItemIndex := 0;
- ComboBox_ConstraintType.ItemIndex := 0;
- ComboBox_Collider.ItemIndex := 3;
- ComboBox_ShadowChange(nil);
- Button_LoadMesh.Click;
- TrackBar_IterationsChange(nil);
- GLShadowVolume1.Occluders.AddCaster(GLActor1);
- end;
- procedure PrepareMeshForNormalsRecalc(BaseMesh: TGLBaseMesh);
- var
- i, j, k: Integer;
- mo: TMeshObject;
- fg: TFGVertexNormalTexIndexList;
- begin
- // update normals
- // (not very efficient, could use some work...)
- for i := 0 to BaseMesh.MeshObjects.Count - 1 do
- begin
- mo := BaseMesh.MeshObjects[i];
- for j := 0 to mo.FaceGroups.Count - 1 do
- begin
- if mo.FaceGroups[j] is TFGVertexNormalTexIndexList then
- begin
- fg := TFGVertexNormalTexIndexList(mo.FaceGroups[j]);
- for k := 0 to fg.VertexIndices.Count - 1 do
- begin
- fg.NormalIndices.List[k] := fg.VertexIndices.List[k];
- end;
- end;
- end;
- end;
- BaseMesh.StructureChanged;
- end;
- procedure RecalcMeshNormals(BaseMesh: TGLBaseMesh);
- var
- i, j, k: Integer;
- mo: TMeshObject;
- fg: TFGVertexIndexList;
- n: TAffineVector;
- begin
- // update normals
- // (not very efficient, could use some work...)
- for i := 0 to BaseMesh.MeshObjects.Count - 1 do
- begin
- mo := BaseMesh.MeshObjects[i];
- FillChar(mo.Normals.List[0], SizeOf(TAffineVector) * mo.Normals.Count, 0);
- for j := 0 to mo.FaceGroups.Count - 1 do
- begin
- if mo.FaceGroups[j] is TFGVertexIndexList then
- begin
- fg := TFGVertexIndexList(mo.FaceGroups[j]);
- k := 0;
- while k <= fg.VertexIndices.Count - 3 do
- begin
- n := CalcPlaneNormal(mo.Vertices.List[fg.VertexIndices.List[k]],
- mo.Vertices.List[fg.VertexIndices.List[k + 1]],
- mo.Vertices.List[fg.VertexIndices.List[k + 2]]);
- mo.Normals.TranslateItem(fg.VertexIndices.List[k], n);
- mo.Normals.TranslateItem(fg.VertexIndices.List[k + 1], n);
- mo.Normals.TranslateItem(fg.VertexIndices.List[k + 2], n); // }
- Inc(k, 3);
- end;
- end;
- end;
- mo.Normals.Normalize;
- end;
- BaseMesh.StructureChanged;
- end;
- procedure TFormClothify.Button_LoadMeshClick(Sender: TObject);
- var
- Floor: TGLVerletFloor;
- Capsule: TGLVerletFricCapsule;
- Cube: TGLVerletFricCube;
- Sides: TAffineVector;
- ColliderGravy: Single;
- s: string;
- f: single;
- p: Integer;
- procedure CreateCubeFromGLCube(GLCube: TGLCube);
- begin
- Cube := TGLVerletFricCube.Create(VerletWorld);
- Cube.Location := AffineVectorMake(GLCube.AbsolutePosition);
- Cube.FrictionRatio := 0.1;
- Sides.X := GLCube.CubeWidth * 1.1;
- Sides.Y := GLCube.CubeHeight * 1.1;
- Sides.Z := GLCube.CubeDepth * 1.1;
- Cube.Sides := Sides; // }
- end;
- procedure CreateODEWorld;
- var
- m: TdMass;
- begin
- GLSphere1.Visible := true;
- world := dWorldCreate;
- dWorldSetGravity(world, 0, -9.81, 0);
- contactgroup := dJointGroupCreate(0);
- space := dHashSpaceCreate(nil);
- body := dBodyCreate(world);
- dMassSetSphere(m, 0.1, GLSphere1.Radius);
- dCreatePlane(space, 0, 1, 0, GLShadowPlane1.Position.Y);
- ODESphere := dCreateSphere(space, GLSphere1.Radius);
- dGeomSetBody(ODESphere, body);
- dBodySetMass(body, @m);
- /// How to set centre of mass to origin ???
- ODESphere.data := GLSphere1;
- PositionSceneObjectForGeom(ODESphere);
- end;
- begin
- randomize;
- if world <> nil then
- begin
- dWorldDestroy(world);
- world := nil;
- GLSphere1.Position.AsAffineVector := NullVector;
- end;
- FreeAndNil(VerletWorld);
- FreeAndNil(EdgeDetector);
- s := ComboBox_MeshName.Items[MaxInteger(ComboBox_MeshName.ItemIndex, 0)];
- System.SysUtils.FormatSettings.DecimalSeparator := '.';
- p := Pos(',', s);
- if p > 0 then
- begin
- f := StrToFloatDef(Trim(Copy(s, p + 1, MaxInt)), 1);
- GLActor1.Scale.AsVector := VectorMake(f, f, f, 0)
- end
- else
- GLActor1.Scale.AsVector := XYZHmgVector;
- GLActor1.AutoCentering := [macUseBarycenter];
- GLActor1.LoadFromFile(Trim(Copy(s, 1, p - 1)));
- PrepareMeshForNormalsRecalc(GLActor1);
- GLActor1.Reference := aarNone;
- // This is what allows for FAST shadow volumes when using actors. Without
- // this line, it'll be _very_ slow.
- GLActor1.BuildSilhouetteConnectivityData;
- GLActor1.Roll(random * 360);
- GLActor1.Turn(random * 360); // }
- GLSphere1.Visible := false;
- GLCylinder1.Visible := false;
- GLCube1.Visible := false;
- GLDummyCube_Stairs.Visible := false;
- GL_Capsule.Visible := false;
- case ComboBox_Collider.ItemIndex of
- 0, -1:
- GLSphere1.Visible := true;
- 1:
- GLCylinder1.Visible := true;
- 2:
- GLCube1.Visible := true;
- 3:
- GLDummyCube_Stairs.Visible := true;
- 4:
- GL_Capsule.Visible := true;
- 5:
- CreateODEWorld;
- end;
- EdgeDetector := TGLEdgeDetector.Create(GLActor1);
- if not CheckBox_Weld.Checked then
- EdgeDetector.WeldDistance := -1;
- EdgeDetector.ProcessMesh;
- VerletWorld := TGLVerletWorld.Create;
- if CheckBox_UseOctree.Checked then
- VerletWorld.CreateOctree(AffineVectorMake(-20, -5.5, -20),
- AffineVectorMake(20, 20, 20), 25, 5); // }
- if CheckBox_SolidEdges.Checked then
- begin
- ColliderGravy := 1;
- EdgeDetector.AddEdgesAsSolidEdges(VerletWorld);
- end
- else
- ColliderGravy := 1.1;
- if ComboBox_ConstraintType.ItemIndex = 0 then
- EdgeDetector.AddEdgesAsSticks(VerletWorld, GetSlack)
- else
- EdgeDetector.AddEdgesAsSprings(VerletWorld, 1000, 100, GetSlack); // }
- // VerletWorld.Nodes[0].NailedDown := true;
- TGLVerletGravity.Create(VerletWorld);
- Floor := TGLVerletFloor.Create(VerletWorld);
- Floor.Location := VectorAdd(GLShadowPlane1.Position.AsAffineVector,
- AffineVectorMake(0, 0.1, 0));
- Floor.Normal := GLShadowPlane1.Direction.AsAffineVector;
- Floor.FrictionRatio := 0.6; // }
- if GLSphere1.Visible then
- begin
- VCSphere := TGLVerletFricSphere.Create(VerletWorld);
- VCSphere.Radius := GLSphere1.Radius * ColliderGravy;
- VCSphere.Location := AffineVectorMake(GLSphere1.AbsolutePosition);
- end;
- if GLCube1.Visible then
- begin
- CreateCubeFromGLCube(GLCube1);
- end;
- if GLCylinder1.Visible then
- begin
- Capsule := TGLVerletFricCapsule.Create(VerletWorld);
- Capsule.Radius := GLCylinder1.TopRadius * ColliderGravy;
- Capsule.Location := AffineVectorMake(GLCylinder1.AbsolutePosition);
- Capsule.Axis := AffineVectorMake(GLCylinder1.AbsoluteUp); // }
- Capsule.Length := 20;
- Capsule.FrictionRatio := 0.6;
- end;
- if GL_Capsule.Visible then
- begin
- Capsule := TGLVerletFricCapsule.Create(VerletWorld);
- Capsule.Radius := GL_Capsule.TopRadius * ColliderGravy;
- Capsule.Location := AffineVectorMake(GL_Capsule.AbsolutePosition);
- Capsule.Axis := AffineVectorMake(GL_Capsule.AbsoluteUp); // }
- Capsule.Length := GL_Capsule.Height * ColliderGravy;
- Capsule.FrictionRatio := 0.6;
- end;
- if GLDummyCube_Stairs.Visible then
- begin
- CreateCubeFromGLCube(GLCube_Stair1);
- CreateCubeFromGLCube(GLCube_Stair2);
- CreateCubeFromGLCube(GLCube_Stair3);
- CreateCubeFromGLCube(GLCube_Stair4);
- end;
- VerletWorld.SimTime := GLCadencer1.GetCurrentTime;
- VerletWorld.MaxDeltaTime := 0.01;
- VerletWorld.Iterations := TrackBar_Iterations.Position;
- TrackBar_FrictionChange(nil);
- GroupBox_LoadForm.Hide;
- CheckBox_ShowOctree.Enabled := CheckBox_UseOctree.Checked;
- TrackBar_Iterations.Enabled := (ComboBox_ConstraintType.ItemIndex = 0);
- TrackBar_Slack.Enabled := (ComboBox_ConstraintType.ItemIndex = 0);
- end;
- procedure TFormClothify.GLSceneViewer1MouseMove(Sender: TObject;
- Shift: TShiftState; X, Y: Integer);
- begin
- if ssLeft in Shift then
- GLCamera1.MoveAroundTarget(my - Y, mx - X);
- mx := X;
- my := Y
- end;
- procedure nearCallback(data: pointer; o1, o2: PdxGeom); cdecl;
- const
- cCOL_MAX = 3;
- var
- i: Integer;
- b1, b2: PdxBody;
- numc: Integer;
- contact: array [0 .. cCOL_MAX - 1] of TdContact;
- c: TdJointID;
- begin
- // exit without doing anything if the two bodies are connected by a joint
- b1 := dGeomGetBody(o1);
- b2 := dGeomGetBody(o2);
- if (assigned(b1) and assigned(b2) and (dAreConnected(b1, b2) <> 0)) then
- exit; // }
- for i := 0 to cCOL_MAX - 1 do
- begin
- contact[i].surface.mode := dContactBounce;
- // This determines friction, play around with it!
- contact[i].surface.mu := 10E9; // dInfinity; SHOULD BE INFINITY!
- contact[i].surface.mu2 := 0;
- contact[i].surface.bounce := 0.5; // 0.5;
- contact[i].surface.bounce_vel := 0.1;
- end;
- numc := dCollide(o1, o2, cCOL_MAX, contact[0].geom, SizeOf(TdContact));
- if (numc > 0) then
- begin
- // dMatrix3 RI;
- // dRSetIdentity (RI);
- // const dReal ss[3] = {0.02,0.02,0.02};
- for i := 0 to numc - 1 do
- begin
- c := dJointCreateContact(FormClothify.world, FormClothify.contactgroup,
- @contact[i]);
- dJointAttach(c, b1, b2);
- // dsDrawBox (contact[i].geom.pos,RI,ss);
- end;
- end;
- end;
- procedure TFormClothify.GLCadencer1Progress(Sender: TObject;
- const deltaTime, newTime: Double);
- begin
- { if CheckBox_Pause.Checked then
- VerletWorld.SimTime := newTime
- else// }
- begin
- if world <> nil then
- begin
- PositionSceneObjectForGeom(ODESphere);
- VCSphere.Location := GLSphere1.Position.AsAffineVector;
- dBodyAddForce(dGeomGetBody(ODESphere), VCSphere.KickbackForce.X,
- VCSphere.KickbackForce.Y, VCSphere.KickbackForce.Z);
- dSpaceCollide(space, nil, nearCallback);
- dWorldStep(world, VerletWorld.MaxDeltaTime);
- dJointGroupEmpty(contactgroup);
- end;
- VerletWorld.Progress(VerletWorld.MaxDeltaTime, newTime);
- RecalcMeshNormals(GLActor1);
- end;
- end;
- procedure TFormClothify.Timer1Timer(Sender: TObject);
- begin
- Label1.Caption := Format('%2.1f FPS', [GLSceneViewer1.FramesPerSecond]);
- GLSceneViewer1.ResetPerformanceMonitor;
- end;
- procedure TFormClothify.TrackBar_SlackChange(Sender: TObject);
- var
- i: Integer;
- begin
- for i := 0 to VerletWorld.Constraints.Count - 1 do
- begin
- if VerletWorld.Constraints[i] is TGLVerletStick then
- TGLVerletStick(VerletWorld.Constraints[i]).Slack := GetSlack;
- end;
- end;
- function TFormClothify.GetSlack: single;
- begin
- result := TrackBar_Slack.Position / 500;
- end;
- procedure TFormClothify.TrackBar_IterationsChange(Sender: TObject);
- begin
- VerletWorld.Iterations := TrackBar_Iterations.Position;
- Label6.Caption := Format('Iterations %d', [TrackBar_Iterations.Position]);
- end;
- procedure TFormClothify.FormMouseWheel(Sender: TObject; Shift: TShiftState;
- WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
- begin
- GLCamera1.AdjustDistanceToTarget(Power(1.1, WheelDelta / 120));
- end;
- procedure TFormClothify.TrackBar_FrictionChange(Sender: TObject);
- var
- i: Integer;
- begin
- for i := 0 to VerletWorld.Constraints.Count - 1 do
- if VerletWorld.Constraints[i] is TGLVerletGlobalFrictionConstraint then
- TGLVerletGlobalFrictionConstraint(VerletWorld.Constraints[i])
- .FrictionRatio := TrackBar_Friction.Position / 100;
- end;
- procedure TFormClothify.GLDirectOpenGL1Render(Sender: TObject;
- var rci: TGLRenderContextInfo);
- procedure RenderAABB(AABB: TAABB; w, r, g, b: single);
- begin
- GL.Color3f(r, g, b);
- rci.GLStates.LineWidth := w;
- GL.Begin_(GL_LINE_STRIP);
- GL.Vertex3f(AABB.min.X, AABB.min.Y, AABB.min.Z);
- GL.Vertex3f(AABB.min.X, AABB.max.Y, AABB.min.Z);
- GL.Vertex3f(AABB.max.X, AABB.max.Y, AABB.min.Z);
- GL.Vertex3f(AABB.max.X, AABB.min.Y, AABB.min.Z);
- GL.Vertex3f(AABB.min.X, AABB.min.Y, AABB.min.Z);
- GL.Vertex3f(AABB.min.X, AABB.min.Y, AABB.max.Z);
- GL.Vertex3f(AABB.min.X, AABB.max.Y, AABB.max.Z);
- GL.Vertex3f(AABB.max.X, AABB.max.Y, AABB.max.Z);
- GL.Vertex3f(AABB.max.X, AABB.min.Y, AABB.max.Z);
- GL.Vertex3f(AABB.min.X, AABB.min.Y, AABB.max.Z);
- GL.End_;
- GL.Begin_(GL_LINES);
- GL.Vertex3f(AABB.min.X, AABB.max.Y, AABB.min.Z);
- GL.Vertex3f(AABB.min.X, AABB.max.Y, AABB.max.Z);
- GL.Vertex3f(AABB.max.X, AABB.max.Y, AABB.min.Z);
- GL.Vertex3f(AABB.max.X, AABB.max.Y, AABB.max.Z);
- GL.Vertex3f(AABB.max.X, AABB.min.Y, AABB.min.Z);
- GL.Vertex3f(AABB.max.X, AABB.min.Y, AABB.max.Z);
- GL.End_;
- end;
- procedure RenderOctreeNode(Node: TSectorNode);
- var
- i: Integer;
- AABB: TAABB;
- begin
- if Node.NoChildren then
- begin
- AABB := Node.AABB;
- if Node.RecursiveLeafCount > 0 then
- RenderAABB(AABB, 1, 0, 0, 0)
- else
- RenderAABB(AABB, 1, 0.8, 0.8, 0.8) // }
- end
- else
- begin
- for i := 0 to Node.ChildCount - 1 do
- RenderOctreeNode(Node.Children[i]);
- end;
- end;
- begin
- if CheckBox_ShowOctree.Checked and
- (VerletWorld.SpacePartition is TOctreeSpacePartition) then
- begin
- rci.GLStates.PushAttrib([sttEnable, sttCurrent, sttLine, sttColorBuffer]);
- rci.GLStates.Disable(stLighting);
- RenderOctreeNode(TOctreeSpacePartition(VerletWorld.SpacePartition)
- .RootNode);
- rci.GLStates.PopAttrib;
- end;
- end;
- procedure TFormClothify.Button_OpenLoadFormClick(Sender: TObject);
- begin
- GroupBox_LoadForm.Visible := true;
- GroupBox_LoadForm.SetFocus;
- end;
- procedure TFormClothify.Button_CancelLoadClick(Sender: TObject);
- begin
- GroupBox_LoadForm.Hide;
- end;
- procedure TFormClothify.ComboBox_ShadowChange(Sender: TObject);
- begin
- GLShadowVolume1.mode := svmOff;
- GLShadowPlane1.Visible := false;
- GLPlane1.Visible := true;
- GLSceneViewer1.Buffer.ContextOptions := GLSceneViewer1.Buffer.ContextOptions -
- [roStencilBuffer];
- case ComboBox_Shadow.ItemIndex of
- 0:
- ;
- 1:
- begin
- GLShadowVolume1.mode := svmDarkening;
- GLSceneViewer1.Buffer.ContextOptions :=
- GLSceneViewer1.Buffer.ContextOptions + [roStencilBuffer];
- end;
- 2:
- begin
- GLShadowPlane1.Visible := true;
- GLPlane1.Visible := false;
- GLSceneViewer1.Buffer.ContextOptions :=
- GLSceneViewer1.Buffer.ContextOptions + [roStencilBuffer];
- end;
- end;
- end;
- end.
|