mirror of
https://github.com/cyberarm/cyberarm_engine.git
synced 2025-12-17 21:42:34 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d8551c7428 | |||
| 0017c841dd | |||
| 8cedb40283 | |||
| 93a4e9a2b8 | |||
| a0c0180411 | |||
| 7f25cd49fe | |||
| 7e6a17fe9f | |||
| 0ea1e5c2ff |
36
README.md
36
README.md
@@ -1,8 +1,13 @@
|
|||||||
# CyberarmEngine
|
# CyberarmEngine
|
||||||
|
|
||||||
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/cyberarm_engine`. To experiment with that code, run `bin/console` for an interactive prompt.
|
Yet Another Game Engine On Top Of Gosu
|
||||||
|
|
||||||
TODO: Delete this and the text above, and describe your gem
|
## Features
|
||||||
|
* [Shoes-like](http://shoesrb.com) GUI support
|
||||||
|
* OpenGL Shader support (requires [opengl-bindings](https://github.com/vaiorabbit/ruby-opengl) gem)
|
||||||
|
* Includes classes for handling Vectors, Rays, Bounding Boxes, and Transforms
|
||||||
|
* GameState system
|
||||||
|
* Monolithic GameObjects
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@@ -22,7 +27,32 @@ Or install it yourself as:
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
TODO: Write usage instructions here
|
```ruby
|
||||||
|
require "cyberarm_engine"
|
||||||
|
|
||||||
|
class Hello < CyberarmEngine::GuiState
|
||||||
|
def setup
|
||||||
|
stack do
|
||||||
|
label "Hello World!"
|
||||||
|
|
||||||
|
button "close" do
|
||||||
|
window.close
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Window < CyberarmEngine::Engine
|
||||||
|
def initialize
|
||||||
|
super
|
||||||
|
self.show_cursor = true
|
||||||
|
|
||||||
|
push_state(Hello)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Window.new.show
|
||||||
|
```
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ rescue LoadError => e
|
|||||||
pp e
|
pp e
|
||||||
require "gosu"
|
require "gosu"
|
||||||
end
|
end
|
||||||
|
require "json"
|
||||||
|
|
||||||
require_relative "cyberarm_engine/version"
|
require_relative "cyberarm_engine/version"
|
||||||
|
|
||||||
@@ -24,6 +25,7 @@ require_relative "cyberarm_engine/animator"
|
|||||||
|
|
||||||
require_relative "cyberarm_engine/text"
|
require_relative "cyberarm_engine/text"
|
||||||
require_relative "cyberarm_engine/timer"
|
require_relative "cyberarm_engine/timer"
|
||||||
|
require_relative "cyberarm_engine/config_file"
|
||||||
|
|
||||||
require_relative "cyberarm_engine/ui/dsl"
|
require_relative "cyberarm_engine/ui/dsl"
|
||||||
|
|
||||||
|
|||||||
46
lib/cyberarm_engine/config_file.rb
Normal file
46
lib/cyberarm_engine/config_file.rb
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
module CyberarmEngine
|
||||||
|
class ConfigFile
|
||||||
|
def initialize(file:)
|
||||||
|
@file = file
|
||||||
|
|
||||||
|
if File.exist?(@file)
|
||||||
|
deserialize
|
||||||
|
else
|
||||||
|
@data = {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def []= *keys, value
|
||||||
|
last_key = keys.last
|
||||||
|
|
||||||
|
if keys.size == 1
|
||||||
|
hash = @data
|
||||||
|
else
|
||||||
|
keys.pop
|
||||||
|
hash = @data[keys.shift] ||= {}
|
||||||
|
|
||||||
|
keys.each do |key|
|
||||||
|
hash[key] ||= {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
hash[last_key] = value
|
||||||
|
end
|
||||||
|
|
||||||
|
def get(*keys)
|
||||||
|
@data.dig(*keys)
|
||||||
|
end
|
||||||
|
|
||||||
|
def serialize
|
||||||
|
JSON.dump(@data)
|
||||||
|
end
|
||||||
|
|
||||||
|
def deserialize
|
||||||
|
@data = JSON.parse(File.read(@file), symbolize_names: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def save!
|
||||||
|
File.open(@file, "w") { |f| f.write(serialize) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -3,7 +3,7 @@ module CyberarmEngine
|
|||||||
include Common
|
include Common
|
||||||
|
|
||||||
attr_accessor :options, :global_pause
|
attr_accessor :options, :global_pause
|
||||||
attr_reader :game_objects, :containers
|
attr_reader :game_objects
|
||||||
|
|
||||||
def initialize(options={})
|
def initialize(options={})
|
||||||
@options = options
|
@options = options
|
||||||
|
|||||||
@@ -2,13 +2,44 @@ module CyberarmEngine
|
|||||||
# Ref: https://github.com/vaiorabbit/ruby-opengl/blob/master/sample/OrangeBook/brick.rb
|
# Ref: https://github.com/vaiorabbit/ruby-opengl/blob/master/sample/OrangeBook/brick.rb
|
||||||
class Shader
|
class Shader
|
||||||
include OpenGL
|
include OpenGL
|
||||||
@@shaders = {}
|
@@shaders = {} # Cache for {Shader} instances
|
||||||
PREPROCESSOR_CHARACTER = "@"
|
PREPROCESSOR_CHARACTER = "@".freeze # magic character for preprocessor phase of {Shader} compilation
|
||||||
|
|
||||||
|
# add instance of {Shader} to cache
|
||||||
|
#
|
||||||
|
# @param name [String]
|
||||||
|
# @param instance [Shader]
|
||||||
def self.add(name, instance)
|
def self.add(name, instance)
|
||||||
@@shaders[name] = instance
|
@@shaders[name] = instance
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# removes {Shader} from cache and cleans up
|
||||||
|
#
|
||||||
|
# @param name [String]
|
||||||
|
def self.delete(name)
|
||||||
|
shader = @@shaders.dig(name)
|
||||||
|
|
||||||
|
if shader
|
||||||
|
@@shaders.delete(name)
|
||||||
|
|
||||||
|
if shader.compiled?
|
||||||
|
glDeleteProgram(shader.program)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# runs _block_ using {Shader} with _name_
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
#
|
||||||
|
# CyberarmEngine::Shader.use("blur") do |shader|
|
||||||
|
# shader.uniform_float("radius", 20.0)
|
||||||
|
# # OpenGL Code that uses shader
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# @param name [String] name of {Shader} to use
|
||||||
|
# @return [void]
|
||||||
def self.use(name, &block)
|
def self.use(name, &block)
|
||||||
shader = @@shaders.dig(name)
|
shader = @@shaders.dig(name)
|
||||||
if shader
|
if shader
|
||||||
@@ -18,22 +49,37 @@ module CyberarmEngine
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# returns whether {Shader} with _name_ is in cache
|
||||||
|
#
|
||||||
|
# @param name [String]
|
||||||
|
# @return [Boolean]
|
||||||
def self.available?(name)
|
def self.available?(name)
|
||||||
@@shaders.dig(name).is_a?(Shader)
|
@@shaders.dig(name).is_a?(Shader)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# returns instance of {Shader}, if it exists
|
||||||
|
#
|
||||||
|
# @param name [String]
|
||||||
|
# @return [Shader?]
|
||||||
def self.get(name)
|
def self.get(name)
|
||||||
@@shaders.dig(name)
|
@@shaders.dig(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# returns currently active {Shader}, if one is active
|
||||||
|
#
|
||||||
|
# @return [Shader?]
|
||||||
def self.active_shader
|
def self.active_shader
|
||||||
@active_shader
|
@active_shader
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# sets currently active {Shader}
|
||||||
|
#
|
||||||
|
# @param instance [Shader] instance of {Shader} to set as active
|
||||||
def self.active_shader=(instance)
|
def self.active_shader=(instance)
|
||||||
@active_shader = instance
|
@active_shader = instance
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# stops using currently active {Shader}
|
||||||
def self.stop
|
def self.stop
|
||||||
shader = Shader.active_shader
|
shader = Shader.active_shader
|
||||||
|
|
||||||
@@ -44,11 +90,18 @@ module CyberarmEngine
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# returns location of OpenGL Shader uniform
|
||||||
|
#
|
||||||
|
# @param variable [String]
|
||||||
def self.attribute_location(variable)
|
def self.attribute_location(variable)
|
||||||
raise RuntimeError, "No active shader!" unless Shader.active_shader
|
raise RuntimeError, "No active shader!" unless Shader.active_shader
|
||||||
Shader.active_shader.attribute_location(variable)
|
Shader.active_shader.attribute_location(variable)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# sets _variable_ to _value_
|
||||||
|
#
|
||||||
|
# @param variable [String]
|
||||||
|
# @param value
|
||||||
def self.set_uniform(variable, value)
|
def self.set_uniform(variable, value)
|
||||||
raise RuntimeError, "No active shader!" unless Shader.active_shader
|
raise RuntimeError, "No active shader!" unless Shader.active_shader
|
||||||
Shader.active_shader.set_uniform(variable, value)
|
Shader.active_shader.set_uniform(variable, value)
|
||||||
@@ -64,7 +117,7 @@ module CyberarmEngine
|
|||||||
|
|
||||||
@program = nil
|
@program = nil
|
||||||
|
|
||||||
@error_buffer_size = 1024
|
@error_buffer_size = 1024 * 8
|
||||||
@variable_missing = {}
|
@variable_missing = {}
|
||||||
|
|
||||||
@data = {shaders: {}}
|
@data = {shaders: {}}
|
||||||
@@ -80,20 +133,30 @@ module CyberarmEngine
|
|||||||
compile_shader(type: :fragment)
|
compile_shader(type: :fragment)
|
||||||
link_shaders
|
link_shaders
|
||||||
|
|
||||||
|
@data[:shaders].each { |key, id| glDeleteShader(id) }
|
||||||
|
|
||||||
# Only add shader if it successfully compiles
|
# Only add shader if it successfully compiles
|
||||||
if @compiled
|
if @compiled
|
||||||
puts "compiled!"
|
puts "compiled!"
|
||||||
puts "Compiled shader: #{@name}"
|
puts "Compiled shader: #{@name}"
|
||||||
Shader.add(@name, self)
|
Shader.add(@name, self)
|
||||||
else
|
else
|
||||||
|
glDeleteProgram(@program)
|
||||||
warn "FAILED to compile shader: #{@name}", ""
|
warn "FAILED to compile shader: #{@name}", ""
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# whether vertex and fragment files exist on disk
|
||||||
|
#
|
||||||
|
# @return [Boolean]
|
||||||
def shader_files_exist?(vertex:, fragment:)
|
def shader_files_exist?(vertex:, fragment:)
|
||||||
File.exist?(vertex) && File.exist?(fragment)
|
File.exist?(vertex) && File.exist?(fragment)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# creates an OpenGL Shader of _type_ using _source_
|
||||||
|
#
|
||||||
|
# @param type [Symbol] valid values are: :vertex, :fragment
|
||||||
|
# @param source [String] source code for shader
|
||||||
def create_shader(type:, source:)
|
def create_shader(type:, source:)
|
||||||
_shader = nil
|
_shader = nil
|
||||||
|
|
||||||
@@ -103,7 +166,7 @@ module CyberarmEngine
|
|||||||
when :fragment
|
when :fragment
|
||||||
_shader = glCreateShader(GL_FRAGMENT_SHADER)
|
_shader = glCreateShader(GL_FRAGMENT_SHADER)
|
||||||
else
|
else
|
||||||
warn "Unsupported shader type: #{type.inspect}"
|
raise ArgumentError, "Unsupported shader type: #{type.inspect}"
|
||||||
end
|
end
|
||||||
|
|
||||||
processed_source = preprocess_source(source: source)
|
processed_source = preprocess_source(source: source)
|
||||||
@@ -115,6 +178,23 @@ module CyberarmEngine
|
|||||||
@data[:shaders][type] =_shader
|
@data[:shaders][type] =_shader
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# evaluates shader preprocessors
|
||||||
|
#
|
||||||
|
# currently supported preprocessors:
|
||||||
|
#
|
||||||
|
# @include "file/path" "another/file/path" # => Replace line with contents of file; Shader includes_dir must be specified in constructor
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
# # Example Vertex Shader #
|
||||||
|
# # #version 330 core
|
||||||
|
# # @include "material_struct"
|
||||||
|
# # void main() {
|
||||||
|
# # gl_Position = vec4(1, 1, 1, 1);
|
||||||
|
# # }
|
||||||
|
#
|
||||||
|
# Shader.new(name: "model_renderer", includes_dir: "path/to/includes", vertex: "path/to/vertex_shader.glsl")
|
||||||
|
#
|
||||||
|
# @param source shader source code
|
||||||
def preprocess_source(source:)
|
def preprocess_source(source:)
|
||||||
lines = source.lines
|
lines = source.lines
|
||||||
|
|
||||||
@@ -141,6 +221,9 @@ module CyberarmEngine
|
|||||||
lines.join
|
lines.join
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# compile OpenGL Shader of _type_
|
||||||
|
#
|
||||||
|
# @return [Boolean] whether compilation succeeded
|
||||||
def compile_shader(type:)
|
def compile_shader(type:)
|
||||||
_compiled = false
|
_compiled = false
|
||||||
_shader = @data[:shaders][type]
|
_shader = @data[:shaders][type]
|
||||||
@@ -166,6 +249,11 @@ module CyberarmEngine
|
|||||||
return _compiled
|
return _compiled
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# link compiled OpenGL Shaders in to a OpenGL Program
|
||||||
|
#
|
||||||
|
# @note linking must succeed or shader cannot be used
|
||||||
|
#
|
||||||
|
# @return [Boolean] whether linking succeeded
|
||||||
def link_shaders
|
def link_shaders
|
||||||
@program = glCreateProgram
|
@program = glCreateProgram
|
||||||
@data[:shaders].values.each do |_shader|
|
@data[:shaders].values.each do |_shader|
|
||||||
@@ -187,7 +275,10 @@ module CyberarmEngine
|
|||||||
@compiled = linked == 0 ? false : true
|
@compiled = linked == 0 ? false : true
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns the location of a uniform variable
|
# Returns the location of a uniform _variable_
|
||||||
|
#
|
||||||
|
# @param variable [String]
|
||||||
|
# @return [Integer] location of uniform
|
||||||
def variable(variable)
|
def variable(variable)
|
||||||
loc = glGetUniformLocation(@program, variable)
|
loc = glGetUniformLocation(@program, variable)
|
||||||
if (loc == -1)
|
if (loc == -1)
|
||||||
@@ -197,6 +288,7 @@ module CyberarmEngine
|
|||||||
return loc
|
return loc
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @see Shader.use Shader.use
|
||||||
def use(&block)
|
def use(&block)
|
||||||
return unless compiled?
|
return unless compiled?
|
||||||
raise "Another shader is already in use! #{Shader.active_shader.name.inspect}" if Shader.active_shader
|
raise "Another shader is already in use! #{Shader.active_shader.name.inspect}" if Shader.active_shader
|
||||||
@@ -210,49 +302,93 @@ module CyberarmEngine
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# stop using shader, if shader is active
|
||||||
def stop
|
def stop
|
||||||
Shader.active_shader = nil if Shader.active_shader == self
|
Shader.active_shader = nil if Shader.active_shader == self
|
||||||
glUseProgram(0)
|
glUseProgram(0)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @return [Boolean] whether {Shader} successfully compiled
|
||||||
def compiled?
|
def compiled?
|
||||||
@compiled
|
@compiled
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# returns location of a uniform _variable_
|
||||||
|
#
|
||||||
|
# @note Use {#variable} for friendly error handling
|
||||||
|
# @see #variable Shader#variable
|
||||||
|
#
|
||||||
|
# @param variable [String]
|
||||||
|
# @return [Integer]
|
||||||
def attribute_location(variable)
|
def attribute_location(variable)
|
||||||
glGetUniformLocation(@program, variable)
|
glGetUniformLocation(@program, variable)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# send {Transform} to {Shader}
|
||||||
|
#
|
||||||
|
# @param variable [String]
|
||||||
|
# @param value [Transform]
|
||||||
|
# @param location [Integer]
|
||||||
|
# @return [void]
|
||||||
def uniform_transform(variable, value, location = nil)
|
def uniform_transform(variable, value, location = nil)
|
||||||
attr_loc = location ? location : attribute_location(variable)
|
attr_loc = location ? location : attribute_location(variable)
|
||||||
|
|
||||||
glUniformMatrix4fv(attr_loc, 1, GL_FALSE, value.to_gl.pack("F16"))
|
glUniformMatrix4fv(attr_loc, 1, GL_FALSE, value.to_gl.pack("F16"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# send Boolean to {Shader}
|
||||||
|
#
|
||||||
|
# @param variable [String]
|
||||||
|
# @param value [Boolean]
|
||||||
|
# @param location [Integer]
|
||||||
|
# @return [void]
|
||||||
def uniform_boolean(variable, value, location = nil)
|
def uniform_boolean(variable, value, location = nil)
|
||||||
attr_loc = location ? location : attribute_location(variable)
|
attr_loc = location ? location : attribute_location(variable)
|
||||||
|
|
||||||
glUniform1i(attr_loc, value ? 1 : 0)
|
glUniform1i(attr_loc, value ? 1 : 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# send Integer to {Shader}
|
||||||
|
# @param variable [String]
|
||||||
|
# @param value [Integer]
|
||||||
|
# @param location [Integer]
|
||||||
|
# @return [void]
|
||||||
def uniform_integer(variable, value, location = nil)
|
def uniform_integer(variable, value, location = nil)
|
||||||
attr_loc = location ? location : attribute_location(variable)
|
attr_loc = location ? location : attribute_location(variable)
|
||||||
|
|
||||||
glUniform1i(attr_loc, value)
|
glUniform1i(attr_loc, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# send Float to {Shader}
|
||||||
|
#
|
||||||
|
# @param variable [String]
|
||||||
|
# @param value [Float]
|
||||||
|
# @param location [Integer]
|
||||||
|
# @return [void]
|
||||||
def uniform_float(variable, value, location = nil)
|
def uniform_float(variable, value, location = nil)
|
||||||
attr_loc = location ? location : attribute_location(variable)
|
attr_loc = location ? location : attribute_location(variable)
|
||||||
|
|
||||||
glUniform1f(attr_loc, value)
|
glUniform1f(attr_loc, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# send {Vector} (x, y, z) to {Shader}
|
||||||
|
#
|
||||||
|
# @param variable [String]
|
||||||
|
# @param value [Vector]
|
||||||
|
# @param location [Integer]
|
||||||
|
# @return [void]
|
||||||
def uniform_vec3(variable, value, location = nil)
|
def uniform_vec3(variable, value, location = nil)
|
||||||
attr_loc = location ? location : attribute_location(variable)
|
attr_loc = location ? location : attribute_location(variable)
|
||||||
|
|
||||||
glUniform3f(attr_loc, *value.to_a[0..2])
|
glUniform3f(attr_loc, *value.to_a[0..2])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# send {Vector} to {Shader}
|
||||||
|
#
|
||||||
|
# @param variable [String]
|
||||||
|
# @param value [Vector]
|
||||||
|
# @param location [Integer]
|
||||||
|
# @return [void]
|
||||||
def uniform_vec4(variable, value, location = nil)
|
def uniform_vec4(variable, value, location = nil)
|
||||||
attr_loc = location ? location : attribute_location(variable)
|
attr_loc = location ? location : attribute_location(variable)
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,61 @@
|
|||||||
module CyberarmEngine
|
module CyberarmEngine
|
||||||
class Vector
|
class Vector
|
||||||
|
##
|
||||||
|
# Creates a up vector
|
||||||
|
#
|
||||||
|
# Vector.new(0, 1, 0)
|
||||||
|
#
|
||||||
|
# @return [CyberarmEngine::Vector]
|
||||||
def self.up
|
def self.up
|
||||||
Vector.new(0, 1, 0)
|
Vector.new(0, 1, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Creates a down vector
|
||||||
|
#
|
||||||
|
# Vector.new(0, -1, 0)
|
||||||
|
#
|
||||||
|
# @return [CyberarmEngine::Vector]
|
||||||
def self.down
|
def self.down
|
||||||
Vector.new(0, -1, 0)
|
Vector.new(0, -1, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Creates a left vector
|
||||||
|
#
|
||||||
|
# Vector.new(-1, 0, 0)
|
||||||
|
#
|
||||||
|
# @return [CyberarmEngine::Vector]
|
||||||
def self.left
|
def self.left
|
||||||
Vector.new(-1, 0, 0)
|
Vector.new(-1, 0, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Creates a right vector
|
||||||
|
#
|
||||||
|
# Vector.new(1, 0, 0)
|
||||||
|
#
|
||||||
|
# @return [CyberarmEngine::Vector]
|
||||||
def self.right
|
def self.right
|
||||||
Vector.new(1, 0, 0)
|
Vector.new(1, 0, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Creates a forward vector
|
||||||
|
#
|
||||||
|
# Vector.new(0, 0, 1)
|
||||||
|
#
|
||||||
|
# @return [CyberarmEngine::Vector]
|
||||||
def self.forward
|
def self.forward
|
||||||
Vector.new(0, 0, 1)
|
Vector.new(0, 0, 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Creates a backward vector
|
||||||
|
#
|
||||||
|
# Vector.new(0, 0, -1)
|
||||||
|
#
|
||||||
|
# @return [CyberarmEngine::Vector]
|
||||||
def self.backward
|
def self.backward
|
||||||
Vector.new(0, 0, -1)
|
Vector.new(0, 0, -1)
|
||||||
end
|
end
|
||||||
@@ -43,25 +79,30 @@ module CyberarmEngine
|
|||||||
alias w weight
|
alias w weight
|
||||||
alias w= weight=
|
alias w= weight=
|
||||||
|
|
||||||
|
# @return [Boolean]
|
||||||
def ==(other)
|
def ==(other)
|
||||||
if other.is_a?(Numeric)
|
if other.is_a?(Numeric)
|
||||||
@x == other &&
|
@x == other &&
|
||||||
@y == other &&
|
@y == other &&
|
||||||
@z == other &&
|
@z == other &&
|
||||||
@weight == other
|
@weight == other
|
||||||
else
|
elsif other.is_a?(Vector)
|
||||||
@x == other.x &&
|
@x == other.x &&
|
||||||
@y == other.y &&
|
@y == other.y &&
|
||||||
@z == other.z &&
|
@z == other.z &&
|
||||||
@weight == other.weight
|
@weight == other.weight
|
||||||
|
else
|
||||||
|
other == self
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Create a new vector using {x} and {y} values
|
||||||
|
# @return [CyberarmEngine::Vector]
|
||||||
def xy
|
def xy
|
||||||
Vector.new(@x, @y)
|
Vector.new(@x, @y)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Performs math operation, excluding @weight
|
# Performs math operation, excluding {weight}
|
||||||
private def operator(function, other)
|
private def operator(function, other)
|
||||||
if other.is_a?(Numeric)
|
if other.is_a?(Numeric)
|
||||||
Vector.new(
|
Vector.new(
|
||||||
@@ -78,22 +119,26 @@ module CyberarmEngine
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Adds Vector and Numberic or Vector and Vector, excluding @weight
|
# Adds Vector and Numeric or Vector and Vector, excluding {weight}
|
||||||
|
# @return [CyberarmEngine::Vector]
|
||||||
def +(other)
|
def +(other)
|
||||||
operator("+", other)
|
operator("+", other)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Subtracts Vector and Numberic or Vector and Vector, excluding @weight
|
# Subtracts Vector and Numeric or Vector and Vector, excluding {weight}
|
||||||
|
# @return [CyberarmEngine::Vector]
|
||||||
def -(other)
|
def -(other)
|
||||||
operator("-", other)
|
operator("-", other)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Multiplies Vector and Numberic or Vector and Vector, excluding @weight
|
# Multiplies Vector and Numeric or Vector and Vector, excluding {weight}
|
||||||
|
# @return [CyberarmEngine::Vector]
|
||||||
def *(other)
|
def *(other)
|
||||||
operator("*", other)
|
operator("*", other)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Divides Vector and Numberic or Vector and Vector, excluding @weight
|
# Divides Vector and Numeric or Vector and Vector, excluding {weight}
|
||||||
|
# @return [CyberarmEngine::Vector]
|
||||||
def /(other)
|
def /(other)
|
||||||
# Duplicated to protect from DivideByZero
|
# Duplicated to protect from DivideByZero
|
||||||
if other.is_a?(Numeric)
|
if other.is_a?(Numeric)
|
||||||
@@ -111,6 +156,8 @@ module CyberarmEngine
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# dot product of {Vector}
|
||||||
|
# @return [Integer|Float]
|
||||||
def dot(other)
|
def dot(other)
|
||||||
product = 0
|
product = 0
|
||||||
|
|
||||||
@@ -124,6 +171,8 @@ module CyberarmEngine
|
|||||||
return product
|
return product
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# cross product of {Vector}
|
||||||
|
# @return [CyberarmEngine::Vector]
|
||||||
def cross(other)
|
def cross(other)
|
||||||
a = self.to_a
|
a = self.to_a
|
||||||
b = other.to_a
|
b = other.to_a
|
||||||
@@ -136,24 +185,40 @@ module CyberarmEngine
|
|||||||
end
|
end
|
||||||
|
|
||||||
# returns degrees
|
# returns degrees
|
||||||
|
# @return [Float]
|
||||||
def angle(other)
|
def angle(other)
|
||||||
Math.acos( self.normalized.dot(other.normalized) ) * 180 / Math::PI
|
Math.acos( self.normalized.dot(other.normalized) ) * 180 / Math::PI
|
||||||
end
|
end
|
||||||
|
|
||||||
# returns magnitude of Vector, ignoring #weight
|
# returns magnitude of Vector, ignoring #weight
|
||||||
|
# @return [Float]
|
||||||
def magnitude
|
def magnitude
|
||||||
Math.sqrt((@x * @x) + (@y * @y) + (@z * @z))
|
Math.sqrt((@x * @x) + (@y * @y) + (@z * @z))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# returns normalized {Vector}
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
# CyberarmEngine::Vector.new(50, 21.2, 45).normalized
|
||||||
|
# # => <CyberarmEngine::Vector:0x001 @x=0.7089... @y=0.3005... @z=0.6380... @weight=0>
|
||||||
|
#
|
||||||
|
# @return [CyberarmEngine::Vector]
|
||||||
def normalized
|
def normalized
|
||||||
mag = magnitude
|
mag = magnitude
|
||||||
self / Vector.new(mag, mag, mag)
|
self / Vector.new(mag, mag, mag)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# returns a direction {Vector}
|
||||||
|
#
|
||||||
|
# z is pitch
|
||||||
|
#
|
||||||
|
# y is yaw
|
||||||
|
#
|
||||||
|
# x is roll
|
||||||
|
# @return [CyberarmEngine::Vector]
|
||||||
def direction
|
def direction
|
||||||
# z is pitch
|
|
||||||
# y is yaw
|
|
||||||
# x is roll
|
|
||||||
_x = -Math.sin(@y.degrees_to_radians) * Math.cos(@z.degrees_to_radians)
|
_x = -Math.sin(@y.degrees_to_radians) * Math.cos(@z.degrees_to_radians)
|
||||||
_y = Math.sin(@z.degrees_to_radians)
|
_y = Math.sin(@z.degrees_to_radians)
|
||||||
_z = Math.cos(@y.degrees_to_radians) * Math.cos(@z.degrees_to_radians)
|
_z = Math.cos(@y.degrees_to_radians) * Math.cos(@z.degrees_to_radians)
|
||||||
@@ -161,41 +226,63 @@ module CyberarmEngine
|
|||||||
Vector.new(_x, _y, _z)
|
Vector.new(_x, _y, _z)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# returns an inverse {Vector}
|
||||||
|
# @return [CyberarmEngine::Vector]
|
||||||
def inverse
|
def inverse
|
||||||
Vector.new(1.0 / @x, 1.0 / @y, 1.0 / @z)
|
Vector.new(1.0 / @x, 1.0 / @y, 1.0 / @z)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Adds up values of {x}, {y}, and {z}
|
||||||
|
# @return [Integer|Float]
|
||||||
def sum
|
def sum
|
||||||
@x + @y + @z
|
@x + @y + @z
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Linear interpolation: smoothly transition between two {Vector}
|
||||||
|
#
|
||||||
|
# CyberarmEngine::Vector.new(100, 100, 100).lerp( CyberarmEngine::Vector.new(0, 0, 0), 0.75 )
|
||||||
|
# # => <CyberarmEngine::Vector:0x0001 @x=75.0, @y=75.0, @z=75.0, @weight=0>
|
||||||
|
#
|
||||||
|
# @param other [CyberarmEngine::Vector | Integer | Float] value to subtract from
|
||||||
|
# @param factor [Float] how complete transition to _other_ is, in range [0.0..1.0]
|
||||||
|
# @return [CyberarmEngine::Vector]
|
||||||
def lerp(other, factor)
|
def lerp(other, factor)
|
||||||
(self - other) * factor.clamp(0.0, 1.0)
|
(self - other) * factor.clamp(0.0, 1.0)
|
||||||
end
|
end
|
||||||
|
|
||||||
# 2D distance using X and Y
|
# 2D distance using X and Y
|
||||||
|
# @return [Float]
|
||||||
def distance(other)
|
def distance(other)
|
||||||
Math.sqrt((@x-other.x)**2 + (@y-other.y)**2)
|
Math.sqrt((@x-other.x)**2 + (@y-other.y)**2)
|
||||||
end
|
end
|
||||||
|
|
||||||
# 2D distance using X and Z
|
# 2D distance using X and Z
|
||||||
|
# @return [Float]
|
||||||
def gl_distance2d(other)
|
def gl_distance2d(other)
|
||||||
Math.sqrt((@x-other.x)**2 + (@z-other.z)**2)
|
Math.sqrt((@x-other.x)**2 + (@z-other.z)**2)
|
||||||
end
|
end
|
||||||
|
|
||||||
# 3D distance using X, Y, and Z
|
# 3D distance using X, Y, and Z
|
||||||
|
# @return [Float]
|
||||||
def distance3d(other)
|
def distance3d(other)
|
||||||
Math.sqrt((@x-other.x)**2 + (@y-other.y)**2 + (@z-other.z)**2)
|
Math.sqrt((@x-other.x)**2 + (@y-other.y)**2 + (@z-other.z)**2)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Converts {Vector} to Array
|
||||||
|
# @return [Array]
|
||||||
def to_a
|
def to_a
|
||||||
[@x, @y, @z, @weight]
|
[@x, @y, @z, @weight]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Converts {Vector} to String
|
||||||
|
# @return [String]
|
||||||
def to_s
|
def to_s
|
||||||
"X: #{@x}, Y: #{@y}, Z: #{@z}, Weight: #{@weight}"
|
"X: #{@x}, Y: #{@y}, Z: #{@z}, Weight: #{@weight}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Converts {Vector} to Hash
|
||||||
|
# @return [Hash]
|
||||||
def to_h
|
def to_h
|
||||||
{x: @x, y: @y, z: @z, weight: @weight}
|
{x: @x, y: @y, z: @z, weight: @weight}
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
module CyberarmEngine
|
module CyberarmEngine
|
||||||
NAME = "InDev"
|
NAME = "InDev"
|
||||||
VERSION = "0.13.0"
|
VERSION = "0.13.1"
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user