Class: Jolt::System

Inherits:
Object
  • Object
show all
Includes:
SystemCharacters, SystemConstraints, SystemContacts, SystemQueries
Defined in:
lib/jolt/system.rb

Constant Summary collapse

DEFAULT_LIMITS =
{
  max_bodies: 10_240,
  max_body_pairs: 65_536,
  max_contact_constraints: 10_240
}.freeze
MAX_UINT32 =
0xffff_ffff
MAX_INT32 =
0x7fff_ffff

Constants included from SystemContacts

Jolt::SystemContacts::CONTACT_EVENT_TYPES, Jolt::SystemContacts::MAX_CONTACT_QUEUE_CAPACITY

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from SystemCharacters

#__destroy_all_characters, #__destroy_character, #__register_character

Methods included from SystemConstraints

#__constraints_snapshot, #__destroy_all_constraints, #__destroy_constraint, #__destroy_constraints_for, #__register_constraint

Methods included from SystemQueries

#overlap_point, #overlap_sphere, #raycast

Methods included from SystemContacts

#__create_contact_queue, #__destroy_contact_queue, #__drain_contact_events

Constructor Details

#initialize(max_bodies: DEFAULT_LIMITS[:max_bodies], max_body_pairs: DEFAULT_LIMITS[:max_body_pairs], max_contact_constraints: DEFAULT_LIMITS[:max_contact_constraints], gravity: [0, -9.81, 0], layers: Layers.default, contact_queue_capacity: 65_536) ⇒ System

Returns a new instance of System.



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/jolt/system.rb', line 20

def initialize(max_bodies: DEFAULT_LIMITS[:max_bodies],
               max_body_pairs: DEFAULT_LIMITS[:max_body_pairs],
               max_contact_constraints: DEFAULT_LIMITS[:max_contact_constraints],
               gravity: [0, -9.81, 0], layers: Layers.default,
               contact_queue_capacity: 65_536)
  Jolt.init
  @destroyed = false
  @active_thread = nil
  @body_registry = {}
  @constraint_registry = []
  @character_registry = []
  @user_data = {}
  @shapes = {}
  @layers = validate_layers(layers)
  create_native_system(
    max_bodies, max_body_pairs, max_contact_constraints, contact_queue_capacity
  )
  self.gravity = gravity
  @bodies = BodyCollection.new(self)
  @constraints = ConstraintCollection.new(self)
  Jolt.__register_system(self)
rescue StandardError
  destroy_native_resources
  raise
end

Instance Attribute Details

#bodiesObject (readonly)

Returns the value of attribute bodies.



18
19
20
# File 'lib/jolt/system.rb', line 18

def bodies
  @bodies
end

#constraintsObject (readonly)

Returns the value of attribute constraints.



18
19
20
# File 'lib/jolt/system.rb', line 18

def constraints
  @constraints
end

#contact_eventsObject (readonly)

Returns the value of attribute contact_events.



18
19
20
# File 'lib/jolt/system.rb', line 18

def contact_events
  @contact_events
end

#layersObject (readonly)

Returns the value of attribute layers.



18
19
20
# File 'lib/jolt/system.rb', line 18

def layers
  @layers
end

Instance Method Details

#__bodies_snapshotObject



142
143
144
145
# File 'lib/jolt/system.rb', line 142

def __bodies_snapshot
  __check_alive!
  @body_registry.values
end

#__body(id) ⇒ Object



132
133
134
135
# File 'lib/jolt/system.rb', line 132

def __body(id)
  __check_alive!
  @body_registry[id]
end

#__body_interfaceObject



108
109
110
111
# File 'lib/jolt/system.rb', line 108

def __body_interface
  __check_alive!
  @body_interface
end

#__check_alive!Object



157
158
159
160
161
162
# File 'lib/jolt/system.rb', line 157

def __check_alive!
  raise UseAfterDestroyError, "system has been destroyed" if @destroyed
  return unless @active_thread && !@active_thread.equal?(Thread.current)

  raise ConcurrentAccessError, "system is in use by another thread"
end

#__destroy_body(body) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/jolt/system.rb', line 118

def __destroy_body(body)
  return if body.destroyed?

  __check_alive!
  registered = @body_registry.delete(body.id)
  raise InvalidArgumentError, "body does not belong to this system" unless registered.equal?(body)

  __destroy_constraints_for(body)
  Native.JPH_BodyInterface_RemoveAndDestroyBody(@body_interface, body.id)
  @user_data.delete(body.id)
  body.__mark_destroyed
  nil
end

#__native_pointerObject



137
138
139
140
# File 'lib/jolt/system.rb', line 137

def __native_pointer
  __check_alive!
  @pointer
end

#__register_body(body, shape) ⇒ Object



113
114
115
116
# File 'lib/jolt/system.rb', line 113

def __register_body(body, shape)
  @body_registry[body.id] = body
  @shapes[shape.object_id] = shape
end

#__set_user_data(id, value) ⇒ Object



152
153
154
155
# File 'lib/jolt/system.rb', line 152

def __set_user_data(id, value)
  __check_alive!
  @user_data[id] = value
end

#__user_data(id) ⇒ Object



147
148
149
150
# File 'lib/jolt/system.rb', line 147

def __user_data(id)
  __check_alive!
  @user_data[id]
end

#__with_native_operation(recursive_message = "recursive native operation is not allowed") ⇒ Object



164
165
166
167
168
169
170
171
172
173
174
# File 'lib/jolt/system.rb', line 164

def __with_native_operation(recursive_message = "recursive native operation is not allowed")
  acquired = false
  __check_alive!
  raise Error, recursive_message if @active_thread

  @active_thread = Thread.current
  acquired = true
  yield
ensure
  @active_thread = nil if acquired
end

#destroyObject



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/jolt/system.rb', line 83

def destroy
  return if @destroyed

  __check_alive!
  if @active_thread
    raise ConcurrentAccessError, "cannot destroy a system during a native operation"
  end

  __destroy_all_constraints
  __destroy_all_characters
  @body_registry.each_value(&:__mark_destroyed)
  @body_registry.clear
  @user_data.clear
  destroy_native_resources
  @shapes.each_value { |shape| shape.release unless shape.released? }
  @shapes.clear
  @destroyed = true
  Jolt.__unregister_system(self)
  nil
end

#destroyed?Boolean

Returns:

  • (Boolean)


104
105
106
# File 'lib/jolt/system.rb', line 104

def destroyed?
  @destroyed
end

#gravityObject



63
64
65
66
67
68
# File 'lib/jolt/system.rb', line 63

def gravity
  __check_alive!
  native = Native::Vec3.new
  Native.JPH_PhysicsSystem_GetGravity(@pointer, native.pointer)
  Conversions.vec3(native)
end

#gravity=(value) ⇒ Object



70
71
72
73
74
75
# File 'lib/jolt/system.rb', line 70

def gravity=(value)
  __check_alive!
  native = Conversions.native_vec3(value, name: "gravity")
  Native.JPH_PhysicsSystem_SetGravity(@pointer, native.pointer)
  value
end

#optimize_broad_phaseObject



77
78
79
80
81
# File 'lib/jolt/system.rb', line 77

def optimize_broad_phase
  __check_alive!
  Native.JPH_PhysicsSystem_OptimizeBroadPhase(@pointer)
  self
end

#update(delta_time, collision_steps: 1) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/jolt/system.rb', line 46

def update(delta_time, collision_steps: 1)
  __check_alive!
  delta_time = Conversions.positive_float(delta_time, "delta_time")
  unless collision_steps.is_a?(Integer) && collision_steps.between?(1, MAX_INT32)
    raise InvalidArgumentError, "collision_steps must be a positive 32-bit integer"
  end

  __with_native_operation("recursive System#update is not allowed") do
    @body_registry.each_value(&:__capture_before_step)
    error = Native.JPH_PhysicsSystem_Update(@pointer, delta_time, collision_steps, @job_system)
    @body_registry.each_value(&:__capture_after_step)
    __drain_contact_events
    raise_update_error!(error) unless error.zero?
    self
  end
end