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]] MeshBuffers init(QRhi& rhi) const noexcept override
31 {
32 if(geom.meshes.empty())
33 return {};
34 if(geom.meshes[0].buffers.empty())
35 return {};
36
37 const auto vtx_buf_size = geom.meshes[0].buffers[0].size;
38 auto mesh_buf
39 = rhi.newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::VertexBuffer, vtx_buf_size);
40 mesh_buf->setName("Mesh::mesh_buf");
41 mesh_buf->create();
42
43 QRhiBuffer* idx_buf{};
44 if(geom.meshes[0].buffers.size() > 1)
45 {
46 if(const auto idx_buf_size = geom.meshes[0].buffers[1].size; idx_buf_size > 0)
47 {
48 idx_buf
49 = rhi.newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::IndexBuffer, idx_buf_size);
50 idx_buf->setName("Mesh::idx_buf");
51 idx_buf->create();
52 }
53 }
54
55 MeshBuffers ret{mesh_buf, idx_buf};
56 return ret;
57 }
58
59 void update(MeshBuffers& meshbuf, QRhiResourceUpdateBatch& rb) const noexcept override
60 {
61 if(geom.meshes.empty())
62 return;
63 if(geom.meshes[0].buffers.empty())
64 return;
65
66 void* idx_buf_data = nullptr;
67 const auto vtx_buf = geom.meshes[0].buffers[0];
68 if(auto sz = vtx_buf.size; sz != meshbuf.mesh->size())
69 {
70 meshbuf.mesh->destroy();
71 meshbuf.mesh->setSize(sz);
72 meshbuf.mesh->create();
73 }
74
75 if(meshbuf.index)
76 {
77 const auto idx_buf = geom.meshes[0].buffers[1];
78 if(geom.meshes[0].buffers.size() > 1)
79 {
80 if(const auto idx_buf_size = idx_buf.size; idx_buf_size > 0)
81 {
82 idx_buf_data = idx_buf.data.get();
83 // FIXME what if index disappears
84 if(auto sz = idx_buf.size; sz != meshbuf.index->size())
85 {
86 meshbuf.index->destroy();
87 meshbuf.index->setSize(sz);
88 meshbuf.index->create();
89 }
90 else
91 {
92 }
93 }
94 }
95 }
96 else
97 {
98 // FIXME what if index appears
99 }
100
101 rb.updateDynamicBuffer(meshbuf.mesh, 0, meshbuf.mesh->size(), vtx_buf.data.get());
102 if(meshbuf.index)
103 {
104 rb.updateDynamicBuffer(meshbuf.index, 0, meshbuf.index->size(), idx_buf_data);
105 }
106 }
107
108 Flags flags() const noexcept override
109 {
110 Flags f{};
111 for(auto& attr : vertexAttributes)
112 {
113 switch(attr.location())
114 {
115 case 0:
116 f |= HasPosition;
117 break;
118 case 1:
119 f |= HasTexCoord;
120 break;
121 case 2:
122 f |= HasColor;
123 break;
124 case 3:
125 f |= HasNormals;
126 break;
127 case 4:
128 f |= HasTangents;
129 break;
130 }
131 }
132 return f;
133 }
134
135 void clear()
136 {
137 vertexBindings.clear();
138 vertexAttributes.clear();
139 }
140
141 void preparePipeline(QRhiGraphicsPipeline& pip) const noexcept override
142 {
143 if(cullMode == QRhiGraphicsPipeline::None)
144 {
145 pip.setDepthTest(false);
146 pip.setDepthWrite(false);
147 }
148 else
149 {
150 pip.setDepthTest(true);
151 pip.setDepthWrite(true);
152 }
153
154 pip.setTopology(this->topology);
155 pip.setCullMode(this->cullMode);
156 pip.setFrontFace(this->frontFace);
157
158 QRhiVertexInputLayout inputLayout;
159 inputLayout.setBindings(this->vertexBindings.begin(), this->vertexBindings.end());
160 inputLayout.setAttributes(
161 this->vertexAttributes.begin(), this->vertexAttributes.end());
162 pip.setVertexInputLayout(inputLayout);
163 }
164
165 void reload(const ossia::mesh_list& ml, const ossia::geometry_filter_list_ptr& f)
166 {
167 dirtyGeometryIndex++;
168 this->geom = ml;
169 this->filters = f;
170
171 if(this->geom.meshes.size() == 0)
172 {
173 qDebug() << "Clearing geometry: ";
174 // clear();
175 return;
176 }
177
178 auto& g = this->geom.meshes[0];
179
180 vertexBindings.clear();
181 for(auto& binding : g.bindings)
182 {
183 vertexBindings.emplace_back(
184 binding.stride, (QRhiVertexInputBinding::Classification)binding.classification,
185 binding.step_rate);
186 }
187
188 vertexAttributes.clear();
189 for(auto& attr : g.attributes)
190 {
191 vertexAttributes.emplace_back(
192 attr.binding, attr.location, (QRhiVertexInputAttribute::Format)attr.format,
193 attr.offset);
194 }
195
196 if(g.buffers.empty())
197 {
198 qDebug() << "Error: empty buffer !";
199 clear();
200 }
201
202 topology = (QRhiGraphicsPipeline::Topology)g.topology;
203 cullMode = (QRhiGraphicsPipeline::CullMode)g.cull_mode;
204 frontFace = (QRhiGraphicsPipeline::FrontFace)g.front_face;
205 }
206
207 void draw(const MeshBuffers& bufs, QRhiCommandBuffer& cb) const noexcept override
208 {
209 for(auto& g : this->geom.meshes)
210 {
211 const auto sz = g.input.size();
212
213 QVarLengthArray<QRhiCommandBuffer::VertexInput> bindings(sz);
214
215 int i = 0;
216 for(auto& in : g.input)
217 {
218 bindings[i++] = {bufs.mesh, in.offset};
219 }
220
221 if(g.index.buffer >= 0)
222 {
223 const auto idxFmt = g.index.format == decltype(g.index)::uint16
224 ? QRhiCommandBuffer::IndexUInt32
225 : QRhiCommandBuffer::IndexUInt32;
226 cb.setVertexInput(0, sz, bindings.data(), bufs.index, g.index.offset, idxFmt);
227 }
228 else
229 {
230 cb.setVertexInput(0, sz, bindings.data());
231 }
232
233 if(g.index.buffer > -1)
234 {
235 cb.drawIndexed(g.indices);
236 }
237 else
238 {
239 cb.draw(g.vertices);
240 }
241 }
242 }
243
244 const char* defaultVertexShader() const noexcept override
245 {
246 return "";
247 }
248};
249
250}
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:244
Graphics rendering pipeline for ossia score.
Definition Filter/PreviewWidget.hpp:12
Definition Mesh.hpp:15
Data model for meshes.
Definition Mesh.hpp:23