lib/cyberarm_engine/transform.rb in cyberarm_engine-0.14.0 vs lib/cyberarm_engine/transform.rb in cyberarm_engine-0.15.0

- old
+ new

@@ -1,14 +1,15 @@ module CyberarmEngine # Basic 4x4 matrix operations class Transform attr_reader :elements + def initialize(matrix) @elements = matrix raise "Transform is wrong size! Got #{@elements.size}, expected 16" if 16 != @elements.size - raise "Invalid value for matrix, must all be numeric!" if @elements.any? { |e| e.nil? || !e.is_a?(Numeric)} + raise "Invalid value for matrix, must all be numeric!" if @elements.any? { |e| e.nil? || !e.is_a?(Numeric) } end def self.identity Transform.new( [ @@ -25,14 +26,14 @@ # 2d rotate operation, replicates Gosu's Gosu.rotate function def self.rotate(angle, rotate_around = nil) double c = Math.cos(angle).degrees_to_radians double s = Math.sin(angle).degrees_to_radians matrix = [ - +c, +s, 0, 0, - -s, +c, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1, + +c, +s, 0, 0, + -s, +c, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 ] rotate_matrix = Transform.new(matrix, rows: 4, columns: 4) if rotate_around && (rotate_around.x != 0.0 || rotate_around.y != 0.0) @@ -42,21 +43,21 @@ concat(translate(negative_rotate_around), rotate_matrix), translate(rotate_around) ) end - return rotate_matrix + rotate_matrix end # 2d translate operation, replicates Gosu's Gosu.translate function def self.translate(vector) x, y, z = vector.to_a[0..2] matrix = [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, - x, y, z, 1, + x, y, z, 1 ] Transform.new(matrix) end @@ -65,11 +66,11 @@ scale_x, scale_y, scale_z = vector.to_a[0..2] matrix = [ scale_x, 0, 0, 0, 0, scale_y, 0, 0, 0, 0, scale_z, 0, - 0, 0, 0, 1, + 0, 0, 0, 1 ] scale_matrix = Transform.new(matrix) if center_around && (center_around.x != 0.0 || center_around.y != 0.0) @@ -79,11 +80,11 @@ concat(translate(negative_center_around), scale_matrix), translate(center_around) ) end - return scale_matrix + scale_matrix end def self.concat(left, right) matrix = Array.new(left.elements.size) rows = 4 @@ -105,17 +106,17 @@ x, y, z = vector.to_a[0..2] matrix = [ 1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, - 0, 0, 0, 1, + 0, 0, 0, 1 ] Transform.new(matrix) end - def self.rotate_3d(vector, order = "zyx") + def self.rotate_3d(vector, _order = "zyx") x, y, z = vector.to_a[0..2].map { |axis| axis * Math::PI / 180.0 } rotation_x = Transform.new( [ 1, 0, 0, 0, @@ -161,11 +162,11 @@ Transform.new( [ x * x * n + c, x * y * n - z * s, x * z * n + y * s, 0, y * x * n + z * s, y * y * n + c, y * z * n - x * s, 0, x * z * n - y * s, y * z * n + x * s, z * z * n + c, 0, - 0, 0, 0, 1.0 + 0, 0, 0, 1.0 ] ) end def self.scale_3d(vector) @@ -188,16 +189,39 @@ Transform.new( [ f / aspect_ratio, 0.0, 0.0, 0.0, 0.0, f, 0.0, 0.0, - 0.0, 0.0, zn, zf, + 0.0, 0.0, zn, zf, 0.0, 0.0, -1.0, 0.0 ] ) end + def self.orthographic(left, right, bottom, top, near, far) + s = Vector.new( + 2 / (right - left.to_f), + 2 / (top - bottom.to_f), + -2 / (far - near.to_f) + ) + + t = Vector.new( + (right + left.to_f) / (right - left.to_f), + (top + bottom.to_f) / (top - bottom.to_f), + (far + near.to_f) / (far - near.to_f) + ) + + Transform.new( + [ + s.x, 0.0, 0.0, t.x, + 0.0, s.y, 0.0, t.y, + 0.0, 0.0, s.z, t.z, + 0.0, 0.0, 0.0, 1.0 + ] + ) + end + def self.view(eye, orientation) # https://www.3dgep.com/understanding-the-view-matrix/#The_View_Matrix cosPitch = Math.cos(orientation.z * Math::PI / 180.0) sinPitch = Math.sin(orientation.z * Math::PI / 180.0) cosYaw = Math.cos(orientation.y * Math::PI / 180.0) @@ -207,20 +231,19 @@ y_axis = Vector.new(sinYaw * sinPitch, cosPitch, cosYaw * sinPitch) z_axis = Vector.new(sinYaw * cosPitch, -sinPitch, cosPitch * cosYaw) Transform.new( [ - x_axis.x, y_axis.y, z_axis.z, 0, - x_axis.x, y_axis.y, z_axis.z, 0, - x_axis.x, y_axis.y, z_axis.z, 0, + x_axis.x, y_axis.y, z_axis.z, 0, + x_axis.x, y_axis.y, z_axis.z, 0, + x_axis.x, y_axis.y, z_axis.z, 0, -x_axis.dot(eye), -y_axis.dot(eye), -z_axis.dot(eye), 1 ] ) end def *(other) - case other when CyberarmEngine::Vector matrix = @elements.clone list = other.to_a @@ -229,11 +252,11 @@ end Transform.new(matrix) when CyberarmEngine::Transform - return multiply_matrices(other) + multiply_matrices(other) else p other.class raise TypeError, "Expected CyberarmEngine::Vector or CyberarmEngine::Transform got #{other.class}" end end @@ -254,11 +277,11 @@ matrix[4 * y + x] += get(x, k) * other.get(k, y) end end end - return Transform.new(matrix) + Transform.new(matrix) end # arranges Matrix in column major form def to_gl e = @elements @@ -268,6 +291,6 @@ e[2], e[6], e[10], e[14], e[3], e[7], e[11], e[15] ] end end -end \ No newline at end of file +end