void GenericContactProcess (const NewtonJoint* contactJoint, dFloat timestep, int threadIndex) { int isHightField; NewtonBody* body; NewtonCollision* collision; NewtonCollisionInfoRecord info; isHightField = 1; body = NewtonJointGetBody0 (contactJoint); collision = NewtonBodyGetCollision(body); NewtonCollisionGetInfo(collision, &info); if (info.m_collisionType != SERIALIZE_ID_HEIGHTFIELD) { body = NewtonJointGetBody1 (contactJoint); collision = NewtonBodyGetCollision(body); NewtonCollisionGetInfo(collision, &info); isHightField = (info.m_collisionType == SERIALIZE_ID_HEIGHTFIELD); } #define HOLE_IN_TERRAIN 10 if (isHightField) { void* nextContact; for (void* contact = NewtonContactJointGetFirstContact (contactJoint); contact; contact = nextContact) { int faceID; NewtonMaterial* material; nextContact = NewtonContactJointGetNextContact (contactJoint, contact); material = NewtonContactGetMaterial (contact); faceID = NewtonMaterialGetContactFaceAttribute (material); if (faceID == HOLE_INTERRAIN) { NewtonContactJointRemoveContact (contactJoint, contact); } } } }
static void GetCollisionSubShape(const NewtonJoint* const contactJoint, NewtonBody* const body) { NewtonCollisionInfoRecord collisionInfo; NewtonCollision* const collision = NewtonBodyGetCollision(body); NewtonCollisionGetInfo (collision, &collisionInfo); int count = 0; NewtonCollision* collidingSubShapeArrar[32]; // see if this is a compound collision or any other collision with sub collision shapes if (collisionInfo.m_collisionType == SERIALIZE_ID_COMPOUND) { // to get the torque we need the center of gravity in global space dVector origin; dMatrix bodyMatrix; NewtonBodyGetMatrix(body, &bodyMatrix[0][0]); NewtonBodyGetCentreOfMass(body, &origin[0]); origin = bodyMatrix.TransformVector(origin); for (void* contact = NewtonContactJointGetFirstContact (contactJoint); contact; contact = NewtonContactJointGetNextContact (contactJoint, contact)) { // get the material of this contact, // this part contain all contact information, the sub colliding shape, NewtonMaterial* const material = NewtonContactGetMaterial (contact); NewtonCollision* const subShape = NewtonMaterialGetBodyCollidingShape (material, body); int i = count - 1; for (; i >= 0; i --) { if (collidingSubShapeArrar[i] == subShape) { break; } } if (i < 0) { collidingSubShapeArrar[count] = subShape; count ++; dAssert (count < int (sizeof (collidingSubShapeArrar) / sizeof (collidingSubShapeArrar[0]))); // you can also get the forces here, however when tho function is call form a contact material // we can only get resting forces, impulsive forces can not be read here since they has no being calculated yet. // whoever if this function function is call after the NetwonUpdate they the application can read the contact force, that was applied to each contact point dVector force; dVector posit; dVector normal; NewtonMaterialGetContactForce (material, body, &force[0]); NewtonMaterialGetContactPositionAndNormal (material, body, &posit[0], &normal[0]); // the torque on this contact is dVector torque ((origin - posit) * force); // do what ever you want wit this } } } // here we should have an array of all colling sub shapes if (count) { // do what you need with this sub shape list } }
void SetShowMeshCollision (SceneManager& me, int mode) { NewtonTreeCollisionCallback showFaceCallback; showFaceCallback = NULL; if (mode) { showFaceCallback = ShowMeshCollidingFaces; } // iterate the world for (const NewtonBody* body = NewtonWorldGetFirstBody (me.m_world); body; body = NewtonWorldGetNextBody (me.m_world, body)) { NewtonCollision* collision; NewtonCollisionInfoRecord info; collision = NewtonBodyGetCollision (body); NewtonCollisionGetInfo (collision, &info); switch (info.m_collisionType) { case SERIALIZE_ID_TREE: case SERIALIZE_ID_SCENE: case SERIALIZE_ID_USERMESH: case SERIALIZE_ID_HEIGHTFIELD: { NewtonStaticCollisionSetDebugCallback (collision, showFaceCallback); break; } default: break; } } }
dCollisionBoxNodeInfo::dCollisionBoxNodeInfo(NewtonCollision* box) :dCollisionNodeInfo () { NewtonCollisionInfoRecord record; NewtonCollisionGetInfo(box, &record); _ASSERTE (record.m_collisionType == SERIALIZE_ID_BOX); dMatrix& offsetMatrix = *((dMatrix*) record.m_offsetMatrix); SetName ("box collision"); m_size = dVector (record.m_box.m_x, record.m_box.m_z, record.m_box.m_y); SetTransform (offsetMatrix); SetShapeId (record.m_collisionUserID); CalculateGeometryProperies (box, m_geometricInertia, m_geometricCenterAndVolume); }
dCollisionCompoundNodeInfo::dCollisionCompoundNodeInfo(NewtonCollision* const compound) :dCollisionNodeInfo () { NewtonCollisionInfoRecord record; NewtonCollisionGetInfo(compound, &record); dAssert (record.m_collisionType == SERIALIZE_ID_COMPOUND); dMatrix& offsetMatrix = *((dMatrix*) record.m_offsetMatrix); SetName ("compound collision"); SetTransform (offsetMatrix); SetShapeId (record.m_collisionUserID); CalculateGeometryProperies (compound, m_geometricInertia, m_geometricCenterAndVolume); }
NewtonBody* CreateLevelMeshBody (NewtonWorld* const world, DemoEntity* const ent, bool optimize) { NewtonCollision* const collision = CreateCollisionTree (world, ent, 0, optimize); // Get the root Matrix dMatrix matrix (ent->CalculateGlobalMatrix(NULL)); // create the level rigid body NewtonBody* const level = NewtonCreateDynamicBody(world, collision, &matrix[0][0]); //NewtonCollision* const collision1 = NewtonCreateNull(world); //NewtonBody* const level = NewtonCreateDynamicBody(world, collision1, &matrix[0][0]); //NewtonBodySetCollision(level, collision); //NewtonDestroyCollision (collision1); // save the pointer to the graphic object with the body. NewtonBodySetUserData (level, ent); #if 0 NewtonCollisionInfoRecord collisionInfo; NewtonCollisionGetInfo (collision, &collisionInfo); if (collisionInfo.m_collisionType == SERIALIZE_ID_TREE) { int count; dVector p0(-100, -100, -100); dVector p1(100, 100, 100); const dFloat* vertexArray; int vertexStrideInBytes; int vertexCount; int indexList[256]; int attributeList[256/3]; count = NewtonTreeCollisionGetVertexListTriangleListInAABB (collision, &p0[0], &p1[0], &vertexArray, &vertexCount, &vertexStrideInBytes, indexList, sizeof (indexList)/sizeof (indexList[0]), attributeList); } #endif // set a destructor for this rigid body //NewtonBodySetDestructorCallback (m_level, Destructor); // release the collision tree (this way the application does not have to do book keeping of Newton objects NewtonDestroyCollision (collision); // now we will make a lookup table for quick material index lookup for face to index //CollsionTreeFaceMap faceMap (NewtonBodyGetCollision(level)); return level; }
dCollisionConeNodeInfo::dCollisionConeNodeInfo(NewtonCollision* const cylinder) :dCollisionNodeInfo () { NewtonCollisionInfoRecord record; NewtonCollisionGetInfo(cylinder, &record); dAssert (record.m_collisionType == SERIALIZE_ID_CONE); dMatrix& offsetMatrix = *((dMatrix*) record.m_offsetMatrix); SetName ("cone collision"); m_radius = record.m_cone.m_radio; m_height = record.m_cone.m_height; SetTransform (offsetMatrix); SetShapeId (record.m_collisionUserID); CalculateGeometryProperies (cylinder, m_geometricInertia, m_geometricCenterAndVolume); }
void RigidBodyUIPane::SetSelectionMass (dFloat mass) { RigidBodyWorldDesc* const plugin = (RigidBodyWorldDesc*) RigidBodyWorldDesc::GetDescriptor(); Interface* const ip = GetCOREInterface(); int selectionCount = ip->GetSelNodeCount(); for (int i = 0; i < selectionCount; i ++) { INode* const node = ip->GetSelNode(i); RigidBodyController* const bodyInfo = (RigidBodyController*)plugin->GetRigidBodyControl(node); if (bodyInfo) { bodyInfo->m_mass = mass; _ASSERTE (bodyInfo->m_body); // dVector inertia (bodyInfo->m_inertia.Scale (mass)); // NewtonBodySetMassMatrix(bodyInfo->m_body, mass, inertia.m_x, inertia.m_y, inertia.m_z); NewtonCollisionInfoRecord info; NewtonCollision* const collision = NewtonBodyGetCollision(bodyInfo->m_body); NewtonCollisionGetInfo (collision, &info); switch (info.m_collisionType) { case SERIALIZE_ID_BOX: case SERIALIZE_ID_CONE: case SERIALIZE_ID_SPHERE: case SERIALIZE_ID_CAPSULE: case SERIALIZE_ID_CYLINDER: case SERIALIZE_ID_COMPOUND: case SERIALIZE_ID_CONVEXHULL: case SERIALIZE_ID_CONVEXMODIFIER: case SERIALIZE_ID_CHAMFERCYLINDER: { NewtonConvexCollisionCalculateInertialMatrix (collision, &bodyInfo->m_inertia[0], &bodyInfo->m_origin[0]); NewtonBodySetCentreOfMass(bodyInfo->m_body, &bodyInfo->m_origin[0]); NewtonBodySetMassMatrix(bodyInfo->m_body, bodyInfo->m_mass, bodyInfo->m_mass * bodyInfo->m_inertia.m_x, bodyInfo->m_mass * bodyInfo->m_inertia.m_y, bodyInfo->m_mass * bodyInfo->m_inertia.m_z); } } } } }
void CreateHeightFieldMesh (NewtonCollision* collision, Entity* ent) { int width; int height; dFloat hScale; dFloat vScale; unsigned short* elevations; NewtonCollisionInfoRecord collisionInfo; // keep the compiler happy memset (&collisionInfo, 0, sizeof (NewtonCollisionInfoRecord)); NewtonCollisionGetInfo (collision, &collisionInfo); // get the info from the collision mesh and create a visual mesh width = collisionInfo.m_heightField.m_width; height = collisionInfo.m_heightField.m_height; elevations = collisionInfo.m_heightField.m_elevation; vScale = collisionInfo.m_heightField.m_verticalScale; hScale = collisionInfo.m_heightField.m_horizonalScale; // allocate space to store vertex data ent->m_vertexCount = width * height; ent->m_vertex = (dFloat*) malloc (3 * width * height * sizeof (dFloat)); ent->m_normal = (dFloat*) malloc (3 * width * height * sizeof (dFloat)); ent->m_uv = (dFloat*) malloc (2 * width * height * sizeof (dFloat)); // scan the height field and convert every cell into two triangles for (int z = 0; z < height; z ++) { int z0; int z1; z0 = ((z - 1) < 0) ? 0 : z - 1; z1 = ((z + 1) > (height - 1)) ? height - 1 : z + 1 ; for (int x = 0; x < width; x ++) { int x0; int x1; x0 = ((x - 1) < 0) ? 0 : x - 1; x1 = ((x + 1) > (width - 1)) ? width - 1 : x + 1 ; dVector p0 (hScale * x0, elevations[z * width + x1] * vScale, hScale * z); dVector p1 (hScale * x1, elevations[z * width + x0] * vScale, hScale * z); dVector x10 (p1 - p0); dVector q0 (hScale * x, elevations[z0 * width + x] * vScale, hScale * z0); dVector q1 (hScale * x, elevations[z1 * width + x] * vScale, hScale * z1); dVector z10 (q1 - q0); dVector normal (z10 * x10); normal = normal.Scale (dSqrt (1.0f / (normal % normal))); dVector point (hScale * x, elevations[z * width + x] * vScale, hScale * z); ent->m_vertex[(z * width + x) * 3 + 0] = point.m_x; ent->m_vertex[(z * width + x) * 3 + 1] = point.m_y; ent->m_vertex[(z * width + x) * 3 + 2] = point.m_z; ent->m_normal[(z * width + x) * 3 + 0] = normal.m_x; ent->m_normal[(z * width + x) * 3 + 1] = normal.m_y; ent->m_normal[(z * width + x) * 3 + 2] = normal.m_z; ent->m_uv[(z * width + x) * 2 + 0] = x * TEXTURE_SCALE; ent->m_uv[(z * width + x) * 2 + 1] = z * TEXTURE_SCALE; } } // since the bitmap sample is 256 x 256, i fix into a single 16 bit index vertex array with ent->m_subMeshCount = 1; ent->m_subMeshes = (Entity::SubMesh*) malloc (sizeof (Entity::SubMesh)); // allocate space to the index list ent->m_subMeshes[0].m_textureHandle = LoadTexture ("grassAndDirt.tga"); ent->m_subMeshes[0].m_indexCount = (width - 1) * (height - 1) * 6; ent->m_subMeshes[0].m_indexArray = (unsigned short*) malloc (ent->m_subMeshes[0].m_indexCount * sizeof (unsigned short)); // now following the grid pattern and create and index list int index; int vertexIndex; index = 0; vertexIndex = 0; for (int z = 0; z < height - 1; z ++) { vertexIndex = z * width; for (int x = 0; x < width - 1; x ++) { ent->m_subMeshes[0].m_indexArray[index + 0] = GLushort (vertexIndex); ent->m_subMeshes[0].m_indexArray[index + 1] = GLushort (vertexIndex + width); ent->m_subMeshes[0].m_indexArray[index + 2] = GLushort (vertexIndex + 1); index += 3; ent->m_subMeshes[0].m_indexArray[index + 0] = GLushort (vertexIndex + 1); ent->m_subMeshes[0].m_indexArray[index + 1] = GLushort (vertexIndex + width); ent->m_subMeshes[0].m_indexArray[index + 2] = GLushort (vertexIndex + width + 1); index += 3; vertexIndex ++; } } // Optimize the mesh for hardware rendering if possible ent->OptimizeMesh(); /* dVector boxP0; dVector boxP1; // get the position of the aabb of this geometry dMatrix matrix (ent->m_curRotation, ent->m_curPosition); NewtonCollisionCalculateAABB (collision, &matrix[0][0], &boxP0.m_x, &boxP1.m_x); // place the origin of the visual mesh at the center of the height field matrix.m_posit = (boxP0 + boxP1).Scale (-0.5f); matrix.m_posit.m_w = 1.0f; ent->m_curPosition = matrix.m_posit; ent->m_prevPosition = matrix.m_posit; // create the level rigid body body = NewtonCreateBody(world, collision); // release the collision tree (this way the application does not have to do book keeping of Newton objects NewtonReleaseCollision (world, collision); // save the pointer to the graphic object with the body. NewtonBodySetUserData (body, ent); // set the global position of this body NewtonBodySetMatrix (body, &matrix[0][0]); // set the destructor for this object // NewtonBodySetDestructorCallback (body, Destructor); // get the position of the aabb of this geometry NewtonCollisionCalculateAABB (collision, &matrix[0][0], &boxP0.m_x, &boxP1.m_x); // add some extra padding the world size boxP0.m_x -= 10.0f; boxP0.m_y -= 10.0f; boxP0.m_z -= 10.0f; boxP1.m_x += 10.0f; boxP1.m_y += 400.0f; boxP1.m_z += 10.0f; // set the world size NewtonSetWorldSize (world, &boxP0.m_x, &boxP1.m_x); return body; */ }
static NewtonBody* CreateHeightFieldTerrain (DemoEntityManager* const scene, int sizeInPowerOfTwos, dFloat cellSize, dFloat elevationScale, dFloat roughness, dFloat maxElevation, dFloat minElevation) { int size = (1 << sizeInPowerOfTwos) + 1 ; dFloat* const elevation = new dFloat [size * size]; //MakeFractalTerrain (elevation, sizeInPowerOfTwos, elevationScale, roughness, maxElevation, minElevation); MakeFractalTerrain (elevation, sizeInPowerOfTwos, elevationScale, roughness, maxElevation, minElevation); for (int i = 0; i < 4; i ++) { ApplySmoothFilter (elevation, size); } //memset (elevation, 0, size * size * sizeof (dFloat)); //SetBaseHeight (elevation, size); // apply simple calderas // MakeCalderas (elevation, size, maxElevation * 0.7f, maxElevation * 0.1f); // // create the visual mesh DemoMesh* const mesh = new DemoMesh ("terrain", elevation, size, cellSize, 1.0f/4.0f, TILE_SIZE); DemoEntity* const entity = new DemoEntity(dGetIdentityMatrix(), NULL); scene->Append (entity); entity->SetMesh(mesh, dGetIdentityMatrix()); mesh->Release(); // create the height field collision and rigid body // create the attribute map int width = size; int height = size; char* const attibutes = new char [size * size]; memset (attibutes, 0, width * height * sizeof (char)); NewtonCollision* collision = NewtonCreateHeightFieldCollision (scene->GetNewton(), width, height, 1, 0, elevation, attibutes, 1.0f, cellSize, 0); #ifdef USE_STATIC_MESHES_DEBUG_COLLISION NewtonStaticCollisionSetDebugCallback (collision, ShowMeshCollidingFaces); #endif NewtonCollisionInfoRecord collisionInfo; // keep the compiler happy memset (&collisionInfo, 0, sizeof (NewtonCollisionInfoRecord)); NewtonCollisionGetInfo (collision, &collisionInfo); width = collisionInfo.m_heightField.m_width; height = collisionInfo.m_heightField.m_height; //elevations = collisionInfo.m_heightField.m_elevation; dVector boxP0; dVector boxP1; // get the position of the aabb of this geometry dMatrix matrix (entity->GetCurrentMatrix()); NewtonCollisionCalculateAABB (collision, &matrix[0][0], &boxP0.m_x, &boxP1.m_x); matrix.m_posit = (boxP0 + boxP1).Scale (-0.5f); matrix.m_posit.m_w = 1.0f; //SetMatrix (matrix); entity->ResetMatrix (*scene, matrix); // create the terrainBody rigid body NewtonBody* const terrainBody = NewtonCreateDynamicBody(scene->GetNewton(), collision, &matrix[0][0]); // release the collision tree (this way the application does not have to do book keeping of Newton objects NewtonDestroyCollision (collision); // in newton 300 collision are instance, you need to ready it after you create a body, if you want to male call on the instance collision = NewtonBodyGetCollision(terrainBody); #if 0 // uncomment this to test horizontal displacement unsigned short* const horizontalDisplacemnet = new unsigned short[size * size]; for (int i = 0; i < size * size; i++) { horizontalDisplacemnet[i] = dRand(); } NewtonHeightFieldSetHorizontalDisplacement(collision, horizontalDisplacemnet, 0.02f); delete horizontalDisplacemnet; #endif // save the pointer to the graphic object with the body. NewtonBodySetUserData (terrainBody, entity); // set the global position of this body // NewtonBodySetMatrix (m_terrainBody, &matrix[0][0]); // set the destructor for this object //NewtonBodySetDestructorCallback (terrainBody, Destructor); // get the position of the aabb of this geometry //NewtonCollisionCalculateAABB (collision, &matrix[0][0], &boxP0.m_x, &boxP1.m_x); #ifdef USE_TEST_ALL_FACE_USER_RAYCAST_CALLBACK // set a ray cast callback for all face ray cast NewtonTreeCollisionSetUserRayCastCallback (collision, AllRayHitCallback); dVector p0 (0, 100, 0, 0); dVector p1 (0, -100, 0, 0); dVector normal; dLong id; dFloat parameter; parameter = NewtonCollisionRayCast (collision, &p0[0], &p1[0], &normal[0], &id); #endif delete[] attibutes; delete[] elevation; return terrainBody; }
DemoMesh::DemoMesh(const char* const name, const NewtonCollision* const collision, const char* const texture0, const char* const texture1, const char* const texture2, dFloat opacity, const dMatrix& uvMatrix) :DemoMeshInterface() ,dList<DemoSubMesh>() ,m_uv(NULL) ,m_vertex(NULL) ,m_normal(NULL) ,m_optimizedOpaqueDiplayList(0) ,m_optimizedTransparentDiplayList(0) { // create a helper mesh from the collision collision NewtonMesh* const mesh = NewtonMeshCreateFromCollision(collision); // apply the vertex normals NewtonMeshCalculateVertexNormals(mesh, 30.0f * dDegreeToRad); dMatrix aligmentUV(uvMatrix); // NewtonCollisionGetMatrix(collision, &aligmentUV[0][0]); aligmentUV = aligmentUV.Inverse(); // apply uv projections NewtonCollisionInfoRecord info; NewtonCollisionGetInfo (collision, &info); switch (info.m_collisionType) { case SERIALIZE_ID_SPHERE: { NewtonMeshApplySphericalMapping(mesh, LoadTexture (texture0), &aligmentUV[0][0]); break; } case SERIALIZE_ID_CONE: case SERIALIZE_ID_CAPSULE: case SERIALIZE_ID_CYLINDER: case SERIALIZE_ID_CHAMFERCYLINDER: { //NewtonMeshApplySphericalMapping(mesh, LoadTexture(texture0)); NewtonMeshApplyCylindricalMapping(mesh, LoadTexture(texture0), LoadTexture(texture1), &aligmentUV[0][0]); break; } default: { int tex0 = LoadTexture(texture0); int tex1 = LoadTexture(texture1); int tex2 = LoadTexture(texture2); NewtonMeshApplyBoxMapping(mesh, tex0, tex1, tex2, &aligmentUV[0][0]); break; } } // extract vertex data from the newton mesh int vertexCount = NewtonMeshGetPointCount (mesh); AllocVertexData(vertexCount); NewtonMeshGetVertexChannel(mesh, 3 * sizeof (dFloat), (dFloat*)m_vertex); NewtonMeshGetNormalChannel(mesh, 3 * sizeof (dFloat), (dFloat*)m_normal); NewtonMeshGetUV0Channel(mesh, 2 * sizeof (dFloat), (dFloat*)m_uv); // extract the materials index array for mesh void* const geometryHandle = NewtonMeshBeginHandle (mesh); for (int handle = NewtonMeshFirstMaterial (mesh, geometryHandle); handle != -1; handle = NewtonMeshNextMaterial (mesh, geometryHandle, handle)) { int material = NewtonMeshMaterialGetMaterial (mesh, geometryHandle, handle); int indexCount = NewtonMeshMaterialGetIndexCount (mesh, geometryHandle, handle); DemoSubMesh* const segment = AddSubMesh(); segment->m_textureHandle = (GLuint)material; segment->SetOpacity(opacity); segment->AllocIndexData (indexCount); NewtonMeshMaterialGetIndexStream (mesh, geometryHandle, handle, (int*)segment->m_indexes); } NewtonMeshEndHandle (mesh, geometryHandle); // destroy helper mesh NewtonMeshDestroy(mesh); // optimize this mesh for hardware buffers if possible OptimizeForRender (); }