Files
leocad/common/lc_mesh.h
T
Leonardo Zide 98c67f3705 Align texture acquisition and scoped ownership
Texture lookup previously acquired references implicitly, and mesh sections and
loader requests paired raw texture pointers with manual release paths. Separate
borrowed lookup from scoped acquisition and explicit load requests/waits to match
the piece data ownership API.

Store lcTextureRef in mesh sections and loader requests, retain references on
section copies, and reset worker-shared request handles on the UI thread before
completion, cancellation, or shutdown. Keep reference primitives internal and use
scoped acquisitions for merge validation. Remove redundant section initialization
and synth-notification resets, and document the resulting ownership contracts.

Validation: macOS Debug build, diff whitespace checks, and 30 offscreen lifecycle
checks covering reference copies/moves, texture dependencies, cancellation,
shutdown, merge conflicts, and existing piece ownership paths. Successful GPU
upload/rendering is not covered by the offscreen checks.
2026-10-19 10:38:51 -07:00

145 lines
3.8 KiB
C++

#pragma once
#include "lc_math.h"
#include "lc_assettypes.h"
enum lcMeshPrimitiveType
{
LC_MESH_LINES = 0x01,
LC_MESH_TRIANGLES = 0x02,
LC_MESH_TEXTURED_TRIANGLES = 0x08,
LC_MESH_CONDITIONAL_LINES = 0x10,
LC_MESH_NUM_PRIMITIVE_TYPES
};
struct lcVertex
{
lcVector3 Position;
quint32 Normal;
};
struct lcVertexTextured
{
lcVector3 Position;
quint32 Normal;
lcVector2 TexCoord;
};
struct lcVertexConditional
{
lcVector3 Position1;
lcVector3 Position2;
lcVector3 Position3;
lcVector3 Position4;
};
struct lcMeshSection
{
int ColorIndex; // Holds a color code until FinalizeSections() converts it to an index.
int DrawOffset; // Index-buffer byte offset, or first conditional vertex.
int DrawCount; // Index count, or conditional vertex count.
lcMeshPrimitiveType PrimitiveType;
lcTextureRef Texture;
QString TextureName;
lcBoundingBox BoundingBox;
float Radius;
};
struct lcMeshLod
{
lcMeshSection* Sections = nullptr;
int NumSections = 0;
};
enum
{
LC_MESH_LOD_HIGH,
LC_MESH_LOD_LOW,
LC_NUM_MESH_LODS
};
enum class lcMeshFlag
{
HasDefault = 0x01, // Mesh has triangles using the default color
HasSolid = 0x02, // Mesh has triangles using a solid color
HasTranslucent = 0x04, // Mesh has triangles using a translucent color
HasLines = 0x08, // Mesh has lines
HasTexture = 0x10, // Mesh has sections using textures
HasStyleStud = 0x20 // Mesh has a stud that can have a logo applied
};
Q_DECLARE_FLAGS(lcMeshFlags, lcMeshFlag)
Q_DECLARE_OPERATORS_FOR_FLAGS(lcMeshFlags)
class lcMesh
{
public:
lcMesh();
~lcMesh();
lcMesh(const lcMesh&) = delete;
lcMesh(lcMesh&&) = delete;
lcMesh& operator=(const lcMesh&) = delete;
lcMesh& operator=(lcMesh&&) = delete;
void Create(quint16 (&NumSections)[LC_NUM_MESH_LODS], int VertexCount, int TexturedVertexCount, int ConditionalVertexCount, int IndexCount);
void CreateBox();
bool FileLoad(lcMemFile& File);
bool FileSave(lcMemFile& File);
// Set colors and flags, then sort sections using the current palette on the UI thread.
// Converts stored color codes to indices once, before publishing the mesh.
void FinalizeSections();
template<typename IndexType>
void ExportPOVRay(lcFile& File, const char* MeshName, const char** ColorTable);
void ExportPOVRay(lcFile& File, const char* MeshName, const char** ColorTable);
template<typename IndexType>
void ExportWavefrontIndices(lcFile& File, int DefaultColorIndex, int VertexOffset);
void ExportWavefrontIndices(lcFile& File, int DefaultColorIndex, int VertexOffset);
template<typename IndexType>
bool MinIntersectDist(const lcVector3& Start, const lcVector3& End, float& MinDist, lcVector3& HitPlane);
bool MinIntersectDist(const lcVector3& Start, const lcVector3& End, float& MinDist, lcVector3& HitPlane);
template<typename IndexType>
bool IntersectsPlanes(const lcVector4 (&Planes)[6]);
bool IntersectsPlanes(const lcVector4 (&Planes)[6]);
int GetLodIndex(float Distance) const;
const lcVertex* GetVertexData() const
{
return static_cast<lcVertex*>(mVertexData);
}
const lcVertexTextured* GetTexturedVertexData() const
{
return reinterpret_cast<lcVertexTextured*>(static_cast<char*>(mVertexData) + mNumVertices * sizeof(lcVertex));
}
const lcVertexConditional* GetConditionalVertexData() const
{
return reinterpret_cast<lcVertexConditional*>(static_cast<char*>(mVertexData) + mNumVertices * sizeof(lcVertex) + mNumTexturedVertices * sizeof(lcVertexTextured));
}
lcMeshLod mLods[LC_NUM_MESH_LODS];
lcBoundingBox mBoundingBox;
float mRadius = 0.0f;
lcMeshFlags mFlags;
void* mVertexData = nullptr;
int mVertexDataSize = 0;
void* mIndexData = nullptr;
int mIndexDataSize = 0;
int mVertexCacheOffset = -1;
int mIndexCacheOffset = -1;
int mNumVertices = 0;
int mNumTexturedVertices = 0;
int mConditionalVertexCount = 0;
int mIndexType = 0;
};