From 52228a93f8215ec6bb4d89f313d66049546ed884 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 6 May 2021 21:07:38 +0200 Subject: [PATCH] Fix X3DGeohelper. --- code/AssetLib/X3D/X3DGeoHelper.cpp | 530 ++++++++++++++++++++++++++ code/AssetLib/X3D/X3DGeoHelper.h | 38 ++ code/AssetLib/X3D/X3DImporter.cpp | 179 ++++++++- code/AssetLib/X3D/X3DImporter.hpp | 101 ++++- code/AssetLib/glTF/glTFExporter.cpp | 9 +- code/AssetLib/glTF2/glTF2Exporter.cpp | 50 +-- code/CMakeLists.txt | 2 + code/Common/scene.cpp | 65 ++-- code/PostProcessing/ProcessHelper.h | 4 +- include/assimp/scene.h | 2 - 10 files changed, 895 insertions(+), 85 deletions(-) create mode 100644 code/AssetLib/X3D/X3DGeoHelper.cpp create mode 100644 code/AssetLib/X3D/X3DGeoHelper.h diff --git a/code/AssetLib/X3D/X3DGeoHelper.cpp b/code/AssetLib/X3D/X3DGeoHelper.cpp new file mode 100644 index 000000000..8a078d0f5 --- /dev/null +++ b/code/AssetLib/X3D/X3DGeoHelper.cpp @@ -0,0 +1,530 @@ +#include "X3DGeoHelper.h" +#include "X3DImporter.hpp" + +#include +#include + +#include + +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 &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 &pPoint, std::list &pLine) { + std::list::const_iterator pit = pPoint.begin(); + std::list::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 &pPolylineCoordIdx, std::list &pLineCoordIdx) { + std::list::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::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 &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 &pCoordIdx, std::vector &pFaces, unsigned int &pPrimitiveTypes) { + std::vector f_data(pCoordIdx); + std::vector 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::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(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::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 &pColors, const bool pColorPerVertex) { + std::list tcol; + + // create RGBA array from RGB. + for (std::list::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 &pColors, const bool pColorPerVertex) { + std::list::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 &pCoordIdx, const std::vector &pColorIdx, + const std::list &pColors, const bool pColorPerVertex) { + std::list tcol; + + // create RGBA array from RGB. + for (std::list::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 &coordIdx, const std::vector &colorIdx, + const std::list &colors, bool pColorPerVertex) { + std::vector col_tgt_arr; + std::list col_tgt_list; + std::vector 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::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::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::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::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 &pCoordIdx, const std::vector &pNormalIdx, + const std::list &pNormals, const bool pNormalPerVertex) { + std::vector tind; + std::vector norm_arr_copy; + + // copy list to array because we are need indexed access to normals. + norm_arr_copy.reserve(pNormals.size()); + for (std::list::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::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::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::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 &pNormals, const bool pNormalPerVertex) { + std::list::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 &pCoordIdx, const std::vector &pTexCoordIdx, + const std::list &pTexCoords) { + std::vector texcoord_arr_copy; + std::vector 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::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 &pTexCoords) { + std::vector 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::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 &pCoordIdx, const std::list &pVertices) { + std::vector 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(ts); + for (size_t i = 0; i < ts; i++) + tmesh->mFaces[i] = faces.at(i); + + // vertices + std::list::const_iterator vit = pVertices.begin(); + + ts = pVertices.size(); + tmesh->mVertices = new aiVector3D[ts]; + tmesh->mNumVertices = static_cast(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 diff --git a/code/AssetLib/X3D/X3DGeoHelper.h b/code/AssetLib/X3D/X3DGeoHelper.h new file mode 100644 index 000000000..38b6de4dc --- /dev/null +++ b/code/AssetLib/X3D/X3DGeoHelper.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include + +#include +#include + +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 &pVertices); + static void extend_point_to_line(const std::list &pPoint, std::list &pLine); + static void polylineIdx_to_lineIdx(const std::list &pPolylineCoordIdx, std::list &pLineCoordIdx); + static void rect_parallele_piped(const aiVector3D &pSize, std::list &pVertices); + static void coordIdx_str2faces_arr(const std::vector &pCoordIdx, std::vector &pFaces, unsigned int &pPrimitiveTypes); + static void add_color(aiMesh &pMesh, const std::list &pColors, const bool pColorPerVertex); + static void add_color(aiMesh &pMesh, const std::list &pColors, const bool pColorPerVertex); + static void add_color(aiMesh &pMesh, const std::vector &pCoordIdx, const std::vector &pColorIdx, + const std::list &pColors, const bool pColorPerVertex); + static void add_color(aiMesh &pMesh, const std::vector &pCoordIdx, const std::vector &pColorIdx, + const std::list &pColors, const bool pColorPerVertex); + static void add_normal(aiMesh &pMesh, const std::vector &pCoordIdx, const std::vector &pNormalIdx, + const std::list &pNormals, const bool pNormalPerVertex); + static void add_normal(aiMesh &pMesh, const std::list &pNormals, const bool pNormalPerVertex); + static void add_tex_coord(aiMesh &pMesh, const std::vector &pCoordIdx, const std::vector &pTexCoordIdx, + const std::list &pTexCoords); + static void add_tex_coord(aiMesh &pMesh, const std::list &pTexCoords); + static aiMesh *make_mesh(const std::vector &pCoordIdx, const std::list &pVertices); +}; + +} // namespace Assimp diff --git a/code/AssetLib/X3D/X3DImporter.cpp b/code/AssetLib/X3D/X3DImporter.cpp index ff6e4f40e..341cc9d99 100644 --- a/code/AssetLib/X3D/X3DImporter.cpp +++ b/code/AssetLib/X3D/X3DImporter.cpp @@ -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 -// Header files, Assimp. +#include +#include #include #include // Header files, stdlib. #include #include -#include 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 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 &extensionList ) { +void X3DImporter::GetExtensionList(std::set &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 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 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(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 values; + tokenize(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 values; + tokenize(val, values, " "); + doubleNode = new X3DNodeElementMetaDouble(parent); + for (size_t i = 0; i < values.size(); ++i) { + double current_double = static_cast(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 values; + tokenize(val, values, " "); + floatNode = new X3DNodeElementMetaFloat(parent); + for (size_t i = 0; i < values.size(); ++i) { + float current_float = static_cast(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 values; + tokenize(val, values, " "); + intNode = new X3DNodeElementMetaInt(parent); + for (size_t i = 0; i < values.size(); ++i) { + int current_int = static_cast(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 values; + tokenize(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 diff --git a/code/AssetLib/X3D/X3DImporter.hpp b/code/AssetLib/X3D/X3DImporter.hpp index 4444bacd0..1b6410c36 100644 --- a/code/AssetLib/X3D/X3DImporter.hpp +++ b/code/AssetLib/X3D/X3DImporter.hpp @@ -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 #include #include @@ -56,7 +50,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include +#include namespace Assimp { @@ -282,8 +278,90 @@ enum class X3DElemType { struct X3DNodeElementBase { X3DNodeElementBase *Parent; std::string ID; - std::list Child; + std::list 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 Value; ///< Stored value. + + X3DNodeElementMetaBoolean(X3DNodeElementBase *pParent) : + X3DNodeElementMeta(X3DElemType::ENET_MetaBoolean, pParent) { + // empty + } +}; + +struct X3DNodeElementMetaDouble : X3DNodeElementMeta { + std::vector Value; ///< Stored value. + + X3DNodeElementMetaDouble(X3DNodeElementBase *pParent) : + X3DNodeElementMeta(X3DElemType::ENET_MetaDouble, pParent) { + // empty + } +}; + +struct X3DNodeElementMetaFloat : public X3DNodeElementMeta { + std::vector Value; ///< Stored value. + + X3DNodeElementMetaFloat(X3DNodeElementBase *pParent) : + X3DNodeElementMeta(X3DElemType::ENET_MetaFloat, pParent) { + // empty + } +}; + +struct X3DNodeElementMetaInt : public X3DNodeElementMeta { + std::vector Value; ///< Stored value. + + X3DNodeElementMetaInt(X3DNodeElementBase *pParent) : + X3DNodeElementMeta(X3DElemType::ENET_MetaInteger, pParent) { + // empty + } +}; + +struct X3DNodeElementMetaSet : public X3DNodeElementMeta { + std::list Value; ///< Stored value. + + X3DNodeElementMetaSet(X3DNodeElementBase *pParent) : + X3DNodeElementMeta(X3DElemType::ENET_MetaSet, pParent) { + // empty + } +}; + +struct X3DNodeElementMetaString : public X3DNodeElementMeta { + std::list 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 diff --git a/code/AssetLib/glTF/glTFExporter.cpp b/code/AssetLib/glTF/glTFExporter.cpp index 1951167c6..528604cd8 100644 --- a/code/AssetLib/glTF/glTFExporter.cpp +++ b/code/AssetLib/glTF/glTFExporter.cpp @@ -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; } } diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index 565117ddb..8eaf3c169 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -1297,24 +1297,24 @@ void glTF2Exporter::ExportMetadata() } } -inline Ref GetSamplerInputRef(Asset& asset, std::string& animId, Ref& buffer, std::vector& times) -{ +inline Ref GetSamplerInputRef(Asset& asset, std::string& animId, + Ref& buffer, std::vector& 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, const aiNodeAnim* nodeChannel, float ticksPerSecond, Animation::Sampler& sampler) -{ +inline void ExtractTranslationSampler(Asset& asset, std::string& animId, Ref& buffer, + const aiNodeAnim* nodeChannel, float ticksPerSecond, Animation::Sampler& sampler) { const unsigned int numKeyframes = nodeChannel->mNumPositionKeys; - std::vector times(numKeyframes); - std::vector values(numKeyframes * 3); + std::vector times(numKeyframes); + std::vector 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(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& buffer, const aiNodeAnim* nodeChannel, float ticksPerSecond, Animation::Sampler& sampler) -{ +inline void ExtractScaleSampler(Asset& asset, std::string& animId, Ref& buffer, + const aiNodeAnim* nodeChannel, float ticksPerSecond, Animation::Sampler& sampler) { const unsigned int numKeyframes = nodeChannel->mNumScalingKeys; - std::vector times(numKeyframes); - std::vector values(numKeyframes * 3); + std::vector times(numKeyframes); + std::vector 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(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& sampler.interpolation = Interpolation_LINEAR; } -inline void ExtractRotationSampler(Asset& asset, std::string& animId, Ref& buffer, const aiNodeAnim* nodeChannel, float ticksPerSecond, Animation::Sampler& sampler) -{ +inline void ExtractRotationSampler(Asset& asset, std::string& animId, Ref& buffer, + const aiNodeAnim* nodeChannel, float ticksPerSecond, Animation::Sampler& sampler) { const unsigned int numKeyframes = nodeChannel->mNumRotationKeys; - std::vector times(numKeyframes); - std::vector values(numKeyframes * 4); + std::vector times(numKeyframes); + std::vector 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(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]; // } diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index bbcad86e5..0dbbd85c4 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -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 diff --git a/code/Common/scene.cpp b/code/Common/scene.cpp index f56562b1c..12667f530 100644 --- a/code/Common/scene.cpp +++ b/code/Common/scene.cpp @@ -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 -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]; } diff --git a/code/PostProcessing/ProcessHelper.h b/code/PostProcessing/ProcessHelper.h index 8520b21ec..e851c97e9 100644 --- a/code/PostProcessing/ProcessHelper.h +++ b/code/PostProcessing/ProcessHelper.h @@ -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(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(max(a.mVertexId, b.mVertexId)), static_cast(max(a.mWeight, b.mWeight))); } } // end namespace std diff --git a/include/assimp/scene.h b/include/assimp/scene.h index 2a9a77b02..b8f034ebf 100644 --- a/include/assimp/scene.h +++ b/include/assimp/scene.h @@ -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,