* Read animation data from M2 files. No actual animation, just reading the data
* Cleaned up some of the texture handling (Render flags, Texture lookup), thx to bLuma for the heads-up * bounding boxes should now work as expected
This commit is contained in:
parent
ba6b918a69
commit
ebc0ea6ee2
130
src/Client/GUI/CBoneSceneNode.cpp
Executable file
130
src/Client/GUI/CBoneSceneNode.cpp
Executable file
@ -0,0 +1,130 @@
|
||||
// Copyright (C) 2002-2007 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
#include "irrlicht/irrlicht.h"
|
||||
|
||||
#include "CBoneSceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CBoneSceneNode::CBoneSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
u32 boneIndex, const c8* boneName)
|
||||
: IBoneSceneNode(parent, mgr, id), BoneIndex(boneIndex), BoneName(boneName),
|
||||
AnimationMode(EBAM_AUTOMATIC), SkinningSpace(EBSS_LOCAL)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CBoneSceneNode");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//! Returns the name of the bone
|
||||
const c8* CBoneSceneNode::getBoneName() const
|
||||
{
|
||||
return BoneName.c_str();
|
||||
}
|
||||
|
||||
|
||||
//! Returns the index of the bone
|
||||
u32 CBoneSceneNode::getBoneIndex() const
|
||||
{
|
||||
return BoneIndex;
|
||||
}
|
||||
|
||||
|
||||
//! Sets the animation mode of the bone. Returns true if successful.
|
||||
bool CBoneSceneNode::setAnimationMode(E_BONE_ANIMATION_MODE mode)
|
||||
{
|
||||
AnimationMode = mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the current animation mode of the bone
|
||||
E_BONE_ANIMATION_MODE CBoneSceneNode::getAnimationMode() const
|
||||
{
|
||||
return AnimationMode;
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& CBoneSceneNode::getBoundingBox() const
|
||||
{
|
||||
return Box;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
//! Returns the relative transformation of the scene node.
|
||||
core::matrix4 CBoneSceneNode::getRelativeTransformation() const
|
||||
{
|
||||
return core::matrix4(); // RelativeTransformation;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void CBoneSceneNode::OnAnimate(u32 timeMs)
|
||||
{
|
||||
if (IsVisible)
|
||||
{
|
||||
// animate this node with all animators
|
||||
|
||||
core::list<ISceneNodeAnimator*>::Iterator ait = Animators.begin();
|
||||
for (; ait != Animators.end(); ++ait)
|
||||
(*ait)->animateNode(this, timeMs);
|
||||
|
||||
// update absolute position
|
||||
//updateAbsolutePosition();
|
||||
|
||||
// perform the post render process on all children
|
||||
core::list<ISceneNode*>::Iterator it = Children.begin();
|
||||
for (; it != Children.end(); ++it)
|
||||
(*it)->OnAnimate(timeMs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBoneSceneNode::helper_updateAbsolutePositionOfAllChildren(ISceneNode *Node)
|
||||
{
|
||||
Node->updateAbsolutePosition();
|
||||
|
||||
core::list<ISceneNode*>::ConstIterator it = Node->getChildren().begin();
|
||||
for (; it != Node->getChildren().end(); ++it)
|
||||
{
|
||||
helper_updateAbsolutePositionOfAllChildren( (*it) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBoneSceneNode::updateAbsolutePositionOfAllChildren()
|
||||
{
|
||||
helper_updateAbsolutePositionOfAllChildren( this );
|
||||
}
|
||||
|
||||
|
||||
void CBoneSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
|
||||
{
|
||||
out->addInt("BoneIndex", BoneIndex);
|
||||
out->addString("BoneName", BoneName.c_str());
|
||||
out->addEnum("AnimationMode", AnimationMode, BoneAnimationModeNames);
|
||||
}
|
||||
|
||||
|
||||
void CBoneSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
|
||||
{
|
||||
BoneIndex = in->getAttributeAsInt("BoneIndex");
|
||||
BoneName = in->getAttributeAsString("BoneName");
|
||||
AnimationMode = (E_BONE_ANIMATION_MODE)in->getAttributeAsEnumeration("AnimationMode", BoneAnimationModeNames);
|
||||
// TODO: add/replace bone in parent with bone from mesh
|
||||
}
|
||||
|
||||
|
||||
} // namespace scene
|
||||
} // namespace irr
|
||||
|
||||
|
||||
84
src/Client/GUI/CBoneSceneNode.h
Executable file
84
src/Client/GUI/CBoneSceneNode.h
Executable file
@ -0,0 +1,84 @@
|
||||
// Copyright (C) 2002-2007 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_BONE_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_BONE_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
// Used with SkinnedMesh and IAnimatedMeshSceneNode, for boned meshes
|
||||
#include "irrlicht/irrlicht.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class CBoneSceneNode : public IBoneSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CBoneSceneNode(ISceneNode* parent, ISceneManager* mgr,
|
||||
s32 id=-1, u32 boneIndex=0, const c8* boneName=0);
|
||||
|
||||
//! Returns the name of the bone
|
||||
virtual const c8* getBoneName() const;
|
||||
|
||||
//! Returns the index of the bone
|
||||
virtual u32 getBoneIndex() const;
|
||||
|
||||
//! Sets the animation mode of the bone. Returns true if successful.
|
||||
virtual bool setAnimationMode(E_BONE_ANIMATION_MODE mode);
|
||||
|
||||
//! Gets the current animation mode of the bone
|
||||
virtual E_BONE_ANIMATION_MODE getAnimationMode() const;
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
|
||||
/*
|
||||
//! Returns the relative transformation of the scene node.
|
||||
//virtual core::matrix4 getRelativeTransformation() const;
|
||||
*/
|
||||
|
||||
virtual void OnAnimate(u32 timeMs);
|
||||
|
||||
virtual void updateAbsolutePositionOfAllChildren();
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
|
||||
|
||||
//! How the relative transformation of the bone is used
|
||||
virtual void setSkinningSpace( E_BONE_SKINNING_SPACE space )
|
||||
{
|
||||
SkinningSpace=space;
|
||||
}
|
||||
|
||||
virtual E_BONE_SKINNING_SPACE getSkinningSpace() const
|
||||
{
|
||||
return SkinningSpace;
|
||||
}
|
||||
|
||||
private:
|
||||
void helper_updateAbsolutePositionOfAllChildren(ISceneNode *Node);
|
||||
|
||||
u32 BoneIndex;
|
||||
core::stringc BoneName;
|
||||
|
||||
core::aabbox3d<f32> Box;
|
||||
|
||||
E_BONE_ANIMATION_MODE AnimationMode;
|
||||
E_BONE_SKINNING_SPACE SkinningSpace;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,7 +1,32 @@
|
||||
#include <iostream>
|
||||
#include "CM2MeshFileLoader.h"
|
||||
#include "SSkinnedMesh.h"
|
||||
#define _DEBUG
|
||||
#include "common.h"
|
||||
#ifdef _DEBUG
|
||||
#define DEBUG(code) code;
|
||||
#else
|
||||
#define DEBUG(code) ;
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
void logdebug(const char *str, ...)
|
||||
{
|
||||
if(!str)
|
||||
return;
|
||||
va_list ap;
|
||||
// _log_setcolor(true,LBLUE);
|
||||
va_start(ap, str);
|
||||
vprintf( str, ap );
|
||||
va_end(ap);
|
||||
// _log_resetcolor(true);
|
||||
|
||||
|
||||
printf("\n");
|
||||
|
||||
fflush(stdout);
|
||||
}*/
|
||||
|
||||
namespace irr
|
||||
{
|
||||
@ -32,14 +57,31 @@ bool CM2MeshFileLoader::isALoadableFileExtension(const c8* filename)const
|
||||
//! See IUnknown::drop() for more information.
|
||||
IAnimatedMesh* CM2MeshFileLoader::createMesh(io::IReadFile* file)
|
||||
{
|
||||
ILogger* logger =Device->getLogger();
|
||||
if(!file)
|
||||
return 0;
|
||||
MeshFile = file;
|
||||
AnimatedMesh = new scene::CSkinnedMesh();
|
||||
|
||||
DEBUG(logger->log("Trying to open file",file->getFileName(),ELL_INFORMATION));
|
||||
if ( load() )
|
||||
{
|
||||
AnimatedMesh->finalize();
|
||||
}
|
||||
else
|
||||
{
|
||||
AnimatedMesh->drop();
|
||||
AnimatedMesh = 0;
|
||||
}
|
||||
|
||||
return AnimatedMesh;
|
||||
}
|
||||
bool CM2MeshFileLoader::load()
|
||||
{
|
||||
DEBUG(logdebug("Trying to open file %s",MeshFile->getFileName()));
|
||||
|
||||
|
||||
file->read(&header,sizeof(ModelHeader));
|
||||
if (header.version[0] != 4 && header.version[1] != 1 && header.version[2] != 0 && header.version[3] != 0) {
|
||||
logger->log("Something wrong!",ELL_ERROR);
|
||||
MeshFile->read(&header,sizeof(ModelHeader));
|
||||
if (header.version[0] != 4 && header.version[1] != 1 && header.version[2] != 0 && header.version[3] != 0) {
|
||||
printf("Wrong header! File version doesn't match or file is not a M2 file.");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
@ -60,11 +102,19 @@ if(!M2MVertices.empty())
|
||||
M2MVertices.clear();
|
||||
|
||||
ModelVertex tempM2MVert;
|
||||
file->seek(header.ofsVertices);
|
||||
f32 tempYZ;
|
||||
MeshFile->seek(header.ofsVertices);
|
||||
|
||||
for(u32 i =0;i<header.nVertices;i++)
|
||||
{
|
||||
file->read(&tempM2MVert,sizeof(ModelVertex));
|
||||
MeshFile->read(&tempM2MVert,sizeof(ModelVertex));
|
||||
tempYZ = tempM2MVert.pos.Y;
|
||||
tempM2MVert.pos.Y=tempM2MVert.pos.Z;
|
||||
tempM2MVert.pos.Z=tempYZ;
|
||||
tempYZ = tempM2MVert.normal.Y;
|
||||
tempM2MVert.normal.Y=tempM2MVert.normal.Z;
|
||||
tempM2MVert.normal.Z=tempYZ;
|
||||
|
||||
M2MVertices.push_back(tempM2MVert);
|
||||
}
|
||||
DEBUG(logdebug("Read %u/%u Vertices",M2MVertices.size(),header.nVertices));
|
||||
@ -73,10 +123,10 @@ DEBUG(logdebug("Read %u/%u Vertices",M2MVertices.size(),header.nVertices));
|
||||
if(M2MViews.size()>0)
|
||||
M2MViews.clear();
|
||||
ModelView tempM2MView;
|
||||
file->seek(header.ofsViews);
|
||||
MeshFile->seek(header.ofsViews);
|
||||
for(u32 i =0;i<header.nViews;i++)
|
||||
{
|
||||
file->read(&tempM2MView,sizeof(ModelView));
|
||||
MeshFile->read(&tempM2MView,sizeof(ModelView));
|
||||
M2MViews.push_back(tempM2MView);
|
||||
}
|
||||
//std::cout << "Read "<<M2MViews.size()<<"/"<<header.nViews<<" Views\n";
|
||||
@ -89,10 +139,10 @@ if(M2MIndices.size()>0)
|
||||
M2MIndices.clear();
|
||||
|
||||
u16 tempM2Index;
|
||||
file->seek(M2MViews[0].ofsIndex);
|
||||
MeshFile->seek(M2MViews[0].ofsIndex);
|
||||
for(u32 i =0;i<M2MViews[0].nIndex;i++)
|
||||
{
|
||||
file->read(&tempM2Index,sizeof(u16));
|
||||
MeshFile->read(&tempM2Index,sizeof(u16));
|
||||
M2MIndices.push_back(tempM2Index);
|
||||
}
|
||||
DEBUG(logdebug("Read %u/%u Indices",M2MIndices.size(),M2MViews[0].nIndex));
|
||||
@ -103,10 +153,10 @@ if(M2MTriangles.size()>0)
|
||||
M2MTriangles.clear();
|
||||
|
||||
u16 tempM2Triangle;
|
||||
file->seek(M2MViews[0].ofsTris);
|
||||
MeshFile->seek(M2MViews[0].ofsTris);
|
||||
for(u32 i =0;i<M2MViews[0].nTris;i++)
|
||||
{
|
||||
file->read(&tempM2Triangle,sizeof(u16));
|
||||
MeshFile->read(&tempM2Triangle,sizeof(u16));
|
||||
M2MTriangles.push_back(tempM2Triangle);
|
||||
}
|
||||
DEBUG(logdebug("Read %u/%u Triangles",M2MTriangles.size(),M2MViews[0].nTris));
|
||||
@ -115,10 +165,10 @@ if(M2MSubmeshes.size()>0)
|
||||
M2MSubmeshes.clear();
|
||||
|
||||
ModelViewSubmesh tempM2Submesh;
|
||||
file->seek(M2MViews[0].ofsSub);
|
||||
MeshFile->seek(M2MViews[0].ofsSub);
|
||||
for(u32 i =0;i<M2MViews[0].nSub;i++)
|
||||
{
|
||||
file->read(&tempM2Submesh,sizeof(ModelViewSubmesh));
|
||||
MeshFile->read(&tempM2Submesh,sizeof(ModelViewSubmesh));
|
||||
M2MSubmeshes.push_back(tempM2Submesh);
|
||||
// std::cout<< "Submesh " <<i<<" ID "<<tempM2Submesh.meshpartId<<" starts at V/T "<<tempM2Submesh.ofsVertex<<"/"<<tempM2Submesh.ofsTris<<" and has "<<tempM2Submesh.nVertex<<"/"<<tempM2Submesh.nTris<<" V/T\n";
|
||||
}
|
||||
@ -130,11 +180,12 @@ if(!M2MTextureUnit.empty())
|
||||
{
|
||||
M2MTextureUnit.clear();
|
||||
}
|
||||
file->seek(M2MViews[0].ofsTex);
|
||||
MeshFile->seek(M2MViews[0].ofsTex);
|
||||
for(u32 i=0;i<M2MViews[0].nTex;i++)
|
||||
{
|
||||
file->read(&tempM2TexUnit,sizeof(TextureUnit));
|
||||
MeshFile->read(&tempM2TexUnit,sizeof(TextureUnit));
|
||||
M2MTextureUnit.push_back(tempM2TexUnit);
|
||||
DEBUG(logdebug(" TexUnit %u: Submesh: %u %u Render Flag: %u TextureUnitNumber: %u %u TTU: %u",i,tempM2TexUnit.submeshIndex1,tempM2TexUnit.submeshIndex2, tempM2TexUnit.renderFlagsIndex, tempM2TexUnit.TextureUnitNumber, tempM2TexUnit.TextureUnitNumber2 ,tempM2TexUnit.textureIndex));
|
||||
}
|
||||
DEBUG(logdebug("Read %u Texture Unit entries for View 0",M2MTextureUnit.size()));
|
||||
|
||||
@ -147,11 +198,12 @@ if(!M2MTextureLookup.empty())
|
||||
{
|
||||
M2MTextureLookup.clear();
|
||||
}
|
||||
file->seek(header.ofsTexLookup);
|
||||
MeshFile->seek(header.ofsTexLookup);
|
||||
for(u32 i=0;i<header.nTexLookup;i++)
|
||||
{
|
||||
file->read(&tempM2TexLookup,sizeof(u16));
|
||||
MeshFile->read(&tempM2TexLookup,sizeof(u16));
|
||||
M2MTextureLookup.push_back(tempM2TexLookup);
|
||||
printf("Texture %u Type %u\n",i,tempM2TexLookup);
|
||||
}
|
||||
DEBUG(logdebug("Read %u Texture lookup entries",M2MTextureLookup.size()));
|
||||
|
||||
@ -161,11 +213,12 @@ if(!M2MTextureDef.empty())
|
||||
{
|
||||
M2MTextureDef.clear();
|
||||
}
|
||||
file->seek(header.ofsTextures);
|
||||
MeshFile->seek(header.ofsTextures);
|
||||
for(u32 i=0;i<header.nTextures;i++)
|
||||
{
|
||||
file->read(&tempM2TexDef,sizeof(TextureDefinition));
|
||||
MeshFile->read(&tempM2TexDef,sizeof(TextureDefinition));
|
||||
M2MTextureDef.push_back(tempM2TexDef);
|
||||
printf("Texture %u Type %u\n",i,tempM2TexDef.texType);
|
||||
}
|
||||
DEBUG(logdebug("Read %u Texture Definition entries",M2MTextureDef.size()));
|
||||
|
||||
@ -175,11 +228,12 @@ if(!M2MRenderFlags.empty())
|
||||
{
|
||||
M2MRenderFlags.clear();
|
||||
}
|
||||
file->seek(header.ofsTexFlags);
|
||||
MeshFile->seek(header.ofsTexFlags);
|
||||
for(u32 i=0;i<header.nTexFlags;i++)
|
||||
{
|
||||
file->read(&tempM2RF,sizeof(RenderFlags));
|
||||
MeshFile->read(&tempM2RF,sizeof(RenderFlags));
|
||||
M2MRenderFlags.push_back(tempM2RF);
|
||||
DEBUG(logdebug("Flag %u: (%u, %u)",i,tempM2RF.blending,tempM2RF.flags));
|
||||
}
|
||||
DEBUG(logdebug("Read %u Renderflags",M2MRenderFlags.size()));
|
||||
|
||||
@ -195,15 +249,218 @@ M2MTextureFiles.reallocate(M2MTextureDef.size());
|
||||
for(u32 i=0; i<M2MTextureDef.size(); i++)
|
||||
{
|
||||
tempTexFileName.reserve(M2MTextureDef[i].texFileLen + 1);
|
||||
file->seek(M2MTextureDef[i].texFileOfs);
|
||||
file->read((void*)tempTexFileName.c_str(),M2MTextureDef[i].texFileLen);
|
||||
MeshFile->seek(M2MTextureDef[i].texFileOfs);
|
||||
MeshFile->read((void*)tempTexFileName.c_str(),M2MTextureDef[i].texFileLen);
|
||||
M2MTextureFiles.push_back(tempTexFileName.c_str());
|
||||
DEBUG(logdebug("Texture: %u (%s)",M2MTextureFiles.size(),M2MTextureFiles[i].c_str()));
|
||||
}
|
||||
// std::cout << "Read "<<M2MTextureFiles.size()<<"/"<<M2MTextureDef.size()<<" Texture file names\n";
|
||||
|
||||
///////////////////////////////////////
|
||||
// Animation related stuff //
|
||||
///////////////////////////////////////
|
||||
|
||||
printf("Global Sequences: %u\n",header.nGlobalSequences);
|
||||
//Ignored at the moment, as wolf.m2 has none
|
||||
printf("Animations: %u\n",header.nAnimations);
|
||||
//Animations. This is global data
|
||||
Animation tempAnimation;
|
||||
if(!M2MAnimations.empty())
|
||||
{
|
||||
M2MAnimations.clear();
|
||||
}
|
||||
MeshFile->seek(header.ofsAnimations);
|
||||
for(u32 i=0;i<header.nAnimations;i++)
|
||||
{
|
||||
MeshFile->read(&tempAnimation,sizeof(Animation));
|
||||
M2MAnimations.push_back(tempAnimation);
|
||||
//std::cout<<tempAnimation.start<<" "<<tempAnimation.end<<"\n";
|
||||
}
|
||||
DEBUG(logdebug("Read %u Animations",M2MAnimations.size()));
|
||||
printf("Read %u Animations\n",M2MAnimations.size());
|
||||
|
||||
printf("Bones: %u\n",header.nBones);
|
||||
//Bones. This is global data
|
||||
Bone tempBone;
|
||||
if(!M2MBones.empty())
|
||||
{
|
||||
M2MBones.clear();
|
||||
}
|
||||
MeshFile->seek(header.ofsBones);
|
||||
for(u32 i=0;i<header.nBones;i++)
|
||||
{
|
||||
MeshFile->read(&tempBone,16);
|
||||
MeshFile->read(&tempBone.translation.header,sizeof(AnimBlockHead));
|
||||
MeshFile->read(&tempBone.rotation.header,sizeof(AnimBlockHead));
|
||||
MeshFile->read(&tempBone.scaling.header,sizeof(AnimBlockHead));
|
||||
MeshFile->read(&tempBone.PivotPoint,sizeof(core::vector3df));
|
||||
tempYZ=tempBone.PivotPoint.Y;
|
||||
tempBone.PivotPoint.Y=tempBone.PivotPoint.Z;
|
||||
tempBone.PivotPoint.Z=tempYZ;
|
||||
M2MBones.push_back(tempBone);
|
||||
//std::cout<<i<<":"<<tempBone.flags<<" "<<tempBone.parentBone<<" |"<<tempBone.translation.header.interpolationType<<" "<<tempBone.translation.header.nInterpolationRange<<" "<<tempBone.translation.header.nTimeStamp<<" "<<tempBone.translation.header.nValues<<"|"<<tempBone.rotation.header.interpolationType<<" "<<tempBone.rotation.header.nInterpolationRange<<" "<<tempBone.rotation.header.nTimeStamp<<" "<<tempBone.rotation.header.nValues<<"|"<<tempBone.scaling.header.interpolationType<<" "<<tempBone.scaling.header.nInterpolationRange<<" "<<tempBone.scaling.header.nTimeStamp<<" "<<tempBone.scaling.header.nValues<<"\n";
|
||||
}
|
||||
//Fill in values referenced in Bones. local to each bone
|
||||
InterpolationRange tempBoneIR;
|
||||
u32 tempBoneTS;
|
||||
float tempBoneValue;
|
||||
for(u32 i=0; i<M2MBones.size(); i++)
|
||||
{
|
||||
if(M2MBones[i].translation.header.nInterpolationRange>0)
|
||||
{
|
||||
MeshFile->seek(M2MBones[i].translation.header.ofsInterpolationRange);
|
||||
for(u32 j=0; j<M2MBones[i].translation.header.nInterpolationRange;j++)
|
||||
{
|
||||
MeshFile->read(&tempBoneIR, sizeof(InterpolationRange));
|
||||
M2MBones[i].translation.keyframes.push_back(tempBoneIR);
|
||||
}
|
||||
}
|
||||
if(M2MBones[i].rotation.header.nInterpolationRange>0)
|
||||
{
|
||||
MeshFile->seek(M2MBones[i].rotation.header.ofsInterpolationRange);
|
||||
for(u32 j=0; j<M2MBones[i].rotation.header.nInterpolationRange;j++)
|
||||
{
|
||||
MeshFile->read(&tempBoneIR, sizeof(InterpolationRange));
|
||||
M2MBones[i].rotation.keyframes.push_back(tempBoneIR);
|
||||
}
|
||||
}
|
||||
if(M2MBones[i].scaling.header.nInterpolationRange>0)
|
||||
{
|
||||
MeshFile->seek(M2MBones[i].scaling.header.ofsInterpolationRange);
|
||||
for(u32 j=0; j<M2MBones[i].scaling.header.nInterpolationRange;j++)
|
||||
{
|
||||
MeshFile->read(&tempBoneIR, sizeof(InterpolationRange));
|
||||
M2MBones[i].scaling.keyframes.push_back(tempBoneIR);
|
||||
}
|
||||
}
|
||||
|
||||
if(M2MBones[i].translation.header.nTimeStamp>0)
|
||||
{
|
||||
MeshFile->seek(M2MBones[i].translation.header.ofsTimeStamp);
|
||||
for(u32 j=0; j<M2MBones[i].translation.header.nTimeStamp;j++)
|
||||
{
|
||||
MeshFile->read(&tempBoneTS, sizeof(u32));
|
||||
M2MBones[i].translation.timestamps.push_back(tempBoneTS);
|
||||
}
|
||||
}
|
||||
if(M2MBones[i].rotation.header.nTimeStamp>0)
|
||||
{
|
||||
MeshFile->seek(M2MBones[i].rotation.header.ofsTimeStamp);
|
||||
for(u32 j=0; j<M2MBones[i].rotation.header.nTimeStamp;j++)
|
||||
{
|
||||
MeshFile->read(&tempBoneTS, sizeof(u32));
|
||||
M2MBones[i].rotation.timestamps.push_back(tempBoneTS);
|
||||
}
|
||||
}
|
||||
if(M2MBones[i].scaling.header.nTimeStamp>0)
|
||||
{
|
||||
MeshFile->seek(M2MBones[i].scaling.header.ofsTimeStamp);
|
||||
for(u32 j=0; j<M2MBones[i].scaling.header.nTimeStamp;j++)
|
||||
{
|
||||
MeshFile->read(&tempBoneTS, sizeof(u32));
|
||||
M2MBones[i].scaling.timestamps.push_back(tempBoneTS);
|
||||
}
|
||||
}
|
||||
if(M2MBones[i].translation.header.nValues>0)
|
||||
{
|
||||
MeshFile->seek(M2MBones[i].translation.header.ofsValues);
|
||||
for(u32 j=0; j<M2MBones[i].translation.header.nValues*3;j++)
|
||||
{
|
||||
MeshFile->read(&tempBoneValue, sizeof(float));
|
||||
M2MBones[i].translation.values.push_back(tempBoneValue);
|
||||
}
|
||||
}
|
||||
if(M2MBones[i].rotation.header.nValues>0)
|
||||
{
|
||||
MeshFile->seek(M2MBones[i].rotation.header.ofsValues);
|
||||
for(u32 j=0; j<M2MBones[i].rotation.header.nValues*4;j++)
|
||||
{
|
||||
s16 tempBoneShort;
|
||||
MeshFile->read(&tempBoneShort, sizeof(s16));
|
||||
tempBoneValue=(tempBoneShort>0?tempBoneShort-32767:tempBoneShort+32767)/32767.0f;
|
||||
M2MBones[i].rotation.values.push_back(tempBoneValue);
|
||||
}
|
||||
}
|
||||
if(M2MBones[i].scaling.header.nValues>0)
|
||||
{
|
||||
MeshFile->seek(M2MBones[i].scaling.header.ofsValues);
|
||||
for(u32 j=0; j<M2MBones[i].scaling.header.nValues*3;j++)
|
||||
{
|
||||
MeshFile->read(&tempBoneValue, sizeof(float));
|
||||
M2MBones[i].scaling.values.push_back(tempBoneValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG(logdebug("Read %u Bones",M2MBones.size()));
|
||||
|
||||
|
||||
scene::CSkinnedMesh::SJoint* Joint;
|
||||
for(u32 i=0;i<M2MBones.size();i++)
|
||||
{
|
||||
if(M2MBones[i].parentBone == -1)
|
||||
{
|
||||
ParentJoint=(scene::CSkinnedMesh::SJoint*)0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ParentJoint=AnimatedMesh->getAllJoints()[M2MBones[i].parentBone];
|
||||
}
|
||||
Joint=AnimatedMesh->createJoint(ParentJoint);
|
||||
|
||||
|
||||
//std::cout << i << " "<<Joint->GlobalMatrix.getTranslation().X<< " "<<Joint->GlobalMatrix.getTranslation().Y<< " "<<Joint->GlobalMatrix.getTranslation().Z<<'\n';
|
||||
//std::cout << i << " "<<M2MBones[i].PivotPoint.X<< " "<<M2MBones[i].PivotPoint.Y<< " "<<M2MBones[i].PivotPoint.Z<<'\n';
|
||||
|
||||
/* for(u32 j=0;j<M2MBones[i].translation.header.nValues;j++)
|
||||
{
|
||||
scene::CSkinnedMesh::SPositionKey* pos=AnimatedMesh->createPositionKey(Joint);
|
||||
pos->frame=M2MBones[i].translation.timestamps[j]*.01f;
|
||||
pos->position=core::vector3df(M2MBones[i].translation.values[j*3],M2MBones[i].translation.values[j*3+1],M2MBones[i].translation.values[j*3+2]);
|
||||
}
|
||||
if(M2MBones[i].rotation.header.nValues>0)
|
||||
{
|
||||
for(u32 j=0;j<M2MBones[i].rotation.header.nValues;j++)
|
||||
{
|
||||
scene::CSkinnedMesh::SRotationKey* rot=AnimatedMesh->createRotationKey(Joint);
|
||||
rot->frame=M2MBones[i].rotation.timestamps[j]*.01f;
|
||||
core::quaternion tempQ=core::quaternion(M2MBones[i].rotation.values[j*4+0],M2MBones[i].rotation.values[j*4+1],M2MBones[i].rotation.values[j*4+2],M2MBones[i].rotation.values[j*4+3]);
|
||||
rot->rotation=tempQ;
|
||||
// std::cout <<" "<< M2MBones[i].rotation.values[j*4+0] <<" "<< M2MBones[i].rotation.values[j*4+1] <<" "<< M2MBones[i].rotation.values[j*4+2] <<" "<< M2MBones[i].rotation.values[j*4+3] <<'\n';
|
||||
}
|
||||
}
|
||||
if(M2MBones[i].scaling.header.nValues>0){
|
||||
for(u32 j=0;j<M2MBones[i].scaling.header.nValues;j++)
|
||||
{
|
||||
scene::CSkinnedMesh::SScaleKey* scale=AnimatedMesh->createScaleKey(Joint);
|
||||
scale->frame=M2MBones[i].scaling.timestamps[j]*.01f;
|
||||
scale->scale=core::vector3df(M2MBones[i].scaling.values[j*3],M2MBones[i].scaling.values[j*3+1],M2MBones[i].scaling.values[j*3+2]);
|
||||
}
|
||||
*/
|
||||
// Joint->Animatedposition=M2MBones[i].PivotPoint;
|
||||
// std::cout<<Joint->Animatedposition.X<<' '<<Joint->Animatedposition.Y<<' '<<Joint->Animatedposition.Z<<' '<<'\n';
|
||||
|
||||
// Joint->Animatedscale=core::vector3df(1.0f,1.0f,1.0f);
|
||||
//Joint->Animatedrotation=core::quaternion(0.0f,0.0f,0.0f,0.0f);
|
||||
core::matrix4 positionMatrix;
|
||||
// positionMatrix.setTranslation( Joint->Animatedposition );
|
||||
core::matrix4 scaleMatrix;
|
||||
//scaleMatrix.setScale( Joint->Animatedscale );
|
||||
core::matrix4 rotationMatrix;// = Joint->Animatedrotation.getMatrix();
|
||||
|
||||
Joint->GlobalMatrix = positionMatrix * rotationMatrix * scaleMatrix;//
|
||||
|
||||
if (ParentJoint)
|
||||
{
|
||||
core::matrix4 InverseParentGlobal;
|
||||
ParentJoint->GlobalMatrix.getInverse(InverseParentGlobal);
|
||||
Joint->LocalMatrix = InverseParentGlobal * Joint->GlobalMatrix;
|
||||
}
|
||||
else
|
||||
Joint->LocalMatrix = Joint->GlobalMatrix;
|
||||
}
|
||||
|
||||
//std::cout<<AnimatedMesh->getAllJoints()[1]->Children.size()<<" Children\n";
|
||||
//And M2MVertices are not usable like this. Thus we transform
|
||||
|
||||
if(M2Vertices.size()>0)
|
||||
@ -211,82 +468,89 @@ if(M2Vertices.size()>0)
|
||||
|
||||
for(u32 i=0;i<M2MVertices.size();i++)
|
||||
{
|
||||
M2Vertices.push_back(video::S3DVertex(core::vector3df(M2MVertices[i].pos.X,M2MVertices[i].pos.Z,M2MVertices[i].pos.Y),core::vector3df(M2MVertices[i].normal.X,M2MVertices[i].normal.Z,M2MVertices[i].normal.Y), video::SColor(255,100,100,100),M2MVertices[i].texcoords));
|
||||
//M2Vertices.push_back(video::S3DVertex(core::vector3df(M2MVertices[i].pos.X,M2MVertices[i].pos.Z,M2MVertices[i].pos.Y),core::vector3df(M2MVertices[i].normal.X,M2MVertices[i].normal.Z,M2MVertices[i].normal.Y), video::SColor(255,100,100,100),M2MVertices[i].texcoords));
|
||||
//rotation happens when reading from file, so swapping Y and Z here is no longer necessary
|
||||
M2Vertices.push_back(video::S3DVertex(core::vector3df(M2MVertices[i].pos.X,M2MVertices[i].pos.Y,M2MVertices[i].pos.Z),core::vector3df(M2MVertices[i].normal.X,M2MVertices[i].normal.Y,M2MVertices[i].normal.Z), video::SColor(255,100,100,100),M2MVertices[i].texcoords));
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (Mesh)
|
||||
Mesh->drop();
|
||||
|
||||
Mesh=new SMesh();
|
||||
|
||||
|
||||
while(Mesh->getMeshBufferCount()>0)
|
||||
{
|
||||
Mesh->MeshBuffers.erase(0);
|
||||
}
|
||||
|
||||
|
||||
//Loop through the submeshes
|
||||
for(u32 i=0; i < M2MViews[0].nSub;i++)//
|
||||
{
|
||||
//std::cout << "Proceeding with Submesh "<<i<<"/"<<M2MViews[0].nSub<<"\n";
|
||||
//Now, M2MTriangles refers to M2MIndices and not to M2MVertices.
|
||||
//Now, M2MTriangles refers to M2MIndices and not to M2MVertices.
|
||||
scene::SSkinMeshBuffer *MeshBuffer = AnimatedMesh->createBuffer();
|
||||
|
||||
if(M2Indices.size()>0)
|
||||
M2Indices.clear();
|
||||
|
||||
for(u32 j=M2MSubmeshes[i].ofsTris;j<M2MSubmeshes[i].ofsTris+M2MSubmeshes[i].nTris;j++)
|
||||
{
|
||||
M2Indices.push_back(M2MIndices[M2MTriangles[j]]);
|
||||
}
|
||||
|
||||
//std::cout << "Sending "<<M2Vertices.size() <<" Vertices and " << M2Indices.size() <<" Indices to the MeshBuffer\n";
|
||||
|
||||
IMB = new SMeshBuffer;
|
||||
IMB->append(M2Vertices.const_pointer(),M2Vertices.size(),M2Indices.const_pointer(),M2Indices.size());
|
||||
IMB->recalculateBoundingBox();
|
||||
|
||||
//IMB->getMaterial().DiffuseColor.set(255,255-(u32)(255/(M2MSubmeshes.size()))*i,(u32)(255/(M2MSubmeshes.size()))*i,0);
|
||||
//IMB->getMaterial().DiffuseColor.set(255,(M2MSubmeshes[i].meshpartId==0?0:255),(M2MSubmeshes[i].meshpartId==0?255:0),0);
|
||||
|
||||
|
||||
std::string TexName=Texdir.c_str();
|
||||
TexName+="/";
|
||||
if(i<M2MTextureUnit.size())
|
||||
TexName+=M2MTextureFiles[M2MTextureUnit[i].textureIndex].c_str();
|
||||
|
||||
while(TexName.find('\\')<TexName.size())//Replace \ by /
|
||||
//Put the Indices and Vertices of the Submesh into a mesh buffer
|
||||
//Each Submesh contains only the Indices and Vertices that belong to it.
|
||||
//Because of this the Index values for the Submeshes must be corrected by the Vertex offset of the Submesh
|
||||
for(u32 j=M2MSubmeshes[i].ofsTris;j<M2MSubmeshes[i].ofsTris+M2MSubmeshes[i].nTris;j++)
|
||||
{
|
||||
TexName.replace(TexName.find('\\'),1,"/");
|
||||
MeshBuffer->Indices.push_back(M2MIndices[M2MTriangles[j]]-M2MSubmeshes[i].ofsVertex);
|
||||
}
|
||||
while(TexName.find(' ')<TexName.size())//Replace space by _
|
||||
// std::cout << i << ": " << MeshBuffer->Indices.size() << "\n";
|
||||
for(u32 j=M2MSubmeshes[i].ofsVertex;j<M2MSubmeshes[i].ofsVertex+M2MSubmeshes[i].nVertex;j++)
|
||||
{
|
||||
TexName.replace(TexName.find(' '),1,"_");
|
||||
MeshBuffer->Vertices_Standard.push_back(M2Vertices[j]);
|
||||
for(u32 k=0; k<4; k++)
|
||||
{
|
||||
//std::cout << (u32)M2MVertices[j].bones[k] << " ";
|
||||
if((M2MVertices[j].weights[k]/255.0f)>0.0f)
|
||||
{
|
||||
scene::CSkinnedMesh::SWeight* weight = AnimatedMesh->createWeight(AnimatedMesh->getAllJoints()[(u32)M2MVertices[j].bones[k]]);
|
||||
weight->strength=M2MVertices[j].weights[k]/255.0f;
|
||||
weight->vertex_id=j-M2MSubmeshes[i].ofsVertex;
|
||||
weight->buffer_id=i;
|
||||
}
|
||||
//std::cout<<weight->buffer_id << " " << weight->vertex_id << " " << weight->strength <<"|";
|
||||
}
|
||||
// std::cout<<'\n';
|
||||
}
|
||||
std::transform(TexName.begin(), TexName.end(), TexName.begin(), tolower);
|
||||
//std::cout << i << ": " << MeshBuffer->Vertices_Standard.size() <<" "<<M2MSubmeshes[i].ofsVertex<<" "<<M2MSubmeshes[i].nVertex<< "\n";
|
||||
|
||||
IMB->getMaterial().setTexture(0,Device->getVideoDriver()->getTexture(TexName.c_str()));
|
||||
if(i<M2MRenderFlags.size())
|
||||
{
|
||||
DEBUG(logdebug("Render Flags: %u %u",M2MRenderFlags[i].flags,M2MRenderFlags[i].blending));
|
||||
IMB->getMaterial().BackfaceCulling=(M2MRenderFlags[i].flags & 0x04)?false:true;
|
||||
if(M2MRenderFlags[i].blending==1)
|
||||
IMB->getMaterial().MaterialType=video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
}
|
||||
IMB->recalculateBoundingBox();
|
||||
Mesh->addMeshBuffer(IMB);
|
||||
IMB->drop();
|
||||
//std::cout << "Mesh now has "<<Mesh->getMeshBufferCount()<<" Buffers\n";
|
||||
}
|
||||
Device->getSceneManager()->getMeshManipulator()->flipSurfaces(Mesh); //Fix inverted surfaces after the rotation
|
||||
Device->getSceneManager()->getMeshManipulator()->recalculateNormals(Mesh,true);//just to be sure
|
||||
aniMesh= new SAnimatedMesh();
|
||||
aniMesh->addMesh(Mesh);
|
||||
Mesh->drop();
|
||||
Mesh = 0;
|
||||
|
||||
aniMesh->recalculateBoundingBox();
|
||||
MeshBuffer->recalculateBoundingBox();
|
||||
//MeshBuffer->getMaterial().DiffuseColor.set(255,255-(u32)(255/(M2MSubmeshes.size()))*i,(u32)(255/(M2MSubmeshes.size()))*i,0);
|
||||
//MeshBuffer->getMaterial().DiffuseColor.set(255,(M2MSubmeshes[i].meshpartId==0?0:255),(M2MSubmeshes[i].meshpartId==0?255:0),0);
|
||||
for(u32 j=0;j<M2MTextureUnit.size();j++)//Loop through texture units
|
||||
{
|
||||
if(M2MTextureUnit[j].submeshIndex1==i)//if a texture unit belongs to this submesh
|
||||
{
|
||||
std::string TexName=Texdir.c_str();
|
||||
TexName+="/";
|
||||
if(i<M2MTextureUnit.size())
|
||||
TexName+=M2MTextureFiles[M2MTextureLookup[M2MTextureUnit[j].textureIndex]].c_str();
|
||||
while(TexName.find('\\')<TexName.size())//Replace \ by /
|
||||
{
|
||||
TexName.replace(TexName.find('\\'),1,"/");
|
||||
}
|
||||
while(TexName.find(' ')<TexName.size())//Replace space by _
|
||||
{
|
||||
TexName.replace(TexName.find(' '),1,"_");
|
||||
}
|
||||
std::transform(TexName.begin(), TexName.end(), TexName.begin(), tolower);
|
||||
MeshBuffer->getMaterial().setTexture(M2MTextureUnit[j].TextureUnitNumber,Device->getVideoDriver()->getTexture(TexName.c_str()));
|
||||
|
||||
DEBUG(logdebug("Render Flags: %u %u",M2MRenderFlags[M2MTextureUnit[j].renderFlagsIndex].flags,M2MRenderFlags[M2MTextureUnit[j].renderFlagsIndex].blending));
|
||||
MeshBuffer->getMaterial().BackfaceCulling=(M2MRenderFlags[M2MTextureUnit[j].renderFlagsIndex].flags & 0x04)?false:true;
|
||||
if(M2MRenderFlags[M2MTextureUnit[j].renderFlagsIndex].blending==1)
|
||||
MeshBuffer->getMaterial().MaterialType=video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//MeshBuffer->recalculateBoundingBox();
|
||||
// Mesh->addMeshBuffer(MeshBuffer);
|
||||
// Mesh->recalculateBoundingBox();
|
||||
//MeshBuffer->drop();
|
||||
//std::cout << "Mesh now has "<<Mesh->getMeshBufferCount()<<" Buffers\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Device->getSceneManager()->getMeshManipulator()->flipSurfaces(AnimatedMesh); //Fix inverted surfaces after the rotation
|
||||
Device->getSceneManager()->getMeshManipulator()->recalculateNormals(AnimatedMesh,true);//just to be sure
|
||||
|
||||
AnimatedMesh->setInterpolationMode(scene::EIM_LINEAR);
|
||||
|
||||
M2MTriangles.clear();
|
||||
M2Vertices.clear();
|
||||
@ -300,8 +564,7 @@ M2MSubmeshes.clear();
|
||||
M2MTextureFiles.clear();
|
||||
M2MTextureLookup.clear();
|
||||
M2MViews.clear();
|
||||
|
||||
return aniMesh;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include "irrlicht/irrlicht.h"
|
||||
#include "irrlicht/IMeshLoader.h"
|
||||
#include "SSkinnedMesh.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
@ -100,34 +101,12 @@ struct TextureDefinition {
|
||||
u32 texFileOfs;
|
||||
};
|
||||
|
||||
class CM2MeshFileLoader : public IMeshLoader
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
CM2MeshFileLoader(IrrlichtDevice* device, c8* texdir);
|
||||
|
||||
//! destructor
|
||||
virtual ~CM2MeshFileLoader();
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".cob")
|
||||
virtual bool isALoadableFileExtension(const c8* fileName)const;
|
||||
|
||||
//! creates/loads an animated mesh from the file.
|
||||
//! \return Pointer to the created mesh. Returns 0 if loading failed.
|
||||
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
|
||||
//! See IUnknown::drop() for more information.
|
||||
virtual scene::IAnimatedMesh* createMesh(irr::io::IReadFile* file);
|
||||
private:
|
||||
ModelHeader header;
|
||||
|
||||
struct ModelVertex {
|
||||
core::vector3df pos;//Use Irrlicht Vector here!
|
||||
core::vector3df pos;
|
||||
u8 weights[4];
|
||||
u8 bones[4];
|
||||
core::vector3df normal;//Use Irrlicht Vector here!
|
||||
core::vector2df texcoords;//Use Irrlicht Vector here!
|
||||
core::vector3df normal;
|
||||
core::vector2df texcoords;
|
||||
u32 unk1, unk2; // always 0,0 so this is probably unused
|
||||
};
|
||||
|
||||
@ -170,15 +149,87 @@ struct RenderFlags{
|
||||
u16 blending;
|
||||
};
|
||||
|
||||
//
|
||||
io::IFileSystem* FileSystem;
|
||||
struct Animation{
|
||||
u32 animationID;
|
||||
u32 start, end;
|
||||
float movespeed;
|
||||
u32 loop, flags, unk1, unk2;
|
||||
u32 playbackspeed;
|
||||
float bbox[6];
|
||||
float radius;
|
||||
s16 indexSameID;
|
||||
u16 unk3;
|
||||
};
|
||||
|
||||
struct AnimBlockHead{
|
||||
s16 interpolationType;
|
||||
s16 globalSequenceID;
|
||||
u32 nInterpolationRange;
|
||||
u32 ofsInterpolationRange;
|
||||
u32 nTimeStamp;
|
||||
u32 ofsTimeStamp;
|
||||
u32 nValues;
|
||||
u32 ofsValues;
|
||||
};
|
||||
|
||||
struct InterpolationRange{
|
||||
u32 start, end;
|
||||
};
|
||||
|
||||
struct AnimBlock{
|
||||
AnimBlockHead header;
|
||||
core::array<InterpolationRange> keyframes;
|
||||
core::array<u32> timestamps;
|
||||
core::array<float> values;
|
||||
};
|
||||
|
||||
struct Bone{
|
||||
s32 indexF;
|
||||
u32 flags;
|
||||
s16 parentBone;
|
||||
u16 unk1;
|
||||
u32 unk2;
|
||||
AnimBlock translation, rotation, scaling;
|
||||
core::vector3df PivotPoint;
|
||||
};
|
||||
|
||||
|
||||
class CM2MeshFileLoader : public IMeshLoader
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
CM2MeshFileLoader(IrrlichtDevice* device, c8* texdir);
|
||||
|
||||
//! destructor
|
||||
virtual ~CM2MeshFileLoader();
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".cob")
|
||||
virtual bool isALoadableFileExtension(const c8* fileName)const;
|
||||
|
||||
//! creates/loads an animated mesh from the file.
|
||||
//! \return Pointer to the created mesh. Returns 0 if loading failed.
|
||||
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
|
||||
//! See IUnknown::drop() for more information.
|
||||
virtual scene::IAnimatedMesh* createMesh(io::IReadFile* file);
|
||||
private:
|
||||
|
||||
bool load();
|
||||
|
||||
IrrlichtDevice* Device;
|
||||
// scene::IMeshManipulator* Manipulator;
|
||||
core::stringc M2MeshName;
|
||||
core::stringc Texdir;
|
||||
SAnimatedMesh* aniMesh;
|
||||
io::IReadFile* MeshFile;
|
||||
|
||||
CSkinnedMesh* AnimatedMesh;
|
||||
scene::CSkinnedMesh::SJoint* ParentJoint;
|
||||
|
||||
|
||||
|
||||
ModelHeader header;
|
||||
core::stringc M2MeshName;
|
||||
SMesh* Mesh;
|
||||
SMeshBuffer* IMB;
|
||||
//SSkinMeshBuffer* MeshBuffer;
|
||||
//Taken from the Model file, thus m2M*
|
||||
core::array<ModelVertex> M2MVertices;
|
||||
core::array<ModelView> M2MViews;
|
||||
@ -190,9 +241,13 @@ struct RenderFlags{
|
||||
core::array<std::string> M2MTextureFiles;
|
||||
core::array<TextureUnit> M2MTextureUnit;
|
||||
core::array<RenderFlags> M2MRenderFlags;
|
||||
core::array<Animation> M2MAnimations;
|
||||
core::array<Bone> M2MBones;
|
||||
//Used for the Mesh, thus m2_noM_*
|
||||
core::array<video::S3DVertex> M2Vertices;
|
||||
core::array<u16> M2Indices;
|
||||
core::array<scene::ISkinnedMesh::SJoint> M2Joints;
|
||||
|
||||
|
||||
};
|
||||
}//namespace scene
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
AM_CPPFLAGS = -I$(top_builddir)/src/Client -I$(top_builddir)/src/shared -I$(top_builddir)/src/Client/DefScript -I$(top_builddir)/src/Client/World -I$(top_builddir)/src/Client/Realm -Wall
|
||||
AM_CPPFLAGS = -I$(top_builddir)/src/Client -I$(top_builddir)/src/shared -I$(top_builddir)/src/Client/DefScript -I$(top_builddir)/src/Client/World -I$(top_builddir)/src/Client/Realm -Wall -D_DEBUG
|
||||
## Build pseuwow
|
||||
noinst_LIBRARIES = libgui.a
|
||||
libgui_a_SOURCES =CCursorController.cpp DrawObject.cpp MInput.h Scene.h SImage.h\
|
||||
@ -10,7 +10,7 @@ CM2MeshFileLoader.cpp SceneData.h ShTlTerrainSceneNode.h\
|
||||
CM2MeshFileLoader.h MCamera.h SceneGuiStart.cpp SImage.cpp SceneCharselection.cpp\
|
||||
CIrrKlangAudioStreamLoaderMP3.cpp CIrrKlangAudioStreamLoaderMP3.h CIrrKlangAudioStreamMP3.cpp CIrrKlangAudioStreamMP3.h\
|
||||
ikpMP3.cpp decoder/bits.c decoder/internal.h decoder/mpaudec.c decoder/mpaudec.h decoder/mpaudectab.h decoder/mpegaudio.h\
|
||||
irrKlangSceneNode.cpp irrKlangSceneNode.h
|
||||
irrKlangSceneNode.cpp irrKlangSceneNode.h CBoneSceneNode.cpp CBoneSceneNode.h SSkinnedMesh.cpp SSkinnedMesh.h
|
||||
|
||||
|
||||
libgui_a_LIBADD = $(top_builddir)/src/shared/libshared.a $(top_builddir)/src/shared/Auth/libauth.a $(top_builddir)/src/shared/Network/libnetwork.a
|
||||
|
||||
1414
src/Client/GUI/SSkinnedMesh.cpp
Executable file
1414
src/Client/GUI/SSkinnedMesh.cpp
Executable file
File diff suppressed because it is too large
Load Diff
196
src/Client/GUI/SSkinnedMesh.h
Executable file
196
src/Client/GUI/SSkinnedMesh.h
Executable file
@ -0,0 +1,196 @@
|
||||
// Copyright (C) 2002-2007 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
//New skinned mesh
|
||||
|
||||
#ifndef __C_SKINNED_MESH_H_INCLUDED__
|
||||
#define __C_SKINNED_MESH_H_INCLUDED__
|
||||
|
||||
#include "irrlicht/irrlicht.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class IAnimatedMeshSceneNode;
|
||||
class IBoneSceneNode;
|
||||
|
||||
class CSkinnedMesh: public ISkinnedMesh
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CSkinnedMesh();
|
||||
|
||||
//! destructor
|
||||
virtual ~CSkinnedMesh();
|
||||
|
||||
//! returns the amount of frames. If the amount is 1, it is a static (=non animated) mesh.
|
||||
virtual u32 getFrameCount() const;
|
||||
|
||||
//! returns the animated mesh based on a detail level (which is ignored)
|
||||
virtual IMesh* getMesh(s32 frame, s32 detailLevel=255, s32 startFrameLoop=-1, s32 endFrameLoop=-1);
|
||||
|
||||
//! Animates this mesh's joints based on frame input
|
||||
//! blend: {0-old position, 1-New position}
|
||||
virtual void animateMesh(f32 frame, f32 blend);
|
||||
|
||||
//! Preforms a software skin on this mesh based of joint positions
|
||||
virtual void skinMesh();
|
||||
|
||||
//! returns amount of mesh buffers.
|
||||
virtual u32 getMeshBufferCount() const;
|
||||
|
||||
//! returns pointer to a mesh buffer
|
||||
virtual IMeshBuffer* getMeshBuffer(u32 nr) const;
|
||||
|
||||
//! Returns pointer to a mesh buffer which fits a material
|
||||
/** \param material: material to search for
|
||||
\return Returns the pointer to the mesh buffer or
|
||||
NULL if there is no such mesh buffer. */
|
||||
virtual IMeshBuffer* getMeshBuffer( const video::SMaterial &material) const;
|
||||
|
||||
//! returns an axis aligned bounding box
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
|
||||
//! set user axis aligned bounding box
|
||||
virtual void setBoundingBox( const core::aabbox3df& box);
|
||||
|
||||
//! sets a flag of all contained materials to a new value
|
||||
virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue);
|
||||
|
||||
//! Returns the type of the animated mesh.
|
||||
virtual E_ANIMATED_MESH_TYPE getMeshType() const;
|
||||
|
||||
//! Gets joint count.
|
||||
virtual u32 getJointCount() const;
|
||||
|
||||
//! Gets the name of a joint.
|
||||
virtual const c8* getJointName(u32 number) const;
|
||||
|
||||
//! Gets a joint number from its name
|
||||
virtual s32 getJointNumber(const c8* name) const;
|
||||
|
||||
//! uses animation from another mesh
|
||||
virtual bool useAnimationFrom(const ISkinnedMesh *mesh);
|
||||
|
||||
//! Update Normals when Animating
|
||||
//! False= Don't (default)
|
||||
//! True = Update normals, slower
|
||||
virtual void updateNormalsWhenAnimating(bool on);
|
||||
|
||||
//! Sets Interpolation Mode
|
||||
virtual void setInterpolationMode(E_INTERPOLATION_MODE mode);
|
||||
|
||||
//! Recovers the joints from the mesh
|
||||
virtual void recoverJointsFromMesh(core::array<IBoneSceneNode*> &JointChildSceneNodes);
|
||||
|
||||
//! Tranfers the joint data to the mesh
|
||||
virtual void transferJointsToMesh(const core::array<IBoneSceneNode*> &JointChildSceneNodes);
|
||||
|
||||
//! Tranfers the joint hints to the mesh
|
||||
virtual void transferOnlyJointsHintsToMesh(const core::array<IBoneSceneNode*> &JointChildSceneNodes);
|
||||
|
||||
//! Creates an array of joints from this mesh
|
||||
virtual void createJoints(core::array<IBoneSceneNode*> &JointChildSceneNodes,
|
||||
IAnimatedMeshSceneNode* AnimatedMeshSceneNode,
|
||||
ISceneManager* SceneManager);
|
||||
|
||||
//! Convertes the mesh to contain tangent information
|
||||
virtual void convertMeshToTangents();
|
||||
|
||||
//! Does the mesh have no animation
|
||||
virtual bool isStatic();
|
||||
|
||||
//! (This feature is not implemented in irrlicht yet)
|
||||
virtual bool setHardwareSkinning(bool on);
|
||||
|
||||
//Interface for the mesh loaders (finalize should lock these functions, and they should have some prefix like loader_
|
||||
|
||||
//these functions will use the needed arrays, set vaules, etc to help the loaders
|
||||
|
||||
//! exposed for loaders to add mesh buffers
|
||||
virtual core::array<SSkinMeshBuffer*> &getMeshBuffers();
|
||||
|
||||
//! alternative method for adding joints
|
||||
virtual core::array<SJoint*> &getAllJoints();
|
||||
|
||||
//! alternative method for adding joints
|
||||
virtual const core::array<SJoint*> &getAllJoints() const;
|
||||
|
||||
//! loaders should call this after populating the mesh
|
||||
virtual void finalize();
|
||||
|
||||
virtual SSkinMeshBuffer *createBuffer();
|
||||
|
||||
virtual SJoint *createJoint(SJoint *parent=0);
|
||||
|
||||
virtual SPositionKey *createPositionKey(SJoint *joint);
|
||||
virtual SRotationKey *createRotationKey(SJoint *joint);
|
||||
virtual SScaleKey *createScaleKey(SJoint *joint);
|
||||
|
||||
virtual SWeight *createWeight(SJoint *joint);
|
||||
|
||||
private:
|
||||
|
||||
void checkForAnimation();
|
||||
|
||||
void normalizeWeights();
|
||||
|
||||
void buildAll_LocalAnimatedMatrices(); //public?
|
||||
|
||||
void buildAll_GlobalAnimatedMatrices(SJoint *Joint=0, SJoint *ParentJoint=0);
|
||||
|
||||
void getFrameData(f32 frame, SJoint *Node,
|
||||
core::vector3df &position, s32 &positionHint,
|
||||
core::vector3df &scale, s32 &scaleHint,
|
||||
core::quaternion &rotation, s32 &rotationHint);
|
||||
|
||||
void CalculateGlobalMatrices(SJoint *Joint,SJoint *ParentJoint);
|
||||
|
||||
void SkinJoint(SJoint *Joint, SJoint *ParentJoint);
|
||||
|
||||
void calculateTangents(core::vector3df& normal,
|
||||
core::vector3df& tangent, core::vector3df& binormal,
|
||||
core::vector3df& vt1, core::vector3df& vt2, core::vector3df& vt3,
|
||||
core::vector2df& tc1, core::vector2df& tc2, core::vector2df& tc3);
|
||||
|
||||
|
||||
core::array<SSkinMeshBuffer*> *SkinningBuffers; //Meshbuffer to skin, default is to skin localBuffers
|
||||
|
||||
core::array<SSkinMeshBuffer*> LocalBuffers;
|
||||
|
||||
core::array<SJoint*> AllJoints;
|
||||
core::array<SJoint*> RootJoints;
|
||||
|
||||
bool HasAnimation;
|
||||
|
||||
bool PreparedForSkinning;
|
||||
|
||||
f32 AnimationFrames;
|
||||
|
||||
f32 LastAnimatedFrame;
|
||||
f32 LastSkinnedFrame;
|
||||
bool BoneControlUsed;
|
||||
|
||||
bool AnimateNormals;
|
||||
|
||||
bool HardwareSkinning;
|
||||
|
||||
|
||||
E_INTERPOLATION_MODE InterpolationMode;
|
||||
|
||||
core::aabbox3d<f32> BoundingBox;
|
||||
|
||||
core::array< core::array<bool> > Vertices_Moved;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user