Moderators: Sascha Willems, walaber
aqnuep wrote:AWESOME!!!
As I see there will be way to dynamically remove parts of the geometry. I suppose Newton will provide us a callback to handle the removed parts so they can fly out from the destruction. That will provide loads of possibilities.
aqnuep wrote:AWESOME!!!
Wondering if there would be possibility e.g. if all the pillars are broken then issue some kind of collapsing of the whole building. Of course, this will be probably up to the application.
aqnuep wrote:AWESOME!!!
Another thing that comes to my mind is that maybe this feature can be used also for creating deforming objects like dips on metallic surfaces or stuff like that.
Carli wrote:Is there a possibility to make a destructable huge landscape with Newton Game Dynamics in Realtime? (with fixed 40 FPS)
Carli wrote:Is there a possibility to make a destructable huge landscape with Newton Game Dynamics in Realtime? (with fixed 40 FPS)
Marc wrote:Do I have to define the parts into which a geometry can break myself or does newton split it by itself on demand?
static void LoadSolidBuilding (SceneManager& system, NewtonBody* landScapeBody)
{
int vertexCount;
int texCount;
FILE* file;
int matrialMap[256];
NewtonBody* body;
NewtonWorld* world;
NewtonCollision* compound;
ShareVertexMesh* meshInstance;
NewtonbreakableComponentMesh* meshData;
world = system.m_world;
// open the level data
file = OpenFileAsset(system, "SolidRuins.mdl", landScapeBody);
// read the textures;
memset (matrialMap, 0, sizeof (matrialMap));
DeSerializeFile (file, &texCount, sizeof (int));
for (int i = 0; i < texCount; i ++) {
int id;
char buffer[64];
DeSerializeFile (file, &id, sizeof (int));
DeSerializeFile (file, &buffer, sizeof (buffer));
matrialMap[id] = LoadTexture(buffer);
}
compound = NewtonCreateCollisionFromSerialization (system.m_world, DeSerializeFile, file);
fclose (file);
// tell the engine which pieces of this compound are touching this static body and
// this call is only need it for compound how are static bodies
dMatrix fixMatrix;
NewtonCollision* fixCollision[1];
NewtonBodyGetMatrix(landScapeBody, &fixMatrix[0][0]);
fixCollision[0] = NewtonBodyGetCollision(landScapeBody);
NewtonCompoundBreakableResetAnchoredPieces (compound);
NewtonCompoundBreakableSetAnchoredPieces (compound, 1, &fixMatrix[0][0], fixCollision);
// NewtonCollisionInfoRecord collisionInfo;
// NewtonCollisionGetInfo (compound, &collisionInfo);
// create a visual Mesh for the Compound Breakable
vertexCount = NewtonCompoundBreakableGetVertexCount (compound);
g_vertex = (dFloat*) malloc (3 * vertexCount * sizeof (dFloat));
g_normal = (dFloat*) malloc (3 * vertexCount * sizeof (dFloat));
g_uv = (dFloat*) malloc (2 * vertexCount * sizeof (dFloat));
NewtonCompoundBreakableGetVertexStreams (compound, 3 * sizeof (dFloat), g_vertex, 3 * sizeof (dFloat), g_normal, 2 * sizeof (dFloat), g_uv);
meshData = NewtonBreakableGetMainMesh (compound);
meshInstance = new ShareVertexMesh (vertexCount, g_vertex, g_normal, g_uv);
for (void* segment = NewtonBreakableGetFirstSegment(meshData); segment; segment = NewtonBreakableGetNextSegment ( segment)) {
int material;
int indexCount;
dSubMesh* subMesh;
subMesh = meshInstance->AddSubMesh();
material = NewtonBreakableSegmentGetMaterial (segment);
indexCount = NewtonBreakableSegmentGetIndexCount (segment);
subMesh->m_textureHandle = (GLuint)matrialMap[material];
subMesh->AllocIndexData (indexCount);
// subMesh->m_indexCount = NewtonBreakableSegmentGetIndexStreamShort (compound, meshData, segment, (short int*)subMesh->m_indexes);
subMesh->m_indexCount = NewtonBreakableSegmentGetIndexStream (compound, meshData, segment, (int*)subMesh->m_indexes);
}
dMatrix matrix (GetIdentityMatrix());
RenderPrimitive* primitive;
primitive = new RenderPrimitive (matrix, meshInstance);
system.AddModel(primitive);
meshInstance->Release();
// create the rigid body
body = NewtonCreateBody(world, compound);
// Release the collision
NewtonReleaseCollision(world, compound);
//m_matrix = dPitchMatrix (15.0f* 3.141592f / 180.0f);
// dMatrix matrix (GetIdentityMatrix());
// set the global position of this body
NewtonBodySetMatrix (body, &matrix[0][0]);
// save the pointer to the graphic object with the body.
NewtonBodySetUserData (body, primitive);
}
int ClipSolidCallback (NewtonMesh* const mesh, void* userData, dFloat* pinAndPivotSplitMatrix)
{
dFloat x;
dFloat y;
dFloat z;
dMatrix splitMatrix;
// get the OOBB along for this mesh
NewtonMeshCalculateOOBB (mesh, &splitMatrix[0][0], &x, &y, &z);
if (x > 0.5f) {
// if the largest piece is too big, the continue the split process
// randomize the clip plane position a little
dVector posit = splitMatrix.m_posit;
// randomize the plane orientation
posit += splitMatrix.m_front.Scale (x * RandomVariable(0.5f));
splitMatrix = splitMatrix * dYawMatrix(3.1416f * RandomVariable(1.0f));
splitMatrix = splitMatrix * dRollMatrix(3.1416f * RandomVariable(1.0f));
splitMatrix.m_posit = posit;
memcpy (pinAndPivotSplitMatrix, &splitMatrix[0][0], sizeof (dMatrix));
// return different than zero to indicate that the plane is valid and the process should continue spliting
return 1;
}
// return zero to indicate that this pieces should not be split anymore.
return 0;
}
static FILE* OpenFileAsset(SceneManager& system, const char* name, NewtonBody* landScapeBody)
{
int shapeCount;
GLuint tex;
dFloat width;
dFloat breadth;
HANDLE handle;
char name1[128];
char fullPathName[2048];
char fullPathName1[2048];
int piecesID[512];
dMatrix pallete[512];
NewtonMesh *clippers[512];
NewtonMesh *solidPieces[512];
dMatrix matrixPallete[512];
FILE* file;
OGLModel* model;
NewtonMesh *meshCliper;
NewtonCollision* compound;
strcpy (name1, name);
strtok (name1, ".");
strcat (name1, ".bin");
GetWorkingFileName (name1, fullPathName1);
GetWorkingFileName (name, fullPathName);
handle = CreateFileA(fullPathName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (handle != INVALID_HANDLE_VALUE) {
FILETIME nameCreationTime;
GetFileTime(handle, NULL, NULL, &nameCreationTime);
CloseHandle(handle);
handle = CreateFileA(fullPathName1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (handle != INVALID_HANDLE_VALUE) {
FILETIME nameCreationTime1;
GetFileTime(handle, NULL, NULL, &nameCreationTime1);
CloseHandle(handle);
if (CompareFileTime(&nameCreationTime1, &nameCreationTime) > 0) {
// return fopen (fullPathName1, "rb");
}
}
}
// create a Clip Plane for build the derbies pieces
dMatrix plane (GetIdentityMatrix());
dMatrix texMatrix (GetIdentityMatrix());
width = 20.0f;
breadth = 20.0f;
tex = LoadTexture ("destructionDetail.tga");
texMatrix[1][1] = 4.0f /breadth;
texMatrix[2][2] = 4.0f /breadth;
// create a clipper plane (only one for all solid, but there may be a different one for different meshes
meshCliper = NewtonMeshCreatePlane (&plane[0][0], width, breadth, tex, &texMatrix[0][0]);
// load a model made form solid pieces, each pieces must intersect a nearby piece to make a complex solid large piece
model = new OGLModel ();
OGLLoaderContext context;
model->Load (fullPathName, context);
// create the matrix pallete that locate each child solid piece, relative to the origin
model->UpdateMatrixPalette (GetIdentityMatrix(), pallete, sizeof (pallete) / sizeof (dMatrix));
shapeCount = 0;
// iterate over the mode and searching for each solid piece of geometry
for (ModelComponentList<dList<dMesh*> >::dListNode* list = model->m_meshList.GetFirst(); list; list = list->GetNext()) {
for (dList<dMesh*>::dListNode* node = list->GetInfo().m_data.GetFirst(); node; node = node->GetNext()) {
OGLMesh* mesh;
mesh = (OGLMesh*)node->GetInfo();
// assign a clipped mesh to this solid mesh
clippers[shapeCount] = meshCliper;
// each piece can have it own ID, for now make it 0
piecesID[shapeCount] = 0;
matrixPallete[shapeCount] = pallete[mesh->m_boneID];
// convert the solid geometry to a newton mesh
solidPieces[shapeCount] = mesh->BuildMesh();
shapeCount ++;
}
}
// we do not need the mode anymore
delete model;
// create ad solid destructible
compound = NewtonCreateCompoundBreakable (system.m_world, shapeCount, &solidPieces[0], &clippers[0], &matrixPallete[0][0][0], &piecesID[0], 0, 0, ClipSolidCallback, NULL);
// tell the engine which pieces of this compound are touching this static body and
// this call is only need it for compound how are static bodies
// NewtonCreateCompoundBreakableSetAncheredPieces (compound, 0, NULL, NULL);
// destroy the mesh because not need anymore
NewtonMeshDestroy (meshCliper);
for (int i = 0; i < shapeCount; i ++) {
NewtonMeshDestroy(solidPieces[i]);
}
// save the collision file
file = fopen (fullPathName1, "wb");
// save the Material information Before Serializing the data
// Iterate over all components finding Material ID
dTree<const char*,int>textureMap;
for (NewtonbreakableComponentMesh* component = NewtonBreakableGetFirstComponent (compound); component; component = NewtonBreakableGetNextComponent (component)) {
for (void* segment = NewtonBreakableGetFirstSegment(component); segment; segment = NewtonBreakableGetNextSegment (segment)) {
int material;
const char* textName;
material = NewtonBreakableSegmentGetMaterial (segment);
textName = FindTextureById (material);
if (textName) {
textureMap.Insert(textName, material);
}
}
}
// save all the textures
int texCount;
texCount = textureMap.GetCount();
SerializeFile (file, &texCount, sizeof (int));
dTree<const char*,int>::Iterator iter (textureMap);
for (iter.Begin(); iter; iter++) {
int id;
char buffer[64];
const char* name;
const char* fullName;
id = iter.GetNode()->GetKey();
fullName = iter.GetNode()->GetInfo();
name = strrchr (fullName, '/') + 1;
sprintf (buffer, "%s", name);
SerializeFile (file, &id, sizeof (int));
SerializeFile (file, &buffer, sizeof (buffer));
}
NewtonCollisionSerialize (system.m_world, compound, SerializeFile, file);
fclose (file);
NewtonReleaseCollision (system.m_world, compound);
return fopen (fullPathName1, "rb");
}
static void DestroyThisBodyCallback (const NewtonBody* body, const NewtonJoint* contactJoint)
{
NewtonCollision* collision;
NewtonCollisionInfoRecord collisionInfo;
// Get the collision shape for the body and see if this is a compound breakable shape
collision = NewtonBodyGetCollision(body);
NewtonCollisionGetInfo (collision, &collisionInfo);
if (collisionInfo.m_collisionType == SERIALIZE_ID_COMPOUND_BREAKABLE) {
// this is a compound breakable, finds the part at the contact and create the debris pieces
dFloat maxSpeed;
NewtonMaterial* bestMaterail;
// find the location of the strongest impact
maxSpeed = 0.0f;
bestMaterail = NULL;
for (void* contact = NewtonContactJointGetFirstContact (contactJoint); contact; contact = NewtonContactJointGetNextContact (contactJoint, contact)) {
dFloat speed;
NewtonMaterial* material;
material = NewtonContactGetMaterial (contact);
speed = dAbs (NewtonMaterialGetContactNormalSpeed(material));
if (speed > maxSpeed) {
maxSpeed = speed ;
bestMaterail = material;
}
}
int debriCount;
dVector contactPoint;
dVector contactNormal;
NewtonbreakableComponentMesh* components[32];
dMatrix matrix;
_ASSERTE (bestMaterail);
NewtonMaterialGetContactPositionAndNormal (bestMaterail, &contactPoint.m_x, &contactNormal.m_x);
NewtonBodyGetMatrix(body, &matrix[0][0]);
// Get the origin in the space of the collision mesh
contactPoint = matrix.UntransformVector(contactPoint);
// get all the debris pieces on the radios of the impact
debriCount = NewtonBreakableGetComponentsInRadius (collision, &contactPoint.m_x, 1.0f, components, sizeof (components)/sizeof (components[0]));
// for each piece add a new body to the scene
for (int i = 0; i < debriCount; i ++) {
NewtonbreakableComponentMesh* component;
// get the information from this component and emit a visual an dphysics debris piece
component = components[i];
// finally remove this component for the
NewtonBreakableDeleteComponent (collision, component);
}
// now reconstruct the main visual mesh
// we do no need to allocate the vertex buffer sine the mesh use the same previous buffer
// we only need to create the sub mesh that had changed
RenderPrimitive* primitive;
NewtonbreakableComponentMesh* meshData;
primitive = (RenderPrimitive*) NewtonBodyGetUserData(body);
meshData = NewtonBreakableGetMainMesh (collision);
for (void* segment = NewtonBreakableGetFirstSegment(meshData); segment; segment = NewtonBreakableGetNextSegment ( segment)) {
int material;
int indexCount;
OGLMesh* mesh;
dSubMesh* subMesh;
mesh = NULL;
subMesh = NULL;
material = NewtonBreakableSegmentGetMaterial (segment);
indexCount = NewtonBreakableSegmentGetIndexCount (segment);
// find a mesh and a submesh by this material
for (ModelComponentList<dList<dMesh*> >::dListNode* list = primitive->m_meshList.GetFirst(); !mesh && list; list = list->GetNext()) {
for (dList<dMesh*>::dListNode* node = list->GetInfo().m_data.GetFirst(); !mesh && node; node = node->GetNext()) {
for (dMesh::dListNode* meshSegment = node->GetInfo()->GetFirst(); !mesh && meshSegment; meshSegment = meshSegment->GetNext()) {
if (int (meshSegment->GetInfo().m_textureHandle) == material) {
mesh = (OGLMesh*) &list->GetInfo().m_data;
subMesh = &meshSegment->GetInfo();
}
}
}
}
if (!mesh) {
_ASSERTE (0);
// _ASSERTE (mesh);
}
// if we did no find this material this is a new segment
if (!subMesh) {
subMesh = mesh->AddSubMesh();
subMesh->m_textureHandle = material;
}
// now check if this segment can hold the vertex array;
if (subMesh->m_indexCount < indexCount) {
subMesh->AllocIndexData (indexCount);
}
// subMesh->m_indexCount = NewtonBreakableSegmentGetIndexStreamShort (collision, meshData, segment, (short int*)subMesh->m_indexes);
subMesh->m_indexCount = NewtonBreakableSegmentGetIndexStream (collision, meshData, segment, (int*)subMesh->m_indexes);
}
}
/*
PrefFabDebrisDatabase::dTreeNode *debrisPiecesNode;
// find a the strongest force
debrisPiecesNode = PrefFabDebrisDatabase::prefabDebrisDatabase.Find(NewtonBodyGetCollision(body));
if (debrisPiecesNode) {
dMatrix matrix;
NewtonWorld* world;
SceneManager* system;
NewtonBody* rigidBody;
dVector veloc;
dVector omega;
// Get the world;
world = NewtonBodyGetWorld (body);
system = (SceneManager*) NewtonWorldGetUserData(world);
NewtonBodyGetOmega(body, &omega[0]);
NewtonBodyGetVelocity(body, &veloc[0]);
NewtonBodyGetMatrix (body, &matrix[0][0]);
veloc = veloc.Scale (0.25f);
omega = omega.Scale (0.25f);
for (PrefFabDebriList::dListNode* node = debrisPiecesNode->GetInfo().GetFirst(); node; node = node->GetNext()) {
OGLMesh* meshInstance;
NewtonCollision* collision;
RenderPrimitive* primitive;
PrefFabDebriElement& debriData = node->GetInfo();
// make a visual object
meshInstance = debriData.m_mesh;
// create a visual geometry
primitive = new RenderPrimitive (matrix, meshInstance);
// save the graphics system
system->AddModel (primitive);
collision = debriData.m_shape;
// calculate the moment of inertia and the relative center of mass of the solid
//create the rigid body
rigidBody = NewtonCreateBody (world, collision);
// set the correct center of gravity for this body
NewtonBodySetCentreOfMass (rigidBody, &debriData.m_com[0]);
// set the mass matrix
NewtonBodySetMassMatrix (rigidBody, debriData.m_mass, debriData.m_Ixx, debriData.m_Iyy, debriData.m_Izz);
// save the pointer to the graphic object with the body.
NewtonBodySetUserData (rigidBody, primitive);
// assign the wood id
// NewtonBodySetMaterialGroupID (rigidBody, NewtonBodyGetMaterialGroupID(source));
// set continue collision mode
NewtonBodySetContinuousCollisionMode (rigidBody, 1);
// set a destructor for this rigid body
NewtonBodySetDestructorCallback (rigidBody, PhysicsBodyDestructor);
// set the transform call back function
NewtonBodySetTransformCallback (rigidBody, PhysicsSetTransform);
// set the force and torque call back function
NewtonBodySetForceAndTorqueCallback (rigidBody, PhysicsApplyGravityForce);
// set the matrix for both the rigid body and the graphic body
NewtonBodySetMatrix (rigidBody, &matrix[0][0]);
PhysicsSetTransform (rigidBody, &matrix[0][0], 0);
dVector debriOmega (omega);
dVector debriVeloc (veloc + omega * matrix.RotateVector(debriData.m_com));
// for now so that I can see the body
//debriVeloc = dVector (0, 0, 0, 0);
//debriVeloc.Scale (0.25f);
//debriVeloc.Omega
//omega = dVector (0, 0, 0, 0);
NewtonBodySetOmega(rigidBody, &debriOmega[0]);
NewtonBodySetVelocity(rigidBody, &debriVeloc[0]);
}
RenderPrimitive* srcPrimitive;
srcPrimitive = (RenderPrimitive*) NewtonBodyGetUserData (body);
// remove the old visual from graphics world
delete srcPrimitive;
system->Remove(srcPrimitive);
// finally destroy this body;
NewtonDestroyBody(world, body);
}
*/
}
Users browsing this forum: No registered users and 2 guests