Commit c77b66a5 authored by hybrid's avatar hybrid

Support for Ogre skeletons. Animations are not correctly working, yet. Also...

Support for Ogre skeletons. Animations are not correctly working, yet. Also flipping mesh from right-handed to left-handed now, so expect some changes with loaded meshes.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2827 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 1aa52165
...@@ -31,6 +31,7 @@ namespace scene ...@@ -31,6 +31,7 @@ namespace scene
# error compiler not supported # error compiler not supported
#endif #endif
namespace {
// File header // File header
struct MS3DHeader struct MS3DHeader
{ {
...@@ -99,6 +100,8 @@ struct MS3DVertexWeights ...@@ -99,6 +100,8 @@ struct MS3DVertexWeights
u8 weights[3]; u8 weights[3];
} PACK_STRUCT; } PACK_STRUCT;
} // end namespace
// Default alignment // Default alignment
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) #if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
# pragma pack( pop, packing ) # pragma pack( pop, packing )
......
...@@ -27,6 +27,7 @@ namespace scene ...@@ -27,6 +27,7 @@ namespace scene
{ {
// Main Chunks // Main Chunks
COGRE_HEADER= 0x1000, COGRE_HEADER= 0x1000,
COGRE_SKELETON= 0x2000,
COGRE_MESH= 0x3000, COGRE_MESH= 0x3000,
// sub chunks of COGRE_MESH // sub chunks of COGRE_MESH
...@@ -39,6 +40,13 @@ namespace scene ...@@ -39,6 +40,13 @@ namespace scene
COGRE_MESH_SUBMESH_NAME_TABLE= 0xA000, COGRE_MESH_SUBMESH_NAME_TABLE= 0xA000,
COGRE_MESH_EDGE_LISTS= 0xB000, COGRE_MESH_EDGE_LISTS= 0xB000,
// sub chunks of COGRE_SKELETON
COGRE_BONE_PARENT= 0x3000,
COGRE_ANIMATION= 0x4000,
COGRE_ANIMATION_TRACK= 0x4100,
COGRE_ANIMATION_KEYFRAME= 0x4110,
COGRE_ANIMATION_LINK= 0x5000,
// sub chunks of COGRE_SUBMESH // sub chunks of COGRE_SUBMESH
COGRE_SUBMESH_OPERATION= 0x4010, COGRE_SUBMESH_OPERATION= 0x4010,
COGRE_SUBMESH_BONE_ASSIGNMENT= 0x4100, COGRE_SUBMESH_BONE_ASSIGNMENT= 0x4100,
...@@ -120,24 +128,35 @@ IAnimatedMesh* COgreMeshFileLoader::createMesh(io::IReadFile* file) ...@@ -120,24 +128,35 @@ IAnimatedMesh* COgreMeshFileLoader::createMesh(io::IReadFile* file)
CurrentlyLoadingFromPath = FileSystem->getFileDir(file->getFileName()); CurrentlyLoadingFromPath = FileSystem->getFileDir(file->getFileName());
loadMaterials(file); loadMaterials(file);
Mesh = new SMesh();
if (readChunk(file)) if (readChunk(file))
{ {
// success // delete data loaded from file
SAnimatedMesh* am = new SAnimatedMesh(); clearMeshes();
am->Type = EAMT_3DS;
if (Skeleton.Bones.size())
{
ISkinnedMesh* tmp = static_cast<CSkinnedMesh*>(Mesh);
static_cast<CSkinnedMesh*>(Mesh)->updateBoundingBox();
Skeleton.Animations.clear();
Skeleton.Bones.clear();
Mesh=0;
return tmp;
}
else
{
for (u32 i=0; i<Mesh->getMeshBufferCount(); ++i) for (u32 i=0; i<Mesh->getMeshBufferCount(); ++i)
((SMeshBuffer*)Mesh->getMeshBuffer(i))->recalculateBoundingBox(); ((SMeshBuffer*)Mesh->getMeshBuffer(i))->recalculateBoundingBox();
Mesh->recalculateBoundingBox(); ((SMesh*)Mesh)->recalculateBoundingBox();
SAnimatedMesh* am = new SAnimatedMesh();
am->Type = EAMT_3DS;
am->addMesh(Mesh); am->addMesh(Mesh);
am->recalculateBoundingBox(); am->recalculateBoundingBox();
Mesh->drop(); Mesh->drop();
Mesh = 0; Mesh = 0;
return am; return am;
} }
}
Mesh->drop(); Mesh->drop();
Mesh = 0; Mesh = 0;
...@@ -159,6 +178,10 @@ bool COgreMeshFileLoader::readChunk(io::IReadFile* file) ...@@ -159,6 +178,10 @@ bool COgreMeshFileLoader::readChunk(io::IReadFile* file)
{ {
Meshes.push_back(OgreMesh()); Meshes.push_back(OgreMesh());
readObjectChunk(file, data, Meshes.getLast()); readObjectChunk(file, data, Meshes.getLast());
if (Skeleton.Bones.size())
Mesh = new CSkinnedMesh();
else
Mesh = new SMesh();
composeObject(); composeObject();
} }
break; break;
...@@ -195,24 +218,40 @@ bool COgreMeshFileLoader::readObjectChunk(io::IReadFile* file, ChunkData& parent ...@@ -195,24 +218,40 @@ bool COgreMeshFileLoader::readObjectChunk(io::IReadFile* file, ChunkData& parent
break; break;
case COGRE_MESH_BOUNDS: case COGRE_MESH_BOUNDS:
{ {
#ifdef IRR_OGRE_LOADER_DEBUG
os::Printer::log("Read Mesh Bounds");
#endif
readVector(file, data, mesh.BBoxMinEdge); readVector(file, data, mesh.BBoxMinEdge);
readVector(file, data, mesh.BBoxMaxEdge); readVector(file, data, mesh.BBoxMaxEdge);
readFloat(file, data, &mesh.BBoxRadius); readFloat(file, data, &mesh.BBoxRadius);
} }
break; break;
case COGRE_SKELETON_LINK: case COGRE_SKELETON_LINK:
{
#ifdef IRR_OGRE_LOADER_DEBUG
os::Printer::log("Read Skeleton link");
#endif
core::stringc name;
readString(file, data, name);
loadSkeleton(file, name);
}
break;
case COGRE_BONE_ASSIGNMENT: case COGRE_BONE_ASSIGNMENT:
{
mesh.BoneAssignments.push_back(OgreBoneAssignment());
readInt(file, data, &mesh.BoneAssignments.getLast().VertexID);
readShort(file, data, &mesh.BoneAssignments.getLast().BoneID);
readFloat(file, data, &mesh.BoneAssignments.getLast().Weight);
}
break;
case COGRE_MESH_LOD: case COGRE_MESH_LOD:
case COGRE_MESH_SUBMESH_NAME_TABLE: case COGRE_MESH_SUBMESH_NAME_TABLE:
case COGRE_MESH_EDGE_LISTS: case COGRE_MESH_EDGE_LISTS:
default:
// ignore chunk // ignore chunk
file->seek(data.header.length-data.read, true); file->seek(data.header.length-data.read, true);
data.read += data.header.length-data.read; data.read += data.header.length-data.read;
break; break;
default:
parent.read=parent.header.length;
file->seek(-(long)sizeof(ChunkHeader), true);
return true;
} }
parent.read += data.read; parent.read += data.read;
} }
...@@ -359,9 +398,17 @@ bool COgreMeshFileLoader::readSubMesh(io::IReadFile* file, ChunkData& parent, Og ...@@ -359,9 +398,17 @@ bool COgreMeshFileLoader::readSubMesh(io::IReadFile* file, ChunkData& parent, Og
{ {
case COGRE_SUBMESH_OPERATION: case COGRE_SUBMESH_OPERATION:
readShort(file, data, &subMesh.Operation); readShort(file, data, &subMesh.Operation);
#ifdef IRR_OGRE_LOADER_DEBUG
os::Printer::log("Read Submesh Operation",core::stringc(subMesh.Operation));
#endif
if (subMesh.Operation != 4)
os::Printer::log("Primitive type != trilist not yet implemented", ELL_WARNING);
break; break;
case COGRE_SUBMESH_TEXTURE_ALIAS: case COGRE_SUBMESH_TEXTURE_ALIAS:
{ {
#ifdef IRR_OGRE_LOADER_DEBUG
os::Printer::log("Read Submesh Texture Alias");
#endif
core::stringc texture, alias; core::stringc texture, alias;
readString(file, data, texture); readString(file, data, texture);
readString(file, data, alias); readString(file, data, alias);
...@@ -369,9 +416,12 @@ bool COgreMeshFileLoader::readSubMesh(io::IReadFile* file, ChunkData& parent, Og ...@@ -369,9 +416,12 @@ bool COgreMeshFileLoader::readSubMesh(io::IReadFile* file, ChunkData& parent, Og
} }
break; break;
case COGRE_SUBMESH_BONE_ASSIGNMENT: case COGRE_SUBMESH_BONE_ASSIGNMENT:
// currently ignore chunk {
file->seek(data.header.length-data.read, true); subMesh.BoneAssignments.push_back(OgreBoneAssignment());
data.read += data.header.length-data.read; readInt(file, data, &subMesh.BoneAssignments.getLast().VertexID);
readShort(file, data, &subMesh.BoneAssignments.getLast().BoneID);
readFloat(file, data, &subMesh.BoneAssignments.getLast().Weight);
}
break; break;
default: default:
parent.read=parent.header.length; parent.read=parent.header.length;
...@@ -554,6 +604,91 @@ scene::SMeshBufferLightMap* COgreMeshFileLoader::composeMeshBufferLightMap(const ...@@ -554,6 +604,91 @@ scene::SMeshBufferLightMap* COgreMeshFileLoader::composeMeshBufferLightMap(const
} }
scene::IMeshBuffer* COgreMeshFileLoader::composeMeshBufferSkinned(scene::CSkinnedMesh& mesh, const core::array<s32>& indices, const OgreGeometry& geom)
{
scene::SSkinMeshBuffer *mb=mesh.addMeshBuffer();
if (NumUV>1)
{
mb->convertTo2TCoords();
mb->Vertices_2TCoords.set_used(geom.NumVertex);
}
else
mb->Vertices_Standard.set_used(geom.NumVertex);
u32 i;
mb->Indices.set_used(indices.size());
for (i=0; i<indices.size(); i+=3)
{
mb->Indices[i+0]=indices[i+2];
mb->Indices[i+1]=indices[i+1];
mb->Indices[i+2]=indices[i+0];
}
for (i=0; i<geom.Elements.size(); ++i)
{
if (geom.Elements[i].Semantic==1) //Pos
{
for (u32 j=0; j<geom.Buffers.size(); ++j)
{
if (geom.Elements[i].Source==geom.Buffers[j].BindIndex)
{
u32 eSize=geom.Buffers[j].VertexSize;
u32 ePos=geom.Elements[i].Offset;
for (s32 k=0; k<geom.NumVertex; ++k)
{
if (NumUV>1)
mb->Vertices_2TCoords[k].Color=mb->Material.DiffuseColor;
else
mb->Vertices_Standard[k].Color=mb->Material.DiffuseColor;
mb->getPosition(k).set(-geom.Buffers[j].Data[ePos],geom.Buffers[j].Data[ePos+1],geom.Buffers[j].Data[ePos+2]);
ePos += eSize;
}
}
}
}
if (geom.Elements[i].Semantic==4) //Normal
{
for (u32 j=0; j<geom.Buffers.size(); ++j)
{
if (geom.Elements[i].Source==geom.Buffers[j].BindIndex)
{
u32 eSize=geom.Buffers[j].VertexSize;
u32 ePos=geom.Elements[i].Offset;
for (s32 k=0; k<geom.NumVertex; ++k)
{
mb->getNormal(k).set(-geom.Buffers[j].Data[ePos],geom.Buffers[j].Data[ePos+1],geom.Buffers[j].Data[ePos+2]);
ePos += eSize;
}
}
}
}
if (geom.Elements[i].Semantic==7) //TexCoord
{
for (u32 j=0; j<geom.Buffers.size(); ++j)
{
if (geom.Elements[i].Source==geom.Buffers[j].BindIndex)
{
u32 eSize=geom.Buffers[j].VertexSize;
u32 ePos=geom.Elements[i].Offset;
for (s32 k=0; k<geom.NumVertex; ++k)
{
mb->getTCoords(k).set(geom.Buffers[j].Data[ePos], geom.Buffers[j].Data[ePos+1]);
if (NumUV>1)
mb->Vertices_2TCoords[k].TCoords2.set(geom.Buffers[j].Data[ePos+2], geom.Buffers[j].Data[ePos+3]);
ePos += eSize;
}
}
}
}
}
return mb;
}
void COgreMeshFileLoader::composeObject(void) void COgreMeshFileLoader::composeObject(void)
{ {
for (u32 i=0; i<Meshes.size(); ++i) for (u32 i=0; i<Meshes.size(); ++i)
...@@ -563,7 +698,11 @@ void COgreMeshFileLoader::composeObject(void) ...@@ -563,7 +698,11 @@ void COgreMeshFileLoader::composeObject(void)
IMeshBuffer* mb; IMeshBuffer* mb;
if (Meshes[i].SubMeshes[j].SharedVertices) if (Meshes[i].SubMeshes[j].SharedVertices)
{ {
if (NumUV < 2) if (Skeleton.Bones.size())
{
mb = composeMeshBufferSkinned(*(CSkinnedMesh*)Mesh, Meshes[i].SubMeshes[j].Indices, Meshes[i].Geometry);
}
else if (NumUV < 2)
{ {
mb = composeMeshBuffer(Meshes[i].SubMeshes[j].Indices, Meshes[i].Geometry); mb = composeMeshBuffer(Meshes[i].SubMeshes[j].Indices, Meshes[i].Geometry);
} }
...@@ -574,7 +713,11 @@ void COgreMeshFileLoader::composeObject(void) ...@@ -574,7 +713,11 @@ void COgreMeshFileLoader::composeObject(void)
} }
else else
{ {
if (NumUV < 2) if (Skeleton.Bones.size())
{
mb = composeMeshBufferSkinned(*(CSkinnedMesh*)Mesh, Meshes[i].SubMeshes[j].Indices, Meshes[i].SubMeshes[j].Geometry);
}
else if (NumUV < 2)
{ {
mb = composeMeshBuffer(Meshes[i].SubMeshes[j].Indices, Meshes[i].SubMeshes[j].Geometry); mb = composeMeshBuffer(Meshes[i].SubMeshes[j].Indices, Meshes[i].SubMeshes[j].Geometry);
} }
...@@ -587,11 +730,88 @@ void COgreMeshFileLoader::composeObject(void) ...@@ -587,11 +730,88 @@ void COgreMeshFileLoader::composeObject(void)
if (mb != 0) if (mb != 0)
{ {
composeMeshBufferMaterial(mb, Meshes[i].SubMeshes[j].Material); composeMeshBufferMaterial(mb, Meshes[i].SubMeshes[j].Material);
Mesh->addMeshBuffer(mb); if (!Skeleton.Bones.size())
{
((SMesh*)Mesh)->addMeshBuffer(mb);
mb->drop(); mb->drop();
} }
} }
} }
}
if (Skeleton.Bones.size())
{
CSkinnedMesh* m = (CSkinnedMesh*)Mesh;
// Create Joints
for (u32 i=0; i<Skeleton.Bones.size(); ++i)
{
ISkinnedMesh::SJoint* joint = m->addJoint();
joint->Name=Skeleton.Bones[i].Name;
joint->LocalMatrix = Skeleton.Bones[i].Orientation.getMatrix();
if (Skeleton.Bones[i].Scale != core::vector3df(1,1,1))
{
core::matrix4 scaleMatrix;
scaleMatrix.setScale( Skeleton.Bones[i].Scale );
joint->LocalMatrix *= scaleMatrix;
}
/*
joint->LocalMatrix[2]=-joint->LocalMatrix[2];
joint->LocalMatrix[6]=-joint->LocalMatrix[6];
joint->LocalMatrix[8]=-joint->LocalMatrix[8];
joint->LocalMatrix[9]=-joint->LocalMatrix[9];
*/
joint->LocalMatrix.setTranslation( Skeleton.Bones[i].Position );
}
// Joints hierarchy
core::array<bool> isRoot;
isRoot.set_used(Skeleton.Bones.size());
memset(isRoot.pointer(), true, Skeleton.Bones.size());
for (u32 i=0; i<Skeleton.Bones.size(); ++i)
{
if (Skeleton.Bones[i].Parent<m->getJointCount())
{
m->getAllJoints()[Skeleton.Bones[i].Parent]->Children.push_back(m->getAllJoints()[Skeleton.Bones[i].Handle]);
isRoot[Skeleton.Bones[i].Handle]=false;
}
}
// Weights
u32 bufCount=0;
for (u32 i=0; i<Meshes.size(); ++i)
{
for (u32 j=0; j<Meshes[i].SubMeshes.size(); ++j)
{
for (u32 k=0; k<Meshes[i].SubMeshes[j].BoneAssignments.size(); ++k)
{
ISkinnedMesh::SWeight* w = m->addWeight(m->getAllJoints()[Meshes[i].SubMeshes[j].BoneAssignments[k].BoneID]);
w->strength=Meshes[i].SubMeshes[j].BoneAssignments[k].Weight;
w->vertex_id=Meshes[i].SubMeshes[j].BoneAssignments[k].VertexID;
w->buffer_id=bufCount;
}
++bufCount;
}
}
#if 0
// currently not working correctly
for (u32 i=0; i<Skeleton.Animations.size(); ++i)
{
for (u32 j=0; j<Skeleton.Animations[i].Keyframes.size(); ++j)
{
ISkinnedMesh::SPositionKey* poskey = m->addPositionKey(m->getAllJoints()[Skeleton.Animations[i].Keyframes[j].BoneID]);
poskey->frame=Skeleton.Animations[i].Keyframes[j].Time;
poskey->position=Skeleton.Animations[i].Keyframes[j].Position;
ISkinnedMesh::SRotationKey* rotkey = m->addRotationKey(m->getAllJoints()[Skeleton.Animations[i].Keyframes[j].BoneID]);
rotkey->frame=Skeleton.Animations[i].Keyframes[j].Time;
rotkey->rotation=Skeleton.Animations[i].Keyframes[j].Orientation;
ISkinnedMesh::SScaleKey* scalekey = m->addScaleKey(m->getAllJoints()[Skeleton.Animations[i].Keyframes[j].BoneID]);
scalekey->frame=Skeleton.Animations[i].Keyframes[j].Time;
scalekey->scale=Skeleton.Animations[i].Keyframes[j].Scale;
}
}
#endif
m->finalize();
}
} }
...@@ -1007,7 +1227,6 @@ void COgreMeshFileLoader::readTechnique(io::IReadFile* file, OgreMaterial& mat) ...@@ -1007,7 +1227,6 @@ void COgreMeshFileLoader::readTechnique(io::IReadFile* file, OgreMaterial& mat)
} }
void COgreMeshFileLoader::loadMaterials(io::IReadFile* meshFile) void COgreMeshFileLoader::loadMaterials(io::IReadFile* meshFile)
{ {
#ifdef IRR_OGRE_LOADER_DEBUG #ifdef IRR_OGRE_LOADER_DEBUG
...@@ -1015,11 +1234,11 @@ void COgreMeshFileLoader::loadMaterials(io::IReadFile* meshFile) ...@@ -1015,11 +1234,11 @@ void COgreMeshFileLoader::loadMaterials(io::IReadFile* meshFile)
#endif #endif
core::stringc token = meshFile->getFileName(); core::stringc token = meshFile->getFileName();
io::path filename = token.subString(0, token.size()-4) + L"material"; io::path filename = token.subString(0, token.size()-4) + L"material";
io::IReadFile* file = FileSystem->createAndOpenFile(filename.c_str()); io::IReadFile* file = FileSystem->createAndOpenFile(filename);
if (!file) if (!file)
{ {
os::Printer::log("Could not load OGRE material", filename.c_str()); os::Printer::log("Could not load OGRE material", filename);
return; return;
} }
...@@ -1095,6 +1314,137 @@ void COgreMeshFileLoader::loadMaterials(io::IReadFile* meshFile) ...@@ -1095,6 +1314,137 @@ void COgreMeshFileLoader::loadMaterials(io::IReadFile* meshFile)
} }
bool COgreMeshFileLoader::loadSkeleton(io::IReadFile* meshFile, const core::stringc& name)
{
#ifdef IRR_OGRE_LOADER_DEBUG
os::Printer::log("Load Skeleton", name);
#endif
io::IReadFile* file = FileSystem->createAndOpenFile(name);
if (!file)
{
io::path filename = meshFile->getFileName().subString(0, meshFile->getFileName().size()-4) + L"skeleton";
file = FileSystem->createAndOpenFile(name);
if (!file)
{
os::Printer::log("Could not load matching skeleton", name);
return false;
}
}
s16 id;
file->read(&id, 2);
if (SwapEndian)
id = os::Byteswap::byteswap(id);
if (id != COGRE_HEADER)
{
file->drop();
return false;
}
core::stringc skeletonVersion;
ChunkData head;
readString(file, head, skeletonVersion);
if (skeletonVersion != "[Serializer_v1.10]")
{
file->drop();
return false;
}
u16 bone=0;
f32 animationTotal=0.f;
while(file->getPos() < file->getSize())
{
ChunkData data;
readChunkData(file, data);
switch(data.header.id)
{
case COGRE_SKELETON:
{
Skeleton.Bones.push_back(OgreBone());
OgreBone& bone = Skeleton.Bones.getLast();
readString(file, data, bone.Name);
readShort(file, data, &bone.Handle);
readVector(file, data, bone.Position);
readQuaternion(file, data, bone.Orientation);
#ifdef IRR_OGRE_LOADER_DEBUG
os::Printer::log("Bone", bone.Name+" ("+core::stringc(bone.Handle)+")");
// os::Printer::log("Position", core::stringc(bone.Position.X)+" "+core::stringc(bone.Position.Y)+" "+core::stringc(bone.Position.Z));
// os::Printer::log("Rotation quat", core::stringc(bone.Orientation.W)+" "+core::stringc(bone.Orientation.X)+" "+core::stringc(bone.Orientation.Y)+" "+core::stringc(bone.Orientation.Z));
// core::vector3df rot;
// bone.Orientation.toEuler(rot);
// rot *= core::RADTODEG;
// os::Printer::log("Rotation", core::stringc(rot.X)+" "+core::stringc(rot.Y)+" "+core::stringc(rot.Z));
#endif
if (data.read<(data.header.length-bone.Name.size()))
{
readVector(file, data, bone.Scale);
bone.Scale.X *= -1.f;
}
else
bone.Scale=core::vector3df(1,1,1);
bone.Parent=0xffff;
}
break;
case COGRE_BONE_PARENT:
{
u16 parent;
readShort(file, data, &bone);
readShort(file, data, &parent);
if (bone<Skeleton.Bones.size() && parent<Skeleton.Bones.size())
Skeleton.Bones[bone].Parent=parent;
}
break;
case COGRE_ANIMATION:
{
if (Skeleton.Animations.size())
animationTotal+=Skeleton.Animations.getLast().Length;
Skeleton.Animations.push_back(OgreAnimation());
OgreAnimation& anim = Skeleton.Animations.getLast();
readString(file, data, anim.Name);
readFloat(file, data, &anim.Length);
#ifdef IRR_OGRE_LOADER_DEBUG
os::Printer::log("Animation", anim.Name);
os::Printer::log("Length", core::stringc(anim.Length));
#endif
}
break;
case COGRE_ANIMATION_TRACK:
#ifdef IRR_OGRE_LOADER_DEBUG
// os::Printer::log("for Bone ", core::stringc(bone));
#endif
readShort(file, data, &bone); // store current bone
break;
case COGRE_ANIMATION_KEYFRAME:
{
Skeleton.Animations.getLast().Keyframes.push_back(OgreKeyframe());
OgreKeyframe& keyframe = Skeleton.Animations.getLast().Keyframes.getLast();
readFloat(file, data, &keyframe.Time);
keyframe.Time+=animationTotal;
readVector(file, data, keyframe.Position);
readQuaternion(file, data, keyframe.Orientation);
readVector(file, data, keyframe.Scale);
keyframe.Scale *= 1.f;
keyframe.BoneID=bone;
#ifdef IRR_OGRE_LOADER_DEBUG
// os::Printer::log("Keyframe time", core::stringc(keyframe.Time));
#endif
}
break;
case COGRE_ANIMATION_LINK:
#ifdef IRR_OGRE_LOADER_DEBUG
os::Printer::log("Animation link");
#endif
break;
default:
break;
}
}
file->drop();
return true;
}
void COgreMeshFileLoader::readChunkData(io::IReadFile* file, ChunkData& data) void COgreMeshFileLoader::readChunkData(io::IReadFile* file, ChunkData& data)
{ {
file->read(&data.header, sizeof(ChunkHeader)); file->read(&data.header, sizeof(ChunkHeader));
...@@ -1177,6 +1527,14 @@ void COgreMeshFileLoader::readVector(io::IReadFile* file, ChunkData& data, core: ...@@ -1177,6 +1527,14 @@ void COgreMeshFileLoader::readVector(io::IReadFile* file, ChunkData& data, core:
readFloat(file, data, &out.X); readFloat(file, data, &out.X);
readFloat(file, data, &out.Y); readFloat(file, data, &out.Y);
readFloat(file, data, &out.Z); readFloat(file, data, &out.Z);
out.X *= -1.f;
}
void COgreMeshFileLoader::readQuaternion(io::IReadFile* file, ChunkData& data, core::quaternion& out)
{
readVector(file, data, *((core::vector3df*)&out.X));
readFloat(file, data, &out.W);
} }
...@@ -1202,3 +1560,4 @@ void COgreMeshFileLoader::clearMeshes() ...@@ -1202,3 +1560,4 @@ void COgreMeshFileLoader::clearMeshes()
} // end namespace irr } // end namespace irr
#endif // _IRR_COMPILE_WITH_OGRE_LOADER_ #endif // _IRR_COMPILE_WITH_OGRE_LOADER_
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#include "SMeshBufferLightMap.h" #include "SMeshBufferLightMap.h"
#include "IMeshManipulator.h" #include "IMeshManipulator.h"
#include "matrix4.h" #include "matrix4.h"
#include "quaternion.h"
#include "CSkinnedMesh.h"
namespace irr namespace irr
{ {
...@@ -168,6 +170,13 @@ private: ...@@ -168,6 +170,13 @@ private:
core::stringc Alias; core::stringc Alias;
}; };
struct OgreBoneAssignment
{
s32 VertexID;
u16 BoneID;
f32 Weight;
};
struct OgreSubMesh struct OgreSubMesh
{ {
core::stringc Material; core::stringc Material;
...@@ -176,6 +185,7 @@ private: ...@@ -176,6 +185,7 @@ private:
OgreGeometry Geometry; OgreGeometry Geometry;
u16 Operation; u16 Operation;
core::array<OgreTextureAlias> TextureAliases; core::array<OgreTextureAlias> TextureAliases;
core::array<OgreBoneAssignment> BoneAssignments;
bool Indices32Bit; bool Indices32Bit;
}; };
...@@ -184,11 +194,44 @@ private: ...@@ -184,11 +194,44 @@ private:
bool SkeletalAnimation; bool SkeletalAnimation;
OgreGeometry Geometry; OgreGeometry Geometry;
core::array<OgreSubMesh> SubMeshes; core::array<OgreSubMesh> SubMeshes;
core::array<OgreBoneAssignment> BoneAssignments;
core::vector3df BBoxMinEdge; core::vector3df BBoxMinEdge;
core::vector3df BBoxMaxEdge; core::vector3df BBoxMaxEdge;
f32 BBoxRadius; f32 BBoxRadius;
}; };
struct OgreBone
{
core::stringc Name;
core::vector3df Position;
core::quaternion Orientation;
core::vector3df Scale;
u16 Handle;
u16 Parent;
};
struct OgreKeyframe
{
u16 BoneID;
f32 Time;
core::vector3df Position;
core::quaternion Orientation;
core::vector3df Scale;
};
struct OgreAnimation
{
core::stringc Name;
f32 Length;
core::array<OgreKeyframe> Keyframes;
};
struct OgreSkeleton
{
core::array<OgreBone> Bones;
core::array<OgreAnimation> Animations;
};
bool readChunk(io::IReadFile* file); bool readChunk(io::IReadFile* file);
bool readObjectChunk(io::IReadFile* file, ChunkData& parent, OgreMesh& mesh); bool readObjectChunk(io::IReadFile* file, ChunkData& parent, OgreMesh& mesh);
bool readGeometry(io::IReadFile* file, ChunkData& parent, OgreGeometry& geometry); bool readGeometry(io::IReadFile* file, ChunkData& parent, OgreGeometry& geometry);
...@@ -203,16 +246,19 @@ private: ...@@ -203,16 +246,19 @@ private:
void readShort(io::IReadFile* file, ChunkData& data, u16* out, u32 num=1); void readShort(io::IReadFile* file, ChunkData& data, u16* out, u32 num=1);
void readFloat(io::IReadFile* file, ChunkData& data, f32* out, u32 num=1); void readFloat(io::IReadFile* file, ChunkData& data, f32* out, u32 num=1);
void readVector(io::IReadFile* file, ChunkData& data, core::vector3df& out); void readVector(io::IReadFile* file, ChunkData& data, core::vector3df& out);
void readQuaternion(io::IReadFile* file, ChunkData& data, core::quaternion& out);
void composeMeshBufferMaterial(scene::IMeshBuffer* mb, const core::stringc& materialName); void composeMeshBufferMaterial(scene::IMeshBuffer* mb, const core::stringc& materialName);
scene::SMeshBuffer* composeMeshBuffer(const core::array<s32>& indices, const OgreGeometry& geom); scene::SMeshBuffer* composeMeshBuffer(const core::array<s32>& indices, const OgreGeometry& geom);
scene::SMeshBufferLightMap* composeMeshBufferLightMap(const core::array<s32>& indices, const OgreGeometry& geom); scene::SMeshBufferLightMap* composeMeshBufferLightMap(const core::array<s32>& indices, const OgreGeometry& geom);
scene::IMeshBuffer* composeMeshBufferSkinned(scene::CSkinnedMesh& mesh, const core::array<s32>& indices, const OgreGeometry& geom);
void composeObject(void); void composeObject(void);
bool readColor(io::IReadFile* meshFile, video::SColor& col); bool readColor(io::IReadFile* meshFile, video::SColor& col);
void getMaterialToken(io::IReadFile* file, core::stringc& token, bool noNewLine=false); void getMaterialToken(io::IReadFile* file, core::stringc& token, bool noNewLine=false);
void readTechnique(io::IReadFile* meshFile, OgreMaterial& mat); void readTechnique(io::IReadFile* meshFile, OgreMaterial& mat);
void readPass(io::IReadFile* file, OgreTechnique& technique); void readPass(io::IReadFile* file, OgreTechnique& technique);
void loadMaterials(io::IReadFile* file); void loadMaterials(io::IReadFile* file);
bool loadSkeleton(io::IReadFile* meshFile, const core::stringc& name);
core::stringc getTextureFileName(const core::stringc& texture, core::stringc& model); core::stringc getTextureFileName(const core::stringc& texture, core::stringc& model);
void clearMeshes(); void clearMeshes();
...@@ -225,8 +271,9 @@ private: ...@@ -225,8 +271,9 @@ private:
io::path CurrentlyLoadingFromPath; io::path CurrentlyLoadingFromPath;
core::array<OgreMaterial> Materials; core::array<OgreMaterial> Materials;
OgreSkeleton Skeleton;
SMesh* Mesh; IMesh* Mesh;
u32 NumUV; u32 NumUV;
}; };
......
...@@ -1448,12 +1448,6 @@ void CSkinnedMesh::calculateTangents( ...@@ -1448,12 +1448,6 @@ void CSkinnedMesh::calculateTangents(
} }
} // end namespace scene } // end namespace scene
} // end namespace irr } // end namespace irr
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment