Page 1 of 1
Breaking models into pieces
Posted: Sun Feb 12, 2006 1:20 pm
by Mike
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?
Posted: Sun Feb 12, 2006 1:26 pm
by RadBrad
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
![Very Happy :D](./images/smilies/icon_biggrin.gif)
Posted: Sun Feb 12, 2006 2:42 pm
by Guest
Or you could make them as two meshes in your modelling program that are loaded into irrlicht seperetly and positioned together until you need them to split.
Posted: Sun Feb 12, 2006 3:39 pm
by vermeer
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...
Posted: Sun Feb 12, 2006 3:53 pm
by Mike
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?
Posted: Sun Feb 12, 2006 4:00 pm
by bitplane
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
![Smile :)](./images/smilies/icon_smile.gif)
Posted: Sun Feb 12, 2006 4:04 pm
by bitplane
just missed your post there
![Wink ;)](./images/smilies/icon_wink.gif)
if you export your models as separate parts in your modeling program, or they use different textures, they should show as separate mesh buffers in irrlicht. dunno how to move mesh buffers around though, you might be best off making them completely separate objects.
Posted: Sun Feb 12, 2006 4:25 pm
by RadBrad
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.
Posted: Sun Feb 12, 2006 4:41 pm
by Mike
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?
Posted: Sun Feb 12, 2006 7:53 pm
by Eternl Knight
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
Posted: Mon Feb 13, 2006 12:23 am
by Mike
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?
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;
}
To make the splitting work I still have to delete the polygons rather than align on the plane.
Posted: Mon Feb 13, 2006 12:47 am
by Eternl Knight
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
Posted: Mon Feb 13, 2006 1:12 pm
by Mike
Here is code for splitting a mesh in two and retrieving those parts:
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;
}
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.