The sketch:-
# # Gravitational Attraction (3D) # by Daniel Shiffman. # # Adapted for dome projection by Andres Colubri # # Simulating gravitational attraction # G ---> universal gravitational constant # m1 --> mass of object #1 # m2 --> mass of object #2 # d ---> distance between objects # F = (G*m1*m2)/(d*d) # # For the basics of working with PVector, see # http://processing.org/learning/pvector/ # as well as examples in Topics/Vectors/ # # load_libraries :planetarium, :solar_system include_package 'codeanticode.planetarium' PLANETS = 10 attr_reader :angle, :planets, :sun, :count, :do_rotate java_alias :background_int, :background, [Java::int] # precast for efficiency def setup size(800, 800, Dome::RENDERER) @angle = 0 # Some random planets @planets = [] @count = 10 # warm up time @do_rotate = false (0 ... PLANETS).each do planets << Planet.new(rand(0.1 .. 2), rand(-width/2 .. width/2), rand(-height/2 .. height/2), rand(-100 .. 100)) end # A single sun @sun = Sun.new end def pre if count == frame_count # only enter once per frame planets.each do |planet| # Sun attracts Planets force = sun.attract(planet) planet.apply_force(force) # Update and draw Planets planet.update end @count = frame_count + 1 frame.set_title("Solar System FPS: #{frame_rate.to_i}") @do_rotate = true end end def draw pre background_int 0 # Setup the scene lights translate(width/2, height/2, 300) rotate_y(angle) # Display the Sun sun.display # All the Planets planets.each do |planet| planet.display end post end # Called after rendering all the faces, but before the dome sphere, # so it can be used to draw stuff on the corners of the screen. #def border # perspective # camera # background(255) # fill(0) # text("FPS: #{frame_rate}", 20, 20) #end def post # Rotate around the scene if do_rotate @angle += 0.003 @do_rotate = false end end
The solar system library
# Gravitational Attraction (3D) # Daniel Shiffman <http://www.shiffman.net> # A class for an attractive body in our world class Sun include Processing::Proxy G = 0.4 # Universal gravitational constant (arbitrary value) attr_reader :sphere, :location, :mass def initialize @location = Vect.new(0,0) @mass = 20 @sphere = create_shape(SPHERE, mass * 2, 20) sphere.set_fill(false) sphere.set_stroke(color(255)) end def constrain val, lo, hi # override processing overloaded method result = (val > hi)? hi : (val < lo)? lo : val end def attract(m) force = Vect.sub(location,m.location) # Calculate direction of force d = constrain(force.mag, 5.0, 25.0) # Limiting the distance to eliminate "extreme" results for very close or very far objects strength = (G * mass * m.mass) / (d * d) # Calculate gravitional force magnitude force.set_mag(strength) # Get force vector --> magnitude * direction return force end # Draw Sun def display push_matrix translate(location.x,location.y,location.z) shape(sphere) pop_matrix end end # Gravitational Attraction (3D) # Daniel Shiffman <http://www.shiffman.net> # A class for an orbiting Planet class Planet include Processing::Proxy # Basic physics model (location, velocity, acceleration, mass) attr_reader :location, :velocity, :acceleration, :mass, :sphere def initialize(m, x, y, z) @mass = m @location = Vect.new(x,y,z) @velocity = Vect.new(1,0) # Arbitrary starting velocity @acceleration = Vect.new(0,0) @sphere = create_shape(SPHERE, mass * 8, 20) sphere.set_stroke(false) sphere.set_fill(color(255)) end # Newton's 2nd Law (F = M*A) applied def apply_force(force) f = Vect.div(force,mass) acceleration.add(f) end # Our motion algorithm (aka Euler Integration) def update velocity.add(acceleration) # Velocity changes according to acceleration location.add(velocity) # Location changes according to velocity acceleration.zero end # Draw the Planet def display push_matrix translate(location.x,location.y,location.z) shape(sphere) pop_matrix end end class Vect attr_reader :x, :y, :z def initialize(x, y, z = 0) @x, @y, @z = x, y, z end def normalize @x, @y, @z = x / mag, y / mag, z / mag if (mag != 0 && mag != 1) end def mult a @x, @y, @z = x * a, y * a, z * a end def self.sub(v0, v1) Vect.new(v0.x - v1.x, v0.y - v1.y, v0.z - v1.z) end def add(v) @x, @y, @z = x + v.x, y + v.y, z + v.z end def self.div(v, a) Vect.new(v.x / a, v.y / a, v.z / a) end def mag Math.sqrt(x*x + y*y + z*z) end def set_mag m normalize @x, @y, @z = x * m, y * m, z * m end def zero @x, @y, @z = 0, 0, 0 end end
No comments:
Post a Comment