Code: Select all
//! Finds groups of joined vertices
//! \param buffer: Mesh buffer to search
//! \param dp: accuracy in decimal places (for fast search)
//! \Return: Returns an array of pointers to arrays of 3d vectors
core::array< core::array<core::vector3df>* > findVertexGroups(scene::IMeshBuffer* buffer, s32 dp=1 )
{
core::array< core::array<core::vector3df>* > ret;
if (!buffer)
return ret;
core::array< core::array<u16>* > searchList;
core::array< core::vector3di > vertexPositions;
core::array< u16 > newIndices;
u16 i=0;
// add vertex positions as ints, for fast searching
vertexPositions.set_used(buffer->getVertexCount());
c8 *p = (c8*) buffer->getVertices();
u16 stride = buffer->getVertexPitch();
for (i=0; i < buffer->getVertexCount(); ++i)
{
video::S3DVertex *v = (video::S3DVertex*)p;
core::vector3di roundedPos( (s32)round(v->Pos.X * (f32)((dp+1)*10)),
(s32)round(v->Pos.Y * (f32)((dp+1)*10)),
(s32)round(v->Pos.Z * (f32)((dp+1)*10)));
vertexPositions[i] = roundedPos;
p += stride;
}
// make unique index list
u16 *ip = buffer->getIndices();
for (i=0; i < buffer->getIndexCount(); ++i)
{
core::vector3di vpos = vertexPositions[ ip[i] ];
s32 newIndex = vertexPositions.linear_reverse_search(vpos);
newIndices.push_back((u16)newIndex);
}
// loop through each triangle
for (i=0; i < buffer->getIndexCount(); i+=3)
{
s32 found = -1;
// loop through all groups
for (u16 j=0; j < searchList.size(); ++j)
{
if ( searchList[j]->linear_reverse_search(newIndices[i] ) != -1 ||
searchList[j]->linear_reverse_search(newIndices[i+1]) != -1 ||
searchList[j]->linear_reverse_search(newIndices[i+2]) != -1 )
{
if (found == -1)
{
// add to this group
searchList[j]->set_used(searchList[j]->size()+3);
(*searchList[j])[ searchList[j]->size()-3 ] = newIndices[i];
(*searchList[j])[ searchList[j]->size()-2 ] = newIndices[i+1];
(*searchList[j])[ searchList[j]->size()-1 ] = newIndices[i+2];
found = j;
}
else
{
// found in another group, merge groups
u16 s = searchList[j]->size();
searchList[j]->set_used(s + searchList[found]->size() + 3);
memcpy( (void*)(searchList[j]->pointer() + s),
(void*)(searchList[found]->pointer()),
(size_t)(sizeof(u16)*searchList[found]->size()));
searchList[found]->set_used(0);
(*searchList[j])[ searchList[j]->size()-3 ] = newIndices[i];
(*searchList[j])[ searchList[j]->size()-2 ] = newIndices[i+1];
(*searchList[j])[ searchList[j]->size()-1 ] = newIndices[i+2];
found = j;
}
}
}
if (found==-1)
{
// start a new group
u16 pos = searchList.size();
searchList.push_back( new core::array<u16>() );
searchList[pos]->set_used(buffer->getIndexCount()); // allocate them all for speed
searchList[pos]->set_used(3);
(*searchList[pos])[0] = newIndices[i ];
(*searchList[pos])[1] = newIndices[i+1];
(*searchList[pos])[2] = newIndices[i+2];
}
}
// build output position lists
for (u16 k=0; k < searchList.size(); ++k)
{
if (searchList[k]->size())
{
u16 pos = ret.size();
ret.push_back(new core::array<core::vector3df>);
ret[pos]->set_used(searchList[k]->size());
c8 *firstVertex = (c8*)buffer->getVertices();
for (u16 l = 0; l < searchList[k]->size(); ++l)
{
s32 max = searchList[k]->size();
u16 index = (*searchList[k])[l];
core::vector3df vec = ((video::S3DVertex*)(firstVertex + stride*index ))->Pos;
(*ret[pos])[l] = vec;
}
}
delete searchList[k];
searchList[k] = 0;
}
return ret;
}
and here's mr dwarf's mesh buffer, split in to several groups and sketched out with draw3dline.

Code: Select all
IAnimatedMesh* mesh = smgr->getMesh("../../media/dwarf.x");
core::array< core::array<core::vector3df>* > ret;
ret = findVertexGroups(mesh->getMesh(0)->getMeshBuffer(1), 1);
...
core::matrix4 m4;
video::SMaterial mat;
mat.Lighting = false;
driver->setMaterial(mat);
driver->setTransform(ETS_WORLD, m4);
for (u32 m=0; m<ret.size(); ++m)
{
u32 c = (255/ret.size())*m;
for (u32 n=0; n<ret[m]->size()-1; ++n)
{
driver->draw3DLine( (*ret[m])[n], (*ret[m])[n+1], video::SColor(c,c,c,c));
}
}