/*********************************************************************************************************************** * * 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 #include 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& 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(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(color_data.m_dRed); values[1] = static_cast(color_data.m_dGreen); values[2] = static_cast(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( transparency != 1. ? transparency: material_data.m_dAmbientAlpha ); style.material.diffuse[3] = static_cast( transparency != 1. ? transparency : material_data.m_dDiffuseAlpha ); style.material.specular[3] = static_cast( transparency != 1. ? transparency : material_data.m_dSpecularAlpha ); style.material.emissive[3] = static_cast( transparency != 1. ? transparency : material_data.m_dEmissiveAlpha ); style.material.shininess = static_cast( 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 prepare_render_buffer(A3DRiRepresentationItem* ri, const A3DMiscCascadedAttributes* cascaded_attributes) { std::vector 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; } } } }