http://forums.ogre3d.org/viewtopic.php?f=2&t=93553
http://forums.ogre3d.org/viewtopic.php?f=1&t=93145
http://www.ogre3d.org/tikiwiki/OgreAssi ... ture=Tools
I found OgreAssimpConverter very useful, and I decided to start from it and give a try for OGRE v2.1 mesh.
Currently my codes only work for static mesh (vertex buffer + index buffer).
But I have encountered problems with created mesh coming with glitches (broken triangles, and not everytime!).
It seems the index buffer I created may have some bugs to let this bug happen.
But now I just can't find where the bug is (I also still can't fully understand how to create/access OGRE_SIMD_MALLOC buffers).
So wanna anyone can help view/debug my codes, any helps are really appreciated.
Here is one successful asset case.
https://imgur.com/a/QwqV7
Here is asset with glitches case.
https://imgur.com/a/DXpa8
My test sample is using Assimp library (v3.3.1). I modify Sample_V2Mesh project for my quick test.
Test file is one STL file.
And I posted codes here, cause I have not upload them onto internet yet. Not sure if its a good idea to post too much codes here..
(codes about the mesh and submeshes are generated)
Code: Select all
bool AssimpLoader::genSubMeshV2(const Ogre::String& name, int index, const aiNode* node, const aiMesh* mesh,
const aiMaterial* mat, Ogre::MeshPtr pmeshv2)
{
// if animated all submeshes must have bone weights
if (mBonesByName.size() && !mesh->HasBones())
{
if (!mQuietMode)
{
Ogre::LogManager::getSingleton().logMessage("Skipping Mesh " + Ogre::String(mesh->mName.data) + "with no bone weights");
}
return false;
}
// TODO: Material for v1::Mesh conversion still have problems now.
/*
Ogre::MaterialPtr matptr;
if((mLoaderParams & LP_GENERATE_MATERIALS_AS_CODE) == 0)
{
matptr = createMaterial(mesh->mMaterialIndex, mat, dir);
}
else
{
matptr = createMaterialByScript(mesh->mMaterialIndex, mat);
}
*/
Ogre::VaoManager *vaoManager = Ogre::Root::getSingleton().getRenderSystem()->getVaoManager();
// create vertex buffer
unsigned short numreal = 3;
unsigned short posBytes = 0, normBytes = 0, uvBytes = 0, colBytes = 0;
posBytes = sizeof(Ogre::Real) * 3;
Ogre::VertexElement2Vec velements;
velements.push_back(Ogre::VertexElement2(Ogre::VET_FLOAT3, Ogre::VES_POSITION));
if (mesh->HasNormals())
{
normBytes = sizeof(Ogre::Real) * 3;
numreal += 3;
velements.push_back(Ogre::VertexElement2(Ogre::VET_FLOAT3, Ogre::VES_NORMAL));
}
if (mesh->HasTextureCoords(0)) // currently consider first uv only
{
uvBytes = sizeof(Ogre::Real) * 2;
numreal += 2;
velements.push_back(Ogre::VertexElement2(Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES));
}
if (mesh->HasVertexColors(0)) // assume first color set as diffuse color
{
// TODO: can it be uint32 (RGBA)?
colBytes = sizeof(Ogre::Real) * 3;
numreal += 3;
velements.push_back(Ogre::VertexElement2(Ogre::VET_FLOAT3, Ogre::VES_DIFFUSE));
}
Ogre::Real *vertexdata = reinterpret_cast<Ogre::Real *> (OGRE_MALLOC_SIMD(
sizeof(Ogre::Real) * numreal * mesh->mNumVertices, Ogre::MEMCATEGORY_GEOMETRY));
// fill vertexdata manually
// prime pointers to vertex related data
aiVector3D *vec = mesh->mVertices;
aiVector3D *norm = mesh->mNormals;
aiVector3D *uv = mesh->mTextureCoords[0];
aiColor4D *col = mesh->mColors[0];
Ogre::Aabb subAABB(Ogre::Vector3(vec[0].x, vec[0].y, vec[0].z), Ogre::Vector3::UNIT_SCALE);
#if defined _DEBUG && 0
Ogre::LogManager::getSingleton().logMessage(" = Parsed vertuces (positions):");
#endif
for (unsigned int i = 0, offset = 0; i < mesh->mNumVertices; ++i)
{
// position
memcpy(vertexdata + offset, &vec[i].x, posBytes);
//vertexdata[offset + 0] = vec[i].x;
//vertexdata[offset + 1] = vec[i].y;
//vertexdata[offset + 2] = vec[i].z;
offset += 3;
subAABB.merge(Ogre::Vector3(vec[i].x, vec[i].y, vec[i].z));
#if defined _DEBUG && 0
Ogre::LogManager::getSingleton().logMessage(Ogre::StringConverter::toString(i) + ": " +
Ogre::StringConverter::toString(vec[i].x) + ", " +
Ogre::StringConverter::toString(vec[i].y) + ", " +
Ogre::StringConverter::toString(vec[i].z));
#endif
// normal
if (mesh->HasNormals())
{
memcpy(vertexdata + offset, &norm[i].x, normBytes);
//vertexdata[offset + 0] = norm[i].x;
//vertexdata[offset + 1] = norm[i].y;
//vertexdata[offset + 2] = norm[i].z;
offset += 3;
}
// uv
if (mesh->HasTextureCoords(0))
{
memcpy(vertexdata + offset, &uv[i].x, uvBytes);
//vertexdata[offset + 0] = uv[i].x;
//vertexdata[offset + 1] = uv[i].y;
offset += 2;
}
// color
if (mesh->HasVertexColors(0))
{
memcpy(vertexdata + offset, &col[i].r, colBytes);
//vertex[offset + 0] = col[i].r;
//vertex[offset + 1] = col[i].g;
//vertex[offset + 2] = col[i].b;
offset += 3;
}
}
Ogre::VertexBufferPacked *vertexBuffer = 0;
try
{
//Create the actual vertex buffer.
vertexBuffer = vaoManager->createVertexBuffer(velements, mesh->mNumVertices,
Ogre::BT_IMMUTABLE,
vertexdata, false);
}
catch (Ogre::Exception &e)
{
// When keepAsShadow = true, the memory will be freed when the index buffer is destroyed.
// However if for some weird reason there is an exception raised, the memory will
// not be freed, so it is up to us to do so.
// The reasons for exceptions are very rare. But we're doing this for correctness.
OGRE_FREE_SIMD(vertexBuffer, Ogre::MEMCATEGORY_GEOMETRY);
vertexBuffer = 0;
throw e;
}
//We'll just use one vertex buffer source (multi-source not working yet)
Ogre::VertexBufferPackedVec vertexBuffers;
vertexBuffers.push_back(vertexBuffer);
// currently consider 16-bit indices array only
Ogre::uint16 * indexdata = reinterpret_cast<Ogre::uint16 *>(OGRE_MALLOC_SIMD(
sizeof(Ogre::uint16) * 3 * mesh->mNumFaces, Ogre::MEMCATEGORY_GEOMETRY));
// fill indexdata manually
#if defined _DEBUG && 0
Ogre::LogManager::getSingleton().logMessage(" = Parsed indices:");
#endif
for (unsigned int i = 0, offset = 0; i < mesh->mNumFaces; ++i)
{
indexdata[offset + 0] = (Ogre::uint16)mesh->mFaces[i].mIndices[0];
indexdata[offset + 1] = (Ogre::uint16)mesh->mFaces[i].mIndices[1];
indexdata[offset + 2] = (Ogre::uint16)mesh->mFaces[i].mIndices[2];
#if defined _DEBUG && 0
Ogre::LogManager::getSingleton().logMessage(Ogre::StringConverter::toString(i) + ": " +
Ogre::StringConverter::toString(mesh->mFaces[i].mIndices[0]) + ", " +
Ogre::StringConverter::toString(mesh->mFaces[i].mIndices[1]) + ", " +
Ogre::StringConverter::toString(mesh->mFaces[i].mIndices[2]));
#endif
offset += 3;
}
Ogre::IndexBufferPacked *indexBuffer = 0;
try
{
indexBuffer = vaoManager->createIndexBuffer(Ogre::IndexBufferPacked::IT_16BIT,
sizeof(Ogre::uint16) * 3 * mesh->mNumFaces,
Ogre::BT_IMMUTABLE,
indexdata, false);
}
catch (Ogre::Exception &e)
{
// When keepAsShadow = true, the memory will be freed when the index buffer is destroyed.
// However if for some weird reason there is an exception raised, the memory will
// not be freed, so it is up to us to do so.
// The reasons for exceptions are very rare. But we're doing this for correctness.
OGRE_FREE_SIMD(indexBuffer, Ogre::MEMCATEGORY_GEOMETRY);
indexBuffer = 0;
throw e;
}
Ogre::SubMesh * submesh = pmeshv2->createSubMesh(index);
Ogre::VertexArrayObject *vao = vaoManager->createVertexArrayObject(
vertexBuffers, indexBuffer, Ogre::OT_TRIANGLE_LIST);
//Each Vao pushed to the vector refers to an LOD level.
//Must be in sync with mesh->mLodValues & mesh->mNumLods if you use more than one level
submesh->mVao[Ogre::VpNormal].push_back(vao);
//Use the same geometry for shadow casting.
submesh->mVao[Ogre::VpShadow].push_back(vao);
// AABB
if (index > 0) // not first
{
subAABB.merge(_sV2mesh->getAabb());
}
pmeshv2->_setBounds(subAABB);
pmeshv2->_setBoundingSphereRadius(subAABB.getRadius());
return true;
}
EDIT: Complete codes on my github: https://github.com/riveranb/ogre-assimp
EDIT: Bug fixed.
Code: Select all
indexBuffer = vaoManager->createIndexBuffer(Ogre::IndexBufferPacked::IT_16BIT,
sizeof(Ogre::uint16) * 3 * mesh->mNumFaces,
Ogre::BT_IMMUTABLE,
indexdata, false);