//! Creates/loads an animated mesh from the file. IAnimatedMesh* CSMFMeshFileLoader::createMesh(io::IReadFile* file) { // create empty mesh SMesh *mesh = new SMesh(); // load file u16 version; u8 flags; s32 limbCount; s32 i; io::BinaryFile::read(file, version); io::BinaryFile::read(file, flags); io::BinaryFile::read(file, limbCount); // load mesh data core::matrix4 identity; for (i=0; i < limbCount; ++i) loadLimb(file, mesh, identity); // recalculate buffer bounding boxes for (i=0; i < (s32)mesh->getMeshBufferCount(); ++i) mesh->getMeshBuffer(i)->recalculateBoundingBox(); mesh->recalculateBoundingBox(); SAnimatedMesh *am = new SAnimatedMesh(); am->addMesh(mesh); mesh->drop(); am->recalculateBoundingBox(); return am; }
void CSMFMeshFileLoader::loadLimb(io::IReadFile* file, SMesh* mesh, const core::matrix4 &parentTransformation) { core::matrix4 transformation; // limb transformation core::vector3df translate, rotate, scale; io::BinaryFile::read(file, translate); io::BinaryFile::read(file, rotate); io::BinaryFile::read(file, scale); transformation.setTranslation(translate); transformation.setRotationDegrees(rotate); transformation.setScale(scale); transformation = parentTransformation * transformation; core::stringc textureName, textureGroupName; // texture information io::BinaryFile::read(file, textureGroupName); io::BinaryFile::read(file, textureName); // attempt to load texture using known formats video::ITexture* texture = 0; const c8* extensions[] = {".jpg", ".png", ".tga", ".bmp", 0}; for (const c8 **ext = extensions; !texture && *ext; ++ext) { texture = getMeshTextureLoader() ? getMeshTextureLoader()->getTexture(textureName + *ext) : NULL; if (texture) { textureName = textureName + *ext; break; } } // find the correct mesh buffer u32 i; for (i=0; i<mesh->MeshBuffers.size(); ++i) if (mesh->MeshBuffers[i]->getMaterial().TextureLayer[0].Texture == texture) break; // create mesh buffer if none was found if (i == mesh->MeshBuffers.size()) { CMeshBuffer<video::S3DVertex>* mb = new CMeshBuffer<video::S3DVertex>(); mb->Material.TextureLayer[0].Texture = texture; // horribly hacky way to do this, maybe it's in the flags? if (core::hasFileExtension(textureName, "tga", "png")) mb->Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; else mb->Material.MaterialType = video::EMT_SOLID; mesh->MeshBuffers.push_back(mb); } CMeshBuffer<video::S3DVertex>* mb = (CMeshBuffer<video::S3DVertex>*)mesh->MeshBuffers[i]; u16 vertexCount, firstVertex = mb->getVertexCount(); io::BinaryFile::read(file, vertexCount); mb->Vertices.reallocate(mb->Vertices.size() + vertexCount); // add vertices and set positions for (i=0; i<vertexCount; ++i) { core::vector3df pos; io::BinaryFile::read(file, pos); transformation.transformVect(pos); video::S3DVertex vert; vert.Color = 0xFFFFFFFF; vert.Pos = pos; mb->Vertices.push_back(vert); } // set vertex normals for (i=0; i < vertexCount; ++i) { core::vector3df normal; io::BinaryFile::read(file, normal); transformation.rotateVect(normal); mb->Vertices[firstVertex + i].Normal = normal; } // set texture coordinates for (i=0; i < vertexCount; ++i) { core::vector2df tcoords; io::BinaryFile::read(file, tcoords); mb->Vertices[firstVertex + i].TCoords = tcoords; } // triangles u32 triangleCount; // vertexCount used as temporary io::BinaryFile::read(file, vertexCount); triangleCount=3*vertexCount; mb->Indices.reallocate(mb->Indices.size() + triangleCount); for (i=0; i < triangleCount; ++i) { u16 index; io::BinaryFile::read(file, index); mb->Indices.push_back(firstVertex + index); } // read limbs s32 limbCount; io::BinaryFile::read(file, limbCount); for (s32 l=0; l < limbCount; ++l) loadLimb(file, mesh, transformation); }