diff --git a/source/Irrlicht/CAnimatedMeshMD3.cpp b/source/Irrlicht/CAnimatedMeshMD3.cpp index c6189163..0cc25de2 100644 --- a/source/Irrlicht/CAnimatedMeshMD3.cpp +++ b/source/Irrlicht/CAnimatedMeshMD3.cpp @@ -70,7 +70,7 @@ CAnimatedMeshMD3::CAnimatedMeshMD3() #endif Mesh = new SMD3Mesh(); - + MeshIPol = new SMesh(); setInterpolationShift(0, 0); } @@ -80,6 +80,8 @@ CAnimatedMeshMD3::~CAnimatedMeshMD3() { if (Mesh) Mesh->drop(); + if (MeshIPol) + MeshIPol->drop(); } @@ -91,32 +93,66 @@ u32 CAnimatedMeshMD3::getFrameCount() const //! Rendering Hint -void CAnimatedMeshMD3::setInterpolationShift ( u32 shift, u32 loopMode ) +void CAnimatedMeshMD3::setInterpolationShift(u32 shift, u32 loopMode) { IPolShift = shift; LoopMode = loopMode; } +//! returns amount of mesh buffers. +u32 CAnimatedMeshMD3::getMeshBufferCount() const +{ + return MeshIPol->getMeshBufferCount(); +} + + +//! returns pointer to a mesh buffer +IMeshBuffer* CAnimatedMeshMD3::getMeshBuffer(u32 nr) const +{ + return MeshIPol->getMeshBuffer(nr); +} + + +//! Returns pointer to a mesh buffer which fits a material +IMeshBuffer* CAnimatedMeshMD3::getMeshBuffer(const video::SMaterial &material) const +{ + return MeshIPol->getMeshBuffer(material); +} + + +void CAnimatedMeshMD3::setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) +{ + MeshIPol->setMaterialFlag(flag, newvalue); +} + + //! set the hardware mapping hint, for driver void CAnimatedMeshMD3::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer) { - MeshIPol.setHardwareMappingHint(newMappingHint, buffer); + MeshIPol->setHardwareMappingHint(newMappingHint, buffer); } //! flags the meshbuffer as changed, reloads hardware buffers void CAnimatedMeshMD3::setDirty(E_BUFFER_TYPE buffer) { - MeshIPol.setDirty(buffer); + MeshIPol->setDirty(buffer); +} + + +//! set user axis aligned bounding box +void CAnimatedMeshMD3::setBoundingBox(const core::aabbox3df& box) +{ + MeshIPol->setBoundingBox(box); } //! Returns the animated tag list based on a detail level. 0 is the lowest, 255 the highest detail. SMD3QuaternionTagList *CAnimatedMeshMD3::getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) { - if ( 0 == Mesh ) + if (0 == Mesh) return 0; getMesh(frame, detailLevel, startFrameLoop, endFrameLoop); @@ -127,16 +163,16 @@ SMD3QuaternionTagList *CAnimatedMeshMD3::getTagList(s32 frame, s32 detailLevel, //! Returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. IMesh* CAnimatedMeshMD3::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) { - if ( 0 == Mesh ) + if (0 == Mesh) return 0; //! check if we have the mesh in our private cache - SCacheInfo candidate ( frame, startFrameLoop, endFrameLoop ); - if ( candidate == Current ) - return &MeshIPol; + SCacheInfo candidate(frame, startFrameLoop, endFrameLoop); + if (candidate == Current) + return MeshIPol; - startFrameLoop = core::s32_max ( 0, startFrameLoop >> IPolShift ); - endFrameLoop = core::if_c_a_else_b ( endFrameLoop < 0, Mesh->MD3Header.numFrames - 1, endFrameLoop >> IPolShift ); + startFrameLoop = core::s32_max(0, startFrameLoop >> IPolShift); + endFrameLoop = core::if_c_a_else_b(endFrameLoop < 0, Mesh->MD3Header.numFrames - 1, endFrameLoop >> IPolShift); const u32 mask = 1 << IPolShift; @@ -144,46 +180,46 @@ IMesh* CAnimatedMeshMD3::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 frameB; f32 iPol; - if ( LoopMode ) + if (LoopMode) { // correct frame to "pixel center" frame -= mask >> 1; // interpolation - iPol = f32(frame & ( mask - 1 )) * core::reciprocal ( f32(mask) ); + iPol = f32(frame & (mask - 1)) * core::reciprocal(f32(mask)); // wrap anim frame >>= IPolShift; - frameA = core::if_c_a_else_b ( frame < startFrameLoop, endFrameLoop, frame ); - frameB = core::if_c_a_else_b ( frameA + 1 > endFrameLoop, startFrameLoop, frameA + 1 ); + frameA = core::if_c_a_else_b(frame < startFrameLoop, endFrameLoop, frame); + frameB = core::if_c_a_else_b(frameA + 1 > endFrameLoop, startFrameLoop, frameA + 1); } else { // correct frame to "pixel center" frame -= mask >> 1; - iPol = f32(frame & ( mask - 1 )) * core::reciprocal ( f32(mask) ); + iPol = f32(frame & (mask - 1)) * core::reciprocal(f32(mask)); // clamp anim frame >>= IPolShift; - frameA = core::s32_clamp ( frame, startFrameLoop, endFrameLoop ); - frameB = core::s32_min ( frameA + 1, endFrameLoop ); + frameA = core::s32_clamp(frame, startFrameLoop, endFrameLoop); + frameB = core::s32_min(frameA + 1, endFrameLoop); } // build current vertex - for (u32 i = 0; i!= Mesh->Buffer.size (); ++i) + for (u32 i = 0; i!= Mesh->Buffer.size(); ++i) { buildVertexArray(frameA, frameB, iPol, Mesh->Buffer[i], - (SMeshBufferLightMap*) MeshIPol.getMeshBuffer(i)); + (SMeshBufferLightMap*) MeshIPol->getMeshBuffer(i)); } - MeshIPol.recalculateBoundingBox(); + MeshIPol->recalculateBoundingBox(); // build current tags - buildTagArray( frameA, frameB, iPol ); + buildTagArray(frameA, frameB, iPol); Current = candidate; - return &MeshIPol; + return MeshIPol; } @@ -192,13 +228,13 @@ IMeshBuffer * CAnimatedMeshMD3::createMeshBuffer(const SMD3MeshBuffer* source, io::IFileSystem* fs, video::IVideoDriver * driver) { SMeshBufferLightMap * dest = new SMeshBufferLightMap(); - dest->Vertices.set_used( source->MeshHeader.numVertices ); - dest->Indices.set_used( source->Indices.size () ); + dest->Vertices.set_used(source->MeshHeader.numVertices); + dest->Indices.set_used(source->Indices.size()); u32 i; // fill in static face info - for ( i = 0; i < source->Indices.size(); i += 3 ) + for (i = 0; i < source->Indices.size(); i += 3) { dest->Indices[i + 0] = (u16) source->Indices[i + 0]; dest->Indices[i + 1] = (u16) source->Indices[i + 1]; @@ -206,7 +242,7 @@ IMeshBuffer * CAnimatedMeshMD3::createMeshBuffer(const SMD3MeshBuffer* source, } // fill in static vertex info - for ( i = 0; i!= (u32)source->MeshHeader.numVertices; ++i ) + for (i = 0; i!= (u32)source->MeshHeader.numVertices; ++i) { video::S3DVertex2TCoords &v = dest->Vertices[i]; v.Color = 0xFFFFFFFF; @@ -219,9 +255,9 @@ IMeshBuffer * CAnimatedMeshMD3::createMeshBuffer(const SMD3MeshBuffer* source, // load static texture u32 pos = 0; quake3::tTexArray textureArray; - quake3::getTextures( textureArray, source->Shader, pos, fs, driver ); + quake3::getTextures(textureArray, source->Shader, pos, fs, driver); dest->Material.MaterialType = video::EMT_SOLID; - dest->Material.setTexture ( 0, textureArray[0] ); + dest->Material.setTexture(0, textureArray[0]); dest->Material.Lighting = false; return dest; @@ -229,14 +265,13 @@ IMeshBuffer * CAnimatedMeshMD3::createMeshBuffer(const SMD3MeshBuffer* source, //! build final mesh's vertices from frames frameA and frameB with linear interpolation. -void CAnimatedMeshMD3::buildVertexArray ( u32 frameA, u32 frameB, f32 interpolate, - const SMD3MeshBuffer * source, - SMeshBufferLightMap * dest - ) +void CAnimatedMeshMD3::buildVertexArray(u32 frameA, u32 frameB, f32 interpolate, + const SMD3MeshBuffer* source, + SMeshBufferLightMap* dest) { const u32 frameOffsetA = frameA * source->MeshHeader.numVertices; const u32 frameOffsetB = frameB * source->MeshHeader.numVertices; - const f32 scale = ( 1.f/ 64.f ); + const f32 scale = (1.f/ 64.f); for (s32 i = 0; i != source->MeshHeader.numVertices; ++i) { @@ -246,30 +281,30 @@ void CAnimatedMeshMD3::buildVertexArray ( u32 frameA, u32 frameB, f32 interpolat const SMD3Vertex &vB = source->Vertices [ frameOffsetB + i ]; // position - v.Pos.X = scale * ( vA.position[0] + interpolate * ( vB.position[0] - vA.position[0] ) ); - v.Pos.Y = scale * ( vA.position[2] + interpolate * ( vB.position[2] - vA.position[2] ) ); - v.Pos.Z = scale * ( vA.position[1] + interpolate * ( vB.position[1] - vA.position[1] ) ); + v.Pos.X = scale * (vA.position[0] + interpolate * (vB.position[0] - vA.position[0])); + v.Pos.Y = scale * (vA.position[2] + interpolate * (vB.position[2] - vA.position[2])); + v.Pos.Z = scale * (vA.position[1] + interpolate * (vB.position[1] - vA.position[1])); // normal - const core::vector3df nA( quake3::getMD3Normal ( vA.normal[0], vA.normal[1] )); - const core::vector3df nB( quake3::getMD3Normal ( vB.normal[0], vB.normal[1] )); + const core::vector3df nA(quake3::getMD3Normal(vA.normal[0], vA.normal[1])); + const core::vector3df nB(quake3::getMD3Normal(vB.normal[0], vB.normal[1])); - v.Normal.X = nA.X + interpolate * ( nB.X - nA.X ); - v.Normal.Y = nA.Z + interpolate * ( nB.Z - nA.Z ); - v.Normal.Z = nA.Y + interpolate * ( nB.Y - nA.Y ); + v.Normal.X = nA.X + interpolate * (nB.X - nA.X); + v.Normal.Y = nA.Z + interpolate * (nB.Z - nA.Z); + v.Normal.Z = nA.Y + interpolate * (nB.Y - nA.Y); } - dest->recalculateBoundingBox (); + dest->recalculateBoundingBox(); } //! build final mesh's tag from frames frameA and frameB with linear interpolation. -void CAnimatedMeshMD3::buildTagArray ( u32 frameA, u32 frameB, f32 interpolate ) +void CAnimatedMeshMD3::buildTagArray(u32 frameA, u32 frameB, f32 interpolate) { const u32 frameOffsetA = frameA * Mesh->MD3Header.numTags; const u32 frameOffsetB = frameB * Mesh->MD3Header.numTags; - for ( s32 i = 0; i != Mesh->MD3Header.numTags; ++i ) + for (s32 i = 0; i != Mesh->MD3Header.numTags; ++i) { SMD3QuaternionTag &d = TagListIPol [ i ]; @@ -277,12 +312,12 @@ void CAnimatedMeshMD3::buildTagArray ( u32 frameA, u32 frameB, f32 interpolate ) const SMD3QuaternionTag &qB = Mesh->TagList[ frameOffsetB + i]; // rotation - d.rotation.slerp( qA.rotation, qB.rotation, interpolate ); + d.rotation.slerp(qA.rotation, qB.rotation, interpolate); // position - d.position.X = qA.position.X + interpolate * ( qB.position.X - qA.position.X ); - d.position.Y = qA.position.Y + interpolate * ( qB.position.Y - qA.position.Y ); - d.position.Z = qA.position.Z + interpolate * ( qB.position.Z - qA.position.Z ); + d.position.X = qA.position.X + interpolate * (qB.position.X - qA.position.X); + d.position.Y = qA.position.Y + interpolate * (qB.position.Y - qA.position.Y); + d.position.Z = qA.position.Z + interpolate * (qB.position.Z - qA.position.Z); } } @@ -290,17 +325,17 @@ void CAnimatedMeshMD3::buildTagArray ( u32 frameA, u32 frameB, f32 interpolate ) /*! loads a model */ -bool CAnimatedMeshMD3::loadModelFile( u32 modelIndex, io::IReadFile* file, - io::IFileSystem* fs, video::IVideoDriver * driver) +bool CAnimatedMeshMD3::loadModelFile(u32 modelIndex, io::IReadFile* file, + io::IFileSystem* fs, video::IVideoDriver* driver) { if (!file) return false; //! Check MD3Header { - file->read( &Mesh->MD3Header, sizeof(SMD3Header) ); + file->read(&Mesh->MD3Header, sizeof(SMD3Header)); - if ( strncmp("IDP3", Mesh->MD3Header.headerID, 4) ) + if (strncmp("IDP3", Mesh->MD3Header.headerID, 4)) { os::Printer::log("MD3 Loader: invalid header"); return false; @@ -312,13 +347,13 @@ bool CAnimatedMeshMD3::loadModelFile( u32 modelIndex, io::IReadFile* file, u32 i; - //! Frame Data ( ignore ) + //! Frame Data (ignore) #if 0 SMD3Frame frameImport; - file->seek ( Mesh->MD3Header.frameStart ); - for (i = 0; i != Mesh->MD3Header.numFrames; ++i ) + file->seek(Mesh->MD3Header.frameStart); + for (i = 0; i != Mesh->MD3Header.numFrames; ++i) { - file->read(&frameImport, sizeof(frameImport) ); + file->read(&frameImport, sizeof(frameImport)); } #endif @@ -327,11 +362,11 @@ bool CAnimatedMeshMD3::loadModelFile( u32 modelIndex, io::IReadFile* file, SMD3Tag import; - file->seek( Mesh->MD3Header.tagStart ); - Mesh->TagList.set_used ( totalTags ); - for (i = 0; i != totalTags; ++i ) + file->seek(Mesh->MD3Header.tagStart); + Mesh->TagList.set_used(totalTags); + for (i = 0; i != totalTags; ++i) { - file->read(&import, sizeof(import) ); + file->read(&import, sizeof(import)); SMD3QuaternionTag &exp = Mesh->TagList[i]; @@ -344,84 +379,84 @@ bool CAnimatedMeshMD3::loadModelFile( u32 modelIndex, io::IReadFile* file, exp.position.Z = import.position[1]; //! construct quaternion from a RH 3x3 Matrix - exp.rotation.set (import.rotationMatrix[7], + exp.rotation.set(import.rotationMatrix[7], 0.f, -import.rotationMatrix[6], 1 + import.rotationMatrix[8]); - exp.rotation.normalize (); + exp.rotation.normalize(); } //! Meshes u32 offset = Mesh->MD3Header.tagEnd; - for (i = 0; i != (u32)Mesh->MD3Header.numMeshes; ++i ) + for (i = 0; i != (u32)Mesh->MD3Header.numMeshes; ++i) { //! construct a new mesh buffer - SMD3MeshBuffer * buf = new SMD3MeshBuffer (); + SMD3MeshBuffer * buf = new SMD3MeshBuffer(); // !read mesh header info SMD3MeshHeader &meshHeader = buf->MeshHeader; //! read mesh info - file->seek( offset ); - file->read( &meshHeader, sizeof(SMD3MeshHeader) ); + file->seek(offset); + file->read(&meshHeader, sizeof(SMD3MeshHeader)); //! prepare memory - buf->Vertices.set_used ( meshHeader.numVertices * Mesh->MD3Header.numFrames ); - buf->Indices.set_used ( meshHeader.numTriangles * 3 ); - buf->Tex.set_used ( meshHeader.numVertices ); + buf->Vertices.set_used(meshHeader.numVertices * Mesh->MD3Header.numFrames); + buf->Indices.set_used(meshHeader.numTriangles * 3); + buf->Tex.set_used(meshHeader.numVertices); //! read skins (shaders). should be 1 per meshbuffer SMD3Shader skin; - file->seek( offset + buf->MeshHeader.offset_shaders ); - for ( s32 g = 0; g != buf->MeshHeader.numShader; ++g ) + file->seek(offset + buf->MeshHeader.offset_shaders); + for (s32 g = 0; g != buf->MeshHeader.numShader; ++g) { - file->read( &skin, sizeof(skin) ); + file->read(&skin, sizeof(skin)); io::path name; - cutFilenameExtension ( name, skin.name ); - name.replace ( '\\', '/' ); + cutFilenameExtension(name, skin.name); + name.replace('\\', '/'); buf->Shader = name; } //! read texture coordinates - file->seek( offset + buf->MeshHeader.offset_st); - file->read( buf->Tex.pointer(), buf->MeshHeader.numVertices * sizeof(SMD3TexCoord) ); + file->seek(offset + buf->MeshHeader.offset_st); + file->read(buf->Tex.pointer(), buf->MeshHeader.numVertices * sizeof(SMD3TexCoord)); //! read vertices file->seek(offset + meshHeader.vertexStart); - file->read( buf->Vertices.pointer(), Mesh->MD3Header.numFrames * meshHeader.numVertices * sizeof(SMD3Vertex) ); + file->read(buf->Vertices.pointer(), Mesh->MD3Header.numFrames * meshHeader.numVertices * sizeof(SMD3Vertex)); //! read indices - file->seek( offset + meshHeader.offset_triangles ); - file->read( buf->Indices.pointer(), meshHeader.numTriangles * sizeof(SMD3Face) ); + file->seek(offset + meshHeader.offset_triangles); + file->read(buf->Indices.pointer(), meshHeader.numTriangles * sizeof(SMD3Face)); //! store meshBuffer - Mesh->Buffer.push_back ( buf ); + Mesh->Buffer.push_back(buf); offset += meshHeader.offset_end; } // Init Mesh Interpolation - for ( i = 0; i != Mesh->Buffer.size (); ++i ) + for (i = 0; i != Mesh->Buffer.size(); ++i) { - IMeshBuffer * buffer = createMeshBuffer ( Mesh->Buffer[i], fs, driver ); - MeshIPol.addMeshBuffer ( buffer ); - buffer->drop (); + IMeshBuffer * buffer = createMeshBuffer(Mesh->Buffer[i], fs, driver); + MeshIPol->addMeshBuffer(buffer); + buffer->drop(); } - MeshIPol.recalculateBoundingBox (); + MeshIPol->recalculateBoundingBox(); // Init Tag Interpolation - for (i = 0; i != (u32)Mesh->MD3Header.numTags; ++i ) + for (i = 0; i != (u32)Mesh->MD3Header.numTags; ++i) { - TagListIPol.push_back ( Mesh->TagList[i] ); + TagListIPol.push_back(Mesh->TagList[i]); } return true; } -SMD3Mesh * CAnimatedMeshMD3::getOriginalMesh () +SMD3Mesh * CAnimatedMeshMD3::getOriginalMesh() { return Mesh; } @@ -430,7 +465,7 @@ SMD3Mesh * CAnimatedMeshMD3::getOriginalMesh () //! Returns an axis aligned bounding box const core::aabbox3d& CAnimatedMeshMD3::getBoundingBox() const { - return MeshIPol.BoundingBox; + return MeshIPol->BoundingBox; } diff --git a/source/Irrlicht/CAnimatedMeshMD3.h b/source/Irrlicht/CAnimatedMeshMD3.h index 40e41b30..6e60c637 100644 --- a/source/Irrlicht/CAnimatedMeshMD3.h +++ b/source/Irrlicht/CAnimatedMeshMD3.h @@ -24,52 +24,40 @@ namespace scene public: //! constructor - CAnimatedMeshMD3( ); + CAnimatedMeshMD3(); //! destructor virtual ~CAnimatedMeshMD3(); //! loads a quake3 md3 file - virtual bool loadModelFile( u32 modelIndex, io::IReadFile* file, - io::IFileSystem* fs, video::IVideoDriver * driver - ); + virtual bool loadModelFile(u32 modelIndex, io::IReadFile* file, + io::IFileSystem* fs, video::IVideoDriver* driver); // IAnimatedMeshMD3 - virtual void setInterpolationShift ( u32 shift, u32 loopMode ); - virtual SMD3Mesh * getOriginalMesh (); - virtual SMD3QuaternionTagList *getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop); + virtual void setInterpolationShift(u32 shift, u32 loopMode); + virtual SMD3Mesh* getOriginalMesh(); + virtual SMD3QuaternionTagList* getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop); //IAnimatedMesh virtual u32 getFrameCount() const; - virtual IMesh* getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop); + virtual IMesh* getMesh(s32 frame, s32 detailLevel, + s32 startFrameLoop, s32 endFrameLoop); virtual const core::aabbox3d& getBoundingBox() const; virtual E_ANIMATED_MESH_TYPE getMeshType() const; //! returns amount of mesh buffers. - virtual u32 getMeshBufferCount() const - { - return 0; - } + virtual u32 getMeshBufferCount() const; //! returns pointer to a mesh buffer - virtual IMeshBuffer* getMeshBuffer(u32 nr) const - { - return 0; - } + 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 - { - return 0; - } + virtual IMeshBuffer* getMeshBuffer(const video::SMaterial &material) const; - virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) - { - return; - } + virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue); + + //! set user axis aligned bounding box + virtual void setBoundingBox(const core::aabbox3df& box); //! set the hardware mapping hint, for driver virtual void setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX); @@ -77,16 +65,9 @@ namespace scene //! flags the meshbuffer as changed, reloads hardware buffers virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX); - //! set user axis aligned bounding box - virtual void setBoundingBox(const core::aabbox3df& box) - { - return; - } - - private: //! animates one frame - inline void Animate (u32 frame); + inline void Animate(u32 frame); video::SMaterial Material; @@ -100,9 +81,10 @@ namespace scene //! Cache Info struct SCacheInfo { - SCacheInfo ( s32 frame = -1, s32 start = -1, s32 end = -1 ) - : Frame ( frame ), startFrameLoop ( start ), - endFrameLoop ( end ) {} + SCacheInfo(s32 frame=-1, s32 start=-1, s32 end=-1 ) : + Frame(frame), startFrameLoop(start), + endFrameLoop(end) + {} bool operator == ( const SCacheInfo &other ) const { @@ -115,17 +97,17 @@ namespace scene SCacheInfo Current; //! return a Mesh per frame - SMesh MeshIPol; + SMesh* MeshIPol; SMD3QuaternionTagList TagListIPol; - IMeshBuffer * createMeshBuffer ( const SMD3MeshBuffer *source, io::IFileSystem* fs, video::IVideoDriver * driver ); + IMeshBuffer* createMeshBuffer(const SMD3MeshBuffer* source, + io::IFileSystem* fs, video::IVideoDriver* driver); - void buildVertexArray ( u32 frameA, u32 frameB, f32 interpolate, - const SMD3MeshBuffer * source, - SMeshBufferLightMap * dest - ); + void buildVertexArray(u32 frameA, u32 frameB, f32 interpolate, + const SMD3MeshBuffer* source, + SMeshBufferLightMap* dest); - void buildTagArray ( u32 frameA, u32 frameB, f32 interpolate ); + void buildTagArray(u32 frameA, u32 frameB, f32 interpolate); }; @@ -133,3 +115,4 @@ namespace scene } // end namespace irr #endif +