📄 newtoncustomjoints.pas
字号:
{*******************************************************************************}
{ }
{ Newton Game Dynamics Custom Joints Delphi-Headertranslation }
{ Current SDK version 1.53 }
{ }
{ Copyright (c) 2005,06 Sascha Willems }
{ Jon Walton }
{ }
{*******************************************************************************}
{ }
{ License : }
{ }
{ The contents of this file are used with permission, subject to }
{ the Mozilla Public License Version 1.1 (the "License"); you may }
{ not use this file except in compliance with the License. You may }
{ obtain a copy of the License at }
{ http://www.mozilla.org/MPL/MPL-1.1.html }
{ }
{ Software distributed under the License is distributed on an }
{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or }
{ implied. See the License for the specific language governing }
{ rights and limitations under the License. }
{ }
{*******************************************************************************}
{ Custom Joints in SDK : Implemented : }
{ - BallAndSocket Yes }
{ - LimitedBallAndSocket Yes }
{ - CorkScrew Yes }
{ - DryRollingFriction Yes }
{ - Gear Yes }
{ - Hinge Yes }
{ - Pulley Yes }
{ - Slider Yes }
{ - Universal Yes }
{ - UpVector Yes }
{ - WormGear Yes }
{*******************************************************************************}
unit NewtonCustomJoints;
interface
uses
Math,
SysUtils,
NewtonImport,
NewtonCustomJoints_Math;
{$I delphinewton.inc}
{$IFDEF FPC}
{$MODE DELPHI}
{$APPTYPE GUI}
{$ENDIF}
type
// TNewtonCustomBaseJoint =====================================================
TNewtonCustomBaseJoint = Class(TObject)
private
FMaxDOF : Integer;
FBody0 : PNewtonBody;
FBody1 : PNewtonBody;
FJoint : PNewtonJoint;
FWorld : PNewtonWorld;
public
constructor Create(aMaxDOF : Integer; aBody0, aBody1 : PNewtonBody);
destructor Destroy; override;
procedure CalculateGlobalMatrix(const aLocalMatrix0, aLocalMatrix1 : TMatrix4f; out aMatrix0, aMatrix1 : TMatrix4f);
procedure CalculateLocalMatrix(const aPivot, aDir : TVector3f; out aLocalMatrix0, aLocalMatrix1 : TMatrix4f);
property Joint : PNewtonJoint read FJoint;
protected
procedure SubmitConstraint; virtual; abstract;
end;
// TNewtonCustomJointUpVector =================================================
TNewtonCustomJointUpVector = Class(TNewtonCustomBaseJoint)
private
FLocalMatrix0 : TMatrix4f;
FLocalMatrix1 : TMatrix4f;
public
constructor Create(aPin: TVector3f; aBody : PNewtonBody);
procedure SetPinDir(const aDir : TVector3f);
protected
procedure SubmitConstraint; override;
end;
// TNewtonCustomJointBallAndSocket ============================================
TNewtonCustomJointBallAndSocket = Class(TNewtonCustomBaseJoint)
private
FLocalMatrix0 : TMatrix4f;
FLocalMatrix1 : TMatrix4f;
public
constructor Create(aPivot : TVector3f; aChild, aParent : PNewtonBody);
protected
procedure SubmitConstraint; override;
end;
// TNewtonCustomJointLimitedBallAndSocket =====================================
TNewtonCustomJointLimitedBallAndSocket = Class(TNewtonCustomJointBallAndSocket)
private
FConeAngle : Single;
FTwistAngle : Single;
FCosConeAngle : Single;
public
constructor Create(aPivot, aConeDir : TVector3f; aConeAngle, aTwistAngle : Single; aChild, aParent : PNewtonBody);
protected
procedure SubmitConstraint; override;
end;
// TNewtonCustomJointCorkScrew ================================================
TNewtonCustomJointCorkScrew = Class(TNewtonCustomBaseJoint)
private
FLocalMatrix0 : TMatrix4f;
FLocalMatrix1 : TMatrix4f;
FLimitsOn : Boolean;
FMinDist : Single;
FMaxDist : Single;
FAngularMotorOn : Boolean;
FAngularDamp : Single;
FAngularAccel : Single;
public
constructor Create(aPivot, aPin : TVector3f; aChild, aParent : PNewtonBody);
procedure EnableLimits(aEnabled : Boolean);
procedure SetLimits(aMinDist, aMaxDist : Single);
protected
procedure SubmitConstraint; override;
end;
// TNewtonCustomJointSlider =============================================
TNewtonCustomJointSlider = Class(TNewtonCustomBaseJoint)
private
FLocalMatrix0 : TMatrix4f;
FLocalMatrix1 : TMatrix4f;
FLimitsOn : Boolean;
FMinDist : Single;
FMaxDist : Single;
public
constructor Create(aPivot, aPin : TVector3f; aChild, aParent : PNewtonBody);
procedure EnableLimits(aEnabled : Boolean);
procedure SetLimits(aMinDist, aMaxDist : Single);
protected
procedure SubmitConstraint; override;
end;
// TNewtonCustomJointHinge ===================================================
TNewtonCustomJointHinge = Class(TNewtonCustomBaseJoint)
private
FLocalMatrix0 : TMatrix4f;
FLocalMatrix1 : TMatrix4f;
FLimitsOn : Boolean;
FMinAngle : Single;
FMaxAngle : Single;
public
constructor Create(aPivot, aPin : TVector3f; aChild, aParent : PNewtonBody);
procedure EnableLimits(aEnabled : Boolean);
procedure SetLimits(aMinAngle, aMaxAngle : Single);
protected
procedure SubmitConstraint; override;
end;
// TNewtonCustomJointDryRollingFriction =======================================
// This joint is usefull to simulate the rolling friction of a rolling ball over
// a flat surface.
// Normally this is not important for non spherical objects, but for games like
// pool, pinball, bowling, golf or any other where the movement of balls is the
// main objective, the rolling friction is a real big problem.
TNewtonCustomJointDryRollingFriction = Class(TNewtonCustomBaseJoint)
private
FFrictionCoef : Single;
FFrictionTorque : Single;
public
constructor Create(aRadius, aCoefficient : Single; aChild : PNewtonBody);
protected
procedure SubmitConstraint; override;
end;
// TNewtonCustomJointUniversal ================================================
TNewtonCustomJointUniversal = Class(TNewtonCustomBaseJoint)
private
FLocalMatrix0 : TMatrix4f;
FLocalMatrix1 : TMatrix4f;
FLimit0On : Boolean;
FLimit1On : Boolean;
FMinAngle0 : Single;
FMaxAngle0 : Single;
FMinAngle1 : Single;
FMaxAngle1 : Single;
FAngularMotor0On : Boolean;
FAngularMotor1On : Boolean;
FAngularDamp0 : Single;
FAngularAccel0 : Single;
FAngularDamp1 : Single;
FAngularAccel1 : Single;
public
constructor Create(aPivot, aPin0, aPin1 : TVector3f; aChild, aParent : PNewtonBody);
procedure EnableLimit0(aEnabled : Boolean);
procedure EnableLimit1(aEnabled : Boolean);
procedure SetLimits0(aMinAngle, aMaxAngle : Single);
procedure SetLimits1(aMinAngle, aMaxAngle : Single);
procedure EnableMotor0(aEnabled : Boolean);
procedure EnableMotor1(aEnabled : Boolean);
protected
procedure SubmitConstraint; override;
end;
// TNewtonCustomJointPulley ===================================================
TNewtonCustomJointPulley = Class(TNewtonCustomBaseJoint)
private
FLocalMatrix0 : TMatrix4f;
FLocalMatrix1 : TMatrix4f;
FGearRatio : Single;
public
property GearRatio : Single read FGearRatio write FGearRatio;
constructor Create(aGearRatio : Single; aChildPin, aParentPin : TVector3f; aParentBody, aChildBody : PNewtonBody);
protected
procedure SubmitConstraint; override;
end;
// TNewtonCustomJointGear =====================================================
TNewtonCustomJointGear = Class(TNewtonCustomBaseJoint)
private
FLocalMatrix0 : TMatrix4f;
FLocalMatrix1 : TMatrix4f;
FGearRatio : Single;
public
property GearRatio : Single read FGearRatio write FGearRatio;
constructor Create(aGearRatio : Single; aChildPin, aParentPin : TVector3f; aParentBody, aChildBody : PNewtonBody);
protected
procedure SubmitConstraint; override;
end;
// TNewtonCustomJointWormGear =================================================
TNewtonCustomJointWormGear = Class(TNewtonCustomBaseJoint)
private
FLocalMatrix0 : TMatrix4f;
FLocalMatrix1 : TMatrix4f;
FGearRatio : Single;
public
property GearRatio : Single read FGearRatio write FGearRatio;
constructor Create(aGearRatio : Single; aRotationalPin, aLinearPin : TVector3f; aRotationalBody, aLinearBody : PNewtonBody);
protected
procedure SubmitConstraint; override;
end;
implementation
const
MIN_JOINT_PIN_LENGTH : Single = 50.0;
// =============================================================================
// MatrixGrammSchmidt
// =============================================================================
function MatrixGrammSchmidt(const aDir: TVector3f): TMatrix4f;
var
LUp : TVector4f;
LRight : TVector4f;
LFront : TVector4f;
Begin
LFront := V4(aDir[0], aDir[1], aDir[2], 0);
LFront := VScale(LFront, 1.0 / sqrt(VDot(LFront, LFront)));
if abs(LFront[2]) > 0.577 then
LRight := VCross(LFront, V4(-LFront[1], LFront[2], 0, 0))
else
LRight := VCross(LFront, V4(-LFront[1], LFront[0], 0, 0));
LRight := VScale(LRight, 1.0 / sqrt(VDot(LRight, LRight)));
LUp := VCross(LRight, LFront);
LFront[3] := 0;
LUp[3] := 0;
LRight[3] := 0;
Matrix_SetColumn(Result, 0, LFront);
Matrix_SetColumn(Result, 1, LUp);
Matrix_SetColumn(Result, 2, LRight);
Matrix_SetColumn(Result, 3, V4(0,0,0,1));
end;
// =============================================================================
// JointDestructor
// =============================================================================
procedure JointDestructor(const aJoint: PNewtonJoint); cdecl;
var
LBaseJoint : TNewtonCustomBaseJoint;
Begin
LBaseJoint := TNewtonCustomBaseJoint(NewtonJointGetUserData(aJoint));
NewtonJointSetDestructor(aJoint, nil);
NewtonJointSetUserData(aJoint, nil);
FreeAndNil(LBaseJoint);
end;
// =============================================================================
// SubmitJointConstraint
// =============================================================================
function SubmitJointConstraint(const aJoint: PNewtonJoint): unsigned_int; cdecl;
var
LBaseJoint: TNewtonCustomBaseJoint;
begin
Result := 0;
LBaseJoint := TNewtonCustomBaseJoint(NewtonJointGetUserData(aJoint));
if LBaseJoint <> nil then
LBaseJoint.SubmitConstraint;
end;
// *****************************************************************************
// *****************************************************************************
// Base Joint
// *****************************************************************************
// *****************************************************************************
constructor TNewtonCustomBaseJoint.Create(aMaxDOF: Integer; aBody0, aBody1: PNewtonBody);
begin
FBody0 := aBody0;
FBody1 := aBody1;
FMaxDOF := aMaxDOF;
FWorld := NewtonBodyGetWorld(aBody0);
// @SubmitJointConstraint not working in FP
FJoint := NewtonConstraintCreateUserJoint(FWorld, FMaxDOF, @SubmitJointConstraint, FBody0, FBody1);
//FJoint := NewtonConstraintCreateUserJoint(FWorld, FMaxDOF, @SubmitJointConstraint, FBody0, FBody1);
NewtonJointSetStiffness(FJoint, 1);
NewtonJointSetUserData(FJoint, Self);
NewtonJointSetDestructor(FJoint, @JointDestructor);
end;
destructor TNewtonCustomBaseJoint.Destroy;
begin
if NewtonJointGetUserData(FJoint) <> nil then
begin
NewtonJointSetDestructor(FJoint, nil);
NewtonDestroyJoint(FWorld, FJoint);
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -