AnimEngine
Pose.hpp
1 #pragma once
2 #ifndef KJY_ANIM_ENGINE_COMPONENTS_POSE_HPP_
3 #define KJY_ANIM_ENGINE_COMPONENTS_POSE_HPP_
4 #include <glm/glm.hpp>
5 #define GLM_ENABLE_EXPERIMENTAL
6 #include <glm/gtx/quaternion.hpp>
7 #include <glm/gtx/string_cast.hpp>
8 #include <iostream>
9 #include "AttachableComponent.hpp"
10 
11 class Pose : public virtual AttachableComponent{
12  public:
13  Pose() {}
14  Pose(const glm::vec3& start_location) : translation(start_location) {_update_matrix_cache();}
15  Pose(const glm::vec3& start_location, const glm::quat& start_orientation) : translation(start_location), orientation(start_orientation) {_update_matrix_cache();}
16  Pose(const glm::vec3& start_location, const glm::quat& start_orientation, const glm::vec3& start_scale) : translation(start_location), orientation(start_orientation), scale(start_scale) {_update_matrix_cache();}
17  Pose(const glm::mat4& pre_transform) : preaffine(pre_transform) {_update_matrix_cache();}
18  Pose(const glm::mat4& pre_transform, const glm::mat4& post_transform): preaffine(pre_transform), postaffine(post_transform) {_update_matrix_cache();}
19 
20  const glm::mat4& getMatrix();
21  inline glm::vec3 getCenterOfSpace() const {return(glm::vec3(getMatrix() * glm::vec4(0.0,0.0,0.0,1.0)));}
22  inline glm::vec3 getCenterOfSpace() {return(glm::vec3(getMatrix() * glm::vec4(0.0,0.0,0.0,1.0)));}
23  inline glm::vec3 getOrientationAsVectorX() const {return(glm::normalize(orientation * glm::vec3(1.0, 0.0, 0.0)));}
24  inline glm::vec3 getOrientationAsVectorY() const {return(glm::normalize(orientation * glm::vec3(0.0, 1.0, 1.0)));}
25  inline glm::vec3 getOrientationAsVectorZ() const {return(glm::normalize(orientation * glm::vec3(0.0, 0.0, 1.0)));}
26 
27  /* Copies contents of other into this pose object. Typically you would
28  * want to just use assignment instead, but this is usefull for any
29  * classes which inherit from pose and want to be able to update
30  * themselves based on a plain pose object. */
31  void copyFrom(const Pose& other);
32 
33  inline const glm::vec3& getTranslation() const {return(translation);}
34  inline const glm::quat& getOrientation() const {return(orientation);}
35  inline const glm::vec3& getScale() const {return(scale);}
36  inline const glm::mat4& getPreTransformMatrix() const {return(preaffine);}
37  inline const glm::mat4& getPostTransformMatrix() const {return(postaffine);}
38 
39  /* Returns a new `Pose` that has had all elements which translate the
40  * represented space eliminated except for a translation leaving it at
41  * `origin`. The post/pre-affine matrices will have their final column
42  * overwritten with the identity .
43  */
44  inline Pose getCenteredAndReduced(const glm::vec3& origin = glm::vec3(0.0)) const{
45  Pose newpose = *this;
46  newpose.translation = origin;
47  newpose.postaffine[3] = newpose.preaffine[3] = glm::vec4(0.0, 0.0, 0.0, 1.0);
48  newpose._update_matrix_cache();
49  return(newpose);
50  }
51 
52  static Pose mix(const Pose& p1, const Pose& p2, float t);
53 
54  /* See static getReducedAndReadable. Applies that function to the current pose. */
55  Pose getReducedAndReadable() const;
56 
57  /* Attempts to take existing pose and extract
58  * translation/scale/orientation transformations from the pre and post
59  * affine matrices. These transformations are then merged with existing
60  * translation/scale/orientation in order to produce a new `Pose` that
61  * has a minimal amount of transformation occuring in the post and pre
62  * affine matrices, and is more readable */
63  static Pose getReducedAndReadable(const glm::mat4& matrix);
64 
65 
66  inline void setTranslation(const glm::vec3& new_translation) {_dirty_matrix = true; translation = new_translation;}
67  inline void setOrientation(const glm::quat& new_orientation) {_dirty_matrix = true; orientation = new_orientation;}
68  inline void setScale(const glm::vec3& new_scale) {_dirty_matrix = true; scale = new_scale;}
69  inline void setPostTransformMatrix(const glm::mat4& post_transform){_dirty_matrix = true; postaffine = post_transform;}
70  inline void setPreTransformaMatrix(const glm::mat4& pre_transform){_dirty_matrix = true; preaffine = pre_transform;}
71  inline void appendTransformToEnd(const glm::mat4& transform) {_dirty_matrix = true; postaffine *= transform;}
72  inline void appendTransformToStart(const glm::mat4& transform) {_dirty_matrix = true; preaffine = transform * preaffine;}
73 
74  Pose& operator+=(const glm::vec3& rhs);
75  Pose& operator-=(const glm::vec3& rhs);
76  Pose& operator*=(const glm::vec3& rhs);
77  Pose& operator/=(const glm::vec3& rhs);
78  Pose& operator*=(const Pose& rhs);
79  Pose& operator*=(const glm::mat4& rhs);
80 
81  void print() const;
82  std::string asString() const;
83 
84  operator std::string() const {
85  return("{Pose:\n center @ <" + glm::to_string(getCenterOfSpace()) + "> orientation: <" + glm::to_string(orientation) + "> scale: <" + glm::to_string(scale) + "> \n " + glm::to_string(getMatrix()) + "\n}");
86  }
87  operator std::string() {
88  return("{Pose:\n center @ <" + glm::to_string(getCenterOfSpace()) + "> orientation: <" + glm::to_string(orientation) + "> scale: <" + glm::to_string(scale) + "> \n " + glm::to_string(getMatrix()) + "\n}");
89  }
90  operator glm::mat4() const {return(getMatrix());}
91  operator glm::mat4() {return(getMatrix());}
92 
93  inline glm::mat4 getMatrix() const{
94  if(_dirty_matrix){
95  return(postaffine * glm::translate(glm::mat4(1.0), translation) * glm::mat4_cast(orientation) * glm::scale(glm::mat4(1.0), scale) * preaffine);
96  }
97  return(_cache_matrix);
98  }
99 
100  inline void updateMatrixCache(){_update_matrix_cache();}
101 
102  protected:
103  glm::vec3 translation = glm::vec3(0.0);
104  glm::quat orientation = glm::quat(1.0, 0.0, 0.0, 0.0);
105  glm::vec3 scale = glm::vec3(1.0);
106  glm::mat4 preaffine = glm::mat4(1.0);
107  glm::mat4 postaffine = glm::mat4(1.0);
108 
109  inline void _update_matrix_cache(){
110  _cache_matrix = postaffine * glm::translate(glm::mat4(1.0), translation) * glm::mat4_cast(orientation) * glm::scale(glm::mat4(1.0), scale) * preaffine;
111  _dirty_matrix = false;
112  }
113 
114  private:
115  bool _dirty_matrix = true;
116  glm::mat4 _cache_matrix;
117 
118  public:
119  friend Pose operator+(Pose lhs, const glm::vec3& rhs){
120  lhs.translation += rhs;
121  lhs._update_matrix_cache();
122  return(lhs);
123  }
124  friend Pose operator-(Pose lhs, const glm::vec3& rhs){
125  lhs.translation -= rhs;
126  lhs._update_matrix_cache();
127  return(lhs);
128  }
129  friend Pose operator*(Pose lhs, const glm::vec3& rhs){
130  lhs.translation *= rhs;
131  lhs._update_matrix_cache();
132  return(lhs);
133  }
134  friend Pose operator/(Pose lhs, const glm::vec3& rhs){
135  lhs.translation /= rhs;
136  lhs._update_matrix_cache();
137  return(lhs);
138  }
139  friend Pose operator*(Pose lhs, const Pose& rhs){
140  lhs.preaffine = lhs.preaffine * rhs.getMatrix();
141  lhs._update_matrix_cache();
142  return(lhs);
143  }
144  friend Pose operator*(Pose lhs, const glm::mat4& rhs){
145  lhs.preaffine = lhs.preaffine * rhs;
146  lhs._update_matrix_cache();
147  return(lhs);
148  }
149 };
150 
151 #endif
Definition: AttachableComponent.hpp:5
Definition: Pose.hpp:11