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