mirror of
https://github.com/cyberarm/cyberarm_engine.git
synced 2025-12-16 13:12:34 +00:00
Added initial 3D support to Transform
This commit is contained in:
@@ -188,18 +188,19 @@ module CyberarmEngine
|
||||
def set_uniform(variable, value, location = nil)
|
||||
attr_loc = location ? location : attribute_location(variable)
|
||||
|
||||
case value.class.to_s.downcase.to_sym
|
||||
case value.class.to_s.split("::").last.downcase.to_sym
|
||||
when :integer
|
||||
glUniform1i(attr_loc, value)
|
||||
when :float
|
||||
glUniform1f(attr_loc, value)
|
||||
when :string
|
||||
when :array
|
||||
when :transform
|
||||
glUniformMatrix4fv(attr_loc, 1, GL_FALSE, value.elements.pack("F16"))
|
||||
when :vector
|
||||
glUniformVec4f(attr_loc, *value.to_a)
|
||||
else
|
||||
raise NotImplementedError, "Shader support for #{value.class.inspect} not implemented."
|
||||
end
|
||||
|
||||
Window.handle_gl_error
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,12 +1,28 @@
|
||||
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)}
|
||||
end
|
||||
|
||||
def self.identity
|
||||
Transform.new(
|
||||
[
|
||||
1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
### 2D Operations meant for interacting with Gosu ###
|
||||
|
||||
# 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
|
||||
@@ -31,6 +47,7 @@ module CyberarmEngine
|
||||
return 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 = [
|
||||
@@ -43,6 +60,7 @@ module CyberarmEngine
|
||||
Transform.new(matrix)
|
||||
end
|
||||
|
||||
# 2d scale operation, replicates Gosu's Gosu.rotate function
|
||||
def self.scale(vector, center_around = nil)
|
||||
scale_x, scale_y, scale_z = vector.to_a[0..2]
|
||||
matrix = [
|
||||
@@ -80,5 +98,94 @@ module CyberarmEngine
|
||||
|
||||
Transform.new(matrix)
|
||||
end
|
||||
|
||||
#### 3D Operations meant for OpenGL ###
|
||||
|
||||
def self.translate_3d(vector)
|
||||
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,
|
||||
]
|
||||
|
||||
Transform.new(matrix)
|
||||
end
|
||||
|
||||
def self.rotate_3d(vector, order = "xyz")
|
||||
x, y, z = vector.to_a[0..2]
|
||||
|
||||
rotation_x = Transform.new(
|
||||
[
|
||||
1, 0, 0, 0,
|
||||
0, Math.cos(x), -Math.sin(x), 0,
|
||||
0, Math.sin(x), Math.cos(x), 0,
|
||||
0, 0, 0, 1,
|
||||
]
|
||||
)
|
||||
|
||||
rotation_y = Transform.new(
|
||||
[
|
||||
Math.cos(y), 0, -Math.sin(y), 0,
|
||||
0, 1, 0, 0,
|
||||
Math.sin(y), 1, Math.cos(y), 0,
|
||||
0, 0, 1, 1
|
||||
]
|
||||
)
|
||||
|
||||
rotation_z = Transform.new(
|
||||
[
|
||||
Math.cos(z), -Math.sin(z), 0, 0,
|
||||
Math.sin(z), Math.cos(z), 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1
|
||||
]
|
||||
)
|
||||
|
||||
rotation_x * rotation_y * rotation_z
|
||||
end
|
||||
|
||||
def *(other)
|
||||
|
||||
case other
|
||||
when CyberarmEngine::Vector
|
||||
matrix = Array.new(@elements.size)
|
||||
list = other.to_a
|
||||
|
||||
@elements.each_with_index do |e, i|
|
||||
matrix[i] = e + list[i]
|
||||
end
|
||||
|
||||
Transform.new(matrix)
|
||||
|
||||
when CyberarmEngine::Transform
|
||||
return multiply_matrices(other)
|
||||
else
|
||||
p other.class
|
||||
raise TypeError, "Expected CyberarmEngine::Vector or CyberarmEngine::Transform got #{other.class}"
|
||||
end
|
||||
end
|
||||
|
||||
def get(x, y)
|
||||
width = 4
|
||||
|
||||
# puts "Transform|#{self.object_id} -> #{@elements[width * y + x].inspect} (index: #{width * y + x})"
|
||||
@elements[width * y + x]
|
||||
end
|
||||
|
||||
def multiply_matrices(other)
|
||||
matrix = Array.new(16, 0)
|
||||
|
||||
4.times do |x|
|
||||
4.times do |y|
|
||||
4.times do |k|
|
||||
matrix[4 * y + x] += get(x, k) * other.get(k, y)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Transform.new(matrix)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user