Converted the remaining particle usage (coin bursts) to point sprite.
authorrlk <rlk@78b8d119-cf0a-0410-b17c-f493084dd1d7>
Sat, 2 Apr 2011 16:17:32 +0000 (16:17 +0000)
committerrlk <rlk@78b8d119-cf0a-0410-b17c-f493084dd1d7>
Sat, 2 Apr 2011 16:17:32 +0000 (16:17 +0000)
git-svn-id: https://s.snth.net/svn/neverball/branches/gles@3547 78b8d119-cf0a-0410-b17c-f493084dd1d7

ball/game_client.c
ball/game_draw.c
ball/st_conf.c
ball/st_demo.c
share/part.c
share/part.h

index 40f912b..a41a304 100644 (file)
@@ -423,7 +423,7 @@ int  game_client_init(const char *file_name)
 
     /* Initialize particles. */
 
-    part_reset(GOAL_HEIGHT, JUMP_HEIGHT);
+    part_reset();
 
     /* Initialize command state. */
 
index a143841..7b9cb6b 100644 (file)
@@ -433,11 +433,12 @@ static void game_draw_fore(const struct game_draw *gd,
         glDepthMask(GL_FALSE);
         {
             sol_bill(draw, M, t);
-            part_draw_coin(M, t);
 
             game_draw_goals(gd, M, t);
             game_draw_jumps(gd, M, t);
             game_draw_swchs(draw->vary);
+
+            part_draw_coin(M, t);
         }
         glDepthMask(GL_TRUE);
         glEnable(GL_LIGHTING);
index 5aa140f..b6c9715 100644 (file)
@@ -432,7 +432,7 @@ static int null_enter(struct state *st, struct state *prev)
 
 static void null_leave(struct state *st, struct state *next, int id)
 {
-    part_init(GOAL_HEIGHT, JUMP_HEIGHT);
+    part_init();
     shad_init();
     ball_init();
     item_init();
index 8386ba2..5cd585a 100644 (file)
@@ -617,10 +617,9 @@ static int demo_end_gui(void)
 
 static int demo_end_enter(struct state *st, struct state *prev)
 {
-#if 0
     SDL_Event quit = { SDL_QUIT };
     SDL_PushEvent(&quit);
-#endif
+
     audio_music_fade_out(demo_paused ? 0.2f : 2.0f);
 
     return demo_end_gui();
index 9db5a8d..fc2ce77 100644 (file)
@@ -17,6 +17,7 @@
 #include <string.h>
 #include <math.h>
 
+#include "config.h"
 #include "glext.h"
 #include "part.h"
 #include "vec3.h"
 
 /*---------------------------------------------------------------------------*/
 
-struct part
+struct part_vary
 {
-    float t;
-    float a;
-    float w;
-    float c[3];
-    float p[3];
-    float v[3];
+    GLfloat v[3];             /* Velocity                                    */
 };
 
-static struct part part_coin[PART_MAX_COIN];
-static struct part part_goal[PART_MAX_GOAL];
-static struct part part_jump[PART_MAX_JUMP];
-static GLuint      part_text_star;
-static GLuint      part_text_squiggle;
-static GLuint      part_list;
+struct part_draw
+{
+    GLfloat p[3];             /* Position                                    */
+    GLfloat c[3];             /* Color                                       */
+    GLfloat t;                /* Time until death. Doubles as opacity.       */
+};
+
+static struct part_vary coin_vary[PART_MAX_COIN];
+static struct part_draw coin_draw[PART_MAX_COIN];
 
-static float goal_height;
-static float jump_height;
+static GLuint part_text_star;
+static GLuint coin_vbo;
 
 /*---------------------------------------------------------------------------*/
 
@@ -64,48 +63,26 @@ struct part_lerp
 };
 
 static struct part_lerp part_lerp_coin[PART_MAX_COIN];
-static struct part_lerp part_lerp_goal[PART_MAX_GOAL];
-static struct part_lerp part_lerp_jump[PART_MAX_JUMP];
 
 void part_lerp_copy(void)
 {
     int i;
 
     for (i = 0; i < PART_MAX_COIN; i++)
-        v_cpy(part_lerp_coin[i].p[PREV], part_lerp_coin[i].p[CURR]);
-
-    for (i = 0; i < PART_MAX_GOAL; i++)
-        v_cpy(part_lerp_goal[i].p[PREV], part_lerp_goal[i].p[CURR]);
-
-    for (i = 0; i < PART_MAX_JUMP; i++)
-        v_cpy(part_lerp_jump[i].p[PREV], part_lerp_jump[i].p[CURR]);
+        v_cpy(part_lerp_coin[i].p[PREV],
+              part_lerp_coin[i].p[CURR]);
 }
 
 void part_lerp_init(void)
 {
-    int i;
-
-    for (i = 0; i < PART_MAX_GOAL; i++)
-        if (part_goal[i].t > 0.0f)
-        {
-            v_cpy(part_lerp_goal[i].p[PREV], part_goal[i].p);
-            v_cpy(part_lerp_goal[i].p[CURR], part_goal[i].p);
-        }
-
-    for (i = 0; i < PART_MAX_JUMP; i++)
-        if (part_jump[i].t > 0.0f)
-        {
-            v_cpy(part_lerp_jump[i].p[PREV], part_jump[i].p);
-            v_cpy(part_lerp_jump[i].p[CURR], part_jump[i].p);
-        }
 }
 
 void part_lerp_burst(int i)
 {
-    if (part_coin[i].t >= 1.0f)
+    if (coin_draw[i].t >= 1.0f)
     {
-        v_cpy(part_lerp_coin[i].p[PREV], part_coin[i].p);
-        v_cpy(part_lerp_coin[i].p[CURR], part_coin[i].p);
+        v_cpy(part_lerp_coin[i].p[PREV], coin_draw[i].p);
+        v_cpy(part_lerp_coin[i].p[CURR], coin_draw[i].p);
     }
 }
 
@@ -114,137 +91,47 @@ void part_lerp_apply(float a)
     int i;
 
     for (i = 0; i < PART_MAX_COIN; i++)
-        if (part_coin[i].t > 0.0f)
-        {
-            v_lerp(part_coin[i].p,
+        if (coin_draw[i].t > 0.0f)
+            v_lerp(coin_draw[i].p,
                    part_lerp_coin[i].p[PREV],
                    part_lerp_coin[i].p[CURR], a);
-        }
-
-    for (i = 0; i < PART_MAX_GOAL; i++)
-        if (part_goal[i].t > 0.0f)
-        {
-            v_lerp(part_goal[i].p,
-                   part_lerp_goal[i].p[PREV],
-                   part_lerp_goal[i].p[CURR], a);
-        }
-
-    for (i = 0; i < PART_MAX_GOAL; i++)
-        if (part_jump[i].t > 0.0f)
-        {
-            v_lerp(part_jump[i].p,
-                   part_lerp_jump[i].p[PREV],
-                   part_lerp_jump[i].p[CURR], a);
-        }
 }
 
 /*---------------------------------------------------------------------------*/
 
-void part_reset(float zh, float jh)
+void part_reset(void)
 {
     int i;
 
-    goal_height = zh;
-    jump_height = jh;
-
     for (i = 0; i < PART_MAX_COIN; i++)
-        part_coin[i].t = 0.0f;
-
-    for (i = 0; i < PART_MAX_GOAL; i++)
-    {
-        float t = rnd(+0.1f,      +1.0f);
-        float a = rnd(-1.0f * PI, +1.0f * PI);
-        float w = rnd(-2.0f * PI, +2.0f * PI);
-
-        part_goal[i].t = t;
-        part_goal[i].a = V_DEG(a);
-        part_goal[i].w = V_DEG(w);
-
-        part_goal[i].c[0] = 1.0f;
-        part_goal[i].c[1] = 1.0f;
-        part_goal[i].c[2] = 0.0f;
-
-        part_goal[i].p[0] = fsinf(a);
-        part_goal[i].p[1] = (1.f - t) * goal_height;
-        part_goal[i].p[2] = fcosf(a);
-
-        part_goal[i].v[0] = 0.f;
-        part_goal[i].v[1] = 0.f;
-        part_goal[i].v[2] = 0.f;
-    }
-
-    for (i = 0; i < PART_MAX_JUMP; i++)
-    {
-        float t = rnd(+0.1f,      +1.0f);
-        float a = rnd(-1.0f * PI, +1.0f * PI);
-        float w = rnd(+0.5f,      +2.5f);
-
-        float vy = rnd(+0.025f, +0.25f);
-
-        part_jump[i].t = t;
-        part_jump[i].a = V_DEG(a);
-        part_jump[i].w = w;
-
-        part_jump[i].c[0] = 1.0f;
-        part_jump[i].c[1] = 1.0f;
-        part_jump[i].c[2] = 1.0f;
-
-        part_jump[i].p[0] = fsinf(a);
-        part_jump[i].p[1] = (1.f - t) * jump_height;
-        part_jump[i].p[2] = fcosf(a);
-
-        part_jump[i].v[0] = 0.f;
-        part_jump[i].v[1] = vy;
-        part_jump[i].v[2] = 0.f;
-    }
+        coin_draw[i].t = 0.0f;
 
     part_lerp_init();
 }
 
-void part_init(float zh, float jh)
+void part_init(void)
 {
-    memset(part_coin, 0, PART_MAX_COIN * sizeof (struct part));
-    memset(part_goal, 0, PART_MAX_GOAL * sizeof (struct part));
-    memset(part_jump, 0, PART_MAX_JUMP * sizeof (struct part));
+    part_text_star = make_image_from_file(IMG_PART_STAR);
 
-    part_text_star     = make_image_from_file(IMG_PART_STAR);
-    part_text_squiggle = make_image_from_file(IMG_PART_SQUIGGLE);
+    memset(coin_vary, 0, PART_MAX_COIN * sizeof (struct part_vary));
+    memset(coin_draw, 0, PART_MAX_COIN * sizeof (struct part_draw));
 
-    part_list = glGenLists(1);
+    glGenBuffers(1,              &coin_vbo);
+    glBindBuffer(GL_ARRAY_BUFFER, coin_vbo);
+    glBufferData(GL_ARRAY_BUFFER, sizeof (coin_draw),
+                                          coin_draw, GL_DYNAMIC_DRAW);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
 
-    glNewList(part_list, GL_COMPILE);
-    {
-        glBegin(GL_QUADS);
-        {
-            glTexCoord2f(0.f, 0.f);
-            glVertex2f(-PART_SIZE, -PART_SIZE);
-
-            glTexCoord2f(1.f, 0.f);
-            glVertex2f(+PART_SIZE, -PART_SIZE);
-
-            glTexCoord2f(1.f, 1.f);
-            glVertex2f(+PART_SIZE, +PART_SIZE);
-
-            glTexCoord2f(0.f, 1.f);
-            glVertex2f(-PART_SIZE, +PART_SIZE);
-        }
-        glEnd();
-    }
-    glEndList();
-
-    part_reset(zh, jh);
+    part_reset();
 }
 
 void part_free(void)
 {
-    if (glIsList(part_list))
-        glDeleteLists(part_list, 1);
+    if (glIsBuffer(coin_vbo))
+        glDeleteBuffers(1, &coin_vbo);
 
     if (glIsTexture(part_text_star))
         glDeleteTextures(1, &part_text_star);
-
-    if (glIsTexture(part_text_squiggle))
-        glDeleteTextures(1, &part_text_squiggle);
 }
 
 /*---------------------------------------------------------------------------*/
@@ -254,27 +141,24 @@ void part_burst(const float *p, const float *c)
     int i, n = 0;
 
     for (i = 0; n < 10 && i < PART_MAX_COIN; i++)
-        if (part_coin[i].t <= 0.f)
+        if (coin_draw[i].t <= 0.f)
         {
             float a = rnd(-1.0f * PI, +1.0f * PI);
             float b = rnd(+0.3f * PI, +0.5f * PI);
-            float w = rnd(-4.0f * PI, +4.0f * PI);
 
-            part_coin[i].p[0] = p[0];
-            part_coin[i].p[1] = p[1];
-            part_coin[i].p[2] = p[2];
+            coin_draw[i].c[0] = c[0];
+            coin_draw[i].c[1] = c[1];
+            coin_draw[i].c[2] = c[2];
 
-            part_coin[i].v[0] = 4.f * fcosf(a) * fcosf(b);
-            part_coin[i].v[1] = 4.f *            fsinf(b);
-            part_coin[i].v[2] = 4.f * fsinf(a) * fcosf(b);
+            coin_draw[i].p[0] = p[0];
+            coin_draw[i].p[1] = p[1];
+            coin_draw[i].p[2] = p[2];
 
-            part_coin[i].c[0] = c[0];
-            part_coin[i].c[1] = c[1];
-            part_coin[i].c[2] = c[2];
+            coin_vary[i].v[0] = 4.f * fcosf(a) * fcosf(b);
+            coin_vary[i].v[1] = 4.f *            fsinf(b);
+            coin_vary[i].v[2] = 4.f * fsinf(a) * fcosf(b);
 
-            part_coin[i].t = 1.f;
-            part_coin[i].a = 0.f;
-            part_coin[i].w = V_DEG(w);
+            coin_draw[i].t = 1.f;
 
             part_lerp_burst(i);
 
@@ -285,144 +169,70 @@ void part_burst(const float *p, const float *c)
 /*---------------------------------------------------------------------------*/
 
 static void part_fall(struct part_lerp *lerp,
-                      struct part *part, int n,
-                      const float *g, float dt)
+                      struct part_vary *vary,
+                      struct part_draw *draw,
+                      int n, const float *g, float dt)
 {
     int i;
 
     for (i = 0; i < n; i++)
-        if (part[i].t > 0.f)
+        if (draw[i].t > 0.f)
         {
-            part[i].t -= dt;
-
-            v_mad(part[i].v, part[i].v, g, dt);
-
-            v_mad(lerp[i].p[CURR], lerp[i].p[CURR], part[i].v, dt);
-        }
-}
-
-static void part_spin(struct part_lerp *lerp,
-                      struct part *part, int n,
-                      const float *g, float dt)
-{
-    int i;
+            draw[i].t -= dt;
 
-    for (i = 0; i < n; i++)
-        if (part[i].t > 0.f)
-        {
-            part[i].a += 30.f * dt;
+            v_mad(vary[i].v, vary[i].v, g, dt);
 
-            lerp[i].p[CURR][0] = fsinf(V_RAD(part[i].a));
-            lerp[i].p[CURR][2] = fcosf(V_RAD(part[i].a));
+            v_mad(lerp[i].p[CURR], lerp[i].p[CURR], vary[i].v, dt);
         }
+        else draw[i].t = 0.0f;
 }
 
 void part_step(const float *g, float dt)
 {
-    int i;
-
     part_lerp_copy();
-
-    part_fall(part_lerp_coin, part_coin, PART_MAX_COIN, g, dt);
-
-    if (g[1] > 0.f)
-        part_fall(part_lerp_goal, part_goal, PART_MAX_GOAL, g, dt);
-    else
-        part_spin(part_lerp_goal, part_goal, PART_MAX_GOAL, g, dt);
-
-    for (i = 0; i < PART_MAX_JUMP; i++)
-    {
-        part_lerp_jump[i].p[CURR][1] += part_jump[i].v[1] * dt;
-
-        if (part_lerp_jump[i].p[PREV][1] > jump_height)
-        {
-            part_lerp_jump[i].p[PREV][1] = 0.0f;
-            part_lerp_jump[i].p[CURR][1] = 0.0f;
-        }
-    }
+    part_fall(part_lerp_coin, coin_vary, coin_draw, PART_MAX_COIN, g, dt);
 }
 
 /*---------------------------------------------------------------------------*/
 
-static void part_draw(const float *M,
-                      const float *p, float r, float rz, float s)
-{
-    glPushMatrix();
-    {
-        glTranslatef(r * p[0], p[1], r * p[2]);
-        glMultMatrixf(M);
-        glRotatef(rz, 0.f, 0.f, 1.f);
-        glScalef(s, s, 1.0f);
-
-        glCallList(part_list);
-    }
-    glPopMatrix();
-}
-
 void part_draw_coin(const float *M, float t)
 {
-    int i;
+    const GLfloat c[3] = { 0.0f, 1.0f, 0.0f };
+    GLint s = config_get_d(CONFIG_HEIGHT) / 8;
 
     glBindTexture(GL_TEXTURE_2D, part_text_star);
 
-    for (i = 0; i < PART_MAX_COIN; i++)
-        if (part_coin[i].t > 0.f)
-        {
-            glColor4f(part_coin[i].c[0],
-                      part_coin[i].c[1],
-                      part_coin[i].c[2],
-                      part_coin[i].t);
-
-            part_draw(M, part_coin[i].p, 1.0f, t * part_coin[i].w, 1.0f);
-        }
-
-    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
-}
-
-void part_draw_goal(const float *M, float radius, float a, float t)
-{
-    int i;
-
-    glBindTexture(GL_TEXTURE_2D, part_text_star);
+    /* Upload the current state of the particles. It would be best to limit  */
+    /* this upload to only active particles, but it's more important to do   */
+    /* it all in a single call.                                              */
 
-    glColor4f(1.0f, 1.0f, 0.0f, a);
+    glBindBuffer   (GL_ARRAY_BUFFER, coin_vbo);
+    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof (coin_draw), coin_draw);
 
-    for (i = 0; i < PART_MAX_GOAL; i++)
-        if (part_goal[i].t > 0.0f)
-            part_draw(M, part_goal[i].p, radius - 0.05f,
-                      t * part_goal[i].w, 1.0f);
+    /* Draw the entire buffer.  Dead particles have zero opacity anyway. */
 
-    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
-}
-
-void part_draw_jump(const float *M, float radius, float a, float t)
-{
-    int i;
-
-    glBindTexture(GL_TEXTURE_2D, part_text_squiggle);
-
-    for (i = 0; i < PART_MAX_JUMP; i++)
+    glEnableClientState(GL_COLOR_ARRAY);
+    glEnableClientState(GL_VERTEX_ARRAY);
     {
-        glColor4f(part_jump[i].c[0],
-                  part_jump[i].c[1],
-                  part_jump[i].c[2],
-                  1.0f - part_jump[i].p[1] / jump_height);
-
-        /*
-         * X is the current time since some Epoch, Y is the time it
-         * takes for a squiggle to grow to its full size and then
-         * shrink again.  F is the current scale of the squiggle in
-         * the interval [0.0, 1.0].
-         */
-
-#define F(x, y) fabsf(fcosf(((x) / (y)) * PI))
+        glColorPointer (4, GL_FLOAT, sizeof (struct part_draw),
+                        (GLvoid *) offsetof (struct part_draw, c));
+        glVertexPointer(3, GL_FLOAT, sizeof (struct part_draw),
+                        (GLvoid *) offsetof (struct part_draw, p));
 
-        part_draw(M, part_jump[i].p, radius - 0.05f,
-                  0.0f, F(t, part_jump[i].w));
+        glEnable(GL_POINT_SPRITE);
+        {
+            glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
+            glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, c);
+            glPointSize(s);
 
-#undef F
+            glDrawArrays(GL_POINTS, 0, PART_MAX_COIN);
+        }
+        glDisable(GL_POINT_SPRITE);
     }
+    glDisableClientState(GL_VERTEX_ARRAY);
+    glDisableClientState(GL_COLOR_ARRAY);
 
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
     glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
 }
 
index 08cc645..6b3850d 100644 (file)
 
 /*---------------------------------------------------------------------------*/
 
-void part_reset(float, float);
-void part_init(float, float);
+void part_reset(void);
+void part_init(void);
 void part_free(void);
 
 void part_burst(const float *, const float *);
 void part_step(const float *, float);
 
 void part_draw_coin(const float *, float);
-void part_draw_goal(const float *, float, float, float);
-void part_draw_jump(const float *, float, float, float);
 
 void part_lerp_apply(float);