Fix X3DGeohelper.
parent
ec08092dbf
commit
52228a93f8
|
@ -0,0 +1,530 @@
|
|||
#include "X3DGeoHelper.h"
|
||||
#include "X3DImporter.hpp"
|
||||
|
||||
#include <assimp/vector3.h>
|
||||
#include <assimp/Exceptional.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
aiVector3D X3DGeoHelper::make_point2D(float angle, float radius) {
|
||||
return aiVector3D(radius * std::cos(angle), radius * std::sin(angle), 0);
|
||||
}
|
||||
|
||||
void X3DGeoHelper::make_arc2D(float pStartAngle, float pEndAngle, float pRadius, size_t numSegments, std::list<aiVector3D> &pVertices) {
|
||||
// check argument values ranges.
|
||||
if ((pStartAngle < -AI_MATH_TWO_PI_F) || (pStartAngle > AI_MATH_TWO_PI_F)) {
|
||||
throw DeadlyImportError("GeometryHelper_Make_Arc2D.pStartAngle");
|
||||
}
|
||||
if ((pEndAngle < -AI_MATH_TWO_PI_F) || (pEndAngle > AI_MATH_TWO_PI_F)) {
|
||||
throw DeadlyImportError("GeometryHelper_Make_Arc2D.pEndAngle");
|
||||
}
|
||||
if (pRadius <= 0) {
|
||||
throw DeadlyImportError("GeometryHelper_Make_Arc2D.pRadius");
|
||||
}
|
||||
|
||||
// calculate arc angle and check type of arc
|
||||
float angle_full = std::fabs(pEndAngle - pStartAngle);
|
||||
if ((angle_full > AI_MATH_TWO_PI_F) || (angle_full == 0.0f)) {
|
||||
angle_full = AI_MATH_TWO_PI_F;
|
||||
}
|
||||
|
||||
// calculate angle for one step - angle to next point of line.
|
||||
float angle_step = angle_full / (float)numSegments;
|
||||
// make points
|
||||
for (size_t pi = 0; pi <= numSegments; pi++) {
|
||||
float tangle = pStartAngle + pi * angle_step;
|
||||
pVertices.emplace_back(make_point2D(tangle, pRadius));
|
||||
} // for(size_t pi = 0; pi <= pNumSegments; pi++)
|
||||
|
||||
// if we making full circle then add last vertex equal to first vertex
|
||||
if (angle_full == AI_MATH_TWO_PI_F) pVertices.push_back(*pVertices.begin());
|
||||
}
|
||||
|
||||
void X3DGeoHelper::extend_point_to_line(const std::list<aiVector3D> &pPoint, std::list<aiVector3D> &pLine) {
|
||||
std::list<aiVector3D>::const_iterator pit = pPoint.begin();
|
||||
std::list<aiVector3D>::const_iterator pit_last = pPoint.end();
|
||||
|
||||
--pit_last;
|
||||
|
||||
if (pPoint.size() < 2) {
|
||||
throw DeadlyImportError("GeometryHelper_Extend_PointToLine.pPoint.size() can not be less than 2.");
|
||||
}
|
||||
|
||||
// add first point of first line.
|
||||
pLine.push_back(*pit++);
|
||||
// add internal points
|
||||
while (pit != pit_last) {
|
||||
pLine.push_back(*pit); // second point of previous line
|
||||
pLine.push_back(*pit); // first point of next line
|
||||
++pit;
|
||||
}
|
||||
// add last point of last line
|
||||
pLine.push_back(*pit);
|
||||
}
|
||||
|
||||
void X3DGeoHelper::polylineIdx_to_lineIdx(const std::list<int32_t> &pPolylineCoordIdx, std::list<int32_t> &pLineCoordIdx) {
|
||||
std::list<int32_t>::const_iterator plit = pPolylineCoordIdx.begin();
|
||||
|
||||
while (plit != pPolylineCoordIdx.end()) {
|
||||
// add first point of polyline
|
||||
pLineCoordIdx.push_back(*plit++);
|
||||
while ((*plit != (-1)) && (plit != pPolylineCoordIdx.end())) {
|
||||
std::list<int32_t>::const_iterator plit_next;
|
||||
|
||||
plit_next = plit, ++plit_next;
|
||||
pLineCoordIdx.push_back(*plit); // second point of previous line.
|
||||
pLineCoordIdx.push_back(-1); // delimiter
|
||||
if ((*plit_next == (-1)) || (plit_next == pPolylineCoordIdx.end())) break; // current polyline is finished
|
||||
|
||||
pLineCoordIdx.push_back(*plit); // first point of next line.
|
||||
plit = plit_next;
|
||||
} // while((*plit != (-1)) && (plit != pPolylineCoordIdx.end()))
|
||||
} // while(plit != pPolylineCoordIdx.end())
|
||||
}
|
||||
|
||||
#define MACRO_FACE_ADD_QUAD_FA(pCCW, pOut, pIn, pP1, pP2, pP3, pP4) \
|
||||
do { \
|
||||
if (pCCW) { \
|
||||
pOut.push_back(pIn[pP1]); \
|
||||
pOut.push_back(pIn[pP2]); \
|
||||
pOut.push_back(pIn[pP3]); \
|
||||
pOut.push_back(pIn[pP4]); \
|
||||
} else { \
|
||||
pOut.push_back(pIn[pP4]); \
|
||||
pOut.push_back(pIn[pP3]); \
|
||||
pOut.push_back(pIn[pP2]); \
|
||||
pOut.push_back(pIn[pP1]); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#define MESH_RectParallelepiped_CREATE_VERT \
|
||||
aiVector3D vert_set[8]; \
|
||||
float x1, x2, y1, y2, z1, z2, hs; \
|
||||
\
|
||||
hs = pSize.x / 2, x1 = -hs, x2 = hs; \
|
||||
hs = pSize.y / 2, y1 = -hs, y2 = hs; \
|
||||
hs = pSize.z / 2, z1 = -hs, z2 = hs; \
|
||||
vert_set[0].Set(x2, y1, z2); \
|
||||
vert_set[1].Set(x2, y2, z2); \
|
||||
vert_set[2].Set(x2, y2, z1); \
|
||||
vert_set[3].Set(x2, y1, z1); \
|
||||
vert_set[4].Set(x1, y1, z2); \
|
||||
vert_set[5].Set(x1, y2, z2); \
|
||||
vert_set[6].Set(x1, y2, z1); \
|
||||
vert_set[7].Set(x1, y1, z1)
|
||||
|
||||
void X3DGeoHelper::rect_parallele_piped(const aiVector3D &pSize, std::list<aiVector3D> &pVertices) {
|
||||
MESH_RectParallelepiped_CREATE_VERT;
|
||||
MACRO_FACE_ADD_QUAD_FA(true, pVertices, vert_set, 3, 2, 1, 0); // front
|
||||
MACRO_FACE_ADD_QUAD_FA(true, pVertices, vert_set, 6, 7, 4, 5); // back
|
||||
MACRO_FACE_ADD_QUAD_FA(true, pVertices, vert_set, 7, 3, 0, 4); // left
|
||||
MACRO_FACE_ADD_QUAD_FA(true, pVertices, vert_set, 2, 6, 5, 1); // right
|
||||
MACRO_FACE_ADD_QUAD_FA(true, pVertices, vert_set, 0, 1, 5, 4); // top
|
||||
MACRO_FACE_ADD_QUAD_FA(true, pVertices, vert_set, 7, 6, 2, 3); // bottom
|
||||
}
|
||||
|
||||
#undef MESH_RectParallelepiped_CREATE_VERT
|
||||
|
||||
void X3DGeoHelper::coordIdx_str2faces_arr(const std::vector<int32_t> &pCoordIdx, std::vector<aiFace> &pFaces, unsigned int &pPrimitiveTypes) {
|
||||
std::vector<int32_t> f_data(pCoordIdx);
|
||||
std::vector<unsigned int> inds;
|
||||
unsigned int prim_type = 0;
|
||||
|
||||
if (f_data.back() != (-1)) {
|
||||
f_data.push_back(-1);
|
||||
}
|
||||
|
||||
// reserve average size.
|
||||
pFaces.reserve(f_data.size() / 3);
|
||||
inds.reserve(4);
|
||||
//PrintVectorSet("build. ci", pCoordIdx);
|
||||
for (std::vector<int32_t>::iterator it = f_data.begin(); it != f_data.end(); ++it) {
|
||||
// when face is got count how many indices in it.
|
||||
if (*it == (-1)) {
|
||||
aiFace tface;
|
||||
size_t ts;
|
||||
|
||||
ts = inds.size();
|
||||
switch (ts) {
|
||||
case 0:
|
||||
goto mg_m_err;
|
||||
case 1:
|
||||
prim_type |= aiPrimitiveType_POINT;
|
||||
break;
|
||||
case 2:
|
||||
prim_type |= aiPrimitiveType_LINE;
|
||||
break;
|
||||
case 3:
|
||||
prim_type |= aiPrimitiveType_TRIANGLE;
|
||||
break;
|
||||
default:
|
||||
prim_type |= aiPrimitiveType_POLYGON;
|
||||
break;
|
||||
}
|
||||
|
||||
tface.mNumIndices = static_cast<unsigned int>(ts);
|
||||
tface.mIndices = new unsigned int[ts];
|
||||
memcpy(tface.mIndices, inds.data(), ts * sizeof(unsigned int));
|
||||
pFaces.push_back(tface);
|
||||
inds.clear();
|
||||
} // if(*it == (-1))
|
||||
else {
|
||||
inds.push_back(*it);
|
||||
} // if(*it == (-1)) else
|
||||
} // for(std::list<int32_t>::iterator it = f_data.begin(); it != f_data.end(); it++)
|
||||
//PrintVectorSet("build. faces", pCoordIdx);
|
||||
|
||||
pPrimitiveTypes = prim_type;
|
||||
|
||||
return;
|
||||
|
||||
mg_m_err:
|
||||
for (size_t i = 0, i_e = pFaces.size(); i < i_e; i++)
|
||||
delete[] pFaces.at(i).mIndices;
|
||||
|
||||
pFaces.clear();
|
||||
}
|
||||
|
||||
void X3DGeoHelper::add_color(aiMesh &pMesh, const std::list<aiColor3D> &pColors, const bool pColorPerVertex) {
|
||||
std::list<aiColor4D> tcol;
|
||||
|
||||
// create RGBA array from RGB.
|
||||
for (std::list<aiColor3D>::const_iterator it = pColors.begin(); it != pColors.end(); ++it)
|
||||
tcol.push_back(aiColor4D((*it).r, (*it).g, (*it).b, 1));
|
||||
|
||||
// call existing function for adding RGBA colors
|
||||
add_color(pMesh, tcol, pColorPerVertex);
|
||||
}
|
||||
|
||||
void X3DGeoHelper::add_color(aiMesh &pMesh, const std::list<aiColor4D> &pColors, const bool pColorPerVertex) {
|
||||
std::list<aiColor4D>::const_iterator col_it = pColors.begin();
|
||||
|
||||
if (pColorPerVertex) {
|
||||
if (pColors.size() < pMesh.mNumVertices) {
|
||||
throw DeadlyImportError("MeshGeometry_AddColor1. Colors count(" + to_string(pColors.size()) + ") can not be less than Vertices count(" +
|
||||
to_string(pMesh.mNumVertices) + ").");
|
||||
}
|
||||
|
||||
// copy colors to mesh
|
||||
pMesh.mColors[0] = new aiColor4D[pMesh.mNumVertices];
|
||||
for (size_t i = 0; i < pMesh.mNumVertices; i++)
|
||||
pMesh.mColors[0][i] = *col_it++;
|
||||
} // if(pColorPerVertex)
|
||||
else {
|
||||
if (pColors.size() < pMesh.mNumFaces) {
|
||||
throw DeadlyImportError("MeshGeometry_AddColor1. Colors count(" + to_string(pColors.size()) + ") can not be less than Faces count(" +
|
||||
to_string(pMesh.mNumFaces) + ").");
|
||||
}
|
||||
|
||||
// copy colors to mesh
|
||||
pMesh.mColors[0] = new aiColor4D[pMesh.mNumVertices];
|
||||
for (size_t fi = 0; fi < pMesh.mNumFaces; fi++) {
|
||||
// apply color to all vertices of face
|
||||
for (size_t vi = 0, vi_e = pMesh.mFaces[fi].mNumIndices; vi < vi_e; vi++) {
|
||||
pMesh.mColors[0][pMesh.mFaces[fi].mIndices[vi]] = *col_it;
|
||||
}
|
||||
|
||||
++col_it;
|
||||
}
|
||||
} // if(pColorPerVertex) else
|
||||
}
|
||||
|
||||
void X3DGeoHelper::add_color(aiMesh &pMesh, const std::vector<int32_t> &pCoordIdx, const std::vector<int32_t> &pColorIdx,
|
||||
const std::list<aiColor3D> &pColors, const bool pColorPerVertex) {
|
||||
std::list<aiColor4D> tcol;
|
||||
|
||||
// create RGBA array from RGB.
|
||||
for (std::list<aiColor3D>::const_iterator it = pColors.begin(); it != pColors.end(); ++it) {
|
||||
tcol.push_back(aiColor4D((*it).r, (*it).g, (*it).b, 1));
|
||||
}
|
||||
|
||||
// call existing function for adding RGBA colors
|
||||
add_color(pMesh, pCoordIdx, pColorIdx, tcol, pColorPerVertex);
|
||||
}
|
||||
|
||||
void X3DGeoHelper::add_color(aiMesh &pMesh, const std::vector<int32_t> &coordIdx, const std::vector<int32_t> &colorIdx,
|
||||
const std::list<aiColor4D> &colors, bool pColorPerVertex) {
|
||||
std::vector<aiColor4D> col_tgt_arr;
|
||||
std::list<aiColor4D> col_tgt_list;
|
||||
std::vector<aiColor4D> col_arr_copy;
|
||||
|
||||
if (coordIdx.size() == 0) {
|
||||
throw DeadlyImportError("MeshGeometry_AddColor2. pCoordIdx can not be empty.");
|
||||
}
|
||||
|
||||
// copy list to array because we are need indexed access to colors.
|
||||
col_arr_copy.reserve(colors.size());
|
||||
for (std::list<aiColor4D>::const_iterator it = colors.begin(); it != colors.end(); ++it) {
|
||||
col_arr_copy.push_back(*it);
|
||||
}
|
||||
|
||||
if (pColorPerVertex) {
|
||||
if (colorIdx.size() > 0) {
|
||||
// check indices array count.
|
||||
if (colorIdx.size() < coordIdx.size()) {
|
||||
throw DeadlyImportError("MeshGeometry_AddColor2. Colors indices count(" + to_string(colorIdx.size()) +
|
||||
") can not be less than Coords inidces count(" + to_string(coordIdx.size()) + ").");
|
||||
}
|
||||
// create list with colors for every vertex.
|
||||
col_tgt_arr.resize(pMesh.mNumVertices);
|
||||
for (std::vector<int32_t>::const_iterator colidx_it = colorIdx.begin(), coordidx_it = coordIdx.begin(); colidx_it != colorIdx.end(); ++colidx_it, ++coordidx_it) {
|
||||
if (*colidx_it == (-1)) {
|
||||
continue; // skip faces delimiter
|
||||
}
|
||||
if ((unsigned int)(*coordidx_it) > pMesh.mNumVertices) {
|
||||
throw DeadlyImportError("MeshGeometry_AddColor2. Coordinate idx is out of range.");
|
||||
}
|
||||
if ((unsigned int)*colidx_it > pMesh.mNumVertices) {
|
||||
throw DeadlyImportError("MeshGeometry_AddColor2. Color idx is out of range.");
|
||||
}
|
||||
|
||||
col_tgt_arr[*coordidx_it] = col_arr_copy[*colidx_it];
|
||||
}
|
||||
} // if(pColorIdx.size() > 0)
|
||||
else {
|
||||
// when color indices list is absent use CoordIdx.
|
||||
// check indices array count.
|
||||
if (colors.size() < pMesh.mNumVertices) {
|
||||
throw DeadlyImportError("MeshGeometry_AddColor2. Colors count(" + to_string(colors.size()) + ") can not be less than Vertices count(" +
|
||||
to_string(pMesh.mNumVertices) + ").");
|
||||
}
|
||||
// create list with colors for every vertex.
|
||||
col_tgt_arr.resize(pMesh.mNumVertices);
|
||||
for (size_t i = 0; i < pMesh.mNumVertices; i++) {
|
||||
col_tgt_arr[i] = col_arr_copy[i];
|
||||
}
|
||||
} // if(pColorIdx.size() > 0) else
|
||||
} // if(pColorPerVertex)
|
||||
else {
|
||||
if (colorIdx.size() > 0) {
|
||||
// check indices array count.
|
||||
if (colorIdx.size() < pMesh.mNumFaces) {
|
||||
throw DeadlyImportError("MeshGeometry_AddColor2. Colors indices count(" + to_string(colorIdx.size()) +
|
||||
") can not be less than Faces count(" + to_string(pMesh.mNumFaces) + ").");
|
||||
}
|
||||
// create list with colors for every vertex using faces indices.
|
||||
col_tgt_arr.resize(pMesh.mNumFaces);
|
||||
|
||||
std::vector<int32_t>::const_iterator colidx_it = colorIdx.begin();
|
||||
for (size_t fi = 0; fi < pMesh.mNumFaces; fi++) {
|
||||
if ((unsigned int)*colidx_it > pMesh.mNumFaces) throw DeadlyImportError("MeshGeometry_AddColor2. Face idx is out of range.");
|
||||
|
||||
col_tgt_arr[fi] = col_arr_copy[*colidx_it++];
|
||||
}
|
||||
} // if(pColorIdx.size() > 0)
|
||||
else {
|
||||
// when color indices list is absent use CoordIdx.
|
||||
// check indices array count.
|
||||
if (colors.size() < pMesh.mNumFaces) {
|
||||
throw DeadlyImportError("MeshGeometry_AddColor2. Colors count(" + to_string(colors.size()) + ") can not be less than Faces count(" +
|
||||
to_string(pMesh.mNumFaces) + ").");
|
||||
}
|
||||
// create list with colors for every vertex using faces indices.
|
||||
col_tgt_arr.resize(pMesh.mNumFaces);
|
||||
for (size_t fi = 0; fi < pMesh.mNumFaces; fi++)
|
||||
col_tgt_arr[fi] = col_arr_copy[fi];
|
||||
|
||||
} // if(pColorIdx.size() > 0) else
|
||||
} // if(pColorPerVertex) else
|
||||
|
||||
// copy array to list for calling function that add colors.
|
||||
for (std::vector<aiColor4D>::const_iterator it = col_tgt_arr.begin(); it != col_tgt_arr.end(); ++it)
|
||||
col_tgt_list.push_back(*it);
|
||||
// add prepared colors list to mesh.
|
||||
add_color(pMesh, col_tgt_list, pColorPerVertex);
|
||||
}
|
||||
|
||||
void X3DGeoHelper::add_normal(aiMesh &pMesh, const std::vector<int32_t> &pCoordIdx, const std::vector<int32_t> &pNormalIdx,
|
||||
const std::list<aiVector3D> &pNormals, const bool pNormalPerVertex) {
|
||||
std::vector<size_t> tind;
|
||||
std::vector<aiVector3D> norm_arr_copy;
|
||||
|
||||
// copy list to array because we are need indexed access to normals.
|
||||
norm_arr_copy.reserve(pNormals.size());
|
||||
for (std::list<aiVector3D>::const_iterator it = pNormals.begin(); it != pNormals.end(); ++it) {
|
||||
norm_arr_copy.push_back(*it);
|
||||
}
|
||||
|
||||
if (pNormalPerVertex) {
|
||||
if (pNormalIdx.size() > 0) {
|
||||
// check indices array count.
|
||||
if (pNormalIdx.size() != pCoordIdx.size()) throw DeadlyImportError("Normals and Coords inidces count must be equal.");
|
||||
|
||||
tind.reserve(pNormalIdx.size());
|
||||
for (std::vector<int32_t>::const_iterator it = pNormalIdx.begin(); it != pNormalIdx.end(); ++it) {
|
||||
if (*it != (-1)) tind.push_back(*it);
|
||||
}
|
||||
|
||||
// copy normals to mesh
|
||||
pMesh.mNormals = new aiVector3D[pMesh.mNumVertices];
|
||||
for (size_t i = 0; (i < pMesh.mNumVertices) && (i < tind.size()); i++) {
|
||||
if (tind[i] >= norm_arr_copy.size())
|
||||
throw DeadlyImportError("MeshGeometry_AddNormal. Normal index(" + to_string(tind[i]) +
|
||||
") is out of range. Normals count: " + to_string(norm_arr_copy.size()) + ".");
|
||||
|
||||
pMesh.mNormals[i] = norm_arr_copy[tind[i]];
|
||||
}
|
||||
} else {
|
||||
if (pNormals.size() != pMesh.mNumVertices) throw DeadlyImportError("MeshGeometry_AddNormal. Normals and vertices count must be equal.");
|
||||
|
||||
// copy normals to mesh
|
||||
pMesh.mNormals = new aiVector3D[pMesh.mNumVertices];
|
||||
std::list<aiVector3D>::const_iterator norm_it = pNormals.begin();
|
||||
for (size_t i = 0; i < pMesh.mNumVertices; i++)
|
||||
pMesh.mNormals[i] = *norm_it++;
|
||||
}
|
||||
} // if(pNormalPerVertex)
|
||||
else {
|
||||
if (pNormalIdx.size() > 0) {
|
||||
if (pMesh.mNumFaces != pNormalIdx.size()) throw DeadlyImportError("Normals faces count must be equal to mesh faces count.");
|
||||
|
||||
std::vector<int32_t>::const_iterator normidx_it = pNormalIdx.begin();
|
||||
|
||||
tind.reserve(pNormalIdx.size());
|
||||
for (size_t i = 0, i_e = pNormalIdx.size(); i < i_e; i++)
|
||||
tind.push_back(*normidx_it++);
|
||||
|
||||
} else {
|
||||
tind.reserve(pMesh.mNumFaces);
|
||||
for (size_t i = 0; i < pMesh.mNumFaces; i++)
|
||||
tind.push_back(i);
|
||||
}
|
||||
|
||||
// copy normals to mesh
|
||||
pMesh.mNormals = new aiVector3D[pMesh.mNumVertices];
|
||||
for (size_t fi = 0; fi < pMesh.mNumFaces; fi++) {
|
||||
aiVector3D tnorm;
|
||||
|
||||
tnorm = norm_arr_copy[tind[fi]];
|
||||
for (size_t vi = 0, vi_e = pMesh.mFaces[fi].mNumIndices; vi < vi_e; vi++)
|
||||
pMesh.mNormals[pMesh.mFaces[fi].mIndices[vi]] = tnorm;
|
||||
}
|
||||
} // if(pNormalPerVertex) else
|
||||
}
|
||||
|
||||
void X3DGeoHelper::add_normal(aiMesh &pMesh, const std::list<aiVector3D> &pNormals, const bool pNormalPerVertex) {
|
||||
std::list<aiVector3D>::const_iterator norm_it = pNormals.begin();
|
||||
|
||||
if (pNormalPerVertex) {
|
||||
if (pNormals.size() != pMesh.mNumVertices) throw DeadlyImportError("MeshGeometry_AddNormal. Normals and vertices count must be equal.");
|
||||
|
||||
// copy normals to mesh
|
||||
pMesh.mNormals = new aiVector3D[pMesh.mNumVertices];
|
||||
for (size_t i = 0; i < pMesh.mNumVertices; i++)
|
||||
pMesh.mNormals[i] = *norm_it++;
|
||||
} // if(pNormalPerVertex)
|
||||
else {
|
||||
if (pNormals.size() != pMesh.mNumFaces) throw DeadlyImportError("MeshGeometry_AddNormal. Normals and faces count must be equal.");
|
||||
|
||||
// copy normals to mesh
|
||||
pMesh.mNormals = new aiVector3D[pMesh.mNumVertices];
|
||||
for (size_t fi = 0; fi < pMesh.mNumFaces; fi++) {
|
||||
// apply color to all vertices of face
|
||||
for (size_t vi = 0, vi_e = pMesh.mFaces[fi].mNumIndices; vi < vi_e; vi++)
|
||||
pMesh.mNormals[pMesh.mFaces[fi].mIndices[vi]] = *norm_it;
|
||||
|
||||
++norm_it;
|
||||
}
|
||||
} // if(pNormalPerVertex) else
|
||||
}
|
||||
|
||||
void X3DGeoHelper::add_tex_coord(aiMesh &pMesh, const std::vector<int32_t> &pCoordIdx, const std::vector<int32_t> &pTexCoordIdx,
|
||||
const std::list<aiVector2D> &pTexCoords) {
|
||||
std::vector<aiVector3D> texcoord_arr_copy;
|
||||
std::vector<aiFace> faces;
|
||||
unsigned int prim_type;
|
||||
|
||||
// copy list to array because we are need indexed access to normals.
|
||||
texcoord_arr_copy.reserve(pTexCoords.size());
|
||||
for (std::list<aiVector2D>::const_iterator it = pTexCoords.begin(); it != pTexCoords.end(); ++it) {
|
||||
texcoord_arr_copy.push_back(aiVector3D((*it).x, (*it).y, 0));
|
||||
}
|
||||
|
||||
if (pTexCoordIdx.size() > 0) {
|
||||
coordIdx_str2faces_arr(pTexCoordIdx, faces, prim_type);
|
||||
if (faces.empty()) {
|
||||
throw DeadlyImportError("Failed to add texture coordinates to mesh, faces list is empty.");
|
||||
}
|
||||
if (faces.size() != pMesh.mNumFaces) {
|
||||
throw DeadlyImportError("Texture coordinates faces count must be equal to mesh faces count.");
|
||||
}
|
||||
} else {
|
||||
coordIdx_str2faces_arr(pCoordIdx, faces, prim_type);
|
||||
}
|
||||
|
||||
pMesh.mTextureCoords[0] = new aiVector3D[pMesh.mNumVertices];
|
||||
pMesh.mNumUVComponents[0] = 2;
|
||||
for (size_t fi = 0, fi_e = faces.size(); fi < fi_e; fi++) {
|
||||
if (pMesh.mFaces[fi].mNumIndices != faces.at(fi).mNumIndices)
|
||||
throw DeadlyImportError("Number of indices in texture face and mesh face must be equal. Invalid face index: " + to_string(fi) + ".");
|
||||
|
||||
for (size_t ii = 0; ii < pMesh.mFaces[fi].mNumIndices; ii++) {
|
||||
size_t vert_idx = pMesh.mFaces[fi].mIndices[ii];
|
||||
size_t tc_idx = faces.at(fi).mIndices[ii];
|
||||
|
||||
pMesh.mTextureCoords[0][vert_idx] = texcoord_arr_copy.at(tc_idx);
|
||||
}
|
||||
} // for(size_t fi = 0, fi_e = faces.size(); fi < fi_e; fi++)
|
||||
}
|
||||
|
||||
void X3DGeoHelper::add_tex_coord(aiMesh &pMesh, const std::list<aiVector2D> &pTexCoords) {
|
||||
std::vector<aiVector3D> tc_arr_copy;
|
||||
|
||||
if (pTexCoords.size() != pMesh.mNumVertices) {
|
||||
throw DeadlyImportError("MeshGeometry_AddTexCoord. Texture coordinates and vertices count must be equal.");
|
||||
}
|
||||
|
||||
// copy list to array because we are need convert aiVector2D to aiVector3D and also get indexed access as a bonus.
|
||||
tc_arr_copy.reserve(pTexCoords.size());
|
||||
for (std::list<aiVector2D>::const_iterator it = pTexCoords.begin(); it != pTexCoords.end(); ++it) {
|
||||
tc_arr_copy.push_back(aiVector3D((*it).x, (*it).y, 0));
|
||||
}
|
||||
|
||||
// copy texture coordinates to mesh
|
||||
pMesh.mTextureCoords[0] = new aiVector3D[pMesh.mNumVertices];
|
||||
pMesh.mNumUVComponents[0] = 2;
|
||||
for (size_t i = 0; i < pMesh.mNumVertices; i++) {
|
||||
pMesh.mTextureCoords[0][i] = tc_arr_copy[i];
|
||||
}
|
||||
}
|
||||
|
||||
aiMesh *X3DGeoHelper::make_mesh(const std::vector<int32_t> &pCoordIdx, const std::list<aiVector3D> &pVertices) {
|
||||
std::vector<aiFace> faces;
|
||||
unsigned int prim_type = 0;
|
||||
|
||||
// create faces array from input string with vertices indices.
|
||||
X3DGeoHelper::coordIdx_str2faces_arr(pCoordIdx, faces, prim_type);
|
||||
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.at(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 primitives type and return result.
|
||||
tmesh->mPrimitiveTypes = prim_type;
|
||||
|
||||
return tmesh;
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
|
@ -0,0 +1,38 @@
|
|||
#pragma once
|
||||
|
||||
#include <assimp/vector2.h>
|
||||
#include <assimp/vector3.h>
|
||||
#include <assimp/color4.h>
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
struct aiFace;
|
||||
struct aiMesh;
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
class X3DGeoHelper {
|
||||
public:
|
||||
static aiVector3D make_point2D(float angle, float radius);
|
||||
static void make_arc2D(float pStartAngle, float pEndAngle, float pRadius, size_t numSegments, std::list<aiVector3D> &pVertices);
|
||||
static void extend_point_to_line(const std::list<aiVector3D> &pPoint, std::list<aiVector3D> &pLine);
|
||||
static void polylineIdx_to_lineIdx(const std::list<int32_t> &pPolylineCoordIdx, std::list<int32_t> &pLineCoordIdx);
|
||||
static void rect_parallele_piped(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 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,
|
||||
const std::list<aiColor3D> &pColors, const bool pColorPerVertex);
|
||||
static void add_color(aiMesh &pMesh, const std::vector<int32_t> &pCoordIdx, const std::vector<int32_t> &pColorIdx,
|
||||
const std::list<aiColor4D> &pColors, const bool pColorPerVertex);
|
||||
static void add_normal(aiMesh &pMesh, const std::vector<int32_t> &pCoordIdx, const std::vector<int32_t> &pNormalIdx,
|
||||
const std::list<aiVector3D> &pNormals, const bool pNormalPerVertex);
|
||||
static void add_normal(aiMesh &pMesh, const std::list<aiVector3D> &pNormals, const bool pNormalPerVertex);
|
||||
static void add_tex_coord(aiMesh &pMesh, const std::vector<int32_t> &pCoordIdx, const std::vector<int32_t> &pTexCoordIdx,
|
||||
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);
|
||||
};
|
||||
|
||||
} // namespace Assimp
|
|
@ -46,16 +46,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include <assimp/StringUtils.h>
|
||||
|
||||
// Header files, Assimp.
|
||||
#include <assimp/StringUtils.h>
|
||||
#include <assimp/ParsingUtils.h>
|
||||
#include <assimp/DefaultIOSystem.h>
|
||||
#include <assimp/fast_atof.h>
|
||||
|
||||
// Header files, stdlib.
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
|
@ -126,7 +125,8 @@ struct WordIterator {
|
|||
const char *WordIterator::whitespace = ", \t\r\n";
|
||||
|
||||
X3DImporter::X3DImporter() :
|
||||
mNodeElementCur(nullptr) {
|
||||
mNodeElementCur(nullptr),
|
||||
mScene(nullptr) {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
@ -153,10 +153,29 @@ void X3DImporter::ParseFile(const std::string &file, IOSystem *pIOHandler) {
|
|||
std::unique_ptr<IOStream> fileStream(pIOHandler->Open(file, mode));
|
||||
if (!fileStream.get()) {
|
||||
throw DeadlyImportError("Failed to open file " + file + ".");
|
||||
}
|
||||
}
|
||||
|
||||
XmlParser theParser;
|
||||
if (!theParser.parse(fileStream.get())) {
|
||||
return;
|
||||
}
|
||||
|
||||
XmlNode *node = theParser.findNode("X3D");
|
||||
if (nullptr == node) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto ¤tNode : node->children()) {
|
||||
const std::string ¤tName = currentNode.name();
|
||||
if (currentName == "head") {
|
||||
readMetadata(currentNode);
|
||||
} else if (currentName == "Scene") {
|
||||
readScene(currentNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool X3DImporter::CanRead( const std::string &pFile, IOSystem * /*pIOHandler*/, bool checkSig ) const {
|
||||
bool X3DImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool checkSig) const {
|
||||
if (checkSig) {
|
||||
std::string::size_type pos = pFile.find_last_of(".x3d");
|
||||
if (pos != std::string::npos) {
|
||||
|
@ -167,16 +186,17 @@ bool X3DImporter::CanRead( const std::string &pFile, IOSystem * /*pIOHandler*/,
|
|||
return false;
|
||||
}
|
||||
|
||||
void X3DImporter::GetExtensionList( std::set<std::string> &extensionList ) {
|
||||
void X3DImporter::GetExtensionList(std::set<std::string> &extensionList) {
|
||||
extensionList.insert("x3d");
|
||||
}
|
||||
|
||||
void X3DImporter::InternReadFile( const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler ) {
|
||||
void X3DImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
|
||||
std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb"));
|
||||
if (!stream) {
|
||||
throw DeadlyImportError("Could not open file for reading");
|
||||
}
|
||||
|
||||
mScene = pScene;
|
||||
pScene->mRootNode = new aiNode(pFile);
|
||||
}
|
||||
|
||||
|
@ -184,6 +204,147 @@ const aiImporterDesc *X3DImporter::GetInfo() const {
|
|||
return &Description;
|
||||
}
|
||||
|
||||
}
|
||||
struct meta_entry {
|
||||
std::string name;
|
||||
std::string value;
|
||||
};
|
||||
|
||||
void X3DImporter::readMetadata(XmlNode &node) {
|
||||
std::vector<meta_entry> metaArray;
|
||||
for (auto currentNode : node.children()) {
|
||||
const std::string ¤tName = currentNode.name();
|
||||
if (currentName == "meta") {
|
||||
meta_entry entry;
|
||||
if (XmlParser::getStdStrAttribute(currentNode, "name", entry.name)) {
|
||||
XmlParser::getStdStrAttribute(currentNode, "content", entry.value);
|
||||
metaArray.emplace_back(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
mScene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(metaArray.size()));
|
||||
unsigned int i = 0;
|
||||
for (auto currentMeta : metaArray) {
|
||||
mScene->mMetaData->Set(i, currentMeta.name, currentMeta.value);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void X3DImporter::readScene(XmlNode &node) {
|
||||
for (auto currentNode : node.children()) {
|
||||
const std::string ¤tName = currentNode.name();
|
||||
if (currentName == "Viewpoint") {
|
||||
readViewpoint(currentNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void X3DImporter::readViewpoint(XmlNode &node) {
|
||||
for (auto currentNode : node.children()) {
|
||||
//const std::string ¤tName = currentNode.name();
|
||||
}
|
||||
}
|
||||
|
||||
void readMetadataBoolean(XmlNode &node, X3DNodeElementBase *parent) {
|
||||
std::string val;
|
||||
X3DNodeElementMetaBoolean *boolean = nullptr;
|
||||
if (XmlParser::getStdStrAttribute(node, "value", val)) {
|
||||
std::vector<std::string> values;
|
||||
tokenize<std::string>(val, values, " ");
|
||||
boolean = new X3DNodeElementMetaBoolean(parent);
|
||||
for (size_t i = 0; i < values.size(); ++i) {
|
||||
bool current_boolean = false;
|
||||
if (values[i] == "true") {
|
||||
current_boolean = true;
|
||||
}
|
||||
boolean->Value.emplace_back(current_boolean);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void readMetadataDouble(XmlNode &node, X3DNodeElementBase *parent) {
|
||||
std::string val;
|
||||
X3DNodeElementMetaDouble *doubleNode = nullptr;
|
||||
if (XmlParser::getStdStrAttribute(node, "value", val)) {
|
||||
std::vector<std::string> values;
|
||||
tokenize<std::string>(val, values, " ");
|
||||
doubleNode = new X3DNodeElementMetaDouble(parent);
|
||||
for (size_t i = 0; i < values.size(); ++i) {
|
||||
double current_double = static_cast<double>(fast_atof(values[i].c_str()));
|
||||
doubleNode->Value.emplace_back(current_double);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void readMetadataFloat(XmlNode &node, X3DNodeElementBase *parent) {
|
||||
std::string val;
|
||||
X3DNodeElementMetaFloat *floatNode = nullptr;
|
||||
if (XmlParser::getStdStrAttribute(node, "value", val)) {
|
||||
std::vector<std::string> values;
|
||||
tokenize<std::string>(val, values, " ");
|
||||
floatNode = new X3DNodeElementMetaFloat(parent);
|
||||
for (size_t i = 0; i < values.size(); ++i) {
|
||||
float current_float = static_cast<float>(fast_atof(values[i].c_str()));
|
||||
floatNode->Value.emplace_back(current_float);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void readMetadataInteger(XmlNode &node, X3DNodeElementBase *parent) {
|
||||
std::string val;
|
||||
X3DNodeElementMetaInt *intNode = nullptr;
|
||||
if (XmlParser::getStdStrAttribute(node, "value", val)) {
|
||||
std::vector<std::string> values;
|
||||
tokenize<std::string>(val, values, " ");
|
||||
intNode = new X3DNodeElementMetaInt(parent);
|
||||
for (size_t i = 0; i < values.size(); ++i) {
|
||||
int current_int = static_cast<int>(std::atoi(values[i].c_str()));
|
||||
intNode->Value.emplace_back(current_int);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void readMetadataSet(XmlNode &node, X3DNodeElementBase *parent) {
|
||||
std::string val;
|
||||
X3DNodeElementMetaSet *setNode = new X3DNodeElementMetaSet(parent);
|
||||
if (XmlParser::getStdStrAttribute(node, "name", val)) {
|
||||
setNode->Name = val;
|
||||
}
|
||||
|
||||
if (XmlParser::getStdStrAttribute(node, "reference", val)) {
|
||||
setNode->Reference = val;
|
||||
}
|
||||
}
|
||||
|
||||
void readMetadataString(XmlNode &node, X3DNodeElementBase *parent) {
|
||||
std::string val;
|
||||
X3DNodeElementMetaString *strNode = nullptr;
|
||||
if (XmlParser::getStdStrAttribute(node, "value", val)) {
|
||||
std::vector<std::string> values;
|
||||
tokenize<std::string>(val, values, " ");
|
||||
strNode = new X3DNodeElementMetaString(parent);
|
||||
for (size_t i = 0; i < values.size(); ++i) {
|
||||
strNode->Value.emplace_back(values[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void X3DImporter::readMetadataObject(XmlNode &node) {
|
||||
const std::string &name = node.name();
|
||||
if (name == "MetadataBoolean") {
|
||||
readMetadataBoolean(node, mNodeElementCur);
|
||||
} else if (name == "MetadataDouble") {
|
||||
readMetadataDouble(node, mNodeElementCur);
|
||||
} else if (name == "MetadataFloat") {
|
||||
readMetadataFloat(node, mNodeElementCur);
|
||||
} else if (name == "MetadataInteger") {
|
||||
readMetadataInteger(node, mNodeElementCur);
|
||||
} else if (name == "MetadataSet") {
|
||||
readMetadataSet(node, mNodeElementCur);
|
||||
} else if (name == "MetadataString") {
|
||||
readMetadataString(node, mNodeElementCur);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
|
|
@ -38,16 +38,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
/// \file X3DImporter.hpp
|
||||
/// \brief X3D-format files importer for Assimp.
|
||||
/// \date 2015-2016
|
||||
/// \author smal.root@gmail.com
|
||||
// Thanks to acorn89 for support.
|
||||
|
||||
#ifndef INCLUDED_AI_X3D_IMPORTER_H
|
||||
#define INCLUDED_AI_X3D_IMPORTER_H
|
||||
|
||||
// Header files, Assimp.
|
||||
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include <assimp/XmlParser.h>
|
||||
#include <assimp/importerdesc.h>
|
||||
|
@ -56,7 +50,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/ProgressHandler.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
|
@ -282,8 +278,90 @@ enum class X3DElemType {
|
|||
struct X3DNodeElementBase {
|
||||
X3DNodeElementBase *Parent;
|
||||
std::string ID;
|
||||
std::list<X3DNodeElementBase *> Child;
|
||||
std::list<X3DNodeElementBase *> Children;
|
||||
X3DElemType Type;
|
||||
|
||||
protected:
|
||||
X3DNodeElementBase(X3DElemType type, X3DNodeElementBase *pParent) :
|
||||
Type(type), Parent(pParent) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
struct CX3DNodeElementGroup : X3DNodeElementBase {
|
||||
aiMatrix4x4 Transformation; ///< Transformation matrix.
|
||||
bool Static;
|
||||
bool UseChoice; ///< Flag: if true then use number from \ref Choice to choose what the child will be kept.
|
||||
int32_t Choice; ///< Number of the child which will be kept.
|
||||
};
|
||||
|
||||
struct X3DNodeElementMeta : X3DNodeElementBase {
|
||||
std::string Name; ///< Name of metadata object.
|
||||
std::string Reference;
|
||||
|
||||
virtual ~X3DNodeElementMeta() {
|
||||
// empty
|
||||
}
|
||||
|
||||
protected:
|
||||
X3DNodeElementMeta(X3DElemType type, X3DNodeElementBase *parent) :
|
||||
X3DNodeElementBase(type, parent) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
struct X3DNodeElementMetaBoolean : X3DNodeElementMeta {
|
||||
std::vector<bool> Value; ///< Stored value.
|
||||
|
||||
X3DNodeElementMetaBoolean(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementMeta(X3DElemType::ENET_MetaBoolean, pParent) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
struct X3DNodeElementMetaDouble : X3DNodeElementMeta {
|
||||
std::vector<double> Value; ///< Stored value.
|
||||
|
||||
X3DNodeElementMetaDouble(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementMeta(X3DElemType::ENET_MetaDouble, pParent) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
struct X3DNodeElementMetaFloat : public X3DNodeElementMeta {
|
||||
std::vector<float> Value; ///< Stored value.
|
||||
|
||||
X3DNodeElementMetaFloat(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementMeta(X3DElemType::ENET_MetaFloat, pParent) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
struct X3DNodeElementMetaInt : public X3DNodeElementMeta {
|
||||
std::vector<int32_t> Value; ///< Stored value.
|
||||
|
||||
X3DNodeElementMetaInt(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementMeta(X3DElemType::ENET_MetaInteger, pParent) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
struct X3DNodeElementMetaSet : public X3DNodeElementMeta {
|
||||
std::list<X3DNodeElementMeta> Value; ///< Stored value.
|
||||
|
||||
X3DNodeElementMetaSet(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementMeta(X3DElemType::ENET_MetaSet, pParent) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
struct X3DNodeElementMetaString : public X3DNodeElementMeta {
|
||||
std::list<std::string> Value; ///< Stored value.
|
||||
|
||||
X3DNodeElementMetaString(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementMeta(X3DElemType::ENET_MetaString, pParent) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
class X3DImporter : public BaseImporter {
|
||||
|
@ -311,10 +389,15 @@ public:
|
|||
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
|
||||
const aiImporterDesc *GetInfo() const;
|
||||
void Clear();
|
||||
void readMetadata(XmlNode &node);
|
||||
void readScene(XmlNode &node);
|
||||
void readViewpoint(XmlNode &node);
|
||||
void readMetadataObject(XmlNode &node);
|
||||
|
||||
private:
|
||||
static const aiImporterDesc Description;
|
||||
X3DNodeElementBase *mNodeElementCur; ///< Current element.
|
||||
X3DNodeElementBase *mNodeElementCur;
|
||||
aiScene *mScene;
|
||||
}; // class X3DImporter
|
||||
|
||||
} // namespace Assimp
|
||||
|
|
|
@ -322,8 +322,8 @@ void glTFExporter::GetTexSampler(const aiMaterial* mat, glTF::TexProperty& prop)
|
|||
prop.texture->sampler->minFilter = SamplerMinFilter_Linear;
|
||||
}
|
||||
|
||||
void glTFExporter::GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt)
|
||||
{
|
||||
void glTFExporter::GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& prop,
|
||||
const char* propName, int type, int idx, aiTextureType tt) {
|
||||
aiString tex;
|
||||
aiColor4D col;
|
||||
if (mat->GetTextureCount(tt) > 0) {
|
||||
|
@ -370,7 +370,10 @@ void glTFExporter::GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& pr
|
|||
}
|
||||
|
||||
if (mat->Get(propName, type, idx, col) == AI_SUCCESS) {
|
||||
prop.color[0] = col.r; prop.color[1] = col.g; prop.color[2] = col.b; prop.color[3] = col.a;
|
||||
prop.color[0] = col.r;
|
||||
prop.color[1] = col.g;
|
||||
prop.color[2] = col.b;
|
||||
prop.color[3] = col.a;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1297,24 +1297,24 @@ void glTF2Exporter::ExportMetadata()
|
|||
}
|
||||
}
|
||||
|
||||
inline Ref<Accessor> GetSamplerInputRef(Asset& asset, std::string& animId, Ref<Buffer>& buffer, std::vector<float>& times)
|
||||
{
|
||||
inline Ref<Accessor> GetSamplerInputRef(Asset& asset, std::string& animId,
|
||||
Ref<Buffer>& buffer, std::vector<float>& times) {
|
||||
return ExportData(asset, animId, buffer, (unsigned int)times.size(), ×[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_FLOAT);
|
||||
}
|
||||
|
||||
inline void ExtractTranslationSampler(Asset& asset, std::string& animId, Ref<Buffer>& buffer, const aiNodeAnim* nodeChannel, float ticksPerSecond, Animation::Sampler& sampler)
|
||||
{
|
||||
inline void ExtractTranslationSampler(Asset& asset, std::string& animId, Ref<Buffer>& buffer,
|
||||
const aiNodeAnim* nodeChannel, float ticksPerSecond, Animation::Sampler& sampler) {
|
||||
const unsigned int numKeyframes = nodeChannel->mNumPositionKeys;
|
||||
|
||||
std::vector<float> times(numKeyframes);
|
||||
std::vector<float> values(numKeyframes * 3);
|
||||
std::vector<ai_real> times(numKeyframes);
|
||||
std::vector<ai_real> values(numKeyframes * 3);
|
||||
for (unsigned int i = 0; i < numKeyframes; ++i) {
|
||||
const aiVectorKey& key = nodeChannel->mPositionKeys[i];
|
||||
// mTime is measured in ticks, but GLTF time is measured in seconds, so convert.
|
||||
times[i] = static_cast<float>(key.mTime / ticksPerSecond);
|
||||
values[(i * 3) + 0] = key.mValue.x;
|
||||
values[(i * 3) + 1] = key.mValue.y;
|
||||
values[(i * 3) + 2] = key.mValue.z;
|
||||
values[(i * 3) + 0] = (ai_real) key.mValue.x;
|
||||
values[(i * 3) + 1] = (ai_real) key.mValue.y;
|
||||
values[(i * 3) + 2] = (ai_real) key.mValue.z;
|
||||
}
|
||||
|
||||
sampler.input = GetSamplerInputRef(asset, animId, buffer, times);
|
||||
|
@ -1322,19 +1322,19 @@ inline void ExtractTranslationSampler(Asset& asset, std::string& animId, Ref<Buf
|
|||
sampler.interpolation = Interpolation_LINEAR;
|
||||
}
|
||||
|
||||
inline void ExtractScaleSampler(Asset& asset, std::string& animId, Ref<Buffer>& buffer, const aiNodeAnim* nodeChannel, float ticksPerSecond, Animation::Sampler& sampler)
|
||||
{
|
||||
inline void ExtractScaleSampler(Asset& asset, std::string& animId, Ref<Buffer>& buffer,
|
||||
const aiNodeAnim* nodeChannel, float ticksPerSecond, Animation::Sampler& sampler) {
|
||||
const unsigned int numKeyframes = nodeChannel->mNumScalingKeys;
|
||||
|
||||
std::vector<float> times(numKeyframes);
|
||||
std::vector<float> values(numKeyframes * 3);
|
||||
std::vector<ai_real> times(numKeyframes);
|
||||
std::vector<ai_real> values(numKeyframes * 3);
|
||||
for (unsigned int i = 0; i < numKeyframes; ++i) {
|
||||
const aiVectorKey& key = nodeChannel->mScalingKeys[i];
|
||||
// mTime is measured in ticks, but GLTF time is measured in seconds, so convert.
|
||||
times[i] = static_cast<float>(key.mTime / ticksPerSecond);
|
||||
values[(i * 3) + 0] = key.mValue.x;
|
||||
values[(i * 3) + 1] = key.mValue.y;
|
||||
values[(i * 3) + 2] = key.mValue.z;
|
||||
values[(i * 3) + 0] = (ai_real) key.mValue.x;
|
||||
values[(i * 3) + 1] = (ai_real) key.mValue.y;
|
||||
values[(i * 3) + 2] = (ai_real) key.mValue.z;
|
||||
}
|
||||
|
||||
sampler.input = GetSamplerInputRef(asset, animId, buffer, times);
|
||||
|
@ -1342,20 +1342,20 @@ inline void ExtractScaleSampler(Asset& asset, std::string& animId, Ref<Buffer>&
|
|||
sampler.interpolation = Interpolation_LINEAR;
|
||||
}
|
||||
|
||||
inline void ExtractRotationSampler(Asset& asset, std::string& animId, Ref<Buffer>& buffer, const aiNodeAnim* nodeChannel, float ticksPerSecond, Animation::Sampler& sampler)
|
||||
{
|
||||
inline void ExtractRotationSampler(Asset& asset, std::string& animId, Ref<Buffer>& buffer,
|
||||
const aiNodeAnim* nodeChannel, float ticksPerSecond, Animation::Sampler& sampler) {
|
||||
const unsigned int numKeyframes = nodeChannel->mNumRotationKeys;
|
||||
|
||||
std::vector<float> times(numKeyframes);
|
||||
std::vector<float> values(numKeyframes * 4);
|
||||
std::vector<ai_real> times(numKeyframes);
|
||||
std::vector<ai_real> values(numKeyframes * 4);
|
||||
for (unsigned int i = 0; i < numKeyframes; ++i) {
|
||||
const aiQuatKey& key = nodeChannel->mRotationKeys[i];
|
||||
// mTime is measured in ticks, but GLTF time is measured in seconds, so convert.
|
||||
times[i] = static_cast<float>(key.mTime / ticksPerSecond);
|
||||
values[(i * 4) + 0] = key.mValue.x;
|
||||
values[(i * 4) + 1] = key.mValue.y;
|
||||
values[(i * 4) + 2] = key.mValue.z;
|
||||
values[(i * 4) + 3] = key.mValue.w;
|
||||
values[(i * 4) + 0] = (ai_real) key.mValue.x;
|
||||
values[(i * 4) + 1] = (ai_real) key.mValue.y;
|
||||
values[(i * 4) + 2] = (ai_real) key.mValue.z;
|
||||
values[(i * 4) + 3] = (ai_real) key.mValue.w;
|
||||
}
|
||||
|
||||
sampler.input = GetSamplerInputRef(asset, animId, buffer, times);
|
||||
|
@ -1417,7 +1417,7 @@ void glTF2Exporter::ExportAnimations()
|
|||
}
|
||||
}
|
||||
|
||||
// Assimp documentation staes this is not used (not implemented)
|
||||
// Assimp documentation states this is not used (not implemented)
|
||||
// for (unsigned int channelIndex = 0; channelIndex < anim->mNumMeshChannels; ++channelIndex) {
|
||||
// const aiMeshAnim* meshChannel = anim->mMeshChannels[channelIndex];
|
||||
// }
|
||||
|
|
|
@ -798,6 +798,8 @@ ADD_ASSIMP_IMPORTER( X
|
|||
ADD_ASSIMP_IMPORTER( X3D
|
||||
AssetLib/X3D/X3DImporter.cpp
|
||||
AssetLib/X3D/X3DImporter.hpp
|
||||
AssetLib/X3D/X3DGeoHelper.cpp
|
||||
AssetLib/X3D/X3DGeoHelper.h
|
||||
)
|
||||
|
||||
ADD_ASSIMP_IMPORTER( GLTF
|
||||
|
|
|
@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
|||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
|
@ -42,25 +40,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
*/
|
||||
#include <assimp/scene.h>
|
||||
|
||||
aiNode::aiNode()
|
||||
: mName("")
|
||||
, mParent(nullptr)
|
||||
, mNumChildren(0)
|
||||
, mChildren(nullptr)
|
||||
, mNumMeshes(0)
|
||||
, mMeshes(nullptr)
|
||||
, mMetaData(nullptr) {
|
||||
aiNode::aiNode() :
|
||||
mName(""),
|
||||
mParent(nullptr),
|
||||
mNumChildren(0),
|
||||
mChildren(nullptr),
|
||||
mNumMeshes(0),
|
||||
mMeshes(nullptr),
|
||||
mMetaData(nullptr) {
|
||||
// empty
|
||||
}
|
||||
|
||||
aiNode::aiNode(const std::string& name)
|
||||
: mName(name)
|
||||
, mParent(nullptr)
|
||||
, mNumChildren(0)
|
||||
, mChildren(nullptr)
|
||||
, mNumMeshes(0)
|
||||
, mMeshes(nullptr)
|
||||
, mMetaData(nullptr) {
|
||||
aiNode::aiNode(const std::string &name) :
|
||||
mName(name),
|
||||
mParent(nullptr),
|
||||
mNumChildren(0),
|
||||
mChildren(nullptr),
|
||||
mNumMeshes(0),
|
||||
mMeshes(nullptr),
|
||||
mMetaData(nullptr) {
|
||||
// empty
|
||||
}
|
||||
|
||||
|
@ -68,8 +66,7 @@ aiNode::aiNode(const std::string& name)
|
|||
aiNode::~aiNode() {
|
||||
// delete all children recursively
|
||||
// to make sure we won't crash if the data is invalid ...
|
||||
if (mNumChildren && mChildren)
|
||||
{
|
||||
if (mNumChildren && mChildren) {
|
||||
for (unsigned int a = 0; a < mNumChildren; a++)
|
||||
delete mChildren[a];
|
||||
}
|
||||
|
@ -78,7 +75,7 @@ aiNode::~aiNode() {
|
|||
delete mMetaData;
|
||||
}
|
||||
|
||||
const aiNode *aiNode::FindNode(const char* name) const {
|
||||
const aiNode *aiNode::FindNode(const char *name) const {
|
||||
if (nullptr == name) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -86,7 +83,7 @@ const aiNode *aiNode::FindNode(const char* name) const {
|
|||
return this;
|
||||
}
|
||||
for (unsigned int i = 0; i < mNumChildren; ++i) {
|
||||
const aiNode* const p = mChildren[i]->FindNode(name);
|
||||
const aiNode *const p = mChildren[i]->FindNode(name);
|
||||
if (p) {
|
||||
return p;
|
||||
}
|
||||
|
@ -95,11 +92,10 @@ const aiNode *aiNode::FindNode(const char* name) const {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
aiNode *aiNode::FindNode(const char* name) {
|
||||
if (!::strcmp(mName.data, name))return this;
|
||||
for (unsigned int i = 0; i < mNumChildren; ++i)
|
||||
{
|
||||
aiNode* const p = mChildren[i]->FindNode(name);
|
||||
aiNode *aiNode::FindNode(const char *name) {
|
||||
if (!::strcmp(mName.data, name)) return this;
|
||||
for (unsigned int i = 0; i < mNumChildren; ++i) {
|
||||
aiNode *const p = mChildren[i]->FindNode(name);
|
||||
if (p) {
|
||||
return p;
|
||||
}
|
||||
|
@ -121,17 +117,16 @@ void aiNode::addChildren(unsigned int numChildren, aiNode **children) {
|
|||
}
|
||||
|
||||
if (mNumChildren > 0) {
|
||||
aiNode **tmp = new aiNode*[mNumChildren];
|
||||
::memcpy(tmp, mChildren, sizeof(aiNode*) * mNumChildren);
|
||||
aiNode **tmp = new aiNode *[mNumChildren];
|
||||
::memcpy(tmp, mChildren, sizeof(aiNode *) * mNumChildren);
|
||||
delete[] mChildren;
|
||||
mChildren = new aiNode*[mNumChildren + numChildren];
|
||||
::memcpy(mChildren, tmp, sizeof(aiNode*) * mNumChildren);
|
||||
::memcpy(&mChildren[mNumChildren], children, sizeof(aiNode*)* numChildren);
|
||||
mChildren = new aiNode *[mNumChildren + numChildren];
|
||||
::memcpy(mChildren, tmp, sizeof(aiNode *) * mNumChildren);
|
||||
::memcpy(&mChildren[mNumChildren], children, sizeof(aiNode *) * numChildren);
|
||||
mNumChildren += numChildren;
|
||||
delete[] tmp;
|
||||
}
|
||||
else {
|
||||
mChildren = new aiNode*[numChildren];
|
||||
} else {
|
||||
mChildren = new aiNode *[numChildren];
|
||||
for (unsigned int i = 0; i < numChildren; i++) {
|
||||
mChildren[i] = children[i];
|
||||
}
|
||||
|
|
|
@ -133,12 +133,12 @@ inline ::aiQuatKey max(const ::aiQuatKey &a, const ::aiQuatKey &b) {
|
|||
|
||||
// std::min for aiVertexWeight
|
||||
inline ::aiVertexWeight min(const ::aiVertexWeight &a, const ::aiVertexWeight &b) {
|
||||
return ::aiVertexWeight(min(a.mVertexId, b.mVertexId), min(a.mWeight, b.mWeight));
|
||||
return ::aiVertexWeight(min(a.mVertexId, b.mVertexId),static_cast<ai_real>(min(a.mWeight, b.mWeight)));
|
||||
}
|
||||
|
||||
// std::max for aiVertexWeight
|
||||
inline ::aiVertexWeight max(const ::aiVertexWeight &a, const ::aiVertexWeight &b) {
|
||||
return ::aiVertexWeight(max(a.mVertexId, b.mVertexId), max(a.mWeight, b.mWeight));
|
||||
return ::aiVertexWeight(static_cast<ai_real>(max(a.mVertexId, b.mVertexId)), static_cast<ai_real>(max(a.mWeight, b.mWeight)));
|
||||
}
|
||||
|
||||
} // end namespace std
|
||||
|
|
|
@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
|||
|
||||
Copyright (c) 2006-2020, assimp team
|
||||
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
|
|
Loading…
Reference in New Issue