Size: 2149 bytes.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// cs/renderer/linalg/transform.hh
#ifndef CS_RENDERER_LINALG_TRANSFORM_HH
#define CS_RENDERER_LINALG_TRANSFORM_HH

// Much of this file is based on:
// https://pbr-book.org/3ed-2018/Geometry_and_Transformations/Transformations

#include "cs/renderer/geo/cross.hh"
#include "cs/renderer/geo/vector3.h"
#include "cs/renderer/linalg/matrix4x4.hh"
#include "cs/result.hh"

namespace cs::renderer::linalg {

using m4x4 = ::cs::renderer::linalg::Matrix4x4;
using v3 = ::cs::renderer::geo::Vector3;
using ::cs::Error;
using ::cs::ResultOr;
using ::cs::renderer::geo::cross;

struct Transform {
 private:
  m4x4 m_;
  m4x4 m_inv_;

 public:
  // Default transform is identity matrix
  explicit Transform()
      : Transform(Matrix4x4(), Matrix4x4()) {}
  Transform(const m4x4& m)
      : Transform(m, m.inverse().value()) {}
  Transform(m4x4 m, m4x4 m_inv) : m_(m), m_inv_(m_inv) {}
  Transform inverse() const {
    return Transform(m_inv_, m_);
  }
  inline ResultOr<p3> operator()(const p3& p) const {
    float x = p.x, y = p.y, z = p.z;
    // clang-format off
    float xp = m_.data_[0][0] * x + m_.data_[0][1] * y + m_.data_[0][2] * z + m_.data_[0][3];
    float yp = m_.data_[1][0] * x + m_.data_[1][1] * y + m_.data_[1][2] * z + m_.data_[1][3];
    float zp = m_.data_[2][0] * x + m_.data_[2][1] * y + m_.data_[2][2] * z + m_.data_[2][3];
    float wp = m_.data_[3][0] * x + m_.data_[3][1] * y + m_.data_[3][2] * z + m_.data_[3][3];
    // clang-format on
    if (FloatsNear(wp, 0)) {
      return TRACE(Error("Division by zero"));
    }
    return p3(xp, yp, zp) / wp;
  }
};

namespace transforms {

Transform Translate(v3 delta);

Transform Scale(float x, float y, float z);

Transform RotateX(float theta_rad);

Transform RotateY(float theta_rad);

Transform RotateZ(float theta_rad);

// Rotation around arbitrary axis. See:
// https://github.com/mmp/pbrt-v3/blob/13d871faae88233b327d04cda24022b8bb0093ee/src/core/transform.cpp#L179-L201
Transform Rotate(float theta_rad, const v3& axis);

Transform LookAt(p3 pos, p3 look, v3 up);

}  // namespace transforms

}  // namespace cs::renderer::linalg

#endif  // CS_RENDERER_LINALG_TRANSFORM_HH
v0 (commit) © 2025 @p13i.io | Load balancer proxied to: cs-code-viewer-1:8080 in 4ms.