#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_MS3D_LOADER_
#include "IReadFile.h"
#include "os.h"
#include "CMS3DMeshFileLoader.h"
#include "CSkinnedMesh.h"
namespace irr
{
namespace scene
{
#ifdef _DEBUG
#define _IRR_DEBUG_MS3D_LOADER_
#endif
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
# pragma pack( push, packing )
# pragma pack( 1 )
# define PACK_STRUCT
#elif defined( __GNUC__ )
# define PACK_STRUCT __attribute__((packed))
#else
# error compiler not supported
#endif
namespace {
struct MS3DHeader
{
char ID[10];
int Version;
} PACK_STRUCT;
struct MS3DVertex
{
u8 Flags;
float Vertex[3];
char BoneID;
u8 RefCount;
} PACK_STRUCT;
struct MS3DTriangle
{
u16 Flags;
u16 VertexIndices[3];
float VertexNormals[3][3];
float S[3], T[3];
u8 SmoothingGroup;
u8 GroupIndex;
} PACK_STRUCT;
struct MS3DMaterial
{
char Name[32];
float Ambient[4];
float Diffuse[4];
float Specular[4];
float Emissive[4];
float Shininess;
float Transparency;
u8 Mode;
char Texture[128];
char Alphamap[128];
} PACK_STRUCT;
struct MS3DJoint
{
u8 Flags;
char Name[32];
char ParentName[32];
float Rotation[3];
float Translation[3];
u16 NumRotationKeyframes;
u16 NumTranslationKeyframes;
} PACK_STRUCT;
struct MS3DKeyframe
{
float Time;
float Parameter[3];
} PACK_STRUCT;
struct MS3DVertexWeights
{
char boneIds[3];
u8 weights[3];
} PACK_STRUCT;
}
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
# pragma pack( pop, packing )
#endif
#undef PACK_STRUCT
struct SGroup
{
core::stringc Name;
core::array<u16> VertexIds;
u16 MaterialIdx;
};
CMS3DMeshFileLoader::CMS3DMeshFileLoader(video::IVideoDriver *driver)
: Driver(driver), AnimatedMesh(0)
{
#ifdef _DEBUG
setDebugName("CMS3DMeshFileLoader");
#endif
}
bool CMS3DMeshFileLoader::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "ms3d" );
}
IAnimatedMesh* CMS3DMeshFileLoader::createMesh(io::IReadFile* file)
{
if (!file)
return 0;
AnimatedMesh = new CSkinnedMesh();
if ( load(file) )
{
AnimatedMesh->finalize();
}
else
{
AnimatedMesh->drop();
AnimatedMesh = 0;
}
return AnimatedMesh;
}
bool CMS3DMeshFileLoader::load(io::IReadFile* file)
{
if (!file)
return false;
const long fileSize = file->getSize();
u8* buffer = new u8[fileSize];
s32 read = file->read(buffer, fileSize);
if (read != fileSize)
{
delete [] buffer;
os::Printer::log("Could not read full file. Loading failed", file->getFileName(), ELL_ERROR);
return false;
}
const u8 *pPtr = (u8*)((void*)buffer);
MS3DHeader *pHeader = (MS3DHeader*)pPtr;
pPtr += sizeof(MS3DHeader);
if ( strncmp( pHeader->ID, "MS3D000000", 10 ) != 0 )
{
delete [] buffer;
os::Printer::log("Not a valid Milkshape3D Model File. Loading failed", file->getFileName(), ELL_ERROR);
return false;
}
#ifdef __BIG_ENDIAN__
pHeader->Version = os::Byteswap::byteswap(pHeader->Version);
#endif
if ( pHeader->Version < 3 || pHeader->Version > 4 )
{
delete [] buffer;
os::Printer::log("Only Milkshape3D version 3 and 4 (1.3 to 1.8) is supported. Loading failed", file->getFileName(), ELL_ERROR);
return false;
}
#ifdef _IRR_DEBUG_MS3D_LOADER_
os::Printer::log("Loaded header version", core::stringc(pHeader->Version).c_str());
#endif
u16 numVertices = *(u16*)pPtr;
#ifdef __BIG_ENDIAN__
numVertices = os::Byteswap::byteswap(numVertices);
#endif
#ifdef _IRR_DEBUG_MS3D_LOADER_
os::Printer::log("Load vertices", core::stringc(numVertices).c_str());
#endif
pPtr += sizeof(u16);
MS3DVertex *vertices = (MS3DVertex*)pPtr;
pPtr += sizeof(MS3DVertex) * numVertices;
if (pPtr > buffer+fileSize)
{
delete [] buffer;
os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR);
return false;
}
for (u16 tmp=0; tmp<numVertices; ++tmp)
{
#ifdef __BIG_ENDIAN__
vertices[tmp].Vertex[0] = os::Byteswap::byteswap(vertices[tmp].Vertex[0]);
vertices[tmp].Vertex[1] = os::Byteswap::byteswap(vertices[tmp].Vertex[1]);
vertices[tmp].Vertex[2] = -os::Byteswap::byteswap(vertices[tmp].Vertex[2]);
#else
vertices[tmp].Vertex[2] = -vertices[tmp].Vertex[2];
#endif
}
u16 numTriangles = *(u16*)pPtr;
#ifdef __BIG_ENDIAN__
numTriangles = os::Byteswap::byteswap(numTriangles);
#endif
#ifdef _IRR_DEBUG_MS3D_LOADER_
os::Printer::log("Load Triangles", core::stringc(numTriangles).c_str());
#endif
pPtr += sizeof(u16);
MS3DTriangle *triangles = (MS3DTriangle*)pPtr;
pPtr += sizeof(MS3DTriangle) * numTriangles;
if (pPtr > buffer+fileSize)
{
delete [] buffer;
os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR);
return false;
}
for (u16 tmp=0; tmp<numTriangles; ++tmp)
{
#ifdef __BIG_ENDIAN__
triangles[tmp].Flags = os::Byteswap::byteswap(triangles[tmp].Flags);
for (u16 j=0; j<3; ++j)
{
triangles[tmp].VertexIndices[j] = os::Byteswap::byteswap(triangles[tmp].VertexIndices[j]);
triangles[tmp].VertexNormals[j][0] = os::Byteswap::byteswap(triangles[tmp].VertexNormals[j][0]);
triangles[tmp].VertexNormals[j][1] = os::Byteswap::byteswap(triangles[tmp].VertexNormals[j][1]);
triangles[tmp].VertexNormals[j][2] = -os::Byteswap::byteswap(triangles[tmp].VertexNormals[j][2]);
triangles[tmp].S[j] = os::Byteswap::byteswap(triangles[tmp].S[j]);
triangles[tmp].T[j] = os::Byteswap::byteswap(triangles[tmp].T[j]);
}
#else
triangles[tmp].VertexNormals[0][2] = -triangles[tmp].VertexNormals[0][2];
triangles[tmp].VertexNormals[1][2] = -triangles[tmp].VertexNormals[1][2];
triangles[tmp].VertexNormals[2][2] = -triangles[tmp].VertexNormals[2][2];
#endif
}
u16 numGroups = *(u16*)pPtr;
#ifdef __BIG_ENDIAN__
numGroups = os::Byteswap::byteswap(numGroups);
#endif
#ifdef _IRR_DEBUG_MS3D_LOADER_
os::Printer::log("Load Groups", core::stringc(numGroups).c_str());
#endif
pPtr += sizeof(u16);
core::array<SGroup> groups;
groups.reallocate(numGroups);
u32 i;
for (i=0; i<numGroups; ++i)
{
groups.push_back(SGroup());
SGroup& grp = groups.getLast();
grp.Name = ((const c8*) pPtr) + 1;
pPtr += 33;
u16 triangleCount = *(u16*)pPtr;
#ifdef __BIG_ENDIAN__
triangleCount = os::Byteswap::byteswap(triangleCount);
#endif
pPtr += sizeof(u16);
grp.VertexIds.reallocate(triangleCount);
for (u16 j=0; j<triangleCount; ++j)
{
#ifdef __BIG_ENDIAN__
grp.VertexIds.push_back(os::Byteswap::byteswap(*(u16*)pPtr));
#else
grp.VertexIds.push_back(*(u16*)pPtr);
#endif
pPtr += sizeof (u16);
}
grp.MaterialIdx = *(u8*)pPtr;
if (grp.MaterialIdx == 255)
grp.MaterialIdx = 0;
pPtr += sizeof(c8);
if (pPtr > buffer+fileSize)
{
delete [] buffer;
os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR);
return false;
}
}
u16 numMaterials = *(u16*)pPtr;
#ifdef __BIG_ENDIAN__
numMaterials = os::Byteswap::byteswap(numMaterials);
#endif
#ifdef _IRR_DEBUG_MS3D_LOADER_
os::Printer::log("Load Materials", core::stringc(numMaterials).c_str());
#endif
pPtr += sizeof(u16);
if(numMaterials == 0)
{
AnimatedMesh->addMeshBuffer();
}
for (i=0; i<numMaterials; ++i)
{
MS3DMaterial *material = (MS3DMaterial*)pPtr;
#ifdef __BIG_ENDIAN__
for (u16 j=0; j<4; ++j)
material->Ambient[j] = os::Byteswap::byteswap(material->Ambient[j]);
for (u16 j=0; j<4; ++j)
material->Diffuse[j] = os::Byteswap::byteswap(material->Diffuse[j]);
for (u16 j=0; j<4; ++j)
material->Specular[j] = os::Byteswap::byteswap(material->Specular[j]);
for (u16 j=0; j<4; ++j)
material->Emissive[j] = os::Byteswap::byteswap(material->Emissive[j]);
material->Shininess = os::Byteswap::byteswap(material->Shininess);
material->Transparency = os::Byteswap::byteswap(material->Transparency);
#endif
pPtr += sizeof(MS3DMaterial);
if (pPtr > buffer+fileSize)
{
delete [] buffer;
os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR);
return false;
}
scene::SSkinMeshBuffer *tmpBuffer = AnimatedMesh->addMeshBuffer();
tmpBuffer->Material.MaterialType = video::EMT_SOLID;
tmpBuffer->Material.AmbientColor = video::SColorf(material->Ambient[0], material->Ambient[1], material->Ambient[2], material->Ambient[3]).toSColor ();
tmpBuffer->Material.DiffuseColor = video::SColorf(material->Diffuse[0], material->Diffuse[1], material->Diffuse[2], material->Diffuse[3]).toSColor ();
tmpBuffer->Material.EmissiveColor = video::SColorf(material->Emissive[0], material->Emissive[1], material->Emissive[2], material->Emissive[3]).toSColor ();
tmpBuffer->Material.SpecularColor = video::SColorf(material->Specular[0], material->Specular[1], material->Specular[2], material->Specular[3]).toSColor ();
tmpBuffer->Material.Shininess = material->Shininess;
core::stringc TexturePath(material->Texture);
if (TexturePath.trim()!="")
{
TexturePath=stripPathFromString(file->getFileName(),true) + stripPathFromString(TexturePath,false);
tmpBuffer->Material.setTexture(0, Driver->getTexture(TexturePath));
}
core::stringc AlphamapPath=(const c8*)material->Alphamap;
if (AlphamapPath.trim()!="")
{
AlphamapPath=stripPathFromString(file->getFileName(),true) + stripPathFromString(AlphamapPath,false);
tmpBuffer->Material.setTexture(2, Driver->getTexture(AlphamapPath));
}
}
f32 framesPerSecond = *(float*)pPtr;
#ifdef __BIG_ENDIAN__
framesPerSecond = os::Byteswap::byteswap(framesPerSecond);
#endif
#ifdef _IRR_DEBUG_MS3D_LOADER_
os::Printer::log("FPS", core::stringc(framesPerSecond).c_str());
#endif
pPtr += sizeof(float) * 2;
if (framesPerSecond<1.f)
framesPerSecond=1.f;
#ifdef __BIG_ENDIAN__
#endif
pPtr += sizeof(int);
u16 jointCount = *(u16*)pPtr;
#ifdef __BIG_ENDIAN__
jointCount = os::Byteswap::byteswap(jointCount);
#endif
#ifdef _IRR_DEBUG_MS3D_LOADER_
os::Printer::log("Joints", core::stringc(jointCount).c_str());
#endif
pPtr += sizeof(u16);
if (pPtr > buffer+fileSize)
{
delete [] buffer;
os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR);
return false;
}
core::array<core::stringc> parentNames;
parentNames.reallocate(jointCount);
for (i=0; i<jointCount; ++i)
{
u32 j;
MS3DJoint *pJoint = (MS3DJoint*)pPtr;
#ifdef __BIG_ENDIAN__
for (j=0; j<3; ++j)
pJoint->Rotation[j] = os::Byteswap::byteswap(pJoint->Rotation[j]);
for (j=0; j<3; ++j)
pJoint->Translation[j] = os::Byteswap::byteswap(pJoint->Translation[j]);
pJoint->NumRotationKeyframes= os::Byteswap::byteswap(pJoint->NumRotationKeyframes);
pJoint->NumTranslationKeyframes = os::Byteswap::byteswap(pJoint->NumTranslationKeyframes);
#endif
pPtr += sizeof(MS3DJoint);
if (pPtr > buffer+fileSize)
{
delete [] buffer;
os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR);
return false;
}
ISkinnedMesh::SJoint *jnt = AnimatedMesh->addJoint();
jnt->Name = pJoint->Name;
#ifdef _IRR_DEBUG_MS3D_LOADER_
os::Printer::log("Joint", jnt->Name.c_str());
os::Printer::log("Rotation keyframes", core::stringc(pJoint->NumRotationKeyframes).c_str());
os::Printer::log("Translation keyframes", core::stringc(pJoint->NumTranslationKeyframes).c_str());
#endif
jnt->LocalMatrix.makeIdentity();
jnt->LocalMatrix.setRotationRadians(
core::vector3df(pJoint->Rotation[0], pJoint->Rotation[1], pJoint->Rotation[2]) );
jnt->LocalMatrix[2]=-jnt->LocalMatrix[2];
jnt->LocalMatrix[6]=-jnt->LocalMatrix[6];
jnt->LocalMatrix[8]=-jnt->LocalMatrix[8];
jnt->LocalMatrix[9]=-jnt->LocalMatrix[9];
jnt->LocalMatrix.setTranslation(
core::vector3df(pJoint->Translation[0], pJoint->Translation[1], -pJoint->Translation[2]) );
jnt->Animatedposition.set(jnt->LocalMatrix.getTranslation());
jnt->Animatedrotation.set(jnt->LocalMatrix.getRotationDegrees());
parentNames.push_back( (c8*)pJoint->ParentName );
const u16 numRotationKeyframes = pJoint->NumRotationKeyframes;
for (j=0; j < numRotationKeyframes; ++j)
{
MS3DKeyframe* kf = (MS3DKeyframe*)pPtr;
#ifdef __BIG_ENDIAN__
kf->Time = os::Byteswap::byteswap(kf->Time);
for (u32 l=0; l<3; ++l)
kf->Parameter[l] = os::Byteswap::byteswap(kf->Parameter[l]);
#endif
pPtr += sizeof(MS3DKeyframe);
if (pPtr > buffer+fileSize)
{
delete [] buffer;
os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR);
return false;
}
ISkinnedMesh::SRotationKey *k=AnimatedMesh->addRotationKey(jnt);
k->frame = kf->Time * framesPerSecond-1;
core::matrix4 tmpMatrix;
tmpMatrix.setRotationRadians(
core::vector3df(kf->Parameter[0], kf->Parameter[1], kf->Parameter[2]) );
tmpMatrix[2]=-tmpMatrix[2];
tmpMatrix[6]=-tmpMatrix[6];
tmpMatrix[8]=-tmpMatrix[8];
tmpMatrix[9]=-tmpMatrix[9];
tmpMatrix=jnt->LocalMatrix*tmpMatrix;
k->rotation = core::quaternion(tmpMatrix);
}
const u16 numTranslationKeyframes = pJoint->NumTranslationKeyframes;
for (j=0; j<numTranslationKeyframes; ++j)
{
MS3DKeyframe* kf = (MS3DKeyframe*)pPtr;
#ifdef __BIG_ENDIAN__
kf->Time = os::Byteswap::byteswap(kf->Time);
for (u32 l=0; l<3; ++l)
kf->Parameter[l] = os::Byteswap::byteswap(kf->Parameter[l]);
#endif
pPtr += sizeof(MS3DKeyframe);
if (pPtr > buffer+fileSize)
{
delete [] buffer;
os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR);
return false;
}
ISkinnedMesh::SPositionKey *k=AnimatedMesh->addPositionKey(jnt);
k->frame = kf->Time * framesPerSecond-1;
k->position = core::vector3df
(kf->Parameter[0]+pJoint->Translation[0],
kf->Parameter[1]+pJoint->Translation[1],
-kf->Parameter[2]-pJoint->Translation[2]);
}
}
core::array<MS3DVertexWeights> vertexWeights;
f32 weightFactor=0;
if (jointCount && (pHeader->Version == 4) && (pPtr < buffer+fileSize))
{
s32 subVersion = *(s32*)pPtr;
#ifdef __BIG_ENDIAN__
subVersion = os::Byteswap::byteswap(subVersion);
#endif
pPtr += sizeof(s32);
for (u32 j=0; j<4; ++j)
{
#ifdef _IRR_DEBUG_MS3D_LOADER_
os::Printer::log("Skipping comment group", core::stringc(j+1).c_str());
#endif
u32 numComments = *(u32*)pPtr;
#ifdef __BIG_ENDIAN__
numComments = os::Byteswap::byteswap(numComments);
#endif
pPtr += sizeof(u32);
for (i=0; i<numComments; ++i)
{
if (j!=3)
pPtr += sizeof(s32);
s32 commentLength = *(s32*)pPtr;
#ifdef __BIG_ENDIAN__
commentLength = os::Byteswap::byteswap(commentLength);
#endif
pPtr += sizeof(s32);
pPtr += commentLength;
}
if (pPtr > buffer+fileSize)
{
delete [] buffer;
os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR);
return false;
}
}
if (pPtr < buffer+fileSize)
{
subVersion = *(s32*)pPtr;
#ifdef __BIG_ENDIAN__
subVersion = os::Byteswap::byteswap(subVersion);
#endif
if (subVersion==1)
weightFactor=1.f/255.f;
else
weightFactor=1.f/100.f;
pPtr += sizeof(s32);
#ifdef _IRR_DEBUG_MS3D_LOADER_
os::Printer::log("Reading vertex weights");
#endif
vertexWeights.reallocate(numVertices);
const char offset = (subVersion==1)?6:10;
for (i=0; i<numVertices; ++i)
{
vertexWeights.push_back(*(MS3DVertexWeights*)pPtr);
pPtr += offset;
}
if (pPtr > buffer+fileSize)
{
delete [] buffer;
os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR);
return false;
}
}
if (pPtr < buffer+fileSize)
{
subVersion = *(s32*)pPtr;
#ifdef __BIG_ENDIAN__
subVersion = os::Byteswap::byteswap(subVersion);
#endif
pPtr += sizeof(s32);
#ifdef _IRR_DEBUG_MS3D_LOADER_
os::Printer::log("Skip joint color");
#endif
pPtr += 3*sizeof(float)*jointCount;
if (pPtr > buffer+fileSize)
{
delete [] buffer;
os::Printer::log("Loading failed. Corrupted data found", file->getFileName(), ELL_ERROR);
return false;
}
}
if (pPtr < buffer+fileSize)
{
subVersion = *(s32*)pPtr;
#ifdef __BIG_ENDIAN__
subVersion = os::Byteswap::byteswap(subVersion);
#endif
pPtr += sizeof(s32);
#ifdef _IRR_DEBUG_MS3D_LOADER_
os::Printer::log("Skip model extra information");
#endif
}
}
for (u32 jointnum=0; jointnum<AnimatedMesh->getAllJoints().size(); ++jointnum)
{
for (u32 j2=0; j2<AnimatedMesh->getAllJoints().size(); ++j2)
{
if (jointnum != j2 && parentNames[jointnum] == AnimatedMesh->getAllJoints()[j2]->Name )
{
AnimatedMesh->getAllJoints()[j2]->Children.push_back(AnimatedMesh->getAllJoints()[jointnum]);
break;
}
}
}
video::S3DVertex v;
core::array<video::S3DVertex> *Vertices;
core::array<u16> Indices;
for (i=0; i<numTriangles; ++i)
{
u32 tmp = groups[triangles[i].GroupIndex].MaterialIdx;
Vertices = &AnimatedMesh->getMeshBuffers()[tmp]->Vertices_Standard;
for (s32 j = 2; j!=-1; --j)
{
const u32 vertidx = triangles[i].VertexIndices[j];
v.TCoords.X = triangles[i].S[j];
v.TCoords.Y = triangles[i].T[j];
v.Normal.X = triangles[i].VertexNormals[j][0];
v.Normal.Y = triangles[i].VertexNormals[j][1];
v.Normal.Z = triangles[i].VertexNormals[j][2];
if(triangles[i].GroupIndex < groups.size() &&
groups[triangles[i].GroupIndex].MaterialIdx < AnimatedMesh->getMeshBuffers().size())
v.Color = AnimatedMesh->getMeshBuffers()[groups[triangles[i].GroupIndex].MaterialIdx]->Material.DiffuseColor;
else
v.Color.set(255,255,255,255);
v.Pos.X = vertices[vertidx].Vertex[0];
v.Pos.Y = vertices[vertidx].Vertex[1];
v.Pos.Z = vertices[vertidx].Vertex[2];
s32 index = -1;
for (u32 iV = 0; iV < Vertices->size(); ++iV)
{
if (v == (*Vertices)[iV])
{
index = (s32)iV;
break;
}
}
if (index == -1)
{
index = Vertices->size();
const u32 matidx = groups[triangles[i].GroupIndex].MaterialIdx;
if (vertexWeights.size()==0)
{
const s32 boneid = vertices[vertidx].BoneID;
if ((u32)boneid < AnimatedMesh->getAllJoints().size())
{
ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]);
w->buffer_id = matidx;
w->strength = 1.0f;
w->vertex_id = index;
}
}
else if (jointCount)
{
f32 sum = 1.0f;
s32 boneid = vertices[vertidx].BoneID;
if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[0] != 0))
{
ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]);
w->buffer_id = matidx;
sum -= (w->strength = vertexWeights[vertidx].weights[0]*weightFactor);
w->vertex_id = index;
}
boneid = vertexWeights[vertidx].boneIds[0];
if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[1] != 0))
{
ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]);
w->buffer_id = matidx;
sum -= (w->strength = vertexWeights[vertidx].weights[1]*weightFactor);
w->vertex_id = index;
}
boneid = vertexWeights[vertidx].boneIds[1];
if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[2] != 0))
{
ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]);
w->buffer_id = matidx;
sum -= (w->strength = vertexWeights[vertidx].weights[2]*weightFactor);
w->vertex_id = index;
}
boneid = vertexWeights[vertidx].boneIds[2];
if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (sum > 0.f))
{
ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]);
w->buffer_id = matidx;
w->strength = sum;
w->vertex_id = index;
}
boneid = vertices[vertidx].BoneID;
if ((sum == 1.f) && ((u32)boneid < AnimatedMesh->getAllJoints().size()))
{
ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]);
w->buffer_id = matidx;
w->strength = 1.f;
w->vertex_id = index;
}
}
Vertices->push_back(v);
}
Indices.push_back(index);
}
}
s32 iIndex = -1;
for (i=0; i<groups.size(); ++i)
{
SGroup& grp = groups[i];
if (grp.MaterialIdx >= AnimatedMesh->getMeshBuffers().size())
grp.MaterialIdx = 0;
core::array<u16>& indices = AnimatedMesh->getMeshBuffers()[grp.MaterialIdx]->Indices;
for (u32 k=0; k < grp.VertexIds.size(); ++k)
for (u32 l=0; l<3; ++l)
indices.push_back(Indices[++iIndex]);
}
delete [] buffer;
return true;
}
core::stringc CMS3DMeshFileLoader::stripPathFromString(const core::stringc& inString, bool returnPath) const
{
s32 slashIndex=inString.findLast('/');
s32 backSlash=inString.findLast('\\');
if (backSlash>slashIndex) slashIndex=backSlash;
if (slashIndex==-1)
{
if (returnPath)
return core::stringc();
else
return inString;
}
if (returnPath)
return inString.subString(0, slashIndex + 1);
else
return inString.subString(slashIndex+1, inString.size() - (slashIndex+1));
}
}
}
#endif