pull/2028/head
Kim Kulling 2018-06-18 21:19:54 +02:00
parent 31adc4385c
commit cc08c19248
1 changed files with 201 additions and 223 deletions

View File

@ -55,7 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
using namespace Assimp; using namespace ::Assimp;
static const aiImporterDesc desc = { static const aiImporterDesc desc = {
"Stanford Polygon Library (PLY) Importer", "Stanford Polygon Library (PLY) Importer",
@ -73,13 +73,12 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Internal stuff // Internal stuff
namespace namespace {
{
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Checks that property index is within range // Checks that property index is within range
template <class T> template <class T>
const T &GetProperty(const std::vector<T> &props, int idx) inline
{ const T &GetProperty(const std::vector<T> &props, int idx) {
if (static_cast<size_t>(idx) >= props.size()) { if (static_cast<size_t>(idx) >= props.size()) {
throw DeadlyImportError("Invalid .ply file: Property index is out of range."); throw DeadlyImportError("Invalid .ply file: Property index is out of range.");
} }
@ -88,7 +87,6 @@ namespace
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
PLYImporter::PLYImporter() PLYImporter::PLYImporter()
@ -129,7 +127,7 @@ const aiImporterDesc* PLYImporter::GetInfo() const {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static bool isBigEndian(const char* szMe) { static bool isBigEndian(const char* szMe) {
ai_assert(NULL != szMe); ai_assert(nullptr != szMe);
// binary_little_endian // binary_little_endian
// binary_big_endian // binary_big_endian
@ -150,7 +148,7 @@ static bool isBigEndian(const char* szMe) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) {
static const std::string mode = "rb"; const std::string mode = "rb";
std::unique_ptr<IOStream> fileStream(pIOHandler->Open(pFile, mode)); std::unique_ptr<IOStream> fileStream(pIOHandler->Open(pFile, mode));
if (!fileStream.get()) { if (!fileStream.get()) {
throw DeadlyImportError("Failed to open file " + pFile + "."); throw DeadlyImportError("Failed to open file " + pFile + ".");
@ -184,7 +182,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
char* szMe = (char*)&this->mBuffer[0]; char* szMe = (char*)&this->mBuffer[0];
SkipSpacesAndLineEnd(szMe, (const char**)&szMe); SkipSpacesAndLineEnd(szMe, (const char**)&szMe);
// determine the format of the file data and construct the aimesh // determine the format of the file data and construct the aiMesh
PLY::DOM sPlyDom; PLY::DOM sPlyDom;
this->pcDOM = &sPlyDom; this->pcDOM = &sPlyDom;
@ -192,7 +190,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
if (TokenMatch(szMe, "ascii", 5)) { if (TokenMatch(szMe, "ascii", 5)) {
SkipLine(szMe, (const char**)&szMe); SkipLine(szMe, (const char**)&szMe);
if (!PLY::DOM::ParseInstance(streamedBuffer, &sPlyDom, this)) { if (!PLY::DOM::ParseInstance(streamedBuffer, &sPlyDom, this)) {
if (mGeneratedMesh != NULL) { if (mGeneratedMesh != nullptr) {
delete(mGeneratedMesh); delete(mGeneratedMesh);
mGeneratedMesh = nullptr; mGeneratedMesh = nullptr;
} }
@ -206,7 +204,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
// skip the line, parse the rest of the header and build the DOM // skip the line, parse the rest of the header and build the DOM
if (!PLY::DOM::ParseInstanceBinary(streamedBuffer, &sPlyDom, this, bIsBE)) { if (!PLY::DOM::ParseInstanceBinary(streamedBuffer, &sPlyDom, this, bIsBE)) {
if (mGeneratedMesh != NULL) { if (mGeneratedMesh != nullptr) {
delete(mGeneratedMesh); delete(mGeneratedMesh);
mGeneratedMesh = nullptr; mGeneratedMesh = nullptr;
} }
@ -215,7 +213,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
throw DeadlyImportError("Invalid .ply file: Unable to build DOM (#2)"); throw DeadlyImportError("Invalid .ply file: Unable to build DOM (#2)");
} }
} else { } else {
if (mGeneratedMesh != NULL) { if (mGeneratedMesh != nullptr) {
delete(mGeneratedMesh); delete(mGeneratedMesh);
mGeneratedMesh = nullptr; mGeneratedMesh = nullptr;
} }
@ -225,7 +223,7 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
} }
} else { } else {
AI_DEBUG_INVALIDATE_PTR(this->mBuffer); AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
if (mGeneratedMesh != NULL) { if (mGeneratedMesh != nullptr) {
delete(mGeneratedMesh); delete(mGeneratedMesh);
mGeneratedMesh = nullptr; mGeneratedMesh = nullptr;
} }
@ -237,13 +235,13 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
//free the file buffer //free the file buffer
streamedBuffer.close(); streamedBuffer.close();
if (mGeneratedMesh == NULL) { if (mGeneratedMesh == nullptr) {
throw DeadlyImportError("Invalid .ply file: Unable to extract mesh data "); throw DeadlyImportError("Invalid .ply file: Unable to extract mesh data ");
} }
// if no face list is existing we assume that the vertex // if no face list is existing we assume that the vertex
// list is containing a list of points // list is containing a list of points
bool pointsOnly = mGeneratedMesh->mFaces == NULL ? true : false; bool pointsOnly = mGeneratedMesh->mFaces == nullptr ? true : false;
if (pointsOnly) { if (pointsOnly) {
mGeneratedMesh->mPrimitiveTypes = aiPrimitiveType::aiPrimitiveType_POINT; mGeneratedMesh->mPrimitiveTypes = aiPrimitiveType::aiPrimitiveType_POINT;
} }
@ -277,8 +275,8 @@ void PLYImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
} }
void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos) { void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos) {
ai_assert(NULL != pcElement); ai_assert(nullptr != pcElement);
ai_assert(NULL != instElement); ai_assert(nullptr != instElement);
ai_uint aiPositions[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; ai_uint aiPositions[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
PLY::EDataType aiTypes[3] = { EDT_Char, EDT_Char, EDT_Char }; PLY::EDataType aiTypes[3] = { EDT_Char, EDT_Char, EDT_Char };
@ -416,7 +414,7 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn
haveColor = true; haveColor = true;
} }
// assume 1.0 for the alpha channel ifit is not set // assume 1.0 for the alpha channel if it is not set
if (0xFFFFFFFF == aiColors[3]) { if (0xFFFFFFFF == aiColors[3]) {
cOut.a = 1.0; cOut.a = 1.0;
} else { } else {
@ -481,13 +479,11 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Convert a color component to [0...1] // Convert a color component to [0...1]
ai_real PLYImporter::NormalizeColorValue(PLY::PropertyInstance::ValueUnion val, PLY::EDataType eType) { ai_real PLYImporter::NormalizeColorValue(PLY::PropertyInstance::ValueUnion val, PLY::EDataType eType) {
switch (eType) switch (eType) {
{
case EDT_Float: case EDT_Float:
return val.fFloat; return val.fFloat;
case EDT_Double: case EDT_Double:
return (ai_real)val.fDouble; return (ai_real)val.fDouble;
case EDT_UChar: case EDT_UChar:
return (ai_real)val.iUInt / (ai_real)0xFF; return (ai_real)val.iUInt / (ai_real)0xFF;
case EDT_Char: case EDT_Char:
@ -500,20 +496,23 @@ ai_real PLYImporter::NormalizeColorValue(PLY::PropertyInstance::ValueUnion val,
return (ai_real)val.iUInt / (ai_real)0xFFFF; return (ai_real)val.iUInt / (ai_real)0xFFFF;
case EDT_Int: case EDT_Int:
return ((ai_real)val.iInt / (ai_real)0xFF) + 0.5f; return ((ai_real)val.iInt / (ai_real)0xFF) + 0.5f;
default:; default:
}; break;
}
return 0.0f; return 0.0f;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Try to extract proper faces from the PLY DOM // Try to extract proper faces from the PLY DOM
void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos) void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement,
{ unsigned int pos) {
ai_assert(NULL != pcElement); ai_assert(nullptr != pcElement);
ai_assert(NULL != instElement); ai_assert(nullptr != instElement);
if (mGeneratedMesh == NULL) if (mGeneratedMesh == nullptr) {
throw DeadlyImportError("Invalid .ply file: Vertices should be declared before faces"); throw DeadlyImportError("Invalid .ply file: Vertices should be declared before faces");
}
bool bOne = false; bool bOne = false;
@ -531,35 +530,24 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
PLY::EDataType eType3 = EDT_Char; PLY::EDataType eType3 = EDT_Char;
// face = unique number of vertex indices // face = unique number of vertex indices
if (PLY::EEST_Face == pcElement->eSemantic) if (PLY::EEST_Face == pcElement->eSemantic) {
{
unsigned int _a = 0; unsigned int _a = 0;
for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin(); for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
a != pcElement->alProperties.end(); ++a, ++_a) a != pcElement->alProperties.end(); ++a, ++_a) {
{ if (PLY::EST_VertexIndex == (*a).Semantic) {
if (PLY::EST_VertexIndex == (*a).Semantic)
{
// must be a dynamic list! // must be a dynamic list!
if (!(*a).bIsList) if (!(*a).bIsList) {
continue; continue;
}
iProperty = _a; iProperty = _a;
bOne = true; bOne = true;
eType = (*a).eType; eType = (*a).eType;
} } else if (PLY::EST_TextureCoordinates == (*a).Semantic) {
/*else if (PLY::EST_MaterialIndex == (*a).Semantic)
{
if ((*a).bIsList)
continue;
iMaterialIndex = _a;
bOne = true;
eType2 = (*a).eType;
}*/
else if (PLY::EST_TextureCoordinates == (*a).Semantic)
{
// must be a dynamic list! // must be a dynamic list!
if (!(*a).bIsList) if (!(*a).bIsList) {
continue; continue;
}
iTextureCoord = _a; iTextureCoord = _a;
bOne = true; bOne = true;
eType3 = (*a).eType; eType3 = (*a).eType;
@ -568,15 +556,14 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
} }
// triangle strip // triangle strip
// TODO: triangle strip and material index support??? // TODO: triangle strip and material index support???
else if (PLY::EEST_TriStrip == pcElement->eSemantic) else if (PLY::EEST_TriStrip == pcElement->eSemantic) {
{
unsigned int _a = 0; unsigned int _a = 0;
for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin(); for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
a != pcElement->alProperties.end(); ++a, ++_a) a != pcElement->alProperties.end(); ++a, ++_a) {
{
// must be a dynamic list! // must be a dynamic list!
if (!(*a).bIsList) if (!(*a).bIsList) {
continue; continue;
}
iProperty = _a; iProperty = _a;
bOne = true; bOne = true;
bIsTriStrip = true; bIsTriStrip = true;
@ -586,19 +573,15 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
} }
// check whether we have at least one per-face information set // check whether we have at least one per-face information set
if (bOne) if (bOne) {
{ if (mGeneratedMesh->mFaces == nullptr) {
if (mGeneratedMesh->mFaces == NULL)
{
mGeneratedMesh->mNumFaces = pcElement->NumOccur; mGeneratedMesh->mNumFaces = pcElement->NumOccur;
mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces]; mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
} }
if (!bIsTriStrip) if (!bIsTriStrip) {
{
// parse the list of vertex indices // parse the list of vertex indices
if (0xFFFFFFFF != iProperty) if (0xFFFFFFFF != iProperty) {
{
const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iProperty).avList.size(); const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iProperty).avList.size();
mGeneratedMesh->mFaces[pos].mNumIndices = iNum; mGeneratedMesh->mFaces[pos].mNumIndices = iNum;
mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[iNum]; mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[iNum];
@ -606,8 +589,7 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p = std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
GetProperty(instElement->alProperties, iProperty).avList.begin(); GetProperty(instElement->alProperties, iProperty).avList.begin();
for (unsigned int a = 0; a < iNum; ++a, ++p) for (unsigned int a = 0; a < iNum; ++a, ++p) {
{
mGeneratedMesh->mFaces[pos].mIndices[a] = PLY::PropertyInstance::ConvertTo<unsigned int>(*p, eType); mGeneratedMesh->mFaces[pos].mIndices[a] = PLY::PropertyInstance::ConvertTo<unsigned int>(*p, eType);
} }
} }
@ -620,8 +602,7 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
GetProperty(instElement->alProperties, iMaterialIndex).avList.front(), eType2); GetProperty(instElement->alProperties, iMaterialIndex).avList.front(), eType2);
}*/ }*/
if (0xFFFFFFFF != iTextureCoord) if (0xFFFFFFFF != iTextureCoord) {
{
const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size(); const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size();
//should be 6 coords //should be 6 coords
@ -630,30 +611,26 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
if ((iNum / 3) == 2) // X Y coord if ((iNum / 3) == 2) // X Y coord
{ {
for (unsigned int a = 0; a < iNum; ++a, ++p) for (unsigned int a = 0; a < iNum; ++a, ++p) {
{
unsigned int vindex = mGeneratedMesh->mFaces[pos].mIndices[a / 2]; unsigned int vindex = mGeneratedMesh->mFaces[pos].mIndices[a / 2];
if (vindex < mGeneratedMesh->mNumVertices) if (vindex < mGeneratedMesh->mNumVertices) {
{ if (mGeneratedMesh->mTextureCoords[0] == nullptr ) {
if (mGeneratedMesh->mTextureCoords[0] == NULL)
{
mGeneratedMesh->mNumUVComponents[0] = 2; mGeneratedMesh->mNumUVComponents[0] = 2;
mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices]; mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices];
} }
if (a % 2 == 0) if (a % 2 == 0) {
mGeneratedMesh->mTextureCoords[0][vindex].x = PLY::PropertyInstance::ConvertTo<ai_real>(*p, eType3); mGeneratedMesh->mTextureCoords[0][vindex].x = PLY::PropertyInstance::ConvertTo<ai_real>(*p, eType3);
else } else {
mGeneratedMesh->mTextureCoords[0][vindex].y = PLY::PropertyInstance::ConvertTo<ai_real>(*p, eType3); mGeneratedMesh->mTextureCoords[0][vindex].y = PLY::PropertyInstance::ConvertTo<ai_real>(*p, eType3);
}
mGeneratedMesh->mTextureCoords[0][vindex].z = 0; mGeneratedMesh->mTextureCoords[0][vindex].z = 0;
} }
} }
} }
} }
} } else { // triangle strips
else // triangle strips
{
// normally we have only one triangle strip instance where // normally we have only one triangle strip instance where
// a value of -1 indicates a restart of the strip // a value of -1 indicates a restart of the strip
bool flip = false; bool flip = false;
@ -679,8 +656,7 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
continue; continue;
} }
if (mGeneratedMesh->mFaces == NULL) if (mGeneratedMesh->mFaces == nullptr) {
{
mGeneratedMesh->mNumFaces = pcElement->NumOccur; mGeneratedMesh->mNumFaces = pcElement->NumOccur;
mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces]; mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces];
} }
@ -691,7 +667,9 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
mGeneratedMesh->mFaces[pos].mIndices[1] = aiTable[1]; mGeneratedMesh->mFaces[pos].mIndices[1] = aiTable[1];
mGeneratedMesh->mFaces[pos].mIndices[2] = p; mGeneratedMesh->mFaces[pos].mIndices[2] = p;
if ((flip = !flip)) { // every second pass swap the indices.
flip = !flip;
if ( flip ) {
std::swap(mGeneratedMesh->mFaces[pos].mIndices[0], mGeneratedMesh->mFaces[pos].mIndices[1]); std::swap(mGeneratedMesh->mFaces[pos].mIndices[0], mGeneratedMesh->mFaces[pos].mIndices[1]);
} }