A place to discuss everything related to Newton Dynamics.
Moderators: Sascha Willems, walaber
by zaneski13 » Sun Aug 29, 2010 2:14 am
So, I have a scene with 2 boxes. A floor box, and a cube that falls from a height of 20 feet. I want the box to hit the floor and stop (or bounce around a little) I followed a tutorial on how to use Irrlicht and Newton Physics together and from that I made a cube class that creates a box in the NewtonWorld. (I'm not using Irrlicht, I just used it as a tutorial) Um, anyway, I believe that the collisions and the bodies are set ok. I'm a noo so I'm not really sure if I'm doing collisions correctly.
Heres my code. (You can probably just look at Cube::Cube() and setupNewtonWorld() )
- Code: Select all
#include "GLEngine.h"
#include "Camera.h"
#include "Matrix4.h"
#include <newton.h>
bool quit = false;
bool moveFoward = false;
bool moveBackward = false;
bool moveLeft = false;
bool moveRight = false;
bool rotatingCamera = false;
Camera_Editor *cam = NULL;
SDL_Event evt;
NewtonWorld *world = NULL;
#define GRAVITY -5.0f
void DrawBox(float width, float height, float depth);
void setTransformationNewtonCallback(const NewtonBody *body, const float *matrix, int threadIndex);
void applyForceAndTorqueNewtonCallback(const ::NewtonBody *body, float timeStep, int threadIndex);
void* _cdecl NewtonAlloc (int sizeInBytes)
{
return new char[sizeInBytes];
}
// destruction of memory from Newton
void _cdecl NewtonFree (void *ptr, int sizeInBytes)
{
char *tmp;
tmp = (char*) ptr;
delete[] tmp;
}
class Cube;
vector<Cube> cubes;
class Cube
{
public:
Matrix4 matrix;
int index;
Cube(Vector3f position, Vector3f rotation, Vector3f size_, Vector3f velocity, float mass)
{
size = size_;
NewtonCollision *collision;
collision = ::NewtonCreateBox(world, size.x, size.y, size.z, 1, NULL);
body = ::NewtonCreateBody(world, collision);
::NewtonBodySetCollision(body, collision);
::NewtonReleaseCollision(world, collision);
//::NewtonBodySetUserData(body, this); //We couldn't use this pointer because you can't modify data in the this pointer
index = (int)cubes.size();
::NewtonBodySetUserData(body, &index); //so we can then get this cube with cubes[index] == this
// Set body mass & inertia matrix
float Ixx = 0.7f * mass * (size.y * size.y + size.z * size.z) / 12.0f;
float Iyy = 0.7f * mass * (size.x * size.x + size.z * size.z) / 12.0f;
float Izz = 0.7f * mass * (size.x * size.x + size.y * size.y) / 12.0f;
NewtonBodySetMassMatrix (body, mass, Ixx, Iyy, Izz);
// Set callback functions for the body
NewtonBodySetTransformCallback(body, setTransformationNewtonCallback);
NewtonBodySetForceAndTorqueCallback(body, applyForceAndTorqueNewtonCallback);
//SETUP THE MATIX FOR THE BODY
matrix.LoadIdentity();
matrix.SetRotation(rotation.x, rotation.y, rotation.z);
matrix.SetTranslationPart(position.x, position.y, position.z);
NewtonBodySetMatrix(body, matrix.m);
float vel[3] = {velocity.x, velocity.y, velocity.z};
NewtonBodySetVelocity(body, vel);
float gravityForce[3] = {0.0f, GRAVITY * mass, 0.0f}; //for now
NewtonBodySetForce(body, gravityForce);
}
~Cube()
{
}
void Draw(void)
{
glPushMatrix();
glMultMatrixf(matrix.m);
DrawBox(size.x, size.y, size.z);
glPopMatrix();
}
NewtonBody* GetNewtonBody(void)
{
return body;
}
void SetMatrix(Matrix4 mat)
{
matrix = mat;
}
private:
Vector3f size;
NewtonBody *body;
};
void DrawBox(float width, float height, float depth)
{
//top face
glColor3f(1,0,0);
glBegin(GL_QUADS);
glVertex3f(-width, height,-depth);
glVertex3f( width, height,-depth);
glVertex3f( width, height, depth);
glVertex3f(-width, height, depth);
glEnd();
//bottom face
glBegin(GL_QUADS);
glVertex3f(-width, -height,-depth);
glVertex3f( width, -height,-depth);
glVertex3f( width, -height, depth);
glVertex3f(-width, -height, depth);
glEnd();
//left face
glColor3f(0,1,0);
glBegin(GL_QUADS);
glVertex3f(-width,-height,-depth);
glVertex3f(-width, height,-depth);
glVertex3f(-width, height, depth);
glVertex3f(-width, -height,depth);
glEnd();
//right face
glBegin(GL_QUADS);
glVertex3f(width,-height,-depth);
glVertex3f(width, height,-depth);
glVertex3f(width, height, depth);
glVertex3f(width, -height,depth);
glEnd();
//front face
glColor3f(0,0,1);
glBegin(GL_QUADS);
glVertex3f(-width,-height, depth);
glVertex3f(-width, height, depth);
glVertex3f( width, height, depth);
glVertex3f( width,-height, depth);
glEnd();
//back face
glBegin(GL_QUADS);
glVertex3f(-width,-height, -depth);
glVertex3f(-width, height, -depth);
glVertex3f( width, height, -depth);
glVertex3f( width,-height, -depth);
glEnd();
}
void setupNewtonWorld()
{
NewtonSetMemorySystem(NewtonAlloc,NewtonFree);
world = NewtonCreate();
float min[3] = {-500,-500,-500};
float max[3] = {500,500,500};
NewtonSetWorldSize(world, min, max);
NewtonSetSolverModel(world, 1); //1 is most efficient but least accurate.
// Set up default material properties for newton
int i = NewtonMaterialGetDefaultGroupID(world);
NewtonMaterialSetDefaultFriction(world, i, i, 0.8f, 0.4f);
NewtonMaterialSetDefaultElasticity(world, i, i, 0.3f);
NewtonMaterialSetDefaultSoftness(world, i, i, 0.05f);
NewtonMaterialSetCollisionCallback(world, i, i, NULL, NULL, NULL);
}
void destroyNewtonWorld()
{
NewtonDestroy(world);
}
//newton callbacks
void setTransformationNewtonCallback(const NewtonBody *body, const float *matrixFromNewton, int threadIndex)
{
int index = *((int*)NewtonBodyGetUserData(body));
if ( index < 0 || index >= (int)cubes.size() )
return;
Cube *c = &cubes[index];
if ( !c )
return;
memcpy(c->matrix.m, matrixFromNewton, sizeof(float)*16);
}
void applyForceAndTorqueNewtonCallback(const ::NewtonBody *body, float timeStep, int threadIndex) //this func gives DEBUG Warnings
{
float mass;
float Ixx;
float Iyy;
float Izz;
float force[3];
float torque[3];
NewtonBodyGetMassMatrix (body, &mass, &Ixx, &Iyy, &Izz);
force[0] = 0.0f;
force[1] = GRAVITY * mass; /// <-------- :D
force[2] = 0.0f;
torque[0] = 0.0f;
torque[1] = 0.0f;
torque[2] = 0.0f;
NewtonBodyAddForce (body, force);
NewtonBodyAddTorque (body, torque);
}
void handleEvent(void)
{
if ( evt.type==SDL_QUIT || (evt.type==SDL_KEYDOWN&&evt.key.keysym.sym==SDLK_ESCAPE) )
quit = true;
else if ( evt.type == SDL_KEYDOWN )
{
switch ( evt.key.keysym.sym )
{
case SDLK_UP:
moveFoward = true; break;
case SDLK_DOWN:
moveBackward = true; break;
case SDLK_LEFT:
moveLeft = true; break;
case SDLK_RIGHT:
moveRight = true; break;
}
}
else if ( evt.type == SDL_KEYUP )
{
switch ( evt.key.keysym.sym )
{
case SDLK_UP:
moveFoward = false; break;
case SDLK_DOWN:
moveBackward = false; break;
case SDLK_LEFT:
moveLeft = false; break;
case SDLK_RIGHT:
moveRight = false; break;
}
}
else if ( evt.type == SDL_MOUSEBUTTONDOWN && evt.button.button == SDL_BUTTON_MIDDLE )
rotatingCamera = true;
else if ( evt.type == SDL_MOUSEBUTTONUP && evt.button.button == SDL_BUTTON_MIDDLE )
rotatingCamera = false;
}
void updateScene(void)
{
int curx, cury;
SDL_GetMouseState(&curx,&cury);
cam->Update(moveFoward, moveBackward, moveLeft, moveRight, rotatingCamera, SDL_GetTicks(), curx, cury);
NewtonUpdate(world, 0.01f); //TODO: Implement better time step http://gafferongames.wordpress.com/game-physics/fix-your-timestep/
}
void drawScene(void)
{
GLEngine::ClearScreen();
cam->UpdateGLMatricesToCamera();
for ( int i = 0; i < (int)cubes.size(); i++ )
cubes[i].Draw();
GLEngine::FlushScreen();
}
int main(int argc, char **argv)
{
if ( !GLEngine::Initialize(800,600,32,false) )
return 1;
cam = new Camera_Editor(Vector3f(0,6,0), Vector3f(0,0,0), 8, 10, 800.0f/600.0f);
setupNewtonWorld();
Cube cube(Vector3f(0,20,-60), Vector3f(0,0,0), Vector3f(3,5,1), Vector3f(0,5,0), 10);
cubes.push_back(cube);
Cube floor_(Vector3f(0,-10,0), Vector3f(0,0,0), Vector3f(100,10.0f,100), Vector3f(0,0,0), 0);
cubes.push_back(floor_);
while ( !quit )
{
while ( SDL_PollEvent(&evt) )
handleEvent();
updateScene();
drawScene();
}
destroyNewtonWorld();
delete cam;
GLEngine::Uninitialize();
return 0;
}
I'm not sure if I have to do anything to initialize collisions in Newton. Hopefully someone can help me.
PS. I'm using Newton 2.24 Windows
-
zaneski13
-
- Posts: 10
- Joined: Sat Aug 28, 2010 6:12 pm
by zaneski13 » Sun Aug 29, 2010 12:45 pm
I also wanted to say that I changed some of my code and still nothing...
I changed
NewtonCollision *collision;
collision = ::NewtonCreateBox(world, size.x, size.y, size.z, 1, NULL);
body = ::NewtonCreateBody(world, collision);
::NewtonBodySetCollision(body, collision);
::NewtonReleaseCollision(world, collision);
to
NewtonCollision *collision;
Matrix4 offset;
offset.SetTranslationPart((position.x+size.x)/2.0f, (position.y+size.y)/2.0f, (position.z+size.z)/2.0f);
collision = ::NewtonCreateBox(world, size.x, size.y, size.z, 1, offset.m);
body = ::NewtonCreateBody(world, collision);
::NewtonReleaseCollision(world, collision);
and it still doesn't work D:
-
zaneski13
-
- Posts: 10
- Joined: Sat Aug 28, 2010 6:12 pm
by Stucuk » Sun Aug 29, 2010 1:25 pm
Debug Display would help to tell if its your rendering side or something else. What does two Colon's(::) before a procedure/function mean?
-

Stucuk
-
- Posts: 801
- Joined: Sat Mar 12, 2005 3:54 pm
- Location: Scotland
-
by zaneski13 » Sun Aug 29, 2010 1:42 pm
I'm using my own graphics system (OpenGL) so I don't have any of the Debug Display Functions. (I'm not using the Demo's graphics engine, instead I'm writing my own) Oh, and the :: before some of the functions just activates intellisence in my IDE so I can take a look at all of the available functions.
-
zaneski13
-
- Posts: 10
- Joined: Sat Aug 28, 2010 6:12 pm
by Julio Jerez » Sun Aug 29, 2010 1:46 pm
Debug display are utility funtions tah drw newton collsion shapes.
In teh SDK they are in file
#include <DebugDisplay.h>
in they are writen using straghtforward OpenGl too.
-
Julio Jerez
- Moderator

-
- Posts: 12452
- Joined: Sun Sep 14, 2003 2:18 pm
- Location: Los Angeles
-
by zaneski13 » Sun Aug 29, 2010 2:07 pm
well, I'm using my own matrix class so I transfered my matrix data into your matrix. Then once I got it to compile, it says that I have to link to wxbase28ud.lib
I'm using SDL so this doesn't make sense. So, Debug Display isn't really going to work in my app? Anyway, I'm sure that the problem is just when I create the cube. I'm brand new to the Newton Library so its possible I'm doing something silly.
Cube Creation Code
- Code: Select all
Cube(Vector3f position, Vector3f rotation, Vector3f size_, Vector3f velocity, float mass)
{
size = size_;
NewtonCollision *collision;
Matrix4 offset;
offset.LoadIdentity();
offset.SetTranslationPart((position.x+size.x)/2.0f, (position.y+size.y)/2.0f, (position.z+size.z)/2.0f);
collision = ::NewtonCreateBox(world, size.x, size.y, size.z, 0, offset.m);
body = ::NewtonCreateBody(world, collision);
//::NewtonBodySetUserData(body, this); //We couldn't use this pointer because you can't modify data in the this pointer
index = (int)cubes.size();
NewtonBodySetUserData(body, &index); //so we can then get this cube with cubes[index] == this
// Set body mass & inertia matrix
float inertia[3] = {0.0f};
float centerOfMass[3] = {0.0f};
::NewtonConvexCollisionCalculateInertialMatrix(collision, inertia, centerOfMass);
NewtonBodySetMassMatrix(body, mass, mass*inertia[0], mass*inertia[1], mass*inertia[2]);
NewtonBodySetCentreOfMass(body, centerOfMass);
// Set callback functions for the body
NewtonBodySetTransformCallback(body, setTransformationNewtonCallback);
NewtonBodySetForceAndTorqueCallback(body, applyForceAndTorqueNewtonCallback);
//SETUP THE MATIX FOR THE BODY
matrix.LoadIdentity();
matrix.SetRotation(rotation.x, rotation.y, rotation.z);
matrix.SetTranslationPart(position.x, position.y, position.z);
NewtonBodySetMatrix(body, matrix.m);
float vel[3] = {velocity.x, velocity.y, velocity.z};
NewtonBodySetVelocity(body, vel);
float gravityForce[3] = {0.0f, GRAVITY * mass, 0.0f}; //for now
NewtonBodySetForce(body, gravityForce);
::NewtonReleaseCollision(world, collision);
}
Call backs
- Code: Select all
//newton callbacks
void setTransformationNewtonCallback(const NewtonBody *body, const float *matrixFromNewton, int threadIndex)
{
int index = *((int*)NewtonBodyGetUserData(body));
if ( index < 0 || index >= (int)cubes.size() )
return;
Cube *c = &cubes[index]; //cubes is a global vector<Cube> cubes jsyk
if ( !c )
return;
memcpy(c->matrix.m, matrixFromNewton, sizeof(float)*16);
}
void applyForceAndTorqueNewtonCallback(const ::NewtonBody *body, float timeStep, int threadIndex) //this func gives DEBUG Warnings
{
float mass;
float Ixx;
float Iyy;
float Izz;
float force[3];
float torque[3];
NewtonBodyGetMassMatrix (body, &mass, &Ixx, &Iyy, &Izz);
force[0] = 0.0f;
force[1] = GRAVITY * mass; /// <-------- :D
force[2] = 0.0f;
torque[0] = 0.0f;
torque[1] = 0.0f;
torque[2] = 0.0f;
NewtonBodyAddForce (body, force);
NewtonBodyAddTorque (body, torque);
}
And perhaps the creation of the world?
- Code: Select all
void setupNewtonWorld()
{
NewtonSetMemorySystem(NewtonAlloc,NewtonFree);
world = NewtonCreate();
float min[3] = {-500,-500,-500};
float max[3] = {500,500,500};
NewtonSetWorldSize(world, min, max);
NewtonSetSolverModel(world, 1); //1 is most efficient but least accurate.
// Set up default material properties for newton
int i = NewtonMaterialGetDefaultGroupID(world);
NewtonMaterialSetDefaultFriction(world, i, i, 0.8f, 0.4f);
NewtonMaterialSetDefaultElasticity(world, i, i, 0.3f);
NewtonMaterialSetDefaultSoftness(world, i, i, 0.05f);
NewtonMaterialSetCollisionCallback(world, i, i, NULL, NULL, NULL);
}
-
zaneski13
-
- Posts: 10
- Joined: Sat Aug 28, 2010 6:12 pm
by Stucuk » Sun Aug 29, 2010 2:49 pm
The SDK implements Julios own way of doing a Debug Display. But it doesn't need to require anything. The core stuff is in the Newton Library which just gives you the vertex's of the physics bodies which you can then render however you like.
//Beginning - Call this to begin getting the vertex's
- Code: Select all
NewtonWorldForEachBodyInAABBDo(World,@MinWorld[0],@MaxWorld[0],@Debug_ShowBodyCollision,Nil);
// Debug_ShowBodyCollision
- Code: Select all
procedure Debug_ShowBodyCollision(const Body : PNewtonBody); cdecl;
var
Matrix : TMatrix;
begin
NewtonBodyGetMatrix(body, @Matrix[0][0]);
NewtonCollisionForEachPolygonDo(NewtonBodyGetCollision(body), @Matrix[0][0], @Debug_ShowGeometryCollision, NewtonBodyGetUserData(Body));
end;
// Render
- Code: Select all
procedure Debug_ShowGeometryCollision(const UserData : Pointer; VertexCount : Int; const FaceArray : PFloat; FaceId : int); cdecl;
var
x : Integer;
VectorArray : array of TVec3;
begin
if VertexCount = 0 then
exit;
// if (UserData = Nil) then Exit;
SetLength(VectorArray, VertexCount);
Move(FaceArray^, VectorArray[0], VertexCount*SizeOf(TVec3));
glBegin(GL_POLYGON);
for x := 0 to VertexCount-1 do
begin
{$IFDEF NEWTON_DOUBLE_PRECISION}
glVertex3dv(@VectorArray[x][0]);
{$ELSE}
glVertex3fv(@VectorArray[x][0]);
{$ENDIF}
end;
glEnd;
end;
You can modify the render part to render however you want.
-

Stucuk
-
- Posts: 801
- Joined: Sat Mar 12, 2005 3:54 pm
- Location: Scotland
-
by zaneski13 » Sun Aug 29, 2010 3:28 pm
I did just that and nothing happened. In fact, the DebugShowBodyCollision and Debug_ShowGeometryCollision are never called. But I'm not really concerned about this whole debug display, I just want to know why my box won't land on my floor. Do you see anything odd in my Cube Constructor or in the callbacks?
-
zaneski13
-
- Posts: 10
- Joined: Sat Aug 28, 2010 6:12 pm
by Julio Jerez » Sun Aug 29, 2010 5:57 pm
The box do not land where you think it should, because the collison is in the wrong place.
Debug display is the tool for figuring out what is wrong.
you do not have to use the functions in the demos, you can implements your own using the callback.
The demo can show you how it is done.
-
Julio Jerez
- Moderator

-
- Posts: 12452
- Joined: Sun Sep 14, 2003 2:18 pm
- Location: Los Angeles
-
by Stucuk » Sun Aug 29, 2010 5:58 pm
zaneski13 wrote:I did just that and nothing happened. In fact, the DebugShowBodyCollision and Debug_ShowGeometryCollision are never called.
Then its likely there is nothing within your worlds limits(Well the limits you gave NewtonWorldForEachBodyInAABBDo).
P.S "index = (int)cubes.size(); NewtonBodySetUserData(body, &index);" is wrong(Or at least bad code). You should only send a thing which has its own memory space. I don't see why you can't use
this, classes should still be able to write to there own variables when you use there methods(I.E This.SetMatrix(Matrix) ) .
-

Stucuk
-
- Posts: 801
- Joined: Sat Mar 12, 2005 3:54 pm
- Location: Scotland
-
by zaneski13 » Sun Aug 29, 2010 6:32 pm
Then its likely there is nothing within your worlds limits(Well the limits you gave NewtonWorldForEachBodyInAABBDo).
my min is (-500,-500,-500) and the max is (500,500,500) and my bodies are in between those areas
- Code: Select all
void _cdecl Debug_ShowGeometryCollision(void* userData, int vertexCount, const dFloat* faceArray, int faceId)
{
glPointSize(4);
glColor3f(1,1,1);
glBegin(GL_POINTS);
for ( int i = 0; i < vertexCount; i+=3 )
{
glVertex3f(faceArray[i], faceArray[i+1], faceArray[i+2]);
}
glEnd();
cout << "HI!!!" << endl; //is never writen onto the command prompt
}
void _cdecl DebugShowBodyCollision(const ::NewtonBody *body, void *userData)
{
Matrix4 mat;
::NewtonBodyGetMatrix(body, mat.m);
glPushMatrix();
glMultMatrixf(mat.m);
::NewtonCollisionForEachPolygonDo(NewtonBodyGetCollision(body), mat.m, Debug_ShowGeometryCollision, NewtonBodyGetUserData(body) );
glPopMatrix();
}
void setupNewtonWorld()
{
NewtonSetMemorySystem(NewtonAlloc,NewtonFree);
world = NewtonCreate();
float min[3] = {-500,-500,-500};
float max[3] = {500,500,500};
NewtonSetWorldSize(world, min, max);
NewtonSetSolverModel(world, 1); //1 is most efficient but least accurate.
// Set up default material properties for newton
int i = NewtonMaterialGetDefaultGroupID(world);
NewtonMaterialSetDefaultFriction(world, i, i, 0.8f, 0.4f);
NewtonMaterialSetDefaultElasticity(world, i, i, 0.3f);
NewtonMaterialSetDefaultSoftness(world, i, i, 0.05f);
NewtonMaterialSetCollisionCallback(world, i, i, NULL, NULL, NULL);
//debug
NewtonWorldForEachBodyInAABBDo(world, min, max, DebugShowBodyCollision, NULL);
}
I don't see why you can't use this,
I tried using a this pointer but anytime I tried to modify the data, I couldn't. That's because a this pointer can't be modified. So Instead, after I create the Cube, I put it inside of a vector<Cube>. So when I need to modify the body's cube, I can just get the index and get the cube from the cubes vector.
-
zaneski13
-
- Posts: 10
- Joined: Sat Aug 28, 2010 6:12 pm
by Stucuk » Sun Aug 29, 2010 9:16 pm
Based on the code you posted it will never render any debug as there is no physics bodies added before your calling NewtonWorldForEachBodyInAABBDo. BTW you don't want to put anything in Debug_ShowGeometryCollision relating to OpenGL. Newton gives you the actual locations of the vertex's, so adding its matrix to them will make them display incorrectly as they then have the matrix applied 2 times.
This may be a constant but as its a Pointer to a Class then you should as i stated be able to use the classes methods. I don't mean directly setting variables but actually using the methods. Some SDK demos use This, so you can use it as long as you use it properly. This is just a pointer, all it does is points to a memory location, while you can't make This point somewhere else, you can still modify the memory location it points to.
I.E:
- Code: Select all
Whatever = NewtonBodyGetUserData(Body);
Whatever.DoSomething(Matrix);
-

Stucuk
-
- Posts: 801
- Joined: Sat Mar 12, 2005 3:54 pm
- Location: Scotland
-
Return to General Discussion
Who is online
Users browsing this forum: No registered users and 45 guests