Class: Bestguigui::Render3D::Mat4

Inherits:
Object
  • Object
show all
Defined in:
lib/bestguigui/render_3d/mat4.rb

Overview

Matrice 4x4, colonne-major (convention OpenGL) — le strict nécessaire pour remplacer la pile de matrices figée (glMatrixMode/glRotatef/ gluPerspective/gluLookAt) par des matrices calculées à la main et envoyées aux shaders comme uniforms.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data = Mat4.identity_data) ⇒ Mat4

Returns a new instance of Mat4.



10
11
12
# File 'lib/bestguigui/render_3d/mat4.rb', line 10

def initialize(data = Mat4.identity_data)
  @data = data
end

Instance Attribute Details

#dataObject (readonly)

16 floats, colonne-major



8
9
10
# File 'lib/bestguigui/render_3d/mat4.rb', line 8

def data
  @data
end

Class Method Details

.identityObject



18
19
20
# File 'lib/bestguigui/render_3d/mat4.rb', line 18

def self.identity
  new
end

.identity_dataObject



14
15
16
# File 'lib/bestguigui/render_3d/mat4.rb', line 14

def self.identity_data
  [1.0, 0, 0, 0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 0, 0, 1.0]
end

.look_at(eye, target, up) ⇒ Object

Équivalent de gluLookAt. eye/target/up : tableaux [x, y, z].



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/bestguigui/render_3d/mat4.rb', line 80

def self.look_at(eye, target, up)
  ex, ey, ez = eye
  tx, ty, tz = target
  ux, uy, uz = up

  fx, fy, fz = tx - ex, ty - ey, tz - ez
  flen = Math.sqrt((fx * fx) + (fy * fy) + (fz * fz))
  fx /= flen
  fy /= flen
  fz /= flen

  sx = (fy * uz) - (fz * uy)
  sy = (fz * ux) - (fx * uz)
  sz = (fx * uy) - (fy * ux)
  slen = Math.sqrt((sx * sx) + (sy * sy) + (sz * sz))
  sx /= slen
  sy /= slen
  sz /= slen

  rux = (sy * fz) - (sz * fy)
  ruy = (sz * fx) - (sx * fz)
  ruz = (sx * fy) - (sy * fx)

  new([
    sx, rux, -fx, 0,
    sy, ruy, -fy, 0,
    sz, ruz, -fz, 0,
    -((sx * ex) + (sy * ey) + (sz * ez)),
    -((rux * ex) + (ruy * ey) + (ruz * ez)),
    (fx * ex) + (fy * ey) + (fz * ez),
    1.0
  ])
end

.perspective(fovy_degrees, aspect, near, far) ⇒ Object

Équivalent de gluPerspective. near/far forcés en Float : si on les laisse en Integer (ex: near: 1, far: 1000, les valeurs par défaut de Camera), (far + near) / (near - far) fait de la division entière en Ruby et explose la matrice (ex: 1001/-999 devient -2 au lieu de -1.002) — tout sort du frustum, écran vide sans erreur GL.



67
68
69
70
71
72
73
74
75
76
77
# File 'lib/bestguigui/render_3d/mat4.rb', line 67

def self.perspective(fovy_degrees, aspect, near, far)
  near = near.to_f
  far = far.to_f
  f = 1.0 / Math.tan((fovy_degrees * Math::PI / 180.0) / 2.0)
  new([
    f / aspect, 0, 0, 0,
    0, f, 0, 0,
    0, 0, (far + near) / (near - far), -1.0,
    0, 0, (2.0 * far * near) / (near - far), 0
  ])
end

.rotation_x(degrees) ⇒ Object



40
41
42
43
44
45
46
47
48
49
# File 'lib/bestguigui/render_3d/mat4.rb', line 40

def self.rotation_x(degrees)
  r = degrees * Math::PI / 180.0
  c, s = Math.cos(r), Math.sin(r)
  new([
    1.0, 0, 0, 0,
    0, c, s, 0,
    0, -s, c, 0,
    0, 0, 0, 1.0
  ])
end

.rotation_y(degrees) ⇒ Object



51
52
53
54
55
56
57
58
59
60
# File 'lib/bestguigui/render_3d/mat4.rb', line 51

def self.rotation_y(degrees)
  r = degrees * Math::PI / 180.0
  c, s = Math.cos(r), Math.sin(r)
  new([
    c, 0, -s, 0,
    0, 1.0, 0, 0,
    s, 0, c, 0,
    0, 0, 0, 1.0
  ])
end

.scaling(x, y, z) ⇒ Object



31
32
33
34
35
36
37
38
# File 'lib/bestguigui/render_3d/mat4.rb', line 31

def self.scaling(x, y, z)
  new([
    x.to_f, 0, 0, 0,
    0, y.to_f, 0, 0,
    0, 0, z.to_f, 0,
    0, 0, 0, 1.0
  ])
end

.translation(x, y, z) ⇒ Object



22
23
24
25
26
27
28
29
# File 'lib/bestguigui/render_3d/mat4.rb', line 22

def self.translation(x, y, z)
  new([
    1.0, 0, 0, 0,
    0, 1.0, 0, 0,
    0, 0, 1.0, 0,
    x.to_f, y.to_f, z.to_f, 1.0
  ])
end

Instance Method Details

#*(other) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/bestguigui/render_3d/mat4.rb', line 114

def *(other)
  a = @data
  b = other.data
  result = Array.new(16, 0.0)
  4.times do |col|
    4.times do |row|
      sum = 0.0
      4.times { |k| sum += a[(k * 4) + row] * b[(col * 4) + k] }
      result[(col * 4) + row] = sum
    end
  end
  Mat4.new(result)
end

#to_aObject



128
129
130
# File 'lib/bestguigui/render_3d/mat4.rb', line 128

def to_a
  @data
end