From 393b5cd1dc438872af89d334ef6e5fcc59f27d47 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Sun, 13 Jan 2013 17:24:39 +1000 Subject: Added Irrlicht 1.8, but without all the Windows binaries. --- .../source/Irrlicht/CMS3DMeshFileLoader.cpp | 818 +++++++++++++++++++++ 1 file changed, 818 insertions(+) create mode 100644 libraries/irrlicht-1.8/source/Irrlicht/CMS3DMeshFileLoader.cpp (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CMS3DMeshFileLoader.cpp') diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CMS3DMeshFileLoader.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CMS3DMeshFileLoader.cpp new file mode 100644 index 0000000..9a88d49 --- /dev/null +++ b/libraries/irrlicht-1.8/source/Irrlicht/CMS3DMeshFileLoader.cpp @@ -0,0 +1,818 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "IrrCompileConfig.h" +#ifdef _IRR_COMPILE_WITH_MS3D_LOADER_ + +#include "IReadFile.h" +#include "os.h" +#include "CMS3DMeshFileLoader.h" +#include "CSkinnedMesh.h" + + +namespace irr +{ +namespace scene +{ + +#ifdef _DEBUG +#define _IRR_DEBUG_MS3D_LOADER_ +#endif + +// byte-align structures +#include "irrpack.h" + +namespace { +// File header +struct MS3DHeader +{ + char ID[10]; + int Version; +} PACK_STRUCT; + +// Vertex information +struct MS3DVertex +{ + u8 Flags; + float Vertex[3]; + char BoneID; + u8 RefCount; +} PACK_STRUCT; + +// Triangle information +struct MS3DTriangle +{ + u16 Flags; + u16 VertexIndices[3]; + float VertexNormals[3][3]; + float S[3], T[3]; + u8 SmoothingGroup; + u8 GroupIndex; +} PACK_STRUCT; + +// Material information +struct MS3DMaterial +{ + char Name[32]; + float Ambient[4]; + float Diffuse[4]; + float Specular[4]; + float Emissive[4]; + float Shininess; // 0.0f - 128.0f + float Transparency; // 0.0f - 1.0f + u8 Mode; // 0, 1, 2 is unused now + char Texture[128]; + char Alphamap[128]; +} PACK_STRUCT; + +// Joint information +struct MS3DJoint +{ + u8 Flags; + char Name[32]; + char ParentName[32]; + float Rotation[3]; + float Translation[3]; + u16 NumRotationKeyframes; + u16 NumTranslationKeyframes; +} PACK_STRUCT; + +// Keyframe data +struct MS3DKeyframe +{ + float Time; + float Parameter[3]; +} PACK_STRUCT; + +// vertex weights in 1.8.x +struct MS3DVertexWeights +{ + char boneIds[3]; + u8 weights[3]; +} PACK_STRUCT; + +} // end namespace + +// Default alignment +#include "irrunpack.h" + +struct SGroup +{ + core::stringc Name; + core::array VertexIds; + u16 MaterialIdx; +}; + +//! Constructor +CMS3DMeshFileLoader::CMS3DMeshFileLoader(video::IVideoDriver *driver) +: Driver(driver), AnimatedMesh(0) +{ + #ifdef _DEBUG + setDebugName("CMS3DMeshFileLoader"); + #endif +} + + +//! returns true if the file maybe is able to be loaded by this class +//! based on the file extension (e.g. ".bsp") +bool CMS3DMeshFileLoader::isALoadableFileExtension(const io::path& filename) const +{ + return core::hasFileExtension ( filename, "ms3d" ); +} + + +//! 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 IReferenceCounted::drop() for more information. +IAnimatedMesh* CMS3DMeshFileLoader::createMesh(io::IReadFile* file) +{ + if (!file) + return 0; + + AnimatedMesh = new CSkinnedMesh(); + + if ( load(file) ) + { + AnimatedMesh->finalize(); + } + else + { + AnimatedMesh->drop(); + AnimatedMesh = 0; + } + + return AnimatedMesh; +} + + +//! loads a milkshape file +bool CMS3DMeshFileLoader::load(io::IReadFile* file) +{ + if (!file) + return false; + + // find file size + const long fileSize = file->getSize(); + + // read whole file + + u8* buffer = new u8[fileSize]; + s32 read = file->read(buffer, fileSize); + if (read != fileSize) + { + delete [] buffer; + os::Printer::log("Could not read full file. Loading failed", file->getFileName(), ELL_ERROR); + return false; + } + + // read header + + const u8 *pPtr = (u8*)((void*)buffer); + MS3DHeader *pHeader = (MS3DHeader*)pPtr; + pPtr += sizeof(MS3DHeader); + + if ( strncmp( pHeader->ID, "MS3D000000", 10 ) != 0 ) + { + delete [] buffer; + os::Printer::log("Not a valid Milkshape3D Model File. Loading failed", file->getFileName(), ELL_ERROR); + return false; + } + +#ifdef __BIG_ENDIAN__ + pHeader->Version = os::Byteswap::byteswap(pHeader->Version); +#endif + if ( pHeader->Version < 3 || pHeader->Version > 4 ) + { + delete [] buffer; + os::Printer::log("Only Milkshape3D version 3 and 4 (1.3 to 1.8) is supported. Loading failed", file->getFileName(), ELL_ERROR); + return false; + } +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Loaded header version", core::stringc(pHeader->Version).c_str()); +#endif + + // get pointers to data + + // vertices + u16 numVertices = *(u16*)pPtr; +#ifdef __BIG_ENDIAN__ + numVertices = os::Byteswap::byteswap(numVertices); +#endif +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Load vertices", core::stringc(numVertices).c_str()); +#endif + pPtr += sizeof(u16); + MS3DVertex *vertices = (MS3DVertex*)pPtr; + pPtr += sizeof(MS3DVertex) * numVertices; + if (pPtr > buffer+fileSize) + { + delete [] buffer; + os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + return false; + } + for (u16 tmp=0; tmp buffer+fileSize) + { + delete [] buffer; + os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + return false; + } + for (u16 tmp=0; tmp groups; + groups.reallocate(numGroups); + + //store groups + u32 i; + for (i=0; i buffer+fileSize) + { + delete [] buffer; + os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + return false; + } + } + + // load materials + u16 numMaterials = *(u16*)pPtr; +#ifdef __BIG_ENDIAN__ + numMaterials = os::Byteswap::byteswap(numMaterials); +#endif +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Load Materials", core::stringc(numMaterials).c_str()); +#endif + pPtr += sizeof(u16); + + if(numMaterials == 0) + { + // if there are no materials, add at least one buffer + AnimatedMesh->addMeshBuffer(); + } + + for (i=0; iAmbient[j] = os::Byteswap::byteswap(material->Ambient[j]); + for (u16 j=0; j<4; ++j) + material->Diffuse[j] = os::Byteswap::byteswap(material->Diffuse[j]); + for (u16 j=0; j<4; ++j) + material->Specular[j] = os::Byteswap::byteswap(material->Specular[j]); + for (u16 j=0; j<4; ++j) + material->Emissive[j] = os::Byteswap::byteswap(material->Emissive[j]); + material->Shininess = os::Byteswap::byteswap(material->Shininess); + material->Transparency = os::Byteswap::byteswap(material->Transparency); +#endif + pPtr += sizeof(MS3DMaterial); + if (pPtr > buffer+fileSize) + { + delete [] buffer; + os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + return false; + } + + scene::SSkinMeshBuffer *tmpBuffer = AnimatedMesh->addMeshBuffer(); + + tmpBuffer->Material.MaterialType = video::EMT_SOLID; + + tmpBuffer->Material.AmbientColor = video::SColorf(material->Ambient[0], material->Ambient[1], material->Ambient[2], material->Ambient[3]).toSColor (); + tmpBuffer->Material.DiffuseColor = video::SColorf(material->Diffuse[0], material->Diffuse[1], material->Diffuse[2], material->Diffuse[3]).toSColor (); + tmpBuffer->Material.EmissiveColor = video::SColorf(material->Emissive[0], material->Emissive[1], material->Emissive[2], material->Emissive[3]).toSColor (); + tmpBuffer->Material.SpecularColor = video::SColorf(material->Specular[0], material->Specular[1], material->Specular[2], material->Specular[3]).toSColor (); + tmpBuffer->Material.Shininess = material->Shininess; + + core::stringc TexturePath(material->Texture); + if (TexturePath.trim()!="") + { + TexturePath=stripPathFromString(file->getFileName(),true) + stripPathFromString(TexturePath,false); + tmpBuffer->Material.setTexture(0, Driver->getTexture(TexturePath)); + } + + core::stringc AlphamapPath=(const c8*)material->Alphamap; + if (AlphamapPath.trim()!="") + { + AlphamapPath=stripPathFromString(file->getFileName(),true) + stripPathFromString(AlphamapPath,false); + tmpBuffer->Material.setTexture(2, Driver->getTexture(AlphamapPath)); + } + } + + // animation time + f32 framesPerSecond = *(float*)pPtr; +#ifdef __BIG_ENDIAN__ + framesPerSecond = os::Byteswap::byteswap(framesPerSecond); +#endif +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("FPS", core::stringc(framesPerSecond).c_str()); +#endif + pPtr += sizeof(float) * 2; // fps and current time + + if (framesPerSecond<1.f) + framesPerSecond=1.f; + AnimatedMesh->setAnimationSpeed(framesPerSecond); + +// ignore, calculated inside SkinnedMesh +// s32 frameCount = *(int*)pPtr; +#ifdef __BIG_ENDIAN__ +// frameCount = os::Byteswap::byteswap(frameCount); +#endif + pPtr += sizeof(int); + + u16 jointCount = *(u16*)pPtr; +#ifdef __BIG_ENDIAN__ + jointCount = os::Byteswap::byteswap(jointCount); +#endif +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Joints", core::stringc(jointCount).c_str()); +#endif + pPtr += sizeof(u16); + if (pPtr > buffer+fileSize) + { + delete [] buffer; + os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + return false; + } + + core::array parentNames; + parentNames.reallocate(jointCount); + + // load joints + for (i=0; iRotation[j] = os::Byteswap::byteswap(pJoint->Rotation[j]); + for (j=0; j<3; ++j) + pJoint->Translation[j] = os::Byteswap::byteswap(pJoint->Translation[j]); + pJoint->NumRotationKeyframes= os::Byteswap::byteswap(pJoint->NumRotationKeyframes); + pJoint->NumTranslationKeyframes = os::Byteswap::byteswap(pJoint->NumTranslationKeyframes); +#endif + pPtr += sizeof(MS3DJoint); + if (pPtr > buffer+fileSize) + { + delete [] buffer; + os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + return false; + } + + ISkinnedMesh::SJoint *jnt = AnimatedMesh->addJoint(); + + jnt->Name = pJoint->Name; +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Joint", jnt->Name.c_str()); + os::Printer::log("Rotation keyframes", core::stringc(pJoint->NumRotationKeyframes).c_str()); + os::Printer::log("Translation keyframes", core::stringc(pJoint->NumTranslationKeyframes).c_str()); +#endif + jnt->LocalMatrix.makeIdentity(); + jnt->LocalMatrix.setRotationRadians( + core::vector3df(pJoint->Rotation[0], pJoint->Rotation[1], pJoint->Rotation[2]) ); + // convert right-handed to left-handed + jnt->LocalMatrix[2]=-jnt->LocalMatrix[2]; + jnt->LocalMatrix[6]=-jnt->LocalMatrix[6]; + jnt->LocalMatrix[8]=-jnt->LocalMatrix[8]; + jnt->LocalMatrix[9]=-jnt->LocalMatrix[9]; + + jnt->LocalMatrix.setTranslation( + core::vector3df(pJoint->Translation[0], pJoint->Translation[1], -pJoint->Translation[2]) ); + jnt->Animatedposition.set(jnt->LocalMatrix.getTranslation()); + jnt->Animatedrotation.set(jnt->LocalMatrix.getRotationDegrees()); + + parentNames.push_back( (c8*)pJoint->ParentName ); + + /*if (pJoint->NumRotationKeyframes || + pJoint->NumTranslationKeyframes) + HasAnimation = true; + */ + + // get rotation keyframes + const u16 numRotationKeyframes = pJoint->NumRotationKeyframes; + for (j=0; j < numRotationKeyframes; ++j) + { + MS3DKeyframe* kf = (MS3DKeyframe*)pPtr; +#ifdef __BIG_ENDIAN__ + kf->Time = os::Byteswap::byteswap(kf->Time); + for (u32 l=0; l<3; ++l) + kf->Parameter[l] = os::Byteswap::byteswap(kf->Parameter[l]); +#endif + pPtr += sizeof(MS3DKeyframe); + if (pPtr > buffer+fileSize) + { + delete [] buffer; + os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + return false; + } + + ISkinnedMesh::SRotationKey *k=AnimatedMesh->addRotationKey(jnt); + k->frame = kf->Time * framesPerSecond-1; + + core::matrix4 tmpMatrix; + + tmpMatrix.setRotationRadians( + core::vector3df(kf->Parameter[0], kf->Parameter[1], kf->Parameter[2]) ); + // convert right-handed to left-handed + tmpMatrix[2]=-tmpMatrix[2]; + tmpMatrix[6]=-tmpMatrix[6]; + tmpMatrix[8]=-tmpMatrix[8]; + tmpMatrix[9]=-tmpMatrix[9]; + + tmpMatrix=jnt->LocalMatrix*tmpMatrix; + + // IRR_TEST_BROKEN_QUATERNION_USE: TODO - switched from tmpMatrix to tmpMatrix.getTransposed() for downward compatibility. + // Not tested so far if this was correct or wrong before quaternion fix! + k->rotation = core::quaternion(tmpMatrix.getTransposed()); + } + + // get translation keyframes + const u16 numTranslationKeyframes = pJoint->NumTranslationKeyframes; + for (j=0; jTime = os::Byteswap::byteswap(kf->Time); + for (u32 l=0; l<3; ++l) + kf->Parameter[l] = os::Byteswap::byteswap(kf->Parameter[l]); +#endif + pPtr += sizeof(MS3DKeyframe); + if (pPtr > buffer+fileSize) + { + delete [] buffer; + os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + return false; + } + + ISkinnedMesh::SPositionKey *k=AnimatedMesh->addPositionKey(jnt); + k->frame = kf->Time * framesPerSecond-1; + + k->position = core::vector3df + (kf->Parameter[0]+pJoint->Translation[0], + kf->Parameter[1]+pJoint->Translation[1], + -kf->Parameter[2]-pJoint->Translation[2]); + } + } + + core::array vertexWeights; + f32 weightFactor=0; + + if (jointCount && (pHeader->Version == 4) && (pPtr < buffer+fileSize)) + { + s32 subVersion = *(s32*)pPtr; // comment subVersion, always 1 +#ifdef __BIG_ENDIAN__ + subVersion = os::Byteswap::byteswap(subVersion); +#endif + pPtr += sizeof(s32); + + for (u32 j=0; j<4; ++j) // four comment groups + { +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Skipping comment group", core::stringc(j+1).c_str()); +#endif + u32 numComments = *(u32*)pPtr; +#ifdef __BIG_ENDIAN__ + numComments = os::Byteswap::byteswap(numComments); +#endif + pPtr += sizeof(u32); + for (i=0; i buffer+fileSize) + { + delete [] buffer; + os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + return false; + } + } + + if (pPtr < buffer+fileSize) + { + subVersion = *(s32*)pPtr; // vertex subVersion, 1 or 2 +#ifdef __BIG_ENDIAN__ + subVersion = os::Byteswap::byteswap(subVersion); +#endif + if (subVersion==1) + weightFactor=1.f/255.f; + else + weightFactor=1.f/100.f; + pPtr += sizeof(s32); + +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Reading vertex weights"); +#endif + // read vertex weights, ignoring data 'extra' from 1.8.2 + vertexWeights.reallocate(numVertices); + const char offset = (subVersion==1)?6:10; + for (i=0; i buffer+fileSize) + { + delete [] buffer; + os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + return false; + } + } + + if (pPtr < buffer+fileSize) + { + subVersion = *(s32*)pPtr; // joint subVersion, 1 or 2 +#ifdef __BIG_ENDIAN__ + subVersion = os::Byteswap::byteswap(subVersion); +#endif + pPtr += sizeof(s32); + // skip joint colors +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Skip joint color"); +#endif + pPtr += 3*sizeof(float)*jointCount; + + if (pPtr > buffer+fileSize) + { + delete [] buffer; + os::Printer::log("Loading failed. Corrupted data found", file->getFileName(), ELL_ERROR); + return false; + } + } + + if (pPtr < buffer+fileSize) + { + subVersion = *(s32*)pPtr; // model subVersion, 1 or 2 +#ifdef __BIG_ENDIAN__ + subVersion = os::Byteswap::byteswap(subVersion); +#endif + pPtr += sizeof(s32); +#ifdef _IRR_DEBUG_MS3D_LOADER_ + os::Printer::log("Skip model extra information"); +#endif + // now the model extra information would follow + // we also skip this for now + } + } + + //find parent of every joint + for (u32 jointnum=0; jointnumgetAllJoints().size(); ++jointnum) + { + for (u32 j2=0; j2getAllJoints().size(); ++j2) + { + if (jointnum != j2 && parentNames[jointnum] == AnimatedMesh->getAllJoints()[j2]->Name ) + { + AnimatedMesh->getAllJoints()[j2]->Children.push_back(AnimatedMesh->getAllJoints()[jointnum]); + break; + } + } + } + + // create vertices and indices, attach them to the joints. + video::S3DVertex v; + core::array *Vertices; + core::array Indices; + + for (i=0; igetMeshBuffers()[tmp]->Vertices_Standard; + + for (s32 j = 2; j!=-1; --j) + { + const u32 vertidx = triangles[i].VertexIndices[j]; + + v.TCoords.X = triangles[i].S[j]; + v.TCoords.Y = triangles[i].T[j]; + + v.Normal.X = triangles[i].VertexNormals[j][0]; + v.Normal.Y = triangles[i].VertexNormals[j][1]; + v.Normal.Z = triangles[i].VertexNormals[j][2]; + + if(triangles[i].GroupIndex < groups.size() && + groups[triangles[i].GroupIndex].MaterialIdx < AnimatedMesh->getMeshBuffers().size()) + v.Color = AnimatedMesh->getMeshBuffers()[groups[triangles[i].GroupIndex].MaterialIdx]->Material.DiffuseColor; + else + v.Color.set(255,255,255,255); + + v.Pos.X = vertices[vertidx].Vertex[0]; + v.Pos.Y = vertices[vertidx].Vertex[1]; + v.Pos.Z = vertices[vertidx].Vertex[2]; + + // check if we already have this vertex in our vertex array + s32 index = -1; + for (u32 iV = 0; iV < Vertices->size(); ++iV) + { + if (v == (*Vertices)[iV]) + { + index = (s32)iV; + break; + } + } + + if (index == -1) + { + index = Vertices->size(); + const u32 matidx = groups[triangles[i].GroupIndex].MaterialIdx; + if (vertexWeights.size()==0) + { + const s32 boneid = vertices[vertidx].BoneID; + if ((u32)boneid < AnimatedMesh->getAllJoints().size()) + { + ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); + w->buffer_id = matidx; + w->strength = 1.0f; + w->vertex_id = index; + } + } + else if (jointCount) // new weights from 1.8.x + { + f32 sum = 1.0f; + s32 boneid = vertices[vertidx].BoneID; + if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[0] != 0)) + { + ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); + w->buffer_id = matidx; + sum -= (w->strength = vertexWeights[vertidx].weights[0]*weightFactor); + w->vertex_id = index; + } + boneid = vertexWeights[vertidx].boneIds[0]; + if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[1] != 0)) + { + ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); + w->buffer_id = matidx; + sum -= (w->strength = vertexWeights[vertidx].weights[1]*weightFactor); + w->vertex_id = index; + } + boneid = vertexWeights[vertidx].boneIds[1]; + if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (vertexWeights[vertidx].weights[2] != 0)) + { + ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); + w->buffer_id = matidx; + sum -= (w->strength = vertexWeights[vertidx].weights[2]*weightFactor); + w->vertex_id = index; + } + boneid = vertexWeights[vertidx].boneIds[2]; + if (((u32)boneid < AnimatedMesh->getAllJoints().size()) && (sum > 0.f)) + { + ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); + w->buffer_id = matidx; + w->strength = sum; + w->vertex_id = index; + } + // fallback, if no bone chosen. Seems to be an error in the specs + boneid = vertices[vertidx].BoneID; + if ((sum == 1.f) && ((u32)boneid < AnimatedMesh->getAllJoints().size())) + { + ISkinnedMesh::SWeight *w=AnimatedMesh->addWeight(AnimatedMesh->getAllJoints()[boneid]); + w->buffer_id = matidx; + w->strength = 1.f; + w->vertex_id = index; + } + } + + Vertices->push_back(v); + } + Indices.push_back(index); + } + } + + //create groups + s32 iIndex = -1; + for (i=0; i= AnimatedMesh->getMeshBuffers().size()) + grp.MaterialIdx = 0; + + core::array& indices = AnimatedMesh->getMeshBuffers()[grp.MaterialIdx]->Indices; + + for (u32 k=0; k < grp.VertexIds.size(); ++k) + for (u32 l=0; l<3; ++l) + indices.push_back(Indices[++iIndex]); + } + + delete [] buffer; + + return true; +} + + +core::stringc CMS3DMeshFileLoader::stripPathFromString(const core::stringc& inString, bool returnPath) const +{ + s32 slashIndex=inString.findLast('/'); // forward slash + s32 backSlash=inString.findLast('\\'); // back slash + + if (backSlash>slashIndex) slashIndex=backSlash; + + if (slashIndex==-1)//no slashes found + { + if (returnPath) + return core::stringc(); //no path to return + else + return inString; + } + + if (returnPath) + return inString.subString(0, slashIndex + 1); + else + return inString.subString(slashIndex+1, inString.size() - (slashIndex+1)); +} + + +} // end namespace scene +} // end namespace irr + +#endif -- cgit v1.1