| threebody.rb |
| Path: |
threebody.rb |
| Modified: |
Sun Mar 21 22:16:47 JST 2004 |
|
|
opengl
glut
mathn
Math
Init: setup some GL/GLUT parmeters
# File threebody.rb, line 11
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
# File threebody.rb, line 35
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…
# File threebody.rb, line 46
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)
# </, to single step backward
when ?<,?,
showstep(-1)
# q/Q/ESC to quit
when ?q,?Q,27
exit(0);
end
GLUT.PostRedisplay() if $runstate == 0
}
$runstate = 0
# mouse function
mouse = Proc.new {|button, state, x, y|
case button
# left button to start
when GLUT::LEFT_BUTTON
if (state == GLUT::DOWN)
GLUT.IdleFunc($reDisplay)
$runstate = 1
end
#middle button to stop
when GLUT::MIDDLE_BUTTON
if (state == GLUT::DOWN)
GLUT.IdleFunc(nil)
$runstate = 0
end
#right botton to change the time direction
when GLUT::RIGHT_BUTTON
$inc = - $inc if (state == GLUT::DOWN)
end
}
$reDisplay = Proc.new {
# print "redisplay called"
GLUT.PostRedisplay();
}
# read in the input snapshots. The idea here is to store the entire
# sequence of the snapshot to a single array called $parray. So
# $parray is a three-dimentional file, of (in fortran notation) the
# dimension of (3,N,Nsnapshots)
f = open("testdata","r")
$parray = []
while s = f.gets
pos = []
a = s.split
time = a[0].to_f
for i in 0..2
pos.push [a[i*3+1].to_f,a[i*3+2].to_f,a[i*3+3].to_f]
end
$parray.push(pos)
s = f.gets
end
GLUT.Init
GLUT.InitDisplayMode(GLUT::DOUBLE | GLUT::RGB | GLUT::DEPTH);
GLUT.InitWindowSize(700, 700);
GLUT.InitWindowPosition(100, 0);
GLUT.CreateWindow($0);
init
GLUT.KeyboardFunc(keyboard);
GLUT.MouseFunc(mouse);
GLUT.DisplayFunc(display);
GLUT.MainLoop();
end