Simulant  21.09-46
A portable game engine for Windows, OSX, Linux, Dreamcast, and PSP
types.h
1 /* * Copyright (c) 2011-2017 Luke Benstead https://simulant-engine.appspot.com
2  *
3  * This file is part of Simulant.
4  *
5  * Simulant is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * Simulant is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with Simulant. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef TYPES_H_INCLUDED
20 #define TYPES_H_INCLUDED
21 
22 #include <iostream>
23 #include <memory>
24 #include <tuple>
25 #include <cstdint>
26 #include <string>
27 #include <vector>
28 #include <array>
29 
30 #include "colour.h"
31 #include "generic/optional.h"
32 
33 #include "math/vec2.h"
34 #include "math/vec3.h"
35 #include "math/vec4.h"
36 #include "math/quaternion.h"
37 #include "math/degrees.h"
38 #include "math/radians.h"
39 #include "math/mat3.h"
40 #include "math/mat4.h"
41 #include "math/aabb.h"
42 #include "math/plane.h"
43 #include "math/ray.h"
44 #include "math/operators.h"
45 
46 #include "generic/object_manager.h"
47 #include "generic/unique_id.h"
48 #include "generic/default_init_ptr.h"
49 
50 #include "utils/unicode.h"
51 #include "material_constants.h"
52 
53 namespace smlt {
54 
55 enum VertexAttribute {
56  VERTEX_ATTRIBUTE_NONE,
57  VERTEX_ATTRIBUTE_2F,
58  VERTEX_ATTRIBUTE_3F,
59  VERTEX_ATTRIBUTE_4F,
60  VERTEX_ATTRIBUTE_4UB,
61  VERTEX_ATTRIBUTE_PACKED_VEC4_1I // Packed 10, 10, 10, 2 vector
62 };
63 
64 class VertexSpecification;
65 
66 /*
67  * Allows us to keep the original syntax of VertexSpecification when it was a struct
68  * but also ensure that stride and offsets are updated when a value changes
69  * C++ really could do with properties built-in :(
70  */
72 public:
73  VertexAttributeProperty(VertexSpecification* spec, VertexAttribute VertexSpecification::* attr);
74 
75  operator VertexAttribute() const {
76  return spec_->*attr_;
77  }
78 
79  VertexAttributeProperty& operator=(const VertexAttribute& rhs);
80 
82  VertexAttributeProperty& operator=(const VertexAttributeProperty& rhs) = delete;
83 private:
84  VertexSpecification* spec_ = nullptr;
85  VertexAttribute VertexSpecification::* attr_ = nullptr;
86 };
87 
88 
89 typedef int16_t AttributeOffset;
90 const static AttributeOffset INVALID_ATTRIBUTE_OFFSET = -1;
91 
93  friend struct std::hash<VertexSpecification>;
94  friend class VertexData;
95 
96  VertexAttribute position_attribute_ = VERTEX_ATTRIBUTE_NONE;
97  VertexAttribute normal_attribute_ = VERTEX_ATTRIBUTE_NONE;
98  VertexAttribute texcoord0_attribute_ = VERTEX_ATTRIBUTE_NONE;
99  VertexAttribute texcoord1_attribute_ = VERTEX_ATTRIBUTE_NONE;
100  VertexAttribute texcoord2_attribute_ = VERTEX_ATTRIBUTE_NONE;
101  VertexAttribute texcoord3_attribute_ = VERTEX_ATTRIBUTE_NONE;
102  VertexAttribute texcoord4_attribute_ = VERTEX_ATTRIBUTE_NONE;
103  VertexAttribute texcoord5_attribute_ = VERTEX_ATTRIBUTE_NONE;
104  VertexAttribute texcoord6_attribute_ = VERTEX_ATTRIBUTE_NONE;
105  VertexAttribute texcoord7_attribute_ = VERTEX_ATTRIBUTE_NONE;
106  VertexAttribute diffuse_attribute_ = VERTEX_ATTRIBUTE_NONE;
107  VertexAttribute specular_attribute_ = VERTEX_ATTRIBUTE_NONE;
108 
109  AttributeOffset position_offset_ = 0;
110  AttributeOffset normal_offset_ = 0;
111  AttributeOffset texcoord0_offset_ = 0;
112  AttributeOffset texcoord1_offset_ = 0;
113  AttributeOffset texcoord2_offset_ = 0;
114  AttributeOffset texcoord3_offset_ = 0;
115  AttributeOffset texcoord4_offset_ = 0;
116  AttributeOffset texcoord5_offset_ = 0;
117  AttributeOffset texcoord6_offset_ = 0;
118  AttributeOffset texcoord7_offset_ = 0;
119  AttributeOffset diffuse_offset_ = 0;
120  AttributeOffset specular_offset_ = 0;
121 
122 public:
123  static const VertexSpecification DEFAULT;
124  static const VertexSpecification POSITION_ONLY;
125  static const VertexSpecification POSITION_AND_DIFFUSE;
126 
127  VertexAttributeProperty position_attribute = {this, &VertexSpecification::position_attribute_};
128  VertexAttributeProperty normal_attribute = {this, &VertexSpecification::normal_attribute_};
129  VertexAttributeProperty texcoord0_attribute = {this, &VertexSpecification::texcoord0_attribute_};
130  VertexAttributeProperty texcoord1_attribute = {this, &VertexSpecification::texcoord1_attribute_};
131  VertexAttributeProperty texcoord2_attribute = {this, &VertexSpecification::texcoord2_attribute_};
132  VertexAttributeProperty texcoord3_attribute = {this, &VertexSpecification::texcoord3_attribute_};
133  VertexAttributeProperty texcoord4_attribute = {this, &VertexSpecification::texcoord4_attribute_};
134  VertexAttributeProperty texcoord5_attribute = {this, &VertexSpecification::texcoord5_attribute_};
135  VertexAttributeProperty texcoord6_attribute = {this, &VertexSpecification::texcoord6_attribute_};
136  VertexAttributeProperty texcoord7_attribute = {this, &VertexSpecification::texcoord7_attribute_};
137  VertexAttributeProperty diffuse_attribute = {this, &VertexSpecification::diffuse_attribute_};
138  VertexAttributeProperty specular_attribute = {this, &VertexSpecification::specular_attribute_};
139 
140  VertexSpecification() = default;
142  position_attribute_(rhs.position_attribute_),
143  normal_attribute_(rhs.normal_attribute_),
144  texcoord0_attribute_(rhs.texcoord0_attribute_),
145  texcoord1_attribute_(rhs.texcoord1_attribute_),
146  texcoord2_attribute_(rhs.texcoord2_attribute_),
147  texcoord3_attribute_(rhs.texcoord3_attribute_),
148  texcoord4_attribute_(rhs.texcoord4_attribute_),
149  texcoord5_attribute_(rhs.texcoord5_attribute_),
150  texcoord6_attribute_(rhs.texcoord6_attribute_),
151  texcoord7_attribute_(rhs.texcoord7_attribute_),
152  diffuse_attribute_(rhs.diffuse_attribute_),
153  specular_attribute_(rhs.specular_attribute_),
154  position_attribute(this, &VertexSpecification::position_attribute_),
155  normal_attribute(this, &VertexSpecification::normal_attribute_),
156  texcoord0_attribute(this, &VertexSpecification::texcoord0_attribute_),
157  texcoord1_attribute(this, &VertexSpecification::texcoord1_attribute_),
158  texcoord2_attribute(this, &VertexSpecification::texcoord2_attribute_),
159  texcoord3_attribute(this, &VertexSpecification::texcoord3_attribute_),
160  texcoord4_attribute(this, &VertexSpecification::texcoord4_attribute_),
161  texcoord5_attribute(this, &VertexSpecification::texcoord5_attribute_),
162  texcoord6_attribute(this, &VertexSpecification::texcoord6_attribute_),
163  texcoord7_attribute(this, &VertexSpecification::texcoord7_attribute_),
164  diffuse_attribute(this, &VertexSpecification::diffuse_attribute_),
165  specular_attribute(this, &VertexSpecification::specular_attribute_) {
166 
167  recalc_stride_and_offsets();
168  }
169 
171  position_attribute_(rhs.position_attribute_),
172  normal_attribute_(rhs.normal_attribute_),
173  texcoord0_attribute_(rhs.texcoord0_attribute_),
174  texcoord1_attribute_(rhs.texcoord1_attribute_),
175  texcoord2_attribute_(rhs.texcoord2_attribute_),
176  texcoord3_attribute_(rhs.texcoord3_attribute_),
177  texcoord4_attribute_(rhs.texcoord4_attribute_),
178  texcoord5_attribute_(rhs.texcoord5_attribute_),
179  texcoord6_attribute_(rhs.texcoord6_attribute_),
180  texcoord7_attribute_(rhs.texcoord7_attribute_),
181  diffuse_attribute_(rhs.diffuse_attribute_),
182  specular_attribute_(rhs.specular_attribute_),
183  position_attribute(this, &VertexSpecification::position_attribute_),
184  normal_attribute(this, &VertexSpecification::normal_attribute_),
185  texcoord0_attribute(this, &VertexSpecification::texcoord0_attribute_),
186  texcoord1_attribute(this, &VertexSpecification::texcoord1_attribute_),
187  texcoord2_attribute(this, &VertexSpecification::texcoord2_attribute_),
188  texcoord3_attribute(this, &VertexSpecification::texcoord3_attribute_),
189  texcoord4_attribute(this, &VertexSpecification::texcoord4_attribute_),
190  texcoord5_attribute(this, &VertexSpecification::texcoord5_attribute_),
191  texcoord6_attribute(this, &VertexSpecification::texcoord6_attribute_),
192  texcoord7_attribute(this, &VertexSpecification::texcoord7_attribute_),
193  diffuse_attribute(this, &VertexSpecification::diffuse_attribute_),
194  specular_attribute(this, &VertexSpecification::specular_attribute_) {
195 
196  recalc_stride_and_offsets();
197  }
198 
199  VertexSpecification& operator=(const VertexSpecification& rhs) {
200  position_attribute_ = rhs.position_attribute_;
201  normal_attribute_ = rhs.normal_attribute_;
202  texcoord0_attribute_ = rhs.texcoord0_attribute_;
203  texcoord1_attribute_ = rhs.texcoord1_attribute_;
204  texcoord2_attribute_ = rhs.texcoord2_attribute_;
205  texcoord3_attribute_ = rhs.texcoord3_attribute_;
206  texcoord4_attribute_ = rhs.texcoord4_attribute_;
207  texcoord5_attribute_ = rhs.texcoord5_attribute_;
208  texcoord6_attribute_ = rhs.texcoord6_attribute_;
209  texcoord7_attribute_ = rhs.texcoord7_attribute_;
210  diffuse_attribute_ = rhs.diffuse_attribute_;
211  specular_attribute_ = rhs.specular_attribute_;
212 
213  recalc_stride_and_offsets();
214 
215  return *this;
216  }
217 
218  explicit VertexSpecification(
219  VertexAttribute position,
220  VertexAttribute normal = VERTEX_ATTRIBUTE_NONE,
221  VertexAttribute texcoord0 = VERTEX_ATTRIBUTE_NONE,
222  VertexAttribute texcoord1 = VERTEX_ATTRIBUTE_NONE,
223  VertexAttribute texcoord2 = VERTEX_ATTRIBUTE_NONE,
224  VertexAttribute texcoord3 = VERTEX_ATTRIBUTE_NONE,
225  VertexAttribute texcoord4 = VERTEX_ATTRIBUTE_NONE,
226  VertexAttribute texcoord5 = VERTEX_ATTRIBUTE_NONE,
227  VertexAttribute texcoord6 = VERTEX_ATTRIBUTE_NONE,
228  VertexAttribute texcoord7 = VERTEX_ATTRIBUTE_NONE,
229  VertexAttribute diffuse = VERTEX_ATTRIBUTE_NONE,
230  VertexAttribute specular = VERTEX_ATTRIBUTE_NONE
231  );
232 
233  bool operator==(const VertexSpecification& rhs) const {
234  return position_attribute == rhs.position_attribute &&
235  normal_attribute == rhs.normal_attribute &&
236  texcoord0_attribute == rhs.texcoord0_attribute &&
237  texcoord1_attribute == rhs.texcoord1_attribute &&
238  texcoord2_attribute == rhs.texcoord2_attribute &&
239  texcoord3_attribute == rhs.texcoord3_attribute &&
240  texcoord4_attribute == rhs.texcoord4_attribute &&
241  texcoord5_attribute == rhs.texcoord5_attribute &&
242  texcoord6_attribute == rhs.texcoord6_attribute &&
243  texcoord7_attribute == rhs.texcoord7_attribute &&
244  diffuse_attribute == rhs.diffuse_attribute &&
245  specular_attribute == rhs.specular_attribute;
246  }
247 
248  bool operator!=(const VertexSpecification& rhs) const {
249  return !(*this == rhs);
250  }
251 
252  inline uint32_t stride() const { return stride_; }
253 
254  bool has_positions() const { return bool(position_attribute_); }
255  bool has_normals() const { return bool(normal_attribute_); }
256 
257  bool has_texcoordX(uint8_t which) const;
258 
259  VertexAttribute texcoordX_attribute(uint8_t which) const;
260 
261  bool has_texcoord0() const { return bool(texcoord0_attribute_); }
262  bool has_texcoord1() const { return bool(texcoord1_attribute_); }
263  bool has_texcoord2() const { return bool(texcoord2_attribute_); }
264  bool has_texcoord3() const { return bool(texcoord3_attribute_); }
265  bool has_texcoord4() const { return bool(texcoord4_attribute_); }
266  bool has_texcoord5() const { return bool(texcoord5_attribute_); }
267  bool has_texcoord6() const { return bool(texcoord6_attribute_); }
268  bool has_texcoord7() const { return bool(texcoord7_attribute_); }
269 
270  bool has_diffuse() const { return bool(diffuse_attribute_); }
271  bool has_specular() const { return bool(specular_attribute_); }
272 
273  AttributeOffset position_offset(bool check=true) const;
274  AttributeOffset normal_offset(bool check=true) const;
275  AttributeOffset texcoord0_offset(bool check=true) const;
276  AttributeOffset texcoord1_offset(bool check=true) const;
277  AttributeOffset texcoord2_offset(bool check=true) const;
278  AttributeOffset texcoord3_offset(bool check=true) const;
279  AttributeOffset texcoord4_offset(bool check=true) const;
280  AttributeOffset texcoord5_offset(bool check=true) const;
281  AttributeOffset texcoord6_offset(bool check=true) const;
282  AttributeOffset texcoord7_offset(bool check=true) const;
283 
284  AttributeOffset texcoordX_offset(uint8_t which, bool check=true) const;
285 
286  AttributeOffset diffuse_offset(bool check=true) const;
287  AttributeOffset specular_offset(bool check=true) const;
288 
289 private:
290  friend class VertexAttributeProperty;
291 
292  uint16_t stride_ = 0;
293 
294  void recalc_stride_and_offsets();
295 };
296 
297 enum IndexType {
298  INDEX_TYPE_8_BIT,
299  INDEX_TYPE_16_BIT,
300  INDEX_TYPE_32_BIT
301 };
302 
303 enum MeshArrangement {
304  MESH_ARRANGEMENT_TRIANGLES,
305  MESH_ARRANGEMENT_TRIANGLE_FAN,
306  MESH_ARRANGEMENT_TRIANGLE_STRIP,
307  MESH_ARRANGEMENT_QUADS,
308  MESH_ARRANGEMENT_LINES,
309  MESH_ARRANGEMENT_LINE_STRIP
310 };
311 
312 enum AvailablePartitioner {
313  PARTITIONER_NULL,
314  PARTITIONER_FRUSTUM,
315  PARTITIONER_HASH
316 };
317 
318 enum LightType {
319  LIGHT_TYPE_POINT,
320  LIGHT_TYPE_DIRECTIONAL,
321  LIGHT_TYPE_SPOT_LIGHT
322 };
323 
324 enum AspectRatio {
325  ASPECT_RATIO_CUSTOM,
326  ASPECT_RATIO_4_BY_3,
327  ASPECT_RATIO_16_BY_9,
328  ASPECT_RATIO_16_BY_10
329 };
330 
331 typedef float Ratio; //FIXME: Custom type to restrict between 0 and 1
332 
333 enum ProjectionType {
334  PROJECTION_TYPE_PERSPECTIVE,
335  PROJECTION_TYPE_ORTHOGRAPHIC
336 };
337 
338 enum BufferClearFlag {
339  BUFFER_CLEAR_COLOUR_BUFFER = 0x1,
340  BUFFER_CLEAR_DEPTH_BUFFER = 0x2,
341  BUFFER_CLEAR_STENCIL_BUFFER = 0x4,
342  BUFFER_CLEAR_ALL = BUFFER_CLEAR_COLOUR_BUFFER | BUFFER_CLEAR_DEPTH_BUFFER | BUFFER_CLEAR_STENCIL_BUFFER
343 };
344 
345 typedef int32_t RenderPriority;
346 const RenderPriority RENDER_PRIORITY_MIN = -250;
347 const RenderPriority RENDER_PRIORITY_ABSOLUTE_BACKGROUND = -250;
348 const RenderPriority RENDER_PRIORITY_BACKGROUND = -100;
349 const RenderPriority RENDER_PRIORITY_DISTANT = -50;
350 const RenderPriority RENDER_PRIORITY_MAIN = 0;
351 const RenderPriority RENDER_PRIORITY_NEAR = 50;
352 const RenderPriority RENDER_PRIORITY_FOREGROUND = 100;
353 const RenderPriority RENDER_PRIORITY_ABSOLUTE_FOREGROUND = 250;
354 const RenderPriority RENDER_PRIORITY_MAX = RENDER_PRIORITY_ABSOLUTE_FOREGROUND + 1;
355 
356 const std::vector<RenderPriority> RENDER_PRIORITIES = {
357  RENDER_PRIORITY_ABSOLUTE_BACKGROUND,
358  RENDER_PRIORITY_BACKGROUND,
359  RENDER_PRIORITY_DISTANT,
360  RENDER_PRIORITY_MAIN,
361  RENDER_PRIORITY_NEAR,
362  RENDER_PRIORITY_FOREGROUND,
363  RENDER_PRIORITY_ABSOLUTE_FOREGROUND
364 };
365 
366 enum ShaderType {
367  SHADER_TYPE_VERTEX,
368  SHADER_TYPE_FRAGMENT,
369  SHADER_TYPE_MAX
370 };
371 
372 enum VirtualGamepadConfig {
373  VIRTUAL_GAMEPAD_CONFIG_TWO_BUTTONS,
374  VIRTUAL_GAMEPAD_CONFIG_HAT_AND_BUTTON
375 };
376 
377 const std::string DEFAULT_MATERIAL_SCHEME = "default";
378 
379 class Mesh;
380 typedef std::weak_ptr<Mesh> MeshRef;
381 typedef std::shared_ptr<Mesh> MeshPtr;
382 
383 class SubMesh;
384 typedef SubMesh* SubMeshPtr;
385 
386 class Material;
387 typedef std::weak_ptr<Material> MaterialRef;
388 typedef std::shared_ptr<Material> MaterialPtr;
389 
390 class Texture;
391 typedef std::weak_ptr<Texture> TextureRef;
392 typedef std::shared_ptr<Texture> TexturePtr;
393 
394 class ParticleScript;
395 typedef std::shared_ptr<ParticleScript> ParticleScriptPtr;
396 
397 class Sound;
398 typedef std::weak_ptr<Sound> SoundRef;
399 typedef std::shared_ptr<Sound> SoundPtr;
400 
401 class Font;
402 typedef std::weak_ptr<Font> FontRef;
403 typedef std::shared_ptr<Font> FontPtr;
404 
405 class Actor;
406 typedef default_init_ptr<Actor> ActorPtr;
407 
408 class Geom;
409 typedef default_init_ptr<Geom> GeomPtr;
410 
411 class MeshInstancer;
412 typedef default_init_ptr<MeshInstancer> MeshInstancerPtr;
413 
414 class ParticleSystem;
415 typedef default_init_ptr<ParticleSystem> ParticleSystemPtr;
416 
417 class Sprite;
418 typedef default_init_ptr<Sprite> SpritePtr;
419 
420 class Light;
421 typedef default_init_ptr<Light> LightPtr;
422 
423 class Camera;
424 class CameraProxy;
425 
426 typedef default_init_ptr<Camera> CameraPtr;
427 
428 class Viewport;
429 
430 class Background;
431 typedef default_init_ptr<Background> BackgroundPtr;
432 
433 class Window;
434 
435 class Stage;
436 typedef default_init_ptr<Stage> StagePtr;
437 
438 namespace ui {
439 
440 class Widget;
441 class ProgressBar;
442 class Button;
443 class Label;
444 
445 typedef default_init_ptr<Widget> WidgetPtr;
446 
447 }
448 
449 class AssetManager;
450 typedef std::shared_ptr<AssetManager> ResourceManagerPtr;
451 
452 class Compositor;
453 typedef std::shared_ptr<Compositor> CompositorPtr;
454 
455 class Pipeline;
456 typedef default_init_ptr<Pipeline> PipelinePtr;
457 
458 class Frustum;
459 class Window;
460 class Partitioner;
461 
462 class GPUProgram;
463 typedef std::shared_ptr<GPUProgram> GPUProgramPtr;
464 
465 class Skybox;
466 typedef default_init_ptr<Skybox> SkyboxPtr;
467 
468 typedef uint32_t IdleConnectionID;
469 
470 typedef UniqueID<MeshPtr> MeshID;
471 typedef UniqueID<TexturePtr> TextureID;
472 typedef UniqueID<FontPtr> FontID;
473 typedef UniqueID<CameraPtr> CameraID;
474 typedef UniqueID<MaterialPtr> MaterialID;
475 typedef UniqueID<ParticleScriptPtr> ParticleScriptID;
476 
477 typedef UniqueID<LightPtr> LightID;
478 typedef UniqueID<StagePtr> StageID;
479 typedef UniqueID<ActorPtr> ActorID;
480 typedef UniqueID<GeomPtr> GeomID;
481 typedef UniqueID<MeshInstancerPtr> MeshInstancerID;
482 typedef UniqueID<SoundPtr> SoundID;
483 typedef UniqueID<SpritePtr> SpriteID;
484 typedef UniqueID<BackgroundPtr> BackgroundID;
485 typedef UniqueID<ParticleSystemPtr> ParticleSystemID;
486 typedef UniqueID<SkyboxPtr> SkyID;
487 typedef UniqueID<GPUProgramPtr> GPUProgramID;
488 typedef UniqueID<ui::WidgetPtr> WidgetID;
489 
490 #ifdef __WIN32__
491 typedef unsigned long DWORD;
492 typedef DWORD ProcessID;
493 #else
494 typedef uint32_t ProcessID;
495 #endif
496 
497 // Attributes should be aligned at 4 byte boundaries
498 // according to this
499 // https://developer.apple.com/library/content/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/TechniquesforWorkingwithVertexData/TechniquesforWorkingwithVertexData.html
500 static const uint16_t BUFFER_ATTRIBUTE_ALIGNMENT = 4;
501 
502 // According to Nvidia, stride should be 16 byte aligned
503 static const uint16_t BUFFER_STRIDE_ALIGNMENT = 16;
504 
505 /* Most platforms work better when the data is aligned to 4 byte boundaries */
506 constexpr uint16_t round_to_bytes(uint16_t stride, uint16_t bytes) {
507  return ((stride % bytes) == 0) ? stride : stride + bytes - (stride % bytes);
508 }
509 
510 constexpr uint16_t vertex_attribute_size(VertexAttribute attr) {
511  return round_to_bytes(
512  (attr == VERTEX_ATTRIBUTE_2F) ? sizeof(float) * 2 :
513  (attr == VERTEX_ATTRIBUTE_3F) ? sizeof(float) * 3 :
514  (attr == VERTEX_ATTRIBUTE_4F) ? sizeof(float) * 4 :
515  (attr == VERTEX_ATTRIBUTE_4UB) ? sizeof(uint8_t) * 4 :
516  (attr == VERTEX_ATTRIBUTE_PACKED_VEC4_1I) ? sizeof(uint32_t) : 0,
517  BUFFER_ATTRIBUTE_ALIGNMENT
518  );
519 }
520 
521 }
522 
523 
524 // Generic hash for tuples by Leo Goodstadt
525 // http://stackoverflow.com/questions/7110301/generic-hash-for-tuples-in-unordered-map-unordered-set
526 namespace std{
527  namespace
528  {
529 
530  // Code from boost
531  // Reciprocal of the golden ratio helps spread entropy
532  // and handles duplicates.
533  // See Mike Seymour in magic-numbers-in-boosthash-combine:
534  // http://stackoverflow.com/questions/4948780
535 
536  template <class T>
537  inline void hash_combine(std::size_t& seed, T const& v)
538  {
539  seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
540  }
541 
542  // Recursive template code derived from Matthieu M.
543  template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1>
544  struct HashValueImpl
545  {
546  static void apply(size_t& seed, Tuple const& tuple)
547  {
548  HashValueImpl<Tuple, Index-1>::apply(seed, tuple);
549  hash_combine(seed, std::get<Index>(tuple));
550  }
551  };
552 
553  template <class Tuple>
554  struct HashValueImpl<Tuple,0>
555  {
556  static void apply(size_t& seed, Tuple const& tuple)
557  {
558  hash_combine(seed, std::get<0>(tuple));
559  }
560  };
561  }
562 
563  template <typename ... TT>
564  struct hash<std::tuple<TT...>>
565  {
566  size_t
567  operator()(std::tuple<TT...> const& tt) const
568  {
569  size_t seed = 0;
570  HashValueImpl<std::tuple<TT...> >::apply(seed, tt);
571  return seed;
572  }
573 
574  };
575 
576 
577 #define DEFINE_ENUM_HASH(enum_name) \
578  template <> struct hash<enum_name> { \
579  size_t operator() (const enum_name& t) const { return std::hash<size_t>()((size_t) t); } \
580  }
581 
582  /* Hash functions for smlt types */
583  DEFINE_ENUM_HASH(smlt::MeshArrangement);
584  DEFINE_ENUM_HASH(smlt::IndexType);
585 
586  template<> struct hash<smlt::VertexSpecification> {
587  size_t operator()(const smlt::VertexSpecification& spec) const {
588  size_t seed = 0;
589 
590  hash_combine(seed, (unsigned int) spec.position_attribute_);
591  hash_combine(seed, (unsigned int) spec.normal_attribute_);
592  hash_combine(seed, (unsigned int) spec.texcoord0_attribute_);
593  hash_combine(seed, (unsigned int) spec.texcoord1_attribute_);
594  hash_combine(seed, (unsigned int) spec.texcoord2_attribute_);
595  hash_combine(seed, (unsigned int) spec.texcoord3_attribute_);
596  hash_combine(seed, (unsigned int) spec.texcoord4_attribute_);
597  hash_combine(seed, (unsigned int) spec.texcoord5_attribute_);
598  hash_combine(seed, (unsigned int) spec.texcoord6_attribute_);
599  hash_combine(seed, (unsigned int) spec.texcoord7_attribute_);
600  hash_combine(seed, (unsigned int) spec.diffuse_attribute_);
601  hash_combine(seed, (unsigned int) spec.specular_attribute_);
602  return seed;
603  }
604  };
605 
606 }
607 
608 #endif // TYPES_H_INCLUDED
smlt::VertexData
Definition: vertex_data.h:57
smlt::VertexSpecification
Definition: types.h:92
smlt
Definition: animation.cpp:25
smlt::VertexAttributeProperty
Definition: types.h:71
std
Extensions to the C++ standard library.
Definition: unique_id.h:200