📄 fclothify.pas
字号:
VerletWorld := TVerletWorld.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;
TVFGravity.Create(VerletWorld);
Floor := TVCFloor.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 := TVCSphere.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 := TVCCapsule.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 := TVCCapsule.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 TfrmClothify.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 (frmClothify.world,frmClothify.contactgroup,contact[i]);
dJointAttach (c,b1,b2);
// dsDrawBox (contact[i].geom.pos,RI,ss);
end;
end;
end;
procedure TfrmClothify.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[0],
VCSphere.KickbackForce[1],
VCSphere.KickbackForce[2]);
dSpaceCollide (space,nil,nearCallback);
dWorldStep(World, VerletWorld.MaxDeltaTime);
dJointGroupEmpty (contactgroup);
end;
VerletWorld.Progress(VerletWorld.MaxDeltaTime, newTime);
RecalcMeshNormals(GLActor1);
GLActor1.Position.X := GLActor1.Position.X + 0.001;
end;
end;
procedure TfrmClothify.Timer1Timer(Sender: TObject);
begin
Label1.Caption := Format('%2.1f FPS',[GLSceneViewer1.FramesPerSecond]);
GLSceneViewer1.ResetPerformanceMonitor;
end;
procedure TfrmClothify.TrackBar_SlackChange(Sender: TObject);
var
i : integer;
begin
for i := 0 to VerletWorld.Constraints.Count-1 do
begin
if VerletWorld.Constraints[i] is TVCStick then
TVCStick(VerletWorld.Constraints[i]).Slack := GetSlack;
end;
end;
function TfrmClothify.GetSlack: single;
begin
result := TrackBar_Slack.Position/500;
end;
procedure TfrmClothify.TrackBar_IterationsChange(Sender: TObject);
begin
VerletWorld.Iterations := TrackBar_Iterations.Position;
Label6.Caption := Format('Iterations %d',[TrackBar_Iterations.Position]);
end;
procedure TfrmClothify.FormMouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
begin
GLCamera1.AdjustDistanceToTarget(Power(1.1, WheelDelta/120));
end;
procedure TfrmClothify.TrackBar_FrictionChange(Sender: TObject);
var
i : integer;
begin
for i := 0 to VerletWorld.Constraints.Count-1 do
if VerletWorld.Constraints[i] is TVerletGlobalFrictionConstraint then
TVerletGlobalFrictionConstraint(VerletWorld.Constraints[i]).FrictionRatio := TrackBar_Friction.Position / 100;
end;
procedure TfrmClothify.GLDirectOpenGL1Render(var rci: TRenderContextInfo);
procedure RenderAABB(AABB : TAABB; w, r,g,b : single);
begin
glColor3f(r,g,b);
glLineWidth(w);
glBegin(GL_LINE_STRIP);
glVertex3f(AABB.min[0],AABB.min[1], AABB.min[2]);
glVertex3f(AABB.min[0],AABB.max[1], AABB.min[2]);
glVertex3f(AABB.max[0],AABB.max[1], AABB.min[2]);
glVertex3f(AABB.max[0],AABB.min[1], AABB.min[2]);
glVertex3f(AABB.min[0],AABB.min[1], AABB.min[2]);
glVertex3f(AABB.min[0],AABB.min[1], AABB.max[2]);
glVertex3f(AABB.min[0],AABB.max[1], AABB.max[2]);
glVertex3f(AABB.max[0],AABB.max[1], AABB.max[2]);
glVertex3f(AABB.max[0],AABB.min[1], AABB.max[2]);
glVertex3f(AABB.min[0],AABB.min[1], AABB.max[2]);
glEnd;
glBegin(GL_LINES);
glVertex3f(AABB.min[0],AABB.max[1], AABB.min[2]);
glVertex3f(AABB.min[0],AABB.max[1], AABB.max[2]);
glVertex3f(AABB.max[0],AABB.max[1], AABB.min[2]);
glVertex3f(AABB.max[0],AABB.max[1], AABB.max[2]);
glVertex3f(AABB.max[0],AABB.min[1], AABB.min[2]);
glVertex3f(AABB.max[0],AABB.min[1], AABB.max[2]);
glEnd;
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
glPushAttrib(GL_ENABLE_BIT or GL_CURRENT_BIT or GL_LINE_BIT or GL_COLOR_BUFFER_BIT);
glDisable(GL_LIGHTING);
RenderOctreeNode(TOctreeSpacePartition(VerletWorld.SpacePartition).RootNode);
glPopAttrib;
end;
end;
procedure TfrmClothify.Button_OpenLoadFormClick(Sender: TObject);
begin
GroupBox_LoadForm.Visible := true;
GroupBox_LoadForm.SetFocus;
end;
procedure TfrmClothify.Button_CancelLoadClick(Sender: TObject);
begin
GroupBox_LoadForm.Hide;
end;
procedure TfrmClothify.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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -