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