266 lines
9.0 KiB
C++
266 lines
9.0 KiB
C++
/***********************************************************************************************************************
|
|
*
|
|
* Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc.
|
|
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
|
|
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
|
|
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
|
|
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
|
|
* scope and manner of such use.
|
|
*
|
|
***********************************************************************************************************************/
|
|
|
|
#include "exchange.h"
|
|
#include "he/representation_item.h"
|
|
#include "he/model_file.h"
|
|
|
|
#include <pugixml.hpp>
|
|
#include <iostream>
|
|
|
|
|
|
using Part = he::structure::Part;
|
|
using ModelFile = he::structure::ModelFile;
|
|
|
|
namespace model
|
|
{
|
|
namespace exchange
|
|
{
|
|
int load_model(const std::string& input_file, A3DAsmModelFile*& mdlFile)
|
|
{
|
|
// Declare and initialize the file loading options
|
|
A3DRWParamsLoadData load_params;
|
|
A3D_INITIALIZE_DATA(A3DRWParamsLoadData, load_params);
|
|
load_params.m_sGeneral.m_bReadSolids = true;
|
|
load_params.m_sAssembly.m_bUseRootDirectory = true;
|
|
load_params.m_sAssembly.m_bRootDirRecursive = true;
|
|
load_params.m_sGeneral.m_eReadGeomTessMode = kA3DReadGeomAndTess;
|
|
load_params.m_sTessellation.m_eTessellationLevelOfDetail = kA3DTessLODHigh;
|
|
load_params.m_sGeneral.m_bReadSurfaces = true;
|
|
load_params.m_sMultiEntries.m_bLoadDefault = true;
|
|
|
|
// Pick a file using the standard file open dialog
|
|
// std::string const input_folder{ exchange_data_dir };
|
|
// std::string input_file = input_folder;
|
|
// input_file.append("/catiaV5/CV5_Micro_engine/_micro engine.CATProduct");
|
|
|
|
// Attempt to load the file
|
|
auto const load_status = A3DAsmModelFileLoadFromFile(input_file.c_str(), &load_params, &mdlFile);
|
|
if (A3D_SUCCESS != load_status && A3D_LOAD_MISSING_COMPONENTS != load_status)
|
|
{
|
|
std::cout << "input_file = " << input_file << std::endl;
|
|
std::cout << "ERROR::MODELFILE::FILE_NOT_SUCCESSFULLY_READ: " << load_status << std::endl;
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int collect_leaves(A3DAsmModelFile* model_file, std::vector<Part>& parts)
|
|
{
|
|
ModelFile mdlFile(model_file);
|
|
if (mdlFile.get_status())
|
|
return 1;
|
|
mdlFile.collect(parts);
|
|
return 0;
|
|
}
|
|
|
|
float convert_transparency(const A3DGraphStyleData& sStyle)
|
|
{
|
|
if (sStyle.m_bIsTransparencyDefined)
|
|
return static_cast<float>(sStyle.m_ucTransparency / 255.f);
|
|
return 1.f;
|
|
}
|
|
|
|
bool convert_rgba(A3DInt32 index, glm::vec4& values)
|
|
{
|
|
A3DGraphRgbColorData color_data;
|
|
A3D_INITIALIZE_DATA(A3DGraphRgbColorData, color_data);
|
|
if (A3DGlobalGetGraphRgbColorData(index, &color_data) == A3D_SUCCESS)
|
|
{
|
|
values[0] = static_cast<float>(color_data.m_dRed);
|
|
values[1] = static_cast<float>(color_data.m_dGreen);
|
|
values[2] = static_cast<float>(color_data.m_dBlue);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
utils::properties::style::Graphics convert_material(A3DInt32 index, float transparency)
|
|
{
|
|
A3DGraphMaterialData material_data;
|
|
A3D_INITIALIZE_DATA(A3DGraphMaterialData, material_data);
|
|
utils::properties::style::Graphics style;
|
|
if (A3DGlobalGetGraphMaterialData(index, &material_data) == A3D_SUCCESS)
|
|
{
|
|
if (convert_rgba(material_data.m_uiAmbient, style.material.ambient)
|
|
&& convert_rgba(material_data.m_uiDiffuse, style.material.diffuse)
|
|
&& convert_rgba(material_data.m_uiSpecular, style.material.specular)
|
|
&& convert_rgba(material_data.m_uiEmissive, style.material.emissive))
|
|
{
|
|
style.material.ambient[3] = static_cast<float>( transparency != 1. ? transparency: material_data.m_dAmbientAlpha );
|
|
style.material.diffuse[3] = static_cast<float>( transparency != 1. ? transparency : material_data.m_dDiffuseAlpha );
|
|
style.material.specular[3] = static_cast<float>( transparency != 1. ? transparency : material_data.m_dSpecularAlpha );
|
|
style.material.emissive[3] = static_cast<float>( transparency != 1. ? transparency : material_data.m_dEmissiveAlpha );
|
|
style.material.shininess = static_cast<float>( material_data.m_dShininess );
|
|
style.type = utils::properties::style::Graphics::MATERIAL;
|
|
A3DGlobalGetGraphMaterialData(A3D_DEFAULT_MATERIAL_INDEX, &material_data);
|
|
}
|
|
else
|
|
{
|
|
A3DGlobalGetGraphMaterialData(A3D_DEFAULT_MATERIAL_INDEX, &material_data);
|
|
}
|
|
}
|
|
|
|
return style;
|
|
}
|
|
|
|
utils::properties::style::Graphics convert_style(A3DInt32 style_index)
|
|
{
|
|
utils::properties::style::Graphics style;
|
|
|
|
style.id = style_index;
|
|
|
|
A3DGraphStyleData style_data;
|
|
A3D_INITIALIZE_DATA(A3DGraphStyleData, style_data);
|
|
if (A3DGlobalGetGraphStyleData(style_index, &style_data) != A3D_SUCCESS)
|
|
{
|
|
return style;
|
|
}
|
|
|
|
A3DUns32 index = style_data.m_uiRgbColorIndex;
|
|
if (index == A3D_DEFAULT_COLOR_INDEX)
|
|
{
|
|
return style;
|
|
}
|
|
|
|
if (style_data.m_bMaterial == false)
|
|
{
|
|
if (convert_rgba(index, style.rgba))
|
|
{
|
|
style.type = utils::properties::style::Graphics::RGBA;
|
|
style.rgba[3] = convert_transparency(style_data);
|
|
}
|
|
return style;
|
|
}
|
|
|
|
A3DBool is_texture = false;
|
|
if (A3DGlobalIsMaterialTexture(index, &is_texture) == 0)
|
|
{
|
|
if (is_texture)
|
|
{
|
|
style.type = utils::properties::style::Graphics::TEXTURE;
|
|
}
|
|
else
|
|
{
|
|
style = convert_material(index, convert_transparency(style_data));
|
|
style.id = style_index;
|
|
}
|
|
}
|
|
return style;
|
|
}
|
|
|
|
namespace geometry
|
|
{
|
|
std::vector<utils::geometry::BufferData> prepare_render_buffer(A3DRiRepresentationItem* ri, const A3DMiscCascadedAttributes* cascaded_attributes)
|
|
{
|
|
std::vector<utils::geometry::BufferData> buffer_data_array;
|
|
he::geometry::RepresentationItem rep_item(ri, cascaded_attributes);
|
|
if (rep_item.get_status() != 0)
|
|
return buffer_data_array;
|
|
rep_item.prepare_render_buffer(buffer_data_array);
|
|
return buffer_data_array;
|
|
}
|
|
|
|
}
|
|
namespace tree
|
|
{
|
|
void print_treenode(const A3DTree* tree, const A3DTreeNode* node, pugi::xml_node& xml_parent)
|
|
{
|
|
if (tree == nullptr || node == nullptr)
|
|
return;
|
|
|
|
// Print node data
|
|
pugi::xml_node xml_node = xml_parent.append_child("Node");
|
|
|
|
// name
|
|
A3DUTF8Char* name = nullptr;
|
|
if (A3D_SUCCESS == A3DTreeNodeGetName(node, &name) && name)
|
|
xml_node.append_attribute("name") = name;
|
|
A3DTreeNodeGetName(nullptr, &name);
|
|
|
|
// Print entity data encapsulated by this node
|
|
pugi::xml_node xml_entity = xml_node.append_child("Entity");
|
|
A3DEntity* entity = nullptr;
|
|
if (A3D_SUCCESS == A3DTreeNodeGetEntity(node, &entity) && entity)
|
|
{
|
|
// entity type
|
|
A3DEEntityType type = kA3DTypeUnknown;
|
|
A3DEntityGetType(entity, &type);
|
|
xml_entity.append_attribute("type") = A3DMiscGetEntityTypeMsg(type);
|
|
|
|
// entity persistent id
|
|
A3DRootBaseData root_data;
|
|
A3D_INITIALIZE_DATA(A3DRootBaseData, root_data);
|
|
if (A3D_SUCCESS == A3DRootBaseGet(entity, &root_data))
|
|
if(root_data.m_uiPersistentId != 0)
|
|
xml_entity.append_attribute("persistentUId") = root_data.m_uiPersistentId;
|
|
if(root_data.m_pcPersistentId != nullptr)
|
|
xml_entity.append_attribute("persistentId") = root_data.m_pcPersistentId;
|
|
A3DRootBaseGet(nullptr, &root_data);
|
|
}
|
|
|
|
// Print children nodes recursively
|
|
A3DUns32 children_count;
|
|
A3DTreeNode** child_nodes = nullptr;
|
|
|
|
if (A3D_SUCCESS == A3DTreeNodeGetChildren(tree, node, &children_count, &child_nodes))
|
|
{
|
|
for (size_t i = 0; i < children_count; ++i) {
|
|
print_treenode(tree, child_nodes[i], xml_node);
|
|
}
|
|
}
|
|
A3DTreeNodeGetChildren(nullptr, nullptr, &children_count, &child_nodes);
|
|
}
|
|
|
|
bool print_tree(const A3DAsmModelFile* model, pugi::xml_node& xml_node)
|
|
{
|
|
A3DTree* tree = nullptr;
|
|
if (A3D_SUCCESS != A3DTreeCompute(model, &tree, nullptr))
|
|
return false;
|
|
|
|
A3DTreeNode* node = nullptr;
|
|
if (A3D_SUCCESS != A3DTreeGetRootNode(tree, &node))
|
|
return false;
|
|
|
|
std::cout << "Print model tree" << "\n";
|
|
print_treenode(tree, node, xml_node);
|
|
|
|
A3DTreeCompute(nullptr, &tree, nullptr);
|
|
|
|
return true;
|
|
}
|
|
|
|
void print(const A3DAsmModelFile* model, const std::string& model_file_path, const std::string& model_tree_file_path)
|
|
{
|
|
pugi::xml_document doc;
|
|
try
|
|
{
|
|
// Print model file path
|
|
pugi::xml_node node = doc.append_child("Model");
|
|
node.append_attribute("path") = model_file_path.c_str();
|
|
// Print tree
|
|
print_tree( model, node);
|
|
// Save tree in output file
|
|
std::cout << "Saving result: " << doc.save_file(model_tree_file_path.c_str()) << std::endl;
|
|
}
|
|
catch (const std::bad_alloc&)
|
|
{
|
|
std::cout << "std::bad_alloc exception caught\n";
|
|
if (!doc.empty())
|
|
doc.save_file(model_tree_file_path.c_str());
|
|
}
|
|
|
|
std::cout << "The corresponding XSD file is `dump_model_tree.xsd` in `MeshViewer` sample folder." << std::endl;
|
|
}
|
|
}
|
|
|
|
}
|
|
} |