* M2 Animations Part 1: Animations work for 2.4.3
the viewer got a new debug tab, which allows to play around with debug settings and animations
This commit is contained in:
parent
f27b371b86
commit
fedeb4d8fe
1384
src/Client/GUI/CM2Mesh.cpp
Executable file
1384
src/Client/GUI/CM2Mesh.cpp
Executable file
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,5 @@
|
||||
// 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__
|
||||
#ifndef __M2_MESH_H_INCLUDED__
|
||||
#define __M2_MESH_H_INCLUDED__
|
||||
|
||||
#include "irrlicht/irrlicht.h"
|
||||
|
||||
@ -17,15 +11,15 @@ namespace scene
|
||||
class IAnimatedMeshSceneNode;
|
||||
class IBoneSceneNode;
|
||||
|
||||
class CSkinnedMesh: public ISkinnedMesh
|
||||
class CM2Mesh: public ISkinnedMesh
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CSkinnedMesh();
|
||||
CM2Mesh();
|
||||
|
||||
//! destructor
|
||||
virtual ~CSkinnedMesh();
|
||||
virtual ~CM2Mesh();
|
||||
|
||||
//! returns the amount of frames. If the amount is 1, it is a static (=non animated) mesh.
|
||||
virtual u32 getFrameCount() const;
|
||||
@ -58,19 +52,6 @@ namespace scene
|
||||
//! set user axis aligned bounding box
|
||||
virtual void setBoundingBox( const core::aabbox3df& box);
|
||||
|
||||
//! recalculates the bounding box
|
||||
void recalculateBoundingBox()
|
||||
{
|
||||
if (LocalBuffers.size())
|
||||
{
|
||||
BoundingBox = LocalBuffers[0]->getBoundingBox();
|
||||
for (u32 i=1; i<LocalBuffers.size(); ++i)
|
||||
BoundingBox.addInternalBox(LocalBuffers[i]->getBoundingBox());
|
||||
}
|
||||
else
|
||||
BoundingBox.reset(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
//! sets a flag of all contained materials to a new value
|
||||
virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue);
|
||||
|
||||
@ -80,8 +61,10 @@ namespace scene
|
||||
//! flags the meshbuffer as changed, reloads hardware buffers
|
||||
virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX);
|
||||
|
||||
|
||||
//! Returns the type of the animated mesh.
|
||||
//! updates the bounding box
|
||||
virtual void updateBoundingBox(void);
|
||||
|
||||
//! Returns the type of the animated mesh.
|
||||
virtual E_ANIMATED_MESH_TYPE getMeshType() const;
|
||||
|
||||
//! Gets joint count.
|
||||
@ -159,9 +142,7 @@ private:
|
||||
|
||||
void normalizeWeights();
|
||||
|
||||
void buildAll_LocalAnimatedMatrices(); //public?
|
||||
|
||||
void buildAll_GlobalAnimatedMatrices(SJoint *Joint=0, SJoint *ParentJoint=0);
|
||||
void buildAllAnimatedMatrices(SJoint *Joint=0, SJoint *ParentJoint=0); //public?
|
||||
|
||||
void getFrameData(f32 frame, SJoint *Node,
|
||||
core::vector3df &position, s32 &positionHint,
|
||||
@ -192,8 +173,7 @@ private:
|
||||
f32 AnimationFrames;
|
||||
|
||||
f32 LastAnimatedFrame;
|
||||
f32 LastSkinnedFrame;
|
||||
bool BoneControlUsed;
|
||||
bool SkinnedLastFrame;
|
||||
|
||||
bool AnimateNormals;
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
// #define _DEBUG 1
|
||||
#define _DEBUG 1
|
||||
#include <iostream>
|
||||
#include "MemoryDataHolder.h"
|
||||
#include "MemoryInterface.h"
|
||||
#include "CM2MeshFileLoader.h"
|
||||
#include "SSkinnedMesh.h"
|
||||
#include "common.h"
|
||||
|
||||
namespace irr
|
||||
@ -38,7 +37,7 @@ IAnimatedMesh* CM2MeshFileLoader::createMesh(io::IReadFile* file)
|
||||
if(!file)
|
||||
return 0;
|
||||
MeshFile = file;
|
||||
AnimatedMesh = new scene::CSkinnedMesh();
|
||||
AnimatedMesh = new scene::CM2Mesh();
|
||||
|
||||
if ( load() )
|
||||
{
|
||||
@ -65,13 +64,6 @@ void CM2MeshFileLoader::ReadVertices()
|
||||
for(u32 i =0;i<header.nVertices;i++)
|
||||
{
|
||||
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));
|
||||
@ -114,6 +106,7 @@ void CM2MeshFileLoader::ReadViewData(io::IReadFile* file)
|
||||
{
|
||||
file->read(&tempM2Submesh,sizeof(ModelViewSubmesh)-(header.version==0x100?16:0));
|
||||
M2MSubmeshes.push_back(tempM2Submesh);
|
||||
DEBUG(logdebug("Submesh %u nBone: %u ofsBone: %u",i,tempM2Submesh.nBone, tempM2Submesh.ofsBone));
|
||||
// std::cout<< "Submesh " <<i<<" ID "<<tempM2Submesh.meshpartId<<" starts at V/T "<<tempM2Submesh.ofsVertex<<"/"<<tempM2Submesh.ofsTris<<" and has "<<tempM2Submesh.nVertex<<"/"<<tempM2Submesh.nTris<<" V/T\n";
|
||||
}
|
||||
DEBUG(logdebug("Read %u/%u Submeshes",M2MSubmeshes.size(),currentView.nSub));
|
||||
@ -135,232 +128,69 @@ void CM2MeshFileLoader::ReadViewData(io::IReadFile* file)
|
||||
|
||||
}
|
||||
|
||||
void CM2MeshFileLoader::ReadTextureDefinitions()
|
||||
void CM2MeshFileLoader::ReadAnimationData()
|
||||
{
|
||||
//Texture Lookup table. This is global data
|
||||
u16 tempM2TexLookup;
|
||||
if(!M2MTextureLookup.empty())
|
||||
|
||||
//Global Sequences. This is global data
|
||||
u32 tempGlobalSeq;
|
||||
if(!M2MGlobalSequences.empty())
|
||||
{
|
||||
M2MTextureLookup.clear();
|
||||
M2MGlobalSequences.clear();
|
||||
}
|
||||
MeshFile->seek(header.ofsTexLookup);
|
||||
for(u32 i=0;i<header.nTexLookup;i++)
|
||||
MeshFile->seek(header.ofsGlobalSequences);
|
||||
for(u32 i=0;i<header.nGlobalSequences;i++)
|
||||
{
|
||||
MeshFile->read(&tempM2TexLookup,sizeof(u16));
|
||||
M2MTextureLookup.push_back(tempM2TexLookup);
|
||||
DEBUG(logdebug("Texture %u Type %u",i,tempM2TexLookup));
|
||||
MeshFile->read(&tempGlobalSeq,sizeof(u32));
|
||||
M2MGlobalSequences.push_back(tempGlobalSeq);
|
||||
DEBUG(logdebug("Global Sequence %u End %u",i,tempGlobalSeq));
|
||||
}
|
||||
DEBUG(logdebug("Read %u Texture lookup entries",M2MTextureLookup.size()));
|
||||
DEBUG(logdebug("Read %u Global Sequence entries",M2MGlobalSequences.size()));
|
||||
|
||||
//Texture Definitions table. This is global data
|
||||
TextureDefinition tempM2TexDef;
|
||||
if(!M2MTextureDef.empty())
|
||||
//BoneLookupTable. This is global data
|
||||
u16 tempBoneLookup;
|
||||
if(!M2MBoneLookupTable.empty())
|
||||
{
|
||||
M2MTextureDef.clear();
|
||||
M2MBoneLookupTable.clear();
|
||||
}
|
||||
MeshFile->seek(header.ofsTextures);
|
||||
for(u32 i=0;i<header.nTextures;i++)
|
||||
MeshFile->seek(header.ofsBoneLookupTable);
|
||||
for(u32 i=0;i<header.nBoneLookupTable;i++)
|
||||
{
|
||||
MeshFile->read(&tempM2TexDef,sizeof(TextureDefinition));
|
||||
M2MTextureDef.push_back(tempM2TexDef);
|
||||
DEBUG(logdebug("Texture %u Type %u",i,tempM2TexDef.texType));
|
||||
MeshFile->read(&tempBoneLookup,sizeof(u16));
|
||||
M2MBoneLookupTable.push_back(tempBoneLookup);
|
||||
DEBUG(logdebug("BoneLookupTable %u Value %u",i,tempBoneLookup));
|
||||
}
|
||||
DEBUG(logdebug("Read %u Texture Definition entries",M2MTextureDef.size()));
|
||||
DEBUG(logdebug("Read %u BoneLookupTable entries",M2MBoneLookupTable.size()));
|
||||
|
||||
//Render Flags table. This is global data
|
||||
RenderFlags tempM2RF;
|
||||
if(!M2MRenderFlags.empty())
|
||||
//SkeleBoneLookupTable. This is global data
|
||||
u16 tempSkeleBoneLookup;
|
||||
if(!M2MSkeleBoneLookupTable.empty())
|
||||
{
|
||||
M2MRenderFlags.clear();
|
||||
M2MSkeleBoneLookupTable.clear();
|
||||
}
|
||||
MeshFile->seek(header.ofsTexFlags);
|
||||
for(u32 i=0;i<header.nTexFlags;i++)
|
||||
MeshFile->seek(header.ofsSkelBoneLookup);
|
||||
for(u32 i=0;i<header.nSkelBoneLookup;i++)
|
||||
{
|
||||
MeshFile->read(&tempM2RF,sizeof(RenderFlags));
|
||||
M2MRenderFlags.push_back(tempM2RF);
|
||||
DEBUG(logdebug("Flag %u: (%u, %u)",i,tempM2RF.blending,tempM2RF.flags));
|
||||
MeshFile->read(&tempSkeleBoneLookup,sizeof(u16));
|
||||
M2MSkeleBoneLookupTable.push_back(tempSkeleBoneLookup);
|
||||
DEBUG(logdebug("SkeleBoneLookupTable %u Value %u",i,tempSkeleBoneLookup));
|
||||
}
|
||||
DEBUG(logdebug("Read %u Renderflags",M2MRenderFlags.size()));
|
||||
|
||||
if(!M2MTextureFiles.empty())
|
||||
M2MTextureFiles.clear();
|
||||
|
||||
std::string tempTexFileName="";
|
||||
M2MTextureFiles.reallocate(M2MTextureDef.size());
|
||||
for(u32 i=0; i<M2MTextureDef.size(); i++)
|
||||
DEBUG(logdebug("Read %u SkeleBoneLookupTable entries",M2MSkeleBoneLookupTable.size()));
|
||||
|
||||
//Animations. This is global data
|
||||
Animation tempAnimation;
|
||||
if(!M2MAnimations.empty())
|
||||
{
|
||||
tempTexFileName.resize(M2MTextureDef[i].texFileLen + 1);
|
||||
MeshFile->seek(M2MTextureDef[i].texFileOfs);
|
||||
MeshFile->read((void*)tempTexFileName.data(),M2MTextureDef[i].texFileLen);
|
||||
M2MTextureFiles.push_back("");
|
||||
M2MTextureFiles[i]=tempTexFileName.c_str();
|
||||
DEBUG(logdebug("Texture: %u %u (%s/%s) @ %u(%u)",i,M2MTextureFiles.size(),M2MTextureFiles[i].c_str(),tempTexFileName.c_str(),M2MTextureDef[i].texFileOfs,M2MTextureDef[i].texFileLen));
|
||||
M2MAnimations.clear();
|
||||
}
|
||||
}
|
||||
MeshFile->seek(header.ofsAnimations);
|
||||
for(u32 i=0;i<header.nAnimations;i++)
|
||||
{
|
||||
MeshFile->read(&tempAnimation,sizeof(Animation));
|
||||
M2MAnimations.push_back(tempAnimation);
|
||||
DEBUG(logdebug("Animation %u Id %u Start %u End %u",i,tempAnimation.animationID,tempAnimation.start,tempAnimation.end));
|
||||
}
|
||||
DEBUG(logdebug("Read %u Animations",M2MAnimations.size()));
|
||||
|
||||
|
||||
bool CM2MeshFileLoader::load()
|
||||
{
|
||||
DEBUG(logdebug("Trying to open file %s",MeshFile->getFileName()));
|
||||
|
||||
|
||||
MeshFile->read(&header,20);
|
||||
DEBUG(logdebug("M2 Version %X",header.version));
|
||||
|
||||
switch(header.version)
|
||||
{
|
||||
case 0x100:
|
||||
case 0x104://HACK
|
||||
case 0x105://HACK
|
||||
case 0x106://HACK
|
||||
case 0x107://HACK
|
||||
{
|
||||
MeshFile->read((u8*)&header+20,sizeof(ModelHeader)-20);
|
||||
ReadVertices();
|
||||
MeshFile->seek(header.ofsViews);
|
||||
MeshFile->read(¤tView,sizeof(ModelView));
|
||||
ReadViewData(MeshFile);
|
||||
ReadTextureDefinitions();
|
||||
break;
|
||||
}
|
||||
case 0x108:
|
||||
{
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
logerror("M2: [%s] Wrong header %0X! File version doesn't match or file is not a M2 file.",MeshFile->getFileName(),header.version);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Vertices. Global data
|
||||
// if(!M2MVertices.empty())
|
||||
// M2MVertices.clear();
|
||||
//
|
||||
// ModelVertex tempM2MVert;
|
||||
// f32 tempYZ;
|
||||
// MeshFile->seek(header.ofsVertices);
|
||||
//
|
||||
// for(u32 i =0;i<header.nVertices;i++)
|
||||
// {
|
||||
// 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));
|
||||
|
||||
//Views (skins) == Sets of vertices. Usage yet unknown. Global data
|
||||
|
||||
// std::string SkinName = MeshFile->getFileName();
|
||||
// SkinName = SkinName.substr(0, SkinName.length()-3) + "00.skin"; // FIX ME (and stuffextract) ! as we need more skins
|
||||
// io::IReadFile* SkinFile = io::IrrCreateIReadFileBasic(Device, SkinName.c_str());
|
||||
// if (!SkinFile)
|
||||
// {
|
||||
// logerror("Error! Skin file not found: %s", SkinName.c_str());
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// SkinFile->read(¤tView, sizeof(ModelView));
|
||||
//
|
||||
// //std::cout << "Skins "<<header.nViews<<" (views)\n";
|
||||
//
|
||||
// DEBUG(logdebug("Using View 0 for all further operations"));
|
||||
// DEBUG(logdebug("This View has %u Submeshes",currentView.nSub));
|
||||
//
|
||||
// //Vertex indices of a specific view.Local to View 0
|
||||
// if(M2MIndices.size()>0)
|
||||
// M2MIndices.clear();
|
||||
//
|
||||
// u16 tempM2Index;
|
||||
// SkinFile->seek(currentView.ofsIndex);
|
||||
// for(u32 i =0;i<currentView.nIndex;i++)
|
||||
// {
|
||||
// SkinFile->read(&tempM2Index,sizeof(u16));
|
||||
// M2MIndices.push_back(tempM2Index);
|
||||
// }
|
||||
// DEBUG(logdebug("Read %u/%u Indices",M2MIndices.size(),currentView.nIndex));
|
||||
//
|
||||
//
|
||||
// //Triangles. Data Points point to the Vertex Indices, not the vertices themself. 3 Points = 1 Triangle, Local to View 0
|
||||
// if(M2MTriangles.size()>0)
|
||||
// M2MTriangles.clear();
|
||||
//
|
||||
// u16 tempM2Triangle;
|
||||
// SkinFile->seek(currentView.ofsTris);
|
||||
// for(u32 i =0;i<currentView.nTris;i++)
|
||||
// {
|
||||
// SkinFile->read(&tempM2Triangle,sizeof(u16));
|
||||
// M2MTriangles.push_back(tempM2Triangle);
|
||||
// }
|
||||
// DEBUG(logdebug("Read %u/%u Triangles",M2MTriangles.size(),currentView.nTris));
|
||||
// //Submeshes, Local to View 0
|
||||
// if(M2MSubmeshes.size()>0)
|
||||
// M2MSubmeshes.clear();
|
||||
//
|
||||
// ModelViewSubmesh tempM2Submesh;
|
||||
// SkinFile->seek(currentView.ofsSub);
|
||||
// for(u32 i =0;i<currentView.nSub;i++)
|
||||
// {
|
||||
// SkinFile->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";
|
||||
// }
|
||||
// DEBUG(logdebug("Read %u/%u Submeshes",M2MSubmeshes.size(),currentView.nSub));
|
||||
//
|
||||
// //Texture units. Local to view 0
|
||||
// TextureUnit tempM2TexUnit;
|
||||
// if(!M2MTextureUnit.empty())
|
||||
// {
|
||||
// M2MTextureUnit.clear();
|
||||
// }
|
||||
// SkinFile->seek(currentView.ofsTex);
|
||||
// for(u32 i=0;i<currentView.nTex;i++)
|
||||
// {
|
||||
// SkinFile->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()));
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
// Animation related stuff //
|
||||
///////////////////////////////////////
|
||||
|
||||
/* ANIMATION NEED FIX !!! - search this text to find all code blocks for animations
|
||||
|
||||
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())
|
||||
@ -375,11 +205,8 @@ for(u32 i=0;i<header.nBones;i++)
|
||||
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";
|
||||
DEBUG(logdebug("Bone %u Parent %u PP %f %f %f",i,tempBone.parentBone,tempBone.PivotPoint.X,tempBone.PivotPoint.Y,tempBone.PivotPoint.Z));
|
||||
}
|
||||
//Fill in values referenced in Bones. local to each bone
|
||||
InterpolationRange tempBoneIR;
|
||||
@ -475,95 +302,190 @@ for(u32 i=0; i<M2MBones.size(); i++)
|
||||
|
||||
DEBUG(logdebug("Read %u Bones",M2MBones.size()));
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
scene::CSkinnedMesh::SJoint* Joint;
|
||||
for(u32 i=0;i<M2MBones.size();i++)
|
||||
void CM2MeshFileLoader::ReadTextureDefinitions()
|
||||
{
|
||||
if(M2MBones[i].parentBone == -1)
|
||||
//Texture Lookup table. This is global data
|
||||
u16 tempM2TexLookup;
|
||||
if(!M2MTextureLookup.empty())
|
||||
{
|
||||
ParentJoint=(scene::CSkinnedMesh::SJoint*)0;
|
||||
M2MTextureLookup.clear();
|
||||
}
|
||||
else
|
||||
MeshFile->seek(header.ofsTexLookup);
|
||||
for(u32 i=0;i<header.nTexLookup;i++)
|
||||
{
|
||||
ParentJoint=AnimatedMesh->getAllJoints()[M2MBones[i].parentBone];
|
||||
MeshFile->read(&tempM2TexLookup,sizeof(u16));
|
||||
M2MTextureLookup.push_back(tempM2TexLookup);
|
||||
DEBUG(logdebug("Texture %u Type %u",i,tempM2TexLookup));
|
||||
}
|
||||
Joint=AnimatedMesh->createJoint(ParentJoint);
|
||||
DEBUG(logdebug("Read %u Texture lookup entries",M2MTextureLookup.size()));
|
||||
|
||||
|
||||
//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++)
|
||||
//Texture Definitions table. This is global data
|
||||
TextureDefinition tempM2TexDef;
|
||||
if(!M2MTextureDef.empty())
|
||||
{
|
||||
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]);
|
||||
M2MTextureDef.clear();
|
||||
}
|
||||
if(M2MBones[i].rotation.header.nValues>0)
|
||||
{
|
||||
for(u32 j=0;j<M2MBones[i].rotation.header.nValues;j++)
|
||||
MeshFile->seek(header.ofsTextures);
|
||||
for(u32 i=0;i<header.nTextures;i++)
|
||||
{
|
||||
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';
|
||||
MeshFile->read(&tempM2TexDef,sizeof(TextureDefinition));
|
||||
M2MTextureDef.push_back(tempM2TexDef);
|
||||
DEBUG(logdebug("Texture %u Type %u",i,tempM2TexDef.texType));
|
||||
}
|
||||
DEBUG(logdebug("Read %u Texture Definition entries",M2MTextureDef.size()));
|
||||
|
||||
//Render Flags table. This is global data
|
||||
RenderFlags tempM2RF;
|
||||
if(!M2MRenderFlags.empty())
|
||||
{
|
||||
M2MRenderFlags.clear();
|
||||
}
|
||||
MeshFile->seek(header.ofsTexFlags);
|
||||
for(u32 i=0;i<header.nTexFlags;i++)
|
||||
{
|
||||
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()));
|
||||
|
||||
if(!M2MTextureFiles.empty())
|
||||
M2MTextureFiles.clear();
|
||||
|
||||
std::string tempTexFileName="";
|
||||
M2MTextureFiles.reallocate(M2MTextureDef.size());
|
||||
for(u32 i=0; i<M2MTextureDef.size(); i++)
|
||||
{
|
||||
tempTexFileName.resize(M2MTextureDef[i].texFileLen + 1);
|
||||
MeshFile->seek(M2MTextureDef[i].texFileOfs);
|
||||
MeshFile->read((void*)tempTexFileName.data(),M2MTextureDef[i].texFileLen);
|
||||
M2MTextureFiles.push_back("");
|
||||
M2MTextureFiles[i]=tempTexFileName.c_str();
|
||||
DEBUG(logdebug("Texture: %u %u (%s/%s) @ %u(%u)",i,M2MTextureFiles.size(),M2MTextureFiles[i].c_str(),tempTexFileName.c_str(),M2MTextureDef[i].texFileOfs,M2MTextureDef[i].texFileLen));
|
||||
}
|
||||
}
|
||||
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; ANIMATION NEED FIX !!!
|
||||
// positionMatrix.setTranslation( Joint->Animatedposition );
|
||||
core::matrix4 scaleMatrix;
|
||||
//scaleMatrix.setScale( Joint->Animatedscale );
|
||||
core::matrix4 rotationMatrix;// = Joint->Animatedrotation.getMatrix();
|
||||
|
||||
Joint->GlobalMatrix = positionMatrix * rotationMatrix * scaleMatrix;//
|
||||
bool CM2MeshFileLoader::load()
|
||||
{
|
||||
DEBUG(logdebug("Trying to open file %s",MeshFile->getFileName()));
|
||||
|
||||
if (ParentJoint)
|
||||
{
|
||||
core::matrix4 InverseParentGlobal;
|
||||
ParentJoint->GlobalMatrix.getInverse(InverseParentGlobal);
|
||||
Joint->LocalMatrix = InverseParentGlobal * Joint->GlobalMatrix;
|
||||
}
|
||||
else
|
||||
Joint->LocalMatrix = Joint->GlobalMatrix;
|
||||
|
||||
MeshFile->read(&header,20);
|
||||
DEBUG(logdebug("M2 Version %X",header.version));
|
||||
|
||||
switch(header.version)
|
||||
{
|
||||
case 0x100:
|
||||
case 0x104://HACK
|
||||
case 0x105://HACK
|
||||
case 0x106://HACK
|
||||
case 0x107://HACK
|
||||
{
|
||||
MeshFile->read((u8*)&header+20,sizeof(ModelHeader)-20);
|
||||
ReadVertices();
|
||||
MeshFile->seek(header.ofsViews);
|
||||
MeshFile->read(¤tView,sizeof(ModelView));
|
||||
ReadViewData(MeshFile);
|
||||
ReadTextureDefinitions();
|
||||
ReadAnimationData();
|
||||
break;
|
||||
}
|
||||
case 0x108:
|
||||
{
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
logerror("M2: [%s] Wrong header %0X! File version doesn't match or file is not a M2 file.",MeshFile->getFileName(),header.version);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
//std::cout<<AnimatedMesh->getAllJoints()[1]->Children.size()<<" Children\n";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// EVERYTHING IS READ
|
||||
///////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
// Animation related stuff //
|
||||
///////////////////////////////////////
|
||||
|
||||
scene::CM2Mesh::SJoint* Joint;
|
||||
for(u32 i=0;i<M2MBones.size();i++)
|
||||
{
|
||||
if(M2MBones[i].parentBone == -1)
|
||||
{
|
||||
ParentJoint=(scene::CM2Mesh::SJoint*)0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ParentJoint=AnimatedMesh->getAllJoints()[M2MBones[i].parentBone];
|
||||
}
|
||||
Joint=AnimatedMesh->createJoint(ParentJoint);
|
||||
|
||||
if(M2MBones[i].translation.header.nValues>0)
|
||||
{
|
||||
for(u32 j=0;j<M2MBones[i].translation.header.nValues;j++)
|
||||
{
|
||||
scene::CM2Mesh::SPositionKey* pos=AnimatedMesh->createPositionKey(Joint);
|
||||
pos->frame=M2MBones[i].translation.timestamps[j];
|
||||
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::CM2Mesh::SRotationKey* rot=AnimatedMesh->createRotationKey(Joint);
|
||||
rot->frame=M2MBones[i].rotation.timestamps[j];
|
||||
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]);
|
||||
tempQ.normalize();
|
||||
rot->rotation=tempQ;
|
||||
}
|
||||
}
|
||||
|
||||
if(M2MBones[i].scaling.header.nValues>0)
|
||||
{
|
||||
for(u32 j=0;j<M2MBones[i].scaling.header.nValues;j++)
|
||||
{
|
||||
scene::CM2Mesh::SScaleKey* scale=AnimatedMesh->createScaleKey(Joint);
|
||||
scale->frame=M2MBones[i].scaling.timestamps[j];
|
||||
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;
|
||||
Joint->Animatedscale=core::vector3df(1.0f,1.0f,1.0f);
|
||||
Joint->Animatedrotation=core::quaternion(0.0f,0.0f,0.0f,1.0f);
|
||||
|
||||
core::matrix4 positionMatrix;
|
||||
positionMatrix.setTranslation( Joint->Animatedposition );
|
||||
|
||||
core::matrix4 rotationMatrix = Joint->Animatedrotation.getMatrix();
|
||||
|
||||
core::matrix4 scaleMatrix;
|
||||
scaleMatrix.setScale( Joint->Animatedscale );
|
||||
|
||||
Joint->GlobalMatrix = positionMatrix * rotationMatrix * scaleMatrix;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//And M2MVertices are not usable like this. Thus we transform
|
||||
|
||||
|
||||
//And M2MVertices are not usable like this. Thus we put it into an irrlicht S3DVertex
|
||||
|
||||
if(M2Vertices.size()>0)
|
||||
M2Vertices.clear();
|
||||
|
||||
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));
|
||||
//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));
|
||||
}
|
||||
//Loop through the submeshes
|
||||
@ -583,58 +505,36 @@ for(u32 i=0; i < currentView.nSub;i++)//
|
||||
for(u32 j=M2MSubmeshes[i].ofsVertex;j<M2MSubmeshes[i].ofsVertex+M2MSubmeshes[i].nVertex;j++)
|
||||
{
|
||||
MeshBuffer->Vertices_Standard.push_back(M2Vertices[j]);
|
||||
// for(u32 k=0; k<4; k++)
|
||||
// {
|
||||
//std::cout << (u32)M2MVertices[j].bones[k] << " ";
|
||||
/* ANIMATION NEED FIX !!!
|
||||
for(u32 k=0; k<4; k++)
|
||||
{
|
||||
if((M2MVertices[j].weights[k]/255.0f)>0.0f)
|
||||
{
|
||||
scene::CSkinnedMesh::SWeight* weight = AnimatedMesh->createWeight(AnimatedMesh->getAllJoints()[(u32)M2MVertices[j].bones[k]]);
|
||||
scene::CM2Mesh::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->vertex_id=MeshBuffer->Vertices_Standard.size()-1;
|
||||
weight->buffer_id=i;
|
||||
}
|
||||
*/
|
||||
//std::cout<<weight->buffer_id << " " << weight->vertex_id << " " << weight->strength <<"|";
|
||||
// }
|
||||
// std::cout<<'\n';
|
||||
|
||||
}
|
||||
}
|
||||
//std::cout << i << ": " << MeshBuffer->Vertices_Standard.size() <<" "<<M2MSubmeshes[i].ofsVertex<<" "<<M2MSubmeshes[i].nVertex<< "\n";
|
||||
|
||||
|
||||
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 && !M2MTextureFiles[M2MTextureLookup[M2MTextureUnit[j].textureIndex]].empty())//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);*/
|
||||
char buf[1000];
|
||||
MemoryDataHolder::MakeTextureFilename(buf,M2MTextureFiles[M2MTextureLookup[M2MTextureUnit[j].textureIndex]].c_str());
|
||||
video::ITexture* tex = Device->getVideoDriver()->findTexture(buf);
|
||||
if(!tex)
|
||||
{
|
||||
io::IReadFile* TexFile = io::IrrCreateIReadFileBasic(Device, buf);
|
||||
// logdebug("Texture %s loading",M2MTextureFiles[M2MTextureLookup[M2MTextureUnit[j].textureIndex]].c_str());
|
||||
if (!TexFile)
|
||||
{
|
||||
logerror("CM2MeshFileLoader: Texture file not found: %s", buf);
|
||||
continue;
|
||||
}
|
||||
// logdebug("Texture %s loaded",M2MTextureFiles[M2MTextureLookup[M2MTextureUnit[j].textureIndex]].c_str());
|
||||
tex = Device->getVideoDriver()->getTexture(TexFile);
|
||||
TexFile->drop();
|
||||
}
|
||||
@ -642,32 +542,28 @@ for(u32 i=0; i < currentView.nSub;i++)//
|
||||
|
||||
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;
|
||||
switch(M2MRenderFlags[M2MTextureUnit[j].renderFlagsIndex].blending)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
MeshBuffer->getMaterial().MaterialType=video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
DEBUG(logdebug("Alpha Channel Transparency on"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MeshBuffer->recalculateBoundingBox();
|
||||
MeshBuffer->setHardwareMappingHint(EHM_STATIC);
|
||||
if(header.nAnimations==0 && header.nGlobalSequences == 0)
|
||||
MeshBuffer->setHardwareMappingHint(EHM_STATIC);
|
||||
else
|
||||
MeshBuffer->setHardwareMappingHint(EHM_STREAM);
|
||||
|
||||
// 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
|
||||
|
||||
// False.Genesis: commented out this problematic line.. was causing crashes for me, since 3.x client models
|
||||
// SEEMS TO CRASH ONLY IN OPENGL-MODE ?! -- investigate!
|
||||
//Device->getSceneManager()->getMeshManipulator()->recalculateNormals(AnimatedMesh,true);//just to be sure
|
||||
|
||||
AnimatedMesh->setInterpolationMode(scene::EIM_LINEAR);
|
||||
|
||||
// SkinFile->drop();
|
||||
M2MTriangles.clear();
|
||||
M2Vertices.clear();
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#include "irrlicht/irrlicht.h"
|
||||
#include "irrlicht/IMeshLoader.h"
|
||||
#include "SSkinnedMesh.h"
|
||||
#include "CM2Mesh.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
@ -53,8 +53,8 @@ struct ModelHeader {
|
||||
|
||||
u32 nTexFlags;
|
||||
u32 ofsTexFlags;
|
||||
u32 nY;
|
||||
u32 ofsY; //0x90
|
||||
u32 nBoneLookupTable;
|
||||
u32 ofsBoneLookupTable; //0x90
|
||||
|
||||
u32 nTexLookup;
|
||||
u32 ofsTexLookup;
|
||||
@ -127,7 +127,7 @@ struct ModelViewSubmesh {
|
||||
u16 nVertex;
|
||||
u16 ofsTris;//Starting Triangle index
|
||||
u16 nTris;
|
||||
u16 unk1, unk2, unk3, unk4;
|
||||
u16 nBone, ofsBone, unk3, unk4;
|
||||
core::vector3df v;
|
||||
float unkf[4];
|
||||
};
|
||||
@ -220,14 +220,15 @@ private:
|
||||
bool load();
|
||||
void ReadVertices();
|
||||
void ReadTextureDefinitions();
|
||||
void ReadAnimationData();
|
||||
void ReadViewData(io::IReadFile* file);
|
||||
|
||||
IrrlichtDevice *Device;
|
||||
core::stringc Texdir;
|
||||
io::IReadFile *MeshFile, *SkinFile;
|
||||
|
||||
CSkinnedMesh *AnimatedMesh;
|
||||
scene::CSkinnedMesh::SJoint *ParentJoint;
|
||||
CM2Mesh *AnimatedMesh;
|
||||
scene::CM2Mesh::SJoint *ParentJoint;
|
||||
|
||||
|
||||
|
||||
@ -246,8 +247,11 @@ private:
|
||||
core::array<std::string> M2MTextureFiles;
|
||||
core::array<TextureUnit> M2MTextureUnit;
|
||||
core::array<RenderFlags> M2MRenderFlags;
|
||||
core::array<u32> M2MGlobalSequences;
|
||||
core::array<Animation> M2MAnimations;
|
||||
core::array<Bone> M2MBones;
|
||||
core::array<u16> M2MBoneLookupTable;
|
||||
core::array<u16> M2MSkeleBoneLookupTable;
|
||||
//Used for the Mesh, thus m2_noM_*
|
||||
core::array<video::S3DVertex> M2Vertices;
|
||||
core::array<u16> M2Indices;
|
||||
|
||||
@ -21,5 +21,5 @@ SceneLogin.cpp
|
||||
SceneWorld.cpp
|
||||
ShTlTerrainSceneNode.cpp
|
||||
SImage.cpp
|
||||
SSkinnedMesh.cpp
|
||||
CM2Mesh.cpp
|
||||
)
|
||||
@ -3,7 +3,6 @@
|
||||
#include "MemoryDataHolder.h"
|
||||
#include "MemoryInterface.h"
|
||||
#include "CWMOMeshFileLoader.h"
|
||||
#include "SSkinnedMesh.h"
|
||||
#include "common.h"
|
||||
|
||||
inline void flipcc(irr::u8 *fcc)
|
||||
@ -52,7 +51,7 @@ IAnimatedMesh* CWMOMeshFileLoader::createMesh(io::IReadFile* file)
|
||||
return 0;
|
||||
MeshFile = file;
|
||||
std::string filename=MeshFile->getFileName();
|
||||
Mesh = new scene::CSkinnedMesh();
|
||||
Mesh = new scene::CM2Mesh();
|
||||
|
||||
if ( load(true) )//We try loading a root file first!
|
||||
{
|
||||
@ -69,7 +68,7 @@ IAnimatedMesh* CWMOMeshFileLoader::createMesh(io::IReadFile* file)
|
||||
}
|
||||
load(false);
|
||||
}
|
||||
Mesh->recalculateBoundingBox();
|
||||
Mesh->updateBoundingBox();
|
||||
Device->getSceneManager()->getMeshManipulator()->flipSurfaces(Mesh); //Fix inverted surfaces after the rotation
|
||||
//Does this crash on windows?
|
||||
Device->getSceneManager()->getMeshManipulator()->recalculateNormals(Mesh,true);//just to be sure
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#include "irrlicht/irrlicht.h"
|
||||
#include "irrlicht/IMeshLoader.h"
|
||||
#include "SSkinnedMesh.h"
|
||||
#include "CM2Mesh.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
@ -83,7 +83,7 @@ private:
|
||||
core::stringc Texdir;
|
||||
io::IReadFile* MeshFile;
|
||||
|
||||
CSkinnedMesh* Mesh;
|
||||
CM2Mesh* Mesh;
|
||||
|
||||
|
||||
//Stuff from root file
|
||||
|
||||
@ -193,7 +193,7 @@ void DrawObject::Draw(void)
|
||||
WorldPosition pos = ((WorldObject*)_obj)->GetPosition();
|
||||
node->setPosition(WPToIrr(pos));
|
||||
rotation.Y = O_TO_IRR(pos.o);
|
||||
|
||||
rotation.X -=90;
|
||||
float s = _obj->GetFloatValue(OBJECT_FIELD_SCALE_X);
|
||||
if(s <= 0)
|
||||
s = 1;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -90,6 +90,7 @@ namespace scene
|
||||
private:
|
||||
//! Internal members used by CSkinnedMesh
|
||||
friend class CSkinnedMesh;
|
||||
friend class CM2Mesh;
|
||||
bool *Moved;
|
||||
core::vector3df StaticPos;
|
||||
core::vector3df StaticNormal;
|
||||
@ -162,6 +163,7 @@ namespace scene
|
||||
private:
|
||||
//! Internal members used by CSkinnedMesh
|
||||
friend class CSkinnedMesh;
|
||||
friend class CM2Mesh;
|
||||
|
||||
SJoint *UseAnimationFrom;
|
||||
bool LocalAnimatedMatrix_Animated;
|
||||
|
||||
@ -9,8 +9,7 @@ ${PROJECT_SOURCE_DIR}/src/Client/GUI/SImage.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/Client/GUI/MemoryInterface.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/Client/GUI/CMDHMemoryReadFile.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/Client/GUI/CBoneSceneNode.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/Client/GUI/SSkinnedMesh.cpp
|
||||
|
||||
${PROJECT_SOURCE_DIR}/src/Client/GUI/CM2Mesh.cpp
|
||||
)
|
||||
|
||||
# Link the executable to the libraries.
|
||||
|
||||
@ -19,6 +19,7 @@ tutorial, we use a lot stuff from the gui namespace.
|
||||
#include "GUI/CM2MeshFileLoader.h"
|
||||
#include "GUI/CWMOMeshFileLoader.h"
|
||||
#include "GUI/CImageLoaderBLP.h"
|
||||
#include "MemoryDataHolder.h"
|
||||
|
||||
|
||||
using namespace irr;
|
||||
@ -33,7 +34,7 @@ using namespace gui;
|
||||
Some global variables used later on
|
||||
*/
|
||||
IrrlichtDevice *Device = 0;
|
||||
core::stringc StartUpModelFile = "../../../bin/data/model/draeneifemale.m2";
|
||||
core::stringc StartUpModelFile = "";
|
||||
core::stringw MessageText;
|
||||
core::stringw Caption;
|
||||
scene::ISceneNode* Model = 0;
|
||||
@ -87,6 +88,11 @@ enum
|
||||
GUI_ID_QUIT,
|
||||
|
||||
GUI_ID_TREE_VIEW,
|
||||
|
||||
GUI_ID_FRAME_START,
|
||||
GUI_ID_FRAME_END,
|
||||
GUI_ID_FRAME_SET,
|
||||
|
||||
// And some magic numbers
|
||||
MAX_FRAMERATE = 1000,
|
||||
DEFAULT_FRAMERATE = 30,
|
||||
@ -193,19 +199,18 @@ void loadModel(const c8* fn)
|
||||
else
|
||||
{
|
||||
scene::IAnimatedMeshSceneNode* animModel = Device->getSceneManager()->addAnimatedMeshSceneNode(m);
|
||||
animModel->setAnimationSpeed(30);
|
||||
animModel->setAnimationSpeed(1000);
|
||||
animModel->setFrameLoop(3333,4333);
|
||||
Model = animModel;
|
||||
}
|
||||
Model->setMaterialFlag(video::EMF_LIGHTING, true);
|
||||
// Model->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||
Model->setDebugDataVisible(scene::EDS_OFF);
|
||||
|
||||
Model->setRotation(core::vector3df(-90,0,0));
|
||||
// we need to uncheck the menu entries. would be cool to fake a menu event, but
|
||||
// that's not so simple. so we do it brute force
|
||||
gui::IGUIContextMenu* menu = (gui::IGUIContextMenu*)Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(GUI_ID_TOGGLE_DEBUG_INFO, true);
|
||||
if (menu)
|
||||
for(int item = 1; item < 6; ++item)
|
||||
menu->setItemChecked(item, false);
|
||||
for(int id = GUI_ID_DEBUG_BOUNDING_BOX; id <= GUI_ID_DEBUG_WIRE_OVERLAY; ++id)
|
||||
((IGUICheckBox*)Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(id,true))->setChecked(false);
|
||||
IGUIElement* toolboxWnd = Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(GUI_ID_DIALOG_ROOT_WINDOW, true);
|
||||
if ( toolboxWnd )
|
||||
{
|
||||
@ -213,6 +218,11 @@ void loadModel(const c8* fn)
|
||||
toolboxWnd->getElementFromId(GUI_ID_Y_SCALE, true)->setText(L"1.0");
|
||||
toolboxWnd->getElementFromId(GUI_ID_Z_SCALE, true)->setText(L"1.0");
|
||||
}
|
||||
|
||||
FILE* f = fopen("./viewer_last.txt","w");
|
||||
fwrite(filename.c_str(),1,filename.size(),f);
|
||||
fclose(f);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -292,6 +302,19 @@ void createToolBox()
|
||||
env->addCheckBox(true, core::rect<s32>(22,142,130,156),t3,GUI_ID_LIGHT_VISIBLE,L"Visible");
|
||||
env->addButton(core::rect<s32>(10,164,85,185), t3, GUI_ID_LIGHT_SET, L"Set");
|
||||
|
||||
IGUITab* t4 = tab->addTab(L"Debug");
|
||||
env->addCheckBox(false, core::rect<s32>(22,48,130,68),t4,GUI_ID_DEBUG_BOUNDING_BOX,L"BBox");
|
||||
env->addCheckBox(false, core::rect<s32>(22,78,130,98),t4,GUI_ID_DEBUG_BUFFERS_BOUNDING_BOXES,L"Buffers BBoxes");
|
||||
env->addCheckBox(false, core::rect<s32>(22,108,130,128),t4,GUI_ID_DEBUG_HALF_TRANSPARENT,L"Half Transparent");
|
||||
env->addCheckBox(false, core::rect<s32>(22,138,130,158),t4,GUI_ID_DEBUG_NORMALS,L"Normals");
|
||||
env->addCheckBox(false, core::rect<s32>(22,168,130,188),t4,GUI_ID_DEBUG_SKELETON,L"Skeleton");
|
||||
env->addCheckBox(false, core::rect<s32>(22,198,130,218),t4,GUI_ID_DEBUG_WIRE_OVERLAY,L"Wire Overlay");
|
||||
env->addStaticText(L"Start:", core::rect<s32>(22,228,40,248), false, false, t4);
|
||||
env->addEditBox(L"0", core::rect<s32>(40,248,130,268), true, t4, GUI_ID_FRAME_START);
|
||||
env->addStaticText(L"End:", core::rect<s32>(22,268,40,288), false, false, t4);
|
||||
env->addEditBox(L"0", core::rect<s32>(40,288,130,308), true, t4, GUI_ID_FRAME_END);
|
||||
env->addButton(core::rect<s32>(10,318,85,338), t4, GUI_ID_FRAME_SET, L"Set");
|
||||
|
||||
// bring irrlicht engine logo to front, because it
|
||||
// now may be below the newly created toolbox
|
||||
root->bringToFront(root->getElementFromId(666, true));
|
||||
@ -344,6 +367,38 @@ public:
|
||||
scene::ISceneManager* smgr = Device->getSceneManager();
|
||||
switch(event.GUIEvent.EventType)
|
||||
{
|
||||
case EGET_CHECKBOX_CHANGED:
|
||||
{
|
||||
s32 pos = ((IGUICheckBox*)event.GUIEvent.Caller)->getID();
|
||||
switch (pos)
|
||||
{
|
||||
case GUI_ID_DEBUG_BOUNDING_BOX: // View -> Debug Information
|
||||
if (Model)
|
||||
Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_BBOX));
|
||||
break;
|
||||
case GUI_ID_DEBUG_NORMALS: // View -> Debug Information
|
||||
if (Model)
|
||||
Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_NORMALS));
|
||||
break;
|
||||
case GUI_ID_DEBUG_SKELETON: // View -> Debug Information
|
||||
if (Model)
|
||||
Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_SKELETON));
|
||||
break;
|
||||
case GUI_ID_DEBUG_WIRE_OVERLAY: // View -> Debug Information
|
||||
if (Model)
|
||||
Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_MESH_WIRE_OVERLAY));
|
||||
break;
|
||||
case GUI_ID_DEBUG_HALF_TRANSPARENT: // View -> Debug Information
|
||||
if (Model)
|
||||
Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_HALF_TRANSPARENCY));
|
||||
break;
|
||||
case GUI_ID_DEBUG_BUFFERS_BOUNDING_BOXES: // View -> Debug Information
|
||||
if (Model)
|
||||
Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_BBOX_BUFFERS));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EGET_MENU_ITEM_SELECTED:
|
||||
{
|
||||
// a menu item was clicked
|
||||
@ -370,56 +425,6 @@ public:
|
||||
menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem()));
|
||||
SkyBox->setVisible(!SkyBox->isVisible());
|
||||
break;
|
||||
case GUI_ID_DEBUG_OFF: // View -> Debug Information
|
||||
menu->setItemChecked(menu->getSelectedItem()+1, false);
|
||||
menu->setItemChecked(menu->getSelectedItem()+2, false);
|
||||
menu->setItemChecked(menu->getSelectedItem()+3, false);
|
||||
menu->setItemChecked(menu->getSelectedItem()+4, false);
|
||||
menu->setItemChecked(menu->getSelectedItem()+5, false);
|
||||
menu->setItemChecked(menu->getSelectedItem()+6, false);
|
||||
if (Model)
|
||||
Model->setDebugDataVisible(scene::EDS_OFF);
|
||||
break;
|
||||
case GUI_ID_DEBUG_BOUNDING_BOX: // View -> Debug Information
|
||||
menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem()));
|
||||
if (Model)
|
||||
Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_BBOX));
|
||||
break;
|
||||
case GUI_ID_DEBUG_NORMALS: // View -> Debug Information
|
||||
menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem()));
|
||||
if (Model)
|
||||
Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_NORMALS));
|
||||
break;
|
||||
case GUI_ID_DEBUG_SKELETON: // View -> Debug Information
|
||||
menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem()));
|
||||
if (Model)
|
||||
Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_SKELETON));
|
||||
break;
|
||||
case GUI_ID_DEBUG_WIRE_OVERLAY: // View -> Debug Information
|
||||
menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem()));
|
||||
if (Model)
|
||||
Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_MESH_WIRE_OVERLAY));
|
||||
break;
|
||||
case GUI_ID_DEBUG_HALF_TRANSPARENT: // View -> Debug Information
|
||||
menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem()));
|
||||
if (Model)
|
||||
Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_HALF_TRANSPARENCY));
|
||||
break;
|
||||
case GUI_ID_DEBUG_BUFFERS_BOUNDING_BOXES: // View -> Debug Information
|
||||
menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem()));
|
||||
if (Model)
|
||||
Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_BBOX_BUFFERS));
|
||||
break;
|
||||
case GUI_ID_DEBUG_ALL: // View -> Debug Information
|
||||
menu->setItemChecked(menu->getSelectedItem()-1, true);
|
||||
menu->setItemChecked(menu->getSelectedItem()-2, true);
|
||||
menu->setItemChecked(menu->getSelectedItem()-3, true);
|
||||
menu->setItemChecked(menu->getSelectedItem()-4, true);
|
||||
menu->setItemChecked(menu->getSelectedItem()-5, true);
|
||||
menu->setItemChecked(menu->getSelectedItem()-6, true);
|
||||
if (Model)
|
||||
Model->setDebugDataVisible(scene::EDS_FULL);
|
||||
break;
|
||||
case GUI_ID_MODEL_MATERIAL_SOLID: // View -> Material -> Solid
|
||||
if (Model)
|
||||
Model->setMaterialType(video::EMT_SOLID);
|
||||
@ -450,6 +455,7 @@ public:
|
||||
IGUIFileOpenDialog* dialog =
|
||||
(IGUIFileOpenDialog*)event.GUIEvent.Caller;
|
||||
loadModel(core::stringc(dialog->getFileName()).c_str());
|
||||
StartUpModelFile=core::stringc(dialog->getFileName()).c_str();
|
||||
}
|
||||
break;
|
||||
|
||||
@ -577,6 +583,7 @@ public:
|
||||
env->addFileOpenDialog(L"Please select your game archive/directory");
|
||||
break;
|
||||
case GUI_ID_LIGHT_SET:
|
||||
{
|
||||
scene::ISceneNode* light;
|
||||
|
||||
s32 pos=((IGUIComboBox*)env->getRootGUIElement()->getElementFromId(GUI_ID_LIGHT_BOX,true))->getSelected();
|
||||
@ -600,9 +607,15 @@ public:
|
||||
atof(core::stringc(env->getRootGUIElement()->getElementFromId(GUI_ID_LIGHT_Z_SCALE,true)->getText()).c_str()));
|
||||
light->setPosition(lpos);
|
||||
light->setVisible(((IGUICheckBox*)(env->getRootGUIElement()->getElementFromId(GUI_ID_LIGHT_VISIBLE,true)))->isChecked());
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case GUI_ID_FRAME_SET:
|
||||
{
|
||||
if(Model)
|
||||
((scene::IAnimatedMeshSceneNode*)Model)->setFrameLoop(atoi(core::stringc(env->getRootGUIElement()->getElementFromId(GUI_ID_FRAME_START,true)->getText()).c_str()),
|
||||
atoi(core::stringc(env->getRootGUIElement()->getElementFromId(GUI_ID_FRAME_END,true)->getText()).c_str()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
@ -628,8 +641,23 @@ resizeable, which is quite useful for a mesh viewer.
|
||||
*/
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
// ask user for driver
|
||||
//config hacks
|
||||
log_setloglevel(3);
|
||||
log_prepare("viewerlog.txt","w");
|
||||
MemoryDataHolder::SetUseMPQ("enUS");
|
||||
|
||||
FILE* f;
|
||||
f = fopen("./viewer_last.txt","r");
|
||||
if(f!=NULL)
|
||||
{
|
||||
log("Loading last used mesh");
|
||||
c8 buffer[255];
|
||||
fseek(f,0,SEEK_SET);
|
||||
fread(&buffer,1,255,f);
|
||||
StartUpModelFile = buffer;
|
||||
fclose(f);
|
||||
}
|
||||
// ask user for driver
|
||||
video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D8;
|
||||
|
||||
printf("Please select the driver you want for this example:\n"\
|
||||
@ -650,7 +678,7 @@ int main(int argc, char* argv[])
|
||||
case 'f': driverType = video::EDT_NULL; break;
|
||||
default: return 1;
|
||||
}
|
||||
|
||||
|
||||
// create device and exit if creation failed
|
||||
|
||||
MyEventReceiver receiver;
|
||||
@ -719,16 +747,6 @@ int main(int argc, char* argv[])
|
||||
submenu->addItem(L"toggle model debug information", GUI_ID_TOGGLE_DEBUG_INFO, true, true);
|
||||
submenu->addItem(L"model material", -1, true, true );
|
||||
|
||||
submenu = submenu->getSubMenu(1);
|
||||
submenu->addItem(L"Off", GUI_ID_DEBUG_OFF);
|
||||
submenu->addItem(L"Bounding Box", GUI_ID_DEBUG_BOUNDING_BOX);
|
||||
submenu->addItem(L"Normals", GUI_ID_DEBUG_NORMALS);
|
||||
submenu->addItem(L"Skeleton", GUI_ID_DEBUG_SKELETON);
|
||||
submenu->addItem(L"Wire overlay", GUI_ID_DEBUG_WIRE_OVERLAY);
|
||||
submenu->addItem(L"Half-Transparent", GUI_ID_DEBUG_HALF_TRANSPARENT);
|
||||
submenu->addItem(L"Buffers bounding boxes", GUI_ID_DEBUG_BUFFERS_BOUNDING_BOXES);
|
||||
submenu->addItem(L"All", GUI_ID_DEBUG_ALL);
|
||||
|
||||
submenu = menu->getSubMenu(1)->getSubMenu(2);
|
||||
submenu->addItem(L"Solid", GUI_ID_MODEL_MATERIAL_SOLID);
|
||||
submenu->addItem(L"Transparent", GUI_ID_MODEL_MATERIAL_TRANSPARENT);
|
||||
@ -813,7 +831,8 @@ int main(int argc, char* argv[])
|
||||
// show about message box and load default model
|
||||
// if (argc==1)
|
||||
// showAboutText();
|
||||
loadModel(StartUpModelFile.c_str());
|
||||
if(StartUpModelFile.c_str()!="")
|
||||
loadModel(StartUpModelFile.c_str());
|
||||
|
||||
// add skybox
|
||||
|
||||
@ -832,7 +851,7 @@ int main(int argc, char* argv[])
|
||||
// where the mesh scene node is placed.
|
||||
Camera[0]->setTarget(core::vector3df(0,0,0));
|
||||
|
||||
Camera[1] = smgr->addCameraSceneNodeFPS();
|
||||
Camera[1] = smgr->addCameraSceneNodeFPS(0,50.0f,0.1f);
|
||||
Camera[1]->setFarValue(20000.f);
|
||||
Camera[1]->setPosition(core::vector3df(0,0,-70));
|
||||
Camera[1]->setTarget(core::vector3df(0,0,0));
|
||||
@ -856,14 +875,17 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
driver->beginScene(true, true, video::SColor(150,50,50,50));
|
||||
|
||||
|
||||
smgr->drawAll();
|
||||
video::SMaterial m2;
|
||||
m2.Lighting = false;
|
||||
driver->setMaterial(m2);
|
||||
driver->draw3DLine(core::vector3df(0,0,0),core::vector3df(100,0,0),video::SColor(255,255,0,0));
|
||||
driver->draw3DLine(core::vector3df(0,0,0),core::vector3df(0,100,0),video::SColor(255,0,255,0));
|
||||
driver->draw3DLine(core::vector3df(0,0,0),core::vector3df(0,0,100),video::SColor(255,0,0,255));
|
||||
|
||||
video::SMaterial m;
|
||||
m.Lighting = false;
|
||||
driver->setMaterial(m);
|
||||
driver->setTransform(video::ETS_WORLD, core::matrix4());
|
||||
driver->draw3DLine(core::vector3df(-1,-1,-1),core::vector3df(10,-1,-1),video::SColor(255,255,0,0));
|
||||
driver->draw3DLine(core::vector3df(-1,-1,-1),core::vector3df(-1,10,-1),video::SColor(255,0,255,0));
|
||||
driver->draw3DLine(core::vector3df(-1,-1,-1),core::vector3df(-1,-1,10),video::SColor(255,0,0,255));
|
||||
driver->draw3DLine(core::vector3df(-1,-1,-1),core::vector3df(0,0,0),video::SColor(255,255,0,255));
|
||||
|
||||
env->drawAll();
|
||||
|
||||
driver->endScene();
|
||||
@ -872,8 +894,11 @@ int main(int argc, char* argv[])
|
||||
str.append(core::stringw(driver->getFPS()));
|
||||
str += L" Tris: ";
|
||||
str.append(core::stringw(driver->getPrimitiveCountDrawn()));
|
||||
str += L" Frame: ";
|
||||
if(Model)
|
||||
str.append(core::stringw(((scene::IAnimatedMeshSceneNode*)Model)->getFrameNr()));
|
||||
fpstext->setText(str.c_str());
|
||||
|
||||
|
||||
scene::ICameraSceneNode* cam = Device->getSceneManager()->getActiveCamera();
|
||||
str = L"Pos: ";
|
||||
str.append(core::stringw(cam->getPosition().X));
|
||||
@ -893,7 +918,8 @@ int main(int argc, char* argv[])
|
||||
else
|
||||
Device->yield();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Device->drop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user