X3D: Don't convert IndexedLineSet polylines with > 2 indices to triangles/polygons
Currently, when the coordIndex attribute of an IndexedLineSet contains a polyline with > 2 indices, X3DGeoHelper::coordIdx_str2faces_arr() will incorrectly determine the primitive type to be aiPrimitiveType_TRIANGLE or aiPrimitiveType_POLYGON instead of aiPrimitiveType_LINE. To fix this, this commit adds functions to explicitly handle an IndexedLineSet. Fixes #3101pull/5360/head^2
parent
c8ca1a48ec
commit
9d71a275c3
|
@ -188,6 +188,51 @@ mg_m_err:
|
|||
pFaces.clear();
|
||||
}
|
||||
|
||||
void X3DGeoHelper::coordIdx_str2lines_arr(const std::vector<int32_t> &pCoordIdx, std::vector<aiFace> &pFaces) {
|
||||
std::vector<int32_t> f_data(pCoordIdx);
|
||||
|
||||
if (f_data.back() != (-1)) {
|
||||
f_data.push_back(-1);
|
||||
}
|
||||
|
||||
// reserve average size.
|
||||
pFaces.reserve(f_data.size() / 2);
|
||||
for (std::vector<int32_t>::const_iterator startIt = f_data.cbegin(), endIt = f_data.cbegin(); endIt != f_data.cend(); ++endIt) {
|
||||
// check for end of current polyline
|
||||
if (*endIt != -1)
|
||||
continue;
|
||||
|
||||
// found end of polyline, check if this is a valid polyline
|
||||
std::size_t numIndices = std::distance(startIt, endIt);
|
||||
if (numIndices <= 1)
|
||||
goto mg_m_err;
|
||||
|
||||
// create line faces out of polyline indices
|
||||
for (int32_t idx0 = *startIt++; startIt != endIt; ++startIt) {
|
||||
int32_t idx1 = *startIt;
|
||||
|
||||
aiFace tface;
|
||||
tface.mNumIndices = 2;
|
||||
tface.mIndices = new unsigned int[2];
|
||||
tface.mIndices[0] = idx0;
|
||||
tface.mIndices[1] = idx1;
|
||||
pFaces.push_back(tface);
|
||||
|
||||
idx0 = idx1;
|
||||
}
|
||||
|
||||
++startIt;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
mg_m_err:
|
||||
for (size_t i = 0, i_e = pFaces.size(); i < i_e; i++)
|
||||
delete[] pFaces[i].mIndices;
|
||||
|
||||
pFaces.clear();
|
||||
}
|
||||
|
||||
void X3DGeoHelper::add_color(aiMesh &pMesh, const std::list<aiColor3D> &pColors, const bool pColorPerVertex) {
|
||||
std::list<aiColor4D> tcol;
|
||||
|
||||
|
@ -528,4 +573,40 @@ aiMesh *X3DGeoHelper::make_mesh(const std::vector<int32_t> &pCoordIdx, const std
|
|||
return tmesh;
|
||||
}
|
||||
|
||||
aiMesh *X3DGeoHelper::make_line_mesh(const std::vector<int32_t> &pCoordIdx, const std::list<aiVector3D> &pVertices) {
|
||||
std::vector<aiFace> faces;
|
||||
|
||||
// create faces array from input string with vertices indices.
|
||||
X3DGeoHelper::coordIdx_str2lines_arr(pCoordIdx, faces);
|
||||
if (!faces.size()) {
|
||||
throw DeadlyImportError("Failed to create mesh, faces list is empty.");
|
||||
}
|
||||
|
||||
//
|
||||
// Create new mesh and copy geometry data.
|
||||
//
|
||||
aiMesh *tmesh = new aiMesh;
|
||||
size_t ts = faces.size();
|
||||
// faces
|
||||
tmesh->mFaces = new aiFace[ts];
|
||||
tmesh->mNumFaces = static_cast<unsigned int>(ts);
|
||||
for (size_t i = 0; i < ts; i++)
|
||||
tmesh->mFaces[i] = faces[i];
|
||||
|
||||
// vertices
|
||||
std::list<aiVector3D>::const_iterator vit = pVertices.begin();
|
||||
|
||||
ts = pVertices.size();
|
||||
tmesh->mVertices = new aiVector3D[ts];
|
||||
tmesh->mNumVertices = static_cast<unsigned int>(ts);
|
||||
for (size_t i = 0; i < ts; i++) {
|
||||
tmesh->mVertices[i] = *vit++;
|
||||
}
|
||||
|
||||
// set primitive type and return result.
|
||||
tmesh->mPrimitiveTypes = aiPrimitiveType_LINE;
|
||||
|
||||
return tmesh;
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
|
|
@ -21,6 +21,7 @@ public:
|
|||
static void polylineIdx_to_lineIdx(const std::list<int32_t> &pPolylineCoordIdx, std::list<int32_t> &pLineCoordIdx);
|
||||
static void rect_parallel_epiped(const aiVector3D &pSize, std::list<aiVector3D> &pVertices);
|
||||
static void coordIdx_str2faces_arr(const std::vector<int32_t> &pCoordIdx, std::vector<aiFace> &pFaces, unsigned int &pPrimitiveTypes);
|
||||
static void coordIdx_str2lines_arr(const std::vector<int32_t> &pCoordIdx, std::vector<aiFace> &pFaces);
|
||||
static void add_color(aiMesh &pMesh, const std::list<aiColor3D> &pColors, const bool pColorPerVertex);
|
||||
static void add_color(aiMesh &pMesh, const std::list<aiColor4D> &pColors, const bool pColorPerVertex);
|
||||
static void add_color(aiMesh &pMesh, const std::vector<int32_t> &pCoordIdx, const std::vector<int32_t> &pColorIdx,
|
||||
|
@ -34,6 +35,7 @@ public:
|
|||
const std::list<aiVector2D> &pTexCoords);
|
||||
static void add_tex_coord(aiMesh &pMesh, const std::list<aiVector2D> &pTexCoords);
|
||||
static aiMesh *make_mesh(const std::vector<int32_t> &pCoordIdx, const std::list<aiVector3D> &pVertices);
|
||||
static aiMesh *make_line_mesh(const std::vector<int32_t> &pCoordIdx, const std::list<aiVector3D> &pVertices);
|
||||
};
|
||||
|
||||
} // namespace Assimp
|
||||
|
|
|
@ -320,7 +320,7 @@ void X3DImporter::Postprocess_BuildMesh(const X3DNodeElementBase &pNodeElement,
|
|||
// at first search for <Coordinate> node and create mesh.
|
||||
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||
if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||
*pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
|
||||
*pMesh = X3DGeoHelper::make_line_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue