VisuTwin Canvas
C++ 3D Engine — Metal Backend
Loading...
Searching...
No Matches
meshInstance.h
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2025-2026 Arnis Lektauers
3//
4// Created by Arnis Lektauers 21.12.2025.
5//
6#pragma once
7
8#include <cstdint>
10
11#include "graphNode.h"
12#include "mesh.h"
13#include "skinInstance.h"
14#include "scene/constants.h"
15#include "materials/material.h"
17
18namespace visutwin::canvas { class SkinBatchInstance; }
19
20namespace visutwin::canvas
21{
31 {
32 public:
40 {
41 std::shared_ptr<VertexBuffer> vertexBuffer;
42 int count = 0;
43
44 // GPU-driven indirect draw (Phase 3).
45 // When indirectArgsBuffer != nullptr and indirectSlot >= 0,
46 // renderer uses drawIndexedPrimitives(indirect:) instead of direct draw.
47 void* indirectArgsBuffer = nullptr; // MTL::Buffer* (opaque to avoid Metal headers in scene/)
48 std::shared_ptr<VertexBuffer> compactedVertexBuffer; // Culled output at slot 5
49 int indirectSlot = -1; // >= 0 activates indirect draw
50 };
51
53
55
56 Mesh* mesh() const { return _mesh; }
57
58 Material* material() const { return _material; }
59
60 GraphNode* node() const { return _node; }
61
62 bool castShadow() const { return _castShadow; }
63 void setCastShadow(const bool value) { _castShadow = value; }
64
65 //receiveShadow getter/setter.
66 // When false, the SHADERDEF_NOSHADOW flag is set on the shader defs.
67 bool receiveShadow() const { return _receiveShadow; }
68 void setReceiveShadow(const bool value) { _receiveShadow = value; }
69
70 bool cull() const { return _cull; }
71 void setCull(const bool value) { _cull = value; }
72
73 bool visibleThisFrame() const { return _visibleThisFrame; }
74 void setVisibleThisFrame(const bool value) { _visibleThisFrame = value; }
75
76 uint32_t mask() const { return _mask; }
77 void setMask(const uint32_t value) { _mask = value; }
78
79 // / instancingData / instancingCount.
80 // Sets up hardware instancing for this mesh instance. The vertexBuffer must contain
81 // packed InstanceData structs (80 bytes each: float4x4 + float4).
82 void setInstancing(const std::shared_ptr<VertexBuffer>& vertexBuffer, int count)
83 {
84 _instancingData.vertexBuffer = vertexBuffer;
85 _instancingData.count = count;
86 }
87
88 // GPU-driven indirect instancing (Phase 3).
89 // Sets up the mesh instance for indirect draw with a GPU-culled compacted buffer.
90 // The compactedVB replaces the original instance buffer at slot 5.
91 // indirectArgs is an opaque MTL::Buffer* containing MTLDrawIndexedPrimitivesIndirectArguments.
93 const std::shared_ptr<VertexBuffer>& compactedVB,
94 void* indirectArgs, int slot = 0)
95 {
96 _instancingData.compactedVertexBuffer = compactedVB;
97 _instancingData.indirectArgsBuffer = indirectArgs;
98 _instancingData.indirectSlot = slot;
99 }
100
101 const InstancingData& instancingData() const { return _instancingData; }
102 int instancingCount() const { return _instancingData.count; }
103
104 // --- Batching support (batchGroupId, visible) ---
105
106 int batchGroupId() const { return _batchGroupId; }
107 void setBatchGroupId(int id) { _batchGroupId = id; }
108
110 bool visible() const { return _visible; }
111 void setVisible(bool v) { _visible = v; }
112
113 // --- Dynamic batching support ---
114
116 SkinBatchInstance* skinBatchInstance() const { return _skinBatchInstance; }
117 void setSkinBatchInstance(SkinBatchInstance* sbi) { _skinBatchInstance = sbi; }
118
120 bool isDynamicBatch() const { return _dynamicBatch; }
121 void setDynamicBatch(bool v) { _dynamicBatch = v; }
122
125 _aabb = aabb;
126 _updateAabb = false;
127 }
128
129 private:
130 Material* _material = nullptr;
131 Mesh* _mesh = nullptr;
132
133 // The graph node defining the transform for this instance.
134 GraphNode* _node = nullptr;
135
136 BoundingBox _aabb;
137 bool _updateAabb = true;
138 std::function<BoundingBox&(BoundingBox&)> _updateAabbFunc = nullptr;
139 BoundingBox* _customAabb = nullptr;
140 int _aabbVer = -1;
141 int _aabbMeshVer = -1;
142
143 SkinInstance* _skinInstance = nullptr;
144 SkinBatchInstance* _skinBatchInstance = nullptr;
145 InstancingData _instancingData;
146
147 bool _castShadow = true;
148 bool _receiveShadow = true;
149 bool _cull = true;
150 bool _visibleThisFrame = false;
151 uint32_t _mask = MASK_AFFECT_DYNAMIC;
152
153 // Batching
154 int _batchGroupId = -1; // BatchGroup::NOID
155 bool _visible = true; // Hidden when merged into a batch
156 bool _dynamicBatch = false; // True when part of a dynamic batch
157 };
158}
Axis-Aligned Bounding Box defined by center and half-extents.
Definition boundingBox.h:21
Hierarchical scene graph node with local/world transforms and parent-child relationships.
Definition graphNode.h:28
Base class for GPU materials — owns uniform data, texture bindings, blend/depth state,...
Definition material.h:143
GPU-resident geometry defined by vertex/index buffers and one or more Primitives.
Definition mesh.h:79
void setReceiveShadow(const bool value)
void setCustomAabb(const BoundingBox &aabb)
void setCull(const bool value)
SkinBatchInstance * skinBatchInstance() const
Material * material() const
void setMask(const uint32_t value)
const InstancingData & instancingData() const
void setInstancing(const std::shared_ptr< VertexBuffer > &vertexBuffer, int count)
void setIndirectInstancing(const std::shared_ptr< VertexBuffer > &compactedVB, void *indirectArgs, int slot=0)
void setSkinBatchInstance(SkinBatchInstance *sbi)
MeshInstance(Mesh *mesh, Material *material, GraphNode *node=nullptr)
void setVisibleThisFrame(const bool value)
void setCastShadow(const bool value)
constexpr uint32_t MASK_AFFECT_DYNAMIC
Definition constants.h:31
std::shared_ptr< VertexBuffer > vertexBuffer
std::shared_ptr< VertexBuffer > compactedVertexBuffer