#include "vec3.h"
#include "glext.h"
#include "config.h"
-#include "solid_gl.h"
+#include "common.h"
+
+#include "solid_draw.h"
/*---------------------------------------------------------------------------*/
static int has_inner = 0;
static int has_outer = 0;
-static struct s_file solid;
-static struct s_file inner;
-static struct s_file outer;
+static struct s_full solid;
+static struct s_full inner;
+static struct s_full outer;
-#define F_PENDULUM 1
-#define F_DRAWBACK 2
-#define F_DRAWCLIP 4
-#define F_ZBUFFER 8
+#define F_PENDULUM 1
+#define F_DRAWBACK 2
+#define F_DRAWCLIP 4
+#define F_DEPTHMASK 8
+#define F_DEPTHTEST 16
static int solid_flags;
static int inner_flags;
static int outer_flags;
+static float solid_alpha;
+static float inner_alpha;
+static float outer_alpha;
+
/*---------------------------------------------------------------------------*/
-static int ball_flags(const struct s_file *fp)
+#define SET(B, v, b) ((v) ? ((B) | (b)) : ((B) & ~(b)))
+
+static int ball_opts(const struct s_base *base, float *alpha)
{
- int flags = 0;
+ int flags = F_DEPTHTEST;
int di;
- for (di = 0; di < fp->dc; ++di)
+ for (di = 0; di < base->dc; ++di)
{
- char *k = fp->av + fp->dv[di].ai;
- char *v = fp->av + fp->dv[di].aj;
-
- if (strcmp(k, "pendulum") == 0) flags |= (atoi(v) * F_PENDULUM);
- if (strcmp(k, "drawback") == 0) flags |= (atoi(v) * F_DRAWBACK);
- if (strcmp(k, "drawclip") == 0) flags |= (atoi(v) * F_DRAWCLIP);
- if (strcmp(k, "zbuffer") == 0) flags |= (atoi(v) * F_ZBUFFER);
+ char *k = base->av + base->dv[di].ai;
+ char *v = base->av + base->dv[di].aj;
+
+ if (strcmp(k, "pendulum") == 0)
+ flags = SET(flags, atoi(v), F_PENDULUM);
+ if (strcmp(k, "drawback") == 0)
+ flags = SET(flags, atoi(v), F_DRAWBACK);
+ if (strcmp(k, "drawclip") == 0)
+ flags = SET(flags, atoi(v), F_DRAWCLIP);
+ if (strcmp(k, "depthmask") == 0)
+ flags = SET(flags, atoi(v), F_DEPTHMASK);
+ if (strcmp(k, "depthtest") == 0)
+ flags = SET(flags, atoi(v), F_DEPTHTEST);
+ if (strcmp(k, "alphatest") == 0)
+ sscanf(v, "%f", alpha);
}
return flags;
void ball_init(void)
{
- int T = config_get_d(CONFIG_TEXTURES);
-
- char solid_file[PATHMAX];
- char inner_file[PATHMAX];
- char outer_file[PATHMAX];
-
- config_get_s(CONFIG_BALL, solid_file, PATHMAX - 12);
- config_get_s(CONFIG_BALL, inner_file, PATHMAX - 12);
- config_get_s(CONFIG_BALL, outer_file, PATHMAX - 12);
-
- strcat(solid_file, "-solid.sol");
- strcat(inner_file, "-inner.sol");
- strcat(outer_file, "-outer.sol");
+ char *solid_file = concat_string(config_get_s(CONFIG_BALL_FILE),
+ "-solid.sol", NULL);
+ char *inner_file = concat_string(config_get_s(CONFIG_BALL_FILE),
+ "-inner.sol", NULL);
+ char *outer_file = concat_string(config_get_s(CONFIG_BALL_FILE),
+ "-outer.sol", NULL);
solid_flags = 0;
inner_flags = 0;
outer_flags = 0;
- if ((has_solid = sol_load_gl(&solid, config_data(solid_file), T, 0)))
- solid_flags = ball_flags(&solid);
+ solid_alpha = 1.0f;
+ inner_alpha = 1.0f;
+ outer_alpha = 1.0f;
+
+ if ((has_solid = sol_load_full(&solid, solid_file, 0)))
+ solid_flags = ball_opts(&solid.base, &solid_alpha);
- if ((has_inner = sol_load_gl(&inner, config_data(inner_file), T, 0)))
- inner_flags = ball_flags(&inner);
+ if ((has_inner = sol_load_full(&inner, inner_file, 0)))
+ inner_flags = ball_opts(&inner.base, &inner_alpha);
- if ((has_outer = sol_load_gl(&outer, config_data(outer_file), T, 0)))
- outer_flags = ball_flags(&outer);
+ if ((has_outer = sol_load_full(&outer, outer_file, 0)))
+ outer_flags = ball_opts(&outer.base, &outer_alpha);
+
+ free(solid_file);
+ free(inner_file);
+ free(outer_file);
}
void ball_free(void)
{
- if (has_outer) sol_free_gl(&outer);
- if (has_inner) sol_free_gl(&inner);
- if (has_solid) sol_free_gl(&solid);
+ if (has_outer) sol_free_full(&outer);
+ if (has_inner) sol_free_full(&inner);
+ if (has_solid) sol_free_full(&solid);
has_solid = has_inner = has_outer = 0;
}
/*---------------------------------------------------------------------------*/
-static void ball_draw_solid(const float *ball_M,
- const float *ball_bill_M)
+static void ball_draw_solid(struct s_rend *rend,
+ const float *ball_M,
+ const float *ball_bill_M, float t)
{
if (has_solid)
{
- const int Z = (solid_flags & F_ZBUFFER);
+ const int mask = (solid_flags & F_DEPTHMASK);
+ const int test = (solid_flags & F_DEPTHTEST);
+
+ if (solid_alpha < 1.0f)
+ {
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GEQUAL, solid_alpha);
+ }
glPushMatrix();
{
/* Draw the solid billboard geometry. */
- if (solid.rc)
+ if (solid.base.rc)
{
- glDepthMask(GL_FALSE);
+ if (test == 0) glDisable(GL_DEPTH_TEST);
+ if (mask == 0) glDepthMask(GL_FALSE);
glDisable(GL_LIGHTING);
{
- sol_bill(&solid, ball_bill_M);
+ sol_bill(&solid.draw, rend, ball_bill_M, t);
}
glEnable(GL_LIGHTING);
- glDepthMask(GL_TRUE);
+ if (mask == 0) glDepthMask(GL_TRUE);
+ if (test == 0) glEnable(GL_DEPTH_TEST);
}
/* Draw the solid opaque and transparent geometry. */
- sol_draw(&solid, Z);
+ sol_draw(&solid.draw, rend, mask, test);
}
glPopMatrix();
+
+ if (solid_alpha < 1.0f)
+ glDisable(GL_ALPHA_TEST);
}
}
-static void ball_draw_inner(const float *pend_M,
+static void ball_draw_inner(struct s_rend *rend,
+ const float *pend_M,
const float *bill_M,
- const float *pend_bill_M)
+ const float *pend_bill_M, float t)
{
if (has_inner)
{
- const int P = (inner_flags & F_PENDULUM);
- const int Z = (inner_flags & F_ZBUFFER);
+ const int pend = (inner_flags & F_PENDULUM);
+ const int mask = (inner_flags & F_DEPTHMASK);
+ const int test = (inner_flags & F_DEPTHTEST);
+
+ if (inner_alpha < 1.0f)
+ {
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GEQUAL, inner_alpha);
+ }
/* Apply the pendulum rotation. */
- if (P)
+ if (pend)
{
glPushMatrix();
glMultMatrixf(pend_M);
/* Draw the inner opaque and transparent geometry. */
- sol_draw(&inner, Z);
+ sol_draw(&inner.draw, rend, mask, test);
/* Draw the inner billboard geometry. */
- if (inner.rc)
+ if (inner.base.rc)
{
- glDepthMask(GL_FALSE);
+ if (test == 0) glDisable(GL_DEPTH_TEST);
+ if (mask == 0) glDepthMask(GL_FALSE);
glDisable(GL_LIGHTING);
{
- if (P)
- sol_bill(&inner, pend_bill_M);
+ if (pend)
+ sol_bill(&inner.draw, rend, pend_bill_M, t);
else
- sol_bill(&inner, bill_M);
+ sol_bill(&inner.draw, rend, bill_M, t);
}
glEnable(GL_LIGHTING);
- glDepthMask(GL_TRUE);
+ if (mask == 0) glDepthMask(GL_TRUE);
+ if (test == 0) glEnable(GL_DEPTH_TEST);
}
- if (P)
+ if (pend)
glPopMatrix();
+
+ if (inner_alpha < 1.0f)
+ glDisable(GL_ALPHA_TEST);
}
}
-static void ball_draw_outer(const float *pend_M,
+static void ball_draw_outer(struct s_rend *rend,
+ const float *pend_M,
const float *bill_M,
- const float *pend_bill_M)
+ const float *pend_bill_M, float t)
{
if (has_outer)
{
- const int P = (outer_flags & F_PENDULUM);
- const int Z = (outer_flags & F_ZBUFFER);
+ const int pend = (outer_flags & F_PENDULUM);
+ const int mask = (outer_flags & F_DEPTHMASK);
+ const int test = (outer_flags & F_DEPTHTEST);
+
+ if (outer_alpha < 1.0f)
+ {
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GEQUAL, outer_alpha);
+ }
/* Apply the pendulum rotation. */
- if (P)
+ if (pend)
{
glPushMatrix();
glMultMatrixf(pend_M);
/* Draw the outer opaque and transparent geometry. */
- sol_draw(&outer, Z);
+ sol_draw(&outer.draw, rend, mask, test);
/* Draw the outer billboard geometry. */
- if (outer.rc)
+ if (outer.base.rc)
{
- glDepthMask(GL_FALSE);
+ if (test == 0) glDisable(GL_DEPTH_TEST);
+ if (mask == 0) glDepthMask(GL_FALSE);
glDisable(GL_LIGHTING);
{
- if (P)
- sol_bill(&outer, pend_bill_M);
+ if (pend)
+ sol_bill(&outer.draw, rend, pend_bill_M, t);
else
- sol_bill(&outer, bill_M);
+ sol_bill(&outer.draw, rend, bill_M, t);
}
glEnable(GL_LIGHTING);
- glDepthMask(GL_TRUE);
+ if (mask == 0) glDepthMask(GL_TRUE);
+ if (test == 0) glEnable(GL_DEPTH_TEST);
}
- if (P)
+ if (pend)
glPopMatrix();
+
+ if (outer_alpha < 1.0f)
+ glDisable(GL_ALPHA_TEST);
}
}
/*---------------------------------------------------------------------------*/
-static void ball_pass_inner(const float *ball_M,
+static void ball_pass_inner(struct s_rend *rend,
+ const float *ball_M,
const float *pend_M,
const float *bill_M,
const float *ball_bill_M,
- const float *pend_bill_M)
+ const float *pend_bill_M, float t)
{
/* Sort the inner ball using clip planes. */
if (inner_flags & F_DRAWCLIP)
{
glEnable(GL_CLIP_PLANE1);
- ball_draw_inner( pend_M, bill_M, pend_bill_M);
+ ball_draw_inner(rend, pend_M, bill_M, pend_bill_M, t);
glDisable(GL_CLIP_PLANE1);
-
+
glEnable(GL_CLIP_PLANE2);
- ball_draw_inner( pend_M, bill_M, pend_bill_M);
+ ball_draw_inner(rend, pend_M, bill_M, pend_bill_M, t);
glDisable(GL_CLIP_PLANE2);
}
else if (inner_flags & F_DRAWBACK)
{
glCullFace(GL_FRONT);
- ball_draw_inner( pend_M, bill_M, pend_bill_M);
+ ball_draw_inner(rend, pend_M, bill_M, pend_bill_M, t);
glCullFace(GL_BACK);
- ball_draw_inner( pend_M, bill_M, pend_bill_M);
+ ball_draw_inner(rend, pend_M, bill_M, pend_bill_M, t);
}
/* Draw the inner ball normally. */
else
{
- ball_draw_inner( pend_M, bill_M, pend_bill_M);
+ ball_draw_inner(rend, pend_M, bill_M, pend_bill_M, t);
}
}
-static void ball_pass_solid(const float *ball_M,
+static void ball_pass_solid(struct s_rend *rend,
+ const float *ball_M,
const float *pend_M,
const float *bill_M,
const float *ball_bill_M,
- const float *pend_bill_M)
+ const float *pend_bill_M, float t)
{
/* Sort the solid ball with the inner ball using clip planes. */
if (solid_flags & F_DRAWCLIP)
{
glEnable(GL_CLIP_PLANE1);
- ball_draw_solid(ball_M, ball_bill_M);
+ ball_draw_solid(rend, ball_M, ball_bill_M, t);
glDisable(GL_CLIP_PLANE1);
-
- ball_pass_inner(ball_M, pend_M, bill_M, ball_bill_M, pend_bill_M);
+
+ ball_pass_inner(rend, ball_M, pend_M, bill_M, ball_bill_M, pend_bill_M, t);
glEnable(GL_CLIP_PLANE2);
- ball_draw_solid(ball_M, ball_bill_M);
+ ball_draw_solid(rend, ball_M, ball_bill_M, t);
glDisable(GL_CLIP_PLANE2);
}
else if (solid_flags & F_DRAWBACK)
{
glCullFace(GL_FRONT);
- ball_draw_solid(ball_M, ball_bill_M);
+ ball_draw_solid(rend, ball_M, ball_bill_M, t);
glCullFace(GL_BACK);
-
- ball_pass_inner(ball_M, pend_M, bill_M, ball_bill_M, pend_bill_M);
- ball_draw_solid(ball_M, ball_bill_M);
+
+ ball_pass_inner(rend, ball_M, pend_M, bill_M, ball_bill_M, pend_bill_M, t);
+ ball_draw_solid(rend, ball_M, ball_bill_M, t);
}
/* Draw the solid ball after the inner ball. */
else
{
- ball_pass_inner(ball_M, pend_M, bill_M, ball_bill_M, pend_bill_M);
- ball_draw_solid(ball_M, ball_bill_M);
+ ball_pass_inner(rend, ball_M, pend_M, bill_M, ball_bill_M, pend_bill_M, t);
+ ball_draw_solid(rend, ball_M, ball_bill_M, t);
}
}
-static void ball_pass_outer(const float *ball_M,
+static void ball_pass_outer(struct s_rend *rend,
+ const float *ball_M,
const float *pend_M,
const float *bill_M,
const float *ball_bill_M,
- const float *pend_bill_M)
+ const float *pend_bill_M, float t)
{
/* Sort the outer ball with the solid ball using clip planes. */
if (outer_flags & F_DRAWCLIP)
{
glEnable(GL_CLIP_PLANE1);
- ball_draw_outer( pend_M, bill_M, pend_bill_M);
+ ball_draw_outer(rend, pend_M, bill_M, pend_bill_M, t);
glDisable(GL_CLIP_PLANE1);
-
- ball_pass_solid(ball_M, pend_M, bill_M, ball_bill_M, pend_bill_M);
+
+ ball_pass_solid(rend, ball_M, pend_M, bill_M, ball_bill_M, pend_bill_M, t);
glEnable(GL_CLIP_PLANE2);
- ball_draw_outer( pend_M, bill_M, pend_bill_M);
+ ball_draw_outer(rend, pend_M, bill_M, pend_bill_M, t);
glDisable(GL_CLIP_PLANE2);
}
else if (outer_flags & F_DRAWBACK)
{
glCullFace(GL_FRONT);
- ball_draw_outer( pend_M, bill_M, pend_bill_M);
+ ball_draw_outer(rend, pend_M, bill_M, pend_bill_M, t);
glCullFace(GL_BACK);
-
- ball_pass_solid(ball_M, pend_M, bill_M, ball_bill_M, pend_bill_M);
- ball_draw_outer( pend_M, bill_M, pend_bill_M);
+
+ ball_pass_solid(rend, ball_M, pend_M, bill_M, ball_bill_M, pend_bill_M, t);
+ ball_draw_outer(rend, pend_M, bill_M, pend_bill_M, t);
}
/* Draw the outer ball after the solid ball. */
else
{
- ball_pass_solid(ball_M, pend_M, bill_M, ball_bill_M, pend_bill_M);
- ball_draw_outer( pend_M, bill_M, pend_bill_M);
+ ball_pass_solid(rend, ball_M, pend_M, bill_M, ball_bill_M, pend_bill_M, t);
+ ball_draw_outer(rend, pend_M, bill_M, pend_bill_M, t);
}
}
/*---------------------------------------------------------------------------*/
-void ball_draw(const float *ball_M,
+void ball_draw(struct s_rend *rend,
+ const float *ball_M,
const float *pend_M,
- const float *bill_M)
+ const float *bill_M, float t)
{
/* Compute transforms for ball and pendulum billboards. */
m_xps(ball_T, ball_M);
m_xps(pend_T, pend_M);
- m_xps(pend_T, pend_M);
m_mult(ball_bill_M, ball_T, bill_M);
m_mult(pend_bill_M, pend_T, bill_M);
/* Go to GREAT pains to ensure all layers are drawn back-to-front. */
- ball_pass_outer(ball_M, pend_M, bill_M, ball_bill_M, pend_bill_M);
+ ball_pass_outer(rend, ball_M, pend_M, bill_M, ball_bill_M, pend_bill_M, t);
}
/*---------------------------------------------------------------------------*/