#!/usr/local/bin/ruby require "opengl" require "glut" require "mathn" include Math # Initial comment block? # Why don't this appear anywhere? # Init: setup some GL/GLUT parmeters def init mat_specular = [ 1.0, 1.0, 1.0, 1.0 ]; light_position = [ 0.0, 30.0, 50.0, 0.0 ]; GL.ClearColor(0.0, 0.0, 0.0, 0.0); GL.ShadeModel(GL::SMOOTH); GL.Enable(GL::DEPTH_TEST); GL.Light(GL::LIGHT0, GL::POSITION, light_position); GL.Enable(GL::LIGHTING); GL.Enable(GL::LIGHT0); GL.Material(GL::FRONT, GL::DIFFUSE, $diffuseMaterial); # GL.Material(GL::FRONT, GL::SPECULAR, mat_specular); # GL.Material(GL::FRONT, GL::SHININESS, 25.0); # GL.ColorMaterial(GL::FRONT, GL::DIFFUSE); GL.Enable(GL::COLOR_MATERIAL); GL.MatrixMode(GL::PROJECTION); GLU.Perspective(40.0, 1.0, 1.0, 10.0); GL.MatrixMode(GL::MODELVIEW); GLU.LookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) end # showstep: do a single step in the current direction and wait def showstep(direction) if $runstate == 1 GLUT.IdleFunc(nil) $runstate = 0; end $inc = -$inc if $inc < 0 $inc = 1 if $inc == 0 $inc = -$inc if direction < 0 end # main: do all the dirty works... def main # # the above single blanck comment seems to be necessary to prevent the # next comment block from appearing at the top of the file. # Parameter setups to be used in display function. # Specialized to three particles. If you need to use N!=3, you need to # change this part and display function below accordingly. # In particular, you need to change $color and $size. # If yu just want to show all particles in same size and colur, # you can use something like # $color = [0.0,1.0,1.0] # $size = 0.1 # and remove index from their uses in the display function below. $diffuseMaterial = [0.5,0.5,0.5,1.0]; $Material = [[0.1,0.1,0.1,1.0],[0.0,1.0,1.0,1.0],[1.0,1.0,1.0,1.0]] $color = [[0.0,1.0,1.0],[1.0,0.0,1.0],[1.0,1.0,0.0]] $frame = 0 $inc = 3 $size=[0.1,0.05,0.1] $scale = 20 $radius = 10 $theta= -60 $phi = -135 # display function for three particles. display = Proc.new { scale = $scale GL.Clear(GL::COLOR_BUFFER_BIT | GL::DEPTH_BUFFER_BIT); GL.PushMatrix print $theta," ", $phi, "\n" #need to change the next line if you have N!=3 for j in 0..2 GL.PushMatrix # GL.Material(GL::FRONT, GL::AMBIENT, $Material[j]); GL.Color(*$color[j]) GL.Rotate($theta, 0.0, 0.0, 1.0) GL.Rotate($phi, 1.0, 0.0, 0.0) GL.Translate($parray[$frame][j][0]/scale,$parray[$frame][j][1]/scale, $parray[$frame][j][2]/scale) GLUT.SolidSphere($size[j]/scale*$radius, 10, 6); GL.PopMatrix end GL.PopMatrix GLUT.SwapBuffers(); $frame += $inc if $frame >= $parray.size $frame=0 # for onetrip (useful for making GIF files) # exit elsif $frame <= 0 $frame = $parray.size - 1 end # activate the next line (and the above "exit" to make GIF images of # each frames # system "xwd -nobdrs -name threebody.rb|xwdtopnm|ppmtogif> #{$frame}.gif" } # keyboard function keyboard = Proc.new {|key, x, y| case key # H/h to stop animation when ?h,?H $inc =0 # A/a to increase the speed when ?a,?A if $inc >= 0 $inc += 1 else $inc -= 1 end # D/d to decrease the speed when ?d,?D if $inc > 0 $inc -= 1 else $inc += 1 end # s/S to scale down/up when ?s $scale *= 1.2 when ?S $scale /= 1.2 # R/r to increase/decrease sphere radius when ?R $radius *= 1.2 when ?r $radius /= 1.2 # x/X to rotate frame when ?x $phi += 3 when ?X $phi -= 3 # y/Y to rotate frame when ?y $theta += 3 when ?Y $theta -= 3 # >/. to single step forward when ?>,?. showstep(1) #