Files
Hoops_Exchange/exchange/exchangesource/MeshViewer/model/exchange.cpp
2025-12-15 23:22:33 +08:00

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;
}
}
}
}