class Mittsu::Object3D

Constants

DefaultUp

Attributes

cast_shadow[RW]
children[RW]
frustum_culled[RW]
geometry[RW]
id[R]
matrix[RW]
matrix_auto_update[RW]
matrix_world[RW]
matrix_world_needs_update[RW]
name[W]
parent[RW]
position[RW]
quaternion[RW]
receive_shadow[RW]
render_order[RW]
rotation[RW]
rotation_auto_update[RW]
scale[RW]
type[R]
up[RW]
user_data[RW]
uuid[R]
visible[RW]

Public Class Methods

new() click to toggle source
Calls superclass method
# File lib/mittsu/core/object_3d.rb, line 15
def initialize
  super
  @id = (@@id ||= 1).tap { @@id += 1 }

  @uuid = SecureRandom.uuid

  @type = 'Object3D'

  @children = []
  @parent = nil
  @name = nil

  @up = DefaultUp.clone

  @position = Vector3.new
  @rotation = Euler.new
  @quaternion = Quaternion.new
  @scale = Vector3.new(1.0, 1.0, 1.0)

  @rotation.on_change do
    @quaternion.set_from_euler(rotation, false)
  end

  @quaternion.on_change do
    @rotation.set_from_quaternion(quaternion, false)
  end

  @rotation_auto_update = true

  @matrix = Matrix4.new
  @matrix_world = Matrix4.new

  @matrix_auto_update = true
  @matrix_world_needs_update = false

  @visible = true

  @cast_shadow = false
  @receive_shadow = false

  @frustum_culled = true
  @render_order = 0

  @user_data = {}
  @_listeners = {}
end

Public Instance Methods

add(*arguments) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 154
def add(*arguments)
  if arguments.length > 1
    arguments.each do |arg|
      self.add(arg)
    end
    return self
  end
  object = arguments.first
  if object == self
    puts("ERROR: Mittsu::Object3D#add: object can't be added as a child of itself.", object.inspect)
    return self
  end
  if object.is_a? Object3D
    object.parent.remove(object) unless object.parent.nil?
    object.parent = self
    object.dispatch_event type: :added
    @children << object
  else
    puts('ERROR: Mittsu::Object3D#add: object not an instance of Object3D.', object.inspect)
  end
  self
end
apply_matrix(matrix) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 66
def apply_matrix(matrix)
  @matrix.multiply_matrices(matrix, @matrix)
  @matrix.decompose(@position, @quaternion, @scale)
end
clone(object = nil, recursive = true) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 317
def clone(object = nil, recursive = true)
  object ||= Object3D.new
  object.name = @name
  object.up.copy(@up)
  object.position.copy(@position)
  object.quaternion.copy(@quaternion)
  object.scale.copy(@scale)
  object.rotation_auto_update = @rotation_auto_update
  object.matrix.copy(@matrix)
  object.matrix_world.copy(@matrix_world)
  object.matrix_auto_update = @matrix_auto_update
  object.matrix_world_needs_update = @matrix_world_needs_update
  object.visible = @visible
  object.cast_shadow = @cast_shadow
  object.receive_shadow = @receive_shadow
  object.frustum_culled = @frustum_culled
  object.user_data = @user_data
  if recursive
    @children.each do |child|
      object.add(child.clone)
    end
  end
  object
end
get_object_by_id(id) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 194
def get_object_by_id(id)
  self.get_object_by_property(:id, id)
end
get_object_by_name(name) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 198
def get_object_by_name(name)
  self.get_object_by_property(:name, name)
end
get_object_by_property(name, value) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 202
def get_object_by_property(name, value)
  return self if self.send(name) == value
  @children.each do |child|
    object = child.get_object_by_property(name, value)
    return object unless object.nil?
  end
  nil
end
get_world_direction(target = Vector3.new) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 238
def get_world_direction(target = Vector3.new)
  @_quaternion ||= Quaternion.new
  self.get_world_quaternion(@_quaternion)
  target.set(0.0, 0.0, 1.0).apply_quaternion(@_quaternion)
end
get_world_position(target = Vector3.new) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 211
def get_world_position(target = Vector3.new)
  self.update_matrix_world(true)
  target.set_from_matrix_position(@matrix_world)
end
get_world_quaternion(target = Quaternion.new) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 216
def get_world_quaternion(target = Quaternion.new)
  @_position ||= Vector3.new
  @_scale ||= Vector3.new
  self.update_matrix_world(true)
  @matrix_world.decompose(@_position, target, @_scale)
  target
end
get_world_rotation(target = Euler.new) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 224
def get_world_rotation(target = Euler.new)
  @_quaternion ||= Quaternion.new
  self.get_world_quaternion(quaternion)
  target.set_from_quaternion(quaternion, @rotation.order, false)
end
get_world_scale(target = Vector3.new) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 230
def get_world_scale(target = Vector3.new)
  @_position ||= Vector3.new
  @_quaternion ||= Quaternion.new
  self.update_matrix_world(true)
  @matrix_world.decompose(@_position, @_quaternion, target)
  target
end
local_to_world(vector) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 138
def local_to_world(vector)
  vector.apply_matrix4(@matrix_world)
end
look_at(vector) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 147
def look_at(vector)
  # This routine does not support objects with rotated and/or translated parent(s)
  @_m1 ||= Matrix4.new
  @_m1.look_at(vector, @position, self.up)
  @quaternion.set_from_rotation_matrix(@_m1)
end
name() click to toggle source
# File lib/mittsu/core/object_3d.rb, line 62
def name
  @name || "<#{@type} ##{@id}>"
end
print_tree(lines=[]) click to toggle source
raycast(raycaster, intersects) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 244
def raycast(raycaster, intersects); end
remove(*arguments) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 177
def remove(*arguments)
  if arguments.length > 1
    arguments.each do |arg|
      self.remove(arg)
    end
    return
  end
  object = arguments.first
  index = @children.index(object)
  if index
    object.parent = nil
    object.dispatch_event type: :removed
    @children.delete_at index
  end
  nil
end
rotate_on_axis(axis, angle) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 90
def rotate_on_axis(axis, angle)
  # rotate object on axis in object space
  # axis is assumed to be normalized
  @_q1 ||= Quaternion.new
  @_q1.set_from_axis_angle(axis, angle)
  @quaternion.multiply(@_q1)
  self
end
rotate_x(angle) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 99
def rotate_x(angle)
  @_x_axis ||= Vector3.new(1, 0, 0)
  self.rotate_on_axis(@_x_axis, angle)
end
rotate_y(angle) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 104
def rotate_y(angle)
  @_y_axis ||= Vector3.new(0, 1, 0)
  self.rotate_on_axis(@_y_axis, angle)
end
rotate_z(angle) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 109
def rotate_z(angle)
  @_z_axis ||= Vector3.new(0, 0, 1)
  self.rotate_on_axis(@_z_axis, angle)
end
set_rotation_from_axis_angle(axis, angle) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 71
def set_rotation_from_axis_angle(axis, angle)
  # assumes axis is normalized
  @quaternion.set_from_axis_angle(axis, angle)
end
set_rotation_from_euler(euler) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 76
def set_rotation_from_euler(euler)
  @quaternion.set_from_euler(euler, true)
end
set_rotation_from_matrix(m) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 80
def set_rotation_from_matrix(m)
  # assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
  @quaternion.set_from_rotation_matrix(m)
end
set_rotation_from_quaternion(q) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 85
def set_rotation_from_quaternion(q)
  # assumes q is normalized
  @quaternion.copy(q)
end
to_json() click to toggle source
# File lib/mittsu/core/object_3d.rb, line 307
def to_json
  {
    metadata: {
      version: 4.3,
      type: 'Object',
      generator: 'ObjectExporter'
    },
  }.merge(jsonify)
end
to_s() click to toggle source
# File lib/mittsu/core/object_3d.rb, line 266
def to_s
  "#{type} (#{name}) #{position}"
end
translate_on_axis(axis, distance) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 114
def translate_on_axis(axis, distance)
  # translate object by distance along axis in object space
  # axis is assumed to be normalized
  @_v1 ||= Vector3.new
  @_v1.copy(axis).apply_quaternion(@quaternion)
  @position.add(@_v1.multiply_scalar(distance))
  self
end
translate_x(distance) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 123
def translate_x(distance)
  @_x_axis ||= Vector3.new(1, 0, 0)
  self.translate_on_axis(@_x_axis, distance)
end
translate_y(distance) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 128
def translate_y(distance)
  @_y_axis ||= Vector3.new(0, 1, 0)
  self.translate_on_axis(@_y_axis, distance)
end
translate_z(distance) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 133
def translate_z(distance)
  @_z_axis ||= Vector3.new(0, 0, 1)
  self.translate_on_axis(@_z_axis, distance)
end
traverse(&callback) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 246
def traverse(&callback)
  callback.yield self
  @children.each do |child|
    child.traverse(&callback)
  end
end
traverse_ancestors(&callback) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 278
def traverse_ancestors(&callback)
  if @parent
    callback.yield @parent
    @parent.traverse_ancestors(&callback)
  end
end
traverse_visible(&callback) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 270
def traverse_visible(&callback)
  return unless @visible
  callback.yield self
  @children.each do |child|
    child.traverse_visible(&callback)
  end
end
update_matrix() click to toggle source
# File lib/mittsu/core/object_3d.rb, line 285
def update_matrix
  @matrix.compose(@position, @quaternion, @scale)
  @matrix_world_needs_update = true
end
update_matrix_world(force = false) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 290
def update_matrix_world(force = false)
  self.update_matrix if @matrix_auto_update
  if @matrix_world_needs_update || force
    if @parent.nil?
      @matrix_world.copy(@matrix)
    else
      @matrix_world.multiply_matrices(@parent.matrix_world, @matrix)
    end
    @matrix_world_needs_update = false
    force = true
  end
  # update children
  @children.each do |child|
    child.update_matrix_world(force)
  end
end
world_to_local(vector) click to toggle source
# File lib/mittsu/core/object_3d.rb, line 142
def world_to_local(vector)
  @_m1 ||= Matrix4.new
  vector.apply_matrix4(@_m1.get_inverse(@matrix_world))
end

Protected Instance Methods

jsonify() click to toggle source
# File lib/mittsu/core/object_3d.rb, line 344
def jsonify
  children = @children.map(&:to_json)
  {
    object: {
      uuid: @uuid,
      type: @type,
      matrix: @matrix.to_a,
      geometry: @geometry&.uuid,
      material: @material&.uuid,
      name: @name&.empty? ? nil : @name,
      user_data: @user_data&.empty? ? nil : @user_data,
      visible: @visible ? nil : @visible,
      children: children.map { |x| x[:object] }.flatten
    }.reject { |k,v| v.nil? || v == [] },
    geometries: ([jsonify_geometry] + children.map { |x| x[:geometries] }).flatten.compact,
    materials: ([jsonify_material] + children.map { |x| x[:materials] }).flatten.compact
  }.reject { |k,v| v.nil? || v == [] }
end
jsonify_geometry() click to toggle source
# File lib/mittsu/core/object_3d.rb, line 363
def jsonify_geometry
  return nil if @geometry.nil?
  @geometry.to_json.delete_if {|k, v| k == :metadata }
end
jsonify_material() click to toggle source
# File lib/mittsu/core/object_3d.rb, line 368
def jsonify_material
  return nil if @material.nil?
  @material.to_json.delete_if {|k, v| k == :metadata }
end