Loading...
Searching...
No Matches
CustomMesh.hpp
1#pragma once
2#include <Gfx/Graph/Mesh.hpp>
3
4#include <ossia/dataflow/geometry_port.hpp>
5
6#include <QtGui/private/qrhi_p.h>
7
8namespace score::gfx
9{
10
12{
13 ossia::mesh_list geom;
14
15 using pip = QRhiGraphicsPipeline;
16 pip::Topology topology = pip::Topology::TriangleStrip;
17 pip::CullMode cullMode = pip::CullMode::None;
18 pip::FrontFace frontFace = pip::FrontFace::CW;
19
20 ossia::small_vector<QRhiVertexInputBinding, 2> vertexBindings;
21 ossia::small_vector<QRhiVertexInputAttribute, 2> vertexAttributes;
22
23public:
24 explicit CustomMesh(
25 const ossia::mesh_list& g, const ossia::geometry_filter_list_ptr& f)
26 {
27 reload(g, f);
28 }
29
30 [[nodiscard]]
31 QRhiBuffer* init_vbo(const ossia::geometry::cpu_buffer& buf, QRhi& rhi) const noexcept
32 {
33 const auto vtx_buf_size = buf.size;
34 auto mesh_buf
35 = rhi.newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::VertexBuffer, vtx_buf_size);
36 mesh_buf->setName("Mesh::mesh_buf");
37 mesh_buf->create();
38
39 return mesh_buf;
40 }
41
42 [[nodiscard]]
43 QRhiBuffer* init_vbo(const ossia::geometry::gpu_buffer& buf, QRhi& rhi) const noexcept
44 {
45 return static_cast<QRhiBuffer*>(buf.handle);
46 }
47 [[nodiscard]]
48 QRhiBuffer*
49 init_index(const ossia::geometry::cpu_buffer& buf, QRhi& rhi) const noexcept
50 {
51 QRhiBuffer* idx_buf{};
52 if(const auto idx_buf_size = buf.size; idx_buf_size > 0)
53 {
54 idx_buf
55 = rhi.newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::IndexBuffer, idx_buf_size);
56 idx_buf->setName("Mesh::idx_buf");
57 idx_buf->create();
58 }
59
60 return idx_buf;
61 }
62
63 [[nodiscard]]
64 QRhiBuffer*
65 init_index(const ossia::geometry::gpu_buffer& buf, QRhi& rhi) const noexcept
66 {
67 return static_cast<QRhiBuffer*>(buf.handle);
68 }
69
70 [[nodiscard]] MeshBuffers init(QRhi& rhi) const noexcept override
71 {
72 if(geom.meshes.empty())
73 return {};
74 if(geom.meshes[0].buffers.empty())
75 return {};
76
77 MeshBuffers ret;
78 ret.mesh = ossia::visit(
79 [&](auto& buf) { return init_vbo(buf, rhi); }, geom.meshes[0].buffers[0].data);
80 if(geom.meshes[0].buffers.size() > 1)
81 ret.index = ossia::visit([&](auto& buf) {
82 return init_index(buf, rhi);
83 }, geom.meshes[0].buffers[1].data);
84 return ret;
85 }
86
87 void update_vbo(
88 const ossia::geometry::cpu_buffer& vtx_buf, MeshBuffers& meshbuf,
89 QRhiResourceUpdateBatch& rb) const noexcept
90 {
91 if(auto sz = vtx_buf.size; sz != meshbuf.mesh->size())
92 {
93 meshbuf.mesh->destroy();
94 meshbuf.mesh->setSize(sz);
95 meshbuf.mesh->create();
96 }
97 rb.updateDynamicBuffer(meshbuf.mesh, 0, meshbuf.mesh->size(), vtx_buf.data.get());
98 }
99
100 void update_vbo(
101 const ossia::geometry::gpu_buffer& vtx_buf, MeshBuffers& meshbuf,
102 QRhiResourceUpdateBatch& rb) const noexcept
103 {
104 }
105
106 void update_index(
107 const ossia::geometry::cpu_buffer& idx_buf, MeshBuffers& meshbuf,
108 QRhiResourceUpdateBatch& rb) const noexcept
109 {
110 void* idx_buf_data = nullptr;
111 if(meshbuf.index)
112 {
113 if(geom.meshes[0].buffers.size() > 1)
114 {
115 if(const auto idx_buf_size = idx_buf.size; idx_buf_size > 0)
116 {
117 idx_buf_data = idx_buf.data.get();
118 // FIXME what if index disappears
119 if(auto sz = idx_buf.size; sz != meshbuf.index->size())
120 {
121 meshbuf.index->destroy();
122 meshbuf.index->setSize(sz);
123 meshbuf.index->create();
124 }
125 else
126 {
127 }
128 }
129 }
130 }
131 else
132 {
133 // FIXME what if index appears
134 }
135
136 if(meshbuf.index && idx_buf_data)
137 {
138 rb.updateDynamicBuffer(meshbuf.index, 0, meshbuf.index->size(), idx_buf_data);
139 }
140 }
141
142 void update_index(
143 const ossia::geometry::gpu_buffer& idx_buf, MeshBuffers& meshbuf,
144 QRhiResourceUpdateBatch& rb) const noexcept
145 {
146 }
147 void update(MeshBuffers& meshbuf, QRhiResourceUpdateBatch& rb) const noexcept override
148 {
149 if(geom.meshes.empty())
150 return;
151 if(geom.meshes[0].buffers.empty())
152 return;
153 ossia::visit([&](auto& buf) {
154 return update_vbo(buf, meshbuf, rb);
155 }, geom.meshes[0].buffers[0].data);
156
157 if(geom.meshes[0].buffers.size() > 1)
158 ossia::visit([&](auto& buf) {
159 return update_index(buf, meshbuf, rb);
160 }, geom.meshes[0].buffers[1].data);
161 }
162 Flags flags() const noexcept override
163 {
164 Flags f{};
165 for(auto& attr : vertexAttributes)
166 {
167 switch(attr.location())
168 {
169 case 0:
170 f |= HasPosition;
171 break;
172 case 1:
173 f |= HasTexCoord;
174 break;
175 case 2:
176 f |= HasColor;
177 break;
178 case 3:
179 f |= HasNormals;
180 break;
181 case 4:
182 f |= HasTangents;
183 break;
184 }
185 }
186 return f;
187 }
188
189 void clear()
190 {
191 vertexBindings.clear();
192 vertexAttributes.clear();
193 }
194
195 void preparePipeline(QRhiGraphicsPipeline& pip) const noexcept override
196 {
197 if(cullMode == QRhiGraphicsPipeline::None)
198 {
199 pip.setDepthTest(false);
200 pip.setDepthWrite(false);
201 }
202 else
203 {
204 pip.setDepthTest(true);
205 pip.setDepthWrite(true);
206 }
207
208 pip.setTopology(this->topology);
209 pip.setCullMode(this->cullMode);
210 pip.setFrontFace(this->frontFace);
211
212 QRhiVertexInputLayout inputLayout;
213 inputLayout.setBindings(this->vertexBindings.begin(), this->vertexBindings.end());
214 inputLayout.setAttributes(
215 this->vertexAttributes.begin(), this->vertexAttributes.end());
216 pip.setVertexInputLayout(inputLayout);
217 }
218
219 void reload(const ossia::mesh_list& ml, const ossia::geometry_filter_list_ptr& f)
220 {
221 this->geom = ml;
222 this->filters = f;
223
224 if(this->geom.meshes.size() == 0)
225 {
226 qDebug() << "Clearing geometry: ";
227 // clear();
228 return;
229 }
230
231 auto& g = this->geom.meshes[0];
232
233 vertexBindings.clear();
234 for(auto& binding : g.bindings)
235 {
236 vertexBindings.emplace_back(
237 binding.stride, (QRhiVertexInputBinding::Classification)binding.classification,
238 binding.step_rate);
239 }
240
241 vertexAttributes.clear();
242 for(auto& attr : g.attributes)
243 {
244 vertexAttributes.emplace_back(
245 attr.binding, attr.location, (QRhiVertexInputAttribute::Format)attr.format,
246 attr.offset);
247 }
248
249 if(g.buffers.empty())
250 {
251 qDebug() << "Error: empty buffer !";
252 clear();
253 }
254
255 topology = (QRhiGraphicsPipeline::Topology)g.topology;
256 cullMode = (QRhiGraphicsPipeline::CullMode)g.cull_mode;
257 frontFace = (QRhiGraphicsPipeline::FrontFace)g.front_face;
258 }
259
260 void draw(const MeshBuffers& bufs, QRhiCommandBuffer& cb) const noexcept override
261 {
262 for(auto& g : this->geom.meshes)
263 {
264 const auto sz = g.input.size();
265
266 QVarLengthArray<QRhiCommandBuffer::VertexInput> bindings(sz);
267
268 int i = 0;
269 for(auto& in : g.input)
270 {
271 bindings[i++] = {bufs.mesh, in.offset};
272 }
273
274 if(g.index.buffer >= 0)
275 {
276 const auto idxFmt = g.index.format == decltype(g.index)::uint16
277 ? QRhiCommandBuffer::IndexUInt32
278 : QRhiCommandBuffer::IndexUInt32;
279 cb.setVertexInput(0, sz, bindings.data(), bufs.index, g.index.offset, idxFmt);
280 }
281 else
282 {
283 cb.setVertexInput(0, sz, bindings.data());
284 }
285
286 if(g.index.buffer > -1)
287 {
288 cb.drawIndexed(g.indices);
289 }
290 else
291 {
292 cb.draw(g.vertices);
293 }
294 }
295 }
296
297 const char* defaultVertexShader() const noexcept override
298 {
299 return "";
300 }
301};
302
303}
Definition CustomMesh.hpp:12
const char * defaultVertexShader() const noexcept override
A basic vertex shader that is going to work with this mesh.
Definition CustomMesh.hpp:297
Graphics rendering pipeline for ossia score.
Definition Filter/PreviewWidget.hpp:12
Definition Mesh.hpp:15
Data model for meshes.
Definition Mesh.hpp:23