PDA

View Full Version : Newton Terrain Physics



M109uk
09-06-2007, 10:48 AM
Hi,

I have a terrain, and i want to use newton for collision detection.. i have the terrain working and the physics of course in not working to good,

my code is:


procedure TMTFloor.CreateCollisionTree;
var
Face: Array [0..3] Of Geometry.TVector3f;
M: Geometry.TMatrix4f;
Min,Max: Geometry.TVector3f;
X,Z: Integer;
begin
nCollTree := NewtonCreateTreeCollision(nWorld, Nil);
NewtonTreeCollisionBeginBuild(nCollTree);

For X := 0 To MAP_SIZE Do
Begin
For Z := 0 To MAP_SIZE Do
Begin
xz := floorIndex(X, Z);
x1z := floorIndex(X+1, Z);
xz1 := floorIndex(X, Z+1);
x1z1 := floorIndex(X+1, Z+1);

Face[0] := Vector3fMake(X*lBlock, height[xz], Z*lBlock);
Face[1] := Vector3fMake((X+1)*lBlock, height[x1z], Z*lBlock);
Face[2] := Vector3fMake((X+1)*lBlock, height[x1z1], (Z+1)*lBlock);
Face[3] := Vector3fMake(X*lBlock, height[xz1], (Z+1)*lBlock);

NewtonTreeCollisionAddFace(nCollTree, 4, @Face[0], SizeOf(TVector3f), 1);
End;
End;

NewtonTreeCollisionEndBuild(nCollTree, 0);
nBody := NewtonCreateBody(nWorld, nCollTree);

M := IdentityHmgMatrix;
NewtonBodySetMatrix(nBody, @M[0, 0]);
NewtonCollisionCalculateAABB(nCollTree, @M[0, 0], @Min[0], @Max[0]);
NewtonSetWorldSize(nWorld, @Min[0], @Max[0]);
NewtonReleaseCollision(nWorld, nCollTree);
end;


lBlock is a const value set at 8.001, this is because the terrain is scaled by 8.001, 1, 8.001..

If i dont use scale and i take out lBlock then the physics works fine, so im positive its something to with the scale, so i removed glScale from the terrain, and i am now using the same coordinates given to Newton, the terrain renders correctly yet still the collision detection does'nt.. am i missing something??

Thanks for any help :)

JernejL
09-06-2007, 03:05 PM
what exactly happens wrong? make a debug renderer of the scene.

M109uk
09-06-2007, 03:51 PM
there is a form of collision detection, it just does'nt match the terrain.. how would i go about doing a debug render, i am rendering the terrain with exaclty the same vertex data that i am putting into newton.

JernejL
09-06-2007, 07:14 PM
there is a form of collision detection, it just does'nt match the terrain.. how would i go about doing a debug render, i am rendering the terrain with exaclty the same vertex data that i am putting into newton.

see how newton examples implement debug rendering, and the geometry comes from newton's internals - not your app.

M109uk
10-06-2007, 10:33 AM
I have put in debug rendering, and it is correct, exactly the same as the terrain im rendering...

Heres the app to show whats wrong, the debug lines on on automaticlly.
www.pulse-soft.oneuk.com/downloads/mt.zip

The modified code:


procedure TMTFloor.CreateCollisionTree;
var
Face: Array [0..3] Of Geometry.TVector3f;
M: Geometry.TMatrix4f;
Min,Max: Geometry.TVector3f;
X,Z,x1,z1,x1t,z1t,xz,x1z,xz1,x1z1: Integer;
xt,zt: Double;
begin
nCollTree := NewtonCreateTreeCollision(nWorld, Nil);
NewtonTreeCollisionBeginBuild(nCollTree);

For X := 0 To MAP_SIZE Do
Begin
For Z := 0 To MAP_SIZE Do
Begin
xz := floorIndex(X, Z);
x1z := floorIndex(X+1, Z);
xz1 := floorIndex(X, Z+1);
x1z1 := floorIndex(X+1, Z+1);

Face[0] := Vector3fMake(X*lBlock, hf[xz], Z*lBlock);
Face[1] := Vector3fMake((X+1)*lBlock, hf[x1z], Z*lBlock);
Face[2] := Vector3fMake((X+1)*lBlock, hf[x1z1], (Z+1)*lBlock);
Face[3] := Vector3fMake(X*lBlock, hf[xz1], (Z+1)*lBlock);

NewtonTreeCollisionAddFace(nCollTree, 4, @Face[0], SizeOf(TVector3f), 1);
End;
End;

NewtonTreeCollisionEndBuild(nCollTree, 0);
nBody := NewtonCreateBody(nWorld, nCollTree);

tmpM := IdentityHmgMatrix;
NewtonBodySetMatrix(nBody, @M[0,0]);
NewtonCollisionCalculateAABB(nCollTree, @M[0,0], @Min[0], @Max[0]);
NewtonSetWorldSize(nWorld, @Min[0], @Max[0]);
NewtonReleaseCollision(nWorld, nCollTree);
end;


Many thanks..

JernejL
10-06-2007, 02:27 PM
I have put in debug rendering, and it is correct, exactly the same as the terrain im rendering...

did you use the actual NewtonBodyForEachPolygonDo ?

your app is totally non-interactive, i cant even see myself how the physics are supposedly "wrong".

and how about some instructions to go with the test app?

M109uk
10-06-2007, 04:47 PM
For debug im using:


procedure Debug_ShowGeometryCollision(const Body: PNewtonBody; VertexCount: Integer; const FaceArray: PFloat; FaceId: Int); cdecl;
var
i: Integer;
v0,v1: TVector3f;
vA: Array Of Single;
begin
If VertexCount = 0 Then Exit;
SetLength(vA, VertexCount*3);
Move(FaceArray^, vA[0], VertexCount*3*SizeOf(Single));
v0[0] := vA[(VertexCount-1)*3];
v0[1] := vA[(VertexCount-1)*3+1];
v0[2] := vA[(VertexCount-1)*3+2];
For i := 0 To VertexCount-1 Do
Begin
v1[0] := vA[i*3];
v1[1] := vA[i*3+1];
v1[2] := vA[i*3+2];
glVertex3f(v0[0], v0[1], v0[2]);
glVertex3f(v1[0], v1[1], v1[2]);
v0 := v1;
End;
end;

procedure Debug_ShowBodyCollision(const Body: PNewtonBody); cdecl;
begin
NewtonBodyForEachPolygonDo(Body, Debug_ShowGeometryCollision);
end;


Sorry my bad, completly forgot :s

forward=W
backward=S
turn left=A
turn right=D
run=SHIFT
Quit=ESC
Regenerate terrain=F1

JernejL
10-06-2007, 05:19 PM
what about, dropping some cubes onto terrain? :/

M109uk
10-06-2007, 06:09 PM
what about, dropping some cubes onto terrain? :/

I dont have any other objects except for the camera and the terrain atm... i will implement some cubes in tonight :)

JernejL
10-06-2007, 09:04 PM
Then how do you know that something is wrong in newton if you only got the terrain in without even testing?

what is the actual problem?

M109uk
10-06-2007, 09:10 PM
I know its not working correctly because the camera is the character, i have newton physics assigned to the camera too.

i want the camera to follow on top of the terrain, but it doesnt work, you will notice if you walk around in the demo.

M109uk
11-06-2007, 12:01 AM
I think i might of found the reason, i forgot to delete some extra translate routines out of my camera class, i will check it tomorow.

Thanks again :)

M109uk
14-06-2007, 05:00 PM
Ok, i still have the same problem, if not worse :s

I have now got a Player Class (based upon the SDLCharacterController Demo from Sascha), however it doesnt seem to work as plan, it does'nt call the forceback procedures or the jumps feedback function..

I have the ellipse hovering above the terrain without any movement of any kind:
http://www.pulse-soft.oneuk.com/images/stories/terrain_newton.jpg

(Note: The screenshot is rendered using the geometry from Newton.)

the code is as follows:


const
PlayerSpeed = 10;
PlayerMass = 25;
PlayerJumpForce = 5000;

procedure playerApplyForceCallback(const Body: PNewtonBody); cdecl;
var
Mass,Ixx,Iyy,Izz,Length: Single;
Force,Velocity,GoalVelocity,Accel: TVector3f;
UserData: Pointer;
begin
Accel := Vector3fMake(0,0,0);
Time := SDL_GetTicks-Time;
UserData := NewtonBodyGetUserData(Body);
If UserData = Nil Then Exit;

With TMTPlayer(UserData) Do
Begin
NewtonBodyGetMassMatrix(Body, @Mass, @Ixx, @Iyy, @Izz);
Force := Vector3fMake(0, -9.8 * Mass, 0);
NewtonBodyAddForce(Body, @Force[0]);

NewtonBodyGetMatrix(Body, @Matrix[0,0]);

Length := Sqrt(Sqr(Movement[0])+Sqr(Movement[2]));
If Length = 0 Then Length := 1;
Movement := Vector3fMake(Movement[0]/Length, Movement[1], Movement[2]/Length);

NewtonBodyGetVelocity(Body, @Velocity[0]);

GoalVelocity := Vector3fMake(Movement[0]*PlayerSpeed, 0, Movement[2]*PlayerSpeed);

If Run Then
GoalVelocity := Vector3fMake(GoalVelocity[0]*3, GoalVelocity[1]*3, GoalVelocity[2]*3);

If Time = 0 Then Time := 1;
Accel[0] := 0.3*((GoalVelocity[0]-Velocity[0])/(Time/10))*100;
Accel[2] := 0.3*((GoalVelocity[2]-Velocity[2])/(Time/10))*100;

If Accel[0] > 200 Then Accel[0] := 200;
If Accel&#91;0&#93; <200> 200 Then Accel&#91;2&#93; &#58;= 200;
If Accel&#91;2&#93; < -200 Then Accel&#91;2&#93; &#58;= -200;

NewtonBodyAddForce&#40;Body, @Accel&#91;0&#93;&#41;;

NewtonBodyAddForce&#40;Body, @ExternalForce&#91;0&#93;&#41;;
If &#40;ExternalForce&#91;0&#93; <> 0&#41; or &#40;ExternalForce&#91;1&#93; <> 0&#41; or &#40;ExternalForce&#91;2&#93; <> 0&#41; then
ExternalForce &#58;= Vector3fMake&#40;0, 0, 0&#41;;
End;
Time &#58;= SDL_GetTicks;
end;

function playerRayCastFilter&#40;const Body&#58; PNewtonBody; const hitNormal&#58; PFloat; collisionID&#58; NewtonImport.Int; userData&#58; Pointer; intersectParam&#58; Float &#41;&#58; Float; cdecl;
begin
Result &#58;= IntersectParam;
If Body = Player.nBody Then Exit;
Distance &#58;= IntersectParam;
end;

constructor TMTPlayer.Create&#40;const Pos,Rot&#58; Geometry.TVector3f&#41;;
const
UpDir&#58; Geometry.TVector3f = &#40;0, 1, 0&#41;;
var
Collider&#58; PNewtonCollision;
StartMatrix&#58; Geometry.TMatrix4f;
begin
Size &#58;= Vector3fMake&#40;1.5, 3.5, 1.5&#41;;
Collider &#58;= NewtonCreateSphere&#40;nWorld, Size&#91;0&#93;, Size&#91;1&#93;, Size&#91;2&#93;, Nil&#41;;
nBody &#58;= NewtonCreateBody&#40;nWorld, Collider&#41;;

StartMatrix &#58;= IdentityHmgMatrix;
StartMatrix&#91;3&#93;&#91;0&#93; &#58;= Pos&#91;0&#93;;
StartMatrix&#91;3&#93;&#91;1&#93; &#58;= Pos&#91;1&#93;;
StartMatrix&#91;3&#93;&#91;2&#93; &#58;= Pos&#91;2&#93;;
NewtonBodySetMatrix&#40;nBody, @StartMatrix&#91;0, 0&#93;&#41;;
NewtonBodySetMassMatrix&#40;nBody, 12, 1/5*PlayerMass*&#40;Sqr&#40;Size&#91;1&#93;&#41;+Sqr&#40;Size&#91;0&#93;&#41;&#41;, 1/5*PlayerMass*&#40;Sqr&#40;Size&#91;2&#93;&#41;+Sqr&#40;Size&#91;0&#93;&#41;&#41;, 1/5*PlayerMass*&#40;Sqr&#40;Size&#91;2&#93;&#41;+Sqr&#40;Size&#91;1&#93;&#41;&#41;&#41;;
NewtonConstraintCreateUpVector&#40;nWorld, @UpDir&#91;0&#93;, nBody&#41;;
NewtonBodySetForceAndTorqueCallBack&#40;nBody, playerApplyForceCallback&#41;;

NewtonReleaseCollision&#40;nWorld, Collider&#41;;

NewtonBodySetAutoFreeze&#40;nBody, 0&#41;;
NewtonWorldUnfreezeBody&#40;nWorld, nBody&#41;;

NewtonBodySetUserData&#40;nBody, Self&#41;;
NewtonBodySetMaterialGroupID&#40;nBody, Material.PlayerID&#41;;
end;

destructor TMTPlayer.Destroy;
begin
NewtonDestroyBody&#40;nWorld, nBody&#41;;
inherited Destroy;
end;

procedure TMTPlayer.Jump;
var
P1,P2&#58; TVector3f;
begin
P1 &#58;= Vector3fMake&#40;Matrix&#91;3, 0&#93;, Matrix&#91;3, 1&#93;, Matrix&#91;3, 2&#93;&#41;;
P2 &#58;= Vector3fMake&#40;Matrix&#91;3, 0&#93;, Matrix&#91;3, 1&#93;-Size&#91;1&#93;*1.1, Matrix&#91;3, 2&#93;&#41;;
Distance &#58;= 1.1;
NewtonWorldRayCast&#40;nWorld, @P1&#91;0&#93;, @P2&#91;0&#93;, @playerRayCastFilter, @Self, Nil&#41;;
If Distance <1> 3600 Then Rotation&#91;1&#93; &#58;= Rotation&#91;1&#93;-360;
If Rotation&#91;1&#93; <0> 80 Then Rotation&#91;0&#93; &#58;= 80;
If Rotation&#91;0&#93; < -80 Then Rotation&#91;0&#93; &#58;= -80;
End;
End;

Run &#58;= &#40;&#40;xkLShift In Keys&#41; Or &#40;xkRShift In Keys&#41;&#41;;
end;


I have gone through the code and cant work out what im missing..

Thanks

tux
14-06-2007, 09:01 PM
move the body so that its within the world space

M109uk
14-06-2007, 09:10 PM
Sorry, im not sure what you mean?

Im creating the player object so its within the terrains X and Z.. i placed the Y at 100 for the time being since the terrain is randomly generated.

M109uk
14-06-2007, 11:18 PM
Ah great, no worries... i guess you meant to have it within the min and max of the world.. all seems to work great now :) many thanks