sub
abs
{
((
$_
[0]>0)?
$_
[0]:-
$_
[0]);
}
$cow
=1;
$plane
=2;
$floor
=3;
$enterprise
=4;
sub
initlists{
glNewList(
$cow
,GL_COMPILE);
glColor3f(1.0,0.0,0.0);
glBegin(GL_POLYGON);
glNormal3f(-1.0, 0.0, 0.0);
glVertex3f(-1.0 , -1.0, -1.0);
glVertex3f(-1.0 , 1.0, -1.0);
glVertex3f(-1.0 , 1.0, 1.0);
glVertex3f(-1.0 , -1.0, 1.0);
glEnd();
glColor3f(0.0,1.0,0.0);
glBegin(GL_POLYGON);
glNormal3f( 1.0, 0.0, 0.0);
glVertex3f( 1.0 , -1.0, -1.0);
glVertex3f( 1.0 , 1.0, -1.0);
glVertex3f( 1.0 , 1.0, 1.0);
glVertex3f( 1.0 , -1.0, 1.0);
glEnd();
glEndList();
glNewList(
$plane
,GL_COMPILE);
glColor3f(0,0,0);
glBegin(GL_POLYGON);
glVertex3f( 1 , 2, 1.0);
glVertex3f( 2 , 1, 1.0);
glVertex3f( 2 , -1, 1.0);
glVertex3f( 1 , -2, 1.0);
glVertex3f( -1 , -2, 1.0);
glVertex3f( -2 , -1, 1.0);
glVertex3f( -2 , 1, 1.0);
glVertex3f( -1 , 2, 1.0);
glEnd();
glColor3f(1.0,0.0,1.0);
glBegin(GL_POLYGON);
glVertex3f( 1 , 2, 3.0);
glVertex3f( 2 , 1, 3.0);
glVertex3f( 2 , -1, 3.0);
glVertex3f( 1 , -2, 3.0);
glVertex3f( -1 , -2, 3.0);
glVertex3f( -2 , -1, 3.0);
glVertex3f( -2 , 1, 3.0);
glVertex3f( -1 , 2, 3.0);
glEnd();
glEndList();
glNewList(
$floor
,GL_COMPILE);
for
(
$i
=0;
$i
<10;
$i
++) {
for
(
$j
=0;
$j
<10;
$j
++) {
$b
= 1-
sqrt
((
$i
-4.5)*(
$i
-4.5)+(
$j
-4.5)*(
$j
-4.5))/6.4;
glColor3f(
$b
*0.5,((
$i
%2) ^ (
$j
%2) )?0.7
*$b
: 0 ,0);
glBegin(GL_POLYGON);
glVertex3f( (0+
$i
-5)*10 , (0+
$j
-5) *10, 0.0);
glVertex3f( (1+
$i
-5)*10 , (0+
$j
-5) *10, 0.0);
glVertex3f( (1+
$i
-5)*10 , (1+
$j
-5) *10, 0.0);
glVertex3f( (0+
$i
-5)*10 , (1+
$j
-5) *10, 0.0);
glEnd();
}
}
glEndList();
}
sub
readnff{
my
$file
=
'spaceship.nff'
;
$file
=
"examples/$file"
unless
-r
$file
;
open
(FILE,
"<$file"
) ||
die
"cant open $file"
;
$_
=
""
;
while
(!(/^82\s*$/)){
$_
=<FILE>;}
$n
=82;
for
(
$i
=0;
$i
<
$n
;
$i
++) {
$_
=<FILE>;
/(\S+)\s+(\S+)\s+(\S+)\s*$/ ||
die
"couldn't parse file"
;
(
$x
[
$i
],
$y
[
$i
],
$z
[
$i
])=($1,$2,$3);
}
$_
=<FILE>;
/^140/ ||
die
"couldn't parse file"
;
$p
=140;
glNewList(
$enterprise
,GL_COMPILE);
glScalef(0.02,0.02,0.02);
glRotatef(90.0,0.0,0.0,1.0);
glColor3f(0.0,1.0,1.0);
for
(
$i
=0;
$i
<
$p
;
$i
++) {
glBegin(GL_POLYGON);
$_
=<FILE>;
/3\s+(\d+)\s+(\d+)\s+(\d+)\s/ ||
die
"couldn't parse file"
;
glVertex3f(
$x
[$1],
$y
[$1],
$z
[$1]);
glVertex3f(
$x
[$2],
$y
[$2],
$z
[$2]);
glVertex3f(
$x
[$3],
$y
[$3],
$z
[$3]);
glEnd();
}
close
(FILE);
glEndList();
$enterprise
;
}
%defaults
= (
'name'
=>
'unnamed'
,
'x'
=> 0 ,
'y'
=> 0 ,
'z'
=> 0 ,
'dl'
=>
$main::plane
,
);
sub
initialize {
my
$self
=
shift
;
local
%v
=
@_
;
foreach
$k
(
keys
(
%v
)) {
$self
->{
$k
} =
$v
{
$k
};
}
$self
;
}
sub
print
{
my
$self
=
shift
;
print
"\tObject '"
,
$self
->{'name
'},"'
is a
'",ref($self),"'
\n";
foreach
$k
(
sort
keys
(
%$self
)) {
print
(
"\t\t$k\t$self->{$k}\n"
)
if
(
$k
cmp
'name'
);
}
print
"\n"
;
}
sub
new {
my
$type
=
shift
;
my
$self
= {};
initialize(
$self
,
%defaults
);
initialize(
$self
,
@_
);
push
(
@objects
,
$self
);
bless
$self
;
}
sub
move {
}
sub
draw {
my
$self
=
shift
;
glPushMatrix();
glTranslatef(
$self
->{
'x'
},
$self
->{
'y'
},
$self
->{
'z'
});
glCallList(
$self
->{
'dl'
});
glPopMatrix ();
}
@ISA
=
qw(A)
;
%defaults
= (
'dx'
,0,
'dy'
,0,
'dz'
,0,
);
sub
new {
my
$type
=
shift
;
my
$self
= A->new(
%defaults
,
@_
);
push
(
@objects
,
$self
);
bless
$self
;
}
$WORLD_BOUNDARY
=(20.0);
$WORLD_CEILING
=(10.0);
$WORLD_FLOOR
=(0.0);
sub
move {
my
$self
=
shift
;
local
(
$x
,
$y
,
$z
,
$dx
,
$dy
,
$dz
)=
(\
$self
->{
'x'
}, \
$self
->{
'y'
}, \
$self
->{
'z'
},
\
$self
->{
'dx'
},\
$self
->{
'dy'
},\
$self
->{
'dz'
});
$$x
+=
$$dx
;
$$y
+=
$$dy
;
$$z
+=
$$dz
;
(
$$x
>
$WORLD_BOUNDARY
) && (
$$dx
= -
abs
(
$$dx
));
(
$$x
< -
$WORLD_BOUNDARY
) && (
$$dx
=
abs
(
$$dx
));
(
$$y
>
$WORLD_BOUNDARY
) && (
$$dy
= -
abs
(
$$dy
));
(
$$y
< -
$WORLD_BOUNDARY
) && (
$$dy
=
abs
(
$$dy
));
(
$$z
>
$WORLD_CEILING
) && (
$$dz
= -
abs
(
$$dz
));
(
$$z
<
$WORLD_FLOOR
) && (
$$dz
=
abs
(
$$dz
));
}
@ISA
=
qw(B)
;
%defaults
= (
'name'
,
'target'
,
'wait'
,0,
);
$damping
= 0.99;
sub
new {
my
$type
=
shift
;
my
$self
= B->new(
%defaults
,
@_
);
push
(
@objects
,
$self
);
bless
$self
;
}
sub
move {
my
$self
=
shift
;
$self
->{
'dx'
} *=
$damping
;
$self
->{
'dy'
} *=
$damping
;
$self
->{
'wait'
}--
if
(
$self
->{
'wait'
}>0) ;
$self
->B::move;
}
sub
takeoff {
my
$self
=
shift
;
return
if
(
$self
->{
'wait'
}>0) ;
$self
->{
'dx'
} =
rand
(2)-1.0;
$self
->{
'dy'
} =
rand
(2)-1.0;
$self
->{
'wait'
}=10;
}
@ISA
=
qw(B)
;
%defaults
= (
'target'
=> 0,
'h'
=> 0,
'dh'
=> 0,
);
sub
new {
my
$type
=
shift
;
my
$self
= B->new(
%defaults
,
@_
);
push
(
@objects
,
$self
);
bless
$self
;
}
$DAMPING
= (0.98);
$ACCELLERATION
= (0.01);
$BANK_DAMPING
= (0.8);
sub
move{
my
$self
=
shift
;
local
(
$x
,
$y
,
$z
,
$dx
,
$dy
,
$dz
,
$h
,
$dh
)=
(\
$self
->{
'x'
}, \
$self
->{
'y'
}, \
$self
->{
'z'
},
\
$self
->{
'dx'
},\
$self
->{
'dy'
},\
$self
->{
'dz'
},
\
$self
->{
'h'
},\
$self
->{
'dh'
});
local
$t
=
$self
->{
'target'
};
(
$t
) ||
die
"No Target\n"
;
local
(
$tx
,
$ty
) = (
$t
->{
'x'
},
$t
->{
'y'
});
local
$theading
=
atan2
(
$ty
-
$$y
,
$tx
-
$$x
);
local
$speed
=
sqrt
(
$$dx
*
$$dx
+
$$dy
*
$$dy
);
$$h
= (
$$dy
==0.0&&
$$dx
==0.0)?
$$h
:
atan2
(
$$dy
,
$$dx
);
$tdheading
=
$theading
-
$$h
;
while
(
$tdheading
> 3.14){
$tdheading
-= 2*3.14};
while
(
$tdheading
<-3.14){
$tdheading
+= 2*3.14};
$$dh
*=
$BANK_DAMPING
;
$$dh
+=
$tdheading
* 0.01;
$$h
+=
$$dh
;
if
(
$tdheading
<3.14/6 &&
$tdheading
>-3.14/6 ) {
$speed
+=
$ACCELLERATION
;
}
elsif
(
$tdheading
<3.14/3 &&
$tdheading
>-3.14/3 ) {
$speed
+=
$ACCELLERATION
/4;
}
$$dx
=
cos
(
$$h
)
*$speed
;
$$dy
=
sin
(
$$h
)
*$speed
;
$$dx
*=
$DAMPING
;
$$dy
*=
$DAMPING
;
$$dz
*=
$DAMPING
;
$$x
+=
$$dx
;
$$y
+=
$$dy
;
$$z
+=
$$dz
;
$t
->takeoff
if
(
$$x
>
$tx
-5 &&
$$x
<
$tx
+5 &&
$$y
>
$ty
-5 &&
$$y
<
$ty
+5 );
}
sub
draw {
my
$self
=
shift
;
glPushMatrix();
glTranslatef(
$self
->{
'x'
},
$self
->{
'y'
},
$self
->{
'z'
});
glRotatef(
$self
->{
'h'
}*180/3.14, 0.0,0.0,1.0);
glRotatef(-60.0 *
$self
->{
'dh'
}/(1.0/(1.0-0.8)*0.01*3.14), 1.0, 0.0, 0.0);
glCallList(
$self
->{
'dl'
});
glPopMatrix ();
}
glpOpenWindow(
width
=>400,
height
=>400,
mask
=> StructureNotifyMask|KeyPressMask,
attributes
=>[GLX_RGBA,GLX_DOUBLEBUFFER]);
glShadeModel (GL_FLAT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum (-1.0, 1.0, -1.0, 1.0, 1.5, 500.0);
glMatrixMode(GL_MODELVIEW);
initlists;
glColor3f(1,0,0);
glClearColor(0,0,0.3,1);
A->new(
'dl'
=>
$floor
,
'name'
=>
'the happy floor'
);
$b
= T->new(
'x'
=> 10,
'dx'
=> 0.4,
'name'
=>
'bad dude'
);
readnff;
$c
= C->new(
'z'
=> 5,
'dl'
=>
$enterprise
,
'x'
=> -10,
'target'
=>
$b
,
'name'
=>
'killer'
);
$w
=100.0;
$t
=
time
;
$p
=
$t
-1;
$rin
=
$win
=
$ein
=
''
;
$spf
= 1;
$spin
=0;
$cb
{
&ConfigureNotify
} =
sub
{
local
(
$e
,
$w
,
$h
)=
@_
;glViewport(0,0,
$w
,
$h
);
};
$cb
{
&KeyPress
} =
sub
{
local
(
$ss
);
&$ss
(
@_
[1])
if
(
$ss
=
$kcb
{
@_
[1]}); };
$kcb
{
'q'
} =
$kcb
{
'Q'
} =
$kcb
{
"\033"
} =
sub
{
print
"Good-Bye\n"
;
exit
0;};
sub
setspeed{
$C::ACCELLERATION
=
$_
[0]/100;}
foreach
$i
(0..9){
$kcb
{
"$i"
}=\
&setspeed
;
}
$is_pm
= OpenGL::_have_glp && ! OpenGL::_have_glx;
while
(1){
$spf
= (
$spf
*$w
+
$t
-
$p
) /(
$w
+1.0);
$fps
= (
$spf
)?1.0/
$spf
:0;
$p
=
$t
;
$t
=
time
;
while
(
$p
=XPending) {
@e
=
&glpXNextEvent
;
&$s
(
@e
)
if
(
$s
=
$cb
{
$e
[0]});
}
vec
(
$rin
,0,1) = 1;
if
(!
$is_pm
&&
select
(
$rout
=
$rin
,
undef
,
undef
,0)) {
$_
=<> ||
die
"End Of File"
;
eval
;
}
foreach
$x
(
@A::objects
) {
$x
->move;
}
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity ();
glTranslatef (0.0, 0.0, -30.0);
glRotatef(-45.0, 1.0,0.0,0.0);
$spin
+= 1;
glRotatef(
$spin
, 0.0,0.0,1.0);
foreach
$x
(
@A::objects
) {
$x
->draw;
}
glFlush();
glXSwapBuffers;
}