Breaking models into pieces
Breaking models into pieces
I would like to break a mesh into pieces. For example I have a car model loaded from a file and I want to split it in two through the center (thus creating two models). Any thoughts on how could this be done in Irrlicht?
I'm not sure Irrlicht could do this, and if it could be done it wouldn't be easy. I've heard that the Newton Physics SDK can mess around with the polygons for meshes. If not the easier way to do it is in your modeler program have an animation within the file that starts at frame 5 onwards. During this animation have the car split in two there. Then in irrlicht when you want the car to split into two just have irrlicht play frames 5 to x. Simple
there are a pair of plugins in max...
But...can be done in any, ie, blender.
In wings3d, my loved modeler, I'd use the fast connect (kindda quick knife) and do some loopcuts. Tha is, draw a cut, and the select loop(L) , and..."loopcut".
There, visually the car is almost the same (try not to put the cut in middle of curved surfaces, the smooth normals cut is noticed) keeps as the whole car. Ok, now I export into blender or whatever...and do some repositioning of the pieces, even applying some rigid body physics, if the program has it, if not, I do my self just repositioning parts with autokey on... in several keys in time. Then export as "car explode anim" in the format needed... ¿3ds? ¿ms3d? Dunno.Maybe u'd even need an anim per piece. I have not experienced with multiple meshes anims...maybe Milkshape 3d software can help here.
lol...more and more I think there'd be a good think to have a full bridge Blender-->Irrlicht for all these matters...But man, what a task to make an exporter wearing all the Blender info...
But...can be done in any, ie, blender.
In wings3d, my loved modeler, I'd use the fast connect (kindda quick knife) and do some loopcuts. Tha is, draw a cut, and the select loop(L) , and..."loopcut".
There, visually the car is almost the same (try not to put the cut in middle of curved surfaces, the smooth normals cut is noticed) keeps as the whole car. Ok, now I export into blender or whatever...and do some repositioning of the pieces, even applying some rigid body physics, if the program has it, if not, I do my self just repositioning parts with autokey on... in several keys in time. Then export as "car explode anim" in the format needed... ¿3ds? ¿ms3d? Dunno.Maybe u'd even need an anim per piece. I have not experienced with multiple meshes anims...maybe Milkshape 3d software can help here.
lol...more and more I think there'd be a good think to have a full bridge Blender-->Irrlicht for all these matters...But man, what a task to make an exporter wearing all the Blender info...
Finally making games again!
http://www.konekogames.com
http://www.konekogames.com
Does anybody know a dynamic algorithm?
Anywau if I'd make breakable parts in a modeling program, could I store different meshes in lets say different frames? For example:
Frame 1 - engine
Frame 2 - tires
Frame 3 - back
Frame 4 - front
Frame 5 - windows
And then make a complete model out of these 5 frames. If something breaks, like the windows I would just make a model out of frames 1-4 without 5?
Anywau if I'd make breakable parts in a modeling program, could I store different meshes in lets say different frames? For example:
Frame 1 - engine
Frame 2 - tires
Frame 3 - back
Frame 4 - front
Frame 5 - windows
And then make a complete model out of these 5 frames. If something breaks, like the windows I would just make a model out of frames 1-4 without 5?
i think if you want to split the mesh up in realtime the hardest part will be clipping the triangles. The new software renderer clips triangles against the camera's frustrum (the old one didn't), the algorithm will be somewhere in CSoftwareDriver2.cpp (cliptohyperplane around line 380?)
It would be very cool to have splitting and exploding meshes
It would be very cool to have splitting and exploding meshes
I think bitplane may be onto something there. If you did each part as a seperate model and wrote a class that matched each part up you could have the car there. Then within that class have a function which would ungroup the meshes from parenting each other and then have them animated through Irrlicht to move away in different directions. Just a thought. The only problem with that though would be your polygon count might go up by 4-5 fold, which will make the program run slower.
I still think its a good idea having the car animated to blow up in your modeling program. Then all you have to do is tell Irrlicht when to play the frames. Simple. If you wanted each part to blow off individually based on where another object collides then maybe seperate mesh files are the way to go. Meh.
I still think its a good idea having the car animated to blow up in your modeling program. Then all you have to do is tell Irrlicht when to play the frames. Simple. If you wanted each part to blow off individually based on where another object collides then maybe seperate mesh files are the way to go. Meh.
Loading individual models is an easy solution but the problem is that it is a lot of work from the modellers part. And I don't know if you wouldn't have to align the parts manually, which is not nice.
As for bitplanes idea from cliptohyperplane:
This is a nice thing. From looking how it works I think it would be possible to crush models. So if a car hits a wall, you take the plane of the wall and squish the car using the algorithm. I just have to find out how to manipulate the mesh data, move around the vertices, maybe copy parts from one mesh buffer to another. Any tips on that?
As for bitplanes idea from cliptohyperplane:
This is a nice thing. From looking how it works I think it would be possible to crush models. So if a car hits a wall, you take the plane of the wall and squish the car using the algorithm. I just have to find out how to manipulate the mesh data, move around the vertices, maybe copy parts from one mesh buffer to another. Any tips on that?
-
- Posts: 313
- Joined: Tue Nov 01, 2005 5:01 am
Splitting models based on a plane is not too hard... As mentioned, there is code in the software rendering on how to "clip" triangles to a plane. You could modify that and instead of simply clip them, split them in two and add the new triangles to two new meshes (which mesh would depend on the side to of the plane they were on).
If you are after more complex CSG operations (i.e. not just splitting by plane), take a look onlinne for BSP CSG operations. This is how Red Faction did their GeoMod (although they also had to do alot of tweaking to make it decent performance wise).
--EK
If you are after more complex CSG operations (i.e. not just splitting by plane), take a look onlinne for BSP CSG operations. This is how Red Faction did their GeoMod (although they also had to do alot of tweaking to make it decent performance wise).
--EK
I got this piece of code working which crushes the mesh along a plane, like it would hit a wall or something. There is probably a memory leakage when I create an SMesh and SMeshBuffer, Irrlicht doesn't take care of that right?
To make the splitting work I still have to delete the polygons rather than align on the plane.
Code: Select all
IMesh* getCrushedMesh( IMesh* iMesh, plane3df plane )
{
SMesh* smesh = new SMesh;
S3DVertex vertex;
s32 i, j;
f32 bDotPlane;
vector3df vN;
plane.Normal.normalize();
// copy the mesh buffer to a smesh so we can manipulate it
for ( j=0; j < iMesh->getMeshBufferCount(); j++ )
{
SMeshBuffer* smeshbuf = new SMeshBuffer;
irr::scene::IMeshBuffer *pMeshBuffer = iMesh->getMeshBuffer(j);
s32 vcount = pMeshBuffer->getVertexCount();
irr::video::S3DVertex *currentVertex = (irr::video::S3DVertex*) pMeshBuffer->getVertices();
for ( i = 0; i < vcount; i++)
{
smeshbuf->Vertices.push_back( currentVertex[i] );
}
s32 icount = pMeshBuffer->getIndexCount();
u16 *currentIndex = (u16 *) pMeshBuffer->getIndices();
for ( i = 0; i < icount; i++)
{
smeshbuf->Indices.push_back( currentIndex[i] );
}
smeshbuf->Material = pMeshBuffer->getMaterial();
// clip the vertices to the plane
for ( i = 0; i < vcount; i++ )
{
if (plane.classifyPointRelation( smeshbuf->Vertices[i].Pos ) != ISREL3D_BACK )
{
vN = plane.Normal * plane.getDistanceTo( smeshbuf->Vertices[i].Pos );
smeshbuf->Vertices[i].Pos -= vN;
}
}
smesh->addMeshBuffer( smeshbuf );
}
return smesh;
}
-
- Posts: 313
- Joined: Tue Nov 01, 2005 5:01 am
That is correct. I suggest using the polygon clipping/splitting code in the software renderer (the new one).
There will be three cases you need to handle:
1. Triangle completely on side A of Plane: Put triangle into Mesh A
1. Triangle completely on side B of Plane: Put triangle into Mesh B
1. Triangle crossed Plane: Use the triangle splitting code to create multiple triangles and then test them as above.
So long as the calling function/object calls "drop" on the returned IMesh when it is finished with it - it should be OK... Though I think you may need to call drop on the MeshBuffer AFTER you have added it to the SMesh.
--EK
There will be three cases you need to handle:
1. Triangle completely on side A of Plane: Put triangle into Mesh A
1. Triangle completely on side B of Plane: Put triangle into Mesh B
1. Triangle crossed Plane: Use the triangle splitting code to create multiple triangles and then test them as above.
So long as the calling function/object calls "drop" on the returned IMesh when it is finished with it - it should be OK... Though I think you may need to call drop on the MeshBuffer AFTER you have added it to the SMesh.
--EK
Here is code for splitting a mesh in two and retrieving those parts:
I didn't expect it to work this good when I started writing this. It produces a really nice cut. Although it is not perfect because the vertices aren't aligned well on the plane (I use the plane normal). If the plane is not perpendicular or parallel to the model it makes the model on the cut look skewed. I don't have an idea right now how to fix it. Also the algorithm isn't optimized at all.
Code: Select all
// returns frontMesh
IMesh* getSlicedMesh( IMesh* sourceMesh, IMesh* &backMesh, plane3df plane )
{
SMesh* smesh = new SMesh;
SMesh* smesh2 = new SMesh;
irr::scene::IMeshBuffer *pMeshBuffer;
SMeshBuffer* smeshbuf;
SMeshBuffer* smeshbuf2;
S3DVertex vertex;
s32 i, j;
f32 bDotPlane, fDistSum;
vector3df vN;
// copy the mesh buffer to two smesh's so we can manipulate it
for ( j = 0; j < sourceMesh->getMeshBufferCount(); j++ )
{
smeshbuf = new SMeshBuffer;
smeshbuf2 = new SMeshBuffer;
pMeshBuffer = sourceMesh->getMeshBuffer(j);
// get vertices and clip them to the plane
s32 vcount = pMeshBuffer->getVertexCount();
irr::video::S3DVertex *currentVertex = (irr::video::S3DVertex*) pMeshBuffer->getVertices();
for ( i = 0; i < vcount; i++)
{
smeshbuf->Vertices.push_back( currentVertex[i] );
smeshbuf2->Vertices.push_back( currentVertex[i] );
vN = plane.Normal * plane.getDistanceTo( currentVertex[i].Pos );
if (plane.classifyPointRelation( currentVertex[i].Pos ) == ISREL3D_BACK )
{
smeshbuf->Vertices[i].Pos -= vN;
}
else
{
smeshbuf2->Vertices[i].Pos -= vN;
}
}
// get indices (send front polygons to front mesh and all to back mesh)
s32 icount = pMeshBuffer->getIndexCount();
u16 *currentIndex = (u16 *) pMeshBuffer->getIndices();
for ( i = 0; i < icount; i += 3)
{
if ( (plane.classifyPointRelation( currentVertex[currentIndex[i+0]].Pos ) == ISREL3D_BACK )
&&(plane.classifyPointRelation( currentVertex[currentIndex[i+1]].Pos ) == ISREL3D_BACK )
&&(plane.classifyPointRelation( currentVertex[currentIndex[i+2]].Pos ) == ISREL3D_BACK ) )
{
smeshbuf2->Indices.push_back( currentIndex[i+0] );
smeshbuf2->Indices.push_back( currentIndex[i+1] );
smeshbuf2->Indices.push_back( currentIndex[i+2] );
}
else
{
smeshbuf->Indices.push_back( currentIndex[i+0] );
smeshbuf->Indices.push_back( currentIndex[i+1] );
smeshbuf->Indices.push_back( currentIndex[i+2] );
smeshbuf2->Indices.push_back( currentIndex[i+0] );
smeshbuf2->Indices.push_back( currentIndex[i+1] );
smeshbuf2->Indices.push_back( currentIndex[i+2] );
}
}
// get materials
smeshbuf->Material = smeshbuf2->Material = pMeshBuffer->getMaterial();
// delete junk polygons aligned on the plane on the back mesh
for ( i = 0; i < smeshbuf2->Indices.size(); i += 3 )
{
fDistSum = plane.getDistanceTo( smeshbuf2->Vertices[smeshbuf2->Indices[i+0]].Pos )
+ plane.getDistanceTo( smeshbuf2->Vertices[smeshbuf2->Indices[i+1]].Pos ) + plane.getDistanceTo( smeshbuf2->Vertices[smeshbuf2->Indices[i+2]].Pos );
if ( fDistSum < 0.00001f )
{
smeshbuf2->Indices.erase( i, 3 );
if (i > 2)
i -= 3;
}
}
smesh->addMeshBuffer( smeshbuf );
smesh2->addMeshBuffer( smeshbuf2 );
smeshbuf->drop();
smeshbuf2->drop();
}
backMesh = smesh2;
return smesh;
}