The good thing is: I've reduced the scene to 1 static ground box, 20 boxes and one cylinder above it.
The bad is: Boxes and cylinder are in the air initially. The Boxes fall on the ground and the cylinder falls on the boxes.
After that the scene is in the state where the crash happens. If i start the scene with no gravity, no crash.
I think you'll be able to reproduce with given code, otherwise let me know...
See the attache image for how the scene should look like after the cylinder collided with the boxes.
When the boxes are at rest, the raycast using given coords should reproduce the crash.
The cylinder is still moving, but that does not have effect.
my machine is a i7 930 or 730?, however, older generation quad core.
Running in debug mode, without advise newton to do multithreading.

- raycastScene.jpg (180.08 KiB) Viewed 5569 times
- Code: Select all
void PhysicsWorld::CreateTestScene () // PhysicsWorld is derived from NewtonPhysics, given below
{
float cubeHalf = 0.5f;
float extraHeight = cubeHalf*2;
sMat4 trans;
trans.Identity();
Shape *groundShape = CreateBoxShape (sVec3 (100, 10, 100));
trans.Identity();
*trans.Translation() = sVec3 (0,-5,0);
CreateRigidBody (0, trans, groundShape);
ReleaseShape (groundShape);
Shape *cylShape = CreateCylinderShape (8, 2);
trans.Identity();
*trans.Translation() = sVec3 (0,60,0);
CreateRigidBody (1, trans, cylShape);
ReleaseShape (cylShape);
if (1)
{
for (int i=0; i<20; i++)
{
sVec3 dim (1, 1 + (float) (i%5) * 0.8f, 1 + (float) i * 0.8f);
Shape *stackShape = CreateBoxShape (dim);
trans.Identity();
trans.Rotation()->FromEulerZYX (sVec3(0, (float) (i) * 0.05f, 0));
*trans.Translation() = sVec3 (i * 5.0f - 47.5f, 20, 0);
CreateRigidBody (1, trans, stackShape);
ReleaseShape (stackShape);
}
}
}
void PhysicsWorld::Step ()
{
NewtonUpdate (world, 0.024999000); // nicely simplyfied
}
Body* PhysicsWorld::CreateRigidBody (float mass, sMat4 &trans, Shape *shape) // Body == NewtonBody
{
Body *body = ((NewtonPhysics*)this)->CreateRigidBody (mass, trans, shape);
if (body)
{
const float damp = 0.01f;
NewtonBodySetAngularDamping (body, &damp);
NewtonBodySetLinearDamping (body, 0.01f);
//NewtonBodyG
BodyData *data = new BodyData;
//todo: check alloc
NewtonBodySetUserData (body, (void*) data);
NewtonBodySetForceAndTorqueCallback (body, ForceAndTorqueCallback);
bodies.push_back (body);
//BodySetMaterial (body, 0);
}
return body;
}
class NewtonPhysics
{
public:
NewtonWorld* world;
NewtonCollision* CreateBoxShape (sVec3 &dim, sMat4 *offset = 0)
{
return NewtonCreateBox (world, dim.x(), dim.y(), dim.z(), SERIALIZE_ID_BOX, &(*offset)[0][0]);
}
NewtonCollision* CreateCylinderShape (float height, float radius, sMat4 *offset = 0)
{
return NewtonCreateCylinder (world, radius, height, SERIALIZE_ID_CYLINDER, &(*offset)[0][0]);
}
// because i initially used a single interface for both bullet and newton, i use functions like this, they do nothing special, simply what you expect
void ReleaseShape (NewtonCollision* shape)
{
NewtonReleaseCollision (world, shape);
}
void CreateWorld ()
{
// set the memory allocators
NewtonSetMemorySystem (AllocMemory, FreeMemory);
// create the Newton World
world = NewtonCreate ();
// use the standard x87 floating point model
NewtonSetPlatformArchitecture (world, 0);
// set a fix world size
v3f minSize (-1000.0f, -1000.0f, -1000.0f);
v3f maxSize ( 1000.0f, 1000.0f, 1000.0f);
NewtonSetWorldSize (world, &minSize[0], &maxSize[0]);
NewtonSetSolverModel (world, 4);
}
NewtonBody* CreateRigidBody (float mass, sMat4 &trans, NewtonCollision *shape)
{
float origin[4];
float inertia[4];
NewtonBody* body;
body = NewtonCreateBody (world, shape, &trans[0][0]);//
NewtonConvexCollisionCalculateInertialMatrix (shape, &inertia[0], &origin[0]);
NewtonBodySetMassMatrix (body, mass, mass * inertia[0], mass * inertia[1], mass * inertia[2]);
NewtonBodySetCentreOfMass (body, &origin[0]);
return body;
}
// let me know if something's missing...
}
void ForceAndTorqueCallback (const NewtonBody* body, dFloat timestep, int threadIndex)
{
dFloat Ixx;
dFloat Iyy;
dFloat Izz;
dFloat mass;
NewtonBodyGetMassMatrix (body, &mass, &Ixx, &Iyy, &Izz);
sVec3 force (0.0f, mass * -40.0f, 0.0f);
NewtonBodyAddForce (body, &force[0]);
}
// this is from the free sony math lib coming with bullet, that rotation is required to reproduce, but this 3x3 correspondents to the top left of a dgMatrix with equal ordering
inline const Matrix3 Matrix3::rotationZYX( const Vector3 & radiansXYZ )
{
float sX, cX, sY, cY, sZ, cZ, tmp0, tmp1;
sX = sinf( radiansXYZ.getX() );
cX = cosf( radiansXYZ.getX() );
sY = sinf( radiansXYZ.getY() );
cY = cosf( radiansXYZ.getY() );
sZ = sinf( radiansXYZ.getZ() );
cZ = cosf( radiansXYZ.getZ() );
tmp0 = ( cZ * sY );
tmp1 = ( sZ * sY );
return Matrix3(
Vector3( ( cZ * cY ), ( sZ * cY ), -sY ),
Vector3( ( ( tmp0 * sX ) - ( sZ * cX ) ), ( ( tmp1 * sX ) + ( cZ * cX ) ), ( cY * sX ) ),
Vector3( ( ( tmp0 * cX ) + ( sZ * sX ) ), ( ( tmp1 * cX ) - ( cZ * sX ) ), ( cY * cX ) )
);
}
// raycast...
struct RayCastInfo
{
float param;
sVec3 normal;
Body* hitBody;
RayCastInfo ()
{
param = 1.1f;
hitBody = 0;
}
};
unsigned nRayCastPrefilter (const NewtonBody* body, const NewtonCollision* collision, void* userData)
{
// ray cannot pick trigger volumes
return NewtonCollisionIsTriggerVolume(collision) ? 0 : 1;
}
float nRayCastFilter (const NewtonBody* body, const float* normal, int collisionID, void* userData, float intersectParam)
{
float mass;
float Ixx;
float Iyy;
float Izz;
NewtonBodyGetMassMatrix (body, &mass, &Ixx, &Iyy, &Izz);
RayCastInfo *rc = (RayCastInfo*) userData;
if (intersectParam < rc->param)
{
rc->param = intersectParam;
rc->hitBody = (Body*) body;
sMat4 m; BodyGetMatrix ((Body*)body, m);
rc->normal = m.Unrotate (*((sVec3*)normal));
}
return intersectParam;
}