mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-14 16:14:38 +00:00
update assimp to 5.2.3 Bugfix-Release
This commit is contained in:
parent
3f796d2a06
commit
f297476092
1150 changed files with 165834 additions and 112019 deletions
675
Engine/lib/assimp/code/AssetLib/X3D/X3DExporter.cpp
Normal file
675
Engine/lib/assimp/code/AssetLib/X3D/X3DExporter.cpp
Normal file
|
|
@ -0,0 +1,675 @@
|
|||
/// \file X3DExporter.cpp
|
||||
/// \brief X3D-format files exporter for Assimp. Implementation.
|
||||
/// \date 2016
|
||||
/// \author smal.root@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_EXPORT
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_EXPORTER
|
||||
|
||||
#include "X3DExporter.hpp"
|
||||
|
||||
// Header files, Assimp.
|
||||
#include <assimp/Exceptional.h>
|
||||
#include <assimp/StringUtils.h>
|
||||
#include <assimp/Exporter.hpp>
|
||||
#include <assimp/IOSystem.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
void ExportSceneX3D(const char *pFile, IOSystem *pIOSystem, const aiScene *pScene, const ExportProperties *pProperties) {
|
||||
X3DExporter exporter(pFile, pIOSystem, pScene, pProperties);
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
void X3DExporter::IndentationStringSet(const size_t pNewLevel) {
|
||||
if (pNewLevel > mIndentationString.size()) {
|
||||
if (pNewLevel > mIndentationString.capacity()) mIndentationString.reserve(pNewLevel + 1);
|
||||
|
||||
for (size_t i = 0, i_e = pNewLevel - mIndentationString.size(); i < i_e; i++)
|
||||
mIndentationString.push_back('\t');
|
||||
} else if (pNewLevel < mIndentationString.size()) {
|
||||
mIndentationString.resize(pNewLevel);
|
||||
}
|
||||
}
|
||||
|
||||
void X3DExporter::XML_Write(const string &pData) {
|
||||
if (pData.size() == 0) return;
|
||||
if (mOutFile->Write((void *)pData.data(), pData.length(), 1) != 1) throw DeadlyExportError("Failed to write scene data!");
|
||||
}
|
||||
|
||||
aiMatrix4x4 X3DExporter::Matrix_GlobalToCurrent(const aiNode &pNode) const {
|
||||
aiNode *cur_node;
|
||||
std::list<aiMatrix4x4> matr;
|
||||
aiMatrix4x4 out_matr;
|
||||
|
||||
// starting walk from current element to root
|
||||
matr.push_back(pNode.mTransformation);
|
||||
cur_node = pNode.mParent;
|
||||
if (cur_node != nullptr) {
|
||||
do {
|
||||
matr.push_back(cur_node->mTransformation);
|
||||
cur_node = cur_node->mParent;
|
||||
} while (cur_node != nullptr);
|
||||
}
|
||||
|
||||
// multiplicate all matrices in reverse order
|
||||
for (std::list<aiMatrix4x4>::reverse_iterator rit = matr.rbegin(); rit != matr.rend(); ++rit)
|
||||
out_matr = out_matr * (*rit);
|
||||
|
||||
return out_matr;
|
||||
}
|
||||
|
||||
void X3DExporter::AttrHelper_FloatToString(const float pValue, std::string &pTargetString) {
|
||||
pTargetString = to_string(pValue);
|
||||
AttrHelper_CommaToPoint(pTargetString);
|
||||
}
|
||||
|
||||
void X3DExporter::AttrHelper_Vec3DArrToString(const aiVector3D *pArray, const size_t pArray_Size, string &pTargetString) {
|
||||
pTargetString.clear();
|
||||
pTargetString.reserve(pArray_Size * 6); // (Number + space) * 3.
|
||||
for (size_t idx = 0; idx < pArray_Size; idx++)
|
||||
pTargetString.append(to_string(pArray[idx].x) + " " + to_string(pArray[idx].y) + " " + to_string(pArray[idx].z) + " ");
|
||||
|
||||
// remove last space symbol.
|
||||
pTargetString.resize(pTargetString.length() - 1);
|
||||
AttrHelper_CommaToPoint(pTargetString);
|
||||
}
|
||||
|
||||
void X3DExporter::AttrHelper_Vec2DArrToString(const aiVector2D *pArray, const size_t pArray_Size, std::string &pTargetString) {
|
||||
pTargetString.clear();
|
||||
pTargetString.reserve(pArray_Size * 4); // (Number + space) * 2.
|
||||
for (size_t idx = 0; idx < pArray_Size; idx++)
|
||||
pTargetString.append(to_string(pArray[idx].x) + " " + to_string(pArray[idx].y) + " ");
|
||||
|
||||
// remove last space symbol.
|
||||
pTargetString.resize(pTargetString.length() - 1);
|
||||
AttrHelper_CommaToPoint(pTargetString);
|
||||
}
|
||||
|
||||
void X3DExporter::AttrHelper_Vec3DAsVec2fArrToString(const aiVector3D *pArray, const size_t pArray_Size, string &pTargetString) {
|
||||
pTargetString.clear();
|
||||
pTargetString.reserve(pArray_Size * 4); // (Number + space) * 2.
|
||||
for (size_t idx = 0; idx < pArray_Size; idx++)
|
||||
pTargetString.append(to_string(pArray[idx].x) + " " + to_string(pArray[idx].y) + " ");
|
||||
|
||||
// remove last space symbol.
|
||||
pTargetString.resize(pTargetString.length() - 1);
|
||||
AttrHelper_CommaToPoint(pTargetString);
|
||||
}
|
||||
|
||||
void X3DExporter::AttrHelper_Col4DArrToString(const aiColor4D *pArray, const size_t pArray_Size, string &pTargetString) {
|
||||
pTargetString.clear();
|
||||
pTargetString.reserve(pArray_Size * 8); // (Number + space) * 4.
|
||||
for (size_t idx = 0; idx < pArray_Size; idx++)
|
||||
pTargetString.append(to_string(pArray[idx].r) + " " + to_string(pArray[idx].g) + " " + to_string(pArray[idx].b) + " " +
|
||||
to_string(pArray[idx].a) + " ");
|
||||
|
||||
// remove last space symbol.
|
||||
pTargetString.resize(pTargetString.length() - 1);
|
||||
AttrHelper_CommaToPoint(pTargetString);
|
||||
}
|
||||
|
||||
void X3DExporter::AttrHelper_Col3DArrToString(const aiColor3D *pArray, const size_t pArray_Size, std::string &pTargetString) {
|
||||
pTargetString.clear();
|
||||
pTargetString.reserve(pArray_Size * 6); // (Number + space) * 3.
|
||||
for (size_t idx = 0; idx < pArray_Size; idx++)
|
||||
pTargetString.append(to_string(pArray[idx].r) + " " + to_string(pArray[idx].g) + " " + to_string(pArray[idx].b) + " ");
|
||||
|
||||
// remove last space symbol.
|
||||
pTargetString.resize(pTargetString.length() - 1);
|
||||
AttrHelper_CommaToPoint(pTargetString);
|
||||
}
|
||||
|
||||
void X3DExporter::AttrHelper_Color3ToAttrList(std::list<SAttribute> &pList, const std::string &pName, const aiColor3D &pValue, const aiColor3D &pDefaultValue) {
|
||||
string tstr;
|
||||
|
||||
if (pValue == pDefaultValue) return;
|
||||
|
||||
AttrHelper_Col3DArrToString(&pValue, 1, tstr);
|
||||
pList.push_back({ pName, tstr });
|
||||
}
|
||||
|
||||
void X3DExporter::AttrHelper_FloatToAttrList(std::list<SAttribute> &pList, const string &pName, const float pValue, const float pDefaultValue) {
|
||||
string tstr;
|
||||
|
||||
if (pValue == pDefaultValue) return;
|
||||
|
||||
AttrHelper_FloatToString(pValue, tstr);
|
||||
pList.push_back({ pName, tstr });
|
||||
}
|
||||
|
||||
void X3DExporter::NodeHelper_OpenNode(const string &pNodeName, const size_t pTabLevel, const bool pEmptyElement, const list<SAttribute> &pAttrList) {
|
||||
// Write indentation.
|
||||
IndentationStringSet(pTabLevel);
|
||||
XML_Write(mIndentationString);
|
||||
// Begin of the element
|
||||
XML_Write("<" + pNodeName);
|
||||
// Write attributes
|
||||
for (const SAttribute &attr : pAttrList) {
|
||||
XML_Write(" " + attr.Name + "='" + attr.Value + "'");
|
||||
}
|
||||
|
||||
// End of the element
|
||||
if (pEmptyElement) {
|
||||
XML_Write("/>\n");
|
||||
} else {
|
||||
XML_Write(">\n");
|
||||
}
|
||||
}
|
||||
|
||||
void X3DExporter::NodeHelper_OpenNode(const string &pNodeName, const size_t pTabLevel, const bool pEmptyElement) {
|
||||
const list<SAttribute> attr_list;
|
||||
|
||||
NodeHelper_OpenNode(pNodeName, pTabLevel, pEmptyElement, attr_list);
|
||||
}
|
||||
|
||||
void X3DExporter::NodeHelper_CloseNode(const string &pNodeName, const size_t pTabLevel) {
|
||||
// Write indentation.
|
||||
IndentationStringSet(pTabLevel);
|
||||
XML_Write(mIndentationString);
|
||||
// Write element
|
||||
XML_Write("</" + pNodeName + ">\n");
|
||||
}
|
||||
|
||||
void X3DExporter::Export_Node(const aiNode *pNode, const size_t pTabLevel) {
|
||||
bool transform = false;
|
||||
list<SAttribute> attr_list;
|
||||
|
||||
// In Assimp lights is stored in next way: light source store in mScene->mLights and in node tree must present aiNode with name same as
|
||||
// light source has. Considering it we must compare every aiNode name with light sources names. Why not to look where ligths is present
|
||||
// and save them to fili? Because corresponding aiNode can be already written to file and we can only add information to file not to edit.
|
||||
if (CheckAndExport_Light(*pNode, pTabLevel)) return;
|
||||
|
||||
// Check if need DEF.
|
||||
if (pNode->mName.length) attr_list.push_back({ "DEF", pNode->mName.C_Str() });
|
||||
|
||||
// Check if need <Transformation> node against <Group>.
|
||||
if (!pNode->mTransformation.IsIdentity()) {
|
||||
auto Vector2String = [this](const aiVector3D pVector) -> string {
|
||||
string tstr = to_string(pVector.x) + " " + to_string(pVector.y) + " " + to_string(pVector.z);
|
||||
|
||||
AttrHelper_CommaToPoint(tstr);
|
||||
|
||||
return tstr;
|
||||
};
|
||||
|
||||
auto Rotation2String = [this](const aiVector3D pAxis, const ai_real pAngle) -> string {
|
||||
string tstr = to_string(pAxis.x) + " " + to_string(pAxis.y) + " " + to_string(pAxis.z) + " " + to_string(pAngle);
|
||||
|
||||
AttrHelper_CommaToPoint(tstr);
|
||||
|
||||
return tstr;
|
||||
};
|
||||
|
||||
aiVector3D scale, translate, rotate_axis;
|
||||
ai_real rotate_angle;
|
||||
|
||||
transform = true;
|
||||
pNode->mTransformation.Decompose(scale, rotate_axis, rotate_angle, translate);
|
||||
// Check if values different from default
|
||||
if ((rotate_angle != 0) && (rotate_axis.Length() > 0))
|
||||
attr_list.push_back({ "rotation", Rotation2String(rotate_axis, rotate_angle) });
|
||||
|
||||
if (!scale.Equal({ 1.0, 1.0, 1.0 })) {
|
||||
attr_list.push_back({ "scale", Vector2String(scale) });
|
||||
}
|
||||
if (translate.Length() > 0) {
|
||||
attr_list.push_back({ "translation", Vector2String(translate) });
|
||||
}
|
||||
}
|
||||
|
||||
// Begin node if need.
|
||||
if (transform)
|
||||
NodeHelper_OpenNode("Transform", pTabLevel, false, attr_list);
|
||||
else
|
||||
NodeHelper_OpenNode("Group", pTabLevel);
|
||||
|
||||
// Export metadata
|
||||
if (pNode->mMetaData != nullptr) {
|
||||
for (size_t idx_prop = 0; idx_prop < pNode->mMetaData->mNumProperties; idx_prop++) {
|
||||
const aiString *key;
|
||||
const aiMetadataEntry *entry;
|
||||
|
||||
if (pNode->mMetaData->Get(idx_prop, key, entry)) {
|
||||
switch (entry->mType) {
|
||||
case AI_BOOL:
|
||||
Export_MetadataBoolean(*key, *static_cast<bool *>(entry->mData), pTabLevel + 1);
|
||||
break;
|
||||
case AI_DOUBLE:
|
||||
Export_MetadataDouble(*key, *static_cast<double *>(entry->mData), pTabLevel + 1);
|
||||
break;
|
||||
case AI_FLOAT:
|
||||
Export_MetadataFloat(*key, *static_cast<float *>(entry->mData), pTabLevel + 1);
|
||||
break;
|
||||
case AI_INT32:
|
||||
Export_MetadataInteger(*key, *static_cast<int32_t *>(entry->mData), pTabLevel + 1);
|
||||
break;
|
||||
case AI_AISTRING:
|
||||
Export_MetadataString(*key, *static_cast<aiString *>(entry->mData), pTabLevel + 1);
|
||||
break;
|
||||
default:
|
||||
LogError("Unsupported metadata type: " + to_string(entry->mType));
|
||||
break;
|
||||
} // switch(entry->mType)
|
||||
}
|
||||
}
|
||||
} // if(pNode->mMetaData != nullptr)
|
||||
|
||||
// Export meshes.
|
||||
for (size_t idx_mesh = 0; idx_mesh < pNode->mNumMeshes; idx_mesh++)
|
||||
Export_Mesh(pNode->mMeshes[idx_mesh], pTabLevel + 1);
|
||||
// Export children.
|
||||
for (size_t idx_node = 0; idx_node < pNode->mNumChildren; idx_node++)
|
||||
Export_Node(pNode->mChildren[idx_node], pTabLevel + 1);
|
||||
|
||||
// End node if need.
|
||||
if (transform)
|
||||
NodeHelper_CloseNode("Transform", pTabLevel);
|
||||
else
|
||||
NodeHelper_CloseNode("Group", pTabLevel);
|
||||
}
|
||||
|
||||
void X3DExporter::Export_Mesh(const size_t pIdxMesh, const size_t pTabLevel) {
|
||||
const char *NodeName_IFS = "IndexedFaceSet";
|
||||
const char *NodeName_Shape = "Shape";
|
||||
|
||||
list<SAttribute> attr_list;
|
||||
aiMesh &mesh = *mScene->mMeshes[pIdxMesh]; // create alias for convenience.
|
||||
|
||||
// Check if mesh already defined early.
|
||||
if (mDEF_Map_Mesh.find(pIdxMesh) != mDEF_Map_Mesh.end()) {
|
||||
// Mesh already defined, just refer to it
|
||||
attr_list.push_back({ "USE", mDEF_Map_Mesh.at(pIdxMesh) });
|
||||
NodeHelper_OpenNode(NodeName_Shape, pTabLevel, true, attr_list);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
string mesh_name(mesh.mName.C_Str() + string("_IDX_") + to_string(pIdxMesh)); // Create mesh name
|
||||
|
||||
// Define mesh name.
|
||||
attr_list.push_back({ "DEF", mesh_name });
|
||||
mDEF_Map_Mesh[pIdxMesh] = mesh_name;
|
||||
|
||||
//
|
||||
// "Shape" node.
|
||||
//
|
||||
NodeHelper_OpenNode(NodeName_Shape, pTabLevel, false, attr_list);
|
||||
attr_list.clear();
|
||||
|
||||
//
|
||||
// "Appearance" node.
|
||||
//
|
||||
Export_Material(mesh.mMaterialIndex, pTabLevel + 1);
|
||||
|
||||
//
|
||||
// "IndexedFaceSet" node.
|
||||
//
|
||||
// Fill attributes which differ from default. In Assimp for colors, vertices and normals used one indices set. So, only "coordIndex" must be set.
|
||||
string coordIndex;
|
||||
|
||||
// fill coordinates index.
|
||||
coordIndex.reserve(mesh.mNumVertices * 4); // Index + space + Face delimiter
|
||||
for (size_t idx_face = 0; idx_face < mesh.mNumFaces; idx_face++) {
|
||||
const aiFace &face_cur = mesh.mFaces[idx_face];
|
||||
|
||||
for (size_t idx_vert = 0; idx_vert < face_cur.mNumIndices; idx_vert++) {
|
||||
coordIndex.append(to_string(face_cur.mIndices[idx_vert]) + " ");
|
||||
}
|
||||
|
||||
coordIndex.append("-1 "); // face delimiter.
|
||||
}
|
||||
|
||||
// remove last space symbol.
|
||||
coordIndex.resize(coordIndex.length() - 1);
|
||||
attr_list.push_back({ "coordIndex", coordIndex });
|
||||
// create node
|
||||
NodeHelper_OpenNode(NodeName_IFS, pTabLevel + 1, false, attr_list);
|
||||
attr_list.clear();
|
||||
// Child nodes for "IndexedFaceSet" needed when used colors, textures or normals.
|
||||
string attr_value;
|
||||
|
||||
// Export <Coordinate>
|
||||
AttrHelper_Vec3DArrToString(mesh.mVertices, mesh.mNumVertices, attr_value);
|
||||
attr_list.push_back({ "point", attr_value });
|
||||
NodeHelper_OpenNode("Coordinate", pTabLevel + 2, true, attr_list);
|
||||
attr_list.clear();
|
||||
|
||||
// Export <ColorRGBA>
|
||||
if (mesh.HasVertexColors(0)) {
|
||||
AttrHelper_Col4DArrToString(mesh.mColors[0], mesh.mNumVertices, attr_value);
|
||||
attr_list.push_back({ "color", attr_value });
|
||||
NodeHelper_OpenNode("ColorRGBA", pTabLevel + 2, true, attr_list);
|
||||
attr_list.clear();
|
||||
}
|
||||
|
||||
// Export <TextureCoordinate>
|
||||
if (mesh.HasTextureCoords(0)) {
|
||||
AttrHelper_Vec3DAsVec2fArrToString(mesh.mTextureCoords[0], mesh.mNumVertices, attr_value);
|
||||
attr_list.push_back({ "point", attr_value });
|
||||
NodeHelper_OpenNode("TextureCoordinate", pTabLevel + 2, true, attr_list);
|
||||
attr_list.clear();
|
||||
}
|
||||
|
||||
// Export <Normal>
|
||||
if (mesh.HasNormals()) {
|
||||
AttrHelper_Vec3DArrToString(mesh.mNormals, mesh.mNumVertices, attr_value);
|
||||
attr_list.push_back({ "vector", attr_value });
|
||||
NodeHelper_OpenNode("Normal", pTabLevel + 2, true, attr_list);
|
||||
attr_list.clear();
|
||||
}
|
||||
|
||||
//
|
||||
// Close opened nodes.
|
||||
//
|
||||
NodeHelper_CloseNode(NodeName_IFS, pTabLevel + 1);
|
||||
NodeHelper_CloseNode(NodeName_Shape, pTabLevel);
|
||||
}
|
||||
|
||||
void X3DExporter::Export_Material(const size_t pIdxMaterial, const size_t pTabLevel) {
|
||||
const char *NodeName_A = "Appearance";
|
||||
|
||||
list<SAttribute> attr_list;
|
||||
aiMaterial &material = *mScene->mMaterials[pIdxMaterial]; // create alias for convenience.
|
||||
|
||||
// Check if material already defined early.
|
||||
if (mDEF_Map_Material.find(pIdxMaterial) != mDEF_Map_Material.end()) {
|
||||
// Material already defined, just refer to it
|
||||
attr_list.push_back({ "USE", mDEF_Map_Material.at(pIdxMaterial) });
|
||||
NodeHelper_OpenNode(NodeName_A, pTabLevel, true, attr_list);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
string material_name(string("_IDX_") + to_string(pIdxMaterial)); // Create material name
|
||||
aiString ai_mat_name;
|
||||
|
||||
if (material.Get(AI_MATKEY_NAME, ai_mat_name) == AI_SUCCESS) material_name.insert(0, ai_mat_name.C_Str());
|
||||
|
||||
// Define material name.
|
||||
attr_list.push_back({ "DEF", material_name });
|
||||
mDEF_Map_Material[pIdxMaterial] = material_name;
|
||||
|
||||
//
|
||||
// "Appearance" node.
|
||||
//
|
||||
NodeHelper_OpenNode(NodeName_A, pTabLevel, false, attr_list);
|
||||
attr_list.clear();
|
||||
|
||||
//
|
||||
// "Material" node.
|
||||
//
|
||||
{
|
||||
auto Color4ToAttrList = [&](const string &pAttrName, const aiColor4D &pAttrValue, const aiColor3D &pAttrDefaultValue) {
|
||||
string tstr;
|
||||
|
||||
if (aiColor3D(pAttrValue.r, pAttrValue.g, pAttrValue.b) != pAttrDefaultValue) {
|
||||
AttrHelper_Col4DArrToString(&pAttrValue, 1, tstr);
|
||||
attr_list.push_back({ pAttrName, tstr });
|
||||
}
|
||||
};
|
||||
|
||||
float tvalf;
|
||||
aiColor3D color3;
|
||||
aiColor4D color4;
|
||||
|
||||
// ambientIntensity="0.2" SFFloat [inputOutput]
|
||||
if (material.Get(AI_MATKEY_COLOR_AMBIENT, color3) == AI_SUCCESS)
|
||||
AttrHelper_FloatToAttrList(attr_list, "ambientIntensity", (color3.r + color3.g + color3.b) / 3.0f, 0.2f);
|
||||
else if (material.Get(AI_MATKEY_COLOR_AMBIENT, color4) == AI_SUCCESS)
|
||||
AttrHelper_FloatToAttrList(attr_list, "ambientIntensity", (color4.r + color4.g + color4.b) / 3.0f, 0.2f);
|
||||
|
||||
// diffuseColor="0.8 0.8 0.8" SFColor [inputOutput]
|
||||
if (material.Get(AI_MATKEY_COLOR_DIFFUSE, color3) == AI_SUCCESS)
|
||||
AttrHelper_Color3ToAttrList(attr_list, "diffuseColor", color3, aiColor3D(0.8f, 0.8f, 0.8f));
|
||||
else if (material.Get(AI_MATKEY_COLOR_DIFFUSE, color4) == AI_SUCCESS)
|
||||
Color4ToAttrList("diffuseColor", color4, aiColor3D(0.8f, 0.8f, 0.8f));
|
||||
|
||||
// emissiveColor="0 0 0" SFColor [inputOutput]
|
||||
if (material.Get(AI_MATKEY_COLOR_EMISSIVE, color3) == AI_SUCCESS)
|
||||
AttrHelper_Color3ToAttrList(attr_list, "emissiveColor", color3, aiColor3D(0, 0, 0));
|
||||
else if (material.Get(AI_MATKEY_COLOR_EMISSIVE, color4) == AI_SUCCESS)
|
||||
Color4ToAttrList("emissiveColor", color4, aiColor3D(0, 0, 0));
|
||||
|
||||
// shininess="0.2" SFFloat [inputOutput]
|
||||
if (material.Get(AI_MATKEY_SHININESS, tvalf) == AI_SUCCESS) AttrHelper_FloatToAttrList(attr_list, "shininess", tvalf, 0.2f);
|
||||
|
||||
// specularColor="0 0 0" SFColor [inputOutput]
|
||||
if (material.Get(AI_MATKEY_COLOR_SPECULAR, color3) == AI_SUCCESS)
|
||||
AttrHelper_Color3ToAttrList(attr_list, "specularColor", color3, aiColor3D(0, 0, 0));
|
||||
else if (material.Get(AI_MATKEY_COLOR_SPECULAR, color4) == AI_SUCCESS)
|
||||
Color4ToAttrList("specularColor", color4, aiColor3D(0, 0, 0));
|
||||
|
||||
// transparency="0" SFFloat [inputOutput]
|
||||
if (material.Get(AI_MATKEY_OPACITY, tvalf) == AI_SUCCESS) {
|
||||
if (tvalf > 1) tvalf = 1;
|
||||
|
||||
tvalf = 1.0f - tvalf;
|
||||
AttrHelper_FloatToAttrList(attr_list, "transparency", tvalf, 0);
|
||||
}
|
||||
|
||||
NodeHelper_OpenNode("Material", pTabLevel + 1, true, attr_list);
|
||||
attr_list.clear();
|
||||
} // "Material" node. END.
|
||||
|
||||
//
|
||||
// "ImageTexture" node.
|
||||
//
|
||||
{
|
||||
auto RepeatToAttrList = [&](const string &pAttrName, const bool pAttrValue) {
|
||||
if (!pAttrValue) attr_list.push_back({ pAttrName, "false" });
|
||||
};
|
||||
|
||||
bool tvalb;
|
||||
aiString tstring;
|
||||
|
||||
// url="" MFString
|
||||
if (material.Get(AI_MATKEY_TEXTURE_DIFFUSE(0), tstring) == AI_SUCCESS) {
|
||||
if (strncmp(tstring.C_Str(), AI_EMBEDDED_TEXNAME_PREFIX, strlen(AI_EMBEDDED_TEXNAME_PREFIX)) == 0)
|
||||
LogError("Embedded texture is not supported");
|
||||
else
|
||||
attr_list.push_back({ "url", string("\"") + tstring.C_Str() + "\"" });
|
||||
}
|
||||
|
||||
// repeatS="true" SFBool
|
||||
if (material.Get(AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0), tvalb) == AI_SUCCESS) RepeatToAttrList("repeatS", tvalb);
|
||||
|
||||
// repeatT="true" SFBool
|
||||
if (material.Get(AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0), tvalb) == AI_SUCCESS) RepeatToAttrList("repeatT", tvalb);
|
||||
|
||||
NodeHelper_OpenNode("ImageTexture", pTabLevel + 1, true, attr_list);
|
||||
attr_list.clear();
|
||||
} // "ImageTexture" node. END.
|
||||
|
||||
//
|
||||
// "TextureTransform" node.
|
||||
//
|
||||
{
|
||||
auto Vec2ToAttrList = [&](const string &pAttrName, const aiVector2D &pAttrValue, const aiVector2D &pAttrDefaultValue) {
|
||||
string tstr;
|
||||
|
||||
if (pAttrValue != pAttrDefaultValue) {
|
||||
AttrHelper_Vec2DArrToString(&pAttrValue, 1, tstr);
|
||||
attr_list.push_back({ pAttrName, tstr });
|
||||
}
|
||||
};
|
||||
|
||||
aiUVTransform transform;
|
||||
|
||||
if (material.Get(AI_MATKEY_UVTRANSFORM_DIFFUSE(0), transform) == AI_SUCCESS) {
|
||||
Vec2ToAttrList("translation", transform.mTranslation, aiVector2D(0, 0));
|
||||
AttrHelper_FloatToAttrList(attr_list, "rotation", transform.mRotation, 0);
|
||||
Vec2ToAttrList("scale", transform.mScaling, aiVector2D(1, 1));
|
||||
|
||||
NodeHelper_OpenNode("TextureTransform", pTabLevel + 1, true, attr_list);
|
||||
attr_list.clear();
|
||||
}
|
||||
} // "TextureTransform" node. END.
|
||||
|
||||
//
|
||||
// Close opened nodes.
|
||||
//
|
||||
NodeHelper_CloseNode(NodeName_A, pTabLevel);
|
||||
}
|
||||
|
||||
void X3DExporter::Export_MetadataBoolean(const aiString &pKey, const bool pValue, const size_t pTabLevel) {
|
||||
list<SAttribute> attr_list;
|
||||
|
||||
attr_list.push_back({ "name", pKey.C_Str() });
|
||||
attr_list.push_back({ "value", pValue ? "true" : "false" });
|
||||
NodeHelper_OpenNode("MetadataBoolean", pTabLevel, true, attr_list);
|
||||
}
|
||||
|
||||
void X3DExporter::Export_MetadataDouble(const aiString &pKey, const double pValue, const size_t pTabLevel) {
|
||||
list<SAttribute> attr_list;
|
||||
|
||||
attr_list.push_back({ "name", pKey.C_Str() });
|
||||
attr_list.push_back({ "value", to_string(pValue) });
|
||||
NodeHelper_OpenNode("MetadataDouble", pTabLevel, true, attr_list);
|
||||
}
|
||||
|
||||
void X3DExporter::Export_MetadataFloat(const aiString &pKey, const float pValue, const size_t pTabLevel) {
|
||||
list<SAttribute> attr_list;
|
||||
|
||||
attr_list.push_back({ "name", pKey.C_Str() });
|
||||
attr_list.push_back({ "value", to_string(pValue) });
|
||||
NodeHelper_OpenNode("MetadataFloat", pTabLevel, true, attr_list);
|
||||
}
|
||||
|
||||
void X3DExporter::Export_MetadataInteger(const aiString &pKey, const int32_t pValue, const size_t pTabLevel) {
|
||||
list<SAttribute> attr_list;
|
||||
|
||||
attr_list.push_back({ "name", pKey.C_Str() });
|
||||
attr_list.push_back({ "value", to_string(pValue) });
|
||||
NodeHelper_OpenNode("MetadataInteger", pTabLevel, true, attr_list);
|
||||
}
|
||||
|
||||
void X3DExporter::Export_MetadataString(const aiString &pKey, const aiString &pValue, const size_t pTabLevel) {
|
||||
list<SAttribute> attr_list;
|
||||
|
||||
attr_list.push_back({ "name", pKey.C_Str() });
|
||||
attr_list.push_back({ "value", pValue.C_Str() });
|
||||
NodeHelper_OpenNode("MetadataString", pTabLevel, true, attr_list);
|
||||
}
|
||||
|
||||
bool X3DExporter::CheckAndExport_Light(const aiNode &pNode, const size_t pTabLevel) {
|
||||
list<SAttribute> attr_list;
|
||||
|
||||
auto Vec3ToAttrList = [&](const string &pAttrName, const aiVector3D &pAttrValue, const aiVector3D &pAttrDefaultValue) {
|
||||
string tstr;
|
||||
|
||||
if (pAttrValue != pAttrDefaultValue) {
|
||||
AttrHelper_Vec3DArrToString(&pAttrValue, 1, tstr);
|
||||
attr_list.push_back({ pAttrName, tstr });
|
||||
}
|
||||
};
|
||||
|
||||
size_t idx_light;
|
||||
bool found = false;
|
||||
|
||||
// Name of the light source can not be empty.
|
||||
if (pNode.mName.length == 0) return false;
|
||||
|
||||
// search for light with name like node has.
|
||||
for (idx_light = 0; mScene->mNumLights; idx_light++) {
|
||||
if (pNode.mName == mScene->mLights[idx_light]->mName) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) return false;
|
||||
|
||||
// Light source is found.
|
||||
const aiLight &light = *mScene->mLights[idx_light]; // Alias for convenience.
|
||||
|
||||
aiMatrix4x4 trafo_mat = Matrix_GlobalToCurrent(pNode).Inverse();
|
||||
|
||||
attr_list.push_back({ "DEF", light.mName.C_Str() });
|
||||
attr_list.push_back({ "global", "true" }); // "false" is not supported.
|
||||
// ambientIntensity="0" SFFloat [inputOutput]
|
||||
AttrHelper_FloatToAttrList(attr_list, "ambientIntensity", aiVector3D(light.mColorAmbient.r, light.mColorAmbient.g, light.mColorAmbient.b).Length(), 0);
|
||||
// color="1 1 1" SFColor [inputOutput]
|
||||
AttrHelper_Color3ToAttrList(attr_list, "color", light.mColorDiffuse, aiColor3D(1, 1, 1));
|
||||
|
||||
switch (light.mType) {
|
||||
case aiLightSource_DIRECTIONAL: {
|
||||
aiVector3D direction = trafo_mat * light.mDirection;
|
||||
|
||||
Vec3ToAttrList("direction", direction, aiVector3D(0, 0, -1));
|
||||
NodeHelper_OpenNode("DirectionalLight", pTabLevel, true, attr_list);
|
||||
}
|
||||
|
||||
break;
|
||||
case aiLightSource_POINT: {
|
||||
aiVector3D attenuation(light.mAttenuationConstant, light.mAttenuationLinear, light.mAttenuationQuadratic);
|
||||
aiVector3D location = trafo_mat * light.mPosition;
|
||||
|
||||
Vec3ToAttrList("attenuation", attenuation, aiVector3D(1, 0, 0));
|
||||
Vec3ToAttrList("location", location, aiVector3D(0, 0, 0));
|
||||
NodeHelper_OpenNode("PointLight", pTabLevel, true, attr_list);
|
||||
}
|
||||
|
||||
break;
|
||||
case aiLightSource_SPOT: {
|
||||
aiVector3D attenuation(light.mAttenuationConstant, light.mAttenuationLinear, light.mAttenuationQuadratic);
|
||||
aiVector3D location = trafo_mat * light.mPosition;
|
||||
aiVector3D direction = trafo_mat * light.mDirection;
|
||||
|
||||
Vec3ToAttrList("attenuation", attenuation, aiVector3D(1, 0, 0));
|
||||
Vec3ToAttrList("location", location, aiVector3D(0, 0, 0));
|
||||
Vec3ToAttrList("direction", direction, aiVector3D(0, 0, -1));
|
||||
AttrHelper_FloatToAttrList(attr_list, "beamWidth", light.mAngleInnerCone, 0.7854f);
|
||||
AttrHelper_FloatToAttrList(attr_list, "cutOffAngle", light.mAngleOuterCone, 1.570796f);
|
||||
NodeHelper_OpenNode("SpotLight", pTabLevel, true, attr_list);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
throw DeadlyExportError("Unknown light type: " + to_string(light.mType));
|
||||
} // switch(light.mType)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
X3DExporter::X3DExporter(const char *pFileName, IOSystem *pIOSystem, const aiScene *pScene, const ExportProperties * /*pProperties*/) :
|
||||
mScene(pScene) {
|
||||
list<SAttribute> attr_list;
|
||||
|
||||
mOutFile = pIOSystem->Open(pFileName, "wt");
|
||||
if (mOutFile == nullptr) throw DeadlyExportError("Could not open output .x3d file: " + string(pFileName));
|
||||
|
||||
// Begin document
|
||||
XML_Write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
||||
XML_Write("<!DOCTYPE X3D PUBLIC \"ISO//Web3D//DTD X3D 3.3//EN\" \"http://www.web3d.org/specifications/x3d-3.3.dtd\">\n");
|
||||
// Root node
|
||||
attr_list.push_back({ "profile", "Interchange" });
|
||||
attr_list.push_back({ "version", "3.3" });
|
||||
attr_list.push_back({ "xmlns:xsd", "http://www.w3.org/2001/XMLSchema-instance" });
|
||||
attr_list.push_back({ "xsd:noNamespaceSchemaLocation", "http://www.web3d.org/specifications/x3d-3.3.xsd" });
|
||||
NodeHelper_OpenNode("X3D", 0, false, attr_list);
|
||||
attr_list.clear();
|
||||
// <head>: meta data.
|
||||
NodeHelper_OpenNode("head", 1);
|
||||
XML_Write(mIndentationString + "<!-- All \"meta\" from this section tou will found in <Scene> node as MetadataString nodes. -->\n");
|
||||
NodeHelper_CloseNode("head", 1);
|
||||
// Scene node.
|
||||
NodeHelper_OpenNode("Scene", 1);
|
||||
Export_Node(mScene->mRootNode, 2);
|
||||
NodeHelper_CloseNode("Scene", 1);
|
||||
// Close Root node.
|
||||
NodeHelper_CloseNode("X3D", 0);
|
||||
// Cleanup
|
||||
pIOSystem->Close(mOutFile);
|
||||
mOutFile = nullptr;
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_X3D_EXPORTER
|
||||
#endif // ASSIMP_BUILD_NO_EXPORT
|
||||
250
Engine/lib/assimp/code/AssetLib/X3D/X3DExporter.hpp
Normal file
250
Engine/lib/assimp/code/AssetLib/X3D/X3DExporter.hpp
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
/// \file X3DExporter.hpp
|
||||
/// \brief X3D-format files exporter for Assimp.
|
||||
/// \date 2016
|
||||
/// \author smal.root@gmail.com
|
||||
// Thanks to acorn89 for support.
|
||||
|
||||
#ifndef INCLUDED_AI_X3D_EXPORTER_H
|
||||
#define INCLUDED_AI_X3D_EXPORTER_H
|
||||
|
||||
// Header files, Assimp.
|
||||
#include <assimp/material.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/Exporter.hpp>
|
||||
|
||||
// Header files, stdlib.
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
/// \class X3DExporter
|
||||
/// Class which export aiScene to X3D file.
|
||||
///
|
||||
/// Limitations.
|
||||
///
|
||||
/// Pay attention that X3D is format for interactive graphic and simulations for web browsers. aiScene can not contain all features of the X3D format.
|
||||
/// Also, aiScene contain rasterized-like data. For example, X3D can describe circle all cylinder with one tag, but aiScene contain result of tessellation:
|
||||
/// vertices, faces etc. Yes, you can use algorithm for detecting figures or shapes, but that's not a good idea at all.
|
||||
///
|
||||
/// Supported nodes:
|
||||
/// Core component:
|
||||
/// "MetadataBoolean", "MetadataDouble", "MetadataFloat", "MetadataInteger", "MetadataSet", "MetadataString"
|
||||
/// Geometry3D component:
|
||||
/// "IndexedFaceSet"
|
||||
/// Grouping component:
|
||||
/// "Group", "Transform"
|
||||
/// Lighting component:
|
||||
/// "DirectionalLight", "PointLight", "SpotLight"
|
||||
/// Rendering component:
|
||||
/// "ColorRGBA", "Coordinate", "Normal"
|
||||
/// Shape component:
|
||||
/// "Shape", "Appearance", "Material"
|
||||
/// Texturing component:
|
||||
/// "ImageTexture", "TextureCoordinate", "TextureTransform"
|
||||
///
|
||||
class X3DExporter {
|
||||
/***********************************************/
|
||||
/******************** Types ********************/
|
||||
/***********************************************/
|
||||
|
||||
struct SAttribute {
|
||||
const std::string Name;
|
||||
const std::string Value;
|
||||
SAttribute() :
|
||||
Name(),
|
||||
Value() {
|
||||
// empty
|
||||
}
|
||||
SAttribute(const std::string &name, const std::string &value) :
|
||||
Name(name),
|
||||
Value(value) {
|
||||
// empty
|
||||
}
|
||||
|
||||
SAttribute(SAttribute &&rhs) AI_NO_EXCEPT :
|
||||
Name(rhs.Name),
|
||||
Value(rhs.Value) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
/***********************************************/
|
||||
/****************** Constants ******************/
|
||||
/***********************************************/
|
||||
|
||||
const aiScene *const mScene;
|
||||
|
||||
/***********************************************/
|
||||
/****************** Variables ******************/
|
||||
/***********************************************/
|
||||
|
||||
IOStream *mOutFile;
|
||||
std::map<size_t, std::string> mDEF_Map_Mesh;
|
||||
std::map<size_t, std::string> mDEF_Map_Material;
|
||||
|
||||
private:
|
||||
std::string mIndentationString;
|
||||
|
||||
/***********************************************/
|
||||
/****************** Functions ******************/
|
||||
/***********************************************/
|
||||
|
||||
/// \fn void IndentationStringSet(const size_t pNewLevel)
|
||||
/// Set value of the indentation string.
|
||||
/// \param [in] pNewLevel - new level of the indentation.
|
||||
void IndentationStringSet(const size_t pNewLevel);
|
||||
|
||||
/// \fn void XML_Write(const std::string& pData)
|
||||
/// Write data to XML-file.
|
||||
/// \param [in] pData - reference to string which must be written.
|
||||
void XML_Write(const std::string &pData);
|
||||
|
||||
/// \fn aiMatrix4x4 Matrix_GlobalToCurrent(const aiNode& pNode) const
|
||||
/// Calculate transformation matrix for transformation from global coordinate system to pointed aiNode.
|
||||
/// \param [in] pNode - reference to local node.
|
||||
/// \return calculated matrix.
|
||||
aiMatrix4x4 Matrix_GlobalToCurrent(const aiNode &pNode) const;
|
||||
|
||||
/// \fn void AttrHelper_CommaToPoint(std::string& pStringWithComma)
|
||||
/// Convert commas in string to points. That's needed because "std::to_string" result depends on locale (regional settings).
|
||||
/// \param [in, out] pStringWithComma - reference to string, which must be modified.
|
||||
void AttrHelper_CommaToPoint(std::string &pStringWithComma) {
|
||||
for (char &c : pStringWithComma) {
|
||||
if (c == ',') c = '.';
|
||||
}
|
||||
}
|
||||
|
||||
/// \fn void AttrHelper_FloatToString(const float pValue, std::string& pTargetString)
|
||||
/// Converts float to string.
|
||||
/// \param [in] pValue - value for converting.
|
||||
/// \param [out] pTargetString - reference to string where result will be placed. Will be cleared before using.
|
||||
void AttrHelper_FloatToString(const float pValue, std::string &pTargetString);
|
||||
|
||||
/// \fn void AttrHelper_Vec3DArrToString(const aiVector3D* pArray, const size_t pArray_Size, std::string& pTargetString)
|
||||
/// Converts array of vectors to string.
|
||||
/// \param [in] pArray - pointer to array of vectors.
|
||||
/// \param [in] pArray_Size - count of elements in array.
|
||||
/// \param [out] pTargetString - reference to string where result will be placed. Will be cleared before using.
|
||||
void AttrHelper_Vec3DArrToString(const aiVector3D *pArray, const size_t pArray_Size, std::string &pTargetString);
|
||||
|
||||
/// \fn void AttrHelper_Vec2DArrToString(const aiVector2D* pArray, const size_t pArray_Size, std::string& pTargetString)
|
||||
/// \overload void AttrHelper_Vec3DArrToString(const aiVector3D* pArray, const size_t pArray_Size, std::string& pTargetString)
|
||||
void AttrHelper_Vec2DArrToString(const aiVector2D *pArray, const size_t pArray_Size, std::string &pTargetString);
|
||||
|
||||
/// \fn void AttrHelper_Vec3DAsVec2fArrToString(const aiVector3D* pArray, const size_t pArray_Size, std::string& pTargetString)
|
||||
/// \overload void AttrHelper_Vec3DArrToString(const aiVector3D* pArray, const size_t pArray_Size, std::string& pTargetString)
|
||||
/// Only x, y is used from aiVector3D.
|
||||
void AttrHelper_Vec3DAsVec2fArrToString(const aiVector3D *pArray, const size_t pArray_Size, std::string &pTargetString);
|
||||
|
||||
/// \fn void AttrHelper_Col4DArrToString(const aiColor4D* pArray, const size_t pArray_Size, std::string& pTargetString)
|
||||
/// \overload void AttrHelper_Vec3DArrToString(const aiVector3D* pArray, const size_t pArray_Size, std::string& pTargetString)
|
||||
/// Converts array of colors to string.
|
||||
void AttrHelper_Col4DArrToString(const aiColor4D *pArray, const size_t pArray_Size, std::string &pTargetString);
|
||||
|
||||
/// \fn void AttrHelper_Col3DArrToString(const aiColor3D* pArray, const size_t pArray_Size, std::string& pTargetString)
|
||||
/// \overload void AttrHelper_Col4DArrToString(const aiColor4D* pArray, const size_t pArray_Size, std::string& pTargetString)
|
||||
/// Converts array of colors to string.
|
||||
void AttrHelper_Col3DArrToString(const aiColor3D *pArray, const size_t pArray_Size, std::string &pTargetString);
|
||||
|
||||
/// \fn void AttrHelper_FloatToAttrList(std::list<SAttribute> pList, const std::string& pName, const float pValue, const float pDefaultValue)
|
||||
/// \overload void AttrHelper_Col3DArrToString(const aiColor3D* pArray, const size_t pArray_Size, std::string& pTargetString)
|
||||
void AttrHelper_FloatToAttrList(std::list<SAttribute> &pList, const std::string &pName, const float pValue, const float pDefaultValue);
|
||||
|
||||
/// \fn void AttrHelper_Color3ToAttrList(std::list<SAttribute> pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue)
|
||||
/// Add attribute to list if value not equal to default.
|
||||
/// \param [in] pList - target list of the attributes.
|
||||
/// \param [in] pName - name of new attribute.
|
||||
/// \param [in] pValue - value of the new attribute.
|
||||
/// \param [in] pDefaultValue - default value for checking: if pValue is equal to pDefaultValue then attribute will not be added.
|
||||
void AttrHelper_Color3ToAttrList(std::list<SAttribute> &pList, const std::string &pName, const aiColor3D &pValue, const aiColor3D &pDefaultValue);
|
||||
|
||||
/// \fn void NodeHelper_OpenNode(const std::string& pNodeName, const size_t pTabLevel, const bool pEmptyElement, const std::list<SAttribute>& pAttrList)
|
||||
/// Begin new XML-node element.
|
||||
/// \param [in] pNodeName - name of the element.
|
||||
/// \param [in] pTabLevel - indentation level.
|
||||
/// \param [in] pEmtyElement - if true then empty element will be created.
|
||||
/// \param [in] pAttrList - list of the attributes for element.
|
||||
void NodeHelper_OpenNode(const std::string &pNodeName, const size_t pTabLevel, const bool pEmptyElement, const std::list<SAttribute> &pAttrList);
|
||||
|
||||
/// \fn void NodeHelper_OpenNode(const std::string& pNodeName, const size_t pTabLevel, const bool pEmptyElement = false)
|
||||
/// \overload void NodeHelper_OpenNode(const std::string& pNodeName, const size_t pTabLevel, const bool pEmptyElement, const std::list<SAttribute>& pAttrList)
|
||||
void NodeHelper_OpenNode(const std::string &pNodeName, const size_t pTabLevel, const bool pEmptyElement = false);
|
||||
|
||||
/// \fn void NodeHelper_CloseNode(const std::string& pNodeName, const size_t pTabLevel)
|
||||
/// End XML-node element.
|
||||
/// \param [in] pNodeName - name of the element.
|
||||
/// \param [in] pTabLevel - indentation level.
|
||||
void NodeHelper_CloseNode(const std::string &pNodeName, const size_t pTabLevel);
|
||||
|
||||
/// \fn void Export_Node(const aiNode* pNode, const size_t pTabLevel)
|
||||
/// Export data from scene to XML-file: aiNode.
|
||||
/// \param [in] pNode - source aiNode.
|
||||
/// \param [in] pTabLevel - indentation level.
|
||||
void Export_Node(const aiNode *pNode, const size_t pTabLevel);
|
||||
|
||||
/// \fn void Export_Mesh(const size_t pIdxMesh, const size_t pTabLevel)
|
||||
/// Export data from scene to XML-file: aiMesh.
|
||||
/// \param [in] pMesh - index of the source aiMesh.
|
||||
/// \param [in] pTabLevel - indentation level.
|
||||
void Export_Mesh(const size_t pIdxMesh, const size_t pTabLevel);
|
||||
|
||||
/// \fn void Export_Material(const size_t pIdxMaterial, const size_t pTabLevel)
|
||||
/// Export data from scene to XML-file: aiMaterial.
|
||||
/// \param [in] pIdxMaterial - index of the source aiMaterial.
|
||||
/// \param [in] pTabLevel - indentation level.
|
||||
void Export_Material(const size_t pIdxMaterial, const size_t pTabLevel);
|
||||
|
||||
/// \fn void Export_MetadataBoolean(const aiString& pKey, const bool pValue, const size_t pTabLevel)
|
||||
/// Export data from scene to XML-file: aiMetadata.
|
||||
/// \param [in] pKey - source data: value of the metadata key.
|
||||
/// \param [in] pValue - source data: value of the metadata value.
|
||||
/// \param [in] pTabLevel - indentation level.
|
||||
void Export_MetadataBoolean(const aiString &pKey, const bool pValue, const size_t pTabLevel);
|
||||
|
||||
/// \fn void Export_MetadataDouble(const aiString& pKey, const double pValue, const size_t pTabLevel)
|
||||
/// \overload void Export_MetadataBoolean(const aiString& pKey, const bool pValue, const size_t pTabLevel)
|
||||
void Export_MetadataDouble(const aiString &pKey, const double pValue, const size_t pTabLevel);
|
||||
|
||||
/// \fn void Export_MetadataFloat(const aiString& pKey, const float pValue, const size_t pTabLevel)
|
||||
/// \overload void Export_MetadataBoolean(const aiString& pKey, const bool pValue, const size_t pTabLevel)
|
||||
void Export_MetadataFloat(const aiString &pKey, const float pValue, const size_t pTabLevel);
|
||||
|
||||
/// \fn void Export_MetadataInteger(const aiString& pKey, const int32_t pValue, const size_t pTabLevel)
|
||||
/// \overload void Export_MetadataBoolean(const aiString& pKey, const bool pValue, const size_t pTabLevel)
|
||||
void Export_MetadataInteger(const aiString &pKey, const int32_t pValue, const size_t pTabLevel);
|
||||
|
||||
/// \fn void Export_MetadataString(const aiString& pKey, const aiString& pValue, const size_t pTabLevel)
|
||||
/// \overload void Export_MetadataBoolean(const aiString& pKey, const bool pValue, const size_t pTabLevel)
|
||||
void Export_MetadataString(const aiString &pKey, const aiString &pValue, const size_t pTabLevel);
|
||||
|
||||
/// \fn bool CheckAndExport_Light(const aiNode& pNode, const size_t pTabLevel)
|
||||
/// Check if node point to light source. If yes then export light source.
|
||||
/// \param [in] pNode - reference to node for checking.
|
||||
/// \param [in] pTabLevel - indentation level.
|
||||
/// \return true - if node assigned with light and it was exported, else - return false.
|
||||
bool CheckAndExport_Light(const aiNode &pNode, const size_t pTabLevel);
|
||||
|
||||
/***********************************************/
|
||||
/************** Functions: LOG set *************/
|
||||
/***********************************************/
|
||||
|
||||
/// \fn void LogError(const std::string& pMessage)
|
||||
/// Short variant for calling \ref DefaultLogger::get()->error()
|
||||
void LogError(const std::string &pMessage) { DefaultLogger::get()->error(pMessage); }
|
||||
|
||||
public:
|
||||
/// \fn X3DExporter()
|
||||
/// Default constructor.
|
||||
X3DExporter(const char *pFileName, IOSystem *pIOSystem, const aiScene *pScene, const ExportProperties *pProperties);
|
||||
|
||||
/// \fn ~X3DExporter()
|
||||
/// Default destructor.
|
||||
~X3DExporter() {}
|
||||
|
||||
}; // class X3DExporter
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // INCLUDED_AI_X3D_EXPORTER_H
|
||||
531
Engine/lib/assimp/code/AssetLib/X3D/X3DGeoHelper.cpp
Normal file
531
Engine/lib/assimp/code/AssetLib/X3D/X3DGeoHelper.cpp
Normal file
|
|
@ -0,0 +1,531 @@
|
|||
#include "X3DGeoHelper.h"
|
||||
#include "X3DImporter.hpp"
|
||||
|
||||
#include <assimp/vector3.h>
|
||||
#include <assimp/Exceptional.h>
|
||||
#include <assimp/StringUtils.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_parallel_epiped(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(" + ai_to_string(pColors.size()) + ") can not be less than Vertices count(" +
|
||||
ai_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(" + ai_to_string(pColors.size()) + ") can not be less than Faces count(" +
|
||||
ai_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(" + ai_to_string(colorIdx.size()) +
|
||||
") can not be less than Coords indices count(" + ai_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(" + ai_to_string(colors.size()) + ") can not be less than Vertices count(" +
|
||||
ai_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(" + ai_to_string(colorIdx.size()) +
|
||||
") can not be less than Faces count(" + ai_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(" + ai_to_string(colors.size()) + ") can not be less than Faces count(" +
|
||||
ai_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(" + ai_to_string(tind[i]) +
|
||||
") is out of range. Normals count: " + ai_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: " + ai_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
|
||||
39
Engine/lib/assimp/code/AssetLib/X3D/X3DGeoHelper.h
Normal file
39
Engine/lib/assimp/code/AssetLib/X3D/X3DGeoHelper.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#pragma once
|
||||
|
||||
#include <assimp/vector2.h>
|
||||
#include <assimp/vector3.h>
|
||||
#include <assimp/color4.h>
|
||||
#include <assimp/types.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_parallel_epiped(const aiVector3D &pSize, std::list<aiVector3D> &pVertices);
|
||||
static void coordIdx_str2faces_arr(const std::vector<int32_t> &pCoordIdx, std::vector<aiFace> &pFaces, unsigned int &pPrimitiveTypes);
|
||||
static void 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
|
||||
488
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter.cpp
Normal file
488
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter.cpp
Normal file
|
|
@ -0,0 +1,488 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
/// \file X3DImporter.cpp
|
||||
/// \brief X3D-format files importer for Assimp: main algorithm implementation.
|
||||
/// \date 2015-2016
|
||||
/// \author smal.root@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include "X3DImporter_Macro.hpp"
|
||||
|
||||
#include <assimp/DefaultIOSystem.h>
|
||||
|
||||
// Header files, stdlib.
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
/// Constant which holds the importer description
|
||||
const aiImporterDesc X3DImporter::Description = {
|
||||
"Extensible 3D(X3D) Importer",
|
||||
"smalcom",
|
||||
"",
|
||||
"See documentation in source code. Chapter: Limitations.",
|
||||
aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"x3d x3db"
|
||||
};
|
||||
|
||||
bool X3DImporter::isNodeEmpty(XmlNode &node) {
|
||||
return node.first_child().empty();
|
||||
}
|
||||
|
||||
void X3DImporter::checkNodeMustBeEmpty(XmlNode &node) {
|
||||
if (!isNodeEmpty(node)) throw DeadlyImportError(std::string("Node <") + node.name() + "> must be empty.");
|
||||
}
|
||||
|
||||
void X3DImporter::skipUnsupportedNode(const std::string &pParentNodeName, XmlNode &node) {
|
||||
static const size_t Uns_Skip_Len = 192;
|
||||
static const char *Uns_Skip[Uns_Skip_Len] = {
|
||||
// CAD geometry component
|
||||
"CADAssembly", "CADFace", "CADLayer", "CADPart", "IndexedQuadSet", "QuadSet",
|
||||
// Core
|
||||
"ROUTE", "ExternProtoDeclare", "ProtoDeclare", "ProtoInstance", "ProtoInterface", "WorldInfo",
|
||||
// Distributed interactive simulation (DIS) component
|
||||
"DISEntityManager", "DISEntityTypeMapping", "EspduTransform", "ReceiverPdu", "SignalPdu", "TransmitterPdu",
|
||||
// Cube map environmental texturing component
|
||||
"ComposedCubeMapTexture", "GeneratedCubeMapTexture", "ImageCubeMapTexture",
|
||||
// Environmental effects component
|
||||
"Background", "Fog", "FogCoordinate", "LocalFog", "TextureBackground",
|
||||
// Environmental sensor component
|
||||
"ProximitySensor", "TransformSensor", "VisibilitySensor",
|
||||
// Followers component
|
||||
"ColorChaser", "ColorDamper", "CoordinateChaser", "CoordinateDamper", "OrientationChaser", "OrientationDamper", "PositionChaser", "PositionChaser2D",
|
||||
"PositionDamper", "PositionDamper2D", "ScalarChaser", "ScalarDamper", "TexCoordChaser2D", "TexCoordDamper2D",
|
||||
// Geospatial component
|
||||
"GeoCoordinate", "GeoElevationGrid", "GeoLocation", "GeoLOD", "GeoMetadata", "GeoOrigin", "GeoPositionInterpolator", "GeoProximitySensor",
|
||||
"GeoTouchSensor", "GeoTransform", "GeoViewpoint",
|
||||
// Humanoid Animation (H-Anim) component
|
||||
"HAnimDisplacer", "HAnimHumanoid", "HAnimJoint", "HAnimSegment", "HAnimSite",
|
||||
// Interpolation component
|
||||
"ColorInterpolator", "CoordinateInterpolator", "CoordinateInterpolator2D", "EaseInEaseOut", "NormalInterpolator", "OrientationInterpolator",
|
||||
"PositionInterpolator", "PositionInterpolator2D", "ScalarInterpolator", "SplinePositionInterpolator", "SplinePositionInterpolator2D",
|
||||
"SplineScalarInterpolator", "SquadOrientationInterpolator",
|
||||
// Key device sensor component
|
||||
"KeySensor", "StringSensor",
|
||||
// Layering component
|
||||
"Layer", "LayerSet", "Viewport",
|
||||
// Layout component
|
||||
"Layout", "LayoutGroup", "LayoutLayer", "ScreenFontStyle", "ScreenGroup",
|
||||
// Navigation component
|
||||
"Billboard", "Collision", "LOD", "NavigationInfo", "OrthoViewpoint", "Viewpoint", "ViewpointGroup",
|
||||
// Networking component
|
||||
"EXPORT", "IMPORT", "Anchor", "LoadSensor",
|
||||
// NURBS component
|
||||
"Contour2D", "ContourPolyline2D", "CoordinateDouble", "NurbsCurve", "NurbsCurve2D", "NurbsOrientationInterpolator", "NurbsPatchSurface",
|
||||
"NurbsPositionInterpolator", "NurbsSet", "NurbsSurfaceInterpolator", "NurbsSweptSurface", "NurbsSwungSurface", "NurbsTextureCoordinate",
|
||||
"NurbsTrimmedSurface",
|
||||
// Particle systems component
|
||||
"BoundedPhysicsModel", "ConeEmitter", "ExplosionEmitter", "ForcePhysicsModel", "ParticleSystem", "PointEmitter", "PolylineEmitter", "SurfaceEmitter",
|
||||
"VolumeEmitter", "WindPhysicsModel",
|
||||
// Picking component
|
||||
"LinePickSensor", "PickableGroup", "PointPickSensor", "PrimitivePickSensor", "VolumePickSensor",
|
||||
// Pointing device sensor component
|
||||
"CylinderSensor", "PlaneSensor", "SphereSensor", "TouchSensor",
|
||||
// Rendering component
|
||||
"ClipPlane",
|
||||
// Rigid body physics
|
||||
"BallJoint", "CollidableOffset", "CollidableShape", "CollisionCollection", "CollisionSensor", "CollisionSpace", "Contact", "DoubleAxisHingeJoint",
|
||||
"MotorJoint", "RigidBody", "RigidBodyCollection", "SingleAxisHingeJoint", "SliderJoint", "UniversalJoint",
|
||||
// Scripting component
|
||||
"Script",
|
||||
// Programmable shaders component
|
||||
"ComposedShader", "FloatVertexAttribute", "Matrix3VertexAttribute", "Matrix4VertexAttribute", "PackagedShader", "ProgramShader", "ShaderPart",
|
||||
"ShaderProgram",
|
||||
// Shape component
|
||||
"FillProperties", "LineProperties", "TwoSidedMaterial",
|
||||
// Sound component
|
||||
"AudioClip", "Sound",
|
||||
// Text component
|
||||
"FontStyle", "Text",
|
||||
// Texturing3D Component
|
||||
"ComposedTexture3D", "ImageTexture3D", "PixelTexture3D", "TextureCoordinate3D", "TextureCoordinate4D", "TextureTransformMatrix3D", "TextureTransform3D",
|
||||
// Texturing component
|
||||
"MovieTexture", "MultiTexture", "MultiTextureCoordinate", "MultiTextureTransform", "PixelTexture", "TextureCoordinateGenerator", "TextureProperties",
|
||||
// Time component
|
||||
"TimeSensor",
|
||||
// Event Utilities component
|
||||
"BooleanFilter", "BooleanSequencer", "BooleanToggle", "BooleanTrigger", "IntegerSequencer", "IntegerTrigger", "TimeTrigger",
|
||||
// Volume rendering component
|
||||
"BlendedVolumeStyle", "BoundaryEnhancementVolumeStyle", "CartoonVolumeStyle", "ComposedVolumeStyle", "EdgeEnhancementVolumeStyle", "IsoSurfaceVolumeData",
|
||||
"OpacityMapVolumeStyle", "ProjectionVolumeStyle", "SegmentedVolumeData", "ShadedVolumeStyle", "SilhouetteEnhancementVolumeStyle", "ToneMappedVolumeStyle",
|
||||
"VolumeData"
|
||||
};
|
||||
|
||||
const std::string nn = node.name();
|
||||
|
||||
if (nn.empty()) {
|
||||
const std::string nv = node.value();
|
||||
if (!nv.empty()) {
|
||||
LogInfo("Ignoring comment \"" + nv + "\" in " + pParentNodeName + ".");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
|
||||
for (size_t i = 0; i < Uns_Skip_Len; i++) {
|
||||
if (nn == Uns_Skip[i]) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) throw DeadlyImportError("Unknown node \"" + nn + "\" in " + pParentNodeName + ".");
|
||||
|
||||
LogInfo("Skipping node \"" + nn + "\" in " + pParentNodeName + ".");
|
||||
}
|
||||
|
||||
X3DImporter::X3DImporter() :
|
||||
mNodeElementCur(nullptr),
|
||||
mScene(nullptr),
|
||||
mpIOHandler(nullptr) {
|
||||
// empty
|
||||
}
|
||||
|
||||
X3DImporter::~X3DImporter() {
|
||||
// Clear() is accounting if data already is deleted. So, just check again if all data is deleted.
|
||||
Clear();
|
||||
}
|
||||
|
||||
void X3DImporter::Clear() {
|
||||
mNodeElementCur = nullptr;
|
||||
// Delete all elements
|
||||
if (!NodeElement_List.empty()) {
|
||||
for (std::list<X3DNodeElementBase *>::iterator it = NodeElement_List.begin(); it != NodeElement_List.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
NodeElement_List.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void X3DImporter::ParseFile(const std::string &file, IOSystem *pIOHandler) {
|
||||
ai_assert(nullptr != pIOHandler);
|
||||
|
||||
static const std::string mode = "rb";
|
||||
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") {
|
||||
readHead(currentNode);
|
||||
} else if (currentName == "Scene") {
|
||||
readScene(currentNode);
|
||||
} else {
|
||||
skipUnsupportedNode("X3D", currentNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool X3DImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool checkSig) const {
|
||||
if (checkSig) {
|
||||
if (GetExtension(pFile) == "x3d")
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void X3DImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
|
||||
mpIOHandler = pIOHandler;
|
||||
|
||||
Clear();
|
||||
std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb"));
|
||||
if (!stream) {
|
||||
throw DeadlyImportError("Could not open file for reading");
|
||||
}
|
||||
std::string::size_type slashPos = pFile.find_last_of("\\/");
|
||||
|
||||
mScene = pScene;
|
||||
pScene->mRootNode = new aiNode(pFile);
|
||||
pScene->mRootNode->mParent = nullptr;
|
||||
pScene->mFlags |= AI_SCENE_FLAGS_ALLOW_SHARED;
|
||||
|
||||
pIOHandler->PushDirectory(slashPos == std::string::npos ? std::string() : pFile.substr(0, slashPos + 1));
|
||||
ParseFile(pFile, pIOHandler);
|
||||
pIOHandler->PopDirectory();
|
||||
|
||||
//search for root node element
|
||||
|
||||
mNodeElementCur = NodeElement_List.front();
|
||||
if (mNodeElementCur == nullptr) {
|
||||
return;
|
||||
}
|
||||
while (mNodeElementCur->Parent != nullptr) {
|
||||
mNodeElementCur = mNodeElementCur->Parent;
|
||||
}
|
||||
|
||||
{ // fill aiScene with objects.
|
||||
std::list<aiMesh *> mesh_list;
|
||||
std::list<aiMaterial *> mat_list;
|
||||
std::list<aiLight *> light_list;
|
||||
|
||||
// create nodes tree
|
||||
Postprocess_BuildNode(*mNodeElementCur, *pScene->mRootNode, mesh_list, mat_list, light_list);
|
||||
// copy needed data to scene
|
||||
if (!mesh_list.empty()) {
|
||||
std::list<aiMesh *>::const_iterator it = mesh_list.begin();
|
||||
|
||||
pScene->mNumMeshes = static_cast<unsigned int>(mesh_list.size());
|
||||
pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
|
||||
for (size_t i = 0; i < pScene->mNumMeshes; i++)
|
||||
pScene->mMeshes[i] = *it++;
|
||||
}
|
||||
|
||||
if (!mat_list.empty()) {
|
||||
std::list<aiMaterial *>::const_iterator it = mat_list.begin();
|
||||
|
||||
pScene->mNumMaterials = static_cast<unsigned int>(mat_list.size());
|
||||
pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials];
|
||||
for (size_t i = 0; i < pScene->mNumMaterials; i++)
|
||||
pScene->mMaterials[i] = *it++;
|
||||
}
|
||||
|
||||
if (!light_list.empty()) {
|
||||
std::list<aiLight *>::const_iterator it = light_list.begin();
|
||||
|
||||
pScene->mNumLights = static_cast<unsigned int>(light_list.size());
|
||||
pScene->mLights = new aiLight *[pScene->mNumLights];
|
||||
for (size_t i = 0; i < pScene->mNumLights; i++)
|
||||
pScene->mLights[i] = *it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const aiImporterDesc *X3DImporter::GetInfo() const {
|
||||
return &Description;
|
||||
}
|
||||
|
||||
struct meta_entry {
|
||||
std::string name;
|
||||
std::string value;
|
||||
};
|
||||
|
||||
void X3DImporter::readHead(XmlNode &node) {
|
||||
std::vector<meta_entry> metaArray;
|
||||
for (auto currentNode : node.children()) {
|
||||
const std::string ¤tName = currentNode.name();
|
||||
if (currentName == "meta") {
|
||||
//checkNodeMustBeEmpty(node);
|
||||
meta_entry entry;
|
||||
if (XmlParser::getStdStrAttribute(currentNode, "name", entry.name)) {
|
||||
XmlParser::getStdStrAttribute(currentNode, "content", entry.value);
|
||||
metaArray.emplace_back(entry);
|
||||
}
|
||||
}
|
||||
// TODO: check if other node types in head should be supported
|
||||
}
|
||||
mScene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(metaArray.size()));
|
||||
unsigned int i = 0;
|
||||
for (auto currentMeta : metaArray) {
|
||||
mScene->mMetaData->Set(i, currentMeta.name, aiString(currentMeta.value));
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void X3DImporter::readChildNodes(XmlNode &node, const std::string &pParentNodeName) {
|
||||
if (node.empty()) {
|
||||
return;
|
||||
}
|
||||
for (auto currentNode : node.children()) {
|
||||
const std::string ¤tName = currentNode.name();
|
||||
if (currentName == "Shape")
|
||||
readShape(currentNode);
|
||||
else if (currentName == "Group") {
|
||||
startReadGroup(currentNode);
|
||||
readChildNodes(currentNode, "Group");
|
||||
endReadGroup();
|
||||
} else if (currentName == "StaticGroup") {
|
||||
startReadStaticGroup(currentNode);
|
||||
readChildNodes(currentNode, "StaticGroup");
|
||||
endReadStaticGroup();
|
||||
} else if (currentName == "Transform") {
|
||||
startReadTransform(currentNode);
|
||||
readChildNodes(currentNode, "Transform");
|
||||
endReadTransform();
|
||||
} else if (currentName == "Switch") {
|
||||
startReadSwitch(currentNode);
|
||||
readChildNodes(currentNode, "Switch");
|
||||
endReadSwitch();
|
||||
} else if (currentName == "DirectionalLight") {
|
||||
readDirectionalLight(currentNode);
|
||||
} else if (currentName == "PointLight") {
|
||||
readPointLight(currentNode);
|
||||
} else if (currentName == "SpotLight") {
|
||||
readSpotLight(currentNode);
|
||||
} else if (currentName == "Inline") {
|
||||
readInline(currentNode);
|
||||
} else if (!checkForMetadataNode(currentNode)) {
|
||||
skipUnsupportedNode(pParentNodeName, currentNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void X3DImporter::readScene(XmlNode &node) {
|
||||
ParseHelper_Group_Begin(true);
|
||||
readChildNodes(node, "Scene");
|
||||
ParseHelper_Node_Exit();
|
||||
}
|
||||
|
||||
/*********************************************************************************************************************************************/
|
||||
/************************************************************ Functions: find set ************************************************************/
|
||||
/*********************************************************************************************************************************************/
|
||||
|
||||
bool X3DImporter::FindNodeElement_FromRoot(const std::string &pID, const X3DElemType pType, X3DNodeElementBase **pElement) {
|
||||
for (std::list<X3DNodeElementBase *>::iterator it = NodeElement_List.begin(); it != NodeElement_List.end(); ++it) {
|
||||
if (((*it)->Type == pType) && ((*it)->ID == pID)) {
|
||||
if (pElement != nullptr) *pElement = *it;
|
||||
|
||||
return true;
|
||||
}
|
||||
} // for(std::list<CX3DImporter_NodeElement*>::iterator it = NodeElement_List.begin(); it != NodeElement_List.end(); it++)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool X3DImporter::FindNodeElement_FromNode(X3DNodeElementBase *pStartNode, const std::string &pID,
|
||||
const X3DElemType pType, X3DNodeElementBase **pElement) {
|
||||
bool found = false; // flag: true - if requested element is found.
|
||||
|
||||
// Check if pStartNode - this is the element, we are looking for.
|
||||
if ((pStartNode->Type == pType) && (pStartNode->ID == pID)) {
|
||||
found = true;
|
||||
if (pElement != nullptr) {
|
||||
*pElement = pStartNode;
|
||||
}
|
||||
|
||||
goto fne_fn_end;
|
||||
} // if((pStartNode->Type() == pType) && (pStartNode->ID() == pID))
|
||||
|
||||
// Check childs of pStartNode.
|
||||
for (std::list<X3DNodeElementBase *>::iterator ch_it = pStartNode->Children.begin(); ch_it != pStartNode->Children.end(); ++ch_it) {
|
||||
found = FindNodeElement_FromNode(*ch_it, pID, pType, pElement);
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
} // for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = it->Children.begin(); ch_it != it->Children.end(); ch_it++)
|
||||
|
||||
fne_fn_end:
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
bool X3DImporter::FindNodeElement(const std::string &pID, const X3DElemType pType, X3DNodeElementBase **pElement) {
|
||||
X3DNodeElementBase *tnd = mNodeElementCur; // temporary pointer to node.
|
||||
bool static_search = false; // flag: true if searching in static node.
|
||||
|
||||
// At first check if we have deal with static node. Go up through parent nodes and check flag.
|
||||
while (tnd != nullptr) {
|
||||
if (tnd->Type == X3DElemType::ENET_Group) {
|
||||
if (((X3DNodeElementGroup *)tnd)->Static) {
|
||||
static_search = true; // Flag found, stop walking up. Node with static flag will holded in tnd variable.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tnd = tnd->Parent; // go up in graph.
|
||||
} // while (tnd != nullptr)
|
||||
|
||||
// at now call appropriate search function.
|
||||
if (static_search) {
|
||||
return FindNodeElement_FromNode(tnd, pID, pType, pElement);
|
||||
} else {
|
||||
return FindNodeElement_FromRoot(pID, pType, pElement);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************************************************************/
|
||||
/************************************************************ Functions: parse set ***********************************************************/
|
||||
/*********************************************************************************************************************************************/
|
||||
|
||||
void X3DImporter::ParseHelper_Group_Begin(const bool pStatic) {
|
||||
X3DNodeElementGroup *new_group = new X3DNodeElementGroup(mNodeElementCur, pStatic); // create new node with current node as parent.
|
||||
|
||||
// if we are adding not the root element then add new element to current element child list.
|
||||
if (mNodeElementCur != nullptr) {
|
||||
mNodeElementCur->Children.push_back(new_group);
|
||||
}
|
||||
|
||||
NodeElement_List.push_back(new_group); // it's a new element - add it to list.
|
||||
mNodeElementCur = new_group; // switch current element to new one.
|
||||
}
|
||||
|
||||
void X3DImporter::ParseHelper_Node_Enter(X3DNodeElementBase *pNode) {
|
||||
ai_assert(nullptr != pNode);
|
||||
|
||||
mNodeElementCur->Children.push_back(pNode); // add new element to current element child list.
|
||||
mNodeElementCur = pNode; // switch current element to new one.
|
||||
}
|
||||
|
||||
void X3DImporter::ParseHelper_Node_Exit() {
|
||||
// check if we can walk up.
|
||||
if (mNodeElementCur != nullptr) {
|
||||
mNodeElementCur = mNodeElementCur->Parent;
|
||||
} else {
|
||||
int i = 0;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
383
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter.hpp
Normal file
383
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter.hpp
Normal file
|
|
@ -0,0 +1,383 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2022, assimp team
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef INCLUDED_AI_X3D_IMPORTER_H
|
||||
#define INCLUDED_AI_X3D_IMPORTER_H
|
||||
|
||||
#include "X3DImporter_Node.hpp"
|
||||
|
||||
#include <assimp/BaseImporter.h>
|
||||
#include <assimp/XmlParser.h>
|
||||
#include <assimp/importerdesc.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/types.h>
|
||||
#include <assimp/DefaultLogger.hpp>
|
||||
#include <assimp/ProgressHandler.hpp>
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
inline void Throw_ArgOutOfRange(const std::string &argument) {
|
||||
throw DeadlyImportError("Argument value is out of range for: \"" + argument + "\".");
|
||||
}
|
||||
|
||||
inline void Throw_CloseNotFound(const std::string &node) {
|
||||
throw DeadlyImportError("Close tag for node <" + node + "> not found. Seems file is corrupt.");
|
||||
}
|
||||
|
||||
inline void Throw_ConvertFail_Str2ArrF(const std::string &nodeName, const std::string &pAttrValue) {
|
||||
throw DeadlyImportError("In <" + nodeName + "> failed to convert attribute value \"" + pAttrValue +
|
||||
"\" from string to array of floats.");
|
||||
}
|
||||
|
||||
inline void Throw_ConvertFail_Str2ArrD(const std::string &nodeName, const std::string &pAttrValue) {
|
||||
throw DeadlyImportError("In <" + nodeName + "> failed to convert attribute value \"" + pAttrValue +
|
||||
"\" from string to array of doubles.");
|
||||
}
|
||||
|
||||
inline void Throw_ConvertFail_Str2ArrB(const std::string &nodeName, const std::string &pAttrValue) {
|
||||
throw DeadlyImportError("In <" + nodeName + "> failed to convert attribute value \"" + pAttrValue +
|
||||
"\" from string to array of booleans.");
|
||||
}
|
||||
|
||||
inline void Throw_ConvertFail_Str2ArrI(const std::string &nodeName, const std::string &pAttrValue) {
|
||||
throw DeadlyImportError("In <" + nodeName + "> failed to convert attribute value \"" + pAttrValue +
|
||||
"\" from string to array of integers.");
|
||||
}
|
||||
|
||||
inline void Throw_DEF_And_USE(const std::string &nodeName) {
|
||||
throw DeadlyImportError("\"DEF\" and \"USE\" can not be defined both in <" + nodeName + ">.");
|
||||
}
|
||||
|
||||
inline void Throw_IncorrectAttr(const std::string &nodeName, const std::string &pAttrName) {
|
||||
throw DeadlyImportError("Node <" + nodeName + "> has incorrect attribute \"" + pAttrName + "\".");
|
||||
}
|
||||
|
||||
inline void Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &pAttrName) {
|
||||
throw DeadlyImportError("Attribute \"" + pAttrName + "\" in node <" + nodeName + "> has incorrect value.");
|
||||
}
|
||||
|
||||
inline void Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription) {
|
||||
throw DeadlyImportError("\"" + pNodeType + "\" node can be used only once in " + nodeName + ". Description: " + pDescription);
|
||||
}
|
||||
|
||||
inline void Throw_TagCountIncorrect(const std::string &pNode) {
|
||||
throw DeadlyImportError("Count of open and close tags for node <" + pNode + "> are not equivalent. Seems file is corrupt.");
|
||||
}
|
||||
|
||||
inline void Throw_USE_NotFound(const std::string &nodeName, const std::string &pAttrValue) {
|
||||
throw DeadlyImportError("Not found node with name \"" + pAttrValue + "\" in <" + nodeName + ">.");
|
||||
}
|
||||
|
||||
inline void LogInfo(const std::string &message) {
|
||||
DefaultLogger::get()->info(message);
|
||||
}
|
||||
|
||||
/// \class X3DImporter
|
||||
/// Class that holding scene graph which include: groups, geometry, metadata etc.
|
||||
///
|
||||
/// Limitations.
|
||||
///
|
||||
/// Pay attention that X3D is format for interactive graphic and simulations for web browsers.
|
||||
/// So not all features can be imported using Assimp.
|
||||
///
|
||||
/// Unsupported nodes:
|
||||
/// CAD geometry component:
|
||||
/// "CADAssembly", "CADFace", "CADLayer", "CADPart", "IndexedQuadSet", "QuadSet"
|
||||
/// Core component:
|
||||
/// "ROUTE", "ExternProtoDeclare", "ProtoDeclare", "ProtoInstance", "ProtoInterface", "WorldInfo"
|
||||
/// Distributed interactive simulation (DIS) component:
|
||||
/// "DISEntityManager", "DISEntityTypeMapping", "EspduTransform", "ReceiverPdu", "SignalPdu", "TransmitterPdu"
|
||||
/// Cube map environmental texturing component:
|
||||
/// "ComposedCubeMapTexture", "GeneratedCubeMapTexture", "ImageCubeMapTexture"
|
||||
/// Environmental effects component:
|
||||
/// "Background", "Fog", "FogCoordinate", "LocalFog", "TextureBackground"
|
||||
/// Environmental sensor component:
|
||||
/// "ProximitySensor", "TransformSensor", "VisibilitySensor"
|
||||
/// Followers component:
|
||||
/// "ColorChaser", "ColorDamper", "CoordinateChaser", "CoordinateDamper", "OrientationChaser", "OrientationDamper", "PositionChaser",
|
||||
/// "PositionChaser2D", "PositionDamper", "PositionDamper2D", "ScalarChaser", "ScalarDamper", "TexCoordChaser2D", "TexCoordDamper2D"
|
||||
/// Geospatial component:
|
||||
/// "GeoCoordinate", "GeoElevationGrid", "GeoLocation", "GeoLOD", "GeoMetadata", "GeoOrigin", "GeoPositionInterpolator", "GeoProximitySensor",
|
||||
/// "GeoTouchSensor", "GeoTransform", "GeoViewpoint"
|
||||
/// Humanoid Animation (H-Anim) component:
|
||||
/// "HAnimDisplacer", "HAnimHumanoid", "HAnimJoint", "HAnimSegment", "HAnimSite"
|
||||
/// Interpolation component:
|
||||
/// "ColorInterpolator", "CoordinateInterpolator", "CoordinateInterpolator2D", "EaseInEaseOut", "NormalInterpolator", "OrientationInterpolator",
|
||||
/// "PositionInterpolator", "PositionInterpolator2D", "ScalarInterpolator", "SplinePositionInterpolator", "SplinePositionInterpolator2D",
|
||||
/// "SplineScalarInterpolator", "SquadOrientationInterpolator",
|
||||
/// Key device sensor component:
|
||||
/// "KeySensor", "StringSensor"
|
||||
/// Layering component:
|
||||
/// "Layer", "LayerSet", "Viewport"
|
||||
/// Layout component:
|
||||
/// "Layout", "LayoutGroup", "LayoutLayer", "ScreenFontStyle", "ScreenGroup"
|
||||
/// Navigation component:
|
||||
/// "Billboard", "Collision", "LOD", "NavigationInfo", "OrthoViewpoint", "Viewpoint", "ViewpointGroup"
|
||||
/// Networking component:
|
||||
/// "EXPORT", "IMPORT", "Anchor", "LoadSensor"
|
||||
/// NURBS component:
|
||||
/// "Contour2D", "ContourPolyline2D", "CoordinateDouble", "NurbsCurve", "NurbsCurve2D", "NurbsOrientationInterpolator", "NurbsPatchSurface",
|
||||
/// "NurbsPositionInterpolator", "NurbsSet", "NurbsSurfaceInterpolator", "NurbsSweptSurface", "NurbsSwungSurface", "NurbsTextureCoordinate",
|
||||
/// "NurbsTrimmedSurface"
|
||||
/// Particle systems component:
|
||||
/// "BoundedPhysicsModel", "ConeEmitter", "ExplosionEmitter", "ForcePhysicsModel", "ParticleSystem", "PointEmitter", "PolylineEmitter",
|
||||
/// "SurfaceEmitter", "VolumeEmitter", "WindPhysicsModel"
|
||||
/// Picking component:
|
||||
/// "LinePickSensor", "PickableGroup", "PointPickSensor", "PrimitivePickSensor", "VolumePickSensor"
|
||||
/// Pointing device sensor component:
|
||||
/// "CylinderSensor", "PlaneSensor", "SphereSensor", "TouchSensor"
|
||||
/// Rendering component:
|
||||
/// "ClipPlane"
|
||||
/// Rigid body physics:
|
||||
/// "BallJoint", "CollidableOffset", "CollidableShape", "CollisionCollection", "CollisionSensor", "CollisionSpace", "Contact", "DoubleAxisHingeJoint",
|
||||
/// "MotorJoint", "RigidBody", "RigidBodyCollection", "SingleAxisHingeJoint", "SliderJoint", "UniversalJoint"
|
||||
/// Scripting component:
|
||||
/// "Script"
|
||||
/// Programmable shaders component:
|
||||
/// "ComposedShader", "FloatVertexAttribute", "Matrix3VertexAttribute", "Matrix4VertexAttribute", "PackagedShader", "ProgramShader", "ShaderPart",
|
||||
/// "ShaderProgram",
|
||||
/// Shape component:
|
||||
/// "FillProperties", "LineProperties", "TwoSidedMaterial"
|
||||
/// Sound component:
|
||||
/// "AudioClip", "Sound"
|
||||
/// Text component:
|
||||
/// "FontStyle", "Text"
|
||||
/// Texturing3D Component:
|
||||
/// "ComposedTexture3D", "ImageTexture3D", "PixelTexture3D", "TextureCoordinate3D", "TextureCoordinate4D", "TextureTransformMatrix3D",
|
||||
/// "TextureTransform3D"
|
||||
/// Texturing component:
|
||||
/// "MovieTexture", "MultiTexture", "MultiTextureCoordinate", "MultiTextureTransform", "PixelTexture", "TextureCoordinateGenerator",
|
||||
/// "TextureProperties",
|
||||
/// Time component:
|
||||
/// "TimeSensor"
|
||||
/// Event Utilities component:
|
||||
/// "BooleanFilter", "BooleanSequencer", "BooleanToggle", "BooleanTrigger", "IntegerSequencer", "IntegerTrigger", "TimeTrigger",
|
||||
/// Volume rendering component:
|
||||
/// "BlendedVolumeStyle", "BoundaryEnhancementVolumeStyle", "CartoonVolumeStyle", "ComposedVolumeStyle", "EdgeEnhancementVolumeStyle",
|
||||
/// "IsoSurfaceVolumeData", "OpacityMapVolumeStyle", "ProjectionVolumeStyle", "SegmentedVolumeData", "ShadedVolumeStyle",
|
||||
/// "SilhouetteEnhancementVolumeStyle", "ToneMappedVolumeStyle", "VolumeData"
|
||||
///
|
||||
/// Supported nodes:
|
||||
/// Core component:
|
||||
/// "MetadataBoolean", "MetadataDouble", "MetadataFloat", "MetadataInteger", "MetadataSet", "MetadataString"
|
||||
/// Geometry2D component:
|
||||
/// "Arc2D", "ArcClose2D", "Circle2D", "Disk2D", "Polyline2D", "Polypoint2D", "Rectangle2D", "TriangleSet2D"
|
||||
/// Geometry3D component:
|
||||
/// "Box", "Cone", "Cylinder", "ElevationGrid", "Extrusion", "IndexedFaceSet", "Sphere"
|
||||
/// Grouping component:
|
||||
/// "Group", "StaticGroup", "Switch", "Transform"
|
||||
/// Lighting component:
|
||||
/// "DirectionalLight", "PointLight", "SpotLight"
|
||||
/// Networking component:
|
||||
/// "Inline"
|
||||
/// Rendering component:
|
||||
/// "Color", "ColorRGBA", "Coordinate", "IndexedLineSet", "IndexedTriangleFanSet", "IndexedTriangleSet", "IndexedTriangleStripSet", "LineSet",
|
||||
/// "PointSet", "TriangleFanSet", "TriangleSet", "TriangleStripSet", "Normal"
|
||||
/// Shape component:
|
||||
/// "Shape", "Appearance", "Material"
|
||||
/// Texturing component:
|
||||
/// "ImageTexture", "TextureCoordinate", "TextureTransform"
|
||||
///
|
||||
/// Limitations of attribute "USE".
|
||||
/// If "USE" is set then node must be empty, like that:
|
||||
/// <Node USE='name'/>
|
||||
/// not the
|
||||
/// <Node USE='name'><!-- something --> </Node>
|
||||
///
|
||||
/// Ignored attributes: "creaseAngle", "convex", "solid".
|
||||
///
|
||||
/// Texture coordinates generating: only for Sphere, Cone, Cylinder. In all other case used PLANE mapping.
|
||||
/// It's better that Assimp main code has powerful texture coordinates generator. Then is not needed to
|
||||
/// duplicate this code in every importer.
|
||||
///
|
||||
/// Lighting limitations.
|
||||
/// If light source placed in some group with "DEF" set. And after that some node is use it group with "USE" attribute then
|
||||
/// you will get error about duplicate light sources. That's happening because Assimp require names for lights but do not like
|
||||
/// duplicates of it )).
|
||||
///
|
||||
/// Color for faces.
|
||||
/// That's happening when attribute "colorPerVertex" is set to "false". But Assimp do not hold how many colors has mesh and require
|
||||
/// equal length for mVertices and mColors. You will see the colors but vertices will use call which last used in "colorIdx".
|
||||
///
|
||||
/// That's all for now. Enjoy
|
||||
///
|
||||
|
||||
using X3DElementList = std::list<X3DNodeElementBase *>;
|
||||
|
||||
class X3DImporter : public BaseImporter {
|
||||
public:
|
||||
std::list<X3DNodeElementBase *> NodeElement_List; ///< All elements of scene graph.
|
||||
|
||||
public:
|
||||
/// Default constructor.
|
||||
X3DImporter();
|
||||
|
||||
/// Default destructor.
|
||||
~X3DImporter();
|
||||
|
||||
/***********************************************/
|
||||
/******** Functions: parse set, public *********/
|
||||
/***********************************************/
|
||||
|
||||
/// Parse X3D file and fill scene graph. The function has no return value. Result can be found by analyzing the generated graph.
|
||||
/// Also exception can be thrown if trouble will found.
|
||||
/// \param [in] pFile - name of file to be parsed.
|
||||
/// \param [in] pIOHandler - pointer to IO helper object.
|
||||
void ParseFile(const std::string &pFile, IOSystem *pIOHandler);
|
||||
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const;
|
||||
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
|
||||
const aiImporterDesc *GetInfo() const;
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
X3DNodeElementBase *MACRO_USE_CHECKANDAPPLY(XmlNode &node, std::string pDEF, std::string pUSE, X3DElemType pType, X3DNodeElementBase *pNE);
|
||||
bool isNodeEmpty(XmlNode &node);
|
||||
void checkNodeMustBeEmpty(XmlNode &node);
|
||||
void skipUnsupportedNode(const std::string &pParentNodeName, XmlNode &node);
|
||||
void readHead(XmlNode &node);
|
||||
void readChildNodes(XmlNode &node, const std::string &pParentNodeName);
|
||||
void readScene(XmlNode &node);
|
||||
|
||||
bool FindNodeElement_FromRoot(const std::string &pID, const X3DElemType pType, X3DNodeElementBase **pElement);
|
||||
bool FindNodeElement_FromNode(X3DNodeElementBase *pStartNode, const std::string &pID,
|
||||
const X3DElemType pType, X3DNodeElementBase **pElement);
|
||||
bool FindNodeElement(const std::string &pID, const X3DElemType pType, X3DNodeElementBase **pElement);
|
||||
void ParseHelper_Group_Begin(const bool pStatic = false);
|
||||
void ParseHelper_Node_Enter(X3DNodeElementBase *pNode);
|
||||
void ParseHelper_Node_Exit();
|
||||
|
||||
// 2D geometry
|
||||
void readArc2D(XmlNode &node);
|
||||
void readArcClose2D(XmlNode &node);
|
||||
void readCircle2D(XmlNode &node);
|
||||
void readDisk2D(XmlNode &node);
|
||||
void readPolyline2D(XmlNode &node);
|
||||
void readPolypoint2D(XmlNode &node);
|
||||
void readRectangle2D(XmlNode &node);
|
||||
void readTriangleSet2D(XmlNode &node);
|
||||
|
||||
// 3D geometry
|
||||
void readBox(XmlNode &node);
|
||||
void readCone(XmlNode &node);
|
||||
void readCylinder(XmlNode &node);
|
||||
void readElevationGrid(XmlNode &node);
|
||||
void readExtrusion(XmlNode &node);
|
||||
void readIndexedFaceSet(XmlNode &node);
|
||||
void readSphere(XmlNode &node);
|
||||
|
||||
// group
|
||||
void startReadGroup(XmlNode &node);
|
||||
void endReadGroup();
|
||||
void startReadStaticGroup(XmlNode &node);
|
||||
void endReadStaticGroup();
|
||||
void startReadSwitch(XmlNode &node);
|
||||
void endReadSwitch();
|
||||
void startReadTransform(XmlNode &node);
|
||||
void endReadTransform();
|
||||
|
||||
// light
|
||||
void readDirectionalLight(XmlNode &node);
|
||||
void readPointLight(XmlNode &node);
|
||||
void readSpotLight(XmlNode &node);
|
||||
|
||||
// metadata
|
||||
bool checkForMetadataNode(XmlNode &node);
|
||||
void childrenReadMetadata(XmlNode &node, X3DNodeElementBase *pParentElement, const std::string &pNodeName);
|
||||
void readMetadataBoolean(XmlNode &node);
|
||||
void readMetadataDouble(XmlNode &node);
|
||||
void readMetadataFloat(XmlNode &node);
|
||||
void readMetadataInteger(XmlNode &node);
|
||||
void readMetadataSet(XmlNode &node);
|
||||
void readMetadataString(XmlNode &node);
|
||||
|
||||
// networking
|
||||
void readInline(XmlNode &node);
|
||||
|
||||
// postprocessing
|
||||
aiMatrix4x4 PostprocessHelper_Matrix_GlobalToCurrent() const;
|
||||
void PostprocessHelper_CollectMetadata(const X3DNodeElementBase &pNodeElement, std::list<X3DNodeElementBase *> &pList) const;
|
||||
bool PostprocessHelper_ElementIsMetadata(const X3DElemType pType) const;
|
||||
bool PostprocessHelper_ElementIsMesh(const X3DElemType pType) const;
|
||||
void Postprocess_BuildLight(const X3DNodeElementBase &pNodeElement, std::list<aiLight *> &pSceneLightList) const;
|
||||
void Postprocess_BuildMaterial(const X3DNodeElementBase &pNodeElement, aiMaterial **pMaterial) const;
|
||||
void Postprocess_BuildMesh(const X3DNodeElementBase &pNodeElement, aiMesh **pMesh) const;
|
||||
void Postprocess_BuildNode(const X3DNodeElementBase &pNodeElement, aiNode &pSceneNode, std::list<aiMesh *> &pSceneMeshList,
|
||||
std::list<aiMaterial *> &pSceneMaterialList, std::list<aiLight *> &pSceneLightList) const;
|
||||
void Postprocess_BuildShape(const X3DNodeElementShape &pShapeNodeElement, std::list<unsigned int> &pNodeMeshInd,
|
||||
std::list<aiMesh *> &pSceneMeshList, std::list<aiMaterial *> &pSceneMaterialList) const;
|
||||
void Postprocess_CollectMetadata(const X3DNodeElementBase &pNodeElement, aiNode &pSceneNode) const;
|
||||
|
||||
// rendering
|
||||
void readColor(XmlNode &node);
|
||||
void readColorRGBA(XmlNode &node);
|
||||
void readCoordinate(XmlNode &node);
|
||||
void readIndexedLineSet(XmlNode &node);
|
||||
void readIndexedTriangleFanSet(XmlNode &node);
|
||||
void readIndexedTriangleSet(XmlNode &node);
|
||||
void readIndexedTriangleStripSet(XmlNode &node);
|
||||
void readLineSet(XmlNode &node);
|
||||
void readPointSet(XmlNode &node);
|
||||
void readTriangleFanSet(XmlNode &node);
|
||||
void readTriangleSet(XmlNode &node);
|
||||
void readTriangleStripSet(XmlNode &node);
|
||||
void readNormal(XmlNode &node);
|
||||
|
||||
// shape
|
||||
void readShape(XmlNode &node);
|
||||
void readAppearance(XmlNode &node);
|
||||
void readMaterial(XmlNode &node);
|
||||
|
||||
// texturing
|
||||
void readImageTexture(XmlNode &node);
|
||||
void readTextureCoordinate(XmlNode &node);
|
||||
void readTextureTransform(XmlNode &node);
|
||||
|
||||
static const aiImporterDesc Description;
|
||||
X3DNodeElementBase *mNodeElementCur;
|
||||
aiScene *mScene;
|
||||
IOSystem *mpIOHandler;
|
||||
}; // class X3DImporter
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // INCLUDED_AI_X3D_IMPORTER_H
|
||||
467
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Geometry2D.cpp
Normal file
467
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Geometry2D.cpp
Normal file
|
|
@ -0,0 +1,467 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
/// \file X3DImporter_Geometry2D.cpp
|
||||
/// \brief Parsing data from nodes of "Geometry2D" set of X3D.
|
||||
/// date 2015-2016
|
||||
/// author smal.root@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include "X3DImporter_Macro.hpp"
|
||||
#include "X3DXmlHelper.h"
|
||||
#include "X3DGeoHelper.h"
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
// <Arc2D
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// endAngle="1.570796" SFFloat [initializeOnly]
|
||||
// radius="1" SFFloat [initializeOnly]
|
||||
// startAngle="0" SFFloat [initializeOnly]
|
||||
// />
|
||||
// The Arc2D node specifies a linear circular arc whose center is at (0,0) and whose angles are measured starting at the positive x-axis and sweeping
|
||||
// towards the positive y-axis. The radius field specifies the radius of the circle of which the arc is a portion. The arc extends from the startAngle
|
||||
// counterclockwise to the endAngle. The values of startAngle and endAngle shall be in the range [-2pi, 2pi] radians (or the equivalent if a different
|
||||
// angle base unit has been specified). If startAngle and endAngle have the same value, a circle is specified.
|
||||
void X3DImporter::readArc2D(XmlNode &node) {
|
||||
std::string def, use;
|
||||
float endAngle = AI_MATH_HALF_PI_F;
|
||||
float radius = 1;
|
||||
float startAngle = 0;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getFloatAttribute(node, "endAngle", endAngle);
|
||||
XmlParser::getFloatAttribute(node, "radius", radius);
|
||||
XmlParser::getFloatAttribute(node, "startAngle", startAngle);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Arc2D, ne);
|
||||
} else {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_Arc2D, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
// create point list of geometry object and convert it to line set.
|
||||
std::list<aiVector3D> tlist;
|
||||
|
||||
X3DGeoHelper::make_arc2D(startAngle, endAngle, radius, 10, tlist); ///TODO: IME - AI_CONFIG for NumSeg
|
||||
X3DGeoHelper::extend_point_to_line(tlist, ((X3DNodeElementGeometry2D *)ne)->Vertices);
|
||||
((X3DNodeElementGeometry2D *)ne)->NumIndices = 2;
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "Arc2D");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <ArcClose2D
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// closureType="PIE" SFString [initializeOnly], {"PIE", "CHORD"}
|
||||
// endAngle="1.570796" SFFloat [initializeOnly]
|
||||
// radius="1" SFFloat [initializeOnly]
|
||||
// solid="false" SFBool [initializeOnly]
|
||||
// startAngle="0" SFFloat [initializeOnly]
|
||||
// />
|
||||
// The ArcClose node specifies a portion of a circle whose center is at (0,0) and whose angles are measured starting at the positive x-axis and sweeping
|
||||
// towards the positive y-axis. The end points of the arc specified are connected as defined by the closureType field. The radius field specifies the radius
|
||||
// of the circle of which the arc is a portion. The arc extends from the startAngle counterclockwise to the endAngle. The value of radius shall be greater
|
||||
// than zero. The values of startAngle and endAngle shall be in the range [-2pi, 2pi] radians (or the equivalent if a different default angle base unit has
|
||||
// been specified). If startAngle and endAngle have the same value, a circle is specified and closureType is ignored. If the absolute difference between
|
||||
// startAngle and endAngle is greater than or equal to 2pi, a complete circle is produced with no chord or radial line(s) drawn from the center.
|
||||
// A closureType of "PIE" connects the end point to the start point by defining two straight line segments first from the end point to the center and then
|
||||
// the center to the start point. A closureType of "CHORD" connects the end point to the start point by defining a straight line segment from the end point
|
||||
// to the start point. Textures are applied individually to each face of the ArcClose2D. On the front (+Z) and back (-Z) faces of the ArcClose2D, when
|
||||
// viewed from the +Z-axis, the texture is mapped onto each face with the same orientation as if the image were displayed normally in 2D.
|
||||
void X3DImporter::readArcClose2D(XmlNode &node) {
|
||||
std::string def, use;
|
||||
std::string closureType("PIE");
|
||||
float endAngle = AI_MATH_HALF_PI_F;
|
||||
float radius = 1;
|
||||
bool solid = false;
|
||||
float startAngle = 0;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getStdStrAttribute(node, "closureType", closureType);
|
||||
XmlParser::getFloatAttribute(node, "endAngle", endAngle);
|
||||
XmlParser::getFloatAttribute(node, "endAngle", endAngle);
|
||||
XmlParser::getFloatAttribute(node, "radius", radius);
|
||||
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||
XmlParser::getFloatAttribute(node, "startAngle", startAngle);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ArcClose2D, ne);
|
||||
} else {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_ArcClose2D, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
((X3DNodeElementGeometry2D *)ne)->Solid = solid;
|
||||
// create point list of geometry object.
|
||||
X3DGeoHelper::make_arc2D(startAngle, endAngle, radius, 10, ((X3DNodeElementGeometry2D *)ne)->Vertices); ///TODO: IME - AI_CONFIG for NumSeg
|
||||
// add chord or two radiuses only if not a circle was defined
|
||||
if (!((std::fabs(endAngle - startAngle) >= AI_MATH_TWO_PI_F) || (endAngle == startAngle))) {
|
||||
std::list<aiVector3D> &vlist = ((X3DNodeElementGeometry2D *)ne)->Vertices; // just short alias.
|
||||
|
||||
if ((closureType == "PIE") || (closureType == "\"PIE\""))
|
||||
vlist.push_back(aiVector3D(0, 0, 0)); // center point - first radial line
|
||||
else if ((closureType != "CHORD") && (closureType != "\"CHORD\""))
|
||||
Throw_IncorrectAttrValue("ArcClose2D", "closureType");
|
||||
|
||||
vlist.push_back(*vlist.begin()); // arc first point - chord from first to last point of arc(if CHORD) or second radial line(if PIE).
|
||||
}
|
||||
|
||||
((X3DNodeElementGeometry2D *)ne)->NumIndices = ((X3DNodeElementGeometry2D *)ne)->Vertices.size();
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "ArcClose2D");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <Circle2D
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// radius="1" SFFloat [initializeOnly]
|
||||
// />
|
||||
void X3DImporter::readCircle2D(XmlNode &node) {
|
||||
std::string def, use;
|
||||
float radius = 1;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getFloatAttribute(node, "radius", radius);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Circle2D, ne);
|
||||
} else {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_Circle2D, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
// create point list of geometry object and convert it to line set.
|
||||
std::list<aiVector3D> tlist;
|
||||
|
||||
X3DGeoHelper::make_arc2D(0, 0, radius, 10, tlist); ///TODO: IME - AI_CONFIG for NumSeg
|
||||
X3DGeoHelper::extend_point_to_line(tlist, ((X3DNodeElementGeometry2D *)ne)->Vertices);
|
||||
((X3DNodeElementGeometry2D *)ne)->NumIndices = 2;
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "Circle2D");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <Disk2D
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// innerRadius="0" SFFloat [initializeOnly]
|
||||
// outerRadius="1" SFFloat [initializeOnly]
|
||||
// solid="false" SFBool [initializeOnly]
|
||||
// />
|
||||
// The Disk2D node specifies a circular disk which is centred at (0, 0) in the local coordinate system. The outerRadius field specifies the radius of the
|
||||
// outer dimension of the Disk2D. The innerRadius field specifies the inner dimension of the Disk2D. The value of outerRadius shall be greater than zero.
|
||||
// The value of innerRadius shall be greater than or equal to zero and less than or equal to outerRadius. If innerRadius is zero, the Disk2D is completely
|
||||
// filled. Otherwise, the area within the innerRadius forms a hole in the Disk2D. If innerRadius is equal to outerRadius, a solid circular line shall
|
||||
// be drawn using the current line properties. Textures are applied individually to each face of the Disk2D. On the front (+Z) and back (-Z) faces of
|
||||
// the Disk2D, when viewed from the +Z-axis, the texture is mapped onto each face with the same orientation as if the image were displayed normally in 2D.
|
||||
void X3DImporter::readDisk2D(XmlNode &node) {
|
||||
std::string def, use;
|
||||
float innerRadius = 0;
|
||||
float outerRadius = 1;
|
||||
bool solid = false;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getFloatAttribute(node, "innerRadius", innerRadius);
|
||||
XmlParser::getFloatAttribute(node, "outerRadius", outerRadius);
|
||||
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Disk2D, ne);
|
||||
} else {
|
||||
std::list<aiVector3D> tlist_o, tlist_i;
|
||||
|
||||
if (innerRadius > outerRadius) Throw_IncorrectAttrValue("Disk2D", "innerRadius");
|
||||
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_Disk2D, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
// create point list of geometry object.
|
||||
///TODO: IME - AI_CONFIG for NumSeg
|
||||
X3DGeoHelper::make_arc2D(0, 0, outerRadius, 10, tlist_o); // outer circle
|
||||
if (innerRadius == 0.0f) { // make filled disk
|
||||
// in tlist_o we already have points of circle. just copy it and sign as polygon.
|
||||
((X3DNodeElementGeometry2D *)ne)->Vertices = tlist_o;
|
||||
((X3DNodeElementGeometry2D *)ne)->NumIndices = tlist_o.size();
|
||||
} else if (innerRadius == outerRadius) { // make circle
|
||||
// in tlist_o we already have points of circle. convert it to line set.
|
||||
X3DGeoHelper::extend_point_to_line(tlist_o, ((X3DNodeElementGeometry2D *)ne)->Vertices);
|
||||
((X3DNodeElementGeometry2D *)ne)->NumIndices = 2;
|
||||
} else { // make disk
|
||||
std::list<aiVector3D> &vlist = ((X3DNodeElementGeometry2D *)ne)->Vertices; // just short alias.
|
||||
|
||||
X3DGeoHelper::make_arc2D(0, 0, innerRadius, 10, tlist_i); // inner circle
|
||||
//
|
||||
// create quad list from two point lists
|
||||
//
|
||||
if (tlist_i.size() < 2) throw DeadlyImportError("Disk2D. Not enough points for creating quad list."); // tlist_i and tlist_o has equal size.
|
||||
|
||||
// add all quads except last
|
||||
for (std::list<aiVector3D>::iterator it_i = tlist_i.begin(), it_o = tlist_o.begin(); it_i != tlist_i.end();) {
|
||||
// do not forget - CCW direction
|
||||
vlist.push_back(*it_i++); // 1st point
|
||||
vlist.push_back(*it_o++); // 2nd point
|
||||
vlist.push_back(*it_o); // 3rd point
|
||||
vlist.push_back(*it_i); // 4th point
|
||||
}
|
||||
|
||||
// add last quad
|
||||
vlist.push_back(*tlist_i.end()); // 1st point
|
||||
vlist.push_back(*tlist_o.end()); // 2nd point
|
||||
vlist.push_back(*tlist_o.begin()); // 3rd point
|
||||
vlist.push_back(*tlist_o.begin()); // 4th point
|
||||
|
||||
((X3DNodeElementGeometry2D *)ne)->NumIndices = 4;
|
||||
}
|
||||
|
||||
((X3DNodeElementGeometry2D *)ne)->Solid = solid;
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "Disk2D");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <Polyline2D
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// lineSegments="" MFVec2F [intializeOnly]
|
||||
// />
|
||||
void X3DImporter::readPolyline2D(XmlNode &node) {
|
||||
std::string def, use;
|
||||
std::list<aiVector2D> lineSegments;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
X3DXmlHelper::getVector2DListAttribute(node, "lineSegments", lineSegments);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Polyline2D, ne);
|
||||
} else {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_Polyline2D, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
//
|
||||
// convert read point list of geometry object to line set.
|
||||
//
|
||||
std::list<aiVector3D> tlist;
|
||||
|
||||
// convert vec2 to vec3
|
||||
for (std::list<aiVector2D>::iterator it2 = lineSegments.begin(); it2 != lineSegments.end(); ++it2)
|
||||
tlist.push_back(aiVector3D(it2->x, it2->y, 0));
|
||||
|
||||
// convert point set to line set
|
||||
X3DGeoHelper::extend_point_to_line(tlist, ((X3DNodeElementGeometry2D *)ne)->Vertices);
|
||||
((X3DNodeElementGeometry2D *)ne)->NumIndices = 2;
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "Polyline2D");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <Polypoint2D
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// point="" MFVec2F [inputOutput]
|
||||
// />
|
||||
void X3DImporter::readPolypoint2D(XmlNode &node) {
|
||||
std::string def, use;
|
||||
std::list<aiVector2D> point;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
X3DXmlHelper::getVector2DListAttribute(node, "point", point);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Polypoint2D, ne);
|
||||
} else {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_Polypoint2D, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
// convert vec2 to vec3
|
||||
for (std::list<aiVector2D>::iterator it2 = point.begin(); it2 != point.end(); ++it2) {
|
||||
((X3DNodeElementGeometry2D *)ne)->Vertices.push_back(aiVector3D(it2->x, it2->y, 0));
|
||||
}
|
||||
|
||||
((X3DNodeElementGeometry2D *)ne)->NumIndices = 1;
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "Polypoint2D");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <Rectangle2D
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// size="2 2" SFVec2f [initializeOnly]
|
||||
// solid="false" SFBool [initializeOnly]
|
||||
// />
|
||||
void X3DImporter::readRectangle2D(XmlNode &node) {
|
||||
std::string def, use;
|
||||
aiVector2D size(2, 2);
|
||||
bool solid = false;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
X3DXmlHelper::getVector2DAttribute(node, "size", size);
|
||||
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Rectangle2D, ne);
|
||||
} else {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_Rectangle2D, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
float x1 = -size.x / 2.0f;
|
||||
float x2 = size.x / 2.0f;
|
||||
float y1 = -size.y / 2.0f;
|
||||
float y2 = size.y / 2.0f;
|
||||
std::list<aiVector3D> &vlist = ((X3DNodeElementGeometry2D *)ne)->Vertices; // just short alias.
|
||||
|
||||
vlist.push_back(aiVector3D(x2, y1, 0)); // 1st point
|
||||
vlist.push_back(aiVector3D(x2, y2, 0)); // 2nd point
|
||||
vlist.push_back(aiVector3D(x1, y2, 0)); // 3rd point
|
||||
vlist.push_back(aiVector3D(x1, y1, 0)); // 4th point
|
||||
((X3DNodeElementGeometry2D *)ne)->Solid = solid;
|
||||
((X3DNodeElementGeometry2D *)ne)->NumIndices = 4;
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "Rectangle2D");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <TriangleSet2D
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// solid="false" SFBool [initializeOnly]
|
||||
// vertices="" MFVec2F [inputOutput]
|
||||
// />
|
||||
void X3DImporter::readTriangleSet2D(XmlNode &node) {
|
||||
std::string def, use;
|
||||
bool solid = false;
|
||||
std::list<aiVector2D> vertices;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
X3DXmlHelper::getVector2DListAttribute(node, "vertices", vertices);
|
||||
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleSet2D, ne);
|
||||
} else {
|
||||
if (vertices.size() % 3) throw DeadlyImportError("TriangleSet2D. Not enough points for defining triangle.");
|
||||
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementGeometry2D(X3DElemType::ENET_TriangleSet2D, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
// convert vec2 to vec3
|
||||
for (std::list<aiVector2D>::iterator it2 = vertices.begin(); it2 != vertices.end(); ++it2) {
|
||||
((X3DNodeElementGeometry2D *)ne)->Vertices.push_back(aiVector3D(it2->x, it2->y, 0));
|
||||
}
|
||||
|
||||
((X3DNodeElementGeometry2D *)ne)->Solid = solid;
|
||||
((X3DNodeElementGeometry2D *)ne)->NumIndices = 3;
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "TriangleSet2D");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
918
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Geometry3D.cpp
Normal file
918
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Geometry3D.cpp
Normal file
|
|
@ -0,0 +1,918 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
/// \file X3DImporter_Geometry3D.cpp
|
||||
/// \brief Parsing data from nodes of "Geometry3D" set of X3D.
|
||||
/// \date 2015-2016
|
||||
/// \author smal.root@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DGeoHelper.h"
|
||||
#include "X3DImporter.hpp"
|
||||
#include "X3DImporter_Macro.hpp"
|
||||
#include "X3DXmlHelper.h"
|
||||
|
||||
// Header files, Assimp.
|
||||
#include <assimp/StandardShapes.h>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
// <Box
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// size="2 2 2" SFVec3f [initializeOnly]
|
||||
// solid="true" SFBool [initializeOnly]
|
||||
// />
|
||||
// The Box node specifies a rectangular parallelepiped box centred at (0, 0, 0) in the local coordinate system and aligned with the local coordinate axes.
|
||||
// By default, the box measures 2 units in each dimension, from -1 to +1. The size field specifies the extents of the box along the X-, Y-, and Z-axes
|
||||
// respectively and each component value shall be greater than zero.
|
||||
void X3DImporter::readBox(XmlNode &node) {
|
||||
std::string def, use;
|
||||
bool solid = true;
|
||||
aiVector3D size(2, 2, 2);
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
X3DXmlHelper::getVector3DAttribute(node, "size", size);
|
||||
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Box, ne);
|
||||
} else {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Box, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
X3DGeoHelper::rect_parallel_epiped(size, ((X3DNodeElementGeometry3D *)ne)->Vertices); // get quad list
|
||||
((X3DNodeElementGeometry3D *)ne)->Solid = solid;
|
||||
((X3DNodeElementGeometry3D *)ne)->NumIndices = 4;
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "Box");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <Cone
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// bottom="true" SFBool [initializeOnly]
|
||||
// bottomRadius="1" SFloat [initializeOnly]
|
||||
// height="2" SFloat [initializeOnly]
|
||||
// side="true" SFBool [initializeOnly]
|
||||
// solid="true" SFBool [initializeOnly]
|
||||
// />
|
||||
void X3DImporter::readCone(XmlNode &node) {
|
||||
std::string use, def;
|
||||
bool bottom = true;
|
||||
float bottomRadius = 1;
|
||||
float height = 2;
|
||||
bool side = true;
|
||||
bool solid = true;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||
XmlParser::getBoolAttribute(node, "side", side);
|
||||
XmlParser::getBoolAttribute(node, "bottom", bottom);
|
||||
XmlParser::getFloatAttribute(node, "height", height);
|
||||
XmlParser::getFloatAttribute(node, "bottomRadius", bottomRadius);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Cone, ne);
|
||||
} else {
|
||||
const unsigned int tess = 30; ///TODO: IME tessellation factor through ai_property
|
||||
|
||||
std::vector<aiVector3D> tvec; // temp array for vertices.
|
||||
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Cone, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
// make cone or parts according to flags.
|
||||
if (side) {
|
||||
StandardShapes::MakeCone(height, 0, bottomRadius, tess, tvec, !bottom);
|
||||
} else if (bottom) {
|
||||
StandardShapes::MakeCircle(bottomRadius, tess, tvec);
|
||||
height = -(height / 2);
|
||||
for (std::vector<aiVector3D>::iterator it = tvec.begin(); it != tvec.end(); ++it)
|
||||
it->y = height; // y - because circle made in oXZ.
|
||||
}
|
||||
|
||||
// copy data from temp array
|
||||
for (std::vector<aiVector3D>::iterator it = tvec.begin(); it != tvec.end(); ++it)
|
||||
((X3DNodeElementGeometry3D *)ne)->Vertices.push_back(*it);
|
||||
|
||||
((X3DNodeElementGeometry3D *)ne)->Solid = solid;
|
||||
((X3DNodeElementGeometry3D *)ne)->NumIndices = 3;
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "Cone");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <Cylinder
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// bottom="true" SFBool [initializeOnly]
|
||||
// height="2" SFloat [initializeOnly]
|
||||
// radius="1" SFloat [initializeOnly]
|
||||
// side="true" SFBool [initializeOnly]
|
||||
// solid="true" SFBool [initializeOnly]
|
||||
// top="true" SFBool [initializeOnly]
|
||||
// />
|
||||
void X3DImporter::readCylinder(XmlNode &node) {
|
||||
std::string use, def;
|
||||
bool bottom = true;
|
||||
float height = 2;
|
||||
float radius = 1;
|
||||
bool side = true;
|
||||
bool solid = true;
|
||||
bool top = true;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getFloatAttribute(node, "radius", radius);
|
||||
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||
XmlParser::getBoolAttribute(node, "bottom", bottom);
|
||||
XmlParser::getBoolAttribute(node, "top", top);
|
||||
XmlParser::getBoolAttribute(node, "side", side);
|
||||
XmlParser::getFloatAttribute(node, "height", height);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Cylinder, ne);
|
||||
} else {
|
||||
const unsigned int tess = 30; ///TODO: IME tessellation factor through ai_property
|
||||
|
||||
std::vector<aiVector3D> tside; // temp array for vertices of side.
|
||||
std::vector<aiVector3D> tcir; // temp array for vertices of circle.
|
||||
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Cylinder, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
// make cilynder or parts according to flags.
|
||||
if (side) StandardShapes::MakeCone(height, radius, radius, tess, tside, true);
|
||||
|
||||
height /= 2; // height defined for whole cylinder, when creating top and bottom circle we are using just half of height.
|
||||
if (top || bottom) StandardShapes::MakeCircle(radius, tess, tcir);
|
||||
// copy data from temp arrays
|
||||
std::list<aiVector3D> &vlist = ((X3DNodeElementGeometry3D *)ne)->Vertices; // just short alias.
|
||||
|
||||
for (std::vector<aiVector3D>::iterator it = tside.begin(); it != tside.end(); ++it)
|
||||
vlist.push_back(*it);
|
||||
|
||||
if (top) {
|
||||
for (std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); ++it) {
|
||||
(*it).y = height; // y - because circle made in oXZ.
|
||||
vlist.push_back(*it);
|
||||
}
|
||||
} // if(top)
|
||||
|
||||
if (bottom) {
|
||||
for (std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); ++it) {
|
||||
(*it).y = -height; // y - because circle made in oXZ.
|
||||
vlist.push_back(*it);
|
||||
}
|
||||
} // if(top)
|
||||
|
||||
((X3DNodeElementGeometry3D *)ne)->Solid = solid;
|
||||
((X3DNodeElementGeometry3D *)ne)->NumIndices = 3;
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "Cylinder");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <ElevationGrid
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// ccw="true" SFBool [initializeOnly]
|
||||
// colorPerVertex="true" SFBool [initializeOnly]
|
||||
// creaseAngle="0" SFloat [initializeOnly]
|
||||
// height="" MFloat [initializeOnly]
|
||||
// normalPerVertex="true" SFBool [initializeOnly]
|
||||
// solid="true" SFBool [initializeOnly]
|
||||
// xDimension="0" SFInt32 [initializeOnly]
|
||||
// xSpacing="1.0" SFloat [initializeOnly]
|
||||
// zDimension="0" SFInt32 [initializeOnly]
|
||||
// zSpacing="1.0" SFloat [initializeOnly]
|
||||
// >
|
||||
// <!-- ColorNormalTexCoordContentModel -->
|
||||
// ColorNormalTexCoordContentModel can contain Color (or ColorRGBA), Normal and TextureCoordinate, in any order. No more than one instance of any single
|
||||
// node type is allowed. A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||
// </ElevationGrid>
|
||||
// The ElevationGrid node specifies a uniform rectangular grid of varying height in the Y=0 plane of the local coordinate system. The geometry is described
|
||||
// by a scalar array of height values that specify the height of a surface above each point of the grid. The xDimension and zDimension fields indicate
|
||||
// the number of elements of the grid height array in the X and Z directions. Both xDimension and zDimension shall be greater than or equal to zero.
|
||||
// If either the xDimension or the zDimension is less than two, the ElevationGrid contains no quadrilaterals.
|
||||
void X3DImporter::readElevationGrid(XmlNode &node) {
|
||||
std::string use, def;
|
||||
bool ccw = true;
|
||||
bool colorPerVertex = true;
|
||||
float creaseAngle = 0;
|
||||
std::vector<float> height;
|
||||
bool normalPerVertex = true;
|
||||
bool solid = true;
|
||||
int32_t xDimension = 0;
|
||||
float xSpacing = 1;
|
||||
int32_t zDimension = 0;
|
||||
float zSpacing = 1;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||
XmlParser::getBoolAttribute(node, "ccw", ccw);
|
||||
XmlParser::getBoolAttribute(node, "colorPerVertex", colorPerVertex);
|
||||
XmlParser::getBoolAttribute(node, "normalPerVertex", normalPerVertex);
|
||||
XmlParser::getFloatAttribute(node, "creaseAngle", creaseAngle);
|
||||
X3DXmlHelper::getFloatArrayAttribute(node, "height", height);
|
||||
XmlParser::getIntAttribute(node, "xDimension", xDimension);
|
||||
XmlParser::getFloatAttribute(node, "xSpacing", xSpacing);
|
||||
XmlParser::getIntAttribute(node, "zDimension", zDimension);
|
||||
XmlParser::getFloatAttribute(node, "zSpacing", zSpacing);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ElevationGrid, ne);
|
||||
} else {
|
||||
if ((xSpacing == 0.0f) || (zSpacing == 0.0f)) throw DeadlyImportError("Spacing in <ElevationGrid> must be grater than zero.");
|
||||
if ((xDimension <= 0) || (zDimension <= 0)) throw DeadlyImportError("Dimension in <ElevationGrid> must be grater than zero.");
|
||||
if ((size_t)(xDimension * zDimension) != height.size()) DeadlyImportError("Heights count must be equal to \"xDimension * zDimension\" in <ElevationGrid>");
|
||||
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementElevationGrid(X3DElemType::ENET_ElevationGrid, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
X3DNodeElementElevationGrid &grid_alias = *((X3DNodeElementElevationGrid *)ne); // create alias for conveience
|
||||
|
||||
{ // create grid vertices list
|
||||
std::vector<float>::const_iterator he_it = height.begin();
|
||||
|
||||
for (int32_t zi = 0; zi < zDimension; zi++) // rows
|
||||
{
|
||||
for (int32_t xi = 0; xi < xDimension; xi++) // columns
|
||||
{
|
||||
aiVector3D tvec(xSpacing * xi, *he_it, zSpacing * zi);
|
||||
|
||||
grid_alias.Vertices.push_back(tvec);
|
||||
++he_it;
|
||||
}
|
||||
}
|
||||
} // END: create grid vertices list
|
||||
//
|
||||
// create faces list. In "coordIdx" format
|
||||
//
|
||||
// check if we have quads
|
||||
if ((xDimension < 2) || (zDimension < 2)) // only one element in dimension is set, create line set.
|
||||
{
|
||||
((X3DNodeElementElevationGrid *)ne)->NumIndices = 2; // will be holded as line set.
|
||||
for (size_t i = 0, i_e = (grid_alias.Vertices.size() - 1); i < i_e; i++) {
|
||||
grid_alias.CoordIdx.push_back(static_cast<int32_t>(i));
|
||||
grid_alias.CoordIdx.push_back(static_cast<int32_t>(i + 1));
|
||||
grid_alias.CoordIdx.push_back(-1);
|
||||
}
|
||||
} else // two or more elements in every dimension is set. create quad set.
|
||||
{
|
||||
((X3DNodeElementElevationGrid *)ne)->NumIndices = 4;
|
||||
for (int32_t fzi = 0, fzi_e = (zDimension - 1); fzi < fzi_e; fzi++) // rows
|
||||
{
|
||||
for (int32_t fxi = 0, fxi_e = (xDimension - 1); fxi < fxi_e; fxi++) // columns
|
||||
{
|
||||
// points direction in face.
|
||||
if (ccw) {
|
||||
// CCW:
|
||||
// 3 2
|
||||
// 0 1
|
||||
grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + fxi);
|
||||
grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + (fxi + 1));
|
||||
grid_alias.CoordIdx.push_back(fzi * xDimension + (fxi + 1));
|
||||
grid_alias.CoordIdx.push_back(fzi * xDimension + fxi);
|
||||
} else {
|
||||
// CW:
|
||||
// 0 1
|
||||
// 3 2
|
||||
grid_alias.CoordIdx.push_back(fzi * xDimension + fxi);
|
||||
grid_alias.CoordIdx.push_back(fzi * xDimension + (fxi + 1));
|
||||
grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + (fxi + 1));
|
||||
grid_alias.CoordIdx.push_back((fzi + 1) * xDimension + fxi);
|
||||
} // if(ccw) else
|
||||
|
||||
grid_alias.CoordIdx.push_back(-1);
|
||||
} // for(int32_t fxi = 0, fxi_e = (xDimension - 1); fxi < fxi_e; fxi++)
|
||||
} // for(int32_t fzi = 0, fzi_e = (zDimension - 1); fzi < fzi_e; fzi++)
|
||||
} // if((xDimension < 2) || (zDimension < 2)) else
|
||||
|
||||
grid_alias.ColorPerVertex = colorPerVertex;
|
||||
grid_alias.NormalPerVertex = normalPerVertex;
|
||||
grid_alias.CreaseAngle = creaseAngle;
|
||||
grid_alias.Solid = solid;
|
||||
// check for child nodes
|
||||
if (!isNodeEmpty(node)) {
|
||||
ParseHelper_Node_Enter(ne);
|
||||
for (auto currentChildNode : node.children()) {
|
||||
const std::string ¤tChildName = currentChildNode.name();
|
||||
// check for X3DComposedGeometryNodes
|
||||
if (currentChildName == "Color")
|
||||
readColor(currentChildNode);
|
||||
else if (currentChildName == "ColorRGBA")
|
||||
readColorRGBA(currentChildNode);
|
||||
else if (currentChildName == "Normal")
|
||||
readNormal(currentChildNode);
|
||||
else if (currentChildName == "TextureCoordinate")
|
||||
readTextureCoordinate(currentChildNode);
|
||||
// check for X3DMetadataObject
|
||||
else if (!checkForMetadataNode(currentChildNode))
|
||||
skipUnsupportedNode("ElevationGrid", currentChildNode);
|
||||
}
|
||||
ParseHelper_Node_Exit();
|
||||
} // if(!mReader->isEmptyElement())
|
||||
else {
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
} // if(!mReader->isEmptyElement()) else
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
template <typename TVector>
|
||||
static void GeometryHelper_Extrusion_CurveIsClosed(std::vector<TVector> &pCurve, const bool pDropTail, const bool pRemoveLastPoint, bool &pCurveIsClosed) {
|
||||
size_t cur_sz = pCurve.size();
|
||||
|
||||
pCurveIsClosed = false;
|
||||
// for curve with less than four points checking is have no sense,
|
||||
if (cur_sz < 4) return;
|
||||
|
||||
for (size_t s = 3, s_e = cur_sz; s < s_e; s++) {
|
||||
// search for first point of duplicated part.
|
||||
if (pCurve[0] == pCurve[s]) {
|
||||
bool found = true;
|
||||
|
||||
// check if tail(indexed by b2) is duplicate of head(indexed by b1).
|
||||
for (size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++) {
|
||||
if (pCurve[b1] != pCurve[b2]) { // points not match: clear flag and break loop.
|
||||
found = false;
|
||||
|
||||
break;
|
||||
}
|
||||
} // for(size_t b1 = 1, b2 = (s + 1); b2 < cur_sz; b1++, b2++)
|
||||
|
||||
// if duplicate tail is found then drop or not it depending on flags.
|
||||
if (found) {
|
||||
pCurveIsClosed = true;
|
||||
if (pDropTail) {
|
||||
if (!pRemoveLastPoint) s++; // prepare value for iterator's arithmetics.
|
||||
|
||||
pCurve.erase(pCurve.begin() + s, pCurve.end()); // remove tail
|
||||
}
|
||||
|
||||
break;
|
||||
} // if(found)
|
||||
} // if(pCurve[0] == pCurve[s])
|
||||
} // for(size_t s = 3, s_e = (cur_sz - 1); s < s_e; s++)
|
||||
}
|
||||
|
||||
static aiVector3D GeometryHelper_Extrusion_GetNextY(const size_t pSpine_PointIdx, const std::vector<aiVector3D> &pSpine, const bool pSpine_Closed) {
|
||||
const size_t spine_idx_last = pSpine.size() - 1;
|
||||
aiVector3D tvec;
|
||||
|
||||
if ((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last)) // at first special cases
|
||||
{
|
||||
if (pSpine_Closed) { // If the spine curve is closed: The SCP for the first and last points is the same and is found using (spine[1] - spine[n - 2]) to compute the Y-axis.
|
||||
// As we even for closed spine curve last and first point in pSpine are not the same: duplicates(spine[n - 1] which are equivalent to spine[0])
|
||||
// in tail are removed.
|
||||
// So, last point in pSpine is a spine[n - 2]
|
||||
tvec = pSpine[1] - pSpine[spine_idx_last];
|
||||
} else if (pSpine_PointIdx == 0) { // The Y-axis used for the first point is the vector from spine[0] to spine[1]
|
||||
tvec = pSpine[1] - pSpine[0];
|
||||
} else { // The Y-axis used for the last point it is the vector from spine[n-2] to spine[n-1]. In our case(see above about dropping tail) spine[n - 1] is
|
||||
// the spine[0].
|
||||
tvec = pSpine[spine_idx_last] - pSpine[spine_idx_last - 1];
|
||||
}
|
||||
} // if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last))
|
||||
else { // For all points other than the first or last: The Y-axis for spine[i] is found by normalizing the vector defined by (spine[i+1] - spine[i-1]).
|
||||
tvec = pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx - 1];
|
||||
} // if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last)) else
|
||||
|
||||
return tvec.Normalize();
|
||||
}
|
||||
|
||||
static aiVector3D GeometryHelper_Extrusion_GetNextZ(const size_t pSpine_PointIdx, const std::vector<aiVector3D> &pSpine, const bool pSpine_Closed,
|
||||
const aiVector3D pVecZ_Prev) {
|
||||
const aiVector3D zero_vec(0);
|
||||
const size_t spine_idx_last = pSpine.size() - 1;
|
||||
|
||||
aiVector3D tvec;
|
||||
|
||||
// at first special cases
|
||||
if (pSpine.size() < 3) // spine have not enough points for vector calculations.
|
||||
{
|
||||
tvec.Set(0, 0, 1);
|
||||
} else if (pSpine_PointIdx == 0) // special case: first point
|
||||
{
|
||||
if (pSpine_Closed) // for calculating use previous point in curve s[n - 2]. In list it's a last point, because point s[n - 1] was removed as duplicate.
|
||||
{
|
||||
tvec = (pSpine[1] - pSpine[0]) ^ (pSpine[spine_idx_last] - pSpine[0]);
|
||||
} else // for not closed curve first and next point(s[0] and s[1]) has the same vector Z.
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
// As said: "If the Z-axis of the first point is undefined (because the spine is not closed and the first two spine segments are collinear)
|
||||
// then the Z-axis for the first spine point with a defined Z-axis is used."
|
||||
// Walk through spine and find Z.
|
||||
for (size_t next_point = 2; (next_point <= spine_idx_last) && !found; next_point++) {
|
||||
// (pSpine[2] - pSpine[1]) ^ (pSpine[0] - pSpine[1])
|
||||
tvec = (pSpine[next_point] - pSpine[next_point - 1]) ^ (pSpine[next_point - 2] - pSpine[next_point - 1]);
|
||||
found = !tvec.Equal(zero_vec);
|
||||
}
|
||||
|
||||
// if entire spine are collinear then use OZ axis.
|
||||
if (!found) tvec.Set(0, 0, 1);
|
||||
} // if(pSpine_Closed) else
|
||||
} // else if(pSpine_PointIdx == 0)
|
||||
else if (pSpine_PointIdx == spine_idx_last) // special case: last point
|
||||
{
|
||||
if (pSpine_Closed) { // do not forget that real last point s[n - 1] is removed as duplicated. And in this case we are calculating vector Z for point s[n - 2].
|
||||
tvec = (pSpine[0] - pSpine[pSpine_PointIdx]) ^ (pSpine[pSpine_PointIdx - 1] - pSpine[pSpine_PointIdx]);
|
||||
// if taken spine vectors are collinear then use previous vector Z.
|
||||
if (tvec.Equal(zero_vec)) tvec = pVecZ_Prev;
|
||||
} else { // vector Z for last point of not closed curve is previous vector Z.
|
||||
tvec = pVecZ_Prev;
|
||||
}
|
||||
} else // regular point
|
||||
{
|
||||
tvec = (pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx]) ^ (pSpine[pSpine_PointIdx - 1] - pSpine[pSpine_PointIdx]);
|
||||
// if taken spine vectors are collinear then use previous vector Z.
|
||||
if (tvec.Equal(zero_vec)) tvec = pVecZ_Prev;
|
||||
}
|
||||
|
||||
// After determining the Z-axis, its dot product with the Z-axis of the previous spine point is computed. If this value is negative, the Z-axis
|
||||
// is flipped (multiplied by -1).
|
||||
if ((tvec * pVecZ_Prev) < 0) tvec = -tvec;
|
||||
|
||||
return tvec.Normalize();
|
||||
}
|
||||
|
||||
// <Extrusion
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// beginCap="true" SFBool [initializeOnly]
|
||||
// ccw="true" SFBool [initializeOnly]
|
||||
// convex="true" SFBool [initializeOnly]
|
||||
// creaseAngle="0.0" SFloat [initializeOnly]
|
||||
// crossSection="1 1 1 -1 -1 -1 -1 1 1 1" MFVec2f [initializeOnly]
|
||||
// endCap="true" SFBool [initializeOnly]
|
||||
// orientation="0 0 1 0" MFRotation [initializeOnly]
|
||||
// scale="1 1" MFVec2f [initializeOnly]
|
||||
// solid="true" SFBool [initializeOnly]
|
||||
// spine="0 0 0 0 1 0" MFVec3f [initializeOnly]
|
||||
// />
|
||||
void X3DImporter::readExtrusion(XmlNode &node) {
|
||||
std::string use, def;
|
||||
bool beginCap = true;
|
||||
bool ccw = true;
|
||||
bool convex = true;
|
||||
float creaseAngle = 0;
|
||||
std::vector<aiVector2D> crossSection;
|
||||
bool endCap = true;
|
||||
std::vector<float> orientation;
|
||||
std::vector<aiVector2D> scale;
|
||||
bool solid = true;
|
||||
std::vector<aiVector3D> spine;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getBoolAttribute(node, "beginCap", beginCap);
|
||||
XmlParser::getBoolAttribute(node, "ccw", ccw);
|
||||
XmlParser::getBoolAttribute(node, "convex", convex);
|
||||
XmlParser::getFloatAttribute(node, "creaseAngle", creaseAngle);
|
||||
X3DXmlHelper::getVector2DArrayAttribute(node, "crossSection", crossSection);
|
||||
XmlParser::getBoolAttribute(node, "endCap", endCap);
|
||||
X3DXmlHelper::getFloatArrayAttribute(node, "orientation", orientation);
|
||||
X3DXmlHelper::getVector2DArrayAttribute(node, "scale", scale);
|
||||
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||
X3DXmlHelper::getVector3DArrayAttribute(node, "spine", spine);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Extrusion, ne);
|
||||
} else {
|
||||
//
|
||||
// check if default values must be assigned
|
||||
//
|
||||
if (spine.size() == 0) {
|
||||
spine.resize(2);
|
||||
spine[0].Set(0, 0, 0), spine[1].Set(0, 1, 0);
|
||||
} else if (spine.size() == 1) {
|
||||
throw DeadlyImportError("ParseNode_Geometry3D_Extrusion. Spine must have at least two points.");
|
||||
}
|
||||
|
||||
if (crossSection.size() == 0) {
|
||||
crossSection.resize(5);
|
||||
crossSection[0].Set(1, 1), crossSection[1].Set(1, -1), crossSection[2].Set(-1, -1), crossSection[3].Set(-1, 1), crossSection[4].Set(1, 1);
|
||||
}
|
||||
|
||||
{ // orientation
|
||||
size_t ori_size = orientation.size() / 4;
|
||||
|
||||
if (ori_size < spine.size()) {
|
||||
float add_ori[4]; // values that will be added
|
||||
|
||||
if (ori_size == 1) // if "orientation" has one element(means one MFRotation with four components) then use it value for all spine points.
|
||||
{
|
||||
add_ori[0] = orientation[0], add_ori[1] = orientation[1], add_ori[2] = orientation[2], add_ori[3] = orientation[3];
|
||||
} else // else - use default values
|
||||
{
|
||||
add_ori[0] = 0, add_ori[1] = 0, add_ori[2] = 1, add_ori[3] = 0;
|
||||
}
|
||||
|
||||
orientation.reserve(spine.size() * 4);
|
||||
for (size_t i = 0, i_e = (spine.size() - ori_size); i < i_e; i++)
|
||||
orientation.push_back(add_ori[0]), orientation.push_back(add_ori[1]), orientation.push_back(add_ori[2]), orientation.push_back(add_ori[3]);
|
||||
}
|
||||
|
||||
if (orientation.size() % 4) throw DeadlyImportError("Attribute \"orientation\" in <Extrusion> must has multiple four quantity of numbers.");
|
||||
} // END: orientation
|
||||
|
||||
{ // scale
|
||||
if (scale.size() < spine.size()) {
|
||||
aiVector2D add_sc;
|
||||
|
||||
if (scale.size() == 1) // if "scale" has one element then use it value for all spine points.
|
||||
add_sc = scale[0];
|
||||
else // else - use default values
|
||||
add_sc.Set(1, 1);
|
||||
|
||||
scale.reserve(spine.size());
|
||||
for (size_t i = 0, i_e = (spine.size() - scale.size()); i < i_e; i++)
|
||||
scale.push_back(add_sc);
|
||||
}
|
||||
} // END: scale
|
||||
//
|
||||
// create and if needed - define new geometry object.
|
||||
//
|
||||
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_Extrusion, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
X3DNodeElementIndexedSet &ext_alias = *((X3DNodeElementIndexedSet *)ne); // create alias for conveience
|
||||
// assign part of input data
|
||||
ext_alias.CCW = ccw;
|
||||
ext_alias.Convex = convex;
|
||||
ext_alias.CreaseAngle = creaseAngle;
|
||||
ext_alias.Solid = solid;
|
||||
|
||||
//
|
||||
// How we done it at all?
|
||||
// 1. At first we will calculate array of basises for every point in spine(look SCP in ISO-dic). Also "orientation" vector
|
||||
// are applied vor every basis.
|
||||
// 2. After that we can create array of point sets: which are scaled, transferred to basis of relative basis and at final translated to real position
|
||||
// using relative spine point.
|
||||
// 3. Next step is creating CoordIdx array(do not forget "-1" delimiter). While creating CoordIdx also created faces for begin and end caps, if
|
||||
// needed. While createing CootdIdx is taking in account CCW flag.
|
||||
// 4. The last step: create Vertices list.
|
||||
//
|
||||
bool spine_closed; // flag: true if spine curve is closed.
|
||||
bool cross_closed; // flag: true if cross curve is closed.
|
||||
std::vector<aiMatrix3x3> basis_arr; // array of basises. ROW_a - X, ROW_b - Y, ROW_c - Z.
|
||||
std::vector<std::vector<aiVector3D>> pointset_arr; // array of point sets: cross curves.
|
||||
|
||||
// detect closed curves
|
||||
GeometryHelper_Extrusion_CurveIsClosed(crossSection, true, true, cross_closed); // true - drop tail, true - remove duplicate end.
|
||||
GeometryHelper_Extrusion_CurveIsClosed(spine, true, true, spine_closed); // true - drop tail, true - remove duplicate end.
|
||||
// If both cap are requested and spine curve is closed then we can make only one cap. Because second cap will be the same surface.
|
||||
if (spine_closed) {
|
||||
beginCap |= endCap;
|
||||
endCap = false;
|
||||
}
|
||||
|
||||
{ // 1. Calculate array of basises.
|
||||
aiMatrix4x4 rotmat;
|
||||
aiVector3D vecX(0), vecY(0), vecZ(0);
|
||||
|
||||
basis_arr.resize(spine.size());
|
||||
for (size_t i = 0, i_e = spine.size(); i < i_e; i++) {
|
||||
aiVector3D tvec;
|
||||
|
||||
// get axises of basis.
|
||||
vecY = GeometryHelper_Extrusion_GetNextY(i, spine, spine_closed);
|
||||
vecZ = GeometryHelper_Extrusion_GetNextZ(i, spine, spine_closed, vecZ);
|
||||
vecX = (vecY ^ vecZ).Normalize();
|
||||
// get rotation matrix and apply "orientation" to basis
|
||||
aiMatrix4x4::Rotation(orientation[i * 4 + 3], aiVector3D(orientation[i * 4], orientation[i * 4 + 1], orientation[i * 4 + 2]), rotmat);
|
||||
tvec = vecX, tvec *= rotmat, basis_arr[i].a1 = tvec.x, basis_arr[i].a2 = tvec.y, basis_arr[i].a3 = tvec.z;
|
||||
tvec = vecY, tvec *= rotmat, basis_arr[i].b1 = tvec.x, basis_arr[i].b2 = tvec.y, basis_arr[i].b3 = tvec.z;
|
||||
tvec = vecZ, tvec *= rotmat, basis_arr[i].c1 = tvec.x, basis_arr[i].c2 = tvec.y, basis_arr[i].c3 = tvec.z;
|
||||
} // for(size_t i = 0, i_e = spine.size(); i < i_e; i++)
|
||||
} // END: 1. Calculate array of basises
|
||||
|
||||
{ // 2. Create array of point sets.
|
||||
aiMatrix4x4 scmat;
|
||||
std::vector<aiVector3D> tcross(crossSection.size());
|
||||
|
||||
pointset_arr.resize(spine.size());
|
||||
for (size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++) {
|
||||
aiVector3D tc23vec;
|
||||
|
||||
tc23vec.Set(scale[spi].x, 0, scale[spi].y);
|
||||
aiMatrix4x4::Scaling(tc23vec, scmat);
|
||||
for (size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++) {
|
||||
aiVector3D tvecX, tvecY, tvecZ;
|
||||
|
||||
tc23vec.Set(crossSection[cri].x, 0, crossSection[cri].y);
|
||||
// apply scaling to point
|
||||
tcross[cri] = scmat * tc23vec;
|
||||
//
|
||||
// transfer point to new basis
|
||||
// calculate coordinate in new basis
|
||||
tvecX.Set(basis_arr[spi].a1, basis_arr[spi].a2, basis_arr[spi].a3), tvecX *= tcross[cri].x;
|
||||
tvecY.Set(basis_arr[spi].b1, basis_arr[spi].b2, basis_arr[spi].b3), tvecY *= tcross[cri].y;
|
||||
tvecZ.Set(basis_arr[spi].c1, basis_arr[spi].c2, basis_arr[spi].c3), tvecZ *= tcross[cri].z;
|
||||
// apply new coordinates and translate it to spine point.
|
||||
tcross[cri] = tvecX + tvecY + tvecZ + spine[spi];
|
||||
} // for(size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; i++)
|
||||
|
||||
pointset_arr[spi] = tcross; // store transferred point set
|
||||
} // for(size_t spi = 0, spi_e = spine.size(); spi < spi_e; i++)
|
||||
} // END: 2. Create array of point sets.
|
||||
|
||||
{ // 3. Create CoordIdx.
|
||||
// add caps if needed
|
||||
if (beginCap) {
|
||||
// add cap as polygon. vertices of cap are places at begin, so just add numbers from zero.
|
||||
for (size_t i = 0, i_e = crossSection.size(); i < i_e; i++)
|
||||
ext_alias.CoordIndex.push_back(static_cast<int32_t>(i));
|
||||
|
||||
// add delimiter
|
||||
ext_alias.CoordIndex.push_back(-1);
|
||||
} // if(beginCap)
|
||||
|
||||
if (endCap) {
|
||||
// add cap as polygon. vertices of cap are places at end, as for beginCap use just sequence of numbers but with offset.
|
||||
size_t beg = (pointset_arr.size() - 1) * crossSection.size();
|
||||
|
||||
for (size_t i = beg, i_e = (beg + crossSection.size()); i < i_e; i++)
|
||||
ext_alias.CoordIndex.push_back(static_cast<int32_t>(i));
|
||||
|
||||
// add delimiter
|
||||
ext_alias.CoordIndex.push_back(-1);
|
||||
} // if(beginCap)
|
||||
|
||||
// add quads
|
||||
for (size_t spi = 0, spi_e = (spine.size() - 1); spi <= spi_e; spi++) {
|
||||
const size_t cr_sz = crossSection.size();
|
||||
const size_t cr_last = crossSection.size() - 1;
|
||||
|
||||
size_t right_col; // hold index basis for points of quad placed in right column;
|
||||
|
||||
if (spi != spi_e)
|
||||
right_col = spi + 1;
|
||||
else if (spine_closed) // if spine curve is closed then one more quad is needed: between first and last points of curve.
|
||||
right_col = 0;
|
||||
else
|
||||
break; // if spine curve is not closed then break the loop, because spi is out of range for that type of spine.
|
||||
|
||||
for (size_t cri = 0; cri < cr_sz; cri++) {
|
||||
if (cri != cr_last) {
|
||||
MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex,
|
||||
static_cast<int32_t>(spi * cr_sz + cri),
|
||||
static_cast<int32_t>(right_col * cr_sz + cri),
|
||||
static_cast<int32_t>(right_col * cr_sz + cri + 1),
|
||||
static_cast<int32_t>(spi * cr_sz + cri + 1));
|
||||
// add delimiter
|
||||
ext_alias.CoordIndex.push_back(-1);
|
||||
} else if (cross_closed) // if cross curve is closed then one more quad is needed: between first and last points of curve.
|
||||
{
|
||||
MACRO_FACE_ADD_QUAD(ccw, ext_alias.CoordIndex,
|
||||
static_cast<int32_t>(spi * cr_sz + cri),
|
||||
static_cast<int32_t>(right_col * cr_sz + cri),
|
||||
static_cast<int32_t>(right_col * cr_sz + 0),
|
||||
static_cast<int32_t>(spi * cr_sz + 0));
|
||||
// add delimiter
|
||||
ext_alias.CoordIndex.push_back(-1);
|
||||
}
|
||||
} // for(size_t cri = 0; cri < cr_sz; cri++)
|
||||
} // for(size_t spi = 0, spi_e = (spine.size() - 2); spi < spi_e; spi++)
|
||||
} // END: 3. Create CoordIdx.
|
||||
|
||||
{ // 4. Create vertices list.
|
||||
// just copy all vertices
|
||||
for (size_t spi = 0, spi_e = spine.size(); spi < spi_e; spi++) {
|
||||
for (size_t cri = 0, cri_e = crossSection.size(); cri < cri_e; cri++) {
|
||||
ext_alias.Vertices.emplace_back(pointset_arr[spi][cri]);
|
||||
}
|
||||
}
|
||||
} // END: 4. Create vertices list.
|
||||
//PrintVectorSet("Ext. CoordIdx", ext_alias.CoordIndex);
|
||||
//PrintVectorSet("Ext. Vertices", ext_alias.Vertices);
|
||||
// check for child nodes
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "Extrusion");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <IndexedFaceSet
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// ccw="true" SFBool [initializeOnly]
|
||||
// colorIndex="" MFInt32 [initializeOnly]
|
||||
// colorPerVertex="true" SFBool [initializeOnly]
|
||||
// convex="true" SFBool [initializeOnly]
|
||||
// coordIndex="" MFInt32 [initializeOnly]
|
||||
// creaseAngle="0" SFFloat [initializeOnly]
|
||||
// normalIndex="" MFInt32 [initializeOnly]
|
||||
// normalPerVertex="true" SFBool [initializeOnly]
|
||||
// solid="true" SFBool [initializeOnly]
|
||||
// texCoordIndex="" MFInt32 [initializeOnly]
|
||||
// >
|
||||
// <!-- ComposedGeometryContentModel -->
|
||||
// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
|
||||
// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
|
||||
// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
|
||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||
// </IndexedFaceSet>
|
||||
void X3DImporter::readIndexedFaceSet(XmlNode &node) {
|
||||
std::string use, def;
|
||||
bool ccw = true;
|
||||
std::vector<int32_t> colorIndex;
|
||||
bool colorPerVertex = true;
|
||||
bool convex = true;
|
||||
std::vector<int32_t> coordIndex;
|
||||
float creaseAngle = 0;
|
||||
std::vector<int32_t> normalIndex;
|
||||
bool normalPerVertex = true;
|
||||
bool solid = true;
|
||||
std::vector<int32_t> texCoordIndex;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getBoolAttribute(node, "ccw", ccw);
|
||||
X3DXmlHelper::getInt32ArrayAttribute(node, "colorIndex", colorIndex);
|
||||
XmlParser::getBoolAttribute(node, "colorPerVertex", colorPerVertex);
|
||||
XmlParser::getBoolAttribute(node, "convex", convex);
|
||||
X3DXmlHelper::getInt32ArrayAttribute(node, "coordIndex", coordIndex);
|
||||
XmlParser::getFloatAttribute(node, "creaseAngle", creaseAngle);
|
||||
X3DXmlHelper::getInt32ArrayAttribute(node, "normalIndex", normalIndex);
|
||||
XmlParser::getBoolAttribute(node, "normalPerVertex", normalPerVertex);
|
||||
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||
X3DXmlHelper::getInt32ArrayAttribute(node, "texCoordIndex", texCoordIndex);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedFaceSet, ne);
|
||||
} else {
|
||||
// check data
|
||||
if (coordIndex.size() == 0) throw DeadlyImportError("IndexedFaceSet must contain not empty \"coordIndex\" attribute.");
|
||||
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_IndexedFaceSet, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
X3DNodeElementIndexedSet &ne_alias = *((X3DNodeElementIndexedSet *)ne);
|
||||
|
||||
ne_alias.CCW = ccw;
|
||||
ne_alias.ColorIndex = colorIndex;
|
||||
ne_alias.ColorPerVertex = colorPerVertex;
|
||||
ne_alias.Convex = convex;
|
||||
ne_alias.CoordIndex = coordIndex;
|
||||
ne_alias.CreaseAngle = creaseAngle;
|
||||
ne_alias.NormalIndex = normalIndex;
|
||||
ne_alias.NormalPerVertex = normalPerVertex;
|
||||
ne_alias.Solid = solid;
|
||||
ne_alias.TexCoordIndex = texCoordIndex;
|
||||
// check for child nodes
|
||||
if (!isNodeEmpty(node)) {
|
||||
ParseHelper_Node_Enter(ne);
|
||||
for (auto currentChildNode : node.children()) {
|
||||
const std::string ¤tChildName = currentChildNode.name();
|
||||
// check for X3DComposedGeometryNodes
|
||||
if (currentChildName == "Color")
|
||||
readColor(currentChildNode);
|
||||
else if (currentChildName == "ColorRGBA")
|
||||
readColorRGBA(currentChildNode);
|
||||
else if (currentChildName == "Coordinate")
|
||||
readCoordinate(currentChildNode);
|
||||
else if (currentChildName == "Normal")
|
||||
readNormal(currentChildNode);
|
||||
else if (currentChildName == "TextureCoordinate")
|
||||
readTextureCoordinate(currentChildNode);
|
||||
// check for X3DMetadataObject
|
||||
else if (!checkForMetadataNode(currentChildNode))
|
||||
skipUnsupportedNode("IndexedFaceSet", currentChildNode);
|
||||
}
|
||||
ParseHelper_Node_Exit();
|
||||
} // if(!isNodeEmpty(node))
|
||||
else {
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
}
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <Sphere
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// radius="1" SFloat [initializeOnly]
|
||||
// solid="true" SFBool [initializeOnly]
|
||||
// />
|
||||
void X3DImporter::readSphere(XmlNode &node) {
|
||||
std::string use, def;
|
||||
ai_real radius = 1;
|
||||
bool solid = true;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getRealAttribute(node, "radius", radius);
|
||||
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Sphere, ne);
|
||||
} else {
|
||||
const unsigned int tess = 3; ///TODO: IME tessellation factor through ai_property
|
||||
|
||||
std::vector<aiVector3D> tlist;
|
||||
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementGeometry3D(X3DElemType::ENET_Sphere, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
StandardShapes::MakeSphere(tess, tlist);
|
||||
// copy data from temp array and apply scale
|
||||
for (std::vector<aiVector3D>::iterator it = tlist.begin(); it != tlist.end(); ++it) {
|
||||
aiVector3D v = *it;
|
||||
((X3DNodeElementGeometry3D *)ne)->Vertices.emplace_back(v * radius);
|
||||
}
|
||||
|
||||
((X3DNodeElementGeometry3D *)ne)->Solid = solid;
|
||||
((X3DNodeElementGeometry3D *)ne)->NumIndices = 3;
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "Sphere");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
277
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Group.cpp
Normal file
277
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Group.cpp
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
/// \file X3DImporter_Group.cpp
|
||||
/// \brief Parsing data from nodes of "Grouping" set of X3D.
|
||||
/// date 2015-2016
|
||||
/// author smal.root@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include "X3DImporter_Macro.hpp"
|
||||
#include "X3DXmlHelper.h"
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
// <Group
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// bboxCenter="0 0 0" SFVec3f [initializeOnly]
|
||||
// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
|
||||
// >
|
||||
// <\!-- ChildContentModel -->
|
||||
// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
|
||||
// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
|
||||
// precise palette of legal nodes that are available depends on assigned profile and components.
|
||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||
// </Group>
|
||||
// A Group node contains children nodes without introducing a new transformation. It is equivalent to a Transform node containing an identity transform.
|
||||
void X3DImporter::startReadGroup(XmlNode &node) {
|
||||
std::string def, use;
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne);
|
||||
} else {
|
||||
ParseHelper_Group_Begin(); // create new grouping element and go deeper if node has children.
|
||||
// at this place new group mode created and made current, so we can name it.
|
||||
if (!def.empty()) mNodeElementCur->ID = def;
|
||||
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
||||
|
||||
// for empty element exit from node in that place
|
||||
if (isNodeEmpty(node)) ParseHelper_Node_Exit();
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
void X3DImporter::endReadGroup() {
|
||||
ParseHelper_Node_Exit(); // go up in scene graph
|
||||
}
|
||||
|
||||
// <StaticGroup
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// bboxCenter="0 0 0" SFVec3f [initializeOnly]
|
||||
// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
|
||||
// >
|
||||
// <\!-- ChildContentModel -->
|
||||
// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
|
||||
// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
|
||||
// precise palette of legal nodes that are available depends on assigned profile and components.
|
||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||
// </StaticGroup>
|
||||
// The StaticGroup node contains children nodes which cannot be modified. StaticGroup children are guaranteed to not change, send events, receive events or
|
||||
// contain any USE references outside the StaticGroup.
|
||||
void X3DImporter::startReadStaticGroup(XmlNode &node) {
|
||||
std::string def, use;
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne);
|
||||
} else {
|
||||
ParseHelper_Group_Begin(true); // create new grouping element and go deeper if node has children.
|
||||
// at this place new group mode created and made current, so we can name it.
|
||||
if (!def.empty()) mNodeElementCur->ID = def;
|
||||
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
||||
|
||||
// for empty element exit from node in that place
|
||||
if (isNodeEmpty(node)) ParseHelper_Node_Exit();
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
void X3DImporter::endReadStaticGroup() {
|
||||
ParseHelper_Node_Exit(); // go up in scene graph
|
||||
}
|
||||
|
||||
// <Switch
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// bboxCenter="0 0 0" SFVec3f [initializeOnly]
|
||||
// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
|
||||
// whichChoice="-1" SFInt32 [inputOutput]
|
||||
// >
|
||||
// <\!-- ChildContentModel -->
|
||||
// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
|
||||
// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
|
||||
// precise palette of legal nodes that are available depends on assigned profile and components.
|
||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||
// </Switch>
|
||||
// The Switch grouping node traverses zero or one of the nodes specified in the children field. The whichChoice field specifies the index of the child
|
||||
// to traverse, with the first child having index 0. If whichChoice is less than zero or greater than the number of nodes in the children field, nothing
|
||||
// is chosen.
|
||||
void X3DImporter::startReadSwitch(XmlNode &node) {
|
||||
std::string def, use;
|
||||
int32_t whichChoice = -1;
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getIntAttribute(node, "whichChoice", whichChoice);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne);
|
||||
} else {
|
||||
ParseHelper_Group_Begin(); // create new grouping element and go deeper if node has children.
|
||||
// at this place new group mode created and made current, so we can name it.
|
||||
if (!def.empty()) mNodeElementCur->ID = def;
|
||||
|
||||
// also set values specific to this type of group
|
||||
((X3DNodeElementGroup *)mNodeElementCur)->UseChoice = true;
|
||||
((X3DNodeElementGroup *)mNodeElementCur)->Choice = whichChoice;
|
||||
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
||||
|
||||
// for empty element exit from node in that place
|
||||
if (isNodeEmpty(node)) ParseHelper_Node_Exit();
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
void X3DImporter::endReadSwitch() {
|
||||
// just exit from node. Defined choice will be accepted at postprocessing stage.
|
||||
ParseHelper_Node_Exit(); // go up in scene graph
|
||||
}
|
||||
|
||||
// <Transform
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// bboxCenter="0 0 0" SFVec3f [initializeOnly]
|
||||
// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
|
||||
// center="0 0 0" SFVec3f [inputOutput]
|
||||
// rotation="0 0 1 0" SFRotation [inputOutput]
|
||||
// scale="1 1 1" SFVec3f [inputOutput]
|
||||
// scaleOrientation="0 0 1 0" SFRotation [inputOutput]
|
||||
// translation="0 0 0" SFVec3f [inputOutput]
|
||||
// >
|
||||
// <\!-- ChildContentModel -->
|
||||
// ChildContentModel is the child-node content model corresponding to X3DChildNode, combining all profiles. ChildContentModel can contain most nodes,
|
||||
// other Grouping nodes, Prototype declarations and ProtoInstances in any order and any combination. When the assigned profile is less than Full, the
|
||||
// precise palette of legal nodes that are available depends on assigned profile and components.
|
||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||
// </Transform>
|
||||
// The Transform node is a grouping node that defines a coordinate system for its children that is relative to the coordinate systems of its ancestors.
|
||||
// Given a 3-dimensional point P and Transform node, P is transformed into point P' in its parent's coordinate system by a series of intermediate
|
||||
// transformations. In matrix transformation notation, where C (center), SR (scaleOrientation), T (translation), R (rotation), and S (scale) are the
|
||||
// equivalent transformation matrices,
|
||||
// P' = T * C * R * SR * S * -SR * -C * P
|
||||
void X3DImporter::startReadTransform(XmlNode &node) {
|
||||
aiVector3D center(0, 0, 0);
|
||||
float rotation[4] = { 0, 0, 1, 0 };
|
||||
aiVector3D scale(1, 1, 1); // A value of zero indicates that any child geometry shall not be displayed
|
||||
float scale_orientation[4] = { 0, 0, 1, 0 };
|
||||
aiVector3D translation(0, 0, 0);
|
||||
aiMatrix4x4 matr, tmatr;
|
||||
std::string use, def;
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
X3DXmlHelper::getVector3DAttribute(node, "center", center);
|
||||
X3DXmlHelper::getVector3DAttribute(node, "scale", scale);
|
||||
X3DXmlHelper::getVector3DAttribute(node, "translation", translation);
|
||||
std::vector<float> tvec;
|
||||
if (X3DXmlHelper::getFloatArrayAttribute(node, "rotation", tvec)) {
|
||||
if (tvec.size() != 4) throw DeadlyImportError("<Transform>: rotation vector must have 4 elements.");
|
||||
memcpy(rotation, tvec.data(), sizeof(rotation));
|
||||
tvec.clear();
|
||||
}
|
||||
if (X3DXmlHelper::getFloatArrayAttribute(node, "scaleOrientation", tvec)) {
|
||||
if (tvec.size() != 4) throw DeadlyImportError("<Transform>: scaleOrientation vector must have 4 elements.");
|
||||
memcpy(scale_orientation, tvec.data(), sizeof(scale_orientation));
|
||||
tvec.clear();
|
||||
}
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
bool newgroup = (nullptr == mNodeElementCur);
|
||||
if(newgroup)
|
||||
ParseHelper_Group_Begin();
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne);
|
||||
if (newgroup && isNodeEmpty(node)) {
|
||||
ParseHelper_Node_Exit();
|
||||
}
|
||||
} else {
|
||||
ParseHelper_Group_Begin(); // create new grouping element and go deeper if node has children.
|
||||
// at this place new group mode created and made current, so we can name it.
|
||||
if (!def.empty()) {
|
||||
mNodeElementCur->ID = def;
|
||||
}
|
||||
|
||||
//
|
||||
// also set values specific to this type of group
|
||||
//
|
||||
// calculate transformation matrix
|
||||
aiMatrix4x4::Translation(translation, matr); // T
|
||||
aiMatrix4x4::Translation(center, tmatr); // C
|
||||
matr *= tmatr;
|
||||
aiMatrix4x4::Rotation(rotation[3], aiVector3D(rotation[0], rotation[1], rotation[2]), tmatr); // R
|
||||
matr *= tmatr;
|
||||
aiMatrix4x4::Rotation(scale_orientation[3], aiVector3D(scale_orientation[0], scale_orientation[1], scale_orientation[2]), tmatr); // SR
|
||||
matr *= tmatr;
|
||||
aiMatrix4x4::Scaling(scale, tmatr); // S
|
||||
matr *= tmatr;
|
||||
aiMatrix4x4::Rotation(-scale_orientation[3], aiVector3D(scale_orientation[0], scale_orientation[1], scale_orientation[2]), tmatr); // -SR
|
||||
matr *= tmatr;
|
||||
aiMatrix4x4::Translation(-center, tmatr); // -C
|
||||
matr *= tmatr;
|
||||
// and assign it
|
||||
((X3DNodeElementGroup *)mNodeElementCur)->Transformation = matr;
|
||||
// in grouping set of nodes check X3DMetadataObject is not needed, because it is done in <Scene> parser function.
|
||||
|
||||
// for empty element exit from node in that place
|
||||
if (isNodeEmpty(node)) {
|
||||
ParseHelper_Node_Exit();
|
||||
}
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
void X3DImporter::endReadTransform() {
|
||||
ParseHelper_Node_Exit(); // go up in scene graph
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
270
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Light.cpp
Normal file
270
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Light.cpp
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
/// \file X3DImporter_Light.cpp
|
||||
/// \brief Parsing data from nodes of "Lighting" set of X3D.
|
||||
/// date 2015-2016
|
||||
/// author smal.root@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include "X3DImporter_Macro.hpp"
|
||||
#include "X3DXmlHelper.h"
|
||||
#include <assimp/StringUtils.h>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
// <DirectionalLight
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// ambientIntensity="0" SFFloat [inputOutput]
|
||||
// color="1 1 1" SFColor [inputOutput]
|
||||
// direction="0 0 -1" SFVec3f [inputOutput]
|
||||
// global="false" SFBool [inputOutput]
|
||||
// intensity="1" SFFloat [inputOutput]
|
||||
// on="true" SFBool [inputOutput]
|
||||
// />
|
||||
void X3DImporter::readDirectionalLight(XmlNode &node) {
|
||||
std::string def, use;
|
||||
float ambientIntensity = 0;
|
||||
aiColor3D color(1, 1, 1);
|
||||
aiVector3D direction(0, 0, -1);
|
||||
bool global = false;
|
||||
float intensity = 1;
|
||||
bool on = true;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getFloatAttribute(node, "ambientIntensity", ambientIntensity);
|
||||
X3DXmlHelper::getColor3DAttribute(node, "color", color);
|
||||
X3DXmlHelper::getVector3DAttribute(node, "direction", direction);
|
||||
XmlParser::getBoolAttribute(node, "global", global);
|
||||
XmlParser::getFloatAttribute(node, "intensity", intensity);
|
||||
XmlParser::getBoolAttribute(node, "on", on);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_DirectionalLight, ne);
|
||||
} else {
|
||||
if (on) {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementLight(X3DElemType::ENET_DirectionalLight, mNodeElementCur);
|
||||
if (!def.empty())
|
||||
ne->ID = def;
|
||||
else
|
||||
ne->ID = "DirectionalLight_" + ai_to_string((size_t)ne); // make random name
|
||||
|
||||
((X3DNodeElementLight *)ne)->AmbientIntensity = ambientIntensity;
|
||||
((X3DNodeElementLight *)ne)->Color = color;
|
||||
((X3DNodeElementLight *)ne)->Direction = direction;
|
||||
((X3DNodeElementLight *)ne)->Global = global;
|
||||
((X3DNodeElementLight *)ne)->Intensity = intensity;
|
||||
// Assimp want a node with name similar to a light. "Why? I don't no." )
|
||||
ParseHelper_Group_Begin(false);
|
||||
|
||||
mNodeElementCur->ID = ne->ID; // assign name to node and return to light element.
|
||||
ParseHelper_Node_Exit();
|
||||
// check for child nodes
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "DirectionalLight");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(on)
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <PointLight
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// ambientIntensity="0" SFFloat [inputOutput]
|
||||
// attenuation="1 0 0" SFVec3f [inputOutput]
|
||||
// color="1 1 1" SFColor [inputOutput]
|
||||
// global="true" SFBool [inputOutput]
|
||||
// intensity="1" SFFloat [inputOutput]
|
||||
// location="0 0 0" SFVec3f [inputOutput]
|
||||
// on="true" SFBool [inputOutput]
|
||||
// radius="100" SFFloat [inputOutput]
|
||||
// />
|
||||
void X3DImporter::readPointLight(XmlNode &node) {
|
||||
std::string def, use;
|
||||
float ambientIntensity = 0;
|
||||
aiVector3D attenuation(1, 0, 0);
|
||||
aiColor3D color(1, 1, 1);
|
||||
bool global = true;
|
||||
float intensity = 1;
|
||||
aiVector3D location(0, 0, 0);
|
||||
bool on = true;
|
||||
float radius = 100;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getFloatAttribute(node, "ambientIntensity", ambientIntensity);
|
||||
X3DXmlHelper::getVector3DAttribute(node, "attenuation", attenuation);
|
||||
X3DXmlHelper::getColor3DAttribute(node, "color", color);
|
||||
XmlParser::getBoolAttribute(node, "global", global);
|
||||
XmlParser::getFloatAttribute(node, "intensity", intensity);
|
||||
X3DXmlHelper::getVector3DAttribute(node, "location", location);
|
||||
XmlParser::getBoolAttribute(node, "on", on);
|
||||
XmlParser::getFloatAttribute(node, "radius", radius);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_PointLight, ne);
|
||||
} else {
|
||||
if (on) {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementLight(X3DElemType::ENET_PointLight, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
((X3DNodeElementLight *)ne)->AmbientIntensity = ambientIntensity;
|
||||
((X3DNodeElementLight *)ne)->Attenuation = attenuation;
|
||||
((X3DNodeElementLight *)ne)->Color = color;
|
||||
((X3DNodeElementLight *)ne)->Global = global;
|
||||
((X3DNodeElementLight *)ne)->Intensity = intensity;
|
||||
((X3DNodeElementLight *)ne)->Location = location;
|
||||
((X3DNodeElementLight *)ne)->Radius = radius;
|
||||
// Assimp want a node with name similar to a light. "Why? I don't no." )
|
||||
ParseHelper_Group_Begin(false);
|
||||
// make random name
|
||||
if (ne->ID.empty()) ne->ID = "PointLight_" + ai_to_string((size_t)ne);
|
||||
|
||||
mNodeElementCur->ID = ne->ID; // assign name to node and return to light element.
|
||||
ParseHelper_Node_Exit();
|
||||
// check for child nodes
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "PointLight");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(on)
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <SpotLight
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// ambientIntensity="0" SFFloat [inputOutput]
|
||||
// attenuation="1 0 0" SFVec3f [inputOutput]
|
||||
// beamWidth="0.7854" SFFloat [inputOutput]
|
||||
// color="1 1 1" SFColor [inputOutput]
|
||||
// cutOffAngle="1.570796" SFFloat [inputOutput]
|
||||
// direction="0 0 -1" SFVec3f [inputOutput]
|
||||
// global="true" SFBool [inputOutput]
|
||||
// intensity="1" SFFloat [inputOutput]
|
||||
// location="0 0 0" SFVec3f [inputOutput]
|
||||
// on="true" SFBool [inputOutput]
|
||||
// radius="100" SFFloat [inputOutput]
|
||||
// />
|
||||
void X3DImporter::readSpotLight(XmlNode &node) {
|
||||
std::string def, use;
|
||||
float ambientIntensity = 0;
|
||||
aiVector3D attenuation(1, 0, 0);
|
||||
float beamWidth = 0.7854f;
|
||||
aiColor3D color(1, 1, 1);
|
||||
float cutOffAngle = 1.570796f;
|
||||
aiVector3D direction(0, 0, -1);
|
||||
bool global = true;
|
||||
float intensity = 1;
|
||||
aiVector3D location(0, 0, 0);
|
||||
bool on = true;
|
||||
float radius = 100;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getFloatAttribute(node, "ambientIntensity", ambientIntensity);
|
||||
X3DXmlHelper::getVector3DAttribute(node, "attenuation", attenuation);
|
||||
XmlParser::getFloatAttribute(node, "beamWidth", beamWidth);
|
||||
X3DXmlHelper::getColor3DAttribute(node, "color", color);
|
||||
XmlParser::getFloatAttribute(node, "cutOffAngle", cutOffAngle);
|
||||
X3DXmlHelper::getVector3DAttribute(node, "direction", direction);
|
||||
XmlParser::getBoolAttribute(node, "global", global);
|
||||
XmlParser::getFloatAttribute(node, "intensity", intensity);
|
||||
X3DXmlHelper::getVector3DAttribute(node, "location", location);
|
||||
XmlParser::getBoolAttribute(node, "on", on);
|
||||
XmlParser::getFloatAttribute(node, "radius", radius);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_SpotLight, ne);
|
||||
} else {
|
||||
if (on) {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementLight(X3DElemType::ENET_SpotLight, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
if (beamWidth > cutOffAngle) beamWidth = cutOffAngle;
|
||||
|
||||
((X3DNodeElementLight *)ne)->AmbientIntensity = ambientIntensity;
|
||||
((X3DNodeElementLight *)ne)->Attenuation = attenuation;
|
||||
((X3DNodeElementLight *)ne)->BeamWidth = beamWidth;
|
||||
((X3DNodeElementLight *)ne)->Color = color;
|
||||
((X3DNodeElementLight *)ne)->CutOffAngle = cutOffAngle;
|
||||
((X3DNodeElementLight *)ne)->Direction = direction;
|
||||
((X3DNodeElementLight *)ne)->Global = global;
|
||||
((X3DNodeElementLight *)ne)->Intensity = intensity;
|
||||
((X3DNodeElementLight *)ne)->Location = location;
|
||||
((X3DNodeElementLight *)ne)->Radius = radius;
|
||||
|
||||
// Assimp want a node with name similar to a light. "Why? I don't no." )
|
||||
ParseHelper_Group_Begin(false);
|
||||
// make random name
|
||||
if (ne->ID.empty()) ne->ID = "SpotLight_" + ai_to_string((size_t)ne);
|
||||
|
||||
mNodeElementCur->ID = ne->ID; // assign name to node and return to light element.
|
||||
ParseHelper_Node_Exit();
|
||||
// check for child nodes
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "SpotLight");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(on)
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
121
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Macro.hpp
Normal file
121
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Macro.hpp
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
/// \file X3DImporter_Macro.hpp
|
||||
/// \brief Useful macrodefines.
|
||||
/// \date 2015-2016
|
||||
/// \author smal.root@gmail.com
|
||||
|
||||
#ifndef X3DIMPORTER_MACRO_HPP_INCLUDED
|
||||
#define X3DIMPORTER_MACRO_HPP_INCLUDED
|
||||
|
||||
#include <assimp/XmlParser.h>
|
||||
#include "X3DImporter.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
/// Used for regular checking while attribute "USE" is defined.
|
||||
/// \param [in] pNode - pugi xml node to read.
|
||||
/// \param [in] pDEF - string holding "DEF" value.
|
||||
/// \param [in] pUSE - string holding "USE" value.
|
||||
/// \param [in] pType - type of element to find.
|
||||
/// \param [out] pNE - pointer to found node element.
|
||||
inline X3DNodeElementBase *X3DImporter::MACRO_USE_CHECKANDAPPLY(XmlNode &node, std::string pDEF, std::string pUSE, X3DElemType pType, X3DNodeElementBase *pNE) {
|
||||
checkNodeMustBeEmpty(node);
|
||||
if (!pDEF.empty())
|
||||
Assimp::Throw_DEF_And_USE(node.name());
|
||||
if (!FindNodeElement(pUSE, pType, &pNE))
|
||||
Assimp::Throw_USE_NotFound(node.name(), pUSE);
|
||||
ai_assert(nullptr != mNodeElementCur);
|
||||
mNodeElementCur->Children.push_back(pNE); /* add found object as child to current element */
|
||||
|
||||
return pNE;
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
/// \def MACRO_ATTRREAD_CHECKUSEDEF_RET
|
||||
/// Compact variant for checking "USE" and "DEF".
|
||||
/// \param [in] pNode - pugi xml node to read.
|
||||
/// \param [out] pDEF_Var - output variable name for "DEF" value.
|
||||
/// \param [out] pUSE_Var - output variable name for "USE" value.
|
||||
#define MACRO_ATTRREAD_CHECKUSEDEF_RET(pNode, pDEF_Var, pUSE_Var) \
|
||||
do { \
|
||||
XmlParser::getStdStrAttribute(pNode, "DEF", pDEF_Var); \
|
||||
XmlParser::getStdStrAttribute(pNode, "USE", pUSE_Var); \
|
||||
} while (false)
|
||||
|
||||
/// \def MACRO_FACE_ADD_QUAD_FA(pCCW, pOut, pIn, pP1, pP2, pP3, pP4)
|
||||
/// Add points as quad. Means that pP1..pP4 set in CCW order.
|
||||
#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)
|
||||
|
||||
/// \def MACRO_FACE_ADD_QUAD(pCCW, pOut, pP1, pP2, pP3, pP4)
|
||||
/// Add points as quad. Means that pP1..pP4 set in CCW order.
|
||||
#define MACRO_FACE_ADD_QUAD(pCCW, pOut, pP1, pP2, pP3, pP4) \
|
||||
do { \
|
||||
if (pCCW) { \
|
||||
pOut.push_back(pP1); \
|
||||
pOut.push_back(pP2); \
|
||||
pOut.push_back(pP3); \
|
||||
pOut.push_back(pP4); \
|
||||
} else { \
|
||||
pOut.push_back(pP4); \
|
||||
pOut.push_back(pP3); \
|
||||
pOut.push_back(pP2); \
|
||||
pOut.push_back(pP1); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#endif // X3DIMPORTER_MACRO_HPP_INCLUDED
|
||||
255
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Metadata.cpp
Normal file
255
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Metadata.cpp
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
/// \file X3DImporter_Metadata.cpp
|
||||
/// \brief Parsing data from nodes of "Metadata" set of X3D.
|
||||
/// \date 2015-2016
|
||||
/// \author smal.root@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include "X3DImporter_Macro.hpp"
|
||||
#include "X3DXmlHelper.h"
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
bool X3DImporter::checkForMetadataNode(XmlNode &node) {
|
||||
const std::string &name = node.name();
|
||||
if (name == "MetadataBoolean") {
|
||||
readMetadataBoolean(node);
|
||||
} else if (name == "MetadataDouble") {
|
||||
readMetadataDouble(node);
|
||||
} else if (name == "MetadataFloat") {
|
||||
readMetadataFloat(node);
|
||||
} else if (name == "MetadataInteger") {
|
||||
readMetadataInteger(node);
|
||||
} else if (name == "MetadataSet") {
|
||||
readMetadataSet(node);
|
||||
} else if (name == "MetadataString") {
|
||||
readMetadataString(node);
|
||||
} else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void X3DImporter::childrenReadMetadata(XmlNode &node, X3DNodeElementBase *pParentElement, const std::string &pNodeName) {
|
||||
ParseHelper_Node_Enter(pParentElement);
|
||||
for (auto childNode : node.children()) {
|
||||
if (!checkForMetadataNode(childNode)) skipUnsupportedNode(pNodeName, childNode);
|
||||
}
|
||||
ParseHelper_Node_Exit();
|
||||
}
|
||||
|
||||
/// \def MACRO_METADATA_FINDCREATE(pDEF_Var, pUSE_Var, pReference, pValue, pNE, pMetaName)
|
||||
/// Find element by "USE" or create new one.
|
||||
/// \param [in] pNode - pugi xml node to read.
|
||||
/// \param [in] pDEF_Var - variable name with "DEF" value.
|
||||
/// \param [in] pUSE_Var - variable name with "USE" value.
|
||||
/// \param [in] pReference - variable name with "reference" value.
|
||||
/// \param [in] pValue - variable name with "value" value.
|
||||
/// \param [in, out] pNE - pointer to node element.
|
||||
/// \param [in] pMetaClass - Class of node.
|
||||
/// \param [in] pMetaName - Name of node.
|
||||
/// \param [in] pType - type of element to find.
|
||||
#define MACRO_METADATA_FINDCREATE(pNode, pDEF_Var, pUSE_Var, pReference, pValue, pNE, pMetaClass, pMetaName, pType) \
|
||||
/* if "USE" defined then find already defined element. */ \
|
||||
if (!pUSE_Var.empty()) { \
|
||||
ne = MACRO_USE_CHECKANDAPPLY(pNode, pDEF_Var, pUSE_Var, pType, pNE); \
|
||||
} else { \
|
||||
pNE = new pMetaClass(mNodeElementCur); \
|
||||
if (!pDEF_Var.empty()) pNE->ID = pDEF_Var; \
|
||||
\
|
||||
((pMetaClass *)pNE)->Reference = pReference; \
|
||||
((pMetaClass *)pNE)->Value = pValue; \
|
||||
/* also metadata node can contain childs */ \
|
||||
if (!isNodeEmpty(pNode)) \
|
||||
childrenReadMetadata(pNode, pNE, pMetaName); /* in that case node element will be added to child elements list of current node. */ \
|
||||
else \
|
||||
mNodeElementCur->Children.push_back(pNE); /* else - add element to child list manually */ \
|
||||
\
|
||||
NodeElement_List.push_back(pNE); /* add new element to elements list. */ \
|
||||
} /* if(!pUSE_Var.empty()) else */ \
|
||||
\
|
||||
do { \
|
||||
} while (false)
|
||||
|
||||
// <MetadataBoolean
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// name="" SFString [inputOutput]
|
||||
// reference="" SFString [inputOutput]
|
||||
// value="" MFBool [inputOutput]
|
||||
// />
|
||||
void X3DImporter::readMetadataBoolean(XmlNode &node) {
|
||||
std::string def, use;
|
||||
std::string name, reference;
|
||||
std::vector<bool> value;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getStdStrAttribute(node, "name", name);
|
||||
XmlParser::getStdStrAttribute(node, "reference", reference);
|
||||
X3DXmlHelper::getBooleanArrayAttribute(node, "value", value);
|
||||
|
||||
MACRO_METADATA_FINDCREATE(node, def, use, reference, value, ne, X3DNodeElementMetaBoolean, "MetadataBoolean", ENET_MetaBoolean);
|
||||
}
|
||||
|
||||
// <MetadataDouble
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// name="" SFString [inputOutput]
|
||||
// reference="" SFString [inputOutput]
|
||||
// value="" MFDouble [inputOutput]
|
||||
// />
|
||||
void X3DImporter::readMetadataDouble(XmlNode &node) {
|
||||
std::string def, use;
|
||||
std::string name, reference;
|
||||
std::vector<double> value;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getStdStrAttribute(node, "name", name);
|
||||
XmlParser::getStdStrAttribute(node, "reference", reference);
|
||||
X3DXmlHelper::getDoubleArrayAttribute(node, "value", value);
|
||||
|
||||
MACRO_METADATA_FINDCREATE(node, def, use, reference, value, ne, X3DNodeElementMetaDouble, "MetadataDouble", ENET_MetaDouble);
|
||||
}
|
||||
|
||||
// <MetadataFloat
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// name="" SFString [inputOutput]
|
||||
// reference="" SFString [inputOutput]
|
||||
// value="" MFFloat [inputOutput]
|
||||
// />
|
||||
void X3DImporter::readMetadataFloat(XmlNode &node) {
|
||||
std::string def, use;
|
||||
std::string name, reference;
|
||||
std::vector<float> value;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getStdStrAttribute(node, "name", name);
|
||||
XmlParser::getStdStrAttribute(node, "reference", reference);
|
||||
X3DXmlHelper::getFloatArrayAttribute(node, "value", value);
|
||||
|
||||
MACRO_METADATA_FINDCREATE(node, def, use, reference, value, ne, X3DNodeElementMetaFloat, "MetadataFloat", ENET_MetaFloat);
|
||||
}
|
||||
|
||||
// <MetadataInteger
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// name="" SFString [inputOutput]
|
||||
// reference="" SFString [inputOutput]
|
||||
// value="" MFInteger [inputOutput]
|
||||
// />
|
||||
void X3DImporter::readMetadataInteger(XmlNode &node) {
|
||||
std::string def, use;
|
||||
std::string name, reference;
|
||||
std::vector<int32_t> value;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getStdStrAttribute(node, "name", name);
|
||||
XmlParser::getStdStrAttribute(node, "reference", reference);
|
||||
X3DXmlHelper::getInt32ArrayAttribute(node, "value", value);
|
||||
|
||||
MACRO_METADATA_FINDCREATE(node, def, use, reference, value, ne, X3DNodeElementMetaInt, "MetadataInteger", ENET_MetaInteger);
|
||||
}
|
||||
|
||||
// <MetadataSet
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// name="" SFString [inputOutput]
|
||||
// reference="" SFString [inputOutput]
|
||||
// />
|
||||
void X3DImporter::readMetadataSet(XmlNode &node) {
|
||||
std::string def, use;
|
||||
std::string name, reference;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getStdStrAttribute(node, "name", name);
|
||||
XmlParser::getStdStrAttribute(node, "reference", reference);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_MetaSet, ne);
|
||||
} else {
|
||||
ne = new X3DNodeElementMetaSet(mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
((X3DNodeElementMetaSet *)ne)->Reference = reference;
|
||||
// also metadata node can contain children
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "MetadataSet");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add new element to elements list.
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <MetadataString
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// name="" SFString [inputOutput]
|
||||
// reference="" SFString [inputOutput]
|
||||
// value="" MFString [inputOutput]
|
||||
// />
|
||||
void X3DImporter::readMetadataString(XmlNode &node) {
|
||||
std::string def, use;
|
||||
std::string name, reference;
|
||||
std::vector<std::string> value;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getStdStrAttribute(node, "name", name);
|
||||
XmlParser::getStdStrAttribute(node, "reference", reference);
|
||||
X3DXmlHelper::getStringArrayAttribute(node, "value", value);
|
||||
|
||||
MACRO_METADATA_FINDCREATE(node, def, use, reference, value, ne, X3DNodeElementMetaString, "MetadataString", ENET_MetaString);
|
||||
}
|
||||
|
||||
}// namespace Assimp
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
124
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Networking.cpp
Normal file
124
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Networking.cpp
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
/// \file X3DImporter_Networking.cpp
|
||||
/// \brief Parsing data from nodes of "Networking" set of X3D.
|
||||
/// date 2015-2016
|
||||
/// author smal.root@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include "X3DImporter_Macro.hpp"
|
||||
#include "X3DXmlHelper.h"
|
||||
|
||||
// Header files, Assimp.
|
||||
#include <assimp/DefaultIOSystem.h>
|
||||
|
||||
//#include <regex>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
//static std::regex pattern_parentDir(R"((^|/)[^/]+/../)");
|
||||
static std::string parentDir("/../");
|
||||
|
||||
// <Inline
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// bboxCenter="0 0 0" SFVec3f [initializeOnly]
|
||||
// bboxSize="-1 -1 -1" SFVec3f [initializeOnly]
|
||||
// load="true" SFBool [inputOutput]
|
||||
// url="" MFString [inputOutput]
|
||||
// />
|
||||
void X3DImporter::readInline(XmlNode &node) {
|
||||
std::string def, use;
|
||||
bool load = true;
|
||||
std::list<std::string> url;
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getBoolAttribute(node, "load", load);
|
||||
X3DXmlHelper::getStringListAttribute(node, "url", url);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
X3DNodeElementBase *ne = nullptr;
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Group, ne);
|
||||
} else {
|
||||
ParseHelper_Group_Begin(true); // create new grouping element and go deeper if node has children.
|
||||
// at this place new group mode created and made current, so we can name it.
|
||||
if (!def.empty()) mNodeElementCur->ID = def;
|
||||
|
||||
if (load && !url.empty()) {
|
||||
std::string full_path = mpIOHandler->CurrentDirectory() + url.front();
|
||||
|
||||
//full_path = std::regex_replace(full_path, pattern_parentDir, "$1");
|
||||
for (std::string::size_type pos = full_path.find(parentDir); pos != std::string::npos; pos = full_path.find(parentDir, pos)) {
|
||||
if (pos > 0) {
|
||||
std::string::size_type pos2 = full_path.rfind('/', pos - 1);
|
||||
if (pos2 != std::string::npos) {
|
||||
full_path.erase(pos2, pos - pos2 + 3);
|
||||
pos = pos2;
|
||||
} else {
|
||||
full_path.erase(0, pos + 4);
|
||||
pos = 0;
|
||||
}
|
||||
} else {
|
||||
pos += 3;
|
||||
}
|
||||
}
|
||||
// Attribute "url" can contain list of strings. But we need only one - first.
|
||||
std::string::size_type slashPos = full_path.find_last_of("\\/");
|
||||
mpIOHandler->PushDirectory(slashPos == std::string::npos ? std::string() : full_path.substr(0, slashPos + 1));
|
||||
ParseFile(full_path, mpIOHandler);
|
||||
mpIOHandler->PopDirectory();
|
||||
}
|
||||
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node)) childrenReadMetadata(node, mNodeElementCur, "Inline");
|
||||
|
||||
// exit from node in that place
|
||||
ParseHelper_Node_Exit();
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
463
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Node.hpp
Normal file
463
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Node.hpp
Normal file
|
|
@ -0,0 +1,463 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
/// \file X3DImporter_Node.hpp
|
||||
/// \brief Elements of scene graph.
|
||||
/// \date 2015-2016
|
||||
/// \author smal.root@gmail.com
|
||||
|
||||
#ifndef INCLUDED_AI_X3D_IMPORTER_NODE_H
|
||||
#define INCLUDED_AI_X3D_IMPORTER_NODE_H
|
||||
|
||||
// Header files, Assimp.
|
||||
#include <assimp/types.h>
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
enum X3DElemType {
|
||||
ENET_Group, ///< Element has type "Group".
|
||||
ENET_MetaBoolean, ///< Element has type "Metadata boolean".
|
||||
ENET_MetaDouble, ///< Element has type "Metadata double".
|
||||
ENET_MetaFloat, ///< Element has type "Metadata float".
|
||||
ENET_MetaInteger, ///< Element has type "Metadata integer".
|
||||
ENET_MetaSet, ///< Element has type "Metadata set".
|
||||
ENET_MetaString, ///< Element has type "Metadata string".
|
||||
ENET_Arc2D, ///< Element has type "Arc2D".
|
||||
ENET_ArcClose2D, ///< Element has type "ArcClose2D".
|
||||
ENET_Circle2D, ///< Element has type "Circle2D".
|
||||
ENET_Disk2D, ///< Element has type "Disk2D".
|
||||
ENET_Polyline2D, ///< Element has type "Polyline2D".
|
||||
ENET_Polypoint2D, ///< Element has type "Polypoint2D".
|
||||
ENET_Rectangle2D, ///< Element has type "Rectangle2D".
|
||||
ENET_TriangleSet2D, ///< Element has type "TriangleSet2D".
|
||||
ENET_Box, ///< Element has type "Box".
|
||||
ENET_Cone, ///< Element has type "Cone".
|
||||
ENET_Cylinder, ///< Element has type "Cylinder".
|
||||
ENET_Sphere, ///< Element has type "Sphere".
|
||||
ENET_ElevationGrid, ///< Element has type "ElevationGrid".
|
||||
ENET_Extrusion, ///< Element has type "Extrusion".
|
||||
ENET_Coordinate, ///< Element has type "Coordinate".
|
||||
ENET_Normal, ///< Element has type "Normal".
|
||||
ENET_TextureCoordinate, ///< Element has type "TextureCoordinate".
|
||||
ENET_IndexedFaceSet, ///< Element has type "IndexedFaceSet".
|
||||
ENET_IndexedLineSet, ///< Element has type "IndexedLineSet".
|
||||
ENET_IndexedTriangleSet, ///< Element has type "IndexedTriangleSet".
|
||||
ENET_IndexedTriangleFanSet, ///< Element has type "IndexedTriangleFanSet".
|
||||
ENET_IndexedTriangleStripSet, ///< Element has type "IndexedTriangleStripSet".
|
||||
ENET_LineSet, ///< Element has type "LineSet".
|
||||
ENET_PointSet, ///< Element has type "PointSet".
|
||||
ENET_TriangleSet, ///< Element has type "TriangleSet".
|
||||
ENET_TriangleFanSet, ///< Element has type "TriangleFanSet".
|
||||
ENET_TriangleStripSet, ///< Element has type "TriangleStripSet".
|
||||
ENET_Color, ///< Element has type "Color".
|
||||
ENET_ColorRGBA, ///< Element has type "ColorRGBA".
|
||||
ENET_Shape, ///< Element has type "Shape".
|
||||
ENET_Appearance, ///< Element has type "Appearance".
|
||||
ENET_Material, ///< Element has type "Material".
|
||||
ENET_ImageTexture, ///< Element has type "ImageTexture".
|
||||
ENET_TextureTransform, ///< Element has type "TextureTransform".
|
||||
ENET_DirectionalLight, ///< Element has type "DirectionalLight".
|
||||
ENET_PointLight, ///< Element has type "PointLight".
|
||||
ENET_SpotLight, ///< Element has type "SpotLight".
|
||||
|
||||
ENET_Invalid ///< Element has invalid type and possible contain invalid data.
|
||||
};
|
||||
|
||||
struct X3DNodeElementBase {
|
||||
X3DNodeElementBase *Parent;
|
||||
std::string ID;
|
||||
std::list<X3DNodeElementBase *> Children;
|
||||
X3DElemType Type;
|
||||
|
||||
virtual ~X3DNodeElementBase() {
|
||||
// empty
|
||||
}
|
||||
|
||||
protected:
|
||||
X3DNodeElementBase(X3DElemType type, X3DNodeElementBase *pParent) :
|
||||
Parent(pParent), Type(type) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
/// This struct hold <Color> value.
|
||||
struct X3DNodeElementColor : X3DNodeElementBase {
|
||||
std::list<aiColor3D> Value; ///< Stored value.
|
||||
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
X3DNodeElementColor(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementBase(X3DElemType::ENET_Color, pParent) {}
|
||||
|
||||
}; // struct X3DNodeElementColor
|
||||
|
||||
/// This struct hold <ColorRGBA> value.
|
||||
struct X3DNodeElementColorRGBA : X3DNodeElementBase {
|
||||
std::list<aiColor4D> Value; ///< Stored value.
|
||||
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
X3DNodeElementColorRGBA(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementBase(X3DElemType::ENET_ColorRGBA, pParent) {}
|
||||
|
||||
}; // struct X3DNodeElementColorRGBA
|
||||
|
||||
/// This struct hold <Coordinate> value.
|
||||
struct X3DNodeElementCoordinate : public X3DNodeElementBase {
|
||||
std::list<aiVector3D> Value; ///< Stored value.
|
||||
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
X3DNodeElementCoordinate(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementBase(X3DElemType::ENET_Coordinate, pParent) {}
|
||||
|
||||
}; // struct X3DNodeElementCoordinate
|
||||
|
||||
/// This struct hold <Normal> value.
|
||||
struct X3DNodeElementNormal : X3DNodeElementBase {
|
||||
std::list<aiVector3D> Value; ///< Stored value.
|
||||
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
X3DNodeElementNormal(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementBase(X3DElemType::ENET_Normal, pParent) {}
|
||||
|
||||
}; // struct X3DNodeElementNormal
|
||||
|
||||
/// This struct hold <TextureCoordinate> value.
|
||||
struct X3DNodeElementTextureCoordinate : X3DNodeElementBase {
|
||||
std::list<aiVector2D> Value; ///< Stored value.
|
||||
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
X3DNodeElementTextureCoordinate(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementBase(X3DElemType::ENET_TextureCoordinate, pParent) {}
|
||||
|
||||
}; // struct X3DNodeElementTextureCoordinate
|
||||
|
||||
/// Two-dimensional figure.
|
||||
struct X3DNodeElementGeometry2D : X3DNodeElementBase {
|
||||
std::list<aiVector3D> Vertices; ///< Vertices list.
|
||||
size_t NumIndices; ///< Number of indices in one face.
|
||||
bool Solid; ///< Flag: if true then render must use back-face culling, else render must draw both sides of object.
|
||||
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
/// \param [in] pType - type of geometry object.
|
||||
X3DNodeElementGeometry2D(X3DElemType pType, X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementBase(pType, pParent), Solid(true) {}
|
||||
|
||||
}; // class X3DNodeElementGeometry2D
|
||||
|
||||
/// Three-dimensional body.
|
||||
struct X3DNodeElementGeometry3D : X3DNodeElementBase {
|
||||
std::list<aiVector3D> Vertices; ///< Vertices list.
|
||||
size_t NumIndices; ///< Number of indices in one face.
|
||||
bool Solid; ///< Flag: if true then render must use back-face culling, else render must draw both sides of object.
|
||||
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
/// \param [in] pType - type of geometry object.
|
||||
X3DNodeElementGeometry3D(X3DElemType pType, X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementBase(pType, pParent), Vertices(), NumIndices(0), Solid(true) {
|
||||
// empty
|
||||
}
|
||||
}; // class X3DNodeElementGeometry3D
|
||||
|
||||
/// Uniform rectangular grid of varying height.
|
||||
struct X3DNodeElementElevationGrid : X3DNodeElementGeometry3D {
|
||||
bool NormalPerVertex; ///< If true then normals are defined for every vertex, else for every face(line).
|
||||
bool ColorPerVertex; ///< If true then colors are defined for every vertex, else for every face(line).
|
||||
/// If the angle between the geometric normals of two adjacent faces is less than the crease angle, normals shall be calculated so that the faces are
|
||||
/// shaded smoothly across the edge; otherwise, normals shall be calculated so that a lighting discontinuity across the edge is produced.
|
||||
float CreaseAngle;
|
||||
std::vector<int32_t> CoordIdx; ///< Coordinates list by faces. In X3D format: "-1" - delimiter for faces.
|
||||
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
/// \param [in] pType - type of geometry object.
|
||||
X3DNodeElementElevationGrid(X3DElemType pType, X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementGeometry3D(pType, pParent) {}
|
||||
}; // class X3DNodeElementIndexedSet
|
||||
|
||||
/// Shape with indexed vertices.
|
||||
struct X3DNodeElementIndexedSet : public X3DNodeElementGeometry3D {
|
||||
/// The ccw field defines the ordering of the vertex coordinates of the geometry with respect to user-given or automatically generated normal vectors
|
||||
/// used in the lighting model equations. If ccw is TRUE, the normals shall follow the right hand rule; the orientation of each normal with respect to
|
||||
/// the vertices (taken in order) shall be such that the vertices appear to be oriented in a counterclockwise order when the vertices are viewed (in the
|
||||
/// local coordinate system of the Shape) from the opposite direction as the normal. If ccw is FALSE, the normals shall be oriented in the opposite
|
||||
/// direction. If normals are not generated but are supplied using a Normal node, and the orientation of the normals does not match the setting of the
|
||||
/// ccw field, results are undefined.
|
||||
bool CCW;
|
||||
std::vector<int32_t> ColorIndex; ///< Field to specify the polygonal faces by indexing into the <Color> or <ColorRGBA>.
|
||||
bool ColorPerVertex; ///< If true then colors are defined for every vertex, else for every face(line).
|
||||
/// The convex field indicates whether all polygons in the shape are convex (TRUE). A polygon is convex if it is planar, does not intersect itself,
|
||||
/// and all of the interior angles at its vertices are less than 180 degrees. Non planar and self intersecting polygons may produce undefined results
|
||||
/// even if the convex field is FALSE.
|
||||
bool Convex;
|
||||
std::vector<int32_t> CoordIndex; ///< Field to specify the polygonal faces by indexing into the <Coordinate>.
|
||||
/// If the angle between the geometric normals of two adjacent faces is less than the crease angle, normals shall be calculated so that the faces are
|
||||
/// shaded smoothly across the edge; otherwise, normals shall be calculated so that a lighting discontinuity across the edge is produced.
|
||||
float CreaseAngle;
|
||||
std::vector<int32_t> NormalIndex; ///< Field to specify the polygonal faces by indexing into the <Normal>.
|
||||
bool NormalPerVertex; ///< If true then normals are defined for every vertex, else for every face(line).
|
||||
std::vector<int32_t> TexCoordIndex; ///< Field to specify the polygonal faces by indexing into the <TextureCoordinate>.
|
||||
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
/// \param [in] pType - type of geometry object.
|
||||
X3DNodeElementIndexedSet(X3DElemType pType, X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementGeometry3D(pType, pParent) {}
|
||||
}; // class X3DNodeElementIndexedSet
|
||||
|
||||
/// Shape with set of vertices.
|
||||
struct X3DNodeElementSet : X3DNodeElementGeometry3D {
|
||||
/// The ccw field defines the ordering of the vertex coordinates of the geometry with respect to user-given or automatically generated normal vectors
|
||||
/// used in the lighting model equations. If ccw is TRUE, the normals shall follow the right hand rule; the orientation of each normal with respect to
|
||||
/// the vertices (taken in order) shall be such that the vertices appear to be oriented in a counterclockwise order when the vertices are viewed (in the
|
||||
/// local coordinate system of the Shape) from the opposite direction as the normal. If ccw is FALSE, the normals shall be oriented in the opposite
|
||||
/// direction. If normals are not generated but are supplied using a Normal node, and the orientation of the normals does not match the setting of the
|
||||
/// ccw field, results are undefined.
|
||||
bool CCW;
|
||||
bool ColorPerVertex; ///< If true then colors are defined for every vertex, else for every face(line).
|
||||
bool NormalPerVertex; ///< If true then normals are defined for every vertex, else for every face(line).
|
||||
std::vector<int32_t> CoordIndex; ///< Field to specify the polygonal faces by indexing into the <Coordinate>.
|
||||
std::vector<int32_t> NormalIndex; ///< Field to specify the polygonal faces by indexing into the <Normal>.
|
||||
std::vector<int32_t> TexCoordIndex; ///< Field to specify the polygonal faces by indexing into the <TextureCoordinate>.
|
||||
std::vector<int32_t> VertexCount; ///< Field describes how many vertices are to be used in each polyline(polygon) from the <Coordinate> field.
|
||||
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
/// \param [in] pType - type of geometry object.
|
||||
X3DNodeElementSet(X3DElemType type, X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementGeometry3D(type, pParent) {}
|
||||
|
||||
}; // class X3DNodeElementSet
|
||||
|
||||
/// This struct hold <Shape> value.
|
||||
struct X3DNodeElementShape : X3DNodeElementBase {
|
||||
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
X3DNodeElementShape(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementBase(X3DElemType::ENET_Shape, pParent) {}
|
||||
}; // struct X3DNodeElementShape
|
||||
|
||||
/// This struct hold <Appearance> value.
|
||||
struct X3DNodeElementAppearance : public X3DNodeElementBase {
|
||||
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
X3DNodeElementAppearance(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementBase(X3DElemType::ENET_Appearance, pParent) {}
|
||||
|
||||
}; // struct X3DNodeElementAppearance
|
||||
|
||||
struct X3DNodeElementMaterial : public X3DNodeElementBase {
|
||||
float AmbientIntensity; ///< Specifies how much ambient light from light sources this surface shall reflect.
|
||||
aiColor3D DiffuseColor; ///< Reflects all X3D light sources depending on the angle of the surface with respect to the light source.
|
||||
aiColor3D EmissiveColor; ///< Models "glowing" objects. This can be useful for displaying pre-lit models.
|
||||
float Shininess; ///< Lower shininess values produce soft glows, while higher values result in sharper, smaller highlights.
|
||||
aiColor3D SpecularColor; ///< The specularColor and shininess fields determine the specular highlights.
|
||||
float Transparency; ///< Specifies how "clear" an object is, with 1.0 being completely transparent, and 0.0 completely opaque.
|
||||
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
/// \param [in] pType - type of geometry object.
|
||||
X3DNodeElementMaterial(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementBase(X3DElemType::ENET_Material, pParent),
|
||||
AmbientIntensity(0.0f),
|
||||
DiffuseColor(),
|
||||
EmissiveColor(),
|
||||
Shininess(0.0f),
|
||||
SpecularColor(),
|
||||
Transparency(1.0f) {
|
||||
// empty
|
||||
}
|
||||
}; // class X3DNodeElementMaterial
|
||||
|
||||
/// This struct hold <ImageTexture> value.
|
||||
struct X3DNodeElementImageTexture : X3DNodeElementBase {
|
||||
/// RepeatS and RepeatT, that specify how the texture wraps in the S and T directions. If repeatS is TRUE (the default), the texture map is repeated
|
||||
/// outside the [0.0, 1.0] texture coordinate range in the S direction so that it fills the shape. If repeatS is FALSE, the texture coordinates are
|
||||
/// clamped in the S direction to lie within the [0.0, 1.0] range. The repeatT field is analogous to the repeatS field.
|
||||
bool RepeatS;
|
||||
bool RepeatT; ///< See \ref RepeatS.
|
||||
std::string URL; ///< URL of the texture.
|
||||
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
X3DNodeElementImageTexture(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementBase(X3DElemType::ENET_ImageTexture, pParent) {}
|
||||
|
||||
}; // struct X3DNodeElementImageTexture
|
||||
|
||||
/// This struct hold <TextureTransform> value.
|
||||
struct X3DNodeElementTextureTransform : X3DNodeElementBase {
|
||||
aiVector2D Center; ///< Specifies a translation offset in texture coordinate space about which the rotation and scale fields are applied.
|
||||
float Rotation; ///< Specifies a rotation in angle base units of the texture coordinates about the center point after the scale has been applied.
|
||||
aiVector2D Scale; ///< Specifies a scaling factor in S and T of the texture coordinates about the center point.
|
||||
aiVector2D Translation; ///< Specifies a translation of the texture coordinates.
|
||||
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
X3DNodeElementTextureTransform(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementBase(X3DElemType::ENET_TextureTransform, pParent) {}
|
||||
|
||||
}; // struct X3DNodeElementTextureTransform
|
||||
|
||||
struct X3DNodeElementGroup : X3DNodeElementBase {
|
||||
aiMatrix4x4 Transformation; ///< Transformation matrix.
|
||||
|
||||
/// As you know node elements can use already defined node elements when attribute "USE" is defined.
|
||||
/// Standard search when looking for an element in the whole scene graph, existing at this moment.
|
||||
/// If a node is marked as static, the children(or lower) can not search for elements in the nodes upper then static.
|
||||
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.
|
||||
|
||||
/// Constructor.
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
/// \param [in] pStatic - static node flag.
|
||||
X3DNodeElementGroup(X3DNodeElementBase *pParent, const bool pStatic = false) :
|
||||
X3DNodeElementBase(X3DElemType::ENET_Group, pParent), Static(pStatic), UseChoice(false) {}
|
||||
};
|
||||
|
||||
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.
|
||||
|
||||
explicit X3DNodeElementMetaBoolean(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementMeta(X3DElemType::ENET_MetaBoolean, pParent) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
struct X3DNodeElementMetaDouble : X3DNodeElementMeta {
|
||||
std::vector<double> Value; ///< Stored value.
|
||||
|
||||
explicit X3DNodeElementMetaDouble(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementMeta(X3DElemType::ENET_MetaDouble, pParent) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
struct X3DNodeElementMetaFloat : public X3DNodeElementMeta {
|
||||
std::vector<float> Value; ///< Stored value.
|
||||
|
||||
explicit X3DNodeElementMetaFloat(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementMeta(X3DElemType::ENET_MetaFloat, pParent) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
struct X3DNodeElementMetaInt : public X3DNodeElementMeta {
|
||||
std::vector<int32_t> Value; ///< Stored value.
|
||||
|
||||
explicit X3DNodeElementMetaInt(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementMeta(X3DElemType::ENET_MetaInteger, pParent) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
struct X3DNodeElementMetaSet : public X3DNodeElementMeta {
|
||||
std::list<X3DNodeElementMeta> Value; ///< Stored value.
|
||||
|
||||
explicit X3DNodeElementMetaSet(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementMeta(X3DElemType::ENET_MetaSet, pParent) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
struct X3DNodeElementMetaString : X3DNodeElementMeta {
|
||||
std::vector<std::string> Value; ///< Stored value.
|
||||
|
||||
explicit X3DNodeElementMetaString(X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementMeta(X3DElemType::ENET_MetaString, pParent) {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
/// \struct X3DNodeElementLight
|
||||
/// This struct hold <TextureTransform> value.
|
||||
struct X3DNodeElementLight : X3DNodeElementBase {
|
||||
float AmbientIntensity; ///< Specifies the intensity of the ambient emission from the light.
|
||||
aiColor3D Color; ///< specifies the spectral colour properties of both the direct and ambient light emission as an RGB value.
|
||||
aiVector3D Direction; ///< Specifies the direction vector of the illumination emanating from the light source in the local coordinate system.
|
||||
/// \var Global
|
||||
/// Field that determines whether the light is global or scoped. Global lights illuminate all objects that fall within their volume of lighting influence.
|
||||
/// Scoped lights only illuminate objects that are in the same transformation hierarchy as the light.
|
||||
bool Global;
|
||||
float Intensity; ///< Specifies the brightness of the direct emission from the light.
|
||||
/// \var Attenuation
|
||||
/// PointLight node's illumination falls off with distance as specified by three attenuation coefficients. The attenuation factor
|
||||
/// is: "1 / max(attenuation[0] + attenuation[1] * r + attenuation[2] * r2, 1)", where r is the distance from the light to the surface being illuminated.
|
||||
aiVector3D Attenuation;
|
||||
aiVector3D Location; ///< Specifies a translation offset of the centre point of the light source from the light's local coordinate system origin.
|
||||
float Radius; ///< Specifies the radial extent of the solid angle and the maximum distance from location that may be illuminated by the light source.
|
||||
float BeamWidth; ///< Specifies an inner solid angle in which the light source emits light at uniform full intensity.
|
||||
float CutOffAngle; ///< The light source's emission intensity drops off from the inner solid angle (beamWidth) to the outer solid angle (cutOffAngle).
|
||||
|
||||
/// Constructor
|
||||
/// \param [in] pParent - pointer to parent node.
|
||||
/// \param [in] pLightType - type of the light source.
|
||||
X3DNodeElementLight(X3DElemType pLightType, X3DNodeElementBase *pParent) :
|
||||
X3DNodeElementBase(pLightType, pParent) {}
|
||||
|
||||
}; // struct X3DNodeElementLight
|
||||
|
||||
#endif // INCLUDED_AI_X3D_IMPORTER_NODE_H
|
||||
731
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Postprocess.cpp
Normal file
731
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Postprocess.cpp
Normal file
|
|
@ -0,0 +1,731 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
/// \file X3DImporter_Postprocess.cpp
|
||||
/// \brief Convert built scenegraph and objects to Assimp scenegraph.
|
||||
/// \date 2015-2016
|
||||
/// \author smal.root@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DGeoHelper.h"
|
||||
#include "X3DImporter.hpp"
|
||||
|
||||
// Header files, Assimp.
|
||||
#include <assimp/StandardShapes.h>
|
||||
#include <assimp/StringUtils.h>
|
||||
#include <assimp/ai_assert.h>
|
||||
|
||||
// Header files, stdlib.
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
aiMatrix4x4 X3DImporter::PostprocessHelper_Matrix_GlobalToCurrent() const {
|
||||
X3DNodeElementBase *cur_node;
|
||||
std::list<aiMatrix4x4> matr;
|
||||
aiMatrix4x4 out_matr;
|
||||
|
||||
// starting walk from current element to root
|
||||
cur_node = mNodeElementCur;
|
||||
if (cur_node != nullptr) {
|
||||
do {
|
||||
// if cur_node is group then store group transformation matrix in list.
|
||||
if (cur_node->Type == X3DElemType::ENET_Group) matr.push_back(((X3DNodeElementGroup *)cur_node)->Transformation);
|
||||
|
||||
cur_node = cur_node->Parent;
|
||||
} while (cur_node != nullptr);
|
||||
}
|
||||
|
||||
// multiplicate all matrices in reverse order
|
||||
for (std::list<aiMatrix4x4>::reverse_iterator rit = matr.rbegin(); rit != matr.rend(); ++rit)
|
||||
out_matr = out_matr * (*rit);
|
||||
|
||||
return out_matr;
|
||||
}
|
||||
|
||||
void X3DImporter::PostprocessHelper_CollectMetadata(const X3DNodeElementBase &pNodeElement, std::list<X3DNodeElementBase *> &pList) const {
|
||||
// walk through childs and find for metadata.
|
||||
for (std::list<X3DNodeElementBase *>::const_iterator el_it = pNodeElement.Children.begin(); el_it != pNodeElement.Children.end(); ++el_it) {
|
||||
if (((*el_it)->Type == X3DElemType::ENET_MetaBoolean) || ((*el_it)->Type == X3DElemType::ENET_MetaDouble) ||
|
||||
((*el_it)->Type == X3DElemType::ENET_MetaFloat) || ((*el_it)->Type == X3DElemType::ENET_MetaInteger) ||
|
||||
((*el_it)->Type == X3DElemType::ENET_MetaString)) {
|
||||
pList.push_back(*el_it);
|
||||
} else if ((*el_it)->Type == X3DElemType::ENET_MetaSet) {
|
||||
PostprocessHelper_CollectMetadata(**el_it, pList);
|
||||
}
|
||||
} // for(std::list<X3DNodeElementBase*>::const_iterator el_it = pNodeElement.Children.begin(); el_it != pNodeElement.Children.end(); el_it++)
|
||||
}
|
||||
|
||||
bool X3DImporter::PostprocessHelper_ElementIsMetadata(const X3DElemType pType) const {
|
||||
if ((pType == X3DElemType::ENET_MetaBoolean) || (pType == X3DElemType::ENET_MetaDouble) ||
|
||||
(pType == X3DElemType::ENET_MetaFloat) || (pType == X3DElemType::ENET_MetaInteger) ||
|
||||
(pType == X3DElemType::ENET_MetaString) || (pType == X3DElemType::ENET_MetaSet)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool X3DImporter::PostprocessHelper_ElementIsMesh(const X3DElemType pType) const {
|
||||
if ((pType == X3DElemType::ENET_Arc2D) || (pType == X3DElemType::ENET_ArcClose2D) ||
|
||||
(pType == X3DElemType::ENET_Box) || (pType == X3DElemType::ENET_Circle2D) ||
|
||||
(pType == X3DElemType::ENET_Cone) || (pType == X3DElemType::ENET_Cylinder) ||
|
||||
(pType == X3DElemType::ENET_Disk2D) || (pType == X3DElemType::ENET_ElevationGrid) ||
|
||||
(pType == X3DElemType::ENET_Extrusion) || (pType == X3DElemType::ENET_IndexedFaceSet) ||
|
||||
(pType == X3DElemType::ENET_IndexedLineSet) || (pType == X3DElemType::ENET_IndexedTriangleFanSet) ||
|
||||
(pType == X3DElemType::ENET_IndexedTriangleSet) || (pType == X3DElemType::ENET_IndexedTriangleStripSet) ||
|
||||
(pType == X3DElemType::ENET_PointSet) || (pType == X3DElemType::ENET_LineSet) ||
|
||||
(pType == X3DElemType::ENET_Polyline2D) || (pType == X3DElemType::ENET_Polypoint2D) ||
|
||||
(pType == X3DElemType::ENET_Rectangle2D) || (pType == X3DElemType::ENET_Sphere) ||
|
||||
(pType == X3DElemType::ENET_TriangleFanSet) || (pType == X3DElemType::ENET_TriangleSet) ||
|
||||
(pType == X3DElemType::ENET_TriangleSet2D) || (pType == X3DElemType::ENET_TriangleStripSet)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void X3DImporter::Postprocess_BuildLight(const X3DNodeElementBase &pNodeElement, std::list<aiLight *> &pSceneLightList) const {
|
||||
const X3DNodeElementLight &ne = *((X3DNodeElementLight *)&pNodeElement);
|
||||
aiMatrix4x4 transform_matr = PostprocessHelper_Matrix_GlobalToCurrent();
|
||||
aiLight *new_light = new aiLight;
|
||||
|
||||
new_light->mName = ne.ID;
|
||||
new_light->mColorAmbient = ne.Color * ne.AmbientIntensity;
|
||||
new_light->mColorDiffuse = ne.Color * ne.Intensity;
|
||||
new_light->mColorSpecular = ne.Color * ne.Intensity;
|
||||
switch (pNodeElement.Type) {
|
||||
case X3DElemType::ENET_DirectionalLight:
|
||||
new_light->mType = aiLightSource_DIRECTIONAL;
|
||||
new_light->mDirection = ne.Direction, new_light->mDirection *= transform_matr;
|
||||
|
||||
break;
|
||||
case X3DElemType::ENET_PointLight:
|
||||
new_light->mType = aiLightSource_POINT;
|
||||
new_light->mPosition = ne.Location, new_light->mPosition *= transform_matr;
|
||||
new_light->mAttenuationConstant = ne.Attenuation.x;
|
||||
new_light->mAttenuationLinear = ne.Attenuation.y;
|
||||
new_light->mAttenuationQuadratic = ne.Attenuation.z;
|
||||
|
||||
break;
|
||||
case X3DElemType::ENET_SpotLight:
|
||||
new_light->mType = aiLightSource_SPOT;
|
||||
new_light->mPosition = ne.Location, new_light->mPosition *= transform_matr;
|
||||
new_light->mDirection = ne.Direction, new_light->mDirection *= transform_matr;
|
||||
new_light->mAttenuationConstant = ne.Attenuation.x;
|
||||
new_light->mAttenuationLinear = ne.Attenuation.y;
|
||||
new_light->mAttenuationQuadratic = ne.Attenuation.z;
|
||||
new_light->mAngleInnerCone = ne.BeamWidth;
|
||||
new_light->mAngleOuterCone = ne.CutOffAngle;
|
||||
|
||||
break;
|
||||
default:
|
||||
throw DeadlyImportError("Postprocess_BuildLight. Unknown type of light: " + ai_to_string(pNodeElement.Type) + ".");
|
||||
}
|
||||
|
||||
pSceneLightList.push_back(new_light);
|
||||
}
|
||||
|
||||
void X3DImporter::Postprocess_BuildMaterial(const X3DNodeElementBase &pNodeElement, aiMaterial **pMaterial) const {
|
||||
// check argument
|
||||
if (pMaterial == nullptr) throw DeadlyImportError("Postprocess_BuildMaterial. pMaterial is nullptr.");
|
||||
if (*pMaterial != nullptr) throw DeadlyImportError("Postprocess_BuildMaterial. *pMaterial must be nullptr.");
|
||||
|
||||
*pMaterial = new aiMaterial;
|
||||
aiMaterial &taimat = **pMaterial; // creating alias for convenience.
|
||||
|
||||
// at this point pNodeElement point to <Appearance> node. Walk through childs and add all stored data.
|
||||
for (std::list<X3DNodeElementBase *>::const_iterator el_it = pNodeElement.Children.begin(); el_it != pNodeElement.Children.end(); ++el_it) {
|
||||
if ((*el_it)->Type == X3DElemType::ENET_Material) {
|
||||
aiColor3D tcol3;
|
||||
float tvalf;
|
||||
X3DNodeElementMaterial &tnemat = *((X3DNodeElementMaterial *)*el_it);
|
||||
|
||||
tcol3.r = tnemat.AmbientIntensity, tcol3.g = tnemat.AmbientIntensity, tcol3.b = tnemat.AmbientIntensity;
|
||||
taimat.AddProperty(&tcol3, 1, AI_MATKEY_COLOR_AMBIENT);
|
||||
taimat.AddProperty(&tnemat.DiffuseColor, 1, AI_MATKEY_COLOR_DIFFUSE);
|
||||
taimat.AddProperty(&tnemat.EmissiveColor, 1, AI_MATKEY_COLOR_EMISSIVE);
|
||||
taimat.AddProperty(&tnemat.SpecularColor, 1, AI_MATKEY_COLOR_SPECULAR);
|
||||
tvalf = 1;
|
||||
taimat.AddProperty(&tvalf, 1, AI_MATKEY_SHININESS_STRENGTH);
|
||||
taimat.AddProperty(&tnemat.Shininess, 1, AI_MATKEY_SHININESS);
|
||||
tvalf = 1.0f - tnemat.Transparency;
|
||||
taimat.AddProperty(&tvalf, 1, AI_MATKEY_OPACITY);
|
||||
} // if((*el_it)->Type == X3DElemType::ENET_Material)
|
||||
else if ((*el_it)->Type == X3DElemType::ENET_ImageTexture) {
|
||||
X3DNodeElementImageTexture &tnetex = *((X3DNodeElementImageTexture *)*el_it);
|
||||
aiString url_str(tnetex.URL.c_str());
|
||||
int mode = aiTextureOp_Multiply;
|
||||
|
||||
taimat.AddProperty(&url_str, AI_MATKEY_TEXTURE_DIFFUSE(0));
|
||||
taimat.AddProperty(&tnetex.RepeatS, 1, AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0));
|
||||
taimat.AddProperty(&tnetex.RepeatT, 1, AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0));
|
||||
taimat.AddProperty(&mode, 1, AI_MATKEY_TEXOP_DIFFUSE(0));
|
||||
} // else if((*el_it)->Type == X3DElemType::ENET_ImageTexture)
|
||||
else if ((*el_it)->Type == X3DElemType::ENET_TextureTransform) {
|
||||
aiUVTransform trans;
|
||||
X3DNodeElementTextureTransform &tnetextr = *((X3DNodeElementTextureTransform *)*el_it);
|
||||
|
||||
trans.mTranslation = tnetextr.Translation - tnetextr.Center;
|
||||
trans.mScaling = tnetextr.Scale;
|
||||
trans.mRotation = tnetextr.Rotation;
|
||||
taimat.AddProperty(&trans, 1, AI_MATKEY_UVTRANSFORM_DIFFUSE(0));
|
||||
} // else if((*el_it)->Type == X3DElemType::ENET_TextureTransform)
|
||||
} // for(std::list<X3DNodeElementBase*>::const_iterator el_it = pNodeElement.Children.begin(); el_it != pNodeElement.Children.end(); el_it++)
|
||||
}
|
||||
|
||||
void X3DImporter::Postprocess_BuildMesh(const X3DNodeElementBase &pNodeElement, aiMesh **pMesh) const {
|
||||
// check argument
|
||||
if (pMesh == nullptr) throw DeadlyImportError("Postprocess_BuildMesh. pMesh is nullptr.");
|
||||
if (*pMesh != nullptr) throw DeadlyImportError("Postprocess_BuildMesh. *pMesh must be nullptr.");
|
||||
|
||||
/************************************************************************************************************************************/
|
||||
/************************************************************ Geometry2D ************************************************************/
|
||||
/************************************************************************************************************************************/
|
||||
if ((pNodeElement.Type == X3DElemType::ENET_Arc2D) || (pNodeElement.Type == X3DElemType::ENET_ArcClose2D) ||
|
||||
(pNodeElement.Type == X3DElemType::ENET_Circle2D) || (pNodeElement.Type == X3DElemType::ENET_Disk2D) ||
|
||||
(pNodeElement.Type == X3DElemType::ENET_Polyline2D) || (pNodeElement.Type == X3DElemType::ENET_Polypoint2D) ||
|
||||
(pNodeElement.Type == X3DElemType::ENET_Rectangle2D) || (pNodeElement.Type == X3DElemType::ENET_TriangleSet2D)) {
|
||||
X3DNodeElementGeometry2D &tnemesh = *((X3DNodeElementGeometry2D *)&pNodeElement); // create alias for convenience
|
||||
std::vector<aiVector3D> tarr;
|
||||
|
||||
tarr.reserve(tnemesh.Vertices.size());
|
||||
for (std::list<aiVector3D>::iterator it = tnemesh.Vertices.begin(); it != tnemesh.Vertices.end(); ++it)
|
||||
tarr.push_back(*it);
|
||||
*pMesh = StandardShapes::MakeMesh(tarr, static_cast<unsigned int>(tnemesh.NumIndices)); // create mesh from vertices using Assimp help.
|
||||
|
||||
return; // mesh is build, nothing to do anymore.
|
||||
}
|
||||
/************************************************************************************************************************************/
|
||||
/************************************************************ Geometry3D ************************************************************/
|
||||
/************************************************************************************************************************************/
|
||||
//
|
||||
// Predefined figures
|
||||
//
|
||||
if ((pNodeElement.Type == X3DElemType::ENET_Box) || (pNodeElement.Type == X3DElemType::ENET_Cone) ||
|
||||
(pNodeElement.Type == X3DElemType::ENET_Cylinder) || (pNodeElement.Type == X3DElemType::ENET_Sphere)) {
|
||||
X3DNodeElementGeometry3D &tnemesh = *((X3DNodeElementGeometry3D *)&pNodeElement); // create alias for convenience
|
||||
std::vector<aiVector3D> tarr;
|
||||
|
||||
tarr.reserve(tnemesh.Vertices.size());
|
||||
for (std::list<aiVector3D>::iterator it = tnemesh.Vertices.begin(); it != tnemesh.Vertices.end(); ++it)
|
||||
tarr.push_back(*it);
|
||||
|
||||
*pMesh = StandardShapes::MakeMesh(tarr, static_cast<unsigned int>(tnemesh.NumIndices)); // create mesh from vertices using Assimp help.
|
||||
|
||||
return; // mesh is build, nothing to do anymore.
|
||||
}
|
||||
//
|
||||
// Parametric figures
|
||||
//
|
||||
if (pNodeElement.Type == X3DElemType::ENET_ElevationGrid) {
|
||||
X3DNodeElementElevationGrid &tnemesh = *((X3DNodeElementElevationGrid *)&pNodeElement); // create alias for convenience
|
||||
|
||||
// at first create mesh from existing vertices.
|
||||
*pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIdx, tnemesh.Vertices);
|
||||
// copy additional information from children
|
||||
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||
if ((*ch_it)->Type == X3DElemType::ENET_Color)
|
||||
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
|
||||
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColorRGBA *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_Normal)
|
||||
X3DGeoHelper::add_normal(**pMesh, ((X3DNodeElementNormal *)*ch_it)->Value, tnemesh.NormalPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_TextureCoordinate)
|
||||
X3DGeoHelper::add_tex_coord(**pMesh, ((X3DNodeElementTextureCoordinate *)*ch_it)->Value);
|
||||
else
|
||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of ElevationGrid: " + ai_to_string((*ch_it)->Type) + ".");
|
||||
} // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
|
||||
|
||||
return; // mesh is build, nothing to do anymore.
|
||||
} // if(pNodeElement.Type == X3DElemType::ENET_ElevationGrid)
|
||||
//
|
||||
// Indexed primitives sets
|
||||
//
|
||||
if (pNodeElement.Type == X3DElemType::ENET_IndexedFaceSet) {
|
||||
X3DNodeElementIndexedSet &tnemesh = *((X3DNodeElementIndexedSet *)&pNodeElement); // create alias for convenience
|
||||
|
||||
// at first search for <Coordinate> node and create mesh.
|
||||
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||
if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||
*pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
|
||||
}
|
||||
}
|
||||
|
||||
// copy additional information from children
|
||||
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||
if ((*ch_it)->Type == X3DElemType::ENET_Color)
|
||||
X3DGeoHelper::add_color(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
|
||||
X3DGeoHelper::add_color(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DNodeElementColorRGBA *)*ch_it)->Value,
|
||||
tnemesh.ColorPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||
} // skip because already read when mesh created.
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_Normal)
|
||||
X3DGeoHelper::add_normal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNodeElementNormal *)*ch_it)->Value,
|
||||
tnemesh.NormalPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_TextureCoordinate)
|
||||
X3DGeoHelper::add_tex_coord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DNodeElementTextureCoordinate *)*ch_it)->Value);
|
||||
else
|
||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedFaceSet: " + ai_to_string((*ch_it)->Type) + ".");
|
||||
} // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
|
||||
|
||||
return; // mesh is build, nothing to do anymore.
|
||||
} // if(pNodeElement.Type == X3DElemType::ENET_IndexedFaceSet)
|
||||
|
||||
if (pNodeElement.Type == X3DElemType::ENET_IndexedLineSet) {
|
||||
X3DNodeElementIndexedSet &tnemesh = *((X3DNodeElementIndexedSet *)&pNodeElement); // create alias for convenience
|
||||
|
||||
// at first search for <Coordinate> node and create mesh.
|
||||
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||
if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||
*pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
|
||||
}
|
||||
}
|
||||
|
||||
// copy additional information from children
|
||||
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||
ai_assert(*pMesh);
|
||||
if ((*ch_it)->Type == X3DElemType::ENET_Color)
|
||||
X3DGeoHelper::add_color(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
|
||||
X3DGeoHelper::add_color(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DNodeElementColorRGBA *)*ch_it)->Value,
|
||||
tnemesh.ColorPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||
} // skip because already read when mesh created.
|
||||
else
|
||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedLineSet: " + ai_to_string((*ch_it)->Type) + ".");
|
||||
} // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
|
||||
|
||||
return; // mesh is build, nothing to do anymore.
|
||||
} // if(pNodeElement.Type == X3DElemType::ENET_IndexedLineSet)
|
||||
|
||||
if ((pNodeElement.Type == X3DElemType::ENET_IndexedTriangleSet) ||
|
||||
(pNodeElement.Type == X3DElemType::ENET_IndexedTriangleFanSet) ||
|
||||
(pNodeElement.Type == X3DElemType::ENET_IndexedTriangleStripSet)) {
|
||||
X3DNodeElementIndexedSet &tnemesh = *((X3DNodeElementIndexedSet *)&pNodeElement); // create alias for convenience
|
||||
|
||||
// at first search for <Coordinate> node and create mesh.
|
||||
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||
if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||
*pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
|
||||
}
|
||||
}
|
||||
|
||||
// copy additional information from children
|
||||
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||
ai_assert(*pMesh);
|
||||
if ((*ch_it)->Type == X3DElemType::ENET_Color)
|
||||
X3DGeoHelper::add_color(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
|
||||
X3DGeoHelper::add_color(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((X3DNodeElementColorRGBA *)*ch_it)->Value,
|
||||
tnemesh.ColorPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||
} // skip because already read when mesh created.
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_Normal)
|
||||
X3DGeoHelper::add_normal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNodeElementNormal *)*ch_it)->Value,
|
||||
tnemesh.NormalPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_TextureCoordinate)
|
||||
X3DGeoHelper::add_tex_coord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DNodeElementTextureCoordinate *)*ch_it)->Value);
|
||||
else
|
||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedTriangleSet or IndexedTriangleFanSet, or \
|
||||
IndexedTriangleStripSet: " +
|
||||
ai_to_string((*ch_it)->Type) + ".");
|
||||
} // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
|
||||
|
||||
return; // mesh is build, nothing to do anymore.
|
||||
} // if((pNodeElement.Type == X3DElemType::ENET_IndexedTriangleFanSet) || (pNodeElement.Type == X3DElemType::ENET_IndexedTriangleStripSet))
|
||||
|
||||
if (pNodeElement.Type == X3DElemType::ENET_Extrusion) {
|
||||
X3DNodeElementIndexedSet &tnemesh = *((X3DNodeElementIndexedSet *)&pNodeElement); // create alias for convenience
|
||||
|
||||
*pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, tnemesh.Vertices);
|
||||
|
||||
return; // mesh is build, nothing to do anymore.
|
||||
} // if(pNodeElement.Type == X3DElemType::ENET_Extrusion)
|
||||
|
||||
//
|
||||
// Primitives sets
|
||||
//
|
||||
if (pNodeElement.Type == X3DElemType::ENET_PointSet) {
|
||||
X3DNodeElementSet &tnemesh = *((X3DNodeElementSet *)&pNodeElement); // create alias for convenience
|
||||
|
||||
// at first search for <Coordinate> node and create mesh.
|
||||
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||
if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||
std::vector<aiVector3D> vec_copy;
|
||||
|
||||
vec_copy.reserve(((X3DNodeElementCoordinate *)*ch_it)->Value.size());
|
||||
for (std::list<aiVector3D>::const_iterator it = ((X3DNodeElementCoordinate *)*ch_it)->Value.begin();
|
||||
it != ((X3DNodeElementCoordinate *)*ch_it)->Value.end(); ++it) {
|
||||
vec_copy.push_back(*it);
|
||||
}
|
||||
|
||||
*pMesh = StandardShapes::MakeMesh(vec_copy, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// copy additional information from children
|
||||
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||
ai_assert(*pMesh);
|
||||
if ((*ch_it)->Type == X3DElemType::ENET_Color)
|
||||
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColor *)*ch_it)->Value, true);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
|
||||
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColorRGBA *)*ch_it)->Value, true);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||
} // skip because already read when mesh created.
|
||||
else
|
||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of PointSet: " + ai_to_string((*ch_it)->Type) + ".");
|
||||
} // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
|
||||
|
||||
return; // mesh is build, nothing to do anymore.
|
||||
} // if(pNodeElement.Type == X3DElemType::ENET_PointSet)
|
||||
|
||||
if (pNodeElement.Type == X3DElemType::ENET_LineSet) {
|
||||
X3DNodeElementSet &tnemesh = *((X3DNodeElementSet *)&pNodeElement); // create alias for convenience
|
||||
|
||||
// at first search for <Coordinate> node and create mesh.
|
||||
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||
if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||
*pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
|
||||
}
|
||||
}
|
||||
|
||||
// copy additional information from children
|
||||
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||
ai_assert(*pMesh);
|
||||
if ((*ch_it)->Type == X3DElemType::ENET_Color)
|
||||
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColor *)*ch_it)->Value, true);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
|
||||
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColorRGBA *)*ch_it)->Value, true);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||
} // skip because already read when mesh created.
|
||||
else
|
||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of LineSet: " + ai_to_string((*ch_it)->Type) + ".");
|
||||
} // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
|
||||
|
||||
return; // mesh is build, nothing to do anymore.
|
||||
} // if(pNodeElement.Type == X3DElemType::ENET_LineSet)
|
||||
|
||||
if (pNodeElement.Type == X3DElemType::ENET_TriangleFanSet) {
|
||||
X3DNodeElementSet &tnemesh = *((X3DNodeElementSet *)&pNodeElement); // create alias for convenience
|
||||
|
||||
// at first search for <Coordinate> node and create mesh.
|
||||
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||
if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||
*pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
|
||||
}
|
||||
}
|
||||
|
||||
// copy additional information from children
|
||||
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||
if (nullptr == *pMesh) {
|
||||
break;
|
||||
}
|
||||
if ((*ch_it)->Type == X3DElemType::ENET_Color)
|
||||
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
|
||||
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColorRGBA *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||
} // skip because already read when mesh created.
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_Normal)
|
||||
X3DGeoHelper::add_normal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNodeElementNormal *)*ch_it)->Value,
|
||||
tnemesh.NormalPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_TextureCoordinate)
|
||||
X3DGeoHelper::add_tex_coord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DNodeElementTextureCoordinate *)*ch_it)->Value);
|
||||
else
|
||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeFanSet: " + ai_to_string((*ch_it)->Type) + ".");
|
||||
} // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
|
||||
|
||||
return; // mesh is build, nothing to do anymore.
|
||||
} // if(pNodeElement.Type == X3DElemType::ENET_TriangleFanSet)
|
||||
|
||||
if (pNodeElement.Type == X3DElemType::ENET_TriangleSet) {
|
||||
X3DNodeElementSet &tnemesh = *((X3DNodeElementSet *)&pNodeElement); // create alias for convenience
|
||||
|
||||
// at first search for <Coordinate> node and create mesh.
|
||||
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||
if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||
std::vector<aiVector3D> vec_copy;
|
||||
|
||||
vec_copy.reserve(((X3DNodeElementCoordinate *)*ch_it)->Value.size());
|
||||
for (std::list<aiVector3D>::const_iterator it = ((X3DNodeElementCoordinate *)*ch_it)->Value.begin();
|
||||
it != ((X3DNodeElementCoordinate *)*ch_it)->Value.end(); ++it) {
|
||||
vec_copy.push_back(*it);
|
||||
}
|
||||
|
||||
*pMesh = StandardShapes::MakeMesh(vec_copy, 3);
|
||||
}
|
||||
}
|
||||
|
||||
// copy additional information from children
|
||||
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||
ai_assert(*pMesh);
|
||||
if ((*ch_it)->Type == X3DElemType::ENET_Color)
|
||||
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
|
||||
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColorRGBA *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||
} // skip because already read when mesh created.
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_Normal)
|
||||
X3DGeoHelper::add_normal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNodeElementNormal *)*ch_it)->Value,
|
||||
tnemesh.NormalPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_TextureCoordinate)
|
||||
X3DGeoHelper::add_tex_coord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DNodeElementTextureCoordinate *)*ch_it)->Value);
|
||||
else
|
||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeSet: " + ai_to_string((*ch_it)->Type) + ".");
|
||||
} // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
|
||||
|
||||
return; // mesh is build, nothing to do anymore.
|
||||
} // if(pNodeElement.Type == X3DElemType::ENET_TriangleSet)
|
||||
|
||||
if (pNodeElement.Type == X3DElemType::ENET_TriangleStripSet) {
|
||||
X3DNodeElementSet &tnemesh = *((X3DNodeElementSet *)&pNodeElement); // create alias for convenience
|
||||
|
||||
// at first search for <Coordinate> node and create mesh.
|
||||
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||
if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||
*pMesh = X3DGeoHelper::make_mesh(tnemesh.CoordIndex, ((X3DNodeElementCoordinate *)*ch_it)->Value);
|
||||
}
|
||||
}
|
||||
|
||||
// copy additional information from children
|
||||
for (std::list<X3DNodeElementBase *>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it) {
|
||||
ai_assert(*pMesh);
|
||||
if ((*ch_it)->Type == X3DElemType::ENET_Color)
|
||||
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColor *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_ColorRGBA)
|
||||
X3DGeoHelper::add_color(**pMesh, ((X3DNodeElementColorRGBA *)*ch_it)->Value, tnemesh.ColorPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_Coordinate) {
|
||||
} // skip because already read when mesh created.
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_Normal)
|
||||
X3DGeoHelper::add_normal(**pMesh, tnemesh.CoordIndex, tnemesh.NormalIndex, ((X3DNodeElementNormal *)*ch_it)->Value,
|
||||
tnemesh.NormalPerVertex);
|
||||
else if ((*ch_it)->Type == X3DElemType::ENET_TextureCoordinate)
|
||||
X3DGeoHelper::add_tex_coord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((X3DNodeElementTextureCoordinate *)*ch_it)->Value);
|
||||
else
|
||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TriangleStripSet: " + ai_to_string((*ch_it)->Type) + ".");
|
||||
} // for(std::list<X3DNodeElementBase*>::iterator ch_it = tnemesh.Children.begin(); ch_it != tnemesh.Children.end(); ++ch_it)
|
||||
|
||||
return; // mesh is build, nothing to do anymore.
|
||||
} // if(pNodeElement.Type == X3DElemType::ENET_TriangleStripSet)
|
||||
|
||||
throw DeadlyImportError("Postprocess_BuildMesh. Unknown mesh type: " + ai_to_string(pNodeElement.Type) + ".");
|
||||
}
|
||||
|
||||
void X3DImporter::Postprocess_BuildNode(const X3DNodeElementBase &pNodeElement, aiNode &pSceneNode, std::list<aiMesh *> &pSceneMeshList,
|
||||
std::list<aiMaterial *> &pSceneMaterialList, std::list<aiLight *> &pSceneLightList) const {
|
||||
std::list<X3DNodeElementBase *>::const_iterator chit_begin = pNodeElement.Children.begin();
|
||||
std::list<X3DNodeElementBase *>::const_iterator chit_end = pNodeElement.Children.end();
|
||||
std::list<aiNode *> SceneNode_Child;
|
||||
std::list<unsigned int> SceneNode_Mesh;
|
||||
|
||||
// At first read all metadata
|
||||
Postprocess_CollectMetadata(pNodeElement, pSceneNode);
|
||||
// check if we have deal with grouping node. Which can contain transformation or switch
|
||||
if (pNodeElement.Type == X3DElemType::ENET_Group) {
|
||||
const X3DNodeElementGroup &tne_group = *((X3DNodeElementGroup *)&pNodeElement); // create alias for convenience
|
||||
|
||||
pSceneNode.mTransformation = tne_group.Transformation;
|
||||
if (tne_group.UseChoice) {
|
||||
// If Choice is less than zero or greater than the number of nodes in the children field, nothing is chosen.
|
||||
if ((tne_group.Choice < 0) || ((size_t)tne_group.Choice >= pNodeElement.Children.size())) {
|
||||
chit_begin = pNodeElement.Children.end();
|
||||
chit_end = pNodeElement.Children.end();
|
||||
} else {
|
||||
for (size_t i = 0; i < (size_t)tne_group.Choice; i++)
|
||||
++chit_begin; // forward iterator to chosen node.
|
||||
|
||||
chit_end = chit_begin;
|
||||
++chit_end; // point end iterator to next element after chosen node.
|
||||
}
|
||||
} // if(tne_group.UseChoice)
|
||||
} // if(pNodeElement.Type == X3DElemType::ENET_Group)
|
||||
|
||||
// Reserve memory for fast access and check children.
|
||||
for (std::list<X3DNodeElementBase *>::const_iterator it = chit_begin; it != chit_end; ++it) { // in this loop we do not read metadata because it's already read at begin.
|
||||
if ((*it)->Type == X3DElemType::ENET_Group) {
|
||||
// if child is group then create new node and do recursive call.
|
||||
aiNode *new_node = new aiNode;
|
||||
|
||||
new_node->mName = (*it)->ID;
|
||||
new_node->mParent = &pSceneNode;
|
||||
SceneNode_Child.push_back(new_node);
|
||||
Postprocess_BuildNode(**it, *new_node, pSceneMeshList, pSceneMaterialList, pSceneLightList);
|
||||
} else if ((*it)->Type == X3DElemType::ENET_Shape) {
|
||||
// shape can contain only one geometry and one appearance nodes.
|
||||
Postprocess_BuildShape(*((X3DNodeElementShape *)*it), SceneNode_Mesh, pSceneMeshList, pSceneMaterialList);
|
||||
} else if (((*it)->Type == X3DElemType::ENET_DirectionalLight) || ((*it)->Type == X3DElemType::ENET_PointLight) ||
|
||||
((*it)->Type == X3DElemType::ENET_SpotLight)) {
|
||||
Postprocess_BuildLight(*((X3DNodeElementLight *)*it), pSceneLightList);
|
||||
} else if (!PostprocessHelper_ElementIsMetadata((*it)->Type)) // skip metadata
|
||||
{
|
||||
throw DeadlyImportError("Postprocess_BuildNode. Unknown type: " + ai_to_string((*it)->Type) + ".");
|
||||
}
|
||||
} // for(std::list<X3DNodeElementBase*>::const_iterator it = chit_begin; it != chit_end; it++)
|
||||
|
||||
// copy data about children and meshes to aiNode.
|
||||
if (!SceneNode_Child.empty()) {
|
||||
std::list<aiNode *>::const_iterator it = SceneNode_Child.begin();
|
||||
|
||||
pSceneNode.mNumChildren = static_cast<unsigned int>(SceneNode_Child.size());
|
||||
pSceneNode.mChildren = new aiNode *[pSceneNode.mNumChildren];
|
||||
for (size_t i = 0; i < pSceneNode.mNumChildren; i++)
|
||||
pSceneNode.mChildren[i] = *it++;
|
||||
}
|
||||
|
||||
if (!SceneNode_Mesh.empty()) {
|
||||
std::list<unsigned int>::const_iterator it = SceneNode_Mesh.begin();
|
||||
|
||||
pSceneNode.mNumMeshes = static_cast<unsigned int>(SceneNode_Mesh.size());
|
||||
pSceneNode.mMeshes = new unsigned int[pSceneNode.mNumMeshes];
|
||||
for (size_t i = 0; i < pSceneNode.mNumMeshes; i++)
|
||||
pSceneNode.mMeshes[i] = *it++;
|
||||
}
|
||||
|
||||
// that's all. return to previous deals
|
||||
}
|
||||
|
||||
void X3DImporter::Postprocess_BuildShape(const X3DNodeElementShape &pShapeNodeElement, std::list<unsigned int> &pNodeMeshInd,
|
||||
std::list<aiMesh *> &pSceneMeshList, std::list<aiMaterial *> &pSceneMaterialList) const {
|
||||
aiMaterial *tmat = nullptr;
|
||||
aiMesh *tmesh = nullptr;
|
||||
X3DElemType mesh_type = X3DElemType::ENET_Invalid;
|
||||
unsigned int mat_ind = 0;
|
||||
|
||||
for (std::list<X3DNodeElementBase *>::const_iterator it = pShapeNodeElement.Children.begin(); it != pShapeNodeElement.Children.end(); ++it) {
|
||||
if (PostprocessHelper_ElementIsMesh((*it)->Type)) {
|
||||
Postprocess_BuildMesh(**it, &tmesh);
|
||||
if (tmesh != nullptr) {
|
||||
// if mesh successfully built then add data about it to arrays
|
||||
pNodeMeshInd.push_back(static_cast<unsigned int>(pSceneMeshList.size()));
|
||||
pSceneMeshList.push_back(tmesh);
|
||||
// keep mesh type. Need above for texture coordinate generation.
|
||||
mesh_type = (*it)->Type;
|
||||
}
|
||||
} else if ((*it)->Type == X3DElemType::ENET_Appearance) {
|
||||
Postprocess_BuildMaterial(**it, &tmat);
|
||||
if (tmat != nullptr) {
|
||||
// if material successfully built then add data about it to array
|
||||
mat_ind = static_cast<unsigned int>(pSceneMaterialList.size());
|
||||
pSceneMaterialList.push_back(tmat);
|
||||
}
|
||||
}
|
||||
} // for(std::list<X3DNodeElementBase*>::const_iterator it = pShapeNodeElement.Children.begin(); it != pShapeNodeElement.Children.end(); it++)
|
||||
|
||||
// associate read material with read mesh.
|
||||
if ((tmesh != nullptr) && (tmat != nullptr)) {
|
||||
tmesh->mMaterialIndex = mat_ind;
|
||||
// Check texture mapping. If material has texture but mesh has no texture coordinate then try to ask Assimp to generate texture coordinates.
|
||||
if ((tmat->GetTextureCount(aiTextureType_DIFFUSE) != 0) && !tmesh->HasTextureCoords(0)) {
|
||||
int32_t tm;
|
||||
aiVector3D tvec3;
|
||||
|
||||
switch (mesh_type) {
|
||||
case X3DElemType::ENET_Box:
|
||||
tm = aiTextureMapping_BOX;
|
||||
break;
|
||||
case X3DElemType::ENET_Cone:
|
||||
case X3DElemType::ENET_Cylinder:
|
||||
tm = aiTextureMapping_CYLINDER;
|
||||
break;
|
||||
case X3DElemType::ENET_Sphere:
|
||||
tm = aiTextureMapping_SPHERE;
|
||||
break;
|
||||
default:
|
||||
tm = aiTextureMapping_PLANE;
|
||||
break;
|
||||
} // switch(mesh_type)
|
||||
|
||||
tmat->AddProperty(&tm, 1, AI_MATKEY_MAPPING_DIFFUSE(0));
|
||||
} // if((tmat->GetTextureCount(aiTextureType_DIFFUSE) != 0) && !tmesh->HasTextureCoords(0))
|
||||
} // if((tmesh != nullptr) && (tmat != nullptr))
|
||||
}
|
||||
|
||||
void X3DImporter::Postprocess_CollectMetadata(const X3DNodeElementBase &pNodeElement, aiNode &pSceneNode) const {
|
||||
std::list<X3DNodeElementBase *> meta_list;
|
||||
size_t meta_idx;
|
||||
|
||||
PostprocessHelper_CollectMetadata(pNodeElement, meta_list); // find metadata in current node element.
|
||||
if (!meta_list.empty()) {
|
||||
if (pSceneNode.mMetaData != nullptr) {
|
||||
throw DeadlyImportError("Postprocess. MetaData member in node are not nullptr. Something went wrong.");
|
||||
}
|
||||
|
||||
// copy collected metadata to output node.
|
||||
pSceneNode.mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(meta_list.size()));
|
||||
meta_idx = 0;
|
||||
for (std::list<X3DNodeElementBase *>::const_iterator it = meta_list.begin(); it != meta_list.end(); ++it, ++meta_idx) {
|
||||
X3DNodeElementMeta *cur_meta = (X3DNodeElementMeta *)*it;
|
||||
|
||||
// due to limitations we can add only first element of value list.
|
||||
// Add an element according to its type.
|
||||
if ((*it)->Type == X3DElemType::ENET_MetaBoolean) {
|
||||
if (((X3DNodeElementMetaBoolean *)cur_meta)->Value.size() > 0)
|
||||
pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, *(((X3DNodeElementMetaBoolean *)cur_meta)->Value.begin()) == true);
|
||||
} else if ((*it)->Type == X3DElemType::ENET_MetaDouble) {
|
||||
if (((X3DNodeElementMetaDouble *)cur_meta)->Value.size() > 0)
|
||||
pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, (float)*(((X3DNodeElementMetaDouble *)cur_meta)->Value.begin()));
|
||||
} else if ((*it)->Type == X3DElemType::ENET_MetaFloat) {
|
||||
if (((X3DNodeElementMetaFloat *)cur_meta)->Value.size() > 0)
|
||||
pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, *(((X3DNodeElementMetaFloat *)cur_meta)->Value.begin()));
|
||||
} else if ((*it)->Type == X3DElemType::ENET_MetaInteger) {
|
||||
if (((X3DNodeElementMetaInt *)cur_meta)->Value.size() > 0)
|
||||
pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, *(((X3DNodeElementMetaInt *)cur_meta)->Value.begin()));
|
||||
} else if ((*it)->Type == X3DElemType::ENET_MetaString) {
|
||||
if (((X3DNodeElementMetaString *)cur_meta)->Value.size() > 0) {
|
||||
aiString tstr(((X3DNodeElementMetaString *)cur_meta)->Value.begin()->data());
|
||||
|
||||
pSceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx), cur_meta->Name, tstr);
|
||||
}
|
||||
} else {
|
||||
throw DeadlyImportError("Postprocess. Unknown metadata type.");
|
||||
} // if((*it)->Type == X3DElemType::ENET_Meta*) else
|
||||
} // for(std::list<X3DNodeElementBase*>::const_iterator it = meta_list.begin(); it != meta_list.end(); it++)
|
||||
} // if( !meta_list.empty() )
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
993
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Rendering.cpp
Normal file
993
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Rendering.cpp
Normal file
|
|
@ -0,0 +1,993 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
/// \file X3DImporter_Rendering.cpp
|
||||
/// \brief Parsing data from nodes of "Rendering" set of X3D.
|
||||
/// \date 2015-2016
|
||||
/// \author smal.root@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include "X3DImporter_Macro.hpp"
|
||||
#include "X3DXmlHelper.h"
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
// <Color
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// color="" MFColor [inputOutput]
|
||||
// />
|
||||
void X3DImporter::readColor(XmlNode &node) {
|
||||
std::string use, def;
|
||||
std::list<aiColor3D> color;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
X3DXmlHelper::getColor3DListAttribute(node, "color", color);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Color, ne);
|
||||
} else {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementColor(mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
((X3DNodeElementColor *)ne)->Value = color;
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "Color");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <ColorRGBA
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// color="" MFColorRGBA [inputOutput]
|
||||
// />
|
||||
void X3DImporter::readColorRGBA(XmlNode &node) {
|
||||
std::string use, def;
|
||||
std::list<aiColor4D> color;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
X3DXmlHelper::getColor4DListAttribute(node, "color", color);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ColorRGBA, ne);
|
||||
} else {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementColorRGBA(mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
((X3DNodeElementColorRGBA *)ne)->Value = color;
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "ColorRGBA");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <Coordinate
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// point="" MFVec3f [inputOutput]
|
||||
// />
|
||||
void X3DImporter::readCoordinate(XmlNode &node) {
|
||||
std::string use, def;
|
||||
std::list<aiVector3D> point;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
X3DXmlHelper::getVector3DListAttribute(node, "point", point);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Coordinate, ne);
|
||||
} else {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementCoordinate(mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
((X3DNodeElementCoordinate *)ne)->Value = point;
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "Coordinate");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <IndexedLineSet
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// colorIndex="" MFInt32 [initializeOnly]
|
||||
// colorPerVertex="true" SFBool [initializeOnly]
|
||||
// coordIndex="" MFInt32 [initializeOnly]
|
||||
// >
|
||||
// <!-- ColorCoordinateContentModel -->
|
||||
// ColorCoordinateContentModel is the child-node content model corresponding to IndexedLineSet, LineSet and PointSet. ColorCoordinateContentModel can
|
||||
// contain any-order Coordinate node with Color (or ColorRGBA) node. No more than one instance of any single node type is allowed.
|
||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||
// </IndexedLineSet>
|
||||
void X3DImporter::readIndexedLineSet(XmlNode &node) {
|
||||
std::string use, def;
|
||||
std::vector<int32_t> colorIndex;
|
||||
bool colorPerVertex = true;
|
||||
std::vector<int32_t> coordIndex;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
X3DXmlHelper::getInt32ArrayAttribute(node, "colorIndex", colorIndex);
|
||||
XmlParser::getBoolAttribute(node, "colorPerVertex", colorPerVertex);
|
||||
X3DXmlHelper::getInt32ArrayAttribute(node, "coordIndex", coordIndex);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedLineSet, ne);
|
||||
} else {
|
||||
// check data
|
||||
if ((coordIndex.size() < 2) || ((coordIndex.back() == (-1)) && (coordIndex.size() < 3)))
|
||||
throw DeadlyImportError("IndexedLineSet must contain not empty \"coordIndex\" attribute.");
|
||||
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_IndexedLineSet, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
X3DNodeElementIndexedSet &ne_alias = *((X3DNodeElementIndexedSet *)ne);
|
||||
|
||||
ne_alias.ColorIndex = colorIndex;
|
||||
ne_alias.ColorPerVertex = colorPerVertex;
|
||||
ne_alias.CoordIndex = coordIndex;
|
||||
// check for child nodes
|
||||
if (!isNodeEmpty(node)) {
|
||||
ParseHelper_Node_Enter(ne);
|
||||
for (auto currentChildNode : node.children()) {
|
||||
const std::string ¤tChildName = currentChildNode.name();
|
||||
// check for Color and Coordinate nodes
|
||||
if (currentChildName == "Color")
|
||||
readColor(currentChildNode);
|
||||
else if (currentChildName == "ColorRGBA")
|
||||
readColorRGBA(currentChildNode);
|
||||
else if (currentChildName == "Coordinate")
|
||||
readCoordinate(currentChildNode);
|
||||
// check for X3DMetadataObject
|
||||
else if (!checkForMetadataNode(currentChildNode))
|
||||
skipUnsupportedNode("IndexedLineSet", currentChildNode);
|
||||
}
|
||||
ParseHelper_Node_Exit();
|
||||
} // if(!isNodeEmpty(node))
|
||||
else {
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
}
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <IndexedTriangleFanSet
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// ccw="true" SFBool [initializeOnly]
|
||||
// colorPerVertex="true" SFBool [initializeOnly]
|
||||
// index="" MFInt32 [initializeOnly]
|
||||
// normalPerVertex="true" SFBool [initializeOnly]
|
||||
// solid="true" SFBool [initializeOnly]
|
||||
// >
|
||||
// <!-- ComposedGeometryContentModel -->
|
||||
// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
|
||||
// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
|
||||
// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
|
||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||
// </IndexedTriangleFanSet>
|
||||
void X3DImporter::readIndexedTriangleFanSet(XmlNode &node) {
|
||||
std::string use, def;
|
||||
bool ccw = true;
|
||||
bool colorPerVertex = true;
|
||||
std::vector<int32_t> index;
|
||||
bool normalPerVertex = true;
|
||||
bool solid = true;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getBoolAttribute(node, "ccw", ccw);
|
||||
XmlParser::getBoolAttribute(node, "colorPerVertex", colorPerVertex);
|
||||
X3DXmlHelper::getInt32ArrayAttribute(node, "index", index);
|
||||
XmlParser::getBoolAttribute(node, "normalPerVertex", normalPerVertex);
|
||||
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleFanSet, ne);
|
||||
} else {
|
||||
// check data
|
||||
if (index.size() == 0) throw DeadlyImportError("IndexedTriangleFanSet must contain not empty \"index\" attribute.");
|
||||
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_IndexedTriangleFanSet, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
X3DNodeElementIndexedSet &ne_alias = *((X3DNodeElementIndexedSet *)ne);
|
||||
|
||||
ne_alias.CCW = ccw;
|
||||
ne_alias.ColorPerVertex = colorPerVertex;
|
||||
ne_alias.NormalPerVertex = normalPerVertex;
|
||||
ne_alias.Solid = solid;
|
||||
|
||||
ne_alias.CoordIndex.clear();
|
||||
int counter = 0;
|
||||
int32_t idx[3];
|
||||
for (std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); ++idx_it) {
|
||||
idx[2] = *idx_it;
|
||||
if (idx[2] < 0) {
|
||||
counter = 0;
|
||||
} else {
|
||||
if (counter >= 2) {
|
||||
if (ccw) {
|
||||
ne_alias.CoordIndex.push_back(idx[0]);
|
||||
ne_alias.CoordIndex.push_back(idx[1]);
|
||||
ne_alias.CoordIndex.push_back(idx[2]);
|
||||
} else {
|
||||
ne_alias.CoordIndex.push_back(idx[0]);
|
||||
ne_alias.CoordIndex.push_back(idx[2]);
|
||||
ne_alias.CoordIndex.push_back(idx[1]);
|
||||
}
|
||||
ne_alias.CoordIndex.push_back(-1);
|
||||
idx[1] = idx[2];
|
||||
} else {
|
||||
idx[counter] = idx[2];
|
||||
}
|
||||
++counter;
|
||||
}
|
||||
} // for(std::list<int32_t>::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++)
|
||||
|
||||
// check for child nodes
|
||||
if (!isNodeEmpty(node)) {
|
||||
ParseHelper_Node_Enter(ne);
|
||||
for (auto currentChildNode : node.children()) {
|
||||
const std::string ¤tChildName = currentChildNode.name();
|
||||
// check for X3DComposedGeometryNodes
|
||||
if (currentChildName == "Color")
|
||||
readColor(currentChildNode);
|
||||
else if (currentChildName == "ColorRGBA")
|
||||
readColorRGBA(currentChildNode);
|
||||
else if (currentChildName == "Coordinate")
|
||||
readCoordinate(currentChildNode);
|
||||
else if (currentChildName == "Normal")
|
||||
readNormal(currentChildNode);
|
||||
else if (currentChildName == "TextureCoordinate")
|
||||
readTextureCoordinate(currentChildNode);
|
||||
// check for X3DMetadataObject
|
||||
else if (!checkForMetadataNode(currentChildNode))
|
||||
skipUnsupportedNode("IndexedTriangleFanSet", currentChildNode);
|
||||
}
|
||||
ParseHelper_Node_Exit();
|
||||
} // if(!isNodeEmpty(node))
|
||||
else {
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
}
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <IndexedTriangleSet
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// ccw="true" SFBool [initializeOnly]
|
||||
// colorPerVertex="true" SFBool [initializeOnly]
|
||||
// index="" MFInt32 [initializeOnly]
|
||||
// normalPerVertex="true" SFBool [initializeOnly]
|
||||
// solid="true" SFBool [initializeOnly]
|
||||
// >
|
||||
// <!-- ComposedGeometryContentModel -->
|
||||
// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
|
||||
// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
|
||||
// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
|
||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||
// </IndexedTriangleSet>
|
||||
void X3DImporter::readIndexedTriangleSet(XmlNode &node) {
|
||||
std::string use, def;
|
||||
bool ccw = true;
|
||||
bool colorPerVertex = true;
|
||||
std::vector<int32_t> index;
|
||||
bool normalPerVertex = true;
|
||||
bool solid = true;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getBoolAttribute(node, "ccw", ccw);
|
||||
XmlParser::getBoolAttribute(node, "colorPerVertex", colorPerVertex);
|
||||
X3DXmlHelper::getInt32ArrayAttribute(node, "index", index);
|
||||
XmlParser::getBoolAttribute(node, "normalPerVertex", normalPerVertex);
|
||||
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleSet, ne);
|
||||
} else {
|
||||
// check data
|
||||
if (index.size() == 0) throw DeadlyImportError("IndexedTriangleSet must contain not empty \"index\" attribute.");
|
||||
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_IndexedTriangleSet, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
X3DNodeElementIndexedSet &ne_alias = *((X3DNodeElementIndexedSet *)ne);
|
||||
|
||||
ne_alias.CCW = ccw;
|
||||
ne_alias.ColorPerVertex = colorPerVertex;
|
||||
ne_alias.NormalPerVertex = normalPerVertex;
|
||||
ne_alias.Solid = solid;
|
||||
|
||||
ne_alias.CoordIndex.clear();
|
||||
int counter = 0;
|
||||
int32_t idx[3];
|
||||
for (std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); ++idx_it) {
|
||||
idx[counter++] = *idx_it;
|
||||
if (counter > 2) {
|
||||
counter = 0;
|
||||
if (ccw) {
|
||||
ne_alias.CoordIndex.push_back(idx[0]);
|
||||
ne_alias.CoordIndex.push_back(idx[1]);
|
||||
ne_alias.CoordIndex.push_back(idx[2]);
|
||||
} else {
|
||||
ne_alias.CoordIndex.push_back(idx[0]);
|
||||
ne_alias.CoordIndex.push_back(idx[2]);
|
||||
ne_alias.CoordIndex.push_back(idx[1]);
|
||||
}
|
||||
ne_alias.CoordIndex.push_back(-1);
|
||||
}
|
||||
} // for(std::list<int32_t>::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++)
|
||||
|
||||
// check for child nodes
|
||||
if (!isNodeEmpty(node)) {
|
||||
ParseHelper_Node_Enter(ne);
|
||||
for (auto currentChildNode : node.children()) {
|
||||
const std::string ¤tChildName = currentChildNode.name();
|
||||
// check for X3DComposedGeometryNodes
|
||||
if (currentChildName == "Color")
|
||||
readColor(currentChildNode);
|
||||
else if (currentChildName == "ColorRGBA")
|
||||
readColorRGBA(currentChildNode);
|
||||
else if (currentChildName == "Coordinate")
|
||||
readCoordinate(currentChildNode);
|
||||
else if (currentChildName == "Normal")
|
||||
readNormal(currentChildNode);
|
||||
else if (currentChildName == "TextureCoordinate")
|
||||
readTextureCoordinate(currentChildNode);
|
||||
// check for X3DMetadataObject
|
||||
else if (!checkForMetadataNode(currentChildNode))
|
||||
skipUnsupportedNode("IndexedTriangleSet", currentChildNode);
|
||||
}
|
||||
ParseHelper_Node_Exit();
|
||||
} // if(!isNodeEmpty(node))
|
||||
else {
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
}
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <IndexedTriangleStripSet
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// ccw="true" SFBool [initializeOnly]
|
||||
// colorPerVertex="true" SFBool [initializeOnly]
|
||||
// index="" MFInt32 [initializeOnly]
|
||||
// normalPerVertex="true" SFBool [initializeOnly]
|
||||
// solid="true" SFBool [initializeOnly]
|
||||
// >
|
||||
// <!-- ComposedGeometryContentModel -->
|
||||
// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
|
||||
// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
|
||||
// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
|
||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||
// </IndexedTriangleStripSet>
|
||||
void X3DImporter::readIndexedTriangleStripSet(XmlNode &node) {
|
||||
std::string use, def;
|
||||
bool ccw = true;
|
||||
bool colorPerVertex = true;
|
||||
std::vector<int32_t> index;
|
||||
bool normalPerVertex = true;
|
||||
bool solid = true;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getBoolAttribute(node, "ccw", ccw);
|
||||
XmlParser::getBoolAttribute(node, "colorPerVertex", colorPerVertex);
|
||||
X3DXmlHelper::getInt32ArrayAttribute(node, "index", index);
|
||||
XmlParser::getBoolAttribute(node, "normalPerVertex", normalPerVertex);
|
||||
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_IndexedTriangleStripSet, ne);
|
||||
} else {
|
||||
// check data
|
||||
if (index.empty()) {
|
||||
throw DeadlyImportError("IndexedTriangleStripSet must contain not empty \"index\" attribute.");
|
||||
}
|
||||
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_IndexedTriangleStripSet, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
X3DNodeElementIndexedSet &ne_alias = *((X3DNodeElementIndexedSet *)ne);
|
||||
|
||||
ne_alias.CCW = ccw;
|
||||
ne_alias.ColorPerVertex = colorPerVertex;
|
||||
ne_alias.NormalPerVertex = normalPerVertex;
|
||||
ne_alias.Solid = solid;
|
||||
|
||||
ne_alias.CoordIndex.clear();
|
||||
int counter = 0;
|
||||
int32_t idx[3];
|
||||
for (std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); ++idx_it) {
|
||||
idx[2] = *idx_it;
|
||||
if (idx[2] < 0) {
|
||||
counter = 0;
|
||||
} else {
|
||||
if (counter >= 2) {
|
||||
if (ccw) {
|
||||
ne_alias.CoordIndex.push_back(idx[0]);
|
||||
ne_alias.CoordIndex.push_back(idx[1]);
|
||||
ne_alias.CoordIndex.push_back(idx[2]);
|
||||
} else {
|
||||
ne_alias.CoordIndex.push_back(idx[0]);
|
||||
ne_alias.CoordIndex.push_back(idx[2]);
|
||||
ne_alias.CoordIndex.push_back(idx[1]);
|
||||
}
|
||||
ne_alias.CoordIndex.push_back(-1);
|
||||
}
|
||||
idx[counter & 1] = idx[2];
|
||||
++counter;
|
||||
}
|
||||
} // for(std::list<int32_t>::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++)
|
||||
|
||||
// check for child nodes
|
||||
if (!isNodeEmpty(node)) {
|
||||
ParseHelper_Node_Enter(ne);
|
||||
for (auto currentChildNode : node.children()) {
|
||||
const std::string ¤tChildName = currentChildNode.name();
|
||||
// check for X3DComposedGeometryNodes
|
||||
if (currentChildName == "Color")
|
||||
readColor(currentChildNode);
|
||||
else if (currentChildName == "ColorRGBA")
|
||||
readColorRGBA(currentChildNode);
|
||||
else if (currentChildName == "Coordinate")
|
||||
readCoordinate(currentChildNode);
|
||||
else if (currentChildName == "Normal")
|
||||
readNormal(currentChildNode);
|
||||
else if (currentChildName == "TextureCoordinate")
|
||||
readTextureCoordinate(currentChildNode);
|
||||
// check for X3DMetadataObject
|
||||
else if (!checkForMetadataNode(currentChildNode))
|
||||
skipUnsupportedNode("IndexedTriangleStripSet", currentChildNode);
|
||||
}
|
||||
ParseHelper_Node_Exit();
|
||||
} // if(!isNodeEmpty(node))
|
||||
else {
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
}
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <LineSet
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// vertexCount="" MFInt32 [initializeOnly]
|
||||
// >
|
||||
// <!-- ColorCoordinateContentModel -->
|
||||
// ColorCoordinateContentModel is the child-node content model corresponding to IndexedLineSet, LineSet and PointSet. ColorCoordinateContentModel can
|
||||
// contain any-order Coordinate node with Color (or ColorRGBA) node. No more than one instance of any single node type is allowed.
|
||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||
// </LineSet>
|
||||
void X3DImporter::readLineSet(XmlNode &node) {
|
||||
std::string use, def;
|
||||
std::vector<int32_t> vertexCount;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
X3DXmlHelper::getInt32ArrayAttribute(node, "vertexCount", vertexCount);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_LineSet, ne);
|
||||
} else {
|
||||
// check data
|
||||
if (vertexCount.empty()) {
|
||||
throw DeadlyImportError("LineSet must contain not empty \"vertexCount\" attribute.");
|
||||
}
|
||||
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementSet(X3DElemType::ENET_LineSet, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
X3DNodeElementSet &ne_alias = *((X3DNodeElementSet *)ne);
|
||||
|
||||
ne_alias.VertexCount = vertexCount;
|
||||
// create CoordIdx
|
||||
size_t coord_num = 0;
|
||||
|
||||
ne_alias.CoordIndex.clear();
|
||||
for (std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); ++vc_it) {
|
||||
if (*vc_it < 2) throw DeadlyImportError("LineSet. vertexCount shall be greater than or equal to two.");
|
||||
|
||||
for (int32_t i = 0; i < *vc_it; i++)
|
||||
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num++)); // add vertices indices
|
||||
|
||||
ne_alias.CoordIndex.push_back(-1); // add face delimiter.
|
||||
}
|
||||
|
||||
// check for child nodes
|
||||
if (!isNodeEmpty(node)) {
|
||||
ParseHelper_Node_Enter(ne);
|
||||
for (auto currentChildNode : node.children()) {
|
||||
const std::string ¤tChildName = currentChildNode.name();
|
||||
// check for X3DComposedGeometryNodes
|
||||
if (currentChildName == "Color")
|
||||
readColor(currentChildNode);
|
||||
else if (currentChildName == "ColorRGBA")
|
||||
readColorRGBA(currentChildNode);
|
||||
else if (currentChildName == "Coordinate")
|
||||
readCoordinate(currentChildNode);
|
||||
// check for X3DMetadataObject
|
||||
else if (!checkForMetadataNode(currentChildNode))
|
||||
skipUnsupportedNode("LineSet", currentChildNode);
|
||||
}
|
||||
ParseHelper_Node_Exit();
|
||||
} // if(!isNodeEmpty(node))
|
||||
else {
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
}
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <PointSet
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// >
|
||||
// <!-- ColorCoordinateContentModel -->
|
||||
// ColorCoordinateContentModel is the child-node content model corresponding to IndexedLineSet, LineSet and PointSet. ColorCoordinateContentModel can
|
||||
// contain any-order Coordinate node with Color (or ColorRGBA) node. No more than one instance of any single node type is allowed.
|
||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||
// </PointSet>
|
||||
void X3DImporter::readPointSet(XmlNode &node) {
|
||||
std::string use, def;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_PointSet, ne);
|
||||
} else {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_PointSet, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
// check for child nodes
|
||||
if (!isNodeEmpty(node)) {
|
||||
ParseHelper_Node_Enter(ne);
|
||||
for (auto currentChildNode : node.children()) {
|
||||
const std::string ¤tChildName = currentChildNode.name();
|
||||
// check for X3DComposedGeometryNodes
|
||||
if (currentChildName == "Color")
|
||||
readColor(currentChildNode);
|
||||
else if (currentChildName == "ColorRGBA")
|
||||
readColorRGBA(currentChildNode);
|
||||
else if (currentChildName == "Coordinate")
|
||||
readCoordinate(currentChildNode);
|
||||
// check for X3DMetadataObject
|
||||
else if (!checkForMetadataNode(currentChildNode))
|
||||
skipUnsupportedNode("PointSet", currentChildNode);
|
||||
}
|
||||
ParseHelper_Node_Exit();
|
||||
} // if(!isNodeEmpty(node))
|
||||
else {
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
}
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <TriangleFanSet
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// ccw="true" SFBool [initializeOnly]
|
||||
// colorPerVertex="true" SFBool [initializeOnly]
|
||||
// fanCount="" MFInt32 [inputOutput]
|
||||
// normalPerVertex="true" SFBool [initializeOnly]
|
||||
// solid="true" SFBool [initializeOnly]
|
||||
// >
|
||||
// <!-- ComposedGeometryContentModel -->
|
||||
// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
|
||||
// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
|
||||
// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
|
||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||
// </TriangleFanSet>
|
||||
void X3DImporter::readTriangleFanSet(XmlNode &node) {
|
||||
std::string use, def;
|
||||
bool ccw = true;
|
||||
bool colorPerVertex = true;
|
||||
std::vector<int32_t> fanCount;
|
||||
bool normalPerVertex = true;
|
||||
bool solid = true;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getBoolAttribute(node, "ccw", ccw);
|
||||
XmlParser::getBoolAttribute(node, "colorPerVertex", colorPerVertex);
|
||||
X3DXmlHelper::getInt32ArrayAttribute(node, "fanCount", fanCount);
|
||||
XmlParser::getBoolAttribute(node, "normalPerVertex", normalPerVertex);
|
||||
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleFanSet, ne);
|
||||
} else {
|
||||
// check data
|
||||
if (fanCount.empty()) {
|
||||
throw DeadlyImportError("TriangleFanSet must contain not empty \"fanCount\" attribute.");
|
||||
}
|
||||
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementSet(X3DElemType::ENET_TriangleFanSet, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
X3DNodeElementSet &ne_alias = *((X3DNodeElementSet *)ne);
|
||||
|
||||
ne_alias.CCW = ccw;
|
||||
ne_alias.ColorPerVertex = colorPerVertex;
|
||||
ne_alias.VertexCount = fanCount;
|
||||
ne_alias.NormalPerVertex = normalPerVertex;
|
||||
ne_alias.Solid = solid;
|
||||
// create CoordIdx
|
||||
size_t coord_num_first, coord_num_prev;
|
||||
|
||||
ne_alias.CoordIndex.clear();
|
||||
// assign indices for first triangle
|
||||
coord_num_first = 0;
|
||||
coord_num_prev = 1;
|
||||
for (std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); ++vc_it) {
|
||||
if (*vc_it < 3) throw DeadlyImportError("TriangleFanSet. fanCount shall be greater than or equal to three.");
|
||||
|
||||
for (int32_t vc = 2; vc < *vc_it; vc++) {
|
||||
if (ccw) {
|
||||
// 2 1
|
||||
// 0
|
||||
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_first)); // first vertex is a center and always is [0].
|
||||
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev++));
|
||||
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev));
|
||||
} else {
|
||||
// 1 2
|
||||
// 0
|
||||
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_first)); // first vertex is a center and always is [0].
|
||||
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev + 1));
|
||||
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num_prev++));
|
||||
} // if(ccw) else
|
||||
|
||||
ne_alias.CoordIndex.push_back(-1); // add face delimiter.
|
||||
} // for(int32_t vc = 2; vc < *vc_it; vc++)
|
||||
|
||||
coord_num_prev++; // that index will be center of next fan
|
||||
coord_num_first = coord_num_prev++; // forward to next point - second point of fan
|
||||
} // for(std::list<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
|
||||
// check for child nodes
|
||||
if (!isNodeEmpty(node)) {
|
||||
ParseHelper_Node_Enter(ne);
|
||||
for (auto currentChildNode : node.children()) {
|
||||
const std::string ¤tChildName = currentChildNode.name();
|
||||
// check for X3DComposedGeometryNodes
|
||||
if (currentChildName == "Color")
|
||||
readColor(currentChildNode);
|
||||
else if (currentChildName == "ColorRGBA")
|
||||
readColorRGBA(currentChildNode);
|
||||
else if (currentChildName == "Coordinate")
|
||||
readCoordinate(currentChildNode);
|
||||
else if (currentChildName == "Normal")
|
||||
readNormal(currentChildNode);
|
||||
else if (currentChildName == "TextureCoordinate")
|
||||
readTextureCoordinate(currentChildNode);
|
||||
// check for X3DMetadataObject
|
||||
else if (!checkForMetadataNode(currentChildNode))
|
||||
skipUnsupportedNode("TriangleFanSet", currentChildNode);
|
||||
}
|
||||
ParseHelper_Node_Exit();
|
||||
} // if(!isNodeEmpty(node))
|
||||
else {
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
}
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <TriangleSet
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// ccw="true" SFBool [initializeOnly]
|
||||
// colorPerVertex="true" SFBool [initializeOnly]
|
||||
// normalPerVertex="true" SFBool [initializeOnly]
|
||||
// solid="true" SFBool [initializeOnly]
|
||||
// >
|
||||
// <!-- ComposedGeometryContentModel -->
|
||||
// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
|
||||
// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
|
||||
// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
|
||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||
// </TriangleSet>
|
||||
void X3DImporter::readTriangleSet(XmlNode &node) {
|
||||
std::string use, def;
|
||||
bool ccw = true;
|
||||
bool colorPerVertex = true;
|
||||
bool normalPerVertex = true;
|
||||
bool solid = true;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getBoolAttribute(node, "ccw", ccw);
|
||||
XmlParser::getBoolAttribute(node, "colorPerVertex", colorPerVertex);
|
||||
XmlParser::getBoolAttribute(node, "normalPerVertex", normalPerVertex);
|
||||
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleSet, ne);
|
||||
} else {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementIndexedSet(X3DElemType::ENET_TriangleSet, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
X3DNodeElementSet &ne_alias = *((X3DNodeElementSet *)ne);
|
||||
|
||||
ne_alias.CCW = ccw;
|
||||
ne_alias.ColorPerVertex = colorPerVertex;
|
||||
ne_alias.NormalPerVertex = normalPerVertex;
|
||||
ne_alias.Solid = solid;
|
||||
// check for child nodes
|
||||
if (!isNodeEmpty(node)) {
|
||||
ParseHelper_Node_Enter(ne);
|
||||
for (auto currentChildNode : node.children()) {
|
||||
const std::string ¤tChildName = currentChildNode.name();
|
||||
// check for X3DComposedGeometryNodes
|
||||
if (currentChildName == "Color")
|
||||
readColor(currentChildNode);
|
||||
else if (currentChildName == "ColorRGBA")
|
||||
readColorRGBA(currentChildNode);
|
||||
else if (currentChildName == "Coordinate")
|
||||
readCoordinate(currentChildNode);
|
||||
else if (currentChildName == "Normal")
|
||||
readNormal(currentChildNode);
|
||||
else if (currentChildName == "TextureCoordinate")
|
||||
readTextureCoordinate(currentChildNode);
|
||||
// check for X3DMetadataObject
|
||||
else if (!checkForMetadataNode(currentChildNode))
|
||||
skipUnsupportedNode("TriangleSet", currentChildNode);
|
||||
}
|
||||
ParseHelper_Node_Exit();
|
||||
} // if(!isNodeEmpty(node))
|
||||
else {
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
}
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <TriangleStripSet
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// ccw="true" SFBool [initializeOnly]
|
||||
// colorPerVertex="true" SFBool [initializeOnly]
|
||||
// normalPerVertex="true" SFBool [initializeOnly]
|
||||
// solid="true" SFBool [initializeOnly]
|
||||
// stripCount="" MFInt32 [inputOutput]
|
||||
// >
|
||||
// <!-- ComposedGeometryContentModel -->
|
||||
// ComposedGeometryContentModel is the child-node content model corresponding to X3DComposedGeometryNodes. It can contain Color (or ColorRGBA), Coordinate,
|
||||
// Normal and TextureCoordinate, in any order. No more than one instance of these nodes is allowed. Multiple VertexAttribute (FloatVertexAttribute,
|
||||
// Matrix3VertexAttribute, Matrix4VertexAttribute) nodes can also be contained.
|
||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model.
|
||||
// </TriangleStripSet>
|
||||
void X3DImporter::readTriangleStripSet(XmlNode &node) {
|
||||
std::string use, def;
|
||||
bool ccw = true;
|
||||
bool colorPerVertex = true;
|
||||
std::vector<int32_t> stripCount;
|
||||
bool normalPerVertex = true;
|
||||
bool solid = true;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getBoolAttribute(node, "ccw", ccw);
|
||||
XmlParser::getBoolAttribute(node, "colorPerVertex", colorPerVertex);
|
||||
X3DXmlHelper::getInt32ArrayAttribute(node, "stripCount", stripCount);
|
||||
XmlParser::getBoolAttribute(node, "normalPerVertex", normalPerVertex);
|
||||
XmlParser::getBoolAttribute(node, "solid", solid);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TriangleStripSet, ne);
|
||||
} else {
|
||||
// check data
|
||||
if (stripCount.size() == 0) throw DeadlyImportError("TriangleStripSet must contain not empty \"stripCount\" attribute.");
|
||||
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementSet(X3DElemType::ENET_TriangleStripSet, mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
X3DNodeElementSet &ne_alias = *((X3DNodeElementSet *)ne);
|
||||
|
||||
ne_alias.CCW = ccw;
|
||||
ne_alias.ColorPerVertex = colorPerVertex;
|
||||
ne_alias.VertexCount = stripCount;
|
||||
ne_alias.NormalPerVertex = normalPerVertex;
|
||||
ne_alias.Solid = solid;
|
||||
// create CoordIdx
|
||||
size_t coord_num0, coord_num1, coord_num2; // indices of current triangle
|
||||
bool odd_tri; // sequence of current triangle
|
||||
size_t coord_num_sb; // index of first point of strip
|
||||
|
||||
ne_alias.CoordIndex.clear();
|
||||
coord_num_sb = 0;
|
||||
for (std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); ++vc_it) {
|
||||
if (*vc_it < 3) throw DeadlyImportError("TriangleStripSet. stripCount shall be greater than or equal to three.");
|
||||
|
||||
// set initial values for first triangle
|
||||
coord_num0 = coord_num_sb;
|
||||
coord_num1 = coord_num_sb + 1;
|
||||
coord_num2 = coord_num_sb + 2;
|
||||
odd_tri = true;
|
||||
|
||||
for (int32_t vc = 2; vc < *vc_it; vc++) {
|
||||
if (ccw) {
|
||||
// 0 2
|
||||
// 1
|
||||
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num0));
|
||||
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num1));
|
||||
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num2));
|
||||
} else {
|
||||
// 0 1
|
||||
// 2
|
||||
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num0));
|
||||
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num2));
|
||||
ne_alias.CoordIndex.push_back(static_cast<int32_t>(coord_num1));
|
||||
} // if(ccw) else
|
||||
|
||||
ne_alias.CoordIndex.push_back(-1); // add face delimiter.
|
||||
// prepare values for next triangle
|
||||
if (odd_tri) {
|
||||
coord_num0 = coord_num2;
|
||||
coord_num2++;
|
||||
} else {
|
||||
coord_num1 = coord_num2;
|
||||
coord_num2 = coord_num1 + 1;
|
||||
}
|
||||
|
||||
odd_tri = !odd_tri;
|
||||
coord_num_sb = coord_num2; // that index will be start of next strip
|
||||
} // for(int32_t vc = 2; vc < *vc_it; vc++)
|
||||
} // for(std::list<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
|
||||
// check for child nodes
|
||||
if (!isNodeEmpty(node)) {
|
||||
ParseHelper_Node_Enter(ne);
|
||||
for (auto currentChildNode : node.children()) {
|
||||
const std::string ¤tChildName = currentChildNode.name();
|
||||
// check for X3DComposedGeometryNodes
|
||||
if (currentChildName == "Color")
|
||||
readColor(currentChildNode);
|
||||
else if (currentChildName == "ColorRGBA")
|
||||
readColorRGBA(currentChildNode);
|
||||
else if (currentChildName == "Coordinate")
|
||||
readCoordinate(currentChildNode);
|
||||
else if (currentChildName == "Normal")
|
||||
readNormal(currentChildNode);
|
||||
else if (currentChildName == "TextureCoordinate")
|
||||
readTextureCoordinate(currentChildNode);
|
||||
// check for X3DMetadataObject
|
||||
else if (!checkForMetadataNode(currentChildNode))
|
||||
skipUnsupportedNode("TriangleStripSet", currentChildNode);
|
||||
}
|
||||
ParseHelper_Node_Exit();
|
||||
} // if(!isNodeEmpty(node))
|
||||
else {
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
}
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <Normal
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// vector="" MFVec3f [inputOutput]
|
||||
// />
|
||||
void X3DImporter::readNormal(XmlNode &node) {
|
||||
std::string use, def;
|
||||
std::list<aiVector3D> vector;
|
||||
X3DNodeElementBase *ne=nullptr;
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
X3DXmlHelper::getVector3DListAttribute(node, "vector", vector);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Normal, ne);
|
||||
} else {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementNormal(mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
((X3DNodeElementNormal *)ne)->Value = vector;
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "Normal");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
241
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Shape.cpp
Normal file
241
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Shape.cpp
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
/// \file X3DImporter_Shape.cpp
|
||||
/// \brief Parsing data from nodes of "Shape" set of X3D.
|
||||
/// \date 2015-2016
|
||||
/// \author smal.root@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include "X3DImporter_Macro.hpp"
|
||||
#include "X3DXmlHelper.h"
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
void X3DImporter::readShape(XmlNode &node) {
|
||||
std::string use, def;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Shape, ne);
|
||||
} else {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementShape(mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
// check for child nodes
|
||||
if (!isNodeEmpty(node)) {
|
||||
ParseHelper_Node_Enter(ne);
|
||||
for (auto currentChildNode : node.children()) {
|
||||
const std::string ¤tChildName = currentChildNode.name();
|
||||
// check for appearance node
|
||||
if (currentChildName == "Appearance") readAppearance(currentChildNode);
|
||||
// check for X3DGeometryNodes
|
||||
else if (currentChildName == "Arc2D")
|
||||
readArc2D(currentChildNode);
|
||||
else if (currentChildName == "ArcClose2D")
|
||||
readArcClose2D(currentChildNode);
|
||||
else if (currentChildName == "Circle2D")
|
||||
readCircle2D(currentChildNode);
|
||||
else if (currentChildName == "Disk2D")
|
||||
readDisk2D(currentChildNode);
|
||||
else if (currentChildName == "Polyline2D")
|
||||
readPolyline2D(currentChildNode);
|
||||
else if (currentChildName == "Polypoint2D")
|
||||
readPolypoint2D(currentChildNode);
|
||||
else if (currentChildName == "Rectangle2D")
|
||||
readRectangle2D(currentChildNode);
|
||||
else if (currentChildName == "TriangleSet2D")
|
||||
readTriangleSet2D(currentChildNode);
|
||||
else if (currentChildName == "Box")
|
||||
readBox(currentChildNode);
|
||||
else if (currentChildName == "Cone")
|
||||
readCone(currentChildNode);
|
||||
else if (currentChildName == "Cylinder")
|
||||
readCylinder(currentChildNode);
|
||||
else if (currentChildName == "ElevationGrid")
|
||||
readElevationGrid(currentChildNode);
|
||||
else if (currentChildName == "Extrusion")
|
||||
readExtrusion(currentChildNode);
|
||||
else if (currentChildName == "IndexedFaceSet")
|
||||
readIndexedFaceSet(currentChildNode);
|
||||
else if (currentChildName == "Sphere")
|
||||
readSphere(currentChildNode);
|
||||
else if (currentChildName == "IndexedLineSet")
|
||||
readIndexedLineSet(currentChildNode);
|
||||
else if (currentChildName == "LineSet")
|
||||
readLineSet(currentChildNode);
|
||||
else if (currentChildName == "PointSet")
|
||||
readPointSet(currentChildNode);
|
||||
else if (currentChildName == "IndexedTriangleFanSet")
|
||||
readIndexedTriangleFanSet(currentChildNode);
|
||||
else if (currentChildName == "IndexedTriangleSet")
|
||||
readIndexedTriangleSet(currentChildNode);
|
||||
else if (currentChildName == "IndexedTriangleStripSet")
|
||||
readIndexedTriangleStripSet(currentChildNode);
|
||||
else if (currentChildName == "TriangleFanSet")
|
||||
readTriangleFanSet(currentChildNode);
|
||||
else if (currentChildName == "TriangleSet")
|
||||
readTriangleSet(currentChildNode);
|
||||
// check for X3DMetadataObject
|
||||
else if (!checkForMetadataNode(currentChildNode))
|
||||
skipUnsupportedNode("Shape", currentChildNode);
|
||||
}
|
||||
|
||||
ParseHelper_Node_Exit();
|
||||
} // if (!isNodeEmpty(node))
|
||||
else {
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
}
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <Appearance
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// >
|
||||
// <!-- AppearanceChildContentModel -->
|
||||
// "Child-node content model corresponding to X3DAppearanceChildNode. Appearance can contain FillProperties, LineProperties, Material, any Texture node and
|
||||
// any TextureTransform node, in any order. No more than one instance of these nodes is allowed. Appearance may also contain multiple shaders (ComposedShader,
|
||||
// PackagedShader, ProgramShader).
|
||||
// A ProtoInstance node (with the proper node type) can be substituted for any node in this content model."
|
||||
// </Appearance>
|
||||
void X3DImporter::readAppearance(XmlNode &node) {
|
||||
std::string use, def;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Appearance, ne);
|
||||
} else {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementAppearance(mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
// check for child nodes
|
||||
if (!isNodeEmpty(node)) {
|
||||
ParseHelper_Node_Enter(ne);
|
||||
for (auto currentChildNode : node.children()) {
|
||||
const std::string ¤tChildName = currentChildNode.name();
|
||||
if (currentChildName == "Material")
|
||||
readMaterial(currentChildNode);
|
||||
else if (currentChildName == "ImageTexture")
|
||||
readImageTexture(currentChildNode);
|
||||
else if (currentChildName == "TextureTransform")
|
||||
readTextureTransform(currentChildNode);
|
||||
// check for X3DMetadataObject
|
||||
else if (!checkForMetadataNode(currentChildNode))
|
||||
skipUnsupportedNode("Appearance", currentChildNode);
|
||||
}
|
||||
ParseHelper_Node_Exit();
|
||||
} // if(!isNodeEmpty(node))
|
||||
else {
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
}
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <Material
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// ambientIntensity="0.2" SFFloat [inputOutput]
|
||||
// diffuseColor="0.8 0.8 0.8" SFColor [inputOutput]
|
||||
// emissiveColor="0 0 0" SFColor [inputOutput]
|
||||
// shininess="0.2" SFFloat [inputOutput]
|
||||
// specularColor="0 0 0" SFColor [inputOutput]
|
||||
// transparency="0" SFFloat [inputOutput]
|
||||
// />
|
||||
void X3DImporter::readMaterial(XmlNode &node) {
|
||||
std::string use, def;
|
||||
float ambientIntensity = 0.2f;
|
||||
float shininess = 0.2f;
|
||||
float transparency = 0;
|
||||
aiColor3D diffuseColor(0.8f, 0.8f, 0.8f);
|
||||
aiColor3D emissiveColor(0, 0, 0);
|
||||
aiColor3D specularColor(0, 0, 0);
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getFloatAttribute(node, "ambientIntensity", ambientIntensity);
|
||||
XmlParser::getFloatAttribute(node, "shininess", shininess);
|
||||
XmlParser::getFloatAttribute(node, "transparency", transparency);
|
||||
X3DXmlHelper::getColor3DAttribute(node, "diffuseColor", diffuseColor);
|
||||
X3DXmlHelper::getColor3DAttribute(node, "emissiveColor", emissiveColor);
|
||||
X3DXmlHelper::getColor3DAttribute(node, "specularColor", specularColor);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_Material, ne);
|
||||
} else {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementMaterial(mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
((X3DNodeElementMaterial *)ne)->AmbientIntensity = ambientIntensity;
|
||||
((X3DNodeElementMaterial *)ne)->Shininess = shininess;
|
||||
((X3DNodeElementMaterial *)ne)->Transparency = transparency;
|
||||
((X3DNodeElementMaterial *)ne)->DiffuseColor = diffuseColor;
|
||||
((X3DNodeElementMaterial *)ne)->EmissiveColor = emissiveColor;
|
||||
((X3DNodeElementMaterial *)ne)->SpecularColor = specularColor;
|
||||
// check for child nodes
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "Material");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
179
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Texturing.cpp
Normal file
179
Engine/lib/assimp/code/AssetLib/X3D/X3DImporter_Texturing.cpp
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
Open Asset Import Library (assimp)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2019, assimp team
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the assimp team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the assimp team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
/// \file X3DImporter_Texturing.cpp
|
||||
/// \brief Parsing data from nodes of "Texturing" set of X3D.
|
||||
/// \date 2015-2016
|
||||
/// \author smal.root@gmail.com
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
|
||||
#include "X3DImporter.hpp"
|
||||
#include "X3DImporter_Macro.hpp"
|
||||
#include "X3DXmlHelper.h"
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
// <ImageTexture
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// repeatS="true" SFBool
|
||||
// repeatT="true" SFBool
|
||||
// url="" MFString
|
||||
// />
|
||||
// When the url field contains no values ([]), texturing is disabled.
|
||||
void X3DImporter::readImageTexture(XmlNode &node) {
|
||||
std::string use, def;
|
||||
bool repeatS = true;
|
||||
bool repeatT = true;
|
||||
std::list<std::string> url;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
XmlParser::getBoolAttribute(node, "repeatS", repeatS);
|
||||
XmlParser::getBoolAttribute(node, "repeatT", repeatT);
|
||||
X3DXmlHelper::getStringListAttribute(node, "url", url);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_ImageTexture, ne);
|
||||
} else {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementImageTexture(mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
((X3DNodeElementImageTexture *)ne)->RepeatS = repeatS;
|
||||
((X3DNodeElementImageTexture *)ne)->RepeatT = repeatT;
|
||||
// Attribute "url" can contain list of strings. But we need only one - first.
|
||||
if (!url.empty())
|
||||
((X3DNodeElementImageTexture *)ne)->URL = url.front();
|
||||
else
|
||||
((X3DNodeElementImageTexture *)ne)->URL = "";
|
||||
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "ImageTexture");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <TextureCoordinate
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// point="" MFVec3f [inputOutput]
|
||||
// />
|
||||
void X3DImporter::readTextureCoordinate(XmlNode &node) {
|
||||
std::string use, def;
|
||||
std::list<aiVector2D> point;
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
X3DXmlHelper::getVector2DListAttribute(node, "point", point);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TextureCoordinate, ne);
|
||||
} else {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementTextureCoordinate(mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
((X3DNodeElementTextureCoordinate *)ne)->Value = point;
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "TextureCoordinate");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
// <TextureTransform
|
||||
// DEF="" ID
|
||||
// USE="" IDREF
|
||||
// center="0 0" SFVec2f [inputOutput]
|
||||
// rotation="0" SFFloat [inputOutput]
|
||||
// scale="1 1" SFVec2f [inputOutput]
|
||||
// translation="0 0" SFVec2f [inputOutput]
|
||||
// />
|
||||
void X3DImporter::readTextureTransform(XmlNode &node) {
|
||||
std::string use, def;
|
||||
aiVector2D center(0, 0);
|
||||
float rotation = 0;
|
||||
aiVector2D scale(1, 1);
|
||||
aiVector2D translation(0, 0);
|
||||
X3DNodeElementBase *ne(nullptr);
|
||||
|
||||
MACRO_ATTRREAD_CHECKUSEDEF_RET(node, def, use);
|
||||
X3DXmlHelper::getVector2DAttribute(node, "center", center);
|
||||
XmlParser::getFloatAttribute(node, "rotation", rotation);
|
||||
X3DXmlHelper::getVector2DAttribute(node, "scale", scale);
|
||||
X3DXmlHelper::getVector2DAttribute(node, "translation", translation);
|
||||
|
||||
// if "USE" defined then find already defined element.
|
||||
if (!use.empty()) {
|
||||
ne = MACRO_USE_CHECKANDAPPLY(node, def, use, ENET_TextureTransform, ne);
|
||||
} else {
|
||||
// create and if needed - define new geometry object.
|
||||
ne = new X3DNodeElementTextureTransform(mNodeElementCur);
|
||||
if (!def.empty()) ne->ID = def;
|
||||
|
||||
((X3DNodeElementTextureTransform *)ne)->Center = center;
|
||||
((X3DNodeElementTextureTransform *)ne)->Rotation = rotation;
|
||||
((X3DNodeElementTextureTransform *)ne)->Scale = scale;
|
||||
((X3DNodeElementTextureTransform *)ne)->Translation = translation;
|
||||
// check for X3DMetadataObject childs.
|
||||
if (!isNodeEmpty(node))
|
||||
childrenReadMetadata(node, ne, "TextureTransform");
|
||||
else
|
||||
mNodeElementCur->Children.push_back(ne); // add made object as child to current element
|
||||
|
||||
NodeElement_List.push_back(ne); // add element to node element list because its a new object in graph
|
||||
} // if(!use.empty()) else
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
|
||||
#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER
|
||||
294
Engine/lib/assimp/code/AssetLib/X3D/X3DXmlHelper.cpp
Normal file
294
Engine/lib/assimp/code/AssetLib/X3D/X3DXmlHelper.cpp
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
#include "X3DXmlHelper.h"
|
||||
#include "X3DImporter.hpp"
|
||||
|
||||
#include <assimp/ParsingUtils.h>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
bool X3DXmlHelper::getColor3DAttribute(XmlNode &node, const char *attributeName, aiColor3D &color) {
|
||||
std::string val;
|
||||
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||
std::vector<std::string> values;
|
||||
tokenize<std::string>(val, values, " ");
|
||||
if (values.size() != 3) {
|
||||
Throw_ConvertFail_Str2ArrF(node.name(), attributeName);
|
||||
return false;
|
||||
}
|
||||
auto it = values.begin();
|
||||
color.r = stof(*it++);
|
||||
color.g = stof(*it++);
|
||||
color.b = stof(*it);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool X3DXmlHelper::getVector2DAttribute(XmlNode &node, const char *attributeName, aiVector2D &color) {
|
||||
std::string val;
|
||||
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||
std::vector<std::string> values;
|
||||
tokenize<std::string>(val, values, " ");
|
||||
if (values.size() != 2) {
|
||||
Throw_ConvertFail_Str2ArrF(node.name(), attributeName);
|
||||
return false;
|
||||
}
|
||||
auto it = values.begin();
|
||||
color.x = stof(*it++);
|
||||
color.y = stof(*it);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool X3DXmlHelper::getVector3DAttribute(XmlNode &node, const char *attributeName, aiVector3D &color) {
|
||||
std::string val;
|
||||
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||
std::vector<std::string> values;
|
||||
tokenize<std::string>(val, values, " ");
|
||||
if (values.size() != 3) {
|
||||
Throw_ConvertFail_Str2ArrF(node.name(), attributeName);
|
||||
return false;
|
||||
}
|
||||
auto it = values.begin();
|
||||
color.x = stof(*it++);
|
||||
color.y = stof(*it++);
|
||||
color.z = stof(*it);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool X3DXmlHelper::getBooleanArrayAttribute(XmlNode &node, const char *attributeName, std::vector<bool> &boolArray) {
|
||||
std::string val;
|
||||
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||
std::vector<std::string> values;
|
||||
tokenize<std::string>(val, values, " ");
|
||||
auto it = values.begin();
|
||||
while (it != values.end()) {
|
||||
auto s = *it++;
|
||||
if (!s.empty())
|
||||
boolArray.push_back(s[0] == 't' || s[0] == '1');
|
||||
else
|
||||
Throw_ConvertFail_Str2ArrB(node.name(), attributeName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool X3DXmlHelper::getDoubleArrayAttribute(XmlNode &node, const char *attributeName, std::vector<double> &doubleArray) {
|
||||
std::string val;
|
||||
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||
std::vector<std::string> values;
|
||||
tokenize<std::string>(val, values, " ");
|
||||
auto it = values.begin();
|
||||
while (it != values.end()) {
|
||||
auto s = *it++;
|
||||
if (!s.empty())
|
||||
doubleArray.push_back(atof(s.c_str()));
|
||||
else
|
||||
Throw_ConvertFail_Str2ArrD(node.name(), attributeName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool X3DXmlHelper::getFloatArrayAttribute(XmlNode &node, const char *attributeName, std::vector<float> &floatArray) {
|
||||
std::string val;
|
||||
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||
std::vector<std::string> values;
|
||||
tokenize<std::string>(val, values, " ");
|
||||
auto it = values.begin();
|
||||
while (it != values.end()) {
|
||||
auto s = *it++;
|
||||
if (!s.empty())
|
||||
floatArray.push_back((float)atof(s.c_str()));
|
||||
else
|
||||
Throw_ConvertFail_Str2ArrF(node.name(), attributeName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool X3DXmlHelper::getInt32ArrayAttribute(XmlNode &node, const char *attributeName, std::vector<int32_t> &intArray) {
|
||||
std::string val;
|
||||
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||
std::vector<std::string> values;
|
||||
tokenize<std::string>(val, values, " ");
|
||||
auto it = values.begin();
|
||||
while (it != values.end()) {
|
||||
auto s = *it++;
|
||||
if (!s.empty())
|
||||
intArray.push_back((int32_t)atof(s.c_str()));
|
||||
else
|
||||
Throw_ConvertFail_Str2ArrI(node.name(), attributeName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool X3DXmlHelper::getStringListAttribute(XmlNode &node, const char *attributeName, std::list<std::string> &stringList) {
|
||||
std::string val;
|
||||
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||
std::vector<std::string> values;
|
||||
tokenize<std::string>(val, values, " ");
|
||||
auto it = values.begin();
|
||||
std::string currentConcat = "";
|
||||
bool inQuotes = false;
|
||||
while (it != values.end()) {
|
||||
auto s = *it++;
|
||||
if (!s.empty()) {
|
||||
if (inQuotes) {
|
||||
if (*(s.rbegin()) == '"') {
|
||||
stringList.push_back(currentConcat + s.substr(0, s.length() - 1));
|
||||
currentConcat = "";
|
||||
inQuotes = false;
|
||||
} else {
|
||||
currentConcat += " " + s;
|
||||
}
|
||||
} else {
|
||||
if (s[0] == '"') {
|
||||
currentConcat = s.substr(1);
|
||||
inQuotes = true;
|
||||
} else {
|
||||
stringList.push_back(s);
|
||||
}
|
||||
}
|
||||
} else if (!inQuotes)
|
||||
Throw_ConvertFail_Str2ArrI(node.name(), attributeName);
|
||||
}
|
||||
if (inQuotes) Throw_ConvertFail_Str2ArrI(node.name(), attributeName);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool X3DXmlHelper::getStringArrayAttribute(XmlNode &node, const char *attributeName, std::vector<std::string> &stringArray) {
|
||||
std::list<std::string> tlist;
|
||||
|
||||
if (getStringListAttribute(node, attributeName, tlist)) {
|
||||
if (!tlist.empty()) {
|
||||
stringArray.reserve(tlist.size());
|
||||
for (std::list<std::string>::iterator it = tlist.begin(); it != tlist.end(); ++it) {
|
||||
stringArray.push_back(*it);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool X3DXmlHelper::getVector2DListAttribute(XmlNode &node, const char *attributeName, std::list<aiVector2D> &vectorList) {
|
||||
std::string val;
|
||||
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||
std::vector<std::string> values;
|
||||
tokenize<std::string>(val, values, " ");
|
||||
if (values.size() % 2) Throw_ConvertFail_Str2ArrF(node.name(), attributeName);
|
||||
auto it = values.begin();
|
||||
while (it != values.end()) {
|
||||
aiVector2D tvec;
|
||||
|
||||
tvec.x = (float)atof((*it++).c_str());
|
||||
tvec.y = (float)atof((*it++).c_str());
|
||||
vectorList.push_back(tvec);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool X3DXmlHelper::getVector2DArrayAttribute(XmlNode &node, const char *attributeName, std::vector<aiVector2D> &vectorArray) {
|
||||
std::list<aiVector2D> tlist;
|
||||
|
||||
if (getVector2DListAttribute(node, attributeName, tlist)) {
|
||||
if (!tlist.empty()) {
|
||||
vectorArray.reserve(tlist.size());
|
||||
for (std::list<aiVector2D>::iterator it = tlist.begin(); it != tlist.end(); ++it) {
|
||||
vectorArray.push_back(*it);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool X3DXmlHelper::getVector3DListAttribute(XmlNode &node, const char *attributeName, std::list<aiVector3D> &vectorList) {
|
||||
std::string val;
|
||||
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||
std::vector<std::string> values;
|
||||
tokenize<std::string>(val, values, " ");
|
||||
if (values.size() % 3 != 0) Throw_ConvertFail_Str2ArrF(node.name(), attributeName);
|
||||
auto it = values.begin();
|
||||
while (it != values.end()) {
|
||||
aiVector3D tvec;
|
||||
|
||||
tvec.x = (float)atof((*it++).c_str());
|
||||
tvec.y = (float)atof((*it++).c_str());
|
||||
tvec.z = (float)atof((*it++).c_str());
|
||||
vectorList.push_back(tvec);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool X3DXmlHelper::getVector3DArrayAttribute(XmlNode &node, const char *attributeName, std::vector<aiVector3D> &vectorArray) {
|
||||
std::list<aiVector3D> tlist;
|
||||
|
||||
if (getVector3DListAttribute(node, attributeName, tlist)) {
|
||||
if (!tlist.empty()) {
|
||||
vectorArray.reserve(tlist.size());
|
||||
for (std::list<aiVector3D>::iterator it = tlist.begin(); it != tlist.end(); ++it) {
|
||||
vectorArray.push_back(*it);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool X3DXmlHelper::getColor3DListAttribute(XmlNode &node, const char *attributeName, std::list<aiColor3D> &colorList) {
|
||||
std::string val;
|
||||
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||
std::vector<std::string> values;
|
||||
tokenize<std::string>(val, values, " ");
|
||||
if (values.size() % 3 != 0) Throw_ConvertFail_Str2ArrF(node.name(), attributeName);
|
||||
auto it = values.begin();
|
||||
while (it != values.end()) {
|
||||
aiColor3D tvec;
|
||||
|
||||
tvec.r = (float)atof((*it++).c_str());
|
||||
tvec.g = (float)atof((*it++).c_str());
|
||||
tvec.b = (float)atof((*it++).c_str());
|
||||
colorList.push_back(tvec);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool X3DXmlHelper::getColor4DListAttribute(XmlNode &node, const char *attributeName, std::list<aiColor4D> &colorList) {
|
||||
std::string val;
|
||||
if (XmlParser::getStdStrAttribute(node, attributeName, val)) {
|
||||
std::vector<std::string> values;
|
||||
tokenize<std::string>(val, values, " ");
|
||||
if (values.size() % 4 != 0) Throw_ConvertFail_Str2ArrF(node.name(), attributeName);
|
||||
auto it = values.begin();
|
||||
while (it != values.end()) {
|
||||
aiColor4D tvec;
|
||||
|
||||
tvec.r = (float)atof((*it++).c_str());
|
||||
tvec.g = (float)atof((*it++).c_str());
|
||||
tvec.b = (float)atof((*it++).c_str());
|
||||
tvec.a = (float)atof((*it++).c_str());
|
||||
colorList.push_back(tvec);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Assimp
|
||||
30
Engine/lib/assimp/code/AssetLib/X3D/X3DXmlHelper.h
Normal file
30
Engine/lib/assimp/code/AssetLib/X3D/X3DXmlHelper.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include <assimp/XmlParser.h>
|
||||
#include <assimp/types.h>
|
||||
#include <list>
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
class X3DXmlHelper {
|
||||
public:
|
||||
static bool getColor3DAttribute(XmlNode &node, const char *attributeName, aiColor3D &color);
|
||||
static bool getVector2DAttribute(XmlNode &node, const char *attributeName, aiVector2D &vector);
|
||||
static bool getVector3DAttribute(XmlNode &node, const char *attributeName, aiVector3D &vector);
|
||||
|
||||
static bool getBooleanArrayAttribute(XmlNode &node, const char *attributeName, std::vector<bool> &boolArray);
|
||||
static bool getDoubleArrayAttribute(XmlNode &node, const char *attributeName, std::vector<double> &doubleArray);
|
||||
static bool getFloatArrayAttribute(XmlNode &node, const char *attributeName, std::vector<float> &floatArray);
|
||||
static bool getInt32ArrayAttribute(XmlNode &node, const char *attributeName, std::vector<int32_t> &intArray);
|
||||
static bool getStringListAttribute(XmlNode &node, const char *attributeName, std::list<std::string> &stringArray);
|
||||
static bool getStringArrayAttribute(XmlNode &node, const char *attributeName, std::vector<std::string> &stringArray);
|
||||
|
||||
static bool getVector2DListAttribute(XmlNode &node, const char *attributeName, std::list<aiVector2D> &vectorList);
|
||||
static bool getVector2DArrayAttribute(XmlNode &node, const char *attributeName, std::vector<aiVector2D> &vectorArray);
|
||||
static bool getVector3DListAttribute(XmlNode &node, const char *attributeName, std::list<aiVector3D> &vectorList);
|
||||
static bool getVector3DArrayAttribute(XmlNode &node, const char *attributeName, std::vector<aiVector3D> &vectorArray);
|
||||
static bool getColor3DListAttribute(XmlNode &node, const char *attributeName, std::list<aiColor3D> &colorList);
|
||||
static bool getColor4DListAttribute(XmlNode &node, const char *attributeName, std::list<aiColor4D> &colorList);
|
||||
};
|
||||
|
||||
} // namespace Assimp
|
||||
Loading…
Add table
Add a link
Reference in a new issue