[svn:parrot] r39614 - trunk/examples/opengl
japhb at svn.parrot.org
japhb at svn.parrot.org
Wed Jun 17 07:12:43 UTC 2009
Author: japhb
Date: Wed Jun 17 07:12:42 2009
New Revision: 39614
URL: https://trac.parrot.org/parrot/changeset/39614
Log:
[OpenGL] shapes.p6: Convert particle effect to Perl 6; now Perl 6 version matches PIR version, except currently a lot slower
Modified:
trunk/examples/opengl/shapes.p6
Modified: trunk/examples/opengl/shapes.p6
==============================================================================
--- trunk/examples/opengl/shapes.p6 Wed Jun 17 05:46:49 2009 (r39613)
+++ trunk/examples/opengl/shapes.p6 Wed Jun 17 07:12:42 2009 (r39614)
@@ -31,6 +31,7 @@
use OpenGL:from<parrot>;
use NCI::Utils:from<parrot>;
+# XXX: Need a better way to import constants
# None of these currently work; they all create an inescapable new lexical pad
# require 'glutconst.p6';
# 'glutconst.p6'.evalfile;
@@ -50,8 +51,10 @@
constant GL_STENCIL_BUFFER_BIT = 0x0400;
constant GL_COLOR_BUFFER_BIT = 0x4000;
+constant GL_POINTS = 0x0000;
constant GL_FALSE = 0x0000;
constant GL_TRUE = 0x0001;
+constant GL_ONE = 0x0001;
constant GL_TRIANGLES = 0x0004;
constant GL_EQUAL = 0x0202;
constant GL_ALWAYS = 0x0207;
@@ -85,6 +88,8 @@
our $time_sim = 0.0;
our $time_sim_dt = 0.0;
+our (@pfx_pos, @pfx_vel);
+
sub MAIN(*@ARGS is rw) {
# Initialize GLUT and create GLUT window
@@ -344,12 +349,6 @@
glPopMatrix();
}
-sub update_particle_effect {
-}
-
-sub draw_particle_effect {
-}
-
sub set_2d_view {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
@@ -358,290 +357,119 @@
glLoadIdentity();
}
-
-=begin pod
-
-.sub main :main
- # Create particle effect
- init_particle_effect()
-.end
-
-.sub init_particle_effect
- .local pmc pfx_pos, pfx_vel
- pfx_pos = new 'ResizablePMCArray'
- pfx_vel = new 'ResizablePMCArray'
-
- new_particle(0, pfx_pos, pfx_vel)
-
- set_global 'pfx_pos', pfx_pos
- set_global 'pfx_vel', pfx_vel
-.end
-
-.sub new_particle
- .param int particle_num
- .param pmc pfx_pos
- .param pmc pfx_vel
-
- .local num x, y, z, vx, vy, vz
- x = 4.0
- y = 0.0
- z = 0.0
-
- vx = 0.0
- vy = 0.135
- vz = 0.0
-
- .local pmc random
- .local num rand
- random = new 'Random'
- rand = random
- rand *= .1
- x += rand
- rand = random
- rand *= .1
- y += rand
- rand = random
- rand *= .1
- z += rand
-
- rand = random
- rand -= .5
- rand *= .01
- vx += rand
- rand = random
- rand -= .5
- rand *= .01
- vy += rand
- rand = random
- rand -= .5
- rand *= .01
- vz += rand
-
- .local pmc pos
- pos = new 'FixedFloatArray'
- pos = 3
- pos[0] = x
- pos[1] = y
- pos[2] = z
-
- .local pmc vel
- vel = new 'FixedFloatArray'
- vel = 3
- vel[0] = vx
- vel[1] = vy
- vel[2] = vz
-
- pfx_pos[particle_num] = pos
- pfx_vel[particle_num] = vel
-.end
-
-.sub update_particle_effect
- .param num dt
-
- # "Black hole" particle effect at +Z
-
+sub update_particle_effect {
# Speed up time a little; this effect is *slow*
- dt *= 30.0
-
- # Global particle state arrays
- .local pmc pfx_pos, pfx_vel
- pfx_pos = get_global 'pfx_pos'
- pfx_vel = get_global 'pfx_vel'
+ my $dt = $time_sim_dt * 30;
# Add a particle at random
- .local int count
- count = pfx_pos
- if count > 1000 goto update_particles
- .local pmc random
- .local num rand
- random = new 'Random'
- rand = random
- rand *= 4
- if rand > dt goto update_particles
- new_particle(count, pfx_pos, pfx_vel)
+ my $count = @pfx_pos.elems;
+ new_particle($count) if $count < 1000 && $dt > rand * 4;
# Update all particles
- update_particles:
- dec count
- if count < 0 goto update_particles_end
-
- # Update particle states
- update_particle(pfx_pos, pfx_vel, count, dt)
-
- goto update_particles
- update_particles_end:
-.end
-
-.sub update_particle
- .param pmc pfx_pos
- .param pmc pfx_vel
- .param int particle_num
- .param num dt
-
- .local pmc pos, vel
- pos = pfx_pos[particle_num]
- vel = pfx_vel[particle_num]
+ update_particle($_, $dt) for ^$count;
+}
+
+sub new_particle($particle_num) {
+ @pfx_pos[$particle_num] = [ 4.0 + rand * .1,
+ 0.0 + rand * .1,
+ 0.0 + rand * .1 ];
+ @pfx_vel[$particle_num] = [ 0.0 + (rand - .5) * .01,
+ 0.135 + (rand - .5) * .01,
+ 0.0 + (rand - .5) * .01 ];
+
+ return;
+}
+sub update_particle($particle_num, $dt) {
# Constants
- .const num G = -.075 # Gravitational force constant
- .const num Cd = -.00033 # Coefficient of drag
- .const num event_grav = -.3 # Gravity at "event horizon"
- .const num min_dist2 = .001 # Minimum distance**2 before calc blows up
- .const num escape_dist = 30 # Distance at which "escape" occurs
+ constant G = -.075; # Gravitational force constant
+ constant Cd = -.00033; # Coefficient of drag
+ constant event_grav = -.3; # Gravity at "event horizon"
+ constant min_dist2 = .001; # Minimum distance**2 before calc blows up
+ constant escape_dist = 30; # Distance at which "escape" occurs
# Particle states
- .local num x, y, z, vx, vy, vz
- x = pos[0]
- y = pos[1]
- z = pos[2]
- vx = vel[0]
- vy = vel[1]
- vz = vel[2]
+ my @pos := @pfx_pos[$particle_num];
+ my @vel := @pfx_vel[$particle_num];
# Calculate distance and distance squared
- .local num x2, y2, z2, dist2, dist
- x2 = x * x
- y2 = y * y
- z2 = z * z
- dist2 = x2 + y2
- dist2 += z2
- if dist2 >= min_dist2 goto dist2_ok
- dist2 = min_dist2
- dist2_ok:
- dist = sqrt dist2
+ my $dist_squared = [+] @pos >>*<< @pos;
+ $dist_squared = min_dist2 unless $dist_squared > min_dist2;
+ my $distance = sqrt($dist_squared);
# If distance is too great, particle has "escaped"; regenerate it
- if dist < escape_dist goto dist_ok
- new_particle(particle_num, pfx_pos, pfx_vel)
- .return ()
- dist_ok:
+ return new_particle($particle_num) if $distance > escape_dist;
# Compute gravity force
- .local num grav
- grav = G / dist2
+ my $gravity = G / $dist_squared;
# If gravity is too strong, it has "passed the event horizon"; regenerate it
- if grav > event_grav goto grav_ok
- new_particle(particle_num, pfx_pos, pfx_vel)
- .return ()
- grav_ok:
+ return new_particle($particle_num) if $gravity <= event_grav;
# Calculate gravity vector (always directed toward center of "hole")
- .local num gx, gy, gz
- gx = x / dist
- gy = y / dist
- gz = z / dist
- gx *= grav
- gy *= grav
- gz *= grav
+ my @grav = @pos >>/>> $distance >>*>> $gravity;
# Calculate drag vector (always directed opposite of velocity)
# NOTE: Using drag proportional to velocity, instead of velocity squared
- .local num dragx, dragy, dragz
- dragx = Cd * vx
- dragy = Cd * vy
- dragz = Cd * vz
+ my @drag = @vel >>*>> Cd;
# Acceleration is gravity + drag
- .local num ax, ay, az
- ax = gx + dragx
- ay = gy + dragy
- az = gz + dragz
+ my @acc = @grav >>+<< @drag;
# Update velocity and position with simple Euler integration
- .local num dvx, dvy, dvz
- .local num dx, dy, dz
- dvx = ax * dt
- dvy = ay * dt
- dvz = az * dt
- vx += dvx
- vy += dvy
- vz += dvz
- dx = vx * dt
- dy = vy * dt
- dz = vz * dt
- x += dx
- y += dy
- z += dz
-
- # Save new values back to particle state
- vel[0] = vx
- vel[1] = vy
- vel[2] = vz
- pos[0] = x
- pos[1] = y
- pos[2] = z
-.end
+ @vel = @vel >>+<< @acc >>*>> $dt;
+ @pos = @pos >>+<< @vel >>*>> $dt;
+}
-.sub draw_particle_effect
+sub draw_particle_effect {
# "Black hole" particle effect at +Z
# Make it visually interesting
- glPushMatrix()
- glTranslatef(0, .3, 1.5)
- glRotatef(-20, 0, 0, 1)
- glRotatef( 90, 1, 0, 0)
- glScalef(.15, .15, .15)
+ glPushMatrix();
+ glTranslatef(0, .3, 1.5);
+ glRotatef(-20, 0, 0, 1);
+ glRotatef( 90, 1, 0, 0);
+ glScalef(.15, .15, .15);
# OpenGL state for "glowing transparent particles"
- glEnable(.GL_BLEND)
- glBlendFunc(.GL_SRC_ALPHA, .GL_ONE)
- glDepthMask(.GL_FALSE)
- glPointSize(4)
-
- # XXXX: Disabled for now because it's broken on many systems;
- # will replace later with textured quads
- # glEnable(.GL_POINT_SMOOTH)
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ glDepthMask(GL_FALSE);
+ glPointSize(4);
+
+ # XXX: Disabled for now because it's broken on many systems;
+ # will replace later with textured quads
+ # glEnable(GL_POINT_SMOOTH);
# # Show plane of effect
-# glColor4f(1, 1, 1, .2)
-# glBegin(.GL_QUADS)
-# glVertex3f(-2, -2, 0)
-# glVertex3f( 2, -2, 0)
-# glVertex3f( 2, 2, 0)
-# glVertex3f(-2, 2, 0)
-# glEnd()
-
- # Start drawing particles
- glColor4f(1, 1, 1, .5)
- glBegin(.GL_POINTS)
-
- # Global particle state arrays
- .local pmc pfx_pos, pfx_vel
- pfx_pos = get_global 'pfx_pos'
- pfx_vel = get_global 'pfx_vel'
-
- # Loop over all particles, updating and drawing them
- .local int count
- count = pfx_pos
- draw_particle_loop:
- dec count
- if count < 0 goto draw_particle_loop_end
-
- # Draw particle
- .local pmc pos
- .local num x, y, z
- pos = pfx_pos[count]
- x = pos[0]
- y = pos[1]
- z = pos[2]
- glVertex3f(x, y, z)
-
- goto draw_particle_loop
-
- # Finished with all particles
- draw_particle_loop_end:
- glEnd()
+# glColor4f(1, 1, 1, .2);
+# glBegin(GL_QUADS);
+# glVertex3f(-2, -2, 0);
+# glVertex3f( 2, -2, 0);
+# glVertex3f( 2, 2, 0);
+# glVertex3f(-2, 2, 0);
+# glEnd();
+
+ # White color, but semi-transparent
+ glColor4f(1, 1, 1, .5);
+
+ # Draw all particles
+ glBegin(GL_POINTS);
+ for @pfx_pos -> $pos {
+ # XXX: Rakudo bug - appears not to properly unpack for NCI calls
+ # glVertex3f(|$pos);
+ my ($x, $y, $z) = @($pos)[0..2];
+ glVertex3f($x, $y, $z);
+ }
+ glEnd();
# Done, return to normal OpenGL state
- glDepthMask(.GL_TRUE)
- glDisable(.GL_BLEND)
-
- glPopMatrix()
-.end
+ glDepthMask(GL_TRUE);
+ glDisable(GL_BLEND);
+ glPopMatrix();
+}
-=end pod
# Local Variables:
# mode: pir
More information about the parrot-commits
mailing list