From 959831f4ef5a3e797f576c3de08cd65032c997ad Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Sun, 13 Jan 2013 18:54:10 +1000 Subject: Remove damned ancient DOS line endings from Irrlicht. Hopefully I did not go overboard. --- .../source/Irrlicht/CPLYMeshFileLoader.cpp | 1634 ++++++++++---------- 1 file changed, 817 insertions(+), 817 deletions(-) (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CPLYMeshFileLoader.cpp') diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CPLYMeshFileLoader.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CPLYMeshFileLoader.cpp index 1ef4946..ef3e399 100644 --- a/libraries/irrlicht-1.8/source/Irrlicht/CPLYMeshFileLoader.cpp +++ b/libraries/irrlicht-1.8/source/Irrlicht/CPLYMeshFileLoader.cpp @@ -1,817 +1,817 @@ -// Copyright (C) 2009-2012 Gaz Davidson -// 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_PLY_LOADER_ - -#include "CPLYMeshFileLoader.h" -#include "IMeshManipulator.h" -#include "SMesh.h" -#include "CDynamicMeshBuffer.h" -#include "SAnimatedMesh.h" -#include "IReadFile.h" -#include "fast_atof.h" -#include "os.h" - -namespace irr -{ -namespace scene -{ - -// input buffer must be at least twice as long as the longest line in the file -#define PLY_INPUT_BUFFER_SIZE 51200 // file is loaded in 50k chunks - -// constructor -CPLYMeshFileLoader::CPLYMeshFileLoader(scene::ISceneManager* smgr) -: SceneManager(smgr), File(0), Buffer(0) -{ -} - - -CPLYMeshFileLoader::~CPLYMeshFileLoader() -{ - // delete the buffer in case we didn't earlier - // (we do, but this could be disabled to increase the speed of loading hundreds of meshes) - if (Buffer) - { - delete [] Buffer; - Buffer = 0; - } - - // Destroy the element list if it exists - for (u32 i=0; igrab(); - - // attempt to allocate the buffer and fill with data - if (!allocateBuffer()) - { - File->drop(); - File = 0; - return 0; - } - - // start with empty mesh - SAnimatedMesh* animMesh = 0; - u32 vertCount=0; - - // Currently only supports ASCII meshes - if (strcmp(getNextLine(), "ply")) - { - os::Printer::log("Not a valid PLY file", file->getFileName().c_str(), ELL_ERROR); - } - else - { - // cut the next line out - getNextLine(); - // grab the word from this line - c8 *word = getNextWord(); - - // ignore comments - while (strcmp(word, "comment") == 0) - { - getNextLine(); - word = getNextWord(); - } - - bool readingHeader = true; - bool continueReading = true; - IsBinaryFile = false; - IsWrongEndian= false; - - do - { - if (strcmp(word, "format") == 0) - { - word = getNextWord(); - - if (strcmp(word, "binary_little_endian") == 0) - { - IsBinaryFile = true; -#ifdef __BIG_ENDIAN__ - IsWrongEndian = true; -#endif - - } - else if (strcmp(word, "binary_big_endian") == 0) - { - IsBinaryFile = true; -#ifndef __BIG_ENDIAN__ - IsWrongEndian = true; -#endif - } - else if (strcmp(word, "ascii")) - { - // abort if this isn't an ascii or a binary mesh - os::Printer::log("Unsupported PLY mesh format", word, ELL_ERROR); - continueReading = false; - } - - if (continueReading) - { - word = getNextWord(); - if (strcmp(word, "1.0")) - { - os::Printer::log("Unsupported PLY mesh version", word, ELL_WARNING); - } - } - } - else if (strcmp(word, "property") == 0) - { - word = getNextWord(); - - if (!ElementList.size()) - { - os::Printer::log("PLY property found before element", word, ELL_WARNING); - } - else - { - // get element - SPLYElement* el = ElementList[ElementList.size()-1]; - - // fill property struct - SPLYProperty prop; - prop.Type = getPropertyType(word); - el->KnownSize += prop.size(); - - if (prop.Type == EPLYPT_LIST) - { - el->IsFixedWidth = false; - - word = getNextWord(); - - prop.Data.List.CountType = getPropertyType(word); - if (IsBinaryFile && prop.Data.List.CountType == EPLYPT_UNKNOWN) - { - os::Printer::log("Cannot read binary PLY file containing data types of unknown length", word, ELL_ERROR); - continueReading = false; - } - else - { - word = getNextWord(); - prop.Data.List.ItemType = getPropertyType(word); - if (IsBinaryFile && prop.Data.List.ItemType == EPLYPT_UNKNOWN) - { - os::Printer::log("Cannot read binary PLY file containing data types of unknown length", word, ELL_ERROR); - continueReading = false; - } - } - } - else if (IsBinaryFile && prop.Type == EPLYPT_UNKNOWN) - { - os::Printer::log("Cannot read binary PLY file containing data types of unknown length", word, ELL_ERROR); - continueReading = false; - } - - prop.Name = getNextWord(); - - // add property to element - el->Properties.push_back(prop); - } - } - else if (strcmp(word, "element") == 0) - { - SPLYElement* el = new SPLYElement; - el->Name = getNextWord(); - el->Count = atoi(getNextWord()); - el->IsFixedWidth = true; - el->KnownSize = 0; - ElementList.push_back(el); - - if (el->Name == "vertex") - vertCount = el->Count; - - } - else if (strcmp(word, "end_header") == 0) - { - readingHeader = false; - if (IsBinaryFile) - { - StartPointer = LineEndPointer + 1; - } - } - else if (strcmp(word, "comment") == 0) - { - // ignore line - } - else - { - os::Printer::log("Unknown item in PLY file", word, ELL_WARNING); - } - - if (readingHeader && continueReading) - { - getNextLine(); - word = getNextWord(); - } - } - while (readingHeader && continueReading); - - // now to read the actual data from the file - if (continueReading) - { - // create a mesh buffer - CDynamicMeshBuffer *mb = new CDynamicMeshBuffer(video::EVT_STANDARD, vertCount > 65565 ? video::EIT_32BIT : video::EIT_16BIT); - mb->getVertexBuffer().reallocate(vertCount); - mb->getIndexBuffer().reallocate(vertCount); - mb->setHardwareMappingHint(EHM_STATIC); - - bool hasNormals=true; - // loop through each of the elements - for (u32 i=0; iName == "vertex") - { - // loop through vertex properties - for (u32 j=0; j < ElementList[i]->Count; ++j) - hasNormals &= readVertex(*ElementList[i], mb); - } - else if (ElementList[i]->Name == "face") - { - // read faces - for (u32 j=0; j < ElementList[i]->Count; ++j) - readFace(*ElementList[i], mb); - } - else - { - // skip these elements - for (u32 j=0; j < ElementList[i]->Count; ++j) - skipElement(*ElementList[i]); - } - } - mb->recalculateBoundingBox(); - if (!hasNormals) - SceneManager->getMeshManipulator()->recalculateNormals(mb); - SMesh* m = new SMesh(); - m->addMeshBuffer(mb); - m->recalculateBoundingBox(); - mb->drop(); - animMesh = new SAnimatedMesh(); - animMesh->addMesh(m); - animMesh->recalculateBoundingBox(); - m->drop(); - } - } - - - // free the buffer - delete [] Buffer; - Buffer = 0; - File->drop(); - File = 0; - - // if we managed to create a mesh, return it - return animMesh; -} - - -bool CPLYMeshFileLoader::readVertex(const SPLYElement &Element, scene::CDynamicMeshBuffer* mb) -{ - if (!IsBinaryFile) - getNextLine(); - - video::S3DVertex vert; - vert.Color.set(255,255,255,255); - vert.TCoords.X = 0.0f; - vert.TCoords.Y = 0.0f; - vert.Normal.X = 0.0f; - vert.Normal.Y = 1.0f; - vert.Normal.Z = 0.0f; - - bool result=false; - for (u32 i=0; i < Element.Properties.size(); ++i) - { - E_PLY_PROPERTY_TYPE t = Element.Properties[i].Type; - - if (Element.Properties[i].Name == "x") - vert.Pos.X = getFloat(t); - else if (Element.Properties[i].Name == "y") - vert.Pos.Z = getFloat(t); - else if (Element.Properties[i].Name == "z") - vert.Pos.Y = getFloat(t); - else if (Element.Properties[i].Name == "nx") - { - vert.Normal.X = getFloat(t); - result=true; - } - else if (Element.Properties[i].Name == "ny") - { - vert.Normal.Z = getFloat(t); - result=true; - } - else if (Element.Properties[i].Name == "nz") - { - vert.Normal.Y = getFloat(t); - result=true; - } - else if (Element.Properties[i].Name == "u") - vert.TCoords.X = getFloat(t); - else if (Element.Properties[i].Name == "v") - vert.TCoords.Y = getFloat(t); - else if (Element.Properties[i].Name == "red") - { - u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t); - vert.Color.setRed(value); - } - else if (Element.Properties[i].Name == "green") - { - u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t); - vert.Color.setGreen(value); - } - else if (Element.Properties[i].Name == "blue") - { - u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t); - vert.Color.setBlue(value); - } - else if (Element.Properties[i].Name == "alpha") - { - u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t); - vert.Color.setAlpha(value); - } - else - skipProperty(Element.Properties[i]); - } - - mb->getVertexBuffer().push_back(vert); - - return result; -} - - -bool CPLYMeshFileLoader::readFace(const SPLYElement &Element, scene::CDynamicMeshBuffer* mb) -{ - if (!IsBinaryFile) - getNextLine(); - - for (u32 i=0; i < Element.Properties.size(); ++i) - { - if ( (Element.Properties[i].Name == "vertex_indices" || - Element.Properties[i].Name == "vertex_index") && Element.Properties[i].Type == EPLYPT_LIST) - { - // get count - s32 count = getInt(Element.Properties[i].Data.List.CountType); - u32 a = getInt(Element.Properties[i].Data.List.ItemType), - b = getInt(Element.Properties[i].Data.List.ItemType), - c = getInt(Element.Properties[i].Data.List.ItemType); - s32 j = 3; - - mb->getIndexBuffer().push_back(a); - mb->getIndexBuffer().push_back(c); - mb->getIndexBuffer().push_back(b); - - for (; j < count; ++j) - { - b = c; - c = getInt(Element.Properties[i].Data.List.ItemType); - mb->getIndexBuffer().push_back(a); - mb->getIndexBuffer().push_back(c); - mb->getIndexBuffer().push_back(b); - } - } - else if (Element.Properties[i].Name == "intensity") - { - // todo: face intensity - skipProperty(Element.Properties[i]); - } - else - skipProperty(Element.Properties[i]); - } - return true; -} - - -// skips an element and all properties. return false on EOF -void CPLYMeshFileLoader::skipElement(const SPLYElement &Element) -{ - if (IsBinaryFile) - if (Element.IsFixedWidth) - moveForward(Element.KnownSize); - else - for (u32 i=0; i < Element.Properties.size(); ++i) - skipProperty(Element.Properties[i]); - else - getNextLine(); -} - - -void CPLYMeshFileLoader::skipProperty(const SPLYProperty &Property) -{ - if (Property.Type == EPLYPT_LIST) - { - s32 count = getInt(Property.Data.List.CountType); - - for (s32 i=0; i < count; ++i) - getInt(Property.Data.List.CountType); - } - else - { - if (IsBinaryFile) - moveForward(Property.size()); - else - getNextWord(); - } -} - - -bool CPLYMeshFileLoader::allocateBuffer() -{ - // Destroy the element list if it exists - for (u32 i=0; igetPos() == File->getSize()) - { - EndOfFile = true; - } - else - { - // read data from the file - u32 count = File->read(EndPointer, PLY_INPUT_BUFFER_SIZE - length); - - // increment the end pointer by the number of bytes read - EndPointer = EndPointer + count; - - // if we didn't completely fill the buffer - if (count != PLY_INPUT_BUFFER_SIZE - length) - { - // blank the rest of the memory - memset(EndPointer, 0, Buffer + PLY_INPUT_BUFFER_SIZE - EndPointer); - - // end of file - EndOfFile = true; - } - } -} - - -// skips x bytes in the file, getting more data if required -void CPLYMeshFileLoader::moveForward(u32 bytes) -{ - if (StartPointer + bytes >= EndPointer) - fillBuffer(); - if (StartPointer + bytes < EndPointer) - StartPointer += bytes; - else - StartPointer = EndPointer; -} - - -E_PLY_PROPERTY_TYPE CPLYMeshFileLoader::getPropertyType(const c8* typeString) const -{ - if (strcmp(typeString, "char") == 0 || - strcmp(typeString, "uchar") == 0 || - strcmp(typeString, "int8") == 0 || - strcmp(typeString, "uint8") == 0) - { - return EPLYPT_INT8; - } - else if (strcmp(typeString, "uint") == 0 || - strcmp(typeString, "int16") == 0 || - strcmp(typeString, "uint16") == 0 || - strcmp(typeString, "short") == 0 || - strcmp(typeString, "ushort") == 0) - { - return EPLYPT_INT16; - } - else if (strcmp(typeString, "int") == 0 || - strcmp(typeString, "long") == 0 || - strcmp(typeString, "ulong") == 0 || - strcmp(typeString, "int32") == 0 || - strcmp(typeString, "uint32") == 0) - { - return EPLYPT_INT32; - } - else if (strcmp(typeString, "float") == 0 || - strcmp(typeString, "float32") == 0) - { - return EPLYPT_FLOAT32; - } - else if (strcmp(typeString, "float64") == 0 || - strcmp(typeString, "double") == 0) - { - return EPLYPT_FLOAT64; - } - else if ( strcmp(typeString, "list") == 0 ) - { - return EPLYPT_LIST; - } - else - { - // unsupported type. - // cannot be loaded in binary mode - return EPLYPT_UNKNOWN; - } -} - - -// Split the string data into a line in place by terminating it instead of copying. -c8* CPLYMeshFileLoader::getNextLine() -{ - // move the start pointer along - StartPointer = LineEndPointer + 1; - - // crlf split across buffer move - if (*StartPointer == '\n') - { - *StartPointer = '\0'; - ++StartPointer; - } - - // begin at the start of the next line - c8* pos = StartPointer; - while (pos < EndPointer && *pos && *pos != '\r' && *pos != '\n') - ++pos; - - if ( pos < EndPointer && ( *(pos+1) == '\r' || *(pos+1) == '\n') ) - { - *pos = '\0'; - ++pos; - } - - // we have reached the end of the buffer - if (pos >= EndPointer) - { - // get data from the file - if (!EndOfFile) - { - fillBuffer(); - // reset line end pointer - LineEndPointer = StartPointer - 1; - - if (StartPointer != EndPointer) - return getNextLine(); - else - return Buffer; - } - else - { - // EOF - StartPointer = EndPointer-1; - *StartPointer = '\0'; - return StartPointer; - } - } - else - { - // null terminate the string in place - *pos = '\0'; - LineEndPointer = pos; - WordLength = -1; - // return pointer to the start of the line - return StartPointer; - } -} - - -// null terminate the next word on the previous line and move the next word pointer along -// since we already have a full line in the buffer, we never need to retrieve more data -c8* CPLYMeshFileLoader::getNextWord() -{ - // move the start pointer along - StartPointer += WordLength + 1; - - if (StartPointer == LineEndPointer) - { - WordLength = -1; // - return LineEndPointer; - } - // begin at the start of the next word - c8* pos = StartPointer; - while (*pos && pos < LineEndPointer && pos < EndPointer && *pos != ' ' && *pos != '\t') - ++pos; - - while(*pos && pos < LineEndPointer && pos < EndPointer && (*pos == ' ' || *pos == '\t') ) - { - // null terminate the string in place - *pos = '\0'; - ++pos; - } - --pos; - WordLength = (s32)(pos-StartPointer); - // return pointer to the start of the word - return StartPointer; -} - - -// read the next float from the file and move the start pointer along -f32 CPLYMeshFileLoader::getFloat(E_PLY_PROPERTY_TYPE t) -{ - f32 retVal = 0.0f; - - if (IsBinaryFile) - { - if (EndPointer - StartPointer < 8) - fillBuffer(); - - if (EndPointer - StartPointer > 0) - { - switch (t) - { - case EPLYPT_INT8: - retVal = *StartPointer; - StartPointer++; - break; - case EPLYPT_INT16: - if (IsWrongEndian) - retVal = os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); - else - retVal = *(reinterpret_cast(StartPointer)); - StartPointer += 2; - break; - case EPLYPT_INT32: - if (IsWrongEndian) - retVal = f32(os::Byteswap::byteswap(*(reinterpret_cast(StartPointer)))); - else - retVal = f32(*(reinterpret_cast(StartPointer))); - StartPointer += 4; - break; - case EPLYPT_FLOAT32: - if (IsWrongEndian) - retVal = os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); - else - retVal = *(reinterpret_cast(StartPointer)); - StartPointer += 4; - break; - case EPLYPT_FLOAT64: - // todo: byteswap 64-bit - retVal = f32(*(reinterpret_cast(StartPointer))); - StartPointer += 8; - break; - case EPLYPT_LIST: - case EPLYPT_UNKNOWN: - default: - retVal = 0.0f; - StartPointer++; // ouch! - } - } - else - retVal = 0.0f; - } - else - { - c8* word = getNextWord(); - switch (t) - { - case EPLYPT_INT8: - case EPLYPT_INT16: - case EPLYPT_INT32: - retVal = f32(atoi(word)); - break; - case EPLYPT_FLOAT32: - case EPLYPT_FLOAT64: - retVal = f32(atof(word)); - break; - case EPLYPT_LIST: - case EPLYPT_UNKNOWN: - default: - retVal = 0.0f; - } - } - return retVal; -} - - -// read the next int from the file and move the start pointer along -u32 CPLYMeshFileLoader::getInt(E_PLY_PROPERTY_TYPE t) -{ - u32 retVal = 0; - - if (IsBinaryFile) - { - if (!EndOfFile && EndPointer - StartPointer < 8) - fillBuffer(); - - if (EndPointer - StartPointer) - { - switch (t) - { - case EPLYPT_INT8: - retVal = *StartPointer; - StartPointer++; - break; - case EPLYPT_INT16: - if (IsWrongEndian) - retVal = os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); - else - retVal = *(reinterpret_cast(StartPointer)); - StartPointer += 2; - break; - case EPLYPT_INT32: - if (IsWrongEndian) - retVal = os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); - else - retVal = *(reinterpret_cast(StartPointer)); - StartPointer += 4; - break; - case EPLYPT_FLOAT32: - if (IsWrongEndian) - retVal = (u32)os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); - else - retVal = (u32)(*(reinterpret_cast(StartPointer))); - StartPointer += 4; - break; - case EPLYPT_FLOAT64: - // todo: byteswap 64-bit - retVal = (u32)(*(reinterpret_cast(StartPointer))); - StartPointer += 8; - break; - case EPLYPT_LIST: - case EPLYPT_UNKNOWN: - default: - retVal = 0; - StartPointer++; // ouch! - } - } - else - retVal = 0; - } - else - { - c8* word = getNextWord(); - switch (t) - { - case EPLYPT_INT8: - case EPLYPT_INT16: - case EPLYPT_INT32: - retVal = atoi(word); - break; - case EPLYPT_FLOAT32: - case EPLYPT_FLOAT64: - retVal = u32(atof(word)); - break; - case EPLYPT_LIST: - case EPLYPT_UNKNOWN: - default: - retVal = 0; - } - } - return retVal; -} - - - -} // end namespace scene -} // end namespace irr - -#endif // _IRR_COMPILE_WITH_PLY_LOADER_ - +// Copyright (C) 2009-2012 Gaz Davidson +// 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_PLY_LOADER_ + +#include "CPLYMeshFileLoader.h" +#include "IMeshManipulator.h" +#include "SMesh.h" +#include "CDynamicMeshBuffer.h" +#include "SAnimatedMesh.h" +#include "IReadFile.h" +#include "fast_atof.h" +#include "os.h" + +namespace irr +{ +namespace scene +{ + +// input buffer must be at least twice as long as the longest line in the file +#define PLY_INPUT_BUFFER_SIZE 51200 // file is loaded in 50k chunks + +// constructor +CPLYMeshFileLoader::CPLYMeshFileLoader(scene::ISceneManager* smgr) +: SceneManager(smgr), File(0), Buffer(0) +{ +} + + +CPLYMeshFileLoader::~CPLYMeshFileLoader() +{ + // delete the buffer in case we didn't earlier + // (we do, but this could be disabled to increase the speed of loading hundreds of meshes) + if (Buffer) + { + delete [] Buffer; + Buffer = 0; + } + + // Destroy the element list if it exists + for (u32 i=0; igrab(); + + // attempt to allocate the buffer and fill with data + if (!allocateBuffer()) + { + File->drop(); + File = 0; + return 0; + } + + // start with empty mesh + SAnimatedMesh* animMesh = 0; + u32 vertCount=0; + + // Currently only supports ASCII meshes + if (strcmp(getNextLine(), "ply")) + { + os::Printer::log("Not a valid PLY file", file->getFileName().c_str(), ELL_ERROR); + } + else + { + // cut the next line out + getNextLine(); + // grab the word from this line + c8 *word = getNextWord(); + + // ignore comments + while (strcmp(word, "comment") == 0) + { + getNextLine(); + word = getNextWord(); + } + + bool readingHeader = true; + bool continueReading = true; + IsBinaryFile = false; + IsWrongEndian= false; + + do + { + if (strcmp(word, "format") == 0) + { + word = getNextWord(); + + if (strcmp(word, "binary_little_endian") == 0) + { + IsBinaryFile = true; +#ifdef __BIG_ENDIAN__ + IsWrongEndian = true; +#endif + + } + else if (strcmp(word, "binary_big_endian") == 0) + { + IsBinaryFile = true; +#ifndef __BIG_ENDIAN__ + IsWrongEndian = true; +#endif + } + else if (strcmp(word, "ascii")) + { + // abort if this isn't an ascii or a binary mesh + os::Printer::log("Unsupported PLY mesh format", word, ELL_ERROR); + continueReading = false; + } + + if (continueReading) + { + word = getNextWord(); + if (strcmp(word, "1.0")) + { + os::Printer::log("Unsupported PLY mesh version", word, ELL_WARNING); + } + } + } + else if (strcmp(word, "property") == 0) + { + word = getNextWord(); + + if (!ElementList.size()) + { + os::Printer::log("PLY property found before element", word, ELL_WARNING); + } + else + { + // get element + SPLYElement* el = ElementList[ElementList.size()-1]; + + // fill property struct + SPLYProperty prop; + prop.Type = getPropertyType(word); + el->KnownSize += prop.size(); + + if (prop.Type == EPLYPT_LIST) + { + el->IsFixedWidth = false; + + word = getNextWord(); + + prop.Data.List.CountType = getPropertyType(word); + if (IsBinaryFile && prop.Data.List.CountType == EPLYPT_UNKNOWN) + { + os::Printer::log("Cannot read binary PLY file containing data types of unknown length", word, ELL_ERROR); + continueReading = false; + } + else + { + word = getNextWord(); + prop.Data.List.ItemType = getPropertyType(word); + if (IsBinaryFile && prop.Data.List.ItemType == EPLYPT_UNKNOWN) + { + os::Printer::log("Cannot read binary PLY file containing data types of unknown length", word, ELL_ERROR); + continueReading = false; + } + } + } + else if (IsBinaryFile && prop.Type == EPLYPT_UNKNOWN) + { + os::Printer::log("Cannot read binary PLY file containing data types of unknown length", word, ELL_ERROR); + continueReading = false; + } + + prop.Name = getNextWord(); + + // add property to element + el->Properties.push_back(prop); + } + } + else if (strcmp(word, "element") == 0) + { + SPLYElement* el = new SPLYElement; + el->Name = getNextWord(); + el->Count = atoi(getNextWord()); + el->IsFixedWidth = true; + el->KnownSize = 0; + ElementList.push_back(el); + + if (el->Name == "vertex") + vertCount = el->Count; + + } + else if (strcmp(word, "end_header") == 0) + { + readingHeader = false; + if (IsBinaryFile) + { + StartPointer = LineEndPointer + 1; + } + } + else if (strcmp(word, "comment") == 0) + { + // ignore line + } + else + { + os::Printer::log("Unknown item in PLY file", word, ELL_WARNING); + } + + if (readingHeader && continueReading) + { + getNextLine(); + word = getNextWord(); + } + } + while (readingHeader && continueReading); + + // now to read the actual data from the file + if (continueReading) + { + // create a mesh buffer + CDynamicMeshBuffer *mb = new CDynamicMeshBuffer(video::EVT_STANDARD, vertCount > 65565 ? video::EIT_32BIT : video::EIT_16BIT); + mb->getVertexBuffer().reallocate(vertCount); + mb->getIndexBuffer().reallocate(vertCount); + mb->setHardwareMappingHint(EHM_STATIC); + + bool hasNormals=true; + // loop through each of the elements + for (u32 i=0; iName == "vertex") + { + // loop through vertex properties + for (u32 j=0; j < ElementList[i]->Count; ++j) + hasNormals &= readVertex(*ElementList[i], mb); + } + else if (ElementList[i]->Name == "face") + { + // read faces + for (u32 j=0; j < ElementList[i]->Count; ++j) + readFace(*ElementList[i], mb); + } + else + { + // skip these elements + for (u32 j=0; j < ElementList[i]->Count; ++j) + skipElement(*ElementList[i]); + } + } + mb->recalculateBoundingBox(); + if (!hasNormals) + SceneManager->getMeshManipulator()->recalculateNormals(mb); + SMesh* m = new SMesh(); + m->addMeshBuffer(mb); + m->recalculateBoundingBox(); + mb->drop(); + animMesh = new SAnimatedMesh(); + animMesh->addMesh(m); + animMesh->recalculateBoundingBox(); + m->drop(); + } + } + + + // free the buffer + delete [] Buffer; + Buffer = 0; + File->drop(); + File = 0; + + // if we managed to create a mesh, return it + return animMesh; +} + + +bool CPLYMeshFileLoader::readVertex(const SPLYElement &Element, scene::CDynamicMeshBuffer* mb) +{ + if (!IsBinaryFile) + getNextLine(); + + video::S3DVertex vert; + vert.Color.set(255,255,255,255); + vert.TCoords.X = 0.0f; + vert.TCoords.Y = 0.0f; + vert.Normal.X = 0.0f; + vert.Normal.Y = 1.0f; + vert.Normal.Z = 0.0f; + + bool result=false; + for (u32 i=0; i < Element.Properties.size(); ++i) + { + E_PLY_PROPERTY_TYPE t = Element.Properties[i].Type; + + if (Element.Properties[i].Name == "x") + vert.Pos.X = getFloat(t); + else if (Element.Properties[i].Name == "y") + vert.Pos.Z = getFloat(t); + else if (Element.Properties[i].Name == "z") + vert.Pos.Y = getFloat(t); + else if (Element.Properties[i].Name == "nx") + { + vert.Normal.X = getFloat(t); + result=true; + } + else if (Element.Properties[i].Name == "ny") + { + vert.Normal.Z = getFloat(t); + result=true; + } + else if (Element.Properties[i].Name == "nz") + { + vert.Normal.Y = getFloat(t); + result=true; + } + else if (Element.Properties[i].Name == "u") + vert.TCoords.X = getFloat(t); + else if (Element.Properties[i].Name == "v") + vert.TCoords.Y = getFloat(t); + else if (Element.Properties[i].Name == "red") + { + u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t); + vert.Color.setRed(value); + } + else if (Element.Properties[i].Name == "green") + { + u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t); + vert.Color.setGreen(value); + } + else if (Element.Properties[i].Name == "blue") + { + u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t); + vert.Color.setBlue(value); + } + else if (Element.Properties[i].Name == "alpha") + { + u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t); + vert.Color.setAlpha(value); + } + else + skipProperty(Element.Properties[i]); + } + + mb->getVertexBuffer().push_back(vert); + + return result; +} + + +bool CPLYMeshFileLoader::readFace(const SPLYElement &Element, scene::CDynamicMeshBuffer* mb) +{ + if (!IsBinaryFile) + getNextLine(); + + for (u32 i=0; i < Element.Properties.size(); ++i) + { + if ( (Element.Properties[i].Name == "vertex_indices" || + Element.Properties[i].Name == "vertex_index") && Element.Properties[i].Type == EPLYPT_LIST) + { + // get count + s32 count = getInt(Element.Properties[i].Data.List.CountType); + u32 a = getInt(Element.Properties[i].Data.List.ItemType), + b = getInt(Element.Properties[i].Data.List.ItemType), + c = getInt(Element.Properties[i].Data.List.ItemType); + s32 j = 3; + + mb->getIndexBuffer().push_back(a); + mb->getIndexBuffer().push_back(c); + mb->getIndexBuffer().push_back(b); + + for (; j < count; ++j) + { + b = c; + c = getInt(Element.Properties[i].Data.List.ItemType); + mb->getIndexBuffer().push_back(a); + mb->getIndexBuffer().push_back(c); + mb->getIndexBuffer().push_back(b); + } + } + else if (Element.Properties[i].Name == "intensity") + { + // todo: face intensity + skipProperty(Element.Properties[i]); + } + else + skipProperty(Element.Properties[i]); + } + return true; +} + + +// skips an element and all properties. return false on EOF +void CPLYMeshFileLoader::skipElement(const SPLYElement &Element) +{ + if (IsBinaryFile) + if (Element.IsFixedWidth) + moveForward(Element.KnownSize); + else + for (u32 i=0; i < Element.Properties.size(); ++i) + skipProperty(Element.Properties[i]); + else + getNextLine(); +} + + +void CPLYMeshFileLoader::skipProperty(const SPLYProperty &Property) +{ + if (Property.Type == EPLYPT_LIST) + { + s32 count = getInt(Property.Data.List.CountType); + + for (s32 i=0; i < count; ++i) + getInt(Property.Data.List.CountType); + } + else + { + if (IsBinaryFile) + moveForward(Property.size()); + else + getNextWord(); + } +} + + +bool CPLYMeshFileLoader::allocateBuffer() +{ + // Destroy the element list if it exists + for (u32 i=0; igetPos() == File->getSize()) + { + EndOfFile = true; + } + else + { + // read data from the file + u32 count = File->read(EndPointer, PLY_INPUT_BUFFER_SIZE - length); + + // increment the end pointer by the number of bytes read + EndPointer = EndPointer + count; + + // if we didn't completely fill the buffer + if (count != PLY_INPUT_BUFFER_SIZE - length) + { + // blank the rest of the memory + memset(EndPointer, 0, Buffer + PLY_INPUT_BUFFER_SIZE - EndPointer); + + // end of file + EndOfFile = true; + } + } +} + + +// skips x bytes in the file, getting more data if required +void CPLYMeshFileLoader::moveForward(u32 bytes) +{ + if (StartPointer + bytes >= EndPointer) + fillBuffer(); + if (StartPointer + bytes < EndPointer) + StartPointer += bytes; + else + StartPointer = EndPointer; +} + + +E_PLY_PROPERTY_TYPE CPLYMeshFileLoader::getPropertyType(const c8* typeString) const +{ + if (strcmp(typeString, "char") == 0 || + strcmp(typeString, "uchar") == 0 || + strcmp(typeString, "int8") == 0 || + strcmp(typeString, "uint8") == 0) + { + return EPLYPT_INT8; + } + else if (strcmp(typeString, "uint") == 0 || + strcmp(typeString, "int16") == 0 || + strcmp(typeString, "uint16") == 0 || + strcmp(typeString, "short") == 0 || + strcmp(typeString, "ushort") == 0) + { + return EPLYPT_INT16; + } + else if (strcmp(typeString, "int") == 0 || + strcmp(typeString, "long") == 0 || + strcmp(typeString, "ulong") == 0 || + strcmp(typeString, "int32") == 0 || + strcmp(typeString, "uint32") == 0) + { + return EPLYPT_INT32; + } + else if (strcmp(typeString, "float") == 0 || + strcmp(typeString, "float32") == 0) + { + return EPLYPT_FLOAT32; + } + else if (strcmp(typeString, "float64") == 0 || + strcmp(typeString, "double") == 0) + { + return EPLYPT_FLOAT64; + } + else if ( strcmp(typeString, "list") == 0 ) + { + return EPLYPT_LIST; + } + else + { + // unsupported type. + // cannot be loaded in binary mode + return EPLYPT_UNKNOWN; + } +} + + +// Split the string data into a line in place by terminating it instead of copying. +c8* CPLYMeshFileLoader::getNextLine() +{ + // move the start pointer along + StartPointer = LineEndPointer + 1; + + // crlf split across buffer move + if (*StartPointer == '\n') + { + *StartPointer = '\0'; + ++StartPointer; + } + + // begin at the start of the next line + c8* pos = StartPointer; + while (pos < EndPointer && *pos && *pos != '\r' && *pos != '\n') + ++pos; + + if ( pos < EndPointer && ( *(pos+1) == '\r' || *(pos+1) == '\n') ) + { + *pos = '\0'; + ++pos; + } + + // we have reached the end of the buffer + if (pos >= EndPointer) + { + // get data from the file + if (!EndOfFile) + { + fillBuffer(); + // reset line end pointer + LineEndPointer = StartPointer - 1; + + if (StartPointer != EndPointer) + return getNextLine(); + else + return Buffer; + } + else + { + // EOF + StartPointer = EndPointer-1; + *StartPointer = '\0'; + return StartPointer; + } + } + else + { + // null terminate the string in place + *pos = '\0'; + LineEndPointer = pos; + WordLength = -1; + // return pointer to the start of the line + return StartPointer; + } +} + + +// null terminate the next word on the previous line and move the next word pointer along +// since we already have a full line in the buffer, we never need to retrieve more data +c8* CPLYMeshFileLoader::getNextWord() +{ + // move the start pointer along + StartPointer += WordLength + 1; + + if (StartPointer == LineEndPointer) + { + WordLength = -1; // + return LineEndPointer; + } + // begin at the start of the next word + c8* pos = StartPointer; + while (*pos && pos < LineEndPointer && pos < EndPointer && *pos != ' ' && *pos != '\t') + ++pos; + + while(*pos && pos < LineEndPointer && pos < EndPointer && (*pos == ' ' || *pos == '\t') ) + { + // null terminate the string in place + *pos = '\0'; + ++pos; + } + --pos; + WordLength = (s32)(pos-StartPointer); + // return pointer to the start of the word + return StartPointer; +} + + +// read the next float from the file and move the start pointer along +f32 CPLYMeshFileLoader::getFloat(E_PLY_PROPERTY_TYPE t) +{ + f32 retVal = 0.0f; + + if (IsBinaryFile) + { + if (EndPointer - StartPointer < 8) + fillBuffer(); + + if (EndPointer - StartPointer > 0) + { + switch (t) + { + case EPLYPT_INT8: + retVal = *StartPointer; + StartPointer++; + break; + case EPLYPT_INT16: + if (IsWrongEndian) + retVal = os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); + else + retVal = *(reinterpret_cast(StartPointer)); + StartPointer += 2; + break; + case EPLYPT_INT32: + if (IsWrongEndian) + retVal = f32(os::Byteswap::byteswap(*(reinterpret_cast(StartPointer)))); + else + retVal = f32(*(reinterpret_cast(StartPointer))); + StartPointer += 4; + break; + case EPLYPT_FLOAT32: + if (IsWrongEndian) + retVal = os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); + else + retVal = *(reinterpret_cast(StartPointer)); + StartPointer += 4; + break; + case EPLYPT_FLOAT64: + // todo: byteswap 64-bit + retVal = f32(*(reinterpret_cast(StartPointer))); + StartPointer += 8; + break; + case EPLYPT_LIST: + case EPLYPT_UNKNOWN: + default: + retVal = 0.0f; + StartPointer++; // ouch! + } + } + else + retVal = 0.0f; + } + else + { + c8* word = getNextWord(); + switch (t) + { + case EPLYPT_INT8: + case EPLYPT_INT16: + case EPLYPT_INT32: + retVal = f32(atoi(word)); + break; + case EPLYPT_FLOAT32: + case EPLYPT_FLOAT64: + retVal = f32(atof(word)); + break; + case EPLYPT_LIST: + case EPLYPT_UNKNOWN: + default: + retVal = 0.0f; + } + } + return retVal; +} + + +// read the next int from the file and move the start pointer along +u32 CPLYMeshFileLoader::getInt(E_PLY_PROPERTY_TYPE t) +{ + u32 retVal = 0; + + if (IsBinaryFile) + { + if (!EndOfFile && EndPointer - StartPointer < 8) + fillBuffer(); + + if (EndPointer - StartPointer) + { + switch (t) + { + case EPLYPT_INT8: + retVal = *StartPointer; + StartPointer++; + break; + case EPLYPT_INT16: + if (IsWrongEndian) + retVal = os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); + else + retVal = *(reinterpret_cast(StartPointer)); + StartPointer += 2; + break; + case EPLYPT_INT32: + if (IsWrongEndian) + retVal = os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); + else + retVal = *(reinterpret_cast(StartPointer)); + StartPointer += 4; + break; + case EPLYPT_FLOAT32: + if (IsWrongEndian) + retVal = (u32)os::Byteswap::byteswap(*(reinterpret_cast(StartPointer))); + else + retVal = (u32)(*(reinterpret_cast(StartPointer))); + StartPointer += 4; + break; + case EPLYPT_FLOAT64: + // todo: byteswap 64-bit + retVal = (u32)(*(reinterpret_cast(StartPointer))); + StartPointer += 8; + break; + case EPLYPT_LIST: + case EPLYPT_UNKNOWN: + default: + retVal = 0; + StartPointer++; // ouch! + } + } + else + retVal = 0; + } + else + { + c8* word = getNextWord(); + switch (t) + { + case EPLYPT_INT8: + case EPLYPT_INT16: + case EPLYPT_INT32: + retVal = atoi(word); + break; + case EPLYPT_FLOAT32: + case EPLYPT_FLOAT64: + retVal = u32(atof(word)); + break; + case EPLYPT_LIST: + case EPLYPT_UNKNOWN: + default: + retVal = 0; + } + } + return retVal; +} + + + +} // end namespace scene +} // end namespace irr + +#endif // _IRR_COMPILE_WITH_PLY_LOADER_ + -- cgit v1.1