SHARE
TWEET

Untitled

a guest Jul 15th, 2019 105 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //
  2. // Created by mtesseract on 7/5/19.
  3. //
  4.  
  5. #ifndef MACH_TRANSFORM_HPP
  6. #define MACH_TRANSFORM_HPP
  7.  
  8. #include <math/linalg/LinAlgTypes.hpp>
  9. #include <math/linalg/Matrix/RotationMatrix.hpp>
  10. #include <math/linalg/Matrix/ScaleMatrix.hpp>
  11. #include <math/linalg/Matrix/MatrixUtils.hpp>
  12. #include <auxiliary/Properties.hpp>
  13.  
  14.  
  15. namespace mach {
  16.     template<typename T>
  17.     class Transform {
  18.         Matrix4<T> m_local_transform;
  19.  
  20.         Vector3<T> m_local_position;
  21.         Quaternion<T> m_local_rotation;
  22.         Vector3<T> m_local_scale;
  23.  
  24.         Matrix4<T> m_world_transform;
  25.  
  26.         Vector3<T> m_world_position;
  27.         Quaternion<T> m_world_rotation;
  28.         Vector3<T> m_world_scale;
  29.  
  30.         bool m_changed;
  31.  
  32.         std::vector<std::weak_ptr<Transform>> m_children;
  33.         std::shared_ptr<Transform> m_parent;
  34.  
  35.         void notify_children() {
  36.             for (int i = m_children.size() - 1; i >= 0; --i) {
  37.                 auto child = m_children[i].lock();
  38.                 child->mark_changed();
  39.             }
  40.         }
  41.  
  42.         void update_transform() {
  43.             m_local_transform = math::compose_trs(m_local_position, m_local_rotation, m_local_scale);
  44.             if (m_parent) {
  45.                 m_world_transform = m_parent->get_mat() * m_local_transform;
  46.             } else {
  47.                 m_world_transform = m_local_transform;
  48.             }
  49.             update_world_vars();
  50.             notify_children();
  51.             m_changed = false;
  52.         }
  53.  
  54.         //To be used in conjunction with the world pos/rot/scale setters
  55.         Matrix4<T> create_local_transform(const Matrix4<T> &p_world_transform) {
  56.             if (m_parent) {
  57.                 return m_local_transform = m_parent->get_mat().inverse() * p_world_transform;
  58.             } else {
  59.                 return m_local_transform = p_world_transform;
  60.             }
  61.         }
  62.  
  63.         void update_world_vars() {
  64.             math::decompose_trs(m_world_transform, &m_world_position, &m_world_rotation, &m_world_scale);
  65.         }
  66.  
  67.         void update_local_vars() {
  68.             math::decompose_trs(m_local_transform, &m_local_position, &m_local_rotation, &m_local_scale);
  69.         }
  70.  
  71.         void add_child(std::weak_ptr<Transform> p_child) {
  72.             auto it = std::find(m_children.begin(), m_children.end(),
  73.                                 p_child); //This line will not work for some reason
  74.             if (it == m_children.end()) {
  75.                 m_children.push_back(p_child);
  76.                 p_child.lock()->m_parent = this; //This line will not work
  77.             }
  78.         }
  79.  
  80.         void check_mat() {
  81.             if (m_changed) {
  82.                 update_transform();
  83.             }
  84.         }
  85.  
  86.         void mark_changed() {
  87.             m_changed = true;
  88.             notify_children();
  89.         }
  90.  
  91.     public:
  92.  
  93.         Transform(const Vector3<T> &p_position = Vector3<T>::zero(),
  94.                   const Quaternion<T> &p_rotation = Quaternion<T>::identity(),
  95.                   const Vector3<T> &p_scale = Vector3<T>::one()) :
  96.                 m_local_position(p_position),
  97.                 m_local_rotation(p_rotation),
  98.                 m_local_scale(p_scale),
  99.                 m_local_transform(Matrix4<T>::identity()),
  100.                 m_world_position(Vector3<T>::zero()),
  101.                 m_world_rotation(Quaternion<T>::identity()),
  102.                 m_world_scale(Vector3<T>::one()),
  103.                 m_world_transform(Matrix4<T>::identity()),
  104.                 m_changed(true),
  105.                 m_parent(nullptr) {
  106.         }
  107.  
  108.         static void add_child(std::shared_ptr<Transform> p_parent, std::weak_ptr<Transform> p_child) {
  109.             if (p_parent && !p_child.expired()) {
  110.                 p_parent->m_children.push_back(p_child);
  111.                 p_child.lock()->m_parent = p_parent;
  112.             }
  113.         }
  114.  
  115.         PROPERTY_READONLY(Quaternion<T>, rotation, get_world_rotation);
  116.         PROPERTY(Vector3<T>, position, get_world_position, set_world_position);
  117.         PROPERTY_READONLY(Vector3<T>, scale, get_world_scale);
  118.         PROPERTY(Quaternion<T>, local_rotation, get_local_rotation, set_local_rotation);
  119.         PROPERTY(Vector3<T>, local_position, get_local_position, set_local_position);
  120.         PROPERTY(Vector3<T>, local_scale, get_local_scale, set_local_scale);
  121.  
  122.         Matrix4<T> get_mat() {
  123.             check_mat();
  124.             return m_local_transform;
  125.         }
  126.  
  127.         void set_world_position(const Vector3<T> &p_position) {
  128.             m_world_position = p_position;
  129.             m_world_transform[3] = Vector4<T>(p_position.x, p_position.y, p_position.z, m_world_transform[3][3]);
  130.             create_local_transform(m_world_transform);
  131.             update_local_vars();
  132.             notify_children();
  133.         };
  134.  
  135.         void set_world_position(const Quaternion<T> &p_rotation) {
  136.             m_world_rotation = p_rotation;
  137.             //m_world_transform[3] = Vector4<T>(p_position.x, p_position.y, p_position.z, m_world_transform[3][3]);
  138.             create_local_transform(m_world_transform);
  139.             update_local_vars();
  140.             notify_children();
  141.         };
  142.  
  143.         Quaternion<T> get_world_rotation() {
  144.             check_mat();
  145.             return m_world_rotation;
  146.         };
  147.  
  148.         Vector3<T> get_world_position() {
  149.             check_mat();
  150.             return m_world_position;
  151.         };
  152.  
  153.         Vector3<T> get_world_scale() {
  154.             check_mat();
  155.             return m_world_scale;
  156.         };
  157.  
  158.         Quaternion<T> get_local_rotation() const {
  159.             return m_local_rotation;
  160.         };
  161.  
  162.         Vector3<T> get_local_position() const {
  163.             return m_local_position;
  164.         };
  165.  
  166.         Vector3<T> get_local_scale() const {
  167.             return m_local_scale;
  168.         };
  169.  
  170.         void set_local_rotation(const Quaternion<T> &p_rotation) {
  171.             mark_changed();
  172.             m_local_rotation = p_rotation;
  173.         };
  174.  
  175.         void set_local_position(const Vector3<T> &p_position) {
  176.             mark_changed();
  177.             m_local_position = p_position;
  178.         };
  179.  
  180.         void set_local_scale(const Vector3<T> &p_scale) {
  181.             mark_changed();
  182.             m_local_scale = p_scale;
  183.         };
  184.     };
  185. }
  186.  
  187. #endif //MACH_TRANSFORM_HPP
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top