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 this->geom = ml;
168 this->filters = f;
169
170 if(this->geom.meshes.size() == 0)
171 {
172 qDebug() << "Clearing geometry: ";
173 // clear();
174 return;
175 }
176
177 auto& g = this->geom.meshes[0];
178
179 vertexBindings.clear();
180 for(auto& binding : g.bindings)
181 {
182 vertexBindings.emplace_back(
183 binding.stride, (QRhiVertexInputBinding::Classification)binding.classification,
184 binding.step_rate);
185 }
186
187 vertexAttributes.clear();
188 for(auto& attr : g.attributes)
189 {
190 vertexAttributes.emplace_back(
191 attr.binding, attr.location, (QRhiVertexInputAttribute::Format)attr.format,
192 attr.offset);
193 }
194
195 if(g.buffers.empty())
196 {
197 qDebug() << "Error: empty buffer !";
198 clear();
199 }
200
201 topology = (QRhiGraphicsPipeline::Topology)g.topology;
202 cullMode = (QRhiGraphicsPipeline::CullMode)g.cull_mode;
203 frontFace = (QRhiGraphicsPipeline::FrontFace)g.front_face;
204 }
205
206 void draw(const MeshBuffers& bufs, QRhiCommandBuffer& cb) const noexcept override
207 {
208 for(auto& g : this->geom.meshes)
209 {
210 const auto sz = g.input.size();
211
212 QVarLengthArray<QRhiCommandBuffer::VertexInput> bindings(sz);
213
214 int i = 0;
215 for(auto& in : g.input)
216 {
217 bindings[i++] = {bufs.mesh, in.offset};
218 }
219
220 if(g.index.buffer >= 0)
221 {
222 const auto idxFmt = g.index.format == decltype(g.index)::uint16
223 ? QRhiCommandBuffer::IndexUInt32
224 : QRhiCommandBuffer::IndexUInt32;
225 cb.setVertexInput(0, sz, bindings.data(), bufs.index, g.index.offset, idxFmt);
226 }
227 else
228 {
229 cb.setVertexInput(0, sz, bindings.data());
230 }
231
232 if(g.index.buffer > -1)
233 {
234 cb.drawIndexed(g.indices);
235 }
236 else
237 {
238 cb.draw(g.vertices);
239 }
240 }
241 }
242
243 const char* defaultVertexShader() const noexcept override
244 {
245 return "";
246 }
247};
248
249}
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:243
Graphics rendering pipeline for ossia score.
Definition Filter/PreviewWidget.hpp:12
Definition Mesh.hpp:15
Data model for meshes.
Definition Mesh.hpp:23