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

171 lines
6.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 <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);
}
}
}
}