Overte C++ Documentation
GeometryCache.h
1 //
2 // GeometryCache.h
3 // interface/src/renderer
4 //
5 // Created by Andrzej Kapolka on 6/21/13.
6 // Copyright 2013 High Fidelity, Inc.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 
12 #ifndef hifi_GeometryCache_h
13 #define hifi_GeometryCache_h
14 
15 #include "model-networking/ModelCache.h"
16 
17 #include <array>
18 
19 #include <QMap>
20 #include <QRunnable>
21 
22 #include <DependencyManager.h>
23 
24 #include <shared/Shapes.h>
25 
26 #include <gpu/Batch.h>
27 #include <gpu/Stream.h>
28 
29 #include <render/ShapePipeline.h>
30 
31 #include <graphics/Material.h>
32 #include <graphics/Asset.h>
33 
34 class SimpleProgramKey;
35 
36 typedef QPair<glm::vec2, float> Vec2FloatPair;
37 typedef QPair<Vec2FloatPair, Vec2FloatPair> Vec2FloatPairPair;
38 typedef QPair<glm::vec2, glm::vec2> Vec2Pair;
39 typedef QPair<Vec2Pair, Vec2Pair> Vec2PairPair;
40 typedef QPair<glm::vec3, glm::vec3> Vec3Pair;
41 typedef QPair<glm::vec4, glm::vec4> Vec4Pair;
42 typedef QPair<Vec3Pair, Vec2Pair> Vec3PairVec2Pair;
43 typedef QPair<Vec3Pair, glm::vec4> Vec3PairVec4;
44 typedef QPair<Vec3Pair, Vec4Pair> Vec3PairVec4Pair;
45 typedef QPair<Vec4Pair, glm::vec4> Vec4PairVec4;
46 typedef QPair<Vec4Pair, Vec4Pair> Vec4PairVec4Pair;
47 
48 inline uint qHash(const Vec2FloatPairPair& v, uint seed) {
49  // multiply by prime numbers greater than the possible size
50  return qHash(v.first.first.x + 5009 * v.first.first.y + 5011 * v.first.second +
51  5021 * v.second.first.x + 5023 * v.second.first.y + 5039 * v.second.second);
52 }
53 
54 inline uint qHash(const Vec2Pair& v, uint seed) {
55  // multiply by prime numbers greater than the possible size
56  return qHash(v.first.x + 5009 * v.first.y + 5011 * v.second.x + 5021 * v.second.y, seed);
57 }
58 
59 inline uint qHash(const glm::vec4& v, uint seed) {
60  // multiply by prime numbers greater than the possible size
61  return qHash(v.x + 5009 * v.y + 5011 * v.z + 5021 * v.w, seed);
62 }
63 
64 inline uint qHash(const Vec2PairPair& v, uint seed) {
65  // multiply by prime numbers greater than the possible size
66  return qHash(v.first.first.x + 5009 * v.first.first.y
67  + 5011 * v.first.second.x + 5021 * v.first.second.y
68  + 5023 * v.second.first.x + 5039 * v.second.first.y
69  + 5051 * v.second.second.x + 5059 * v.second.second.y, seed);
70 }
71 
72 inline uint qHash(const Vec3Pair& v, uint seed) {
73  // multiply by prime numbers greater than the possible size
74  return qHash(v.first.x + 5009 * v.first.y + 5011 * v.first.z
75  + 5021 * v.second.x + 5023 * v.second.y + 5039 * v.second.z, seed);
76 }
77 
78 inline uint qHash(const Vec4Pair& v, uint seed) {
79  // multiply by prime numbers greater than the possible size
80  return qHash(v.first.x + 5009 * v.first.y + 5011 * v.first.z + 5021 * v.first.w
81  + 5023 * v.second.x + 5039 * v.second.y + 5051 * v.second.z + 5059 * v.second.w , seed);
82 }
83 
84 inline uint qHash(const Vec3PairVec2Pair& v, uint seed) {
85  // multiply by prime numbers greater than the possible size
86  return qHash(v.first.first.x + 5009 * v.first.first.y + 5011 * v.first.first.z +
87  5021 * v.first.second.x + 5023 * v.first.second.y + 5039 * v.first.second.z +
88  5051 * v.second.first.x + 5059 * v.second.first.y +
89  5077 * v.second.second.x + 5081 * v.second.second.y, seed);
90 }
91 
92 inline uint qHash(const Vec3PairVec4& v, uint seed) {
93  // multiply by prime numbers greater than the possible size
94  return qHash(v.first.first.x + 5009 * v.first.first.y + 5011 * v.first.first.z +
95  5021 * v.first.second.x + 5023 * v.first.second.y + 5039 * v.first.second.z +
96  5051 * v.second.x + 5059 * v.second.y + 5077 * v.second.z + 5081 * v.second.w, seed);
97 }
98 
99 
100 inline uint qHash(const Vec3PairVec4Pair& v, uint seed) {
101  // multiply by prime numbers greater than the possible size
102  return qHash(v.first.first.x + 5009 * v.first.first.y + 5011 * v.first.first.z
103  + 5023 * v.first.second.x + 5039 * v.first.second.y + 5051 * v.first.second.z
104  + 5077 * v.second.first.x + 5081 * v.second.first.y + 5087 * v.second.first.z + 5099 * v.second.first.w
105  + 5101 * v.second.second.x + 5107 * v.second.second.y + 5113 * v.second.second.z + 5119 * v.second.second.w,
106  seed);
107 }
108 
109 inline uint qHash(const Vec4PairVec4& v, uint seed) {
110  // multiply by prime numbers greater than the possible size
111  return qHash(v.first.first.x + 5009 * v.first.first.y + 5011 * v.first.first.z + 5021 * v.first.first.w
112  + 5023 * v.first.second.x + 5039 * v.first.second.y + 5051 * v.first.second.z + 5059 * v.first.second.w
113  + 5077 * v.second.x + 5081 * v.second.y + 5087 * v.second.z + 5099 * v.second.w,
114  seed);
115 }
116 
117 inline uint qHash(const Vec4PairVec4Pair& v, uint seed) {
118  // multiply by prime numbers greater than the possible size
119  return qHash(v.first.first.x + 5009 * v.first.first.y + 5011 * v.first.first.z + 5021 * v.first.first.w
120  + 5023 * v.first.second.x + 5039 * v.first.second.y + 5051 * v.first.second.z + 5059 * v.first.second.w
121  + 5077 * v.second.first.x + 5081 * v.second.first.y + 5087 * v.second.first.z + 5099 * v.second.first.w
122  + 5101 * v.second.second.x + 5107 * v.second.second.y + 5113 * v.second.second.z + 5119 * v.second.second.w,
123  seed);
124 }
125 
127 class GeometryCache : public Dependency {
128  SINGLETON_DEPENDENCY
129 
130 public:
131  enum Shape {
132  Line,
133  Triangle,
134  Quad,
135  Hexagon,
136  Octagon,
137  Circle,
138  Cube,
139  Sphere,
140  Tetrahedron,
141  Octahedron,
142  Dodecahedron,
143  Icosahedron,
144  Torus, // not yet implemented
145  Cone,
146  Cylinder,
147  NUM_SHAPES,
148  };
149 
155  static GeometryCache::Shape getShapeForEntityShape(int entityShapeEnum);
156  static QString stringFromShape(GeometryCache::Shape geoShape);
157 
158  static void computeSimpleHullPointListForShape(int entityShape, const glm::vec3 &entityExtents, QVector<glm::vec3> &outPointList);
159 
160  int allocateID() { return _nextID++; }
161  void releaseID(int id);
162  static const int UNKNOWN_ID;
163 
164  // Bind the pipeline and get the state to render static geometry
165  void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool transparent = false, bool unlit = false, bool depthBias = false,
166  bool isAntiAliased = true, bool forward = false, graphics::MaterialKey::CullFaceMode cullFaceMode = graphics::MaterialKey::CullFaceMode::CULL_BACK);
167  // Get the pipeline to render static geometry
168  static gpu::PipelinePointer getSimplePipeline(bool textured = false, bool transparent = false, bool unlit = false, bool depthBias = false,
169  bool fading = false, bool isAntiAliased = true, bool forward = false, graphics::MaterialKey::CullFaceMode cullFaceMode = graphics::MaterialKey::CullFaceMode::CULL_BACK);
170 
171  void bindWebBrowserProgram(gpu::Batch& batch, bool transparent, bool forward);
172  gpu::PipelinePointer getWebBrowserProgram(bool transparent, bool forward);
173  static std::map<std::pair<bool, bool>, gpu::PipelinePointer> _webPipelines;
174 
175  static void initializeShapePipelines();
176  render::ShapePipelinePointer getShapePipelinePointer(bool transparent, bool unlit, bool forward,
177  graphics::MaterialKey::CullFaceMode cullFaceMode = graphics::MaterialKey::CULL_BACK) { return _shapePipelines[std::make_tuple(transparent, unlit, forward, cullFaceMode)]; }
178 
179  // Static (instanced) geometry
180  void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
181  void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
182 
183  void renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color,
184  const render::ShapePipelinePointer& pipeline);
185  void renderWireShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color,
186  const render::ShapePipelinePointer& pipeline);
187 
188  void renderSolidSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color,
189  const render::ShapePipelinePointer& pipeline);
190  void renderSolidSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec3& color,
191  const render::ShapePipelinePointer& pipeline) {
192  renderSolidSphereInstance(args, batch, glm::vec4(color, 1.0f), pipeline);
193  }
194 
195  void renderWireCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color,
196  const render::ShapePipelinePointer& pipeline);
197  void renderWireCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec3& color,
198  const render::ShapePipelinePointer& pipeline) {
199  renderWireCubeInstance(args, batch, glm::vec4(color, 1.0f), pipeline);
200  }
201 
202  // Dynamic geometry
203  void renderShape(gpu::Batch& batch, Shape shape, gpu::BufferPointer& colorBuffer);
204  void renderWireShape(gpu::Batch& batch, Shape shape, gpu::BufferPointer& colorBuffer);
205  size_t getShapeTriangleCount(Shape shape);
206 
207  void renderGrid(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner,
208  int majorRows, int majorCols, float majorEdge,
209  int minorRows, int minorCols, float minorEdge,
210  const glm::vec4& color, bool forward, int id);
211 
212  void renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id);
213 
214  void renderUnitQuad(gpu::Batch& batch, const glm::vec4& color, int id);
215 
216  void renderQuad(gpu::Batch& batch, int x, int y, int width, int height, const glm::vec4& color, int id)
217  { renderQuad(batch, glm::vec2(x,y), glm::vec2(x + width, y + height), color, id); }
218 
219  // TODO: I think there's a bug in this version of the renderQuad() that's not correctly rebuilding the vbos
220  // if the color changes by the corners are the same, as evidenced by the audio meter which should turn white
221  // when it's clipping
222  void renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner, const glm::vec4& color, int id);
223 
224  void renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner,
225  const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner,
226  const glm::vec4& color, int id);
227 
228  void renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, const glm::vec3& maxCorner, const glm::vec4& color, int id);
229 
230  void renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, const glm::vec3& bottomLeft,
231  const glm::vec3& bottomRight, const glm::vec3& topRight,
232  const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomLeft,
233  const glm::vec2& texCoordBottomRight, const glm::vec2& texCoordTopRight,
234  const glm::vec4& color, int id);
235 
236 
237  void renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& color, int id)
238  { renderLine(batch, p1, p2, color, color, id); }
239 
240  void renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
241  const glm::vec3& color1, const glm::vec3& color2, int id)
242  { renderLine(batch, p1, p2, glm::vec4(color1, 1.0f), glm::vec4(color2, 1.0f), id); }
243 
244  void renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
245  const glm::vec4& color, int id)
246  { renderLine(batch, p1, p2, color, color, id); }
247 
248  void renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
249  const glm::vec4& color1, const glm::vec4& color2, int id);
250 
251  void renderDashedLine(gpu::Batch& batch, const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, int id)
252  { renderDashedLine(batch, start, end, color, 0.05f, 0.025f, id); }
253 
254  void renderDashedLine(gpu::Batch& batch, const glm::vec3& start, const glm::vec3& end, const glm::vec4& color,
255  const float dash_length, const float gap_length, int id);
256 
257  void updateVertices(int id, const QVector<glm::vec2>& points, const glm::vec4& color);
258  void updateVertices(int id, const QVector<glm::vec2>& points, const QVector<glm::vec4>& colors);
259  void updateVertices(int id, const QVector<glm::vec3>& points, const glm::vec4& color);
260  void updateVertices(int id, const QVector<glm::vec3>& points, const QVector<glm::vec4>& colors);
261  void updateVertices(int id, const QVector<glm::vec3>& points, const QVector<glm::vec2>& texCoords, const glm::vec4& color);
262  void renderVertices(gpu::Batch& batch, gpu::Primitive primitiveType, int id);
263 
265  void useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend = false);
266 
267  struct ShapeVertex {
268  ShapeVertex(const vec3& pos, const vec3& normal, const vec2& uv, const vec3& tangent) : pos(pos), normal(normal), uv(uv), tangent(tangent) {}
269 
270  vec3 pos;
271  vec3 normal;
272  vec2 uv;
273  vec3 tangent;
274  };
275 
276  struct ShapeData {
277  gpu::BufferView _positionView;
278  gpu::BufferView _normalView;
279  gpu::BufferView _texCoordView;
280  gpu::BufferView _tangentView;
281  gpu::BufferView _indicesView;
282  gpu::BufferView _wireIndicesView;
283 
284  void setupVertices(gpu::BufferPointer& vertexBuffer, const std::vector<ShapeVertex>& vertices);
285  void setupIndices(gpu::BufferPointer& indexBuffer, const geometry::IndexVector& indices, const geometry::IndexVector& wireIndices);
286  void setupBatch(gpu::Batch& batch) const;
287  void draw(gpu::Batch& batch) const;
288  void drawWire(gpu::Batch& batch) const;
289  void drawInstances(gpu::Batch& batch, size_t count) const;
290  void drawWireInstances(gpu::Batch& batch, size_t count) const;
291  };
292 
293  using VShape = std::array<ShapeData, NUM_SHAPES>;
294 
297  const ShapeData * getShapeData(Shape shape) const;
298 
299  graphics::MeshPointer meshFromShape(Shape geometryShape, glm::vec3 color);
300 
301  static uint32_t toCompactColor(const glm::vec4& color);
302 
303 private:
304 
305  GeometryCache();
306  virtual ~GeometryCache();
307  void buildShapes();
308 
309  typedef QPair<int, int> IntPair;
310  typedef QPair<unsigned int, unsigned int> VerticesIndices;
311 
312 
313  VShape _shapes;
314 
315  gpu::PipelinePointer _standardDrawPipeline;
316  gpu::PipelinePointer _standardDrawPipelineNoBlend;
317 
318  gpu::BufferPointer _shapeVertices{ std::make_shared<gpu::Buffer>() };
319  gpu::BufferPointer _shapeIndices{ std::make_shared<gpu::Buffer>() };
320 
321  class GridSchema {
322  public:
323  // data is arranged as majorRow, majorCol, minorRow, minorCol
324  glm::vec4 period;
325  glm::vec4 offset;
326  glm::vec4 edge;
327  };
328  using GridBuffer = gpu::BufferView;
329  void useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bool transparent, bool forward);
330  static std::map<std::pair<bool, bool>, gpu::PipelinePointer> _gridPipelines;
331 
332  class BatchItemDetails {
333  public:
334  static int population;
335  gpu::BufferPointer verticesBuffer;
336  gpu::BufferPointer normalBuffer;
337  gpu::BufferPointer colorBuffer;
338  gpu::BufferPointer uniformBuffer;
339  gpu::Stream::FormatPointer streamFormat;
340  gpu::BufferStreamPointer stream;
341 
342  int vertices;
343  int vertexSize;
344  bool isCreated;
345 
346  BatchItemDetails();
347  BatchItemDetails(const GeometryCache::BatchItemDetails& other);
348  ~BatchItemDetails();
349  void clear();
350  };
351 
352  QHash<IntPair, VerticesIndices> _coneVBOs;
353 
354  int _nextID{ 1 };
355 
356  QHash<int, Vec3PairVec4Pair> _lastRegisteredQuad3DTexture;
357  QHash<int, BatchItemDetails> _registeredQuad3DTextures;
358 
359  QHash<int, Vec4PairVec4> _lastRegisteredQuad2DTexture;
360  QHash<int, BatchItemDetails> _registeredQuad2DTextures;
361 
362  QHash<int, Vec3PairVec4> _lastRegisteredQuad3D;
363  QHash<int, BatchItemDetails> _registeredQuad3D;
364 
365  QHash<int, Vec4Pair> _lastRegisteredQuad2D;
366  QHash<int, BatchItemDetails> _registeredQuad2D;
367 
368  QHash<int, Vec3Pair> _lastRegisteredBevelRects;
369  QHash<int, BatchItemDetails> _registeredBevelRects;
370 
371  QHash<int, Vec3Pair> _lastRegisteredLine3D;
372  QHash<int, BatchItemDetails> _registeredLine3DVBOs;
373 
374  QHash<int, Vec2Pair> _lastRegisteredLine2D;
375  QHash<int, BatchItemDetails> _registeredLine2DVBOs;
376 
377  QHash<int, BatchItemDetails> _registeredVertices;
378 
379  QHash<int, Vec3PairVec2Pair> _lastRegisteredDashedLines;
380  QHash<int, BatchItemDetails> _registeredDashedLines;
381 
382  QHash<int, Vec2FloatPairPair> _lastRegisteredGridBuffer;
383  QHash<int, GridBuffer> _registeredGridBuffers;
384 
385  // transparent, unlit, forward, fade
386  static std::map<std::tuple<bool, bool, bool, bool>, gpu::ShaderPointer> _shapeShaders;
387  // transparent, unlit, forward
388  static std::map<std::tuple<bool, bool, bool, graphics::MaterialKey::CullFaceMode>, render::ShapePipelinePointer> _shapePipelines;
389  static QHash<SimpleProgramKey, gpu::PipelinePointer> _simplePrograms;
390 
391  static render::ShapePipelinePointer getShapePipeline(bool textured = false, bool transparent = false, bool unlit = false,
392  bool depthBias = false, bool forward = false, graphics::MaterialKey::CullFaceMode cullFaceMode = graphics::MaterialKey::CullFaceMode::CULL_BACK);
393  static render::ShapePipelinePointer getFadingShapePipeline(bool textured = false, bool transparent = false, bool unlit = false,
394  bool depthBias = false, bool forward = false, graphics::MaterialKey::CullFaceMode cullFaceMode = graphics::MaterialKey::CullFaceMode::CULL_BACK);
395 };
396 
397 #endif // hifi_GeometryCache_h
Stores cached geometry.
Definition: GeometryCache.h:127
void useSimpleDrawPipeline(gpu::Batch &batch, bool noBlend=false)
Set a batch to the simple pipeline, returning the previous pipeline.
Definition: GeometryCache.cpp:1672
static GeometryCache::Shape getShapeForEntityShape(int entityShapeEnum)
Definition: GeometryCache.cpp:607
const ShapeData * getShapeData(Shape shape) const
Definition: GeometryCache.cpp:596