[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