2025.6.1
This commit is contained in:
266
exchange/exchangesource/MeshViewer/model/exchange.cpp
Normal file
266
exchange/exchangesource/MeshViewer/model/exchange.cpp
Normal file
@@ -0,0 +1,266 @@
|
||||
/***********************************************************************************************************************
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
45
exchange/exchangesource/MeshViewer/model/exchange.h
Normal file
45
exchange/exchangesource/MeshViewer/model/exchange.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/***********************************************************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
***********************************************************************************************************************/
|
||||
|
||||
#ifndef EXCHANGE_H
|
||||
#define EXCHANGE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "../utils/properties.h"
|
||||
#include "../utils/geometry.h"
|
||||
#include "he/entity.h"
|
||||
#include "he/part.h"
|
||||
|
||||
namespace model
|
||||
{
|
||||
namespace exchange
|
||||
{
|
||||
namespace geometry
|
||||
{
|
||||
std::vector<utils::geometry::BufferData> prepare_render_buffer(A3DRiRepresentationItem* rep_item, const A3DMiscCascadedAttributes* cascaded_attributes);
|
||||
}
|
||||
|
||||
int load_model(const std::string& input_file, A3DAsmModelFile*& mdlFile);
|
||||
int collect_leaves(A3DAsmModelFile* mdlFile, std::vector<he::structure::Part>& parts);
|
||||
utils::properties::style::Graphics convert_style(A3DInt32 index);
|
||||
|
||||
namespace tree
|
||||
{
|
||||
/*! Dump the model tree in an XML file.
|
||||
* \param[in] model The model to dump.
|
||||
* \param[in] model_file_path The model path.
|
||||
* \param[in] model_tree_file_path The model tree XML file path. */
|
||||
void print(const A3DAsmModelFile* model, const std::string& model_file_path, const std::string& model_tree_file_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // EXCHANGE_H
|
||||
40
exchange/exchangesource/MeshViewer/model/he/entity.cpp
Normal file
40
exchange/exchangesource/MeshViewer/model/he/entity.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
/***********************************************************************************************************************
|
||||
*
|
||||
* 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 "entity.h"
|
||||
|
||||
namespace he
|
||||
{
|
||||
Entity::Entity(A3DMiscCascadedAttributes* attrib) : attributes(attrib) {}
|
||||
Entity::~Entity()
|
||||
{
|
||||
if (attributes)
|
||||
{
|
||||
if (A3DMiscCascadedAttributesDelete(attributes) != A3D_SUCCESS)
|
||||
status = 1;
|
||||
}
|
||||
}
|
||||
std::vector<A3DEntity*> Entity::sub_levels() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
namespace structure
|
||||
{
|
||||
int create_cascaded_attributes(const A3DRootBaseWithGraphics* entity, const A3DMiscCascadedAttributes* parent, A3DMiscCascadedAttributes*& attributes)
|
||||
{
|
||||
if (A3DMiscCascadedAttributesCreate(&attributes) != 0)
|
||||
return 1;
|
||||
if (A3DMiscCascadedAttributesPush(attributes, entity, parent))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
45
exchange/exchangesource/MeshViewer/model/he/entity.h
Normal file
45
exchange/exchangesource/MeshViewer/model/he/entity.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/***********************************************************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
***********************************************************************************************************************/
|
||||
|
||||
#ifndef ENTITY_H
|
||||
#define ENTITY_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <A3DSDKIncludes.h>
|
||||
|
||||
namespace he
|
||||
{
|
||||
namespace structure
|
||||
{
|
||||
int create_cascaded_attributes(const A3DRootBaseWithGraphics* entity, const A3DMiscCascadedAttributes* parent, A3DMiscCascadedAttributes*& attributes);
|
||||
}
|
||||
class Entity
|
||||
{
|
||||
protected:
|
||||
int status = A3D_SUCCESS;
|
||||
A3DMiscCascadedAttributes* attributes = nullptr;
|
||||
|
||||
public:
|
||||
Entity(A3DMiscCascadedAttributes* attributes = nullptr);
|
||||
~Entity();
|
||||
|
||||
int get_status() const {
|
||||
return status;
|
||||
}
|
||||
const A3DMiscCascadedAttributes* get_attributes() const {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
virtual std::vector<A3DEntity*> sub_levels() const;
|
||||
};
|
||||
}
|
||||
#endif // ENTITY_H
|
||||
60
exchange/exchangesource/MeshViewer/model/he/model_file.cpp
Normal file
60
exchange/exchangesource/MeshViewer/model/he/model_file.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
/***********************************************************************************************************************
|
||||
*
|
||||
* 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 "model_file.h"
|
||||
|
||||
#include "part.h"
|
||||
#include "product_occurrence.h"
|
||||
|
||||
namespace he
|
||||
{
|
||||
namespace structure
|
||||
{
|
||||
ModelFile::ModelFile(A3DAsmModelFile* mdlFile)
|
||||
{
|
||||
A3D_INITIALIZE_DATA(A3DAsmModelFileData, data);
|
||||
status = A3DAsmModelFileGet(mdlFile, &data);
|
||||
if (status != A3D_SUCCESS)
|
||||
return;
|
||||
status = A3DMiscCascadedAttributesCreate(&attributes);
|
||||
}
|
||||
|
||||
ModelFile::~ModelFile()
|
||||
{
|
||||
A3DAsmModelFileGet(nullptr, &data);
|
||||
}
|
||||
|
||||
int ModelFile::collect(std::vector<Part>& parts)
|
||||
{
|
||||
if (status)
|
||||
return 1;
|
||||
A3DMiscCascadedAttributes* mdl_attribs = nullptr;
|
||||
A3DMiscCascadedAttributesCreate(&mdl_attribs);
|
||||
|
||||
for (const auto po_entity : sub_levels())
|
||||
{
|
||||
A3DMiscCascadedAttributes* new_attributes = nullptr;
|
||||
if (create_cascaded_attributes(po_entity, mdl_attribs, new_attributes) != 0)
|
||||
return 1;
|
||||
if (A3DMiscCascadedAttributesEntityReferencePush(new_attributes, po_entity, nullptr) != 0)
|
||||
continue;
|
||||
ProductOccurrence po(po_entity, new_attributes);
|
||||
po.collect(parts, nullptr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<A3DEntity*> ModelFile::sub_levels() const
|
||||
{
|
||||
return std::vector<A3DEntity*>(data.m_ppPOccurrences, data.m_ppPOccurrences + data.m_uiPOccurrencesSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
39
exchange/exchangesource/MeshViewer/model/he/model_file.h
Normal file
39
exchange/exchangesource/MeshViewer/model/he/model_file.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/***********************************************************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
***********************************************************************************************************************/
|
||||
|
||||
#ifndef MDL_FILE_H
|
||||
#define MDL_FILE_H
|
||||
|
||||
#include "entity.h"
|
||||
#include "part.h"
|
||||
|
||||
namespace he
|
||||
{
|
||||
namespace structure
|
||||
{
|
||||
class ModelFile : public Entity
|
||||
{
|
||||
A3DAsmModelFileData data;
|
||||
A3DAsmModelFile* entity;
|
||||
|
||||
public:
|
||||
ModelFile(A3DAsmModelFile* mdlFile);
|
||||
~ModelFile();
|
||||
|
||||
const A3DAsmModelFileData& get_data() const {
|
||||
return data;
|
||||
}
|
||||
std::vector<A3DEntity*> sub_levels() const override;
|
||||
int collect(std::vector<Part>& parts);
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif // MDL_FILE_H
|
||||
130
exchange/exchangesource/MeshViewer/model/he/part.cpp
Normal file
130
exchange/exchangesource/MeshViewer/model/he/part.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/***********************************************************************************************************************
|
||||
*
|
||||
* 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 "part.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <A3DSDKIncludes.h>
|
||||
|
||||
namespace he
|
||||
{
|
||||
namespace structure
|
||||
{
|
||||
Part::Part(const Part& other) : Entity(other)
|
||||
{
|
||||
this->entity = other.entity;
|
||||
this->contexts = other.contexts;
|
||||
}
|
||||
Part& Part::operator=(const Part& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
this->entity = other.entity;
|
||||
this->contexts = other.contexts;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
Part::Part(Part&& other) noexcept
|
||||
{
|
||||
this->entity = other.entity;
|
||||
this->contexts = std::move(other.contexts);
|
||||
}
|
||||
Part& Part::operator=(Part&& other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
this->entity = other.entity;
|
||||
this->contexts = std::move(other.contexts);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
Part::Part(A3DAsmPartDefinition* part, const A3DMiscCascadedAttributes* attributes, const glm::mat4& parentPosition) : entity(part)
|
||||
{
|
||||
A3DMiscCascadedAttributesData graphics_data;
|
||||
A3D_INITIALIZE_DATA(A3DMiscCascadedAttributesData, graphics_data);
|
||||
status = A3DMiscCascadedAttributesGet(attributes, &graphics_data);
|
||||
contexts.push_back({ attributes, graphics_data, {parentPosition} });
|
||||
}
|
||||
const A3DAsmPartDefinition* Part::get_entity() const
|
||||
{
|
||||
return entity;
|
||||
}
|
||||
const std::vector<Context>& Part::get_contexts() const
|
||||
{
|
||||
return contexts;
|
||||
}
|
||||
|
||||
std::vector<Context>& Part::grab_contexts()
|
||||
{
|
||||
return contexts;
|
||||
}
|
||||
bool Part::isSame(const A3DAsmPartDefinition* part_def, const A3DMiscCascadedAttributes* graphics, glm::mat4&& position)
|
||||
{
|
||||
if (this->entity != part_def)
|
||||
return false;
|
||||
|
||||
A3DMiscCascadedAttributesData graphics_data;
|
||||
A3D_INITIALIZE_DATA(A3DMiscCascadedAttributesData, graphics_data);
|
||||
status = A3DMiscCascadedAttributesGet(graphics, &graphics_data);
|
||||
if (status != A3D_SUCCESS)
|
||||
return false;
|
||||
|
||||
auto it = std::find_if(
|
||||
contexts.begin(),
|
||||
contexts.end(),
|
||||
[&] (Context& context)
|
||||
{
|
||||
const auto& gpx = std::get<1>(context);
|
||||
auto& positions = std::get<2>(context);
|
||||
if (graphics_data.m_sStyle.m_dWidth != gpx.m_sStyle.m_dWidth || graphics_data.m_sStyle.m_bVPicture != gpx.m_sStyle.m_bVPicture || graphics_data.m_sStyle.m_uiLinePatternIndex != gpx.m_sStyle.m_uiLinePatternIndex || graphics_data.m_sStyle.m_bMaterial != gpx.m_sStyle.m_bMaterial || graphics_data.m_sStyle.m_uiRgbColorIndex != gpx.m_sStyle.m_uiRgbColorIndex || graphics_data.m_sStyle.m_bIsTransparencyDefined != gpx.m_sStyle.m_bIsTransparencyDefined || graphics_data.m_sStyle.m_ucTransparency != gpx.m_sStyle.m_ucTransparency || graphics_data.m_sStyle.m_bSpecialCulling != gpx.m_sStyle.m_bSpecialCulling || graphics_data.m_sStyle.m_bFrontCulling != gpx.m_sStyle.m_bFrontCulling || graphics_data.m_sStyle.m_bBackCulling != gpx.m_sStyle.m_bBackCulling || graphics_data.m_sStyle.m_bNoLight != gpx.m_sStyle.m_bNoLight || graphics_data.m_sStyle.m_eRenderingMode != gpx.m_sStyle.m_eRenderingMode
|
||||
// || graphics_data.m_usLayer != gpx.m_usLayer
|
||||
)
|
||||
{
|
||||
contexts.push_back({ graphics, graphics_data, {position} });
|
||||
return true;
|
||||
}
|
||||
positions.push_back(position);
|
||||
return true;
|
||||
});
|
||||
if (it == contexts.end())
|
||||
contexts.push_back({ graphics, graphics_data, {position} });
|
||||
return true;
|
||||
}
|
||||
void traverse_ri(A3DRiRepresentationItem* ri, std::vector<A3DRiRepresentationItem*>& ri_list)
|
||||
{
|
||||
A3DEEntityType type = kA3DTypeUnknown;
|
||||
A3DEntityGetType(ri, &type);
|
||||
if (type == kA3DTypeRiSet)
|
||||
{
|
||||
A3DRiSetData data;
|
||||
A3D_INITIALIZE_DATA(A3DRiSetData, data);
|
||||
if (A3D_SUCCESS != A3DRiSetGet(ri, &data))
|
||||
return;
|
||||
for (A3DUns32 i = 0; i < data.m_uiRepItemsSize; i++)
|
||||
traverse_ri(data.m_ppRepItems[i], ri_list);
|
||||
}
|
||||
else if(type != kA3DTypeRiPlane)
|
||||
ri_list.push_back(ri);
|
||||
};
|
||||
|
||||
void Part::ri_list(std::vector<A3DRiRepresentationItem*>& ri_list) const
|
||||
{
|
||||
A3DAsmPartDefinitionData data;
|
||||
A3D_INITIALIZE_DATA(A3DAsmPartDefinitionData, data);
|
||||
if (A3D_SUCCESS != A3DAsmPartDefinitionGet(entity, &data) || data.m_uiRepItemsSize == 0)
|
||||
return;
|
||||
for (A3DUns32 i = 0; i < data.m_uiRepItemsSize; i++)
|
||||
traverse_ri(data.m_ppRepItems[i], ri_list);
|
||||
A3DAsmPartDefinitionGet(nullptr, &data);
|
||||
}
|
||||
}
|
||||
}
|
||||
50
exchange/exchangesource/MeshViewer/model/he/part.h
Normal file
50
exchange/exchangesource/MeshViewer/model/he/part.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/***********************************************************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
***********************************************************************************************************************/
|
||||
|
||||
#ifndef PART_H
|
||||
#define PART_H
|
||||
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include <glm/mat4x4.hpp>
|
||||
|
||||
#include "entity.h"
|
||||
|
||||
namespace he
|
||||
{
|
||||
namespace structure
|
||||
{
|
||||
using Context = std::tuple<const A3DMiscCascadedAttributes*, A3DMiscCascadedAttributesData, std::vector<glm::mat4>>;
|
||||
class Part : public Entity
|
||||
{
|
||||
A3DAsmPartDefinition* entity = nullptr;
|
||||
std::vector<Context> contexts;
|
||||
|
||||
public:
|
||||
Part(A3DAsmPartDefinition* part, const A3DMiscCascadedAttributes* attributes, const glm::mat4& parentPosition);
|
||||
~Part() = default;
|
||||
Part(const Part& other);
|
||||
Part& operator=(const Part& other);
|
||||
Part(Part&& other) noexcept;
|
||||
Part& operator=(Part&& other) noexcept;
|
||||
|
||||
public:
|
||||
bool isSame(const A3DAsmPartDefinition* part_def, const A3DMiscCascadedAttributes* graphics, glm::mat4&& position);
|
||||
|
||||
const A3DAsmPartDefinition* get_entity() const;
|
||||
void ri_list(std::vector<A3DRiRepresentationItem*>& ri_list) const;
|
||||
const std::vector<Context>& get_contexts() const;
|
||||
std::vector<Context>& grab_contexts();
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif // PART_H
|
||||
@@ -0,0 +1,227 @@
|
||||
/***********************************************************************************************************************
|
||||
*
|
||||
* 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 "product_occurrence.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <tuple>
|
||||
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <glm/mat4x4.hpp>
|
||||
|
||||
namespace he
|
||||
{
|
||||
namespace structure
|
||||
{
|
||||
ProductOccurrence::ProductOccurrence(const A3DAsmProductOccurrence* entity,
|
||||
A3DMiscCascadedAttributes* attributes) : Entity(attributes)
|
||||
{
|
||||
A3D_INITIALIZE_DATA(A3DAsmProductOccurrenceData, data);
|
||||
status = A3DAsmProductOccurrenceGet(entity, &data);
|
||||
if (status != A3D_SUCCESS)
|
||||
return;
|
||||
|
||||
A3D_INITIALIZE_DATA(A3DMiscCascadedAttributesData, attribute_data);
|
||||
status = A3DMiscCascadedAttributesGet(attributes, &attribute_data);
|
||||
if (status != A3D_SUCCESS)
|
||||
return;
|
||||
}
|
||||
ProductOccurrence::~ProductOccurrence()
|
||||
{
|
||||
status = A3DMiscCascadedAttributesGet(nullptr, &attribute_data);
|
||||
A3DAsmProductOccurrenceGet(nullptr, &data);
|
||||
}
|
||||
|
||||
A3DAsmProductOccurrence* ProductOccurrence::get_reference()
|
||||
{
|
||||
if (data.m_pPrototype)
|
||||
{
|
||||
return data.m_pPrototype;
|
||||
}
|
||||
if (data.m_pExternalData)
|
||||
{
|
||||
return data.m_pExternalData;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
A3DMiscTransformation* ProductOccurrence::get_position()
|
||||
{
|
||||
if (data.m_pLocation)
|
||||
{
|
||||
return data.m_pLocation;
|
||||
}
|
||||
auto reference = get_reference();
|
||||
if (reference)
|
||||
{
|
||||
ProductOccurrence next(reference);
|
||||
return next.get_position();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
A3DAsmPartDefinition* ProductOccurrence::get_partdefinition()
|
||||
{
|
||||
if (data.m_pPart)
|
||||
{
|
||||
return data.m_pPart;
|
||||
}
|
||||
auto reference = get_reference();
|
||||
if (reference)
|
||||
{
|
||||
ProductOccurrence next(reference);
|
||||
return next.get_partdefinition();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
A3DVector3dData cross_product(const A3DVector3dData& X, const A3DVector3dData& Y)
|
||||
{
|
||||
A3DVector3dData Z;
|
||||
Z.m_dX = X.m_dY * Y.m_dZ - X.m_dZ * Y.m_dY;
|
||||
Z.m_dY = X.m_dZ * Y.m_dX - X.m_dX * Y.m_dZ;
|
||||
Z.m_dZ = X.m_dX * Y.m_dY - X.m_dY * Y.m_dX;
|
||||
return Z;
|
||||
}
|
||||
|
||||
int get_glm_matrix(const A3DMiscTransformation* transfo, glm::mat4& matrix_out)
|
||||
{
|
||||
A3DEEntityType type = kA3DTypeUnknown;
|
||||
A3DEntityGetType(transfo, &type);
|
||||
if (type == kA3DTypeMiscCartesianTransformation)
|
||||
{
|
||||
A3DMiscCartesianTransformationData data;
|
||||
A3D_INITIALIZE_DATA(A3DMiscCartesianTransformationData, data);
|
||||
|
||||
if (A3DMiscCartesianTransformationGet(transfo, &data))
|
||||
return 1;
|
||||
const auto sZVector = cross_product(data.m_sXVector, data.m_sYVector);
|
||||
const double dMirror = ( data.m_ucBehaviour & kA3DTransformationMirror ) ? -1. : 1.;
|
||||
double matrix[16];
|
||||
matrix[12] = data.m_sOrigin.m_dX;
|
||||
matrix[13] = data.m_sOrigin.m_dY;
|
||||
matrix[14] = data.m_sOrigin.m_dZ;
|
||||
matrix[15] = 1.;
|
||||
|
||||
matrix[0] = data.m_sXVector.m_dX * data.m_sScale.m_dX;
|
||||
matrix[1] = data.m_sXVector.m_dY * data.m_sScale.m_dX;
|
||||
matrix[2] = data.m_sXVector.m_dZ * data.m_sScale.m_dX;
|
||||
matrix[3] = 0.;
|
||||
|
||||
matrix[4] = data.m_sYVector.m_dX * data.m_sScale.m_dY;
|
||||
matrix[5] = data.m_sYVector.m_dY * data.m_sScale.m_dY;
|
||||
matrix[6] = data.m_sYVector.m_dZ * data.m_sScale.m_dY;
|
||||
matrix[7] = 0.;
|
||||
|
||||
matrix[8] = dMirror * sZVector.m_dX * data.m_sScale.m_dZ;
|
||||
matrix[9] = dMirror * sZVector.m_dY * data.m_sScale.m_dZ;
|
||||
matrix[10] = dMirror * sZVector.m_dZ * data.m_sScale.m_dZ;
|
||||
matrix[11] = 0.;
|
||||
|
||||
matrix_out = glm::make_mat4(matrix);
|
||||
if (A3DMiscCartesianTransformationGet(nullptr, &data))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
glm::mat4 ProductOccurrence::compute_position(const glm::mat4* parent_position)
|
||||
{
|
||||
A3DMiscTransformation* pLocation = get_position();
|
||||
glm::mat4 local_position = glm::mat4(1.f);
|
||||
if (pLocation)
|
||||
get_glm_matrix(pLocation, local_position);
|
||||
if (parent_position)
|
||||
local_position = ( *parent_position ) * local_position;
|
||||
return local_position;
|
||||
}
|
||||
|
||||
int compare(const A3DMiscCascadedAttributesData& data1, const A3DMiscCascadedAttributesData& data2)
|
||||
{
|
||||
return ( data1.m_sStyle.m_dWidth == data2.m_sStyle.m_dWidth
|
||||
&& data1.m_sStyle.m_bVPicture == data2.m_sStyle.m_bVPicture
|
||||
&& data1.m_sStyle.m_uiLinePatternIndex == data2.m_sStyle.m_uiLinePatternIndex
|
||||
&& data1.m_sStyle.m_bMaterial == data2.m_sStyle.m_bMaterial
|
||||
&& data1.m_sStyle.m_uiRgbColorIndex == data2.m_sStyle.m_uiRgbColorIndex
|
||||
&& data1.m_sStyle.m_bIsTransparencyDefined == data2.m_sStyle.m_bIsTransparencyDefined
|
||||
&& data1.m_sStyle.m_ucTransparency == data2.m_sStyle.m_ucTransparency
|
||||
&& data1.m_sStyle.m_bSpecialCulling == data2.m_sStyle.m_bSpecialCulling
|
||||
&& data1.m_sStyle.m_bFrontCulling == data2.m_sStyle.m_bFrontCulling
|
||||
&& data1.m_sStyle.m_bBackCulling == data2.m_sStyle.m_bBackCulling
|
||||
&& data1.m_sStyle.m_bNoLight == data2.m_sStyle.m_bNoLight
|
||||
&& data1.m_sStyle.m_eRenderingMode == data2.m_sStyle.m_eRenderingMode
|
||||
);
|
||||
}
|
||||
void ProductOccurrence::push_part(std::vector<Part>& parts, const glm::mat4& new_position)
|
||||
{
|
||||
auto new_part = get_partdefinition();
|
||||
if (!new_part)
|
||||
return;
|
||||
|
||||
A3DMiscCascadedAttributes* new_attributes;
|
||||
create_cascaded_attributes(new_part, attributes, new_attributes);
|
||||
|
||||
auto it = std::find_if(parts.begin(), parts.end(), [&new_part] (Part& part)
|
||||
{ return part.get_entity() == new_part; });
|
||||
if (it == parts.end())
|
||||
parts.emplace_back(Part(new_part, new_attributes, new_position));
|
||||
else
|
||||
{
|
||||
A3DMiscCascadedAttributesData attrib_data;
|
||||
A3D_INITIALIZE_DATA(A3DMiscCascadedAttributesData, attrib_data);
|
||||
A3DMiscCascadedAttributesGet(new_attributes, &attrib_data);
|
||||
std::vector<Context>& contexes = ( it )->grab_contexts();
|
||||
auto context_it = std::find_if(contexes.begin(), contexes.end(), [&attrib_data] (const Context& context) {
|
||||
const auto& gpx = std::get<1>(context);
|
||||
return compare(attrib_data, gpx);
|
||||
});
|
||||
|
||||
if (context_it == contexes.end())
|
||||
contexes.push_back({ new_attributes, attrib_data, {new_position} });
|
||||
else
|
||||
{
|
||||
auto& positions = std::get<2>(*context_it);
|
||||
positions.push_back(new_position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<A3DEntity*> ProductOccurrence::sub_levels() const
|
||||
{
|
||||
return std::vector<A3DEntity*>(data.m_ppPOccurrences, data.m_ppPOccurrences + data.m_uiPOccurrencesSize);
|
||||
}
|
||||
bool ProductOccurrence::skip() const
|
||||
{
|
||||
return (
|
||||
!attribute_data.m_bShow || attribute_data.m_bRemoved || data.m_ucBehaviour != 1 );
|
||||
}
|
||||
|
||||
int ProductOccurrence::collect(std::vector<Part>& parts, const glm::mat4* parent_position)
|
||||
{
|
||||
auto new_position = compute_position(parent_position);
|
||||
push_part(parts, new_position);
|
||||
|
||||
for (const auto& po_entity : sub_levels())
|
||||
{
|
||||
A3DMiscCascadedAttributes* new_attributes;
|
||||
if (create_cascaded_attributes(po_entity, get_attributes(), new_attributes) != 0)
|
||||
continue;
|
||||
if (A3DMiscCascadedAttributesEntityReferencePush(new_attributes, po_entity, nullptr) != 0)
|
||||
continue;
|
||||
ProductOccurrence po(po_entity, new_attributes);
|
||||
if (po.collect(parts, &new_position))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/***********************************************************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
***********************************************************************************************************************/
|
||||
|
||||
#ifndef PRODUCT_OCCURENCE_H
|
||||
#define PRODUCT_OCCURENCE_H
|
||||
|
||||
#include "entity.h"
|
||||
#include "part.h"
|
||||
|
||||
namespace he
|
||||
{
|
||||
namespace structure
|
||||
{
|
||||
class ProductOccurrence : public Entity
|
||||
{
|
||||
A3DAsmProductOccurrenceData data;
|
||||
A3DMiscCascadedAttributesData attribute_data;
|
||||
|
||||
private:
|
||||
A3DMiscTransformation* get_position();
|
||||
A3DAsmPartDefinition* get_partdefinition();
|
||||
A3DAsmProductOccurrence* get_reference();
|
||||
glm::mat4 compute_position(const glm::mat4* parent_position);
|
||||
void push_part(std::vector<Part>& parts, const glm::mat4& new_position);
|
||||
|
||||
public:
|
||||
ProductOccurrence(const A3DAsmProductOccurrence* asmProductOccurrence,
|
||||
A3DMiscCascadedAttributes* attributes = nullptr);
|
||||
~ProductOccurrence();
|
||||
|
||||
const A3DAsmProductOccurrenceData& get_data() const {
|
||||
return data;
|
||||
}
|
||||
const A3DMiscCascadedAttributesData& get_attribute_data() const {
|
||||
return attribute_data;
|
||||
}
|
||||
std::vector<A3DEntity*> sub_levels() const override;
|
||||
bool skip() const;
|
||||
int collect(std::vector<Part>& parts, const glm::mat4* parent_position);
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif // PRODUCT_OCCURENCE_H
|
||||
@@ -0,0 +1,171 @@
|
||||
/***********************************************************************************************************************
|
||||
*
|
||||
* 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 <map>
|
||||
#include "representation_item.h"
|
||||
#include "../../utils/properties.h"
|
||||
#include "../../utils/bounding_box.h"
|
||||
#include "../../utils/geometry.h"
|
||||
#include "../../model/exchange.h"
|
||||
|
||||
namespace he
|
||||
{
|
||||
namespace geometry
|
||||
{
|
||||
|
||||
RepresentationItem::RepresentationItem(A3DRiRepresentationItem* rep_item, const A3DMiscCascadedAttributes* cascaded_attributes) :
|
||||
Entity()
|
||||
{
|
||||
A3D_INITIALIZE_DATA(A3DMeshData, mesh_data);
|
||||
// for each representation item list, we compute a mesh based on triangle only.
|
||||
status = A3DRiComputeMesh(rep_item, cascaded_attributes, &mesh_data, nullptr);
|
||||
if (status != A3D_SUCCESS)
|
||||
{
|
||||
A3DRWParamsTessellationData tess_params;
|
||||
A3D_INITIALIZE_DATA(A3DRWParamsTessellationData, tess_params);
|
||||
tess_params.m_eTessellationLevelOfDetail = kA3DTessLODMedium;
|
||||
A3DRiRepresentationItemComputeTessellation(rep_item, &tess_params);
|
||||
status = A3DRiComputeMesh(rep_item, cascaded_attributes, &mesh_data, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
RepresentationItem::~RepresentationItem()
|
||||
{
|
||||
A3DRiComputeMesh(nullptr, nullptr, &mesh_data, nullptr);
|
||||
}
|
||||
|
||||
bool RepresentationItem::is_unicolor() const
|
||||
{
|
||||
return mesh_data.m_puiStyleIndexPerFace == nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RepresentationItem::prepare_render_buffer(std::vector <utils::geometry::BufferData>& buffer_data_array)
|
||||
{
|
||||
if (is_unicolor())
|
||||
{
|
||||
utils::geometry::BufferData buffer_data;
|
||||
build_one_buffer(buffer_data);
|
||||
buffer_data_array.push_back(buffer_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
build_buffer_per_style(buffer_data_array);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RepresentationItem::build_one_buffer(utils::geometry::BufferData& buffer_data) const
|
||||
{
|
||||
buffer_data.vertices.reserve(mesh_data.m_uiCoordSize / 3);
|
||||
|
||||
// For each mesh, we create model buffer, and store graphical information, and all positions
|
||||
// associated to it.
|
||||
for (A3DUns32 vertex_i = 0; vertex_i < mesh_data.m_uiCoordSize; vertex_i+=3)
|
||||
{
|
||||
utils::geometry::Vertex vertex;
|
||||
vertex.position = glm::vec3(mesh_data.m_pdCoords[vertex_i],
|
||||
mesh_data.m_pdCoords[vertex_i + 1],
|
||||
mesh_data.m_pdCoords[vertex_i + 2]);
|
||||
vertex.normal = glm::vec3(mesh_data.m_pdNormals[vertex_i],
|
||||
mesh_data.m_pdNormals[vertex_i + 1],
|
||||
mesh_data.m_pdNormals[vertex_i + 2]);
|
||||
|
||||
buffer_data.mesh_box.add_point(vertex.position);
|
||||
buffer_data.vertices.push_back(vertex);
|
||||
}
|
||||
|
||||
// Count the total number of indices
|
||||
size_t indiceCount = 0;
|
||||
for (A3DUns32 face_i = 0; face_i < mesh_data.m_uiFaceSize; ++face_i) {
|
||||
indiceCount += mesh_data.m_puiTriangleCountPerFace[face_i];
|
||||
}
|
||||
indiceCount *= 3; // 3 indices per triangle
|
||||
buffer_data.indices.reserve(indiceCount);
|
||||
|
||||
for (A3DUns32 vertex_i = 0; vertex_i < indiceCount; vertex_i++)
|
||||
buffer_data.indices.push_back(mesh_data.m_puiVertexIndicesPerFace[vertex_i]);
|
||||
|
||||
buffer_data.graphics = model::exchange::convert_style(mesh_data.m_uiStyleIndex);
|
||||
}
|
||||
|
||||
void RepresentationItem::build_buffer_per_style(std::vector <utils::geometry::BufferData>& buffers_data) const
|
||||
{
|
||||
int idx = 0;
|
||||
|
||||
// sort face by style, and create one buffer data per style
|
||||
|
||||
std::map<A3DUns32, std::vector<A3DUns32>> style_face_indices;
|
||||
std::vector<std::vector<A3DUns32>> vertex_indices_per_face(mesh_data.m_uiFaceSize);
|
||||
A3DUns32 vertex_index = 0;
|
||||
|
||||
for (A3DUns32 f = 0; f < mesh_data.m_uiFaceSize; f++)
|
||||
{
|
||||
const A3DUns32 triangle_count = mesh_data.m_puiTriangleCountPerFace[f];
|
||||
if (triangle_count == 0)
|
||||
continue;
|
||||
A3DUns32 face_style = mesh_data.m_puiStyleIndexPerFace[f];
|
||||
style_face_indices[face_style].push_back(f);
|
||||
|
||||
// Store vertex indices per face
|
||||
const A3DUns32 start_index = vertex_index;
|
||||
const A3DUns32 end_index = vertex_index + (triangle_count * 3);
|
||||
for (A3DUns32 v = start_index; v < end_index; ++v)
|
||||
{
|
||||
vertex_indices_per_face[f].push_back(mesh_data.m_puiVertexIndicesPerFace[v]);
|
||||
}
|
||||
vertex_index = end_index;
|
||||
}
|
||||
|
||||
// for each mesh, we create OnpenGL model (buffer), and store graphical information, and all positions
|
||||
// associated to it.
|
||||
|
||||
for (auto iter = style_face_indices.begin(); iter != style_face_indices.end(); ++iter)
|
||||
{
|
||||
utils::geometry::BufferData buffer_data;
|
||||
buffer_data.graphics = model::exchange::convert_style(iter->first);
|
||||
|
||||
idx = 0;
|
||||
for (auto& f : iter->second)
|
||||
{
|
||||
// for each face
|
||||
A3DUns32 triangle_count = mesh_data.m_puiTriangleCountPerFace[f];
|
||||
const std::vector<A3DUns32>& vertex_indices = vertex_indices_per_face[f];
|
||||
|
||||
std::vector<utils::geometry::Vertex> vertices;
|
||||
utils::geometry::BoundingBox box;
|
||||
utils::geometry::Vertex vertex;
|
||||
for (A3DUns32 t = 0; t < triangle_count; t++)
|
||||
{
|
||||
// for each triangle
|
||||
for (A3DUns32 v = 0; v < 3; v++)
|
||||
{
|
||||
const uint32_t indice = vertex_indices[t * 3 + v] * 3;
|
||||
vertex.position = glm::vec3(mesh_data.m_pdCoords[indice],
|
||||
mesh_data.m_pdCoords[indice + 1],
|
||||
mesh_data.m_pdCoords[indice + 2]);
|
||||
vertex.normal = glm::vec3(mesh_data.m_pdNormals[indice],
|
||||
mesh_data.m_pdNormals[indice + 1],
|
||||
mesh_data.m_pdNormals[indice + 2]);
|
||||
|
||||
buffer_data.mesh_box.add_point(vertex.position);
|
||||
buffer_data.vertices.push_back(vertex);
|
||||
buffer_data.indices.push_back(idx++);
|
||||
}
|
||||
}
|
||||
}
|
||||
buffers_data.push_back(buffer_data);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/***********************************************************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
***********************************************************************************************************************/
|
||||
|
||||
#ifndef REP_ITEM_H
|
||||
#define REP_ITEM_H
|
||||
|
||||
#include "entity.h"
|
||||
#include "../../utils/geometry.h"
|
||||
|
||||
namespace he
|
||||
{
|
||||
namespace geometry
|
||||
{
|
||||
class RepresentationItem : public Entity
|
||||
{
|
||||
A3DMeshData mesh_data;
|
||||
public:
|
||||
RepresentationItem(A3DRiRepresentationItem* rep_item, const A3DMiscCascadedAttributes* cascaded_attributes);
|
||||
~RepresentationItem();
|
||||
bool is_unicolor() const;
|
||||
void prepare_render_buffer(std::vector <utils::geometry::BufferData>& buffer_data_array);
|
||||
private:
|
||||
void build_one_buffer(utils::geometry::BufferData& buffer_data) const;
|
||||
void build_buffer_per_style(std::vector <utils::geometry::BufferData>& buffers_data) const;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif // REP_ITEM_H
|
||||
Reference in New Issue
Block a user