MAPC_OBJS := \
share/vec3.o \
share/base_image.o \
- share/solid.o \
+ share/solid_base.o \
share/binary.o \
share/base_config.o \
share/common.o \
share/vec3.o \
share/base_image.o \
share/image.o \
- share/solid.o \
- share/solid_gl.o \
+ share/solid_base.o \
+ share/solid_vary.o \
+ share/solid_draw.o \
share/solid_cmd.o \
share/solid_all.o \
share/part.o \
share/vec3.o \
share/base_image.o \
share/image.o \
- share/solid.o \
- share/solid_gl.o \
+ share/solid_base.o \
+ share/solid_vary.o \
+ share/solid_draw.o \
share/solid_cmd.o \
share/solid_all.o \
share/part.o \
#include "demo.h"
#include "audio.h"
-#include "solid.h"
#include "config.h"
#include "binary.h"
#include "common.h"
#include "ball.h"
#include "image.h"
#include "audio.h"
-#include "solid_gl.h"
#include "config.h"
#include "video.h"
+#include "solid_draw.h"
+
#include "game_client.h"
#include "game_common.h"
#include "game_proxy.h"
/*---------------------------------------------------------------------------*/
-static struct game_draw dr;
+static struct game_draw gd;
static float timer = 0.0f; /* Clock time */
static int status = GAME_NONE; /* Outcome of the game */
static void game_run_cmd(const union cmd *cmd)
{
- if (dr.state)
+ if (gd.state)
{
- struct s_file *fp = &dr.file;
- struct s_item *hp;
- struct s_ball *up;
+ struct s_vary *vary = &gd.file.vary;
+ struct v_item *hp;
+ struct v_ball *up;
float v[3];
float dt;
/* Compute gravity for particle effects. */
if (status == GAME_GOAL)
- game_tilt_grav(v, GRAVITY_UP, &dr.tilt);
+ game_tilt_grav(v, GRAVITY_UP, &gd.tilt);
else
- game_tilt_grav(v, GRAVITY_DN, &dr.tilt);
+ game_tilt_grav(v, GRAVITY_DN, &gd.tilt);
/* Step particle, goal and jump effects. */
{
dt = 1.0f / (float) ups;
- if (dr.goal_e && dr.goal_k < 1.0f)
- dr.goal_k += dt;
+ if (gd.goal_e && gd.goal_k < 1.0f)
+ gd.goal_k += dt;
- if (dr.jump_b)
+ if (gd.jump_b)
{
- dr.jump_dt += dt;
+ gd.jump_dt += dt;
- if (1.0f < dr.jump_dt)
- dr.jump_b = 0;
+ if (1.0f < gd.jump_dt)
+ gd.jump_b = 0;
}
part_step(v, dt);
case CMD_MAKE_BALL:
/* Allocate a new ball and mark it as the current ball. */
- if ((up = realloc(fp->uv, sizeof (*up) * (fp->uc + 1))))
+ if ((up = realloc(vary->uv, sizeof (*up) * (vary->uc + 1))))
{
- fp->uv = up;
- curr_ball = fp->uc;
- fp->uc++;
+ vary->uv = up;
+ curr_ball = vary->uc;
+ vary->uc++;
}
break;
case CMD_MAKE_ITEM:
/* Allocate and initialise a new item. */
- if ((hp = realloc(fp->hv, sizeof (*hp) * (fp->hc + 1))))
+ if ((hp = realloc(vary->hv, sizeof (*hp) * (vary->hc + 1))))
{
- struct s_item h;
+ struct v_item h;
v_cpy(h.p, cmd->mkitem.p);
h.t = cmd->mkitem.t;
h.n = cmd->mkitem.n;
- fp->hv = hp;
- fp->hv[fp->hc] = h;
- fp->hc++;
+ vary->hv = hp;
+ vary->hv[vary->hc] = h;
+ vary->hc++;
}
break;
case CMD_PICK_ITEM:
/* Set up particle effects and discard the item. */
- assert(cmd->pkitem.hi < fp->hc);
+ assert(cmd->pkitem.hi < vary->hc);
- hp = fp->hv + cmd->pkitem.hi;
+ hp = vary->hv + cmd->pkitem.hi;
item_color(hp, v);
part_burst(hp->p, v);
case CMD_TILT_ANGLES:
if (!got_tilt_axes)
- game_tilt_axes(&dr.tilt, dr.view.e);
+ game_tilt_axes(&gd.tilt, gd.view.e);
- dr.tilt.rx = cmd->tiltangles.x;
- dr.tilt.rz = cmd->tiltangles.z;
+ gd.tilt.rx = cmd->tiltangles.x;
+ gd.tilt.rz = cmd->tiltangles.z;
break;
case CMD_SOUND:
break;
case CMD_JUMP_ENTER:
- dr.jump_b = 1;
- dr.jump_e = 0;
- dr.jump_dt = 0.0f;
+ gd.jump_b = 1;
+ gd.jump_e = 0;
+ gd.jump_dt = 0.0f;
break;
case CMD_JUMP_EXIT:
- dr.jump_e = 1;
+ gd.jump_e = 1;
break;
case CMD_BODY_PATH:
- fp->bv[cmd->bodypath.bi].pi = cmd->bodypath.pi;
+ vary->bv[cmd->bodypath.bi].pi = cmd->bodypath.pi;
break;
case CMD_BODY_TIME:
- fp->bv[cmd->bodytime.bi].t = cmd->bodytime.t;
+ vary->bv[cmd->bodytime.bi].t = cmd->bodytime.t;
break;
case CMD_GOAL_OPEN:
* this is the first update.
*/
- if (!dr.goal_e)
+ if (!gd.goal_e)
{
- dr.goal_e = 1;
- dr.goal_k = first_update ? 1.0f : 0.0f;
+ gd.goal_e = 1;
+ gd.goal_k = first_update ? 1.0f : 0.0f;
}
break;
case CMD_SWCH_ENTER:
- fp->xv[cmd->swchenter.xi].e = 1;
+ vary->xv[cmd->swchenter.xi].e = 1;
break;
case CMD_SWCH_TOGGLE:
- fp->xv[cmd->swchtoggle.xi].f = !fp->xv[cmd->swchtoggle.xi].f;
+ vary->xv[cmd->swchtoggle.xi].f = !vary->xv[cmd->swchtoggle.xi].f;
break;
case CMD_SWCH_EXIT:
- fp->xv[cmd->swchexit.xi].e = 0;
+ vary->xv[cmd->swchexit.xi].e = 0;
break;
case CMD_UPDATES_PER_SECOND:
break;
case CMD_BALL_RADIUS:
- fp->uv[curr_ball].r = cmd->ballradius.r;
+ vary->uv[curr_ball].r = cmd->ballradius.r;
break;
case CMD_CLEAR_ITEMS:
- if (fp->hv)
+ if (vary->hv)
{
- free(fp->hv);
- fp->hv = NULL;
+ free(vary->hv);
+ vary->hv = NULL;
}
- fp->hc = 0;
+ vary->hc = 0;
break;
case CMD_CLEAR_BALLS:
- if (fp->uv)
+ if (vary->uv)
{
- free(fp->uv);
- fp->uv = NULL;
+ free(vary->uv);
+ vary->uv = NULL;
}
- fp->uc = 0;
+ vary->uc = 0;
break;
case CMD_BALL_POSITION:
- up = fp->uv + curr_ball;
+ up = vary->uv + curr_ball;
v_cpy(up->p, cmd->ballpos.p);
break;
case CMD_BALL_BASIS:
- up = fp->uv + curr_ball;
+ up = vary->uv + curr_ball;
v_cpy(up->e[0], cmd->ballbasis.e[0]);
v_cpy(up->e[1], cmd->ballbasis.e[1]);
break;
case CMD_BALL_PEND_BASIS:
- up = fp->uv + curr_ball;
+ up = vary->uv + curr_ball;
v_cpy(up->E[0], cmd->ballpendbasis.E[0]);
v_cpy(up->E[1], cmd->ballpendbasis.E[1]);
break;
case CMD_VIEW_POSITION:
- v_cpy(dr.view.p, cmd->viewpos.p);
+ v_cpy(gd.view.p, cmd->viewpos.p);
break;
case CMD_VIEW_CENTER:
- v_cpy(dr.view.c, cmd->viewcenter.c);
+ v_cpy(gd.view.c, cmd->viewcenter.c);
break;
case CMD_VIEW_BASIS:
- v_cpy(dr.view.e[0], cmd->viewbasis.e[0]);
- v_cpy(dr.view.e[1], cmd->viewbasis.e[1]);
- v_crs(dr.view.e[2], dr.view.e[0], dr.view.e[1]);
+ v_cpy(gd.view.e[0], cmd->viewbasis.e[0]);
+ v_cpy(gd.view.e[1], cmd->viewbasis.e[1]);
+ v_crs(gd.view.e[2], gd.view.e[0], gd.view.e[1]);
break;
case CMD_CURRENT_BALL:
break;
case CMD_PATH_FLAG:
- fp->pv[cmd->pathflag.pi].f = cmd->pathflag.f;
+ vary->pv[cmd->pathflag.pi].f = cmd->pathflag.f;
break;
case CMD_STEP_SIMULATION:
dt = cmd->stepsim.dt;
- for (i = 0; i < fp->bc; i++)
+ for (i = 0; i < vary->bc; i++)
{
- struct s_body *bp = fp->bv + i;
- struct s_path *pp = fp->pv + bp->pi;
+ struct v_body *bp = vary->bv + i;
+ struct v_path *pp = vary->pv + bp->pi;
if (bp->pi >= 0 && pp->f)
bp->t += dt;
case CMD_TILT_AXES:
got_tilt_axes = 1;
- v_cpy(dr.tilt.x, cmd->tiltaxes.x);
- v_cpy(dr.tilt.z, cmd->tiltaxes.z);
+ v_cpy(gd.tilt.x, cmd->tiltaxes.x);
+ v_cpy(gd.tilt.z, cmd->tiltaxes.z);
break;
case CMD_NONE:
coins = 0;
status = GAME_NONE;
- if (dr.state)
+ if (gd.state)
game_client_free();
- if (!sol_load_gl(&dr.file, file_name, config_get_d(CONFIG_SHADOW)))
- return (dr.state = 0);
+ if (!sol_load_full(&gd.file, file_name, config_get_d(CONFIG_SHADOW)))
+ return (gd.state = 0);
- dr.reflective = sol_reflective(&dr.file);
+ gd.reflective = sol_reflective(&gd.file.draw);
- dr.state = 1;
+ gd.state = 1;
- game_tilt_init(&dr.tilt);
+ game_tilt_init(&gd.tilt);
/* Initialize jump and goal states. */
- dr.jump_e = 1;
- dr.jump_b = 0;
+ gd.jump_e = 1;
+ gd.jump_b = 0;
- dr.goal_e = 0;
- dr.goal_k = 0.0f;
+ gd.goal_e = 0;
+ gd.goal_k = 0.0f;
/* Initialise the level, background, particles, fade, and view. */
- dr.fade_k = 1.0f;
- dr.fade_d = -2.0f;
+ gd.fade_k = 1.0f;
+ gd.fade_d = -2.0f;
version.x = 0;
version.y = 0;
- for (i = 0; i < dr.file.dc; i++)
+ for (i = 0; i < gd.file.base.dc; i++)
{
- char *k = dr.file.av + dr.file.dv[i].ai;
- char *v = dr.file.av + dr.file.dv[i].aj;
+ char *k = gd.file.base.av + gd.file.base.dv[i].ai;
+ char *v = gd.file.base.av + gd.file.base.dv[i].aj;
if (strcmp(k, "back") == 0) back_name = v;
if (strcmp(k, "grad") == 0) grad_name = v;
first_update = 1;
back_init(grad_name);
- sol_load_gl(&dr.back, back_name, 0);
+ sol_load_full(&gd.back, back_name, 0);
- return dr.state;
+ return gd.state;
}
void game_client_free(void)
{
- if (dr.state)
+ if (gd.state)
{
game_proxy_clr();
- sol_free_gl(&dr.file);
- sol_free_gl(&dr.back);
+ sol_free_full(&gd.file);
+ sol_free_full(&gd.back);
back_free();
}
- dr.state = 0;
+ gd.state = 0;
}
/*---------------------------------------------------------------------------*/
void game_client_draw(int pose, float t)
{
- game_draw(&dr, pose, t);
+ game_draw(&gd, pose, t);
}
/*---------------------------------------------------------------------------*/
void game_look(float phi, float theta)
{
- dr.view.c[0] = dr.view.p[0] + fsinf(V_RAD(theta)) * fcosf(V_RAD(phi));
- dr.view.c[1] = dr.view.p[1] + fsinf(V_RAD(phi));
- dr.view.c[2] = dr.view.p[2] - fcosf(V_RAD(theta)) * fcosf(V_RAD(phi));
+ gd.view.c[0] = gd.view.p[0] + fsinf(V_RAD(theta)) * fcosf(V_RAD(phi));
+ gd.view.c[1] = gd.view.p[1] + fsinf(V_RAD(phi));
+ gd.view.c[2] = gd.view.p[2] - fcosf(V_RAD(theta)) * fcosf(V_RAD(phi));
}
/*---------------------------------------------------------------------------*/
void game_kill_fade(void)
{
- dr.fade_k = 0.0f;
- dr.fade_d = 0.0f;
+ gd.fade_k = 0.0f;
+ gd.fade_d = 0.0f;
}
void game_step_fade(float dt)
{
- if ((dr.fade_k < 1.0f && dr.fade_d > 0.0f) ||
- (dr.fade_k > 0.0f && dr.fade_d < 0.0f))
- dr.fade_k += dr.fade_d * dt;
+ if ((gd.fade_k < 1.0f && gd.fade_d > 0.0f) ||
+ (gd.fade_k > 0.0f && gd.fade_d < 0.0f))
+ gd.fade_k += gd.fade_d * dt;
- if (dr.fade_k < 0.0f)
+ if (gd.fade_k < 0.0f)
{
- dr.fade_k = 0.0f;
- dr.fade_d = 0.0f;
+ gd.fade_k = 0.0f;
+ gd.fade_d = 0.0f;
}
- if (dr.fade_k > 1.0f)
+ if (gd.fade_k > 1.0f)
{
- dr.fade_k = 1.0f;
- dr.fade_d = 0.0f;
+ gd.fade_k = 1.0f;
+ gd.fade_d = 0.0f;
}
}
void game_fade(float d)
{
- dr.fade_d = d;
+ gd.fade_d = d;
}
/*---------------------------------------------------------------------------*/
void game_client_fly(float k)
{
- game_view_fly(&dr.view, &dr.file, k);
+ game_view_fly(&gd.view, &gd.file.vary, k);
}
/*---------------------------------------------------------------------------*/
#ifndef GAME_CLIENT_H
#define GAME_CLIENT_H
-#include <stdio.h>
-#include "solid.h"
#include "fs.h"
/*---------------------------------------------------------------------------*/
#include "game_common.h"
#include "vec3.h"
#include "config.h"
-#include "solid.h"
+#include "solid_vary.h"
/*---------------------------------------------------------------------------*/
view->e[2][2] = 1.0f;
}
-void game_view_fly(struct game_view *view, const struct s_file *fp, float k)
+void game_view_fly(struct game_view *view, const struct s_vary *vary, float k)
{
/* float x[3] = { 1.f, 0.f, 0.f }; */
float y[3] = { 0.f, 1.f, 0.f };
/* k = 0.0 view is at the ball. */
- if (fp->uc > 0)
+ if (vary->uc > 0)
{
- v_cpy(c0, fp->uv[0].p);
- v_cpy(p0, fp->uv[0].p);
+ v_cpy(c0, vary->uv[0].p);
+ v_cpy(p0, vary->uv[0].p);
}
v_mad(p0, p0, y, view->dp);
/* k = +1.0 view is s_view 0 */
- if (k >= 0 && fp->wc > 0)
+ if (k >= 0 && vary->base->wc > 0)
{
- v_cpy(p1, fp->wv[0].p);
- v_cpy(c1, fp->wv[0].q);
+ v_cpy(p1, vary->base->wv[0].p);
+ v_cpy(c1, vary->base->wv[0].q);
}
/* k = -1.0 view is s_view 1 */
- if (k <= 0 && fp->wc > 1)
+ if (k <= 0 && vary->base->wc > 1)
{
- v_cpy(p1, fp->wv[1].p);
- v_cpy(c1, fp->wv[1].q);
+ v_cpy(p1, vary->base->wv[1].p);
+ v_cpy(c1, vary->base->wv[1].q);
}
/* Interpolate the views. */
#define GAME_COMMON_H
#include "lang.h"
-#include "solid.h"
+#include "solid_vary.h"
/*---------------------------------------------------------------------------*/
};
void game_view_init(struct game_view *);
-void game_view_fly(struct game_view *, const struct s_file *, float);
+void game_view_fly(struct game_view *, const struct s_vary *, float);
/*---------------------------------------------------------------------------*/
* General Public License for more details.
*/
-#include "solid.h"
#include "vec3.h"
#include "glext.h"
#include "ball.h"
#include "item.h"
#include "part.h"
#include "geom.h"
-#include "solid_gl.h"
#include "config.h"
#include "back.h"
#include "video.h"
+#include "solid_draw.h"
+
#include "game_draw.h"
/*---------------------------------------------------------------------------*/
-static void game_draw_balls(const struct s_file *fp,
+static void game_draw_balls(const struct s_vary *vary,
const float *bill_M, float t)
{
float c[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
float ball_M[16];
float pend_M[16];
- m_basis(ball_M, fp->uv[0].e[0], fp->uv[0].e[1], fp->uv[0].e[2]);
- m_basis(pend_M, fp->uv[0].E[0], fp->uv[0].E[1], fp->uv[0].E[2]);
+ m_basis(ball_M, vary->uv[0].e[0], vary->uv[0].e[1], vary->uv[0].e[2]);
+ m_basis(pend_M, vary->uv[0].E[0], vary->uv[0].E[1], vary->uv[0].E[2]);
glPushAttrib(GL_LIGHTING_BIT);
glPushMatrix();
{
- glTranslatef(fp->uv[0].p[0],
- fp->uv[0].p[1] + BALL_FUDGE,
- fp->uv[0].p[2]);
- glScalef(fp->uv[0].r,
- fp->uv[0].r,
- fp->uv[0].r);
+ glTranslatef(vary->uv[0].p[0],
+ vary->uv[0].p[1] + BALL_FUDGE,
+ vary->uv[0].p[2]);
+ glScalef(vary->uv[0].r,
+ vary->uv[0].r,
+ vary->uv[0].r);
glColor4fv(c);
ball_draw(ball_M, pend_M, bill_M, t);
glPopAttrib();
}
-static void game_draw_items(const struct s_file *fp, float t)
+static void game_draw_items(const struct s_vary *vary, float t)
{
float r = 360.f * t;
int hi;
{
item_push(ITEM_COIN);
{
- for (hi = 0; hi < fp->hc; hi++)
+ for (hi = 0; hi < vary->hc; hi++)
- if (fp->hv[hi].t == ITEM_COIN && fp->hv[hi].n > 0)
+ if (vary->hv[hi].t == ITEM_COIN && vary->hv[hi].n > 0)
{
glPushMatrix();
{
- glTranslatef(fp->hv[hi].p[0],
- fp->hv[hi].p[1],
- fp->hv[hi].p[2]);
+ glTranslatef(vary->hv[hi].p[0],
+ vary->hv[hi].p[1],
+ vary->hv[hi].p[2]);
glRotatef(r, 0.0f, 1.0f, 0.0f);
- item_draw(&fp->hv[hi], r);
+ item_draw(&vary->hv[hi], r);
}
glPopMatrix();
}
item_push(ITEM_SHRINK);
{
- for (hi = 0; hi < fp->hc; hi++)
+ for (hi = 0; hi < vary->hc; hi++)
- if (fp->hv[hi].t == ITEM_SHRINK)
+ if (vary->hv[hi].t == ITEM_SHRINK)
{
glPushMatrix();
{
- glTranslatef(fp->hv[hi].p[0],
- fp->hv[hi].p[1],
- fp->hv[hi].p[2]);
+ glTranslatef(vary->hv[hi].p[0],
+ vary->hv[hi].p[1],
+ vary->hv[hi].p[2]);
glRotatef(r, 0.0f, 1.0f, 0.0f);
- item_draw(&fp->hv[hi], r);
+ item_draw(&vary->hv[hi], r);
}
glPopMatrix();
}
item_push(ITEM_GROW);
{
- for (hi = 0; hi < fp->hc; hi++)
+ for (hi = 0; hi < vary->hc; hi++)
- if (fp->hv[hi].t == ITEM_GROW)
+ if (vary->hv[hi].t == ITEM_GROW)
{
glPushMatrix();
{
- glTranslatef(fp->hv[hi].p[0],
- fp->hv[hi].p[1],
- fp->hv[hi].p[2]);
+ glTranslatef(vary->hv[hi].p[0],
+ vary->hv[hi].p[1],
+ vary->hv[hi].p[2]);
glRotatef(r, 0.0f, 1.0f, 0.0f);
- item_draw(&fp->hv[hi], r);
+ item_draw(&vary->hv[hi], r);
}
glPopMatrix();
}
glPopAttrib();
}
-static void game_draw_goals(const struct game_draw *dr,
- const struct s_file *fp,
+static void game_draw_goals(const struct game_draw *gd,
const float *M, float t)
{
- if (dr->goal_e)
+ const struct s_base *base = &gd->file.base;
+
+ if (gd->goal_e)
{
int zi;
glEnable(GL_TEXTURE_2D);
{
- for (zi = 0; zi < fp->zc; zi++)
+ for (zi = 0; zi < base->zc; zi++)
{
glPushMatrix();
{
- glTranslatef(fp->zv[zi].p[0],
- fp->zv[zi].p[1],
- fp->zv[zi].p[2]);
+ glTranslatef(base->zv[zi].p[0],
+ base->zv[zi].p[1],
+ base->zv[zi].p[2]);
- part_draw_goal(M, fp->zv[zi].r, dr->goal_k, t);
+ part_draw_goal(M, base->zv[zi].r, gd->goal_k, t);
}
glPopMatrix();
}
/* Draw the goal column. */
- for (zi = 0; zi < fp->zc; zi++)
+ for (zi = 0; zi < base->zc; zi++)
{
glPushMatrix();
{
- glTranslatef(fp->zv[zi].p[0],
- fp->zv[zi].p[1],
- fp->zv[zi].p[2]);
+ glTranslatef(base->zv[zi].p[0],
+ base->zv[zi].p[1],
+ base->zv[zi].p[2]);
- glScalef(fp->zv[zi].r,
- dr->goal_k,
- fp->zv[zi].r);
+ glScalef(base->zv[zi].r,
+ gd->goal_k,
+ base->zv[zi].r);
goal_draw();
}
}
}
-static void game_draw_jumps(const struct game_draw *dr,
- const struct s_file *fp,
+static void game_draw_jumps(const struct game_draw *gd,
const float *M, float t)
{
+ const struct s_base *base = &gd->file.base;
+
int ji;
glEnable(GL_TEXTURE_2D);
{
- for (ji = 0; ji < fp->jc; ji++)
+ for (ji = 0; ji < base->jc; ji++)
{
glPushMatrix();
{
- glTranslatef(fp->jv[ji].p[0],
- fp->jv[ji].p[1],
- fp->jv[ji].p[2]);
+ glTranslatef(base->jv[ji].p[0],
+ base->jv[ji].p[1],
+ base->jv[ji].p[2]);
- part_draw_jump(M, fp->jv[ji].r, 1.0f, t);
+ part_draw_jump(M, base->jv[ji].r, 1.0f, t);
}
glPopMatrix();
}
}
glDisable(GL_TEXTURE_2D);
- for (ji = 0; ji < fp->jc; ji++)
+ for (ji = 0; ji < base->jc; ji++)
{
glPushMatrix();
{
- glTranslatef(fp->jv[ji].p[0],
- fp->jv[ji].p[1],
- fp->jv[ji].p[2]);
- glScalef(fp->jv[ji].r,
+ glTranslatef(base->jv[ji].p[0],
+ base->jv[ji].p[1],
+ base->jv[ji].p[2]);
+ glScalef(base->jv[ji].r,
1.0f,
- fp->jv[ji].r);
+ base->jv[ji].r);
- jump_draw(!dr->jump_e);
+ jump_draw(!gd->jump_e);
}
glPopMatrix();
}
}
-static void game_draw_swchs(const struct s_file *fp)
+static void game_draw_swchs(const struct s_vary *vary)
{
int xi;
- for (xi = 0; xi < fp->xc; xi++)
+ for (xi = 0; xi < vary->xc; xi++)
{
- if (fp->xv[xi].i)
+ struct v_swch *xp = vary->xv + xi;
+
+ if (xp->base->i)
continue;
glPushMatrix();
{
- glTranslatef(fp->xv[xi].p[0],
- fp->xv[xi].p[1],
- fp->xv[xi].p[2]);
- glScalef(fp->xv[xi].r,
+ glTranslatef(xp->base->p[0],
+ xp->base->p[1],
+ xp->base->p[2]);
+ glScalef(xp->base->r,
1.0f,
- fp->xv[xi].r);
+ xp->base->r);
- swch_draw(fp->xv[xi].f, fp->xv[xi].e);
+ swch_draw(xp->f, xp->e);
}
glPopMatrix();
}
/*---------------------------------------------------------------------------*/
-static void game_draw_tilt(const struct game_draw *dr, int d)
+static void game_draw_tilt(const struct game_draw *gd, int d)
{
- const struct game_tilt *tilt = &dr->tilt;
- const float *ball_p = dr->file.uv->p;
+ const struct game_tilt *tilt = &gd->tilt;
+ const float *ball_p = gd->file.vary.uv[0].p;
/* Rotate the environment about the position of the ball. */
glTranslatef(-ball_p[0], -ball_p[1] * d, -ball_p[2]);
}
-static void game_refl_all(const struct game_draw *dr)
+static void game_refl_all(const struct game_draw *gd)
{
glPushMatrix();
{
- game_draw_tilt(dr, 1);
+ game_draw_tilt(gd, 1);
/* Draw the floor. */
- sol_refl(&dr->file);
+ sol_refl(&gd->file.draw);
}
glPopMatrix();
}
glLightfv(GL_LIGHT1, GL_SPECULAR, light_c[1]);
}
-static void game_draw_back(const struct game_draw *dr, int pose, int d, float t)
+static void game_draw_back(const struct game_draw *gd, int pose, int d, float t)
{
if (pose == POSE_BALL)
return;
glPushMatrix();
{
+ const struct game_view *view = &gd->view;
+
if (d < 0)
{
- const struct game_tilt *tilt = &dr->tilt;
+ const struct game_tilt *tilt = &gd->tilt;
glRotatef(tilt->rz * 2, tilt->z[0], tilt->z[1], tilt->z[2]);
glRotatef(tilt->rx * 2, tilt->x[0], tilt->x[1], tilt->x[2]);
}
- glTranslatef(dr->view.p[0], dr->view.p[1] * d, dr->view.p[2]);
+ glTranslatef(view->p[0], view->p[1] * d, view->p[2]);
if (config_get_d(CONFIG_BACKGROUND))
{
/* Draw all background layers back to front. */
- sol_back(&dr->back, BACK_DIST, FAR_DIST, t);
+ sol_back(&gd->back.draw, BACK_DIST, FAR_DIST, t);
back_draw(0);
- sol_back(&dr->back, 0, BACK_DIST, t);
+ sol_back(&gd->back.draw, 0, BACK_DIST, t);
}
else back_draw(0);
}
glClipPlane(GL_CLIP_PLANE0, e);
}
-static void game_clip_ball(const struct game_draw *dr, int d, const float *p)
+static void game_clip_ball(const struct game_draw *gd, int d, const float *p)
{
GLdouble r, c[3], pz[4], nz[4];
c[1] = p[1] * d;
c[2] = p[2];
- pz[0] = dr->view.p[0] - c[0];
- pz[1] = dr->view.p[1] - c[1];
- pz[2] = dr->view.p[2] - c[2];
+ pz[0] = gd->view.p[0] - c[0];
+ pz[1] = gd->view.p[1] - c[1];
+ pz[2] = gd->view.p[2] - c[2];
r = sqrt(pz[0] * pz[0] + pz[1] * pz[1] + pz[2] * pz[2]);
glClipPlane(GL_CLIP_PLANE2, pz);
}
-static void game_draw_fore(const struct game_draw *dr,
+static void game_draw_fore(const struct game_draw *gd,
int pose, const float *M,
int d, float t)
{
- const float *ball_p = dr->file.uv->p;
- const float ball_r = dr->file.uv->r;
+ const float *ball_p = gd->file.vary.uv[0].p;
+ const float ball_r = gd->file.vary.uv[0].r;
- const struct s_file *fp = &dr->file;
+ const struct s_draw *draw = &gd->file.draw;
glPushMatrix();
{
/* Rotate the environment about the position of the ball. */
- game_draw_tilt(dr, d);
+ game_draw_tilt(gd, d);
/* Compute clipping planes for reflection and ball facing. */
game_clip_refl(d);
- game_clip_ball(dr, d, ball_p);
+ game_clip_ball(gd, d, ball_p);
if (d < 0)
glEnable(GL_CLIP_PLANE0);
switch (pose)
{
case POSE_LEVEL:
- sol_draw(fp, 0, 1);
+ sol_draw(draw, 0, 1);
break;
case POSE_NONE:
/* Draw the coins. */
- game_draw_items(fp, t);
+ game_draw_items(draw->vary, t);
/* Draw the floor. */
- sol_draw(fp, 0, 1);
+ sol_draw(draw, 0, 1);
/* Fall through. */
if (d > 0 && config_get_d(CONFIG_SHADOW))
{
shad_draw_set(ball_p, ball_r);
- sol_shad(fp);
+ sol_shad(draw);
shad_draw_clr();
}
/* Draw the ball. */
- game_draw_balls(fp, M, t);
+ game_draw_balls(draw->vary, M, t);
break;
}
{
glColor3f(1.0f, 1.0f, 1.0f);
- sol_bill(fp, M, t);
+ sol_bill(draw, M, t);
part_draw_coin(M, t);
glDisable(GL_TEXTURE_2D);
{
- game_draw_goals(dr, fp, M, t);
- game_draw_jumps(dr, fp, M, t);
- game_draw_swchs(fp);
+ game_draw_goals(gd, M, t);
+ game_draw_jumps(gd, M, t);
+ game_draw_swchs(draw->vary);
}
glEnable(GL_TEXTURE_2D);
/*---------------------------------------------------------------------------*/
-void game_draw(const struct game_draw *dr, int pose, float t)
+void game_draw(const struct game_draw *gd, int pose, float t)
{
float fov = (float) config_get_d(CONFIG_VIEW_FOV);
- if (dr->jump_b) fov *= 2.f * fabsf(dr->jump_dt - 0.5);
+ if (gd->jump_b) fov *= 2.f * fabsf(gd->jump_dt - 0.5);
- if (dr->state)
+ if (gd->state)
{
- const struct game_view *view = &dr->view;
+ const struct game_view *view = &gd->view;
video_push_persp(fov, 0.1f, FAR_DIST);
glPushMatrix();
glMultMatrixf(M);
glTranslatef(-view->c[0], -view->c[1], -view->c[2]);
- if (dr->reflective && config_get_d(CONFIG_REFLECTION))
+ if (gd->reflective && config_get_d(CONFIG_REFLECTION))
{
glEnable(GL_STENCIL_TEST);
{
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_FALSE);
- game_refl_all(dr);
+ game_refl_all(gd);
glDepthMask(GL_TRUE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glScalef(+1.0f, -1.0f, +1.0f);
game_draw_light();
- game_draw_back(dr, pose, -1, t);
- game_draw_fore(dr, pose, U, -1, t);
+ game_draw_back(gd, pose, -1, t);
+ game_draw_fore(gd, pose, U, -1, t);
}
glPopMatrix();
glFrontFace(GL_CCW);
game_draw_light();
- if (dr->reflective)
+ if (gd->reflective)
{
if (config_get_d(CONFIG_REFLECTION))
{
glEnable(GL_STENCIL_TEST);
{
glStencilFunc(GL_NOTEQUAL, 1, 0xFFFFFFFF);
- game_draw_back(dr, pose, +1, t);
+ game_draw_back(gd, pose, +1, t);
}
glDisable(GL_STENCIL_TEST);
/* Draw mirrors. */
- game_refl_all(dr);
+ game_refl_all(gd);
}
else
{
/* Draw background. */
- game_draw_back(dr, pose, +1, t);
+ game_draw_back(gd, pose, +1, t);
/*
* Draw mirrors, first fully opaque with a custom
glEnable(GL_COLOR_MATERIAL);
{
glColor4f(0.0, 0.0, 0.05, 1.0);
- game_refl_all(dr);
+ game_refl_all(gd);
glColor4f(1.0, 1.0, 1.0, 1.0);
}
glDisable(GL_COLOR_MATERIAL);
- game_refl_all(dr);
+ game_refl_all(gd);
}
}
else
{
- game_draw_back(dr, pose, +1, t);
- game_refl_all(dr);
+ game_draw_back(gd, pose, +1, t);
+ game_refl_all(gd);
}
- game_draw_fore(dr, pose, T, +1, t);
+ game_draw_fore(gd, pose, T, +1, t);
}
glPopMatrix();
video_pop_matrix();
/* Draw the fade overlay. */
- fade_draw(dr->fade_k);
+ fade_draw(gd->fade_k);
}
}
#ifndef GAME_DRAW_H
#define GAME_DRAW_H
-#include "solid.h"
+#include "solid_draw.h"
#include "game_common.h"
struct game_draw
{
int state;
- struct s_file file;
- struct s_file back;
+ struct s_full file;
+ struct s_full back;
int reflective; /* Reflective geometry used? */
static int server_state = 0;
-static struct s_file file;
+static struct s_base base;
+static struct s_vary file;
static float timer = 0.f; /* Clock time */
static int timer_down = 1; /* Timer go up or down? */
static int grow_state = 0; /* Current state (values -1, 0, +1) */
-static void grow_init(const struct s_file *fp, int type)
+static void grow_init(const struct s_vary *vary, int type)
{
if (!got_orig)
{
- grow_orig = fp->uv->r;
+ grow_orig = vary->uv->r;
grow_goal = grow_orig;
grow_strt = grow_orig;
if (grow)
{
grow_t = 0.0;
- grow_strt = fp->uv->r;
+ grow_strt = vary->uv->r;
}
}
-static void grow_step(const struct s_file *fp, float dt)
+static void grow_step(const struct s_vary *vary, float dt)
{
float dr;
/* No sinking through the floor! Keeps ball's bottom constant. */
- fp->uv->p[1] += (dr - fp->uv->r);
- fp->uv->r = dr;
+ vary->uv->p[1] += (dr - vary->uv->r);
+ vary->uv->r = dr;
game_cmd_ballradius();
}
if (server_state)
game_server_free();
- if (!sol_load_only_file(&file, file_name))
+ if (!sol_load_base(&base, file_name))
+ return (server_state = 0);
+
+ if (!sol_load_vary(&file, &base))
return (server_state = 0);
server_state = 1;
version.x = 0;
version.y = 0;
- for (i = 0; i < file.dc; i++)
+ for (i = 0; i < file.base->dc; i++)
{
- char *k = file.av + file.dv[i].ai;
- char *v = file.av + file.dv[i].aj;
+ char *k = file.base->av + file.base->dv[i].ai;
+ char *v = file.base->av + file.base->dv[i].aj;
if (strcmp(k, "version") == 0)
sscanf(v, "%d.%d", &version.x, &version.y);
if (server_state)
{
sol_quit_sim();
- sol_free(&file);
+ sol_free_vary(&file);
server_state = 0;
}
}
static int game_update_state(int bt)
{
- struct s_file *fp = &file;
- struct s_goal *zp;
+ struct s_vary *vary = &file;
+ struct b_goal *zp;
int hi;
float p[3];
/* Test for an item. */
- if (bt && (hi = sol_item_test(fp, p, ITEM_RADIUS)) != -1)
+ if (bt && (hi = sol_item_test(vary, p, ITEM_RADIUS)) != -1)
{
- struct s_item *hp = &file.hv[hi];
+ struct v_item *hp = file.hv + hi;
game_cmd_pkitem(hi);
- grow_init(fp, hp->t);
+ grow_init(vary, hp->t);
if (hp->t == ITEM_COIN)
{
/* Test for a switch. */
- if (sol_swch_test(fp, 0) == SWCH_TRIGGER)
+ if (sol_swch_test(vary, 0) == SWCH_TRIGGER)
audio_play(AUD_SWITCH, 1.f);
/* Test for a jump. */
- if (jump_e == 1 && jump_b == 0 && (sol_jump_test(fp, jump_p, 0) ==
+ if (jump_e == 1 && jump_b == 0 && (sol_jump_test(vary, jump_p, 0) ==
JUMP_TRIGGER))
{
jump_b = 1;
jump_e = 0;
jump_dt = 0.f;
- v_sub(jump_w, jump_p, fp->uv->p);
+ v_sub(jump_w, jump_p, vary->uv->p);
v_add(jump_w, view.p, jump_w);
audio_play(AUD_JUMP, 1.f);
game_cmd_jump(1);
}
- if (jump_e == 0 && jump_b == 0 && (sol_jump_test(fp, jump_p, 0) ==
+ if (jump_e == 0 && jump_b == 0 && (sol_jump_test(vary, jump_p, 0) ==
JUMP_OUTSIDE))
{
jump_e = 1;
/* Test for a goal. */
- if (bt && goal_e && (zp = sol_goal_test(fp, p, 0)))
+ if (bt && goal_e && (zp = sol_goal_test(vary, p, 0)))
{
audio_play(AUD_GOAL, 1.0f);
return GAME_GOAL;
/* Test for fall-out. */
- if (bt && fp->uv[0].p[1] < fp->vv[0].p[1])
+ if (bt && vary->uv[0].p[1] < vary->base->vv[0].p[1])
{
audio_play(AUD_FALL, 1.0f);
return GAME_FALL;
{
if (server_state)
{
- struct s_file *fp = &file;
+ struct s_vary *vary = &file;
float h[3];
game_cmd_tiltaxes();
game_cmd_tiltangles();
- grow_step(fp, dt);
+ grow_step(vary, dt);
game_tilt_grav(h, g, &tilt);
if (0.5f < jump_dt)
{
- v_cpy(fp->uv->p, jump_p);
- v_cpy(view.p, jump_w);
+ v_cpy(vary->uv->p, jump_p);
+ v_cpy(view.p, jump_w);
}
if (1.0f < jump_dt)
jump_b = 0;
{
/* Run the sim. */
- float b = sol_step(fp, h, dt, 0, NULL);
+ float b = sol_step(vary, h, dt, 0, NULL);
/* Mix the sound of a ball bounce. */
if (got_orig)
{
- if (fp->uv->r > grow_orig) audio_play(AUD_BUMPL, k);
- else if (fp->uv->r < grow_orig) audio_play(AUD_BUMPS, k);
- else audio_play(AUD_BUMPM, k);
+ if (vary->uv->r > grow_orig) audio_play(AUD_BUMPL, k);
+ else if (vary->uv->r < grow_orig) audio_play(AUD_BUMPS, k);
+ else audio_play(AUD_BUMPM, k);
}
else audio_play(AUD_BUMPM, k);
}
#ifndef GAME_SERVER_H
#define GAME_SERVER_H
-#include "solid.h"
-#include "fs.h"
-
/*---------------------------------------------------------------------------*/
#define RESPONSE 0.05f /* Input smoothing time */
#include <math.h>
#include <assert.h>
+#include "solid_base.h"
+
#include "common.h"
-#include "solid.h"
#include "config.h"
#include "level.h"
#include "set.h"
/*---------------------------------------------------------------------------*/
-static void scan_level_attribs(struct level *l, const struct s_file *fp)
+static void scan_level_attribs(struct level *l, const struct s_base *base)
{
int i;
int need_goal_easy = 0;
int need_coin_easy = 0;
- for (i = 0; i < fp->dc; i++)
+ for (i = 0; i < base->dc; i++)
{
- char *k = fp->av + fp->dv[i].ai;
- char *v = fp->av + fp->dv[i].aj;
+ char *k = base->av + base->dv[i].ai;
+ char *v = base->av + base->dv[i].aj;
if (strcmp(k, "message") == 0)
SAFECPY(l->message, v);
int level_load(const char *filename, struct level *level)
{
- struct s_file sol;
+ struct s_base base;
memset(level, 0, sizeof (struct level));
- memset(&sol, 0, sizeof (sol));
+ memset(&base, 0, sizeof (base));
- if (!sol_load_only_head(&sol, filename))
+ if (!sol_load_meta(&base, filename))
{
fprintf(stderr, L_("Failure to load level file '%s'\n"), filename);
return 0;
score_init_hs(&level->scores[SCORE_GOAL], 59999, 0);
score_init_hs(&level->scores[SCORE_COIN], 59999, 0);
- scan_level_attribs(level, &sol);
+ scan_level_attribs(level, &base);
- sol_free(&sol);
+ sol_free_base(&base);
return 1;
}
#include "demo.h"
#include "progress.h"
#include "audio.h"
-#include "solid.h"
#include "config.h"
#include "util.h"
#include "common.h"
#include "config.h"
#include "video.h"
-#include "solid_gl.h"
+#include "solid_draw.h"
#include "solid_sim.h"
#include "solid_all.h"
/*---------------------------------------------------------------------------*/
-static struct s_file file;
+static struct s_full file;
static int ball;
static float view_a; /* Ideal view rotation about Y axis */
idle_t = 1.0f;
view_init();
- sol_load_gl(&file, s, config_get_d(CONFIG_SHADOW));
- sol_init_sim(&file);
+ sol_load_full(&file, s, config_get_d(CONFIG_SHADOW));
+ sol_init_sim(&file.vary);
- for (i = 0; i < file.dc; i++)
+ for (i = 0; i < file.base.dc; i++)
{
- const char *k = file.av + file.dv[i].ai;
- const char *v = file.av + file.dv[i].aj;
+ const char *k = file.base.av + file.base.dv[i].ai;
+ const char *v = file.base.av + file.base.dv[i].aj;
if (strcmp(k, "idle") == 0)
{
void game_free(void)
{
sol_quit_sim();
- sol_free_gl(&file);
+ sol_free_full(&file);
}
/*---------------------------------------------------------------------------*/
-static void game_draw_vect_prim(const struct s_file *fp, GLenum mode)
+static void game_draw_vect_prim(const struct s_vary *fp, GLenum mode)
{
float p[3];
float x[3];
glEnd();
}
-static void game_draw_vect(const struct s_file *fp)
+static void game_draw_vect(const struct s_vary *fp)
{
if (view_m > 0.f)
{
}
}
-static void game_draw_balls(const struct s_file *fp,
+static void game_draw_balls(const struct s_vary *fp,
const float *bill_M, float t)
{
static const GLfloat color[5][4] = {
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
}
-static void game_draw_goals(const struct s_file *fp)
+static void game_draw_goals(const struct s_base *fp)
{
int zi;
}
}
-static void game_draw_jumps(const struct s_file *fp)
+static void game_draw_jumps(const struct s_base *fp)
{
int ji;
}
}
-static void game_draw_swchs(const struct s_file *fp)
+static void game_draw_swchs(const struct s_vary *fp)
{
int xi;
for (xi = 0; xi < fp->xc; xi++)
{
- if (fp->xv[xi].i)
+ struct v_swch *xp = fp->xv + xi;
+
+ if (xp->base->i)
continue;
glPushMatrix();
{
- glTranslatef(fp->xv[xi].p[0],
- fp->xv[xi].p[1],
- fp->xv[xi].p[2]);
+ glTranslatef(xp->base->p[0],
+ xp->base->p[1],
+ xp->base->p[2]);
- glScalef(fp->xv[xi].r, 1.f, fp->xv[xi].r);
- swch_draw(fp->xv[xi].f, fp->xv[xi].e);
+ glScalef(xp->base->r, 1.f, xp->base->r);
+ swch_draw(xp->f, xp->e);
}
glPopMatrix();
}
const float light_p[4] = { 8.f, 32.f, 8.f, 0.f };
- const struct s_file *fp = &file;
+ const struct s_draw *fp = &file.draw;
float fov = FOV;
if (config_get_d(CONFIG_SHADOW) && !pose)
{
- shad_draw_set(fp->uv[ball].p, fp->uv[ball].r);
+ shad_draw_set(fp->vary->uv[ball].p, fp->vary->uv[ball].r);
sol_shad(fp);
shad_draw_clr();
}
if (pose == 0)
{
- game_draw_balls(fp, T, t);
- game_draw_vect(fp);
+ game_draw_balls(fp->vary, T, t);
+ game_draw_vect(fp->vary);
}
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, a);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, e);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, h);
- game_draw_goals(fp);
+ game_draw_goals(fp->base);
glEnable(GL_COLOR_MATERIAL);
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glDepthMask(GL_FALSE);
{
- game_draw_jumps(fp);
- game_draw_swchs(fp);
+ game_draw_jumps(fp->base);
+ game_draw_swchs(fp->vary);
}
glDepthMask(GL_TRUE);
glEnable(GL_TEXTURE_2D);
/* Center the view about the ball. */
- v_cpy(view_c, file.uv[ball].p);
- v_inv(view_v, file.uv[ball].v);
+ v_cpy(view_c, file.vary.uv[ball].p);
+ v_inv(view_v, file.vary.uv[ball].v);
switch (config_get_d(CONFIG_CAMERA))
{
{
static float t = 0.f;
- struct s_file *fp = &file;
+ struct s_vary *fp = &file.vary;
float p[3];
if (dt > 0.f)
int game_step(const float g[3], float dt)
{
- struct s_file *fp = &file;
+ struct s_vary *fp = &file.vary;
static float s = 0.f;
static float t = 0.f;
* friction too early and stopping the ball prematurely.
*/
- file.uv[ball].v[0] = -4.f * view_e[2][0] * view_m;
- file.uv[ball].v[1] = -4.f * view_e[2][1] * view_m + BALL_FUDGE;
- file.uv[ball].v[2] = -4.f * view_e[2][2] * view_m;
+ file.vary.uv[ball].v[0] = -4.f * view_e[2][0] * view_m;
+ file.vary.uv[ball].v[1] = -4.f * view_e[2][1] * view_m + BALL_FUDGE;
+ file.vary.uv[ball].v[2] = -4.f * view_e[2][2] * view_m;
view_m = 0.f;
}
void game_set_fly(float k)
{
- struct s_file *fp = &file;
+ struct s_vary *fp = &file.vary;
float x[3] = { 1.f, 0.f, 0.f };
float y[3] = { 0.f, 1.f, 0.f };
v_cpy(view_e[0], x);
v_cpy(view_e[1], y);
- v_sub(view_e[2], fp->uv[ball].p, fp->zv[0].p);
+ v_sub(view_e[2], fp->uv[ball].p, fp->base->zv[0].p);
if (fabs(v_dot(view_e[1], view_e[2])) > 0.999)
v_cpy(view_e[2], z);
/* k = +1.0 view is s_view 0 */
- if (k >= 0 && fp->wc > 0)
+ if (k >= 0 && fp->base->wc > 0)
{
- v_cpy(p1, fp->wv[0].p);
- v_cpy(c1, fp->wv[0].q);
+ v_cpy(p1, fp->base->wv[0].p);
+ v_cpy(c1, fp->base->wv[0].q);
}
/* k = -1.0 view is s_view 1 */
- if (k <= 0 && fp->wc > 1)
+ if (k <= 0 && fp->base->wc > 1)
{
- v_cpy(p1, fp->wv[1].p);
- v_cpy(c1, fp->wv[1].q);
+ v_cpy(p1, fp->base->wv[1].p);
+ v_cpy(c1, fp->base->wv[1].q);
}
/* Interpolate the views. */
jump_e = 1;
jump_b = 0;
- for (ui = 0; ui < file.uc; ui++)
+ for (ui = 0; ui < file.vary.uc; ui++)
{
- file.uv[ui].v[0] = 0.f;
- file.uv[ui].v[1] = 0.f;
- file.uv[ui].v[2] = 0.f;
+ file.vary.uv[ui].v[0] = 0.f;
+ file.vary.uv[ui].v[1] = 0.f;
+ file.vary.uv[ui].v[2] = 0.f;
- file.uv[ui].w[0] = 0.f;
- file.uv[ui].w[1] = 0.f;
- file.uv[ui].w[2] = 0.f;
+ file.vary.uv[ui].w[0] = 0.f;
+ file.vary.uv[ui].w[1] = 0.f;
+ file.vary.uv[ui].w[2] = 0.f;
}
}
void game_get_pos(float p[3], float e[3][3])
{
- v_cpy(p, file.uv[ball].p);
- v_cpy(e[0], file.uv[ball].e[0]);
- v_cpy(e[1], file.uv[ball].e[1]);
- v_cpy(e[2], file.uv[ball].e[2]);
+ v_cpy(p, file.vary.uv[ball].p);
+ v_cpy(e[0], file.vary.uv[ball].e[0]);
+ v_cpy(e[1], file.vary.uv[ball].e[1]);
+ v_cpy(e[2], file.vary.uv[ball].e[2]);
}
void game_set_pos(float p[3], float e[3][3])
{
- v_cpy(file.uv[ball].p, p);
- v_cpy(file.uv[ball].e[0], e[0]);
- v_cpy(file.uv[ball].e[1], e[1]);
- v_cpy(file.uv[ball].e[2], e[2]);
+ v_cpy(file.vary.uv[ball].p, p);
+ v_cpy(file.vary.uv[ball].e[0], e[0]);
+ v_cpy(file.vary.uv[ball].e[1], e[1]);
+ v_cpy(file.vary.uv[ball].e[2], e[2]);
}
/*---------------------------------------------------------------------------*/
#include "vec3.h"
#include "glext.h"
#include "config.h"
-#include "solid_gl.h"
#include "common.h"
+#include "solid_draw.h"
+
/*---------------------------------------------------------------------------*/
static int has_solid = 0;
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 SET(B, v, b) ((v) ? ((B) | (b)) : ((B) & ~(b)))
-static int ball_opts(const struct s_file *fp, float *alpha)
+static int ball_opts(const struct s_base *base, float *alpha)
{
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;
+ 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);
inner_alpha = 1.0f;
outer_alpha = 1.0f;
- if ((has_solid = sol_load_gl(&solid, solid_file, 0)))
- solid_flags = ball_opts(&solid, &solid_alpha);
+ 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, inner_file, 0)))
- inner_flags = ball_opts(&inner, &inner_alpha);
+ 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, outer_file, 0)))
- outer_flags = ball_opts(&outer, &outer_alpha);
+ if ((has_outer = sol_load_full(&outer, outer_file, 0)))
+ outer_flags = ball_opts(&outer.base, &outer_alpha);
free(solid_file);
free(inner_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;
}
/* Draw the solid billboard geometry. */
- if (solid.rc)
+ if (solid.base.rc)
{
if (test == 0) glDisable(GL_DEPTH_TEST);
if (mask == 0) glDepthMask(GL_FALSE);
glDisable(GL_LIGHTING);
{
- sol_bill(&solid, ball_bill_M, t);
+ sol_bill(&solid.draw, ball_bill_M, t);
}
glEnable(GL_LIGHTING);
if (mask == 0) glDepthMask(GL_TRUE);
/* Draw the solid opaque and transparent geometry. */
- sol_draw(&solid, mask, test);
+ sol_draw(&solid.draw, mask, test);
}
glPopMatrix();
/* Draw the inner opaque and transparent geometry. */
- sol_draw(&inner, mask, test);
+ sol_draw(&inner.draw, mask, test);
/* Draw the inner billboard geometry. */
- if (inner.rc)
+ if (inner.base.rc)
{
if (test == 0) glDisable(GL_DEPTH_TEST);
if (mask == 0) glDepthMask(GL_FALSE);
glDisable(GL_LIGHTING);
{
if (pend)
- sol_bill(&inner, pend_bill_M, t);
+ sol_bill(&inner.draw, pend_bill_M, t);
else
- sol_bill(&inner, bill_M, t);
+ sol_bill(&inner.draw, bill_M, t);
}
glEnable(GL_LIGHTING);
/* Draw the outer opaque and transparent geometry. */
- sol_draw(&outer, mask, test);
+ sol_draw(&outer.draw, mask, test);
/* Draw the outer billboard geometry. */
- if (outer.rc)
+ if (outer.base.rc)
{
if (test == 0) glDisable(GL_DEPTH_TEST);
if (mask == 0) glDepthMask(GL_FALSE);
glDisable(GL_LIGHTING);
{
if (pend)
- sol_bill(&outer, pend_bill_M, t);
+ sol_bill(&outer.draw, pend_bill_M, t);
else
- sol_bill(&outer, bill_M, t);
+ sol_bill(&outer.draw, bill_M, t);
}
glEnable(GL_LIGHTING);
if (mask == 0) glDepthMask(GL_TRUE);
#include "geom.h"
#include "part.h"
#include "vec3.h"
-#include "solid.h"
#include "image.h"
#include "config.h"
#include "video.h"
/*---------------------------------------------------------------------------*/
-#include "solid.h"
-
-/*---------------------------------------------------------------------------*/
-
#define IMG_SHAD "png/shadow.png"
#define JUMP_HEIGHT 2.00f
#include "item.h"
#include "glext.h"
#include "vec3.h"
-#include "solid_gl.h"
#include "image.h"
#include "config.h"
+#include "solid_draw.h"
+
/*---------------------------------------------------------------------------*/
-static struct s_file item_coin_file;
-static struct s_file item_grow_file;
-static struct s_file item_shrink_file;
+static struct s_full item_coin_file;
+static struct s_full item_grow_file;
+static struct s_full item_shrink_file;
-void item_color(const struct s_item *hp, float *c)
+void item_color(const struct v_item *hp, float *c)
{
switch (hp->t)
{
void item_init(void)
{
- sol_load_gl(&item_coin_file, "item/coin/coin.sol", 0);
- sol_load_gl(&item_grow_file, "item/grow/grow.sol", 0);
- sol_load_gl(&item_shrink_file, "item/shrink/shrink.sol", 0);
+ sol_load_full(&item_coin_file, "item/coin/coin.sol", 0);
+ sol_load_full(&item_grow_file, "item/grow/grow.sol", 0);
+ sol_load_full(&item_shrink_file, "item/shrink/shrink.sol", 0);
}
void item_free(void)
{
- sol_free_gl(&item_coin_file);
- sol_free_gl(&item_grow_file);
- sol_free_gl(&item_shrink_file);
+ sol_free_full(&item_coin_file);
+ sol_free_full(&item_grow_file);
+ sol_free_full(&item_shrink_file);
}
void item_push(int type)
glEnable(GL_COLOR_MATERIAL);
}
-void item_draw(const struct s_item *hp, float r)
+void item_draw(const struct v_item *hp, float r)
{
+ struct s_draw *draw = NULL;
float c[3];
- struct s_file *fp = NULL;
switch (hp->t)
{
- case ITEM_COIN: fp = &item_coin_file; break;
- case ITEM_GROW: fp = &item_grow_file; break;
- case ITEM_SHRINK: fp = &item_shrink_file; break;
+ case ITEM_COIN: draw = &item_coin_file.draw; break;
+ case ITEM_GROW: draw = &item_grow_file.draw; break;
+ case ITEM_SHRINK: draw = &item_shrink_file.draw; break;
}
item_color(hp, c);
glColor3fv(c);
- sol_draw(fp, 0, 1);
+ sol_draw(draw, 0, 1);
}
void item_pull(void)
#ifndef ITEM_H
#define ITEM_H
-#include "solid.h"
+#include "solid_vary.h"
#define ITEM_RADIUS 0.15f
-void item_color(const struct s_item *, float *);
+void item_color(const struct v_item *, float *);
void item_init(void);
void item_free(void);
void item_push(int);
-void item_draw(const struct s_item *, float);
+void item_draw(const struct v_item *, float);
void item_pull(void);
#endif
#include <string.h>
#include <math.h>
+#include "solid_base.h"
+
#include "vec3.h"
-#include "solid.h"
#include "base_image.h"
#include "base_config.h"
#include "fs.h"
return 0;
}
-static int incm(struct s_file *fp)
+static int incm(struct s_base *fp)
{
return (fp->mc < MAXM) ? fp->mc++ : overflow("mtrl");
}
-static int incv(struct s_file *fp)
+static int incv(struct s_base *fp)
{
return (fp->vc < MAXV) ? fp->vc++ : overflow("vert");
}
-static int ince(struct s_file *fp)
+static int ince(struct s_base *fp)
{
return (fp->ec < MAXE) ? fp->ec++ : overflow("edge");
}
-static int incs(struct s_file *fp)
+static int incs(struct s_base *fp)
{
return (fp->sc < MAXS) ? fp->sc++ : overflow("side");
}
-static int inct(struct s_file *fp)
+static int inct(struct s_base *fp)
{
return (fp->tc < MAXT) ? fp->tc++ : overflow("texc");
}
-static int incg(struct s_file *fp)
+static int incg(struct s_base *fp)
{
return (fp->gc < MAXG) ? fp->gc++ : overflow("geom");
}
-static int incl(struct s_file *fp)
+static int incl(struct s_base *fp)
{
return (fp->lc < MAXL) ? fp->lc++ : overflow("lump");
}
-static int incn(struct s_file *fp)
+static int incn(struct s_base *fp)
{
return (fp->nc < MAXN) ? fp->nc++ : overflow("node");
}
-static int incp(struct s_file *fp)
+static int incp(struct s_base *fp)
{
return (fp->pc < MAXP) ? fp->pc++ : overflow("path");
}
-static int incb(struct s_file *fp)
+static int incb(struct s_base *fp)
{
return (fp->bc < MAXB) ? fp->bc++ : overflow("body");
}
-static int inch(struct s_file *fp)
+static int inch(struct s_base *fp)
{
return (fp->hc < MAXH) ? fp->hc++ : overflow("item");
}
-static int incz(struct s_file *fp)
+static int incz(struct s_base *fp)
{
return (fp->zc < MAXZ) ? fp->zc++ : overflow("goal");
}
-static int incj(struct s_file *fp)
+static int incj(struct s_base *fp)
{
return (fp->jc < MAXJ) ? fp->jc++ : overflow("jump");
}
-static int incx(struct s_file *fp)
+static int incx(struct s_base *fp)
{
return (fp->xc < MAXX) ? fp->xc++ : overflow("swch");
}
-static int incr(struct s_file *fp)
+static int incr(struct s_base *fp)
{
return (fp->rc < MAXR) ? fp->rc++ : overflow("bill");
}
-static int incu(struct s_file *fp)
+static int incu(struct s_base *fp)
{
return (fp->uc < MAXU) ? fp->uc++ : overflow("ball");
}
-static int incw(struct s_file *fp)
+static int incw(struct s_base *fp)
{
return (fp->wc < MAXW) ? fp->wc++ : overflow("view");
}
-static int incd(struct s_file *fp)
+static int incd(struct s_base *fp)
{
return (fp->dc < MAXD) ? fp->dc++ : overflow("dict");
}
-static int inci(struct s_file *fp)
+static int inci(struct s_base *fp)
{
return (fp->ic < MAXI) ? fp->ic++ : overflow("indx");
}
-static void init_file(struct s_file *fp)
+static void init_file(struct s_base *fp)
{
fp->mc = 0;
fp->vc = 0;
fp->ac = 0;
fp->ic = 0;
- fp->mv = (struct s_mtrl *) calloc(MAXM, sizeof (struct s_mtrl));
- fp->vv = (struct s_vert *) calloc(MAXV, sizeof (struct s_vert));
- fp->ev = (struct s_edge *) calloc(MAXE, sizeof (struct s_edge));
- fp->sv = (struct s_side *) calloc(MAXS, sizeof (struct s_side));
- fp->tv = (struct s_texc *) calloc(MAXT, sizeof (struct s_texc));
- fp->gv = (struct s_geom *) calloc(MAXG, sizeof (struct s_geom));
- fp->lv = (struct s_lump *) calloc(MAXL, sizeof (struct s_lump));
- fp->nv = (struct s_node *) calloc(MAXN, sizeof (struct s_node));
- fp->pv = (struct s_path *) calloc(MAXP, sizeof (struct s_path));
- fp->bv = (struct s_body *) calloc(MAXB, sizeof (struct s_body));
- fp->hv = (struct s_item *) calloc(MAXH, sizeof (struct s_item));
- fp->zv = (struct s_goal *) calloc(MAXZ, sizeof (struct s_goal));
- fp->jv = (struct s_jump *) calloc(MAXJ, sizeof (struct s_jump));
- fp->xv = (struct s_swch *) calloc(MAXX, sizeof (struct s_swch));
- fp->rv = (struct s_bill *) calloc(MAXR, sizeof (struct s_bill));
- fp->uv = (struct s_ball *) calloc(MAXU, sizeof (struct s_ball));
- fp->wv = (struct s_view *) calloc(MAXW, sizeof (struct s_view));
- fp->dv = (struct s_dict *) calloc(MAXD, sizeof (struct s_dict));
- fp->av = (char *) calloc(MAXA, sizeof (char));
- fp->iv = (int *) calloc(MAXI, sizeof (int));
+ fp->mv = (struct b_mtrl *) calloc(MAXM, sizeof (*fp->mv));
+ fp->vv = (struct b_vert *) calloc(MAXV, sizeof (*fp->vv));
+ fp->ev = (struct b_edge *) calloc(MAXE, sizeof (*fp->ev));
+ fp->sv = (struct b_side *) calloc(MAXS, sizeof (*fp->sv));
+ fp->tv = (struct b_texc *) calloc(MAXT, sizeof (*fp->tv));
+ fp->gv = (struct b_geom *) calloc(MAXG, sizeof (*fp->gv));
+ fp->lv = (struct b_lump *) calloc(MAXL, sizeof (*fp->lv));
+ fp->nv = (struct b_node *) calloc(MAXN, sizeof (*fp->nv));
+ fp->pv = (struct b_path *) calloc(MAXP, sizeof (*fp->pv));
+ fp->bv = (struct b_body *) calloc(MAXB, sizeof (*fp->bv));
+ fp->hv = (struct b_item *) calloc(MAXH, sizeof (*fp->hv));
+ fp->zv = (struct b_goal *) calloc(MAXZ, sizeof (*fp->zv));
+ fp->jv = (struct b_jump *) calloc(MAXJ, sizeof (*fp->jv));
+ fp->xv = (struct b_swch *) calloc(MAXX, sizeof (*fp->xv));
+ fp->rv = (struct b_bill *) calloc(MAXR, sizeof (*fp->rv));
+ fp->uv = (struct b_ball *) calloc(MAXU, sizeof (*fp->uv));
+ fp->wv = (struct b_view *) calloc(MAXW, sizeof (*fp->wv));
+ fp->dv = (struct b_dict *) calloc(MAXD, sizeof (*fp->dv));
+ fp->av = (char *) calloc(MAXA, sizeof (*fp->av));
+ fp->iv = (int *) calloc(MAXI, sizeof (*fp->iv));
}
/*---------------------------------------------------------------------------*/
static int targ_ji[MAXW];
static int targ_n;
-static void targets(struct s_file *fp)
+static void targets(struct s_base *fp)
{
int i;
if (fs_gets((s), sizeof (s), (f))) \
sscanf((s), "%f %f %f %f", (v), (v) + 1, (v) + 2, (v) + 3)
-static int read_mtrl(struct s_file *fp, const char *name)
+static int read_mtrl(struct s_base *fp, const char *name)
{
static char line[MAXSTR];
- struct s_mtrl *mp;
+ struct b_mtrl *mp;
fs_file fin;
int mi;
* specification.
*/
-static void move_side(struct s_side *sp, const float p[3])
+static void move_side(struct b_side *sp, const float p[3])
{
sp->d -= v_dot(sp->n, p);
}
-static void move_vert(struct s_vert *vp, const float p[3])
+static void move_vert(struct b_vert *vp, const float p[3])
{
v_sub(vp->p, vp->p, p);
}
-static void move_lump(struct s_file *fp,
- struct s_lump *lp, const float p[3])
+static void move_lump(struct s_base *fp,
+ struct b_lump *lp, const float p[3])
{
int i;
move_vert(fp->vv + fp->iv[lp->v0 + i], p);
}
-static void move_body(struct s_file *fp,
- struct s_body *bp)
+static void move_body(struct s_base *fp,
+ struct b_body *bp)
{
int i, *b;
}
}
-static void move_file(struct s_file *fp)
+static void move_file(struct s_base *fp)
{
int i;
* references to Neverball materials, rather than MTL definitions.
*/
-static void read_vt(struct s_file *fp, const char *line)
+static void read_vt(struct s_base *fp, const char *line)
{
- struct s_texc *tp = fp->tv + inct(fp);
+ struct b_texc *tp = fp->tv + inct(fp);
sscanf(line, "%f %f", tp->u, tp->u + 1);
}
-static void read_vn(struct s_file *fp, const char *line)
+static void read_vn(struct s_base *fp, const char *line)
{
- struct s_side *sp = fp->sv + incs(fp);
+ struct b_side *sp = fp->sv + incs(fp);
sscanf(line, "%f %f %f", sp->n, sp->n + 1, sp->n + 2);
}
-static void read_v(struct s_file *fp, const char *line)
+static void read_v(struct s_base *fp, const char *line)
{
- struct s_vert *vp = fp->vv + incv(fp);
+ struct b_vert *vp = fp->vv + incv(fp);
sscanf(line, "%f %f %f", vp->p, vp->p + 1, vp->p + 2);
}
-static void read_f(struct s_file *fp, const char *line,
+static void read_f(struct s_base *fp, const char *line,
int v0, int t0, int s0, int mi)
{
- struct s_geom *gp = fp->gv + incg(fp);
+ struct b_geom *gp = fp->gv + incg(fp);
char c1;
char c2;
gp->mi = mi;
}
-static void read_obj(struct s_file *fp, const char *name, int mi)
+static void read_obj(struct s_base *fp, const char *name, int mi)
{
char line[MAXSTR];
char mtrl[MAXSTR];
/* Parse a lump from the given file and add it to the solid. */
-static void read_lump(struct s_file *fp, fs_file fin)
+static void read_lump(struct s_base *fp, fs_file fin)
{
char k[MAXSTR];
char v[MAXSTR];
int t;
- struct s_lump *lp = fp->lv + incl(fp);
+ struct b_lump *lp = fp->lv + incl(fp);
lp->s0 = fp->ic;
/*---------------------------------------------------------------------------*/
-static void make_path(struct s_file *fp,
+static void make_path(struct s_base *fp,
char k[][MAXSTR],
char v[][MAXSTR], int c)
{
int i, pi = incp(fp);
- struct s_path *pp = fp->pv + pi;
+ struct b_path *pp = fp->pv + pi;
pp->p[0] = 0.f;
pp->p[1] = 0.f;
}
}
-static void make_dict(struct s_file *fp,
+static void make_dict(struct s_base *fp,
const char *k,
const char *v)
{
int space_left, space_needed, di = incd(fp);
- struct s_dict *dp = fp->dv + di;
+ struct b_dict *dp = fp->dv + di;
space_left = MAXA - fp->ac;
space_needed = strlen(k) + 1 + strlen(v) + 1;
static int read_dict_entries = 0;
-static void make_body(struct s_file *fp,
+static void make_body(struct s_base *fp,
char k[][MAXSTR],
char v[][MAXSTR], int c, int l0)
{
float y = 0.f;
float z = 0.f;
- struct s_body *bp = fp->bv + bi;
+ struct b_body *bp = fp->bv + bi;
- bp->t = 0.f;
bp->pi = -1;
bp->ni = -1;
read_dict_entries = 0;
}
-static void make_item(struct s_file *fp,
+static void make_item(struct s_base *fp,
char k[][MAXSTR],
char v[][MAXSTR], int c)
{
int i, hi = inch(fp);
- struct s_item *hp = fp->hv + hi;
+ struct b_item *hp = fp->hv + hi;
hp->p[0] = 0.f;
hp->p[1] = 0.f;
}
}
-static void make_bill(struct s_file *fp,
+static void make_bill(struct s_base *fp,
char k[][MAXSTR],
char v[][MAXSTR], int c)
{
int i, ri = incr(fp);
- struct s_bill *rp = fp->rv + ri;
+ struct b_bill *rp = fp->rv + ri;
- memset(rp, 0, sizeof (struct s_bill));
+ memset(rp, 0, sizeof (struct b_bill));
rp->t = 1.0f;
for (i = 0; i < c; i++)
fp->mv[rp->mi].fl |= M_ADDITIVE;
}
-static void make_goal(struct s_file *fp,
+static void make_goal(struct s_base *fp,
char k[][MAXSTR],
char v[][MAXSTR], int c)
{
int i, zi = incz(fp);
- struct s_goal *zp = fp->zv + zi;
+ struct b_goal *zp = fp->zv + zi;
zp->p[0] = 0.f;
zp->p[1] = 0.f;
}
}
-static void make_view(struct s_file *fp,
+static void make_view(struct s_base *fp,
char k[][MAXSTR],
char v[][MAXSTR], int c)
{
int i, wi = incw(fp);
- struct s_view *wp = fp->wv + wi;
+ struct b_view *wp = fp->wv + wi;
wp->p[0] = 0.f;
wp->p[1] = 0.f;
}
}
-static void make_jump(struct s_file *fp,
+static void make_jump(struct s_base *fp,
char k[][MAXSTR],
char v[][MAXSTR], int c)
{
int i, ji = incj(fp);
- struct s_jump *jp = fp->jv + ji;
+ struct b_jump *jp = fp->jv + ji;
jp->p[0] = 0.f;
jp->p[1] = 0.f;
}
}
-static void make_swch(struct s_file *fp,
+static void make_swch(struct s_base *fp,
char k[][MAXSTR],
char v[][MAXSTR], int c)
{
int i, xi = incx(fp);
- struct s_swch *xp = fp->xv + xi;
+ struct b_swch *xp = fp->xv + xi;
xp->p[0] = 0.f;
xp->p[1] = 0.f;
xp->p[2] = 0.f;
xp->r = 0.5;
xp->pi = 0;
- xp->t0 = 0;
xp->t = 0;
- xp->f0 = 0;
xp->f = 0;
xp->i = 0;
make_ref(v[i], &xp->pi);
if (strcmp(k[i], "timer") == 0)
- {
- sscanf(v[i], "%f", &xp->t0);
- xp->t = xp->t0;
- }
+ sscanf(v[i], "%f", &xp->t);
if (strcmp(k[i], "state") == 0)
- {
- xp->f = atoi(v[i]);
- xp->f0 = atoi(v[i]);
- }
+ xp->f = atoi(v[i]);
if (strcmp(k[i], "invisible") == 0)
xp->i = atoi(v[i]);
}
}
-static void make_targ(struct s_file *fp,
+static void make_targ(struct s_base *fp,
char k[][MAXSTR],
char v[][MAXSTR], int c)
{
targ_n++;
}
-static void make_ball(struct s_file *fp,
+static void make_ball(struct s_base *fp,
char k[][MAXSTR],
char v[][MAXSTR], int c)
{
int i, ui = incu(fp);
- struct s_ball *up = fp->uv + ui;
+ struct b_ball *up = fp->uv + ui;
up->p[0] = 0.0f;
up->p[1] = 0.0f;
/*---------------------------------------------------------------------------*/
-static void read_ent(struct s_file *fp, fs_file fin)
+static void read_ent(struct s_base *fp, fs_file fin)
{
char k[MAXKEY][MAXSTR];
char v[MAXKEY][MAXSTR];
if (!strcmp(v[i], "misc_model")) make_body(fp, k, v, c, l0);
}
-static void read_map(struct s_file *fp, fs_file fin)
+static void read_map(struct s_base *fp, fs_file fin)
{
char k[MAXSTR];
char v[MAXSTR];
/* Test the location of a point with respect to a side plane. */
-static int fore_side(const float p[3], const struct s_side *sp)
+static int fore_side(const float p[3], const struct b_side *sp)
{
return (v_dot(p, sp->n) - sp->d > +SMALL) ? 1 : 0;
}
-static int on_side(const float p[3], const struct s_side *sp)
+static int on_side(const float p[3], const struct b_side *sp)
{
float d = v_dot(p, sp->n) - sp->d;
* geometry.
*/
-static int ok_vert(const struct s_file *fp,
- const struct s_lump *lp, const float p[3])
+static int ok_vert(const struct s_base *fp,
+ const struct b_lump *lp, const float p[3])
{
float r[3];
int i;
* Confirm that this point falls within the current lump, and that it
* is unique. Add it as a vert of the solid.
*/
-static void clip_vert(struct s_file *fp,
- struct s_lump *lp, int si, int sj, int sk)
+static void clip_vert(struct s_base *fp,
+ struct b_lump *lp, int si, int sj, int sk)
{
float M[16], X[16], I[16];
float d[3], p[3];
* finding a pair of vertices that fall on both planes. Add it to the
* solid.
*/
-static void clip_edge(struct s_file *fp,
- struct s_lump *lp, int si, int sj)
+static void clip_edge(struct s_base *fp,
+ struct b_lump *lp, int si, int sj)
{
int i, j;
* verts to have a counter-clockwise winding about the plane normal.
* Create geoms to tessellate the resulting convex polygon.
*/
-static void clip_geom(struct s_file *fp,
- struct s_lump *lp, int si)
+static void clip_geom(struct s_base *fp,
+ struct b_lump *lp, int si)
{
int m[256], t[256], d, i, j, n = 0;
float u[3];
float v[3];
float w[3];
- struct s_side *sp = fp->sv + si;
+ struct b_side *sp = fp->sv + si;
/* Find em. */
* each trio of planes, a new edge for each pair of planes, and a new
* set of geom for each visible plane.
*/
-static void clip_lump(struct s_file *fp, struct s_lump *lp)
+static void clip_lump(struct s_base *fp, struct b_lump *lp)
{
int i, j, k;
lp->fl |= L_DETAIL;
}
-static void clip_file(struct s_file *fp)
+static void clip_file(struct s_base *fp)
{
int i;
* the number of elements that can be eliminated.
*/
-static int comp_mtrl(const struct s_mtrl *mp, const struct s_mtrl *mq)
+static int comp_mtrl(const struct b_mtrl *mp, const struct b_mtrl *mq)
{
if (fabs(mp->d[0] - mq->d[0]) > SMALL) return 0;
if (fabs(mp->d[1] - mq->d[1]) > SMALL) return 0;
return 1;
}
-static int comp_vert(const struct s_vert *vp, const struct s_vert *vq)
+static int comp_vert(const struct b_vert *vp, const struct b_vert *vq)
{
if (fabs(vp->p[0] - vq->p[0]) > SMALL) return 0;
if (fabs(vp->p[1] - vq->p[1]) > SMALL) return 0;
return 1;
}
-static int comp_edge(const struct s_edge *ep, const struct s_edge *eq)
+static int comp_edge(const struct b_edge *ep, const struct b_edge *eq)
{
if (ep->vi != eq->vi && ep->vi != eq->vj) return 0;
if (ep->vj != eq->vi && ep->vj != eq->vj) return 0;
return 1;
}
-static int comp_side(const struct s_side *sp, const struct s_side *sq)
+static int comp_side(const struct b_side *sp, const struct b_side *sq)
{
if (fabs(sp->d - sq->d) > SMALL) return 0;
if (v_dot(sp->n, sq->n) < 0.9999) return 0;
return 1;
}
-static int comp_texc(const struct s_texc *tp, const struct s_texc *tq)
+static int comp_texc(const struct b_texc *tp, const struct b_texc *tq)
{
if (fabs(tp->u[0] - tq->u[0]) > SMALL) return 0;
if (fabs(tp->u[1] - tq->u[1]) > SMALL) return 0;
return 1;
}
-static int comp_geom(const struct s_geom *gp, const struct s_geom *gq)
+static int comp_geom(const struct b_geom *gp, const struct b_geom *gq)
{
if (gp->mi != gq->mi) return 0;
* and sorting the file.
*/
-static void swap_mtrl(struct s_file *fp, int mi, int mj)
+static void swap_mtrl(struct s_base *fp, int mi, int mj)
{
int i;
static int vert_swaps[MAXV];
-static void apply_vert_swaps(struct s_file *fp)
+static void apply_vert_swaps(struct s_base *fp)
{
int i, j;
fp->iv[fp->lv[i].v0 + j] = vert_swaps[fp->iv[fp->lv[i].v0 + j]];
}
-static void swap_vert(struct s_file *fp, int vi, int vj)
+static void swap_vert(struct s_base *fp, int vi, int vj)
{
int i, j;
static int edge_swaps[MAXE];
-static void apply_edge_swaps(struct s_file *fp)
+static void apply_edge_swaps(struct s_base *fp)
{
int i, j;
static int side_swaps[MAXS];
-static void apply_side_swaps(struct s_file *fp)
+static void apply_side_swaps(struct s_base *fp)
{
int i, j;
static int texc_swaps[MAXT];
-static void apply_texc_swaps(struct s_file *fp)
+static void apply_texc_swaps(struct s_base *fp)
{
int i;
static int geom_swaps[MAXG];
-static void apply_geom_swaps(struct s_file *fp)
+static void apply_geom_swaps(struct s_base *fp)
{
int i, j;
/*---------------------------------------------------------------------------*/
-static void uniq_mtrl(struct s_file *fp)
+static void uniq_mtrl(struct s_base *fp)
{
int i, j, k = 0;
fp->mc = k;
}
-static void uniq_vert(struct s_file *fp)
+static void uniq_vert(struct s_base *fp)
{
int i, j, k = 0;
fp->vc = k;
}
-static void uniq_edge(struct s_file *fp)
+static void uniq_edge(struct s_base *fp)
{
int i, j, k = 0;
static int geomlist[MAXV];
static int nextgeom[MAXG];
-static void uniq_geom(struct s_file *fp)
+static void uniq_geom(struct s_base *fp)
{
int i, j, k = 0;
fp->gc = k;
}
-static void uniq_texc(struct s_file *fp)
+static void uniq_texc(struct s_base *fp)
{
int i, j, k = 0;
fp->tc = k;
}
-static void uniq_side(struct s_file *fp)
+static void uniq_side(struct s_base *fp)
{
int i, j, k = 0;
fp->sc = k;
}
-static void uniq_file(struct s_file *fp)
+static void uniq_file(struct s_base *fp)
{
/* Debug mode skips optimization, producing oversized output files. */
/*---------------------------------------------------------------------------*/
-struct s_trip
+struct b_trip
{
int vi;
int mi;
static int comp_trip(const void *p, const void *q)
{
- const struct s_trip *tp = (const struct s_trip *) p;
- const struct s_trip *tq = (const struct s_trip *) q;
+ const struct b_trip *tp = (const struct b_trip *) p;
+ const struct b_trip *tq = (const struct b_trip *) q;
if (tp->vi < tq->vi) return -1;
if (tp->vi > tq->vi) return +1;
return 0;
}
-static void smth_file(struct s_file *fp)
+static void smth_file(struct s_base *fp)
{
- struct s_trip temp, *T;
+ struct b_trip temp, *T;
if (debug_output == 0)
{
- if ((T = (struct s_trip *) malloc(fp->gc * 3 * sizeof (struct s_trip))))
+ if ((T = (struct b_trip *) malloc(fp->gc * 3 * sizeof (struct b_trip))))
{
int gi, i, j, k, l, c = 0;
for (gi = 0; gi < fp->gc; ++gi)
{
- struct s_geom *gp = fp->gv + gi;
+ struct b_geom *gp = fp->gv + gi;
T[c].vi = gp->vi;
T[c].mi = gp->mi;
/* Sort all triplets by vertex index and material. */
- qsort(T, c, sizeof (struct s_trip), comp_trip);
+ qsort(T, c, sizeof (struct b_trip), comp_trip);
/* For each set of triplets sharing vertex index and material... */
for (i = 0; i < c; ++i)
{
- struct s_geom *gp = fp->gv + T[i].gi;
+ struct b_geom *gp = fp->gv + T[i].gi;
if (gp->vi == T[i].vi) gp->si = T[i].si;
if (gp->vj == T[i].vi) gp->sj = T[i].si;
/*---------------------------------------------------------------------------*/
-static void sort_file(struct s_file *fp)
+static void sort_file(struct s_base *fp)
{
int i, j;
(fp->rv[j].d == fp->rv[i].d &&
fp->rv[j].mi > fp->rv[i].mi))
{
- struct s_bill t;
+ struct b_bill t;
t = fp->rv[i];
fp->rv[i] = fp->rv[j];
for (i = 0; i < fp->vc; i++)
if (fp->vv[0].p[1] > fp->vv[i].p[1])
{
- struct s_vert t;
+ struct b_vert t;
t = fp->vv[0];
fp->vv[0] = fp->vv[i];
/*---------------------------------------------------------------------------*/
-static int test_lump_side(const struct s_file *fp,
- const struct s_lump *lp,
- const struct s_side *sp,
+static int test_lump_side(const struct s_base *fp,
+ const struct b_lump *lp,
+ const struct b_side *sp,
float bsphere[4])
{
int si;
return 0;
}
-static int node_node(struct s_file *fp, int l0, int lc, float bsphere[][4])
+static int node_node(struct s_base *fp, int l0, int lc, float bsphere[][4])
{
if (lc < 8)
{
for (lj = 0; lj < li; lj++)
if (fp->lv[l0 + li].fl < fp->lv[l0 + lj].fl)
{
- struct s_lump l;
+ struct b_lump l;
float f;
int i;
/*
* Compute a bounding sphere for a lump (not optimal)
*/
-static void lump_bounding_sphere(struct s_file *fp,
- struct s_lump *lp,
+static void lump_bounding_sphere(struct s_base *fp,
+ struct b_lump *lp,
float bsphere[4])
{
float bbox[6];
for (i = 1; i < lp->vc; i++)
{
- struct s_vert *vp = fp->vv + fp->iv[lp->v0 + i];
+ struct b_vert *vp = fp->vv + fp->iv[lp->v0 + i];
int j;
for (j = 0; j < 3; j++)
bsphere[3] = fsqrtf(r);
}
-static void node_file(struct s_file *fp)
+static void node_file(struct s_base *fp)
{
float bsphere[MAXL][4];
int i;
/*---------------------------------------------------------------------------*/
-static void dump_file(struct s_file *p, const char *name)
+static void dump_file(struct s_base *p, const char *name)
{
int i, j;
int c = 0;
{
char src[MAXSTR] = "";
char dst[MAXSTR] = "";
- struct s_file f;
+ struct s_base f;
fs_file fin;
if (!fs_init(argv[0]))
node_file(&f);
dump_file(&f, dst);
- sol_stor(&f, base_name(dst));
+ sol_stor_base(&f, base_name(dst));
fs_close(fin);
+++ /dev/null
-/*
- * Copyright (C) 2003 Robert Kooima
- *
- * NEVERBALL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "solid.h"
-#include "base_config.h"
-#include "binary.h"
-#include "common.h"
-#include "fs.h"
-
-enum
-{
- SOL_VER_MINIMUM = 6,
- SOL_VER_PATH_FLAGS,
- SOL_VER_CURRENT = SOL_VER_PATH_FLAGS
-};
-
-#define SOL_MAGIC (0xAF | 'S' << 8 | 'O' << 16 | 'L' << 24)
-
-/*---------------------------------------------------------------------------*/
-
-static int sol_version;
-
-static int sol_file(fs_file fin)
-{
- int magic;
- int version;
-
- get_index(fin, &magic);
- get_index(fin, &version);
-
- if (magic != SOL_MAGIC || (version < SOL_VER_MINIMUM ||
- version > SOL_VER_CURRENT))
- return 0;
-
- sol_version = version;
-
- return 1;
-}
-
-static void sol_load_mtrl(fs_file fin, struct s_mtrl *mp)
-{
- get_array(fin, mp->d, 4);
- get_array(fin, mp->a, 4);
- get_array(fin, mp->s, 4);
- get_array(fin, mp->e, 4);
- get_array(fin, mp->h, 1);
- get_index(fin, &mp->fl);
-
- fs_read(mp->f, 1, PATHMAX, fin);
-}
-
-static void sol_load_vert(fs_file fin, struct s_vert *vp)
-{
- get_array(fin, vp->p, 3);
-}
-
-static void sol_load_edge(fs_file fin, struct s_edge *ep)
-{
- get_index(fin, &ep->vi);
- get_index(fin, &ep->vj);
-}
-
-static void sol_load_side(fs_file fin, struct s_side *sp)
-{
- get_array(fin, sp->n, 3);
- get_float(fin, &sp->d);
-}
-
-static void sol_load_texc(fs_file fin, struct s_texc *tp)
-{
- get_array(fin, tp->u, 2);
-}
-
-static void sol_load_geom(fs_file fin, struct s_geom *gp)
-{
- get_index(fin, &gp->mi);
- get_index(fin, &gp->ti);
- get_index(fin, &gp->si);
- get_index(fin, &gp->vi);
- get_index(fin, &gp->tj);
- get_index(fin, &gp->sj);
- get_index(fin, &gp->vj);
- get_index(fin, &gp->tk);
- get_index(fin, &gp->sk);
- get_index(fin, &gp->vk);
-}
-
-static void sol_load_lump(fs_file fin, struct s_lump *lp)
-{
- get_index(fin, &lp->fl);
- get_index(fin, &lp->v0);
- get_index(fin, &lp->vc);
- get_index(fin, &lp->e0);
- get_index(fin, &lp->ec);
- get_index(fin, &lp->g0);
- get_index(fin, &lp->gc);
- get_index(fin, &lp->s0);
- get_index(fin, &lp->sc);
-}
-
-static void sol_load_node(fs_file fin, struct s_node *np)
-{
- get_index(fin, &np->si);
- get_index(fin, &np->ni);
- get_index(fin, &np->nj);
- get_index(fin, &np->l0);
- get_index(fin, &np->lc);
-}
-
-static void sol_load_path(fs_file fin, struct s_path *pp)
-{
- get_array(fin, pp->p, 3);
- get_float(fin, &pp->t);
- get_index(fin, &pp->pi);
- get_index(fin, &pp->f);
- get_index(fin, &pp->s);
-
- pp->tm = TIME_TO_MS(pp->t);
- pp->t = MS_TO_TIME(pp->tm);
-
- if (sol_version >= SOL_VER_PATH_FLAGS)
- get_index(fin, &pp->fl);
-
- pp->e[0] = 1.0f;
- pp->e[1] = 0.0f;
- pp->e[2] = 0.0f;
- pp->e[3] = 0.0f;
-
- if (pp->fl & P_ORIENTED)
- get_array(fin, pp->e, 4);
-}
-
-static void sol_load_body(fs_file fin, struct s_body *bp)
-{
- get_index(fin, &bp->pi);
- get_index(fin, &bp->ni);
- get_index(fin, &bp->l0);
- get_index(fin, &bp->lc);
- get_index(fin, &bp->g0);
- get_index(fin, &bp->gc);
-}
-
-static void sol_load_item(fs_file fin, struct s_item *hp)
-{
- get_array(fin, hp->p, 3);
- get_index(fin, &hp->t);
- get_index(fin, &hp->n);
-}
-
-static void sol_load_goal(fs_file fin, struct s_goal *zp)
-{
- get_array(fin, zp->p, 3);
- get_float(fin, &zp->r);
-}
-
-static void sol_load_swch(fs_file fin, struct s_swch *xp)
-{
- get_array(fin, xp->p, 3);
- get_float(fin, &xp->r);
- get_index(fin, &xp->pi);
- get_float(fin, &xp->t0);
- get_float(fin, &xp->t);
- get_index(fin, &xp->f0);
- get_index(fin, &xp->f);
- get_index(fin, &xp->i);
-
- xp->t0m = TIME_TO_MS(xp->t0);
- xp->tm = TIME_TO_MS(xp->t);
-
- xp->t0 = MS_TO_TIME(xp->t0m);
- xp->t = MS_TO_TIME(xp->tm);
-}
-
-static void sol_load_bill(fs_file fin, struct s_bill *rp)
-{
- get_index(fin, &rp->fl);
- get_index(fin, &rp->mi);
- get_float(fin, &rp->t);
- get_float(fin, &rp->d);
- get_array(fin, rp->w, 3);
- get_array(fin, rp->h, 3);
- get_array(fin, rp->rx, 3);
- get_array(fin, rp->ry, 3);
- get_array(fin, rp->rz, 3);
- get_array(fin, rp->p, 3);
-}
-
-static void sol_load_jump(fs_file fin, struct s_jump *jp)
-{
- get_array(fin, jp->p, 3);
- get_array(fin, jp->q, 3);
- get_float(fin, &jp->r);
-}
-
-static void sol_load_ball(fs_file fin, struct s_ball *bp)
-{
- get_array(fin, bp->p, 3);
- get_float(fin, &bp->r);
-
- bp->e[0][0] = bp->E[0][0] = 1.0f;
- bp->e[0][1] = bp->E[0][1] = 0.0f;
- bp->e[0][2] = bp->E[0][2] = 0.0f;
-
- bp->e[1][0] = bp->E[1][0] = 0.0f;
- bp->e[1][1] = bp->E[1][1] = 1.0f;
- bp->e[1][2] = bp->E[1][2] = 0.0f;
-
- bp->e[2][0] = bp->E[2][0] = 0.0f;
- bp->e[2][1] = bp->E[2][1] = 0.0f;
- bp->e[2][2] = bp->E[2][2] = 1.0f;
-}
-
-static void sol_load_view(fs_file fin, struct s_view *wp)
-{
- get_array(fin, wp->p, 3);
- get_array(fin, wp->q, 3);
-}
-
-static void sol_load_dict(fs_file fin, struct s_dict *dp)
-{
- get_index(fin, &dp->ai);
- get_index(fin, &dp->aj);
-}
-
-static void sol_load_indx(fs_file fin, struct s_file *fp)
-{
- get_index(fin, &fp->ac);
- get_index(fin, &fp->dc);
- get_index(fin, &fp->mc);
- get_index(fin, &fp->vc);
- get_index(fin, &fp->ec);
- get_index(fin, &fp->sc);
- get_index(fin, &fp->tc);
- get_index(fin, &fp->gc);
- get_index(fin, &fp->lc);
- get_index(fin, &fp->nc);
- get_index(fin, &fp->pc);
- get_index(fin, &fp->bc);
- get_index(fin, &fp->hc);
- get_index(fin, &fp->zc);
- get_index(fin, &fp->jc);
- get_index(fin, &fp->xc);
- get_index(fin, &fp->rc);
- get_index(fin, &fp->uc);
- get_index(fin, &fp->wc);
- get_index(fin, &fp->ic);
-}
-
-static int sol_load_file(fs_file fin, struct s_file *fp)
-{
- int i;
-
- if (!sol_file(fin))
- return 0;
-
- sol_load_indx(fin, fp);
-
- if (fp->ac)
- fp->av = (char *) calloc(fp->ac, sizeof (char));
- if (fp->mc)
- fp->mv = (struct s_mtrl *) calloc(fp->mc, sizeof (struct s_mtrl));
- if (fp->vc)
- fp->vv = (struct s_vert *) calloc(fp->vc, sizeof (struct s_vert));
- if (fp->ec)
- fp->ev = (struct s_edge *) calloc(fp->ec, sizeof (struct s_edge));
- if (fp->sc)
- fp->sv = (struct s_side *) calloc(fp->sc, sizeof (struct s_side));
- if (fp->tc)
- fp->tv = (struct s_texc *) calloc(fp->tc, sizeof (struct s_texc));
- if (fp->gc)
- fp->gv = (struct s_geom *) calloc(fp->gc, sizeof (struct s_geom));
- if (fp->lc)
- fp->lv = (struct s_lump *) calloc(fp->lc, sizeof (struct s_lump));
- if (fp->nc)
- fp->nv = (struct s_node *) calloc(fp->nc, sizeof (struct s_node));
- if (fp->pc)
- fp->pv = (struct s_path *) calloc(fp->pc, sizeof (struct s_path));
- if (fp->bc)
- fp->bv = (struct s_body *) calloc(fp->bc, sizeof (struct s_body));
- if (fp->hc)
- fp->hv = (struct s_item *) calloc(fp->hc, sizeof (struct s_item));
- if (fp->zc)
- fp->zv = (struct s_goal *) calloc(fp->zc, sizeof (struct s_goal));
- if (fp->jc)
- fp->jv = (struct s_jump *) calloc(fp->jc, sizeof (struct s_jump));
- if (fp->xc)
- fp->xv = (struct s_swch *) calloc(fp->xc, sizeof (struct s_swch));
- if (fp->rc)
- fp->rv = (struct s_bill *) calloc(fp->rc, sizeof (struct s_bill));
- if (fp->uc)
- fp->uv = (struct s_ball *) calloc(fp->uc, sizeof (struct s_ball));
- if (fp->wc)
- fp->wv = (struct s_view *) calloc(fp->wc, sizeof (struct s_view));
- if (fp->dc)
- fp->dv = (struct s_dict *) calloc(fp->dc, sizeof (struct s_dict));
- if (fp->ic)
- fp->iv = (int *) calloc(fp->ic, sizeof (int));
-
- if (fp->ac)
- fs_read(fp->av, 1, fp->ac, fin);
-
- for (i = 0; i < fp->dc; i++) sol_load_dict(fin, fp->dv + i);
- for (i = 0; i < fp->mc; i++) sol_load_mtrl(fin, fp->mv + i);
- for (i = 0; i < fp->vc; i++) sol_load_vert(fin, fp->vv + i);
- for (i = 0; i < fp->ec; i++) sol_load_edge(fin, fp->ev + i);
- for (i = 0; i < fp->sc; i++) sol_load_side(fin, fp->sv + i);
- for (i = 0; i < fp->tc; i++) sol_load_texc(fin, fp->tv + i);
- for (i = 0; i < fp->gc; i++) sol_load_geom(fin, fp->gv + i);
- for (i = 0; i < fp->lc; i++) sol_load_lump(fin, fp->lv + i);
- for (i = 0; i < fp->nc; i++) sol_load_node(fin, fp->nv + i);
- for (i = 0; i < fp->pc; i++) sol_load_path(fin, fp->pv + i);
- for (i = 0; i < fp->bc; i++) sol_load_body(fin, fp->bv + i);
- for (i = 0; i < fp->hc; i++) sol_load_item(fin, fp->hv + i);
- for (i = 0; i < fp->zc; i++) sol_load_goal(fin, fp->zv + i);
- for (i = 0; i < fp->jc; i++) sol_load_jump(fin, fp->jv + i);
- for (i = 0; i < fp->xc; i++) sol_load_swch(fin, fp->xv + i);
- for (i = 0; i < fp->rc; i++) sol_load_bill(fin, fp->rv + i);
- for (i = 0; i < fp->uc; i++) sol_load_ball(fin, fp->uv + i);
- for (i = 0; i < fp->wc; i++) sol_load_view(fin, fp->wv + i);
- for (i = 0; i < fp->ic; i++) get_index(fin, fp->iv + i);
-
- return 1;
-}
-
-static int sol_load_head(fs_file fin, struct s_file *fp)
-{
- if (!sol_file(fin))
- return 0;
-
- sol_load_indx(fin, fp);
-
- if (fp->ac)
- {
- fp->av = (char *) calloc(fp->ac, sizeof (char));
- fs_read(fp->av, 1, fp->ac, fin);
- }
-
- if (fp->dc)
- {
- int i;
-
- fp->dv = (struct s_dict *) calloc(fp->dc, sizeof (struct s_dict));
-
- for (i = 0; i < fp->dc; i++)
- sol_load_dict(fin, fp->dv + i);
- }
-
- return 1;
-}
-
-int sol_load_only_file(struct s_file *fp, const char *filename)
-{
- fs_file fin;
- int res = 0;
-
- if ((fin = fs_open(filename, "r")))
- {
- res = sol_load_file(fin, fp);
- fs_close(fin);
- }
- return res;
-}
-
-int sol_load_only_head(struct s_file *fp, const char *filename)
-{
- fs_file fin;
- int res = 0;
-
- if ((fin = fs_open(filename, "r")))
- {
- res = sol_load_head(fin, fp);
- fs_close(fin);
- }
- return res;
-}
-
-/*---------------------------------------------------------------------------*/
-
-static void sol_stor_mtrl(fs_file fout, struct s_mtrl *mp)
-{
- put_array(fout, mp->d, 4);
- put_array(fout, mp->a, 4);
- put_array(fout, mp->s, 4);
- put_array(fout, mp->e, 4);
- put_array(fout, mp->h, 1);
- put_index(fout, mp->fl);
-
- fs_write(mp->f, 1, PATHMAX, fout);
-}
-
-static void sol_stor_vert(fs_file fout, struct s_vert *vp)
-{
- put_array(fout, vp->p, 3);
-}
-
-static void sol_stor_edge(fs_file fout, struct s_edge *ep)
-{
- put_index(fout, ep->vi);
- put_index(fout, ep->vj);
-}
-
-static void sol_stor_side(fs_file fout, struct s_side *sp)
-{
- put_array(fout, sp->n, 3);
- put_float(fout, sp->d);
-}
-
-static void sol_stor_texc(fs_file fout, struct s_texc *tp)
-{
- put_array(fout, tp->u, 2);
-}
-
-static void sol_stor_geom(fs_file fout, struct s_geom *gp)
-{
- put_index(fout, gp->mi);
- put_index(fout, gp->ti);
- put_index(fout, gp->si);
- put_index(fout, gp->vi);
- put_index(fout, gp->tj);
- put_index(fout, gp->sj);
- put_index(fout, gp->vj);
- put_index(fout, gp->tk);
- put_index(fout, gp->sk);
- put_index(fout, gp->vk);
-}
-
-static void sol_stor_lump(fs_file fout, struct s_lump *lp)
-{
- put_index(fout, lp->fl);
- put_index(fout, lp->v0);
- put_index(fout, lp->vc);
- put_index(fout, lp->e0);
- put_index(fout, lp->ec);
- put_index(fout, lp->g0);
- put_index(fout, lp->gc);
- put_index(fout, lp->s0);
- put_index(fout, lp->sc);
-}
-
-static void sol_stor_node(fs_file fout, struct s_node *np)
-{
- put_index(fout, np->si);
- put_index(fout, np->ni);
- put_index(fout, np->nj);
- put_index(fout, np->l0);
- put_index(fout, np->lc);
-}
-
-static void sol_stor_path(fs_file fout, struct s_path *pp)
-{
- put_array(fout, pp->p, 3);
- put_float(fout, pp->t);
- put_index(fout, pp->pi);
- put_index(fout, pp->f);
- put_index(fout, pp->s);
- put_index(fout, pp->fl);
-
- if (pp->fl & P_ORIENTED)
- put_array(fout, pp->e, 4);
-}
-
-static void sol_stor_body(fs_file fout, struct s_body *bp)
-{
- put_index(fout, bp->pi);
- put_index(fout, bp->ni);
- put_index(fout, bp->l0);
- put_index(fout, bp->lc);
- put_index(fout, bp->g0);
- put_index(fout, bp->gc);
-}
-
-static void sol_stor_item(fs_file fout, struct s_item *hp)
-{
- put_array(fout, hp->p, 3);
- put_index(fout, hp->t);
- put_index(fout, hp->n);
-}
-
-static void sol_stor_goal(fs_file fout, struct s_goal *zp)
-{
- put_array(fout, zp->p, 3);
- put_float(fout, zp->r);
-}
-
-static void sol_stor_swch(fs_file fout, struct s_swch *xp)
-{
- put_array(fout, xp->p, 3);
- put_float(fout, xp->r);
- put_index(fout, xp->pi);
- put_float(fout, xp->t0);
- put_float(fout, xp->t);
- put_index(fout, xp->f0);
- put_index(fout, xp->f);
- put_index(fout, xp->i);
-}
-
-static void sol_stor_bill(fs_file fout, struct s_bill *rp)
-{
- put_index(fout, rp->fl);
- put_index(fout, rp->mi);
- put_float(fout, rp->t);
- put_float(fout, rp->d);
- put_array(fout, rp->w, 3);
- put_array(fout, rp->h, 3);
- put_array(fout, rp->rx, 3);
- put_array(fout, rp->ry, 3);
- put_array(fout, rp->rz, 3);
- put_array(fout, rp->p, 3);
-}
-
-static void sol_stor_jump(fs_file fout, struct s_jump *jp)
-{
- put_array(fout, jp->p, 3);
- put_array(fout, jp->q, 3);
- put_float(fout, jp->r);
-}
-
-static void sol_stor_ball(fs_file fout, struct s_ball *bp)
-{
- put_array(fout, bp->p, 3);
- put_float(fout, bp->r);
-}
-
-static void sol_stor_view(fs_file fout, struct s_view *wp)
-{
- put_array(fout, wp->p, 3);
- put_array(fout, wp->q, 3);
-}
-
-static void sol_stor_dict(fs_file fout, struct s_dict *dp)
-{
- put_index(fout, dp->ai);
- put_index(fout, dp->aj);
-}
-
-static void sol_stor_file(fs_file fout, struct s_file *fp)
-{
- int i;
- int magic = SOL_MAGIC;
- int version = SOL_VER_CURRENT;
-
- put_index(fout, magic);
- put_index(fout, version);
-
- put_index(fout, fp->ac);
- put_index(fout, fp->dc);
- put_index(fout, fp->mc);
- put_index(fout, fp->vc);
- put_index(fout, fp->ec);
- put_index(fout, fp->sc);
- put_index(fout, fp->tc);
- put_index(fout, fp->gc);
- put_index(fout, fp->lc);
- put_index(fout, fp->nc);
- put_index(fout, fp->pc);
- put_index(fout, fp->bc);
- put_index(fout, fp->hc);
- put_index(fout, fp->zc);
- put_index(fout, fp->jc);
- put_index(fout, fp->xc);
- put_index(fout, fp->rc);
- put_index(fout, fp->uc);
- put_index(fout, fp->wc);
- put_index(fout, fp->ic);
-
- fs_write(fp->av, 1, fp->ac, fout);
-
- for (i = 0; i < fp->dc; i++) sol_stor_dict(fout, fp->dv + i);
- for (i = 0; i < fp->mc; i++) sol_stor_mtrl(fout, fp->mv + i);
- for (i = 0; i < fp->vc; i++) sol_stor_vert(fout, fp->vv + i);
- for (i = 0; i < fp->ec; i++) sol_stor_edge(fout, fp->ev + i);
- for (i = 0; i < fp->sc; i++) sol_stor_side(fout, fp->sv + i);
- for (i = 0; i < fp->tc; i++) sol_stor_texc(fout, fp->tv + i);
- for (i = 0; i < fp->gc; i++) sol_stor_geom(fout, fp->gv + i);
- for (i = 0; i < fp->lc; i++) sol_stor_lump(fout, fp->lv + i);
- for (i = 0; i < fp->nc; i++) sol_stor_node(fout, fp->nv + i);
- for (i = 0; i < fp->pc; i++) sol_stor_path(fout, fp->pv + i);
- for (i = 0; i < fp->bc; i++) sol_stor_body(fout, fp->bv + i);
- for (i = 0; i < fp->hc; i++) sol_stor_item(fout, fp->hv + i);
- for (i = 0; i < fp->zc; i++) sol_stor_goal(fout, fp->zv + i);
- for (i = 0; i < fp->jc; i++) sol_stor_jump(fout, fp->jv + i);
- for (i = 0; i < fp->xc; i++) sol_stor_swch(fout, fp->xv + i);
- for (i = 0; i < fp->rc; i++) sol_stor_bill(fout, fp->rv + i);
- for (i = 0; i < fp->uc; i++) sol_stor_ball(fout, fp->uv + i);
- for (i = 0; i < fp->wc; i++) sol_stor_view(fout, fp->wv + i);
- for (i = 0; i < fp->ic; i++) put_index(fout, fp->iv[i]);
-}
-
-/*---------------------------------------------------------------------------*/
-
-int sol_stor(struct s_file *fp, const char *filename)
-{
- fs_file fout;
-
- if ((fout = fs_open(filename, "w")))
- {
- sol_stor_file(fout, fp);
- fs_close(fout);
-
- return 1;
- }
- return 0;
-}
-
-void sol_free(struct s_file *fp)
-{
- if (fp->av) free(fp->av);
- if (fp->mv) free(fp->mv);
- if (fp->vv) free(fp->vv);
- if (fp->ev) free(fp->ev);
- if (fp->sv) free(fp->sv);
- if (fp->tv) free(fp->tv);
- if (fp->gv) free(fp->gv);
- if (fp->lv) free(fp->lv);
- if (fp->nv) free(fp->nv);
- if (fp->pv) free(fp->pv);
- if (fp->bv) free(fp->bv);
- if (fp->hv) free(fp->hv);
- if (fp->zv) free(fp->zv);
- if (fp->jv) free(fp->jv);
- if (fp->xv) free(fp->xv);
- if (fp->rv) free(fp->rv);
- if (fp->uv) free(fp->uv);
- if (fp->wv) free(fp->wv);
- if (fp->dv) free(fp->dv);
- if (fp->iv) free(fp->iv);
-
- memset(fp, 0, sizeof (struct s_file));
-}
-
-/*---------------------------------------------------------------------------*/
+++ /dev/null
-/*
- * Copyright (C) 2003 Robert Kooima
- *
- * NEVERBALL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef SOL_H
-#define SOL_H
-
-#include "glext.h"
-#include "base_config.h"
-
-/*
- * Some might be taken aback at the terseness of the names of the
- * structure members and the variables used by the functions that
- * access them. Yes, yes, I know: readability. I contend that once
- * the naming convention is embraced, the names become more readable
- * than any verbose alternative, and their brevity and uniformity do
- * more to augment readability than longVariableNames ever could.
- *
- * Members and variables are named XY. X determines the type of
- * structure to which the variable refers. Y determines the usage of
- * the variable.
- *
- * The Xs are as documented by struct s_file:
- *
- * f File (struct s_file)
- * m Material (struct s_mtrl)
- * v Vertex (struct s_vert)
- * e Edge (struct s_edge)
- * s Side (struct s_side)
- * t Texture coord (struct s_texc)
- * g Geometry (struct s_geom)
- * l Lump (struct s_lump)
- * n Node (struct s_node)
- * p Path (struct s_path)
- * b Body (struct s_body)
- * h Item (struct s_item)
- * z Goal (struct s_goal)
- * j Jump (struct s_jump)
- * x Switch (struct s_swch)
- * r Billboard (struct s_bill)
- * u User (struct s_ball)
- * w Viewpoint (struct s_view)
- * d Dictionary (struct s_dict)
- * i Index (int)
- * a Text (char)
- *
- * The Ys are as follows:
- *
- * c Counter
- * p Pointer
- * v Vector (array)
- * 0 Index of the first
- * i Index
- * j Subindex
- * k Subsubindex
- *
- * Thus "up" is a pointer to a user structure. "lc" is the number of
- * lumps. "ei" and "ej" are edge indices into some "ev" edge vector.
- * An edge is defined by two vertices, so an edge structure consists
- * of "vi" and "vj". And so on.
- *
- * Those members that do not conform to this convention are explicitly
- * documented with a comment.
- *
- * These prefixes are still available: c k o q y.
- */
-
-/*---------------------------------------------------------------------------*/
-
-/* Material type flags */
-
-#define M_OPAQUE 1
-#define M_TRANSPARENT 2
-#define M_REFLECTIVE 4
-#define M_ENVIRONMENT 8
-#define M_ADDITIVE 16
-#define M_CLAMPED 32
-#define M_DECAL 64
-#define M_TWO_SIDED 128
-#define M_SHADOWED 256
-
-/* Billboard types. */
-
-#define B_EDGE 1
-#define B_FLAT 2
-#define B_ADDITIVE 4
-#define B_NOFACE 8
-
-/* Lump flags. */
-
-#define L_DETAIL 1
-
-/* Item types. */
-
-#define ITEM_NONE 0
-#define ITEM_COIN 1
-#define ITEM_GROW 2
-#define ITEM_SHRINK 3
-
-/* Path flags. */
-
-#define P_ORIENTED 1
-
-/*---------------------------------------------------------------------------*/
-
-struct s_mtrl
-{
- float d[4]; /* diffuse color */
- float a[4]; /* ambient color */
- float s[4]; /* specular color */
- float e[4]; /* emission color */
- float h[1]; /* specular exponent */
- float angle;
-
- int fl; /* material flags */
-
- GLuint o; /* OpenGL texture object */
- char f[PATHMAX]; /* texture file name */
-};
-
-struct s_vert
-{
- float p[3]; /* vertex position */
-};
-
-struct s_edge
-{
- int vi;
- int vj;
-};
-
-struct s_side
-{
- float n[3]; /* plane normal vector */
- float d; /* distance from origin */
-};
-
-struct s_texc
-{
- float u[2]; /* texture coordinate */
-};
-
-struct s_geom
-{
- int mi;
- int ti, si, vi;
- int tj, sj, vj;
- int tk, sk, vk;
-};
-
-struct s_lump
-{
- int fl; /* lump flags */
- int v0, vc;
- int e0, ec;
- int g0, gc;
- int s0, sc;
-};
-
-struct s_node
-{
- int si;
- int ni;
- int nj;
- int l0;
- int lc;
-};
-
-struct s_path
-{
- float p[3]; /* starting position */
- float e[4]; /* orientation (quaternion) */
- float t; /* travel time */
- int tm; /* milliseconds */
-
- int pi;
- int f; /* enable flag */
- int s; /* smooth flag */
-
- int fl; /* flags */
-
- /* TODO: merge enable and smooth into flags. */
-};
-
-struct s_body
-{
- float t; /* time on current path */
- int tm; /* milliseconds */
-
- GLuint ol; /* opaque geometry list */
- GLuint tl; /* transparent geometry list */
- GLuint rl; /* reflective geometry list */
- GLuint sl; /* shadowed geometry list */
-
- int pi;
- int ni;
- int l0;
- int lc;
- int g0;
- int gc;
-};
-
-struct s_item
-{
- float p[3]; /* position */
- int t; /* type */
- int n; /* value */
-};
-
-struct s_goal
-{
- float p[3]; /* position */
- float r; /* radius */
-};
-
-struct s_swch
-{
- float p[3]; /* position */
- float r; /* radius */
- int pi; /* the linked path */
-
- float t0; /* default timer */
- int t0m; /* milliseconds */
- float t; /* current timer */
- int tm; /* milliseconds */
- int f0; /* default state */
- int f; /* current state */
- int i; /* is invisible? */
- int e; /* is a ball inside it? */
-};
-
-struct s_bill
-{
- int fl;
- int mi;
- float t; /* repeat time interval */
- float d; /* distance */
-
- float w[3]; /* width coefficients */
- float h[3]; /* height coefficients */
-
- float rx[3]; /* X rotation coefficients */
- float ry[3]; /* Y rotation coefficients */
- float rz[3]; /* Z rotation coefficients */
-
- float p[3];
-};
-
-struct s_jump
-{
- float p[3]; /* position */
- float q[3]; /* target position */
- float r; /* radius */
-};
-
-struct s_ball
-{
- float e[3][3]; /* basis of orientation */
- float p[3]; /* position vector */
- float v[3]; /* velocity vector */
- float w[3]; /* angular velocity vector */
- float E[3][3]; /* basis of pendulum */
- float W[3]; /* angular pendulum velocity */
- float r; /* radius */
-};
-
-struct s_view
-{
- float p[3];
- float q[3];
-};
-
-struct s_dict
-{
- int ai;
- int aj;
-};
-
-struct s_file
-{
- int ac;
- int mc;
- int vc;
- int ec;
- int sc;
- int tc;
- int gc;
- int lc;
- int nc;
- int pc;
- int bc;
- int hc;
- int zc;
- int jc;
- int xc;
- int rc;
- int uc;
- int wc;
- int dc;
- int ic;
-
- char *av;
- struct s_mtrl *mv;
- struct s_vert *vv;
- struct s_edge *ev;
- struct s_side *sv;
- struct s_texc *tv;
- struct s_geom *gv;
- struct s_lump *lv;
- struct s_node *nv;
- struct s_path *pv;
- struct s_body *bv;
- struct s_item *hv;
- struct s_goal *zv;
- struct s_jump *jv;
- struct s_swch *xv;
- struct s_bill *rv;
- struct s_ball *uv;
- struct s_view *wv;
- struct s_dict *dv;
- int *iv;
-};
-
-/*---------------------------------------------------------------------------*/
-
-int sol_load_only_file(struct s_file *, const char *);
-int sol_load_only_head(struct s_file *, const char *);
-int sol_stor(struct s_file *, const char *);
-void sol_free(struct s_file *);
-
-/*---------------------------------------------------------------------------*/
-
-#endif
#include "solid_all.h"
#include "solid_cmd.h"
-#include "solid.h"
+#include "solid_vary.h"
+
#include "common.h"
#include "vec3.h"
#include "geom.h"
}
#endif
-void sol_body_p(float p[3], const struct s_file *fp, int pi, float t)
+void sol_body_p(float p[3], const struct s_vary *vary, int pi, float t)
{
float v[3];
if (pi >= 0)
{
- const struct s_path *pp = fp->pv + pi;
- const struct s_path *pq = fp->pv + pp->pi;
+ const struct b_path *pp = vary->base->pv + pi;
+ const struct b_path *pq = vary->base->pv + pp->pi;
float s = MIN(t / pp->t, 1.0f);
}
void sol_body_v(float v[3],
- const struct s_file *fp,
+ const struct s_vary *vary,
int pi, float t, float dt)
{
- if (pi >= 0 && fp->pv[pi].f)
+ if (pi >= 0 && vary->pv[pi].f)
{
float p[3], q[3];
- sol_body_p(p, fp, pi, t);
- sol_body_p(q, fp, pi, t + dt);
+ sol_body_p(p, vary, pi, t);
+ sol_body_p(q, vary, pi, t + dt);
v_sub(v, q, p);
}
void sol_body_e(float e[4],
- const struct s_file *fp,
- const struct s_body *bp,
+ const struct s_vary *vary,
+ const struct v_body *bp,
float dt)
{
- struct s_path *pp = fp->pv + bp->pi;
+ struct b_path *pp = vary->base->pv + bp->pi;
if (bp->pi >= 0)
{
- struct s_path *pq = fp->pv + pp->pi;
+ struct b_path *pq = vary->base->pv + pp->pi;
if (pp->fl & P_ORIENTED || pq->fl & P_ORIENTED)
{
- if (!pp->f)
+ if (!vary->pv[bp->pi].f)
dt = 0;
q_slerp(e, pp->e, pq->e, (bp->t + dt) / pp->t);
}
void sol_body_w(float w[3],
- const struct s_file *fp,
- const struct s_body *bp)
+ const struct s_vary *vary,
+ const struct v_body *bp)
{
- struct s_path *pp = fp->pv + bp->pi;
+ struct b_path *pp = vary->base->pv + bp->pi;
- if (bp->pi >= 0 && pp->f)
+ if (bp->pi >= 0 && vary->pv[bp->pi].f)
{
- struct s_path *pq = fp->pv + pp->pi;
+ struct b_path *pq = vary->base->pv + pp->pi;
if (pp->fl & P_ORIENTED || pq->fl & P_ORIENTED)
{
* Compute the new angular velocity and orientation of a ball pendulum.
* A gives the accelleration of the ball. G gives the gravity vector.
*/
-void sol_pendulum(struct s_ball *up,
+void sol_pendulum(struct v_ball *up,
const float a[3],
const float g[3], float dt)
{
/*---------------------------------------------------------------------------*/
-static void sol_path_flag(struct s_file *fp, int pi, int f)
+static void sol_path_flag(struct s_vary *vary, int pi, int f)
{
union cmd cmd;
- if (fp->pv[pi].f == f)
+ if (vary->pv[pi].f == f)
return;
- fp->pv[pi].f = f;
+ vary->pv[pi].f = f;
cmd.type = CMD_PATH_FLAG;
cmd.pathflag.pi = pi;
- cmd.pathflag.f = fp->pv[pi].f;
+ cmd.pathflag.f = vary->pv[pi].f;
sol_cmd_enq(&cmd);
}
-static void sol_path_loop(struct s_file *fp, int p0, int f)
+static void sol_path_loop(struct s_vary *vary, int p0, int f)
{
int pi = p0;
int pj = p0;
do /* Tortoise and hare cycle traverser. */
{
- sol_path_flag(fp, pi, f);
+ sol_path_flag(vary, pi, f);
- pi = fp->pv[pi].pi;
- pj = fp->pv[pj].pi;
- pj = fp->pv[pj].pi;
+ pi = vary->base->pv[pi].pi;
+ pj = vary->base->pv[pj].pi;
+ pj = vary->base->pv[pj].pi;
}
while (pi != pj);
do
{
- sol_path_flag(fp, pi, f);
+ sol_path_flag(vary, pi, f);
- pi = fp->pv[pi].pi;
- pj = fp->pv[pj].pi;
+ pi = vary->base->pv[pi].pi;
+ pj = vary->base->pv[pj].pi;
}
while (pi != pj && pi != pk);
}
/*
* Compute the states of all switches after DT seconds have passed.
*/
-void sol_swch_step(struct s_file *fp, float dt, int ms)
+void sol_swch_step(struct s_vary *vary, float dt, int ms)
{
int xi;
union cmd cmd;
- for (xi = 0; xi < fp->xc; xi++)
+ for (xi = 0; xi < vary->xc; xi++)
{
- struct s_swch *xp = fp->xv + xi;
+ struct v_swch *xp = vary->xv + xi;
- if (xp->tm < xp->t0m)
+ if (xp->tm < xp->base->tm)
{
xp->t += dt;
xp->tm += ms;
- if (xp->tm >= xp->t0m)
+ if (xp->tm >= xp->base->tm)
{
- sol_path_loop(fp, xp->pi, xp->f0);
+ sol_path_loop(vary, xp->base->pi, xp->base->f);
- xp->f = xp->f0;
+ xp->f = xp->base->f;
cmd.type = CMD_SWCH_TOGGLE;
cmd.swchtoggle.xi = xi;
/*
* Compute the positions of all bodies after DT seconds have passed.
*/
-void sol_body_step(struct s_file *fp, float dt, int ms)
+void sol_body_step(struct s_vary *vary, float dt, int ms)
{
int i;
union cmd cmd;
- for (i = 0; i < fp->bc; i++)
+ for (i = 0; i < vary->bc; i++)
{
- struct s_body *bp = fp->bv + i;
- struct s_path *pp = fp->pv + bp->pi;
+ struct v_body *bp = vary->bv + i;
+ struct v_path *pp = vary->pv + bp->pi;
if (bp->pi >= 0 && pp->f)
{
bp->t += dt;
bp->tm += ms;
- if (bp->tm >= pp->tm)
+ if (bp->tm >= pp->base->tm)
{
bp->t = 0;
bp->tm = 0;
- bp->pi = pp->pi;
+ bp->pi = pp->base->pi;
cmd.type = CMD_BODY_TIME;
cmd.bodytime.bi = i;
/*
* Compute the positions of all balls after DT seconds have passed.
*/
-void sol_ball_step(struct s_file *fp, float dt)
+void sol_ball_step(struct s_vary *vary, float dt)
{
int i;
- for (i = 0; i < fp->uc; i++)
+ for (i = 0; i < vary->uc; i++)
{
- struct s_ball *up = fp->uv + i;
+ struct v_ball *up = vary->uv + i;
v_mad(up->p, up->p, up->v, dt);
/*---------------------------------------------------------------------------*/
-int sol_item_test(struct s_file *fp, float *p, float item_r)
+int sol_item_test(struct s_vary *vary, float *p, float item_r)
{
- const float *ball_p = fp->uv->p;
- const float ball_r = fp->uv->r;
+ const float *ball_p = vary->uv->p;
+ const float ball_r = vary->uv->r;
int hi;
- for (hi = 0; hi < fp->hc; hi++)
+ for (hi = 0; hi < vary->hc; hi++)
{
- struct s_item *hp = fp->hv + hi;
+ struct v_item *hp = vary->hv + hi;
float r[3];
v_sub(r, ball_p, hp->p);
return -1;
}
-struct s_goal *sol_goal_test(struct s_file *fp, float *p, int ui)
+struct b_goal *sol_goal_test(struct s_vary *vary, float *p, int ui)
{
- const float *ball_p = fp->uv[ui].p;
- const float ball_r = fp->uv[ui].r;
+ const float *ball_p = vary->uv[ui].p;
+ const float ball_r = vary->uv[ui].r;
int zi;
- for (zi = 0; zi < fp->zc; zi++)
+ for (zi = 0; zi < vary->base->zc; zi++)
{
- struct s_goal *zp = fp->zv + zi;
+ struct b_goal *zp = vary->base->zv + zi;
float r[3];
r[0] = ball_p[0] - zp->p[0];
/*
* Test for a ball entering a teleporter.
*/
-int sol_jump_test(struct s_file *fp, float *p, int ui)
+int sol_jump_test(struct s_vary *vary, float *p, int ui)
{
- const float *ball_p = fp->uv[ui].p;
- const float ball_r = fp->uv[ui].r;
+ const float *ball_p = vary->uv[ui].p;
+ const float ball_r = vary->uv[ui].r;
int ji, in = 0;
- for (ji = 0; ji < fp->jc; ji++)
+ for (ji = 0; ji < vary->base->jc; ji++)
{
- struct s_jump *jp = fp->jv + ji;
+ struct b_jump *jp = vary->base->jv + ji;
float d, r[3];
r[0] = ball_p[0] - jp->p[0];
/*
* Test for a ball entering a switch.
*/
-int sol_swch_test(struct s_file *fp, int ui)
+int sol_swch_test(struct s_vary *vary, int ui)
{
- const float *ball_p = fp->uv[ui].p;
- const float ball_r = fp->uv[ui].r;
+ const float *ball_p = vary->uv[ui].p;
+ const float ball_r = vary->uv[ui].r;
union cmd cmd;
int xi, rc = SWCH_OUTSIDE;
- for (xi = 0; xi < fp->xc; xi++)
+ for (xi = 0; xi < vary->xc; xi++)
{
- struct s_swch *xp = fp->xv + xi;
+ struct v_swch *xp = vary->xv + xi;
/* FIXME enter/exit events don't work for timed switches */
- if (xp->t0m == 0 || xp->f == xp->f0)
+ if (xp->base->t == 0 || xp->f == xp->base->f)
{
float d, r[3];
- r[0] = ball_p[0] - xp->p[0];
- r[1] = ball_p[2] - xp->p[2];
+ r[0] = ball_p[0] - xp->base->p[0];
+ r[1] = ball_p[2] - xp->base->p[2];
r[2] = 0;
/* Distance of the far side from the edge of the halo. */
- d = v_len(r) + ball_r - xp->r;
+ d = v_len(r) + ball_r - xp->base->r;
/*
* The "inside" distance, which must be cleared before
*/
if (d <= ball_r * 2 &&
- ball_p[1] > xp->p[1] &&
- ball_p[1] < xp->p[1] + SWCH_HEIGHT / 2)
+ ball_p[1] > xp->base->p[1] &&
+ ball_p[1] < xp->base->p[1] + SWCH_HEIGHT / 2)
{
if (!xp->e && d <= 0.0f)
{
/* The ball enters. */
- if (xp->t0m == 0)
+ if (xp->base->tm == 0)
{
xp->e = 1;
cmd.swchtoggle.xi = xi;
sol_cmd_enq(&cmd);
- sol_path_loop(fp, xp->pi, xp->f);
+ sol_path_loop(vary, xp->base->pi, xp->f);
/* It toggled to non-default state, start the timer. */
- if (xp->f != xp->f0)
+ if (xp->f != xp->base->f)
{
xp->t = 0.0f;
xp->tm = 0;
/* If visible, set the result. */
- if (!xp->i)
+ if (!xp->base->i)
rc = SWCH_TRIGGER;
}
}
#ifndef SOLID_ALL_H
#define SOLID_ALL_H
-#include "solid.h"
+#include "solid_vary.h"
-void sol_body_p(float p[3], const struct s_file *fp, int pi, float t);
-void sol_body_v(float v[3], const struct s_file *fp, int pi, float t, float dt);
-void sol_body_e(float e[3],
- const struct s_file *fp,
- const struct s_body *bp, float dt);
-void sol_body_w(float w[3], const struct s_file *fp, const struct s_body *bp);
+void sol_body_p(float p[3], const struct s_vary *, int pi, float t);
+void sol_body_v(float v[3], const struct s_vary *, int pi, float t, float dt);
+void sol_body_e(float e[3], const struct s_vary *, const struct v_body *bp,
+ float dt);
+void sol_body_w(float w[3], const struct s_vary *, const struct v_body *bp);
void sol_rotate(float e[3][3], const float w[3], float dt);
-void sol_pendulum(struct s_ball *up,
+void sol_pendulum(struct v_ball *up,
const float a[3],
const float g[3], float dt);
-void sol_swch_step(struct s_file *fp, float dt, int ms);
-void sol_body_step(struct s_file *fp, float dt, int ms);
-void sol_ball_step(struct s_file *fp, float dt);
+void sol_swch_step(struct s_vary *, float dt, int ms);
+void sol_body_step(struct s_vary *, float dt, int ms);
+void sol_ball_step(struct s_vary *, float dt);
enum
{
SWCH_INSIDE
};
-int sol_item_test(struct s_file *fp, float *p, float item_r);
-struct s_goal *sol_goal_test(struct s_file *fp, float *p, int ui);
-int sol_jump_test(struct s_file *fp, float *p, int ui);
-int sol_swch_test(struct s_file *fp, int ui);
+int sol_item_test(struct s_vary *, float *p, float item_r);
+struct b_goal *sol_goal_test(struct s_vary *, float *p, int ui);
+int sol_jump_test(struct s_vary *, float *p, int ui);
+int sol_swch_test(struct s_vary *, int ui);
#endif
--- /dev/null
+/*
+ * Copyright (C) 2003 Robert Kooima
+ *
+ * NEVERBALL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "solid_base.h"
+#include "base_config.h"
+#include "binary.h"
+#include "common.h"
+#include "fs.h"
+#include "vec3.h"
+
+enum
+{
+ SOL_VER_MINIMUM = 6,
+ SOL_VER_PATH_FLAGS,
+ SOL_VER_CURRENT = SOL_VER_PATH_FLAGS
+};
+
+#define SOL_MAGIC (0xAF | 'S' << 8 | 'O' << 16 | 'L' << 24)
+
+/*---------------------------------------------------------------------------*/
+
+static int sol_version;
+
+static int sol_file(fs_file fin)
+{
+ int magic;
+ int version;
+
+ get_index(fin, &magic);
+ get_index(fin, &version);
+
+ if (magic != SOL_MAGIC || (version < SOL_VER_MINIMUM ||
+ version > SOL_VER_CURRENT))
+ return 0;
+
+ sol_version = version;
+
+ return 1;
+}
+
+static void sol_load_mtrl(fs_file fin, struct b_mtrl *mp)
+{
+ get_array(fin, mp->d, 4);
+ get_array(fin, mp->a, 4);
+ get_array(fin, mp->s, 4);
+ get_array(fin, mp->e, 4);
+ get_array(fin, mp->h, 1);
+ get_index(fin, &mp->fl);
+
+ fs_read(mp->f, 1, PATHMAX, fin);
+}
+
+static void sol_load_vert(fs_file fin, struct b_vert *vp)
+{
+ get_array(fin, vp->p, 3);
+}
+
+static void sol_load_edge(fs_file fin, struct b_edge *ep)
+{
+ get_index(fin, &ep->vi);
+ get_index(fin, &ep->vj);
+}
+
+static void sol_load_side(fs_file fin, struct b_side *sp)
+{
+ get_array(fin, sp->n, 3);
+ get_float(fin, &sp->d);
+}
+
+static void sol_load_texc(fs_file fin, struct b_texc *tp)
+{
+ get_array(fin, tp->u, 2);
+}
+
+static void sol_load_geom(fs_file fin, struct b_geom *gp)
+{
+ get_index(fin, &gp->mi);
+ get_index(fin, &gp->ti);
+ get_index(fin, &gp->si);
+ get_index(fin, &gp->vi);
+ get_index(fin, &gp->tj);
+ get_index(fin, &gp->sj);
+ get_index(fin, &gp->vj);
+ get_index(fin, &gp->tk);
+ get_index(fin, &gp->sk);
+ get_index(fin, &gp->vk);
+}
+
+static void sol_load_lump(fs_file fin, struct b_lump *lp)
+{
+ get_index(fin, &lp->fl);
+ get_index(fin, &lp->v0);
+ get_index(fin, &lp->vc);
+ get_index(fin, &lp->e0);
+ get_index(fin, &lp->ec);
+ get_index(fin, &lp->g0);
+ get_index(fin, &lp->gc);
+ get_index(fin, &lp->s0);
+ get_index(fin, &lp->sc);
+}
+
+static void sol_load_node(fs_file fin, struct b_node *np)
+{
+ get_index(fin, &np->si);
+ get_index(fin, &np->ni);
+ get_index(fin, &np->nj);
+ get_index(fin, &np->l0);
+ get_index(fin, &np->lc);
+}
+
+static void sol_load_path(fs_file fin, struct b_path *pp)
+{
+ get_array(fin, pp->p, 3);
+ get_float(fin, &pp->t);
+ get_index(fin, &pp->pi);
+ get_index(fin, &pp->f);
+ get_index(fin, &pp->s);
+
+ pp->tm = TIME_TO_MS(pp->t);
+ pp->t = MS_TO_TIME(pp->tm);
+
+ if (sol_version >= SOL_VER_PATH_FLAGS)
+ get_index(fin, &pp->fl);
+
+ pp->e[0] = 1.0f;
+ pp->e[1] = 0.0f;
+ pp->e[2] = 0.0f;
+ pp->e[3] = 0.0f;
+
+ if (pp->fl & P_ORIENTED)
+ get_array(fin, pp->e, 4);
+}
+
+static void sol_load_body(fs_file fin, struct b_body *bp)
+{
+ get_index(fin, &bp->pi);
+ get_index(fin, &bp->ni);
+ get_index(fin, &bp->l0);
+ get_index(fin, &bp->lc);
+ get_index(fin, &bp->g0);
+ get_index(fin, &bp->gc);
+}
+
+static void sol_load_item(fs_file fin, struct b_item *hp)
+{
+ get_array(fin, hp->p, 3);
+ get_index(fin, &hp->t);
+ get_index(fin, &hp->n);
+}
+
+static void sol_load_goal(fs_file fin, struct b_goal *zp)
+{
+ get_array(fin, zp->p, 3);
+ get_float(fin, &zp->r);
+}
+
+static void sol_load_swch(fs_file fin, struct b_swch *xp)
+{
+ float f;
+ int i;
+
+ get_array(fin, xp->p, 3);
+ get_float(fin, &xp->r);
+ get_index(fin, &xp->pi);
+ get_float(fin, &xp->t);
+ get_float(fin, &f);
+ get_index(fin, &xp->f);
+ get_index(fin, &i);
+ get_index(fin, &xp->i);
+
+ xp->tm = TIME_TO_MS(xp->t);
+ xp->t = MS_TO_TIME(xp->tm);
+}
+
+static void sol_load_bill(fs_file fin, struct b_bill *rp)
+{
+ get_index(fin, &rp->fl);
+ get_index(fin, &rp->mi);
+ get_float(fin, &rp->t);
+ get_float(fin, &rp->d);
+ get_array(fin, rp->w, 3);
+ get_array(fin, rp->h, 3);
+ get_array(fin, rp->rx, 3);
+ get_array(fin, rp->ry, 3);
+ get_array(fin, rp->rz, 3);
+ get_array(fin, rp->p, 3);
+}
+
+static void sol_load_jump(fs_file fin, struct b_jump *jp)
+{
+ get_array(fin, jp->p, 3);
+ get_array(fin, jp->q, 3);
+ get_float(fin, &jp->r);
+}
+
+static void sol_load_ball(fs_file fin, struct b_ball *bp)
+{
+ get_array(fin, bp->p, 3);
+ get_float(fin, &bp->r);
+}
+
+static void sol_load_view(fs_file fin, struct b_view *wp)
+{
+ get_array(fin, wp->p, 3);
+ get_array(fin, wp->q, 3);
+}
+
+static void sol_load_dict(fs_file fin, struct b_dict *dp)
+{
+ get_index(fin, &dp->ai);
+ get_index(fin, &dp->aj);
+}
+
+static void sol_load_indx(fs_file fin, struct s_base *fp)
+{
+ get_index(fin, &fp->ac);
+ get_index(fin, &fp->dc);
+ get_index(fin, &fp->mc);
+ get_index(fin, &fp->vc);
+ get_index(fin, &fp->ec);
+ get_index(fin, &fp->sc);
+ get_index(fin, &fp->tc);
+ get_index(fin, &fp->gc);
+ get_index(fin, &fp->lc);
+ get_index(fin, &fp->nc);
+ get_index(fin, &fp->pc);
+ get_index(fin, &fp->bc);
+ get_index(fin, &fp->hc);
+ get_index(fin, &fp->zc);
+ get_index(fin, &fp->jc);
+ get_index(fin, &fp->xc);
+ get_index(fin, &fp->rc);
+ get_index(fin, &fp->uc);
+ get_index(fin, &fp->wc);
+ get_index(fin, &fp->ic);
+}
+
+static int sol_load_file(fs_file fin, struct s_base *fp)
+{
+ int i;
+
+ if (!sol_file(fin))
+ return 0;
+
+ sol_load_indx(fin, fp);
+
+ if (fp->ac)
+ fp->av = (char *) calloc(fp->ac, sizeof (*fp->av));
+ if (fp->mc)
+ fp->mv = (struct b_mtrl *) calloc(fp->mc, sizeof (*fp->mv));
+ if (fp->vc)
+ fp->vv = (struct b_vert *) calloc(fp->vc, sizeof (*fp->vv));
+ if (fp->ec)
+ fp->ev = (struct b_edge *) calloc(fp->ec, sizeof (*fp->ev));
+ if (fp->sc)
+ fp->sv = (struct b_side *) calloc(fp->sc, sizeof (*fp->sv));
+ if (fp->tc)
+ fp->tv = (struct b_texc *) calloc(fp->tc, sizeof (*fp->tv));
+ if (fp->gc)
+ fp->gv = (struct b_geom *) calloc(fp->gc, sizeof (*fp->gv));
+ if (fp->lc)
+ fp->lv = (struct b_lump *) calloc(fp->lc, sizeof (*fp->lv));
+ if (fp->nc)
+ fp->nv = (struct b_node *) calloc(fp->nc, sizeof (*fp->nv));
+ if (fp->pc)
+ fp->pv = (struct b_path *) calloc(fp->pc, sizeof (*fp->pv));
+ if (fp->bc)
+ fp->bv = (struct b_body *) calloc(fp->bc, sizeof (*fp->bv));
+ if (fp->hc)
+ fp->hv = (struct b_item *) calloc(fp->hc, sizeof (*fp->hv));
+ if (fp->zc)
+ fp->zv = (struct b_goal *) calloc(fp->zc, sizeof (*fp->zv));
+ if (fp->jc)
+ fp->jv = (struct b_jump *) calloc(fp->jc, sizeof (*fp->jv));
+ if (fp->xc)
+ fp->xv = (struct b_swch *) calloc(fp->xc, sizeof (*fp->xv));
+ if (fp->rc)
+ fp->rv = (struct b_bill *) calloc(fp->rc, sizeof (*fp->rv));
+ if (fp->uc)
+ fp->uv = (struct b_ball *) calloc(fp->uc, sizeof (*fp->uv));
+ if (fp->wc)
+ fp->wv = (struct b_view *) calloc(fp->wc, sizeof (*fp->wv));
+ if (fp->dc)
+ fp->dv = (struct b_dict *) calloc(fp->dc, sizeof (*fp->dv));
+ if (fp->ic)
+ fp->iv = (int *) calloc(fp->ic, sizeof (*fp->iv));
+
+ if (fp->ac)
+ fs_read(fp->av, 1, fp->ac, fin);
+
+ for (i = 0; i < fp->dc; i++) sol_load_dict(fin, fp->dv + i);
+ for (i = 0; i < fp->mc; i++) sol_load_mtrl(fin, fp->mv + i);
+ for (i = 0; i < fp->vc; i++) sol_load_vert(fin, fp->vv + i);
+ for (i = 0; i < fp->ec; i++) sol_load_edge(fin, fp->ev + i);
+ for (i = 0; i < fp->sc; i++) sol_load_side(fin, fp->sv + i);
+ for (i = 0; i < fp->tc; i++) sol_load_texc(fin, fp->tv + i);
+ for (i = 0; i < fp->gc; i++) sol_load_geom(fin, fp->gv + i);
+ for (i = 0; i < fp->lc; i++) sol_load_lump(fin, fp->lv + i);
+ for (i = 0; i < fp->nc; i++) sol_load_node(fin, fp->nv + i);
+ for (i = 0; i < fp->pc; i++) sol_load_path(fin, fp->pv + i);
+ for (i = 0; i < fp->bc; i++) sol_load_body(fin, fp->bv + i);
+ for (i = 0; i < fp->hc; i++) sol_load_item(fin, fp->hv + i);
+ for (i = 0; i < fp->zc; i++) sol_load_goal(fin, fp->zv + i);
+ for (i = 0; i < fp->jc; i++) sol_load_jump(fin, fp->jv + i);
+ for (i = 0; i < fp->xc; i++) sol_load_swch(fin, fp->xv + i);
+ for (i = 0; i < fp->rc; i++) sol_load_bill(fin, fp->rv + i);
+ for (i = 0; i < fp->uc; i++) sol_load_ball(fin, fp->uv + i);
+ for (i = 0; i < fp->wc; i++) sol_load_view(fin, fp->wv + i);
+ for (i = 0; i < fp->ic; i++) get_index(fin, fp->iv + i);
+
+ return 1;
+}
+
+static int sol_load_head(fs_file fin, struct s_base *fp)
+{
+ if (!sol_file(fin))
+ return 0;
+
+ sol_load_indx(fin, fp);
+
+ if (fp->ac)
+ {
+ fp->av = (char *) calloc(fp->ac, sizeof (*fp->av));
+ fs_read(fp->av, 1, fp->ac, fin);
+ }
+
+ if (fp->dc)
+ {
+ int i;
+
+ fp->dv = (struct b_dict *) calloc(fp->dc, sizeof (*fp->dv));
+
+ for (i = 0; i < fp->dc; i++)
+ sol_load_dict(fin, fp->dv + i);
+ }
+
+ return 1;
+}
+
+int sol_load_base(struct s_base *fp, const char *filename)
+{
+ fs_file fin;
+ int res = 0;
+
+ memset(fp, 0, sizeof (*fp));
+
+ if ((fin = fs_open(filename, "r")))
+ {
+ res = sol_load_file(fin, fp);
+ fs_close(fin);
+ }
+ return res;
+}
+
+int sol_load_meta(struct s_base *fp, const char *filename)
+{
+ fs_file fin;
+ int res = 0;
+
+ if ((fin = fs_open(filename, "r")))
+ {
+ res = sol_load_head(fin, fp);
+ fs_close(fin);
+ }
+ return res;
+}
+
+void sol_free_base(struct s_base *fp)
+{
+ if (fp->av) free(fp->av);
+ if (fp->mv) free(fp->mv);
+ if (fp->vv) free(fp->vv);
+ if (fp->ev) free(fp->ev);
+ if (fp->sv) free(fp->sv);
+ if (fp->tv) free(fp->tv);
+ if (fp->gv) free(fp->gv);
+ if (fp->lv) free(fp->lv);
+ if (fp->nv) free(fp->nv);
+ if (fp->pv) free(fp->pv);
+ if (fp->bv) free(fp->bv);
+ if (fp->hv) free(fp->hv);
+ if (fp->zv) free(fp->zv);
+ if (fp->jv) free(fp->jv);
+ if (fp->xv) free(fp->xv);
+ if (fp->rv) free(fp->rv);
+ if (fp->uv) free(fp->uv);
+ if (fp->wv) free(fp->wv);
+ if (fp->dv) free(fp->dv);
+ if (fp->iv) free(fp->iv);
+
+ memset(fp, 0, sizeof (*fp));
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void sol_stor_mtrl(fs_file fout, struct b_mtrl *mp)
+{
+ put_array(fout, mp->d, 4);
+ put_array(fout, mp->a, 4);
+ put_array(fout, mp->s, 4);
+ put_array(fout, mp->e, 4);
+ put_array(fout, mp->h, 1);
+ put_index(fout, mp->fl);
+
+ fs_write(mp->f, 1, PATHMAX, fout);
+}
+
+static void sol_stor_vert(fs_file fout, struct b_vert *vp)
+{
+ put_array(fout, vp->p, 3);
+}
+
+static void sol_stor_edge(fs_file fout, struct b_edge *ep)
+{
+ put_index(fout, ep->vi);
+ put_index(fout, ep->vj);
+}
+
+static void sol_stor_side(fs_file fout, struct b_side *sp)
+{
+ put_array(fout, sp->n, 3);
+ put_float(fout, sp->d);
+}
+
+static void sol_stor_texc(fs_file fout, struct b_texc *tp)
+{
+ put_array(fout, tp->u, 2);
+}
+
+static void sol_stor_geom(fs_file fout, struct b_geom *gp)
+{
+ put_index(fout, gp->mi);
+ put_index(fout, gp->ti);
+ put_index(fout, gp->si);
+ put_index(fout, gp->vi);
+ put_index(fout, gp->tj);
+ put_index(fout, gp->sj);
+ put_index(fout, gp->vj);
+ put_index(fout, gp->tk);
+ put_index(fout, gp->sk);
+ put_index(fout, gp->vk);
+}
+
+static void sol_stor_lump(fs_file fout, struct b_lump *lp)
+{
+ put_index(fout, lp->fl);
+ put_index(fout, lp->v0);
+ put_index(fout, lp->vc);
+ put_index(fout, lp->e0);
+ put_index(fout, lp->ec);
+ put_index(fout, lp->g0);
+ put_index(fout, lp->gc);
+ put_index(fout, lp->s0);
+ put_index(fout, lp->sc);
+}
+
+static void sol_stor_node(fs_file fout, struct b_node *np)
+{
+ put_index(fout, np->si);
+ put_index(fout, np->ni);
+ put_index(fout, np->nj);
+ put_index(fout, np->l0);
+ put_index(fout, np->lc);
+}
+
+static void sol_stor_path(fs_file fout, struct b_path *pp)
+{
+ put_array(fout, pp->p, 3);
+ put_float(fout, pp->t);
+ put_index(fout, pp->pi);
+ put_index(fout, pp->f);
+ put_index(fout, pp->s);
+ put_index(fout, pp->fl);
+
+ if (pp->fl & P_ORIENTED)
+ put_array(fout, pp->e, 4);
+}
+
+static void sol_stor_body(fs_file fout, struct b_body *bp)
+{
+ put_index(fout, bp->pi);
+ put_index(fout, bp->ni);
+ put_index(fout, bp->l0);
+ put_index(fout, bp->lc);
+ put_index(fout, bp->g0);
+ put_index(fout, bp->gc);
+}
+
+static void sol_stor_item(fs_file fout, struct b_item *hp)
+{
+ put_array(fout, hp->p, 3);
+ put_index(fout, hp->t);
+ put_index(fout, hp->n);
+}
+
+static void sol_stor_goal(fs_file fout, struct b_goal *zp)
+{
+ put_array(fout, zp->p, 3);
+ put_float(fout, zp->r);
+}
+
+static void sol_stor_swch(fs_file fout, struct b_swch *xp)
+{
+ put_array(fout, xp->p, 3);
+ put_float(fout, xp->r);
+ put_index(fout, xp->pi);
+ put_float(fout, xp->t);
+ put_float(fout, xp->t);
+ put_index(fout, xp->f);
+ put_index(fout, xp->f);
+ put_index(fout, xp->i);
+}
+
+static void sol_stor_bill(fs_file fout, struct b_bill *rp)
+{
+ put_index(fout, rp->fl);
+ put_index(fout, rp->mi);
+ put_float(fout, rp->t);
+ put_float(fout, rp->d);
+ put_array(fout, rp->w, 3);
+ put_array(fout, rp->h, 3);
+ put_array(fout, rp->rx, 3);
+ put_array(fout, rp->ry, 3);
+ put_array(fout, rp->rz, 3);
+ put_array(fout, rp->p, 3);
+}
+
+static void sol_stor_jump(fs_file fout, struct b_jump *jp)
+{
+ put_array(fout, jp->p, 3);
+ put_array(fout, jp->q, 3);
+ put_float(fout, jp->r);
+}
+
+static void sol_stor_ball(fs_file fout, struct b_ball *bp)
+{
+ put_array(fout, bp->p, 3);
+ put_float(fout, bp->r);
+}
+
+static void sol_stor_view(fs_file fout, struct b_view *wp)
+{
+ put_array(fout, wp->p, 3);
+ put_array(fout, wp->q, 3);
+}
+
+static void sol_stor_dict(fs_file fout, struct b_dict *dp)
+{
+ put_index(fout, dp->ai);
+ put_index(fout, dp->aj);
+}
+
+static void sol_stor_file(fs_file fout, struct s_base *fp)
+{
+ int i;
+ int magic = SOL_MAGIC;
+ int version = SOL_VER_CURRENT;
+
+ put_index(fout, magic);
+ put_index(fout, version);
+
+ put_index(fout, fp->ac);
+ put_index(fout, fp->dc);
+ put_index(fout, fp->mc);
+ put_index(fout, fp->vc);
+ put_index(fout, fp->ec);
+ put_index(fout, fp->sc);
+ put_index(fout, fp->tc);
+ put_index(fout, fp->gc);
+ put_index(fout, fp->lc);
+ put_index(fout, fp->nc);
+ put_index(fout, fp->pc);
+ put_index(fout, fp->bc);
+ put_index(fout, fp->hc);
+ put_index(fout, fp->zc);
+ put_index(fout, fp->jc);
+ put_index(fout, fp->xc);
+ put_index(fout, fp->rc);
+ put_index(fout, fp->uc);
+ put_index(fout, fp->wc);
+ put_index(fout, fp->ic);
+
+ fs_write(fp->av, 1, fp->ac, fout);
+
+ for (i = 0; i < fp->dc; i++) sol_stor_dict(fout, fp->dv + i);
+ for (i = 0; i < fp->mc; i++) sol_stor_mtrl(fout, fp->mv + i);
+ for (i = 0; i < fp->vc; i++) sol_stor_vert(fout, fp->vv + i);
+ for (i = 0; i < fp->ec; i++) sol_stor_edge(fout, fp->ev + i);
+ for (i = 0; i < fp->sc; i++) sol_stor_side(fout, fp->sv + i);
+ for (i = 0; i < fp->tc; i++) sol_stor_texc(fout, fp->tv + i);
+ for (i = 0; i < fp->gc; i++) sol_stor_geom(fout, fp->gv + i);
+ for (i = 0; i < fp->lc; i++) sol_stor_lump(fout, fp->lv + i);
+ for (i = 0; i < fp->nc; i++) sol_stor_node(fout, fp->nv + i);
+ for (i = 0; i < fp->pc; i++) sol_stor_path(fout, fp->pv + i);
+ for (i = 0; i < fp->bc; i++) sol_stor_body(fout, fp->bv + i);
+ for (i = 0; i < fp->hc; i++) sol_stor_item(fout, fp->hv + i);
+ for (i = 0; i < fp->zc; i++) sol_stor_goal(fout, fp->zv + i);
+ for (i = 0; i < fp->jc; i++) sol_stor_jump(fout, fp->jv + i);
+ for (i = 0; i < fp->xc; i++) sol_stor_swch(fout, fp->xv + i);
+ for (i = 0; i < fp->rc; i++) sol_stor_bill(fout, fp->rv + i);
+ for (i = 0; i < fp->uc; i++) sol_stor_ball(fout, fp->uv + i);
+ for (i = 0; i < fp->wc; i++) sol_stor_view(fout, fp->wv + i);
+ for (i = 0; i < fp->ic; i++) put_index(fout, fp->iv[i]);
+}
+
+int sol_stor_base(struct s_base *fp, const char *filename)
+{
+ fs_file fout;
+
+ if ((fout = fs_open(filename, "w")))
+ {
+ sol_stor_file(fout, fp);
+ fs_close(fout);
+
+ return 1;
+ }
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*/
--- /dev/null
+/*
+ * Copyright (C) 2003 Robert Kooima
+ *
+ * NEVERBALL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef SOLID_BASE_H
+#define SOLID_BASE_H
+
+#include "base_config.h"
+
+/*
+ * Some might be taken aback at the terseness of the names of the
+ * structure members and the variables used by the functions that
+ * access them. Yes, yes, I know: readability. I contend that once
+ * the naming convention is embraced, the names become more readable
+ * than any verbose alternative, and their brevity and uniformity do
+ * more to augment readability than longVariableNames ever could.
+ *
+ * Members and variables are named XY. X determines the type of
+ * structure to which the variable refers. Y determines the usage of
+ * the variable.
+ *
+ * The Xs are as documented by struct s_file:
+ *
+ * f File (struct s_file)
+ * m Material (struct s_mtrl)
+ * v Vertex (struct s_vert)
+ * e Edge (struct s_edge)
+ * s Side (struct s_side)
+ * t Texture coord (struct s_texc)
+ * g Geometry (struct s_geom)
+ * l Lump (struct s_lump)
+ * n Node (struct s_node)
+ * p Path (struct s_path)
+ * b Body (struct s_body)
+ * h Item (struct s_item)
+ * z Goal (struct s_goal)
+ * j Jump (struct s_jump)
+ * x Switch (struct s_swch)
+ * r Billboard (struct s_bill)
+ * u User (struct s_ball)
+ * w Viewpoint (struct s_view)
+ * d Dictionary (struct s_dict)
+ * i Index (int)
+ * a Text (char)
+ *
+ * The Ys are as follows:
+ *
+ * c Counter
+ * p Pointer
+ * v Vector (array)
+ * 0 Index of the first
+ * i Index
+ * j Subindex
+ * k Subsubindex
+ *
+ * Thus "up" is a pointer to a user structure. "lc" is the number of
+ * lumps. "ei" and "ej" are edge indices into some "ev" edge vector.
+ * An edge is defined by two vertices, so an edge structure consists
+ * of "vi" and "vj". And so on.
+ *
+ * Those members that do not conform to this convention are explicitly
+ * documented with a comment.
+ *
+ * These prefixes are still available: c k o q y.
+ */
+
+/*
+ * Additionally, solid data is split into three main parts: static
+ * data (base), simulation data (vary), and rendering data (draw).
+ */
+
+/*---------------------------------------------------------------------------*/
+
+/* Material type flags */
+
+#define M_OPAQUE 1
+#define M_TRANSPARENT 2
+#define M_REFLECTIVE 4
+#define M_ENVIRONMENT 8
+#define M_ADDITIVE 16
+#define M_CLAMPED 32
+#define M_DECAL 64
+#define M_TWO_SIDED 128
+#define M_SHADOWED 256
+
+/* Billboard types. */
+
+#define B_EDGE 1
+#define B_FLAT 2
+#define B_ADDITIVE 4
+#define B_NOFACE 8
+
+/* Lump flags. */
+
+#define L_DETAIL 1
+
+/* Item types. */
+
+#define ITEM_NONE 0
+#define ITEM_COIN 1
+#define ITEM_GROW 2
+#define ITEM_SHRINK 3
+
+/* Path flags. */
+
+#define P_ORIENTED 1
+
+/*---------------------------------------------------------------------------*/
+
+struct b_mtrl
+{
+ float d[4]; /* diffuse color */
+ float a[4]; /* ambient color */
+ float s[4]; /* specular color */
+ float e[4]; /* emission color */
+ float h[1]; /* specular exponent */
+ float angle;
+
+ int fl; /* material flags */
+
+ char f[PATHMAX]; /* texture file name */
+};
+
+struct b_vert
+{
+ float p[3]; /* vertex position */
+};
+
+struct b_edge
+{
+ int vi;
+ int vj;
+};
+
+struct b_side
+{
+ float n[3]; /* plane normal vector */
+ float d; /* distance from origin */
+};
+
+struct b_texc
+{
+ float u[2]; /* texture coordinate */
+};
+
+struct b_geom
+{
+ int mi;
+ int ti, si, vi;
+ int tj, sj, vj;
+ int tk, sk, vk;
+};
+
+struct b_lump
+{
+ int fl; /* lump flags */
+ int v0, vc;
+ int e0, ec;
+ int g0, gc;
+ int s0, sc;
+};
+
+struct b_node
+{
+ int si;
+ int ni;
+ int nj;
+ int l0;
+ int lc;
+};
+
+struct b_path
+{
+ float p[3]; /* starting position */
+ float e[4]; /* orientation (quaternion) */
+ float t; /* travel time */
+ int tm; /* milliseconds */
+
+ int pi;
+ int f; /* enable flag */
+ int s; /* smooth flag */
+
+ int fl; /* flags */
+
+ /* TODO: merge enable and smooth into flags. */
+};
+
+struct b_body
+{
+ int pi;
+ int ni;
+ int l0;
+ int lc;
+ int g0;
+ int gc;
+};
+
+struct b_item
+{
+ float p[3]; /* position */
+ int t; /* type */
+ int n; /* value */
+};
+
+struct b_goal
+{
+ float p[3]; /* position */
+ float r; /* radius */
+};
+
+struct b_swch
+{
+ float p[3]; /* position */
+ float r; /* radius */
+ int pi; /* the linked path */
+
+ float t; /* default timer */
+ int tm; /* milliseconds */
+ int f; /* default state */
+ int i; /* is invisible? */
+};
+
+struct b_bill
+{
+ int fl;
+ int mi;
+ float t; /* repeat time interval */
+ float d; /* distance */
+
+ float w[3]; /* width coefficients */
+ float h[3]; /* height coefficients */
+
+ float rx[3]; /* X rotation coefficients */
+ float ry[3]; /* Y rotation coefficients */
+ float rz[3]; /* Z rotation coefficients */
+
+ float p[3];
+};
+
+struct b_jump
+{
+ float p[3]; /* position */
+ float q[3]; /* target position */
+ float r; /* radius */
+};
+
+struct b_ball
+{
+ float p[3]; /* position vector */
+ float r; /* radius */
+};
+
+struct b_view
+{
+ float p[3];
+ float q[3];
+};
+
+struct b_dict
+{
+ int ai;
+ int aj;
+};
+
+struct s_base
+{
+ int ac;
+ int mc;
+ int vc;
+ int ec;
+ int sc;
+ int tc;
+ int gc;
+ int lc;
+ int nc;
+ int pc;
+ int bc;
+ int hc;
+ int zc;
+ int jc;
+ int xc;
+ int rc;
+ int uc;
+ int wc;
+ int dc;
+ int ic;
+
+ char *av;
+ struct b_mtrl *mv;
+ struct b_vert *vv;
+ struct b_edge *ev;
+ struct b_side *sv;
+ struct b_texc *tv;
+ struct b_geom *gv;
+ struct b_lump *lv;
+ struct b_node *nv;
+ struct b_path *pv;
+ struct b_body *bv;
+ struct b_item *hv;
+ struct b_goal *zv;
+ struct b_jump *jv;
+ struct b_swch *xv;
+ struct b_bill *rv;
+ struct b_ball *uv;
+ struct b_view *wv;
+ struct b_dict *dv;
+ int *iv;
+};
+
+/*---------------------------------------------------------------------------*/
+
+int sol_load_base(struct s_base *, const char *);
+int sol_load_meta(struct s_base *, const char *);
+void sol_free_base(struct s_base *);
+int sol_stor_base(struct s_base *, const char *);
+
+/*---------------------------------------------------------------------------*/
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2003 Robert Kooima
+ *
+ * NEVERBALL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include <SDL.h>
+#include <SDL_rwops.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "glext.h"
+#include "vec3.h"
+#include "image.h"
+#include "base_image.h"
+#include "base_config.h"
+#include "lang.h"
+
+#include "solid_draw.h"
+#include "solid_all.h"
+
+/*---------------------------------------------------------------------------*/
+
+static int sol_enum_mtrl(const struct s_base *base,
+ const struct b_body *bp, int mi)
+{
+ int li, gi, c = 0;
+
+ /* Count all lump geoms with this material. */
+
+ for (li = 0; li < bp->lc; li++)
+ {
+ int g0 = base->lv[bp->l0 + li].g0;
+ int gc = base->lv[bp->l0 + li].gc;
+
+ for (gi = 0; gi < gc; gi++)
+ if (base->gv[base->iv[g0 + gi]].mi == mi)
+ c++;
+ }
+
+ /* Count all body geoms with this material. */
+
+ for (gi = 0; gi < bp->gc; gi++)
+ if (base->gv[base->iv[bp->g0 + gi]].mi == mi)
+ c++;
+
+ return c;
+}
+
+static int sol_enum_body(const struct s_base *base,
+ const struct b_body *bp, int fl)
+{
+ int mi, c = 0;
+
+ /* Count all geoms with this flag. */
+
+ for (mi = 0; mi < base->mc; mi++)
+ if (base->mv[mi].fl & fl)
+ c = c + sol_enum_mtrl(base, bp, mi);
+
+ return c;
+}
+
+/*---------------------------------------------------------------------------*/
+
+int sol_reflective(const struct s_draw *draw)
+{
+ int bi;
+
+ for (bi = 0; bi < draw->bc; bi++)
+ if (draw->bv[bi].rl)
+ return 1;
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+
+#define tobyte(f) ((GLubyte) (f * 255.0f))
+
+#define color_cmp(a, b) (tobyte((a)[0]) == tobyte((b)[0]) && \
+ tobyte((a)[1]) == tobyte((b)[1]) && \
+ tobyte((a)[2]) == tobyte((b)[2]) && \
+ tobyte((a)[3]) == tobyte((b)[3]))
+
+static struct b_mtrl default_base_mtrl =
+{
+ { 0.8f, 0.8f, 0.8f, 1.0f },
+ { 0.2f, 0.2f, 0.2f, 1.0f },
+ { 0.0f, 0.0f, 0.0f, 1.0f },
+ { 0.0f, 0.0f, 0.0f, 1.0f },
+ { 0.0f }, 0.0f, M_OPAQUE, ""
+};
+
+static struct d_mtrl default_draw_mtrl =
+{
+ &default_base_mtrl, 0
+};
+
+static const struct d_mtrl *sol_draw_mtrl(const struct s_draw *draw,
+ const struct d_mtrl *mp_draw,
+ const struct d_mtrl *mq_draw)
+{
+ const struct b_mtrl *mp_base = mp_draw->base;
+ const struct b_mtrl *mq_base = mq_draw->base;
+
+ /* Change material properties only as needed. */
+
+ if (!color_cmp(mp_base->a, mq_base->a))
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mp_base->a);
+ if (!color_cmp(mp_base->d, mq_base->d))
+ glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp_base->d);
+ if (!color_cmp(mp_base->s, mq_base->s))
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mp_base->s);
+ if (!color_cmp(mp_base->e, mq_base->e))
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mp_base->e);
+ if (tobyte(mp_base->h[0]) != tobyte(mq_base->h[0]))
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mp_base->h);
+
+ /* Bind the texture. */
+
+ if (mp_draw->o != mq_draw->o)
+ glBindTexture(GL_TEXTURE_2D, mp_draw->o);
+
+ /* Enable environment mapping. */
+
+ if ((mp_base->fl & M_ENVIRONMENT) && !(mq_base->fl & M_ENVIRONMENT))
+ {
+ glEnable(GL_TEXTURE_GEN_S);
+ glEnable(GL_TEXTURE_GEN_T);
+
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
+ }
+
+ /* Disable environment mapping. */
+
+ if ((mq_base->fl & M_ENVIRONMENT) && !(mp_base->fl & M_ENVIRONMENT))
+ {
+ glDisable(GL_TEXTURE_GEN_S);
+ glDisable(GL_TEXTURE_GEN_T);
+ }
+
+ /* Enable additive blending. */
+
+ if ((mp_base->fl & M_ADDITIVE) && !(mq_base->fl & M_ADDITIVE))
+ glBlendFunc(GL_ONE, GL_ONE);
+
+ /* Enable standard blending. */
+
+ if ((mq_base->fl & M_ADDITIVE) && !(mp_base->fl & M_ADDITIVE))
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ /* Enable visibility-from-behind. */
+
+ if ((mp_base->fl & M_TWO_SIDED) && !(mq_base->fl & M_TWO_SIDED))
+ {
+ glDisable(GL_CULL_FACE);
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
+ }
+
+ /* Disable visibility-from-behind. */
+
+ if ((mq_base->fl & M_TWO_SIDED) && !(mp_base->fl & M_TWO_SIDED))
+ {
+ glEnable(GL_CULL_FACE);
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
+ }
+
+ /* Enable decal offset. */
+
+ if ((mp_base->fl & M_DECAL) && !(mq_base->fl & M_DECAL))
+ {
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(-1.0f, -2.0f);
+ }
+
+ /* Disable decal offset. */
+
+ if ((mq_base->fl & M_DECAL) && !(mp_base->fl & M_DECAL))
+ glDisable(GL_POLYGON_OFFSET_FILL);
+
+ return mp_draw;
+}
+
+static const struct d_mtrl *sol_back_bill(const struct s_draw *draw,
+ const struct b_bill *rp,
+ const struct d_mtrl *mp,
+ float t)
+{
+ float T = (rp->t > 0.0f) ? (fmodf(t, rp->t) - rp->t / 2) : 0.0f;
+
+ float w = rp->w[0] + rp->w[1] * T + rp->w[2] * T * T;
+ float h = rp->h[0] + rp->h[1] * T + rp->h[2] * T * T;
+
+ if (w > 0 && h > 0)
+ {
+ float rx = rp->rx[0] + rp->rx[1] * T + rp->rx[2] * T * T;
+ float ry = rp->ry[0] + rp->ry[1] * T + rp->ry[2] * T * T;
+ float rz = rp->rz[0] + rp->rz[1] * T + rp->rz[2] * T * T;
+
+ glPushMatrix();
+ {
+ float y0 = (rp->fl & B_EDGE) ? 0 : -h / 2;
+ float y1 = (rp->fl & B_EDGE) ? h : +h / 2;
+
+ glRotatef(ry, 0.0f, 1.0f, 0.0f);
+ glRotatef(rx, 1.0f, 0.0f, 0.0f);
+ glTranslatef(0.0f, 0.0f, -rp->d);
+
+ if (rp->fl & B_FLAT)
+ {
+ glRotatef(-rx - 90.0f, 1.0f, 0.0f, 0.0f);
+ glRotatef(-ry, 0.0f, 0.0f, 1.0f);
+ }
+ if (rp->fl & B_EDGE)
+ glRotatef(-rx, 1.0f, 0.0f, 0.0f);
+
+ glRotatef(rz, 0.0f, 0.0f, 1.0f);
+
+ mp = sol_draw_mtrl(draw, draw->mv + rp->mi, mp);
+
+ glBegin(GL_QUADS);
+ {
+ glTexCoord2f(0.0f, 0.0f); glVertex2f(-w / 2, y0);
+ glTexCoord2f(1.0f, 0.0f); glVertex2f(+w / 2, y0);
+ glTexCoord2f(1.0f, 1.0f); glVertex2f(+w / 2, y1);
+ glTexCoord2f(0.0f, 1.0f); glVertex2f(-w / 2, y1);
+ }
+ glEnd();
+ }
+ glPopMatrix();
+ }
+
+ return mp;
+}
+
+/*---------------------------------------------------------------------------*/
+
+void sol_back(const struct s_draw *draw, float n, float f, float t)
+{
+ const struct d_mtrl *mp = &default_draw_mtrl;
+
+ int ri;
+
+ /* Render all billboards in the given range. */
+
+ glDisable(GL_LIGHTING);
+ glDepthMask(GL_FALSE);
+ {
+ for (ri = 0; ri < draw->base->rc; ri++)
+ if (n <= draw->base->rv[ri].d && draw->base->rv[ri].d < f)
+ mp = sol_back_bill(draw, draw->base->rv + ri, mp, t);
+
+ mp = sol_draw_mtrl(draw, &default_draw_mtrl, mp);
+ }
+ glDepthMask(GL_TRUE);
+ glEnable(GL_LIGHTING);
+}
+
+/*---------------------------------------------------------------------------*/
+/*
+ * The following code renders a body in a ludicrously inefficient
+ * manner. It iterates the materials and scans the data structure for
+ * geometry using each. This has the effect of absolutely minimizing
+ * material changes, texture bindings, and Begin/End pairs, but
+ * maximizing trips through the data.
+ *
+ * However, this is only done once for each level. The results are
+ * stored in display lists. Thus, it is well worth it.
+ */
+
+static void sol_draw_geom(const struct s_base *base,
+ const struct b_geom *gp, int mi)
+{
+ if (gp->mi == mi)
+ {
+ const float *ui = base->tv[gp->ti].u;
+ const float *uj = base->tv[gp->tj].u;
+ const float *uk = base->tv[gp->tk].u;
+
+ const float *ni = base->sv[gp->si].n;
+ const float *nj = base->sv[gp->sj].n;
+ const float *nk = base->sv[gp->sk].n;
+
+ const float *vi = base->vv[gp->vi].p;
+ const float *vj = base->vv[gp->vj].p;
+ const float *vk = base->vv[gp->vk].p;
+
+ glTexCoord2fv(ui);
+ glNormal3fv(ni);
+ glVertex3fv(vi);
+
+ glTexCoord2fv(uj);
+ glNormal3fv(nj);
+ glVertex3fv(vj);
+
+ glTexCoord2fv(uk);
+ glNormal3fv(nk);
+ glVertex3fv(vk);
+ }
+}
+
+static void sol_draw_lump(const struct s_base *base,
+ const struct b_lump *lp, int mi)
+{
+ int i;
+
+ for (i = 0; i < lp->gc; i++)
+ sol_draw_geom(base, base->gv + base->iv[lp->g0 + i], mi);
+}
+
+static const struct d_mtrl *sol_draw_body(const struct s_draw *draw,
+ const struct b_body *bp,
+ const struct d_mtrl *mp,
+ int fl, int decal)
+{
+ const struct s_base *base = draw->base;
+
+ int mi, li, gi;
+
+ /* Iterate all materials of the correct opacity. */
+
+ for (mi = 0; mi < draw->mc; mi++)
+ {
+ struct d_mtrl *mq = draw->mv + mi;
+
+ if ((mq->base->fl & fl) && (mq->base->fl & M_DECAL) == decal)
+ {
+ if (sol_enum_mtrl(draw->base, bp, mi))
+ {
+ /* Set the material state. */
+
+ mp = sol_draw_mtrl(draw, mq, mp);
+
+ /* Render all geometry of that material. */
+
+ glBegin(GL_TRIANGLES);
+ {
+ for (li = 0; li < bp->lc; li++)
+ sol_draw_lump(draw->base,
+ base->lv + bp->l0 + li,
+ mi);
+ for (gi = 0; gi < bp->gc; gi++)
+ sol_draw_geom(draw->base,
+ base->gv + base->iv[bp->g0 + gi],
+ mi);
+ }
+ glEnd();
+ }
+ }
+ }
+
+ return mp;
+}
+
+static void sol_draw_list(const struct s_vary *vary,
+ const struct v_body *bp, GLuint list)
+{
+ float p[3], e[4], u[3], a;
+
+ sol_body_p(p, vary, bp->pi, bp->t);
+ sol_body_e(e, vary, bp, 0);
+
+ q_as_axisangle(e, u, &a);
+ a = V_DEG(a);
+
+ glPushMatrix();
+ {
+ /* Translate and rotate a moving body. */
+
+ glTranslatef(p[0], p[1], p[2]);
+ glRotatef(a, u[0], u[1], u[2]);
+
+ /* Draw the body. */
+
+ glCallList(list);
+ }
+ glPopMatrix();
+}
+
+void sol_draw(const struct s_draw *draw, int depthmask, int depthtest)
+{
+ int bi;
+
+ /* Render all opaque geometry into the color and depth buffers. */
+
+ for (bi = 0; bi < draw->bc; bi++)
+ if (draw->bv[bi].ol)
+ sol_draw_list(draw->vary, draw->vary->bv + bi, draw->bv[bi].ol);
+
+ /* Render all translucent geometry into only the color buffer. */
+
+ if (depthtest == 0) glDisable(GL_DEPTH_TEST);
+ if (depthmask == 0) glDepthMask(GL_FALSE);
+ {
+ for (bi = 0; bi < draw->bc; bi++)
+ if (draw->bv[bi].tl)
+ sol_draw_list(draw->vary, draw->vary->bv + bi, draw->bv[bi].tl);
+ }
+ if (depthmask == 0) glDepthMask(GL_TRUE);
+ if (depthtest == 0) glEnable(GL_DEPTH_TEST);
+}
+
+void sol_bill(const struct s_draw *draw, const float *M, float t)
+{
+ const struct d_mtrl *mp = &default_draw_mtrl;
+
+ int ri;
+
+ for (ri = 0; ri < draw->base->rc; ++ri)
+ {
+ const struct b_bill *rp = draw->base->rv + ri;
+
+ float T = rp->t * t;
+ float S = fsinf(T);
+
+ float w = rp->w [0] + rp->w [1] * T + rp->w [2] * S;
+ float h = rp->h [0] + rp->h [1] * T + rp->h [2] * S;
+ float rx = rp->rx[0] + rp->rx[1] * T + rp->rx[2] * S;
+ float ry = rp->ry[0] + rp->ry[1] * T + rp->ry[2] * S;
+ float rz = rp->rz[0] + rp->rz[1] * T + rp->rz[2] * S;
+
+ mp = sol_draw_mtrl(draw, draw->mv + rp->mi, mp);
+
+ glPushMatrix();
+ {
+ glTranslatef(rp->p[0], rp->p[1], rp->p[2]);
+
+ if (M && ((rp->fl & B_NOFACE) == 0)) glMultMatrixf(M);
+
+ if (fabsf(rx) > 0.0f) glRotatef(rx, 1.0f, 0.0f, 0.0f);
+ if (fabsf(ry) > 0.0f) glRotatef(ry, 0.0f, 1.0f, 0.0f);
+ if (fabsf(rz) > 0.0f) glRotatef(rz, 0.0f, 0.0f, 1.0f);
+
+ glBegin(GL_QUADS);
+ {
+ glTexCoord2f(0.0f, 0.0f); glVertex2f(-w / 2, -h / 2);
+ glTexCoord2f(1.0f, 0.0f); glVertex2f(+w / 2, -h / 2);
+ glTexCoord2f(1.0f, 1.0f); glVertex2f(+w / 2, +h / 2);
+ glTexCoord2f(0.0f, 1.0f); glVertex2f(-w / 2, +h / 2);
+ }
+ glEnd();
+ }
+ glPopMatrix();
+ }
+
+ mp = sol_draw_mtrl(draw, &default_draw_mtrl, mp);
+}
+
+void sol_refl(const struct s_draw *draw)
+{
+ int bi;
+
+ /* Render all reflective geometry into the color and depth buffers. */
+
+ for (bi = 0; bi < draw->bc; bi++)
+ if (draw->bv[bi].rl)
+ sol_draw_list(draw->vary, draw->vary->bv + bi, draw->bv[bi].rl);
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void sol_shad_geom(const struct s_base *base,
+ const struct b_geom *gp, int mi)
+{
+ if (gp->mi == mi)
+ {
+ const float *vi = base->vv[gp->vi].p;
+ const float *vj = base->vv[gp->vj].p;
+ const float *vk = base->vv[gp->vk].p;
+
+ glTexCoord2f(vi[0], vi[2]);
+ glVertex3fv(vi);
+
+ glTexCoord2f(vj[0], vj[2]);
+ glVertex3fv(vj);
+
+ glTexCoord2f(vk[0], vk[2]);
+ glVertex3fv(vk);
+ }
+}
+
+static void sol_shad_lump(const struct s_base *base,
+ const struct b_lump *lp, int mi)
+{
+ int i;
+
+ for (i = 0; i < lp->gc; i++)
+ sol_shad_geom(base, base->gv + base->iv[lp->g0 + i], mi);
+}
+
+static void sol_shad_body(const struct s_base *base,
+ const struct b_body *bp,
+ int fl, int decal)
+{
+ int mi, li, gi;
+
+ if (decal)
+ {
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(-1.0f, -2.0f);
+ }
+
+ glBegin(GL_TRIANGLES);
+ {
+ for (mi = 0; mi < base->mc; mi++)
+ {
+ struct b_mtrl *mp = base->mv + mi;
+
+ if ((mp->fl & fl) && (mp->fl & M_DECAL) == decal)
+ {
+ for (li = 0; li < bp->lc; li++)
+ sol_shad_lump(base, base->lv + bp->l0 + li, mi);
+ for (gi = 0; gi < bp->gc; gi++)
+ sol_shad_geom(base, base->gv + base->iv[bp->g0 + gi], mi);
+ }
+ }
+ }
+ glEnd();
+
+ if (decal)
+ glDisable(GL_POLYGON_OFFSET_FILL);
+}
+
+static void sol_shad_list(const struct s_vary *vary,
+ const struct v_body *bp, GLuint list)
+{
+ float p[3], e[4], u[3], a;
+
+ sol_body_p(p, vary, bp->pi, bp->t);
+ sol_body_e(e, vary, bp, 0);
+
+ q_as_axisangle(e, u, &a);
+ a = V_DEG(a);
+
+ glPushMatrix();
+ {
+ /* Translate and rotate a moving body. */
+
+ glTranslatef(p[0], p[1], p[2]);
+ glRotatef(a, u[0], u[1], u[2]);
+
+ /* Translate the shadow on a moving body. */
+
+ glMatrixMode(GL_TEXTURE);
+ {
+ glPushMatrix();
+ glTranslatef(p[0], p[2], 0.0f);
+ glRotatef(-a, u[0], u[2], u[1]);
+ }
+ glMatrixMode(GL_MODELVIEW);
+
+ /* Draw the body. */
+
+ glCallList(list);
+
+ /* Pop the shadow translation. */
+
+ glMatrixMode(GL_TEXTURE);
+ {
+ glPopMatrix();
+ }
+ glMatrixMode(GL_MODELVIEW);
+ }
+ glPopMatrix();
+}
+
+void sol_shad(const struct s_draw *draw)
+{
+ int bi;
+
+ /* Render all shadowed geometry. */
+
+ glDepthMask(GL_FALSE);
+ {
+ for (bi = 0; bi < draw->bc; bi++)
+ if (draw->bv[bi].sl)
+ sol_shad_list(draw->vary, draw->vary->bv + bi, draw->bv[bi].sl);
+ }
+ glDepthMask(GL_TRUE);
+}
+
+/*---------------------------------------------------------------------------*/
+
+static void sol_load_objects(struct s_draw *draw, int s)
+{
+ int i;
+
+ /* Here we sort geometry into display lists by material type. */
+
+ for (i = 0; i < draw->bc; i++)
+ {
+ struct d_body *bp = draw->bv + i;
+
+ int on = sol_enum_body(draw->base, bp->base, M_OPAQUE);
+ int tn = sol_enum_body(draw->base, bp->base, M_TRANSPARENT);
+ int rn = sol_enum_body(draw->base, bp->base, M_REFLECTIVE);
+ int dn = sol_enum_body(draw->base, bp->base, M_DECAL);
+ int sn = sol_enum_body(draw->base, bp->base, M_SHADOWED);
+
+ /* Draw all opaque geometry, decals last. */
+
+ if (on)
+ {
+ bp->ol = glGenLists(1);
+
+ glNewList(bp->ol, GL_COMPILE);
+ {
+ const struct d_mtrl *mp = &default_draw_mtrl;
+
+ mp = sol_draw_body(draw, bp->base, mp, M_OPAQUE, 0);
+ mp = sol_draw_body(draw, bp->base, mp, M_OPAQUE, M_DECAL);
+ mp = sol_draw_mtrl(draw, &default_draw_mtrl, mp);
+ }
+ glEndList();
+ }
+ else bp->ol = 0;
+
+ /* Draw all translucent geometry, decals first. */
+
+ if (tn)
+ {
+ bp->tl = glGenLists(1);
+
+ glNewList(bp->tl, GL_COMPILE);
+ {
+ const struct d_mtrl *mp = &default_draw_mtrl;
+
+ mp = sol_draw_body(draw, bp->base, mp, M_TRANSPARENT, M_DECAL);
+ mp = sol_draw_body(draw, bp->base, mp, M_TRANSPARENT, 0);
+ mp = sol_draw_mtrl(draw, &default_draw_mtrl, mp);
+ }
+ glEndList();
+ }
+ else bp->tl = 0;
+
+ /* Draw all reflective geometry. */
+
+ if (rn)
+ {
+ bp->rl = glGenLists(1);
+
+ glNewList(bp->rl, GL_COMPILE);
+ {
+ const struct d_mtrl *mp = &default_draw_mtrl;
+
+ mp = sol_draw_body(draw, bp->base, mp, M_REFLECTIVE, 0);
+ mp = sol_draw_mtrl(draw, &default_draw_mtrl, mp);
+ }
+ glEndList();
+ }
+ else bp->rl = 0;
+
+ /* Draw all shadowed geometry. */
+
+ if (s && (on || rn || sn))
+ {
+ bp->sl = glGenLists(1);
+
+ glNewList(bp->sl, GL_COMPILE);
+ {
+ if (on) sol_shad_body(draw->base, bp->base, M_OPAQUE, 0);
+ if (rn) sol_shad_body(draw->base, bp->base, M_REFLECTIVE, 0);
+ if (dn) sol_shad_body(draw->base, bp->base, M_OPAQUE, M_DECAL);
+ if (sn)
+ {
+ /* Transparent shadowed geometry hack. */
+
+ if (dn)
+ sol_shad_body(draw->base, bp->base, M_SHADOWED, M_DECAL);
+
+ sol_shad_body(draw->base, bp->base, M_SHADOWED, 0);
+ }
+ }
+ glEndList();
+ }
+ else bp->sl = 0;
+ }
+}
+
+static GLuint sol_find_texture(const char *name)
+{
+ char png[MAXSTR];
+ char jpg[MAXSTR];
+
+ GLuint o;
+
+ /* Prefer a lossless copy of the texture over a lossy compression. */
+
+ strncpy(png, name, PATHMAX); strcat(png, ".png");
+ strncpy(jpg, name, PATHMAX); strcat(jpg, ".jpg");
+
+ /* Check for a PNG. */
+
+ if ((o = make_image_from_file(png)))
+ return o;
+
+ /* Check for a JPG. */
+
+ if ((o = make_image_from_file(jpg)))
+ return o;
+
+ return 0;
+}
+
+static void sol_load_textures(struct s_draw *draw)
+{
+ int i;
+
+ /* Load the image referenced by each material. */
+
+ for (i = 0; i < draw->mc; i++)
+ {
+ struct d_mtrl *mp = draw->mv + i;
+
+ if ((mp->o = sol_find_texture(_(mp->base->f))))
+ {
+ /* Set the texture to clamp or repeat based on material type. */
+
+ if (mp->base->fl & M_CLAMPED)
+ {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ }
+ else
+ {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ }
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------*/
+
+int sol_load_draw(struct s_draw *draw, const struct s_vary *vary, int s)
+{
+ int i;
+
+ memset(draw, 0, sizeof (*draw));
+
+ draw->vary = vary;
+ draw->base = draw->vary->base;
+
+ if (draw->base->mc)
+ {
+ draw->mv = calloc(draw->base->mc, sizeof (*draw->mv));
+ draw->mc = draw->base->mc;
+
+ for (i = 0; i < draw->base->mc; i++)
+ {
+ struct d_mtrl *mp = draw->mv + i;
+ struct b_mtrl *mq = draw->base->mv + i;
+
+ mp->base = mq;
+ }
+ }
+
+ if (draw->base->bc)
+ {
+ draw->bv = calloc(draw->base->bc, sizeof (*draw->bv));
+ draw->bc = draw->base->bc;
+
+ for (i = 0; i < draw->base->bc; i++)
+ {
+ struct d_body *bp = draw->bv + i;
+ struct b_body *bq = draw->base->bv + i;
+
+ bp->base = bq;
+ }
+ }
+
+ sol_load_textures(draw);
+ sol_load_objects (draw, s);
+
+ return 1;
+}
+
+void sol_free_draw(struct s_draw *draw)
+{
+ int i;
+
+ for (i = 0; i < draw->mc; i++)
+ {
+ if (glIsTexture(draw->mv[i].o))
+ glDeleteTextures(1, &draw->mv[i].o);
+ }
+
+ for (i = 0; i < draw->bc; i++)
+ {
+ if (glIsList(draw->bv[i].ol))
+ glDeleteLists(draw->bv[i].ol, 1);
+ if (glIsList(draw->bv[i].tl))
+ glDeleteLists(draw->bv[i].tl, 1);
+ if (glIsList(draw->bv[i].rl))
+ glDeleteLists(draw->bv[i].rl, 1);
+ if (glIsList(draw->bv[i].sl))
+ glDeleteLists(draw->bv[i].sl, 1);
+ }
+
+ free(draw->mv);
+ free(draw->bv);
+
+ memset(draw, 0, sizeof (*draw));
+}
+
+/*---------------------------------------------------------------------------*/
+
+int sol_load_full(struct s_full *full, const char *filename, int s)
+{
+ if (sol_load_base(&full->base, filename))
+ {
+ sol_load_vary(&full->vary, &full->base);
+ sol_load_draw(&full->draw, &full->vary, s);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+void sol_free_full(struct s_full *full)
+{
+ sol_free_draw(&full->draw);
+ sol_free_vary(&full->vary);
+ sol_free_base(&full->base);
+}
+
+/*---------------------------------------------------------------------------*/
--- /dev/null
+/*
+ * Copyright (C) 2003 Robert Kooima
+ *
+ * NEVERBALL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef SOLID_DRAW_H
+#define SOLID_DRAW_H
+
+#include "solid_base.h"
+#include "solid_vary.h"
+
+/*
+ * Rendered solid data.
+ */
+
+/*---------------------------------------------------------------------------*/
+
+struct d_mtrl
+{
+ const struct b_mtrl *base;
+
+ GLuint o; /* OpenGL texture object */
+};
+
+struct d_body
+{
+ const struct b_body *base;
+
+ GLuint ol; /* opaque geometry list */
+ GLuint tl; /* transparent geometry list */
+ GLuint rl; /* reflective geometry list */
+ GLuint sl; /* shadowed geometry list */
+};
+
+struct s_draw
+{
+ const struct s_base *base;
+ const struct s_vary *vary;
+
+ int mc;
+ int bc;
+
+ struct d_mtrl *mv;
+ struct d_body *bv;
+};
+
+/*---------------------------------------------------------------------------*/
+
+int sol_load_draw(struct s_draw *, const struct s_vary *, int);
+void sol_free_draw(struct s_draw *);
+
+int sol_reflective(const struct s_draw *);
+
+void sol_back(const struct s_draw *, float, float, float);
+void sol_refl(const struct s_draw *);
+void sol_draw(const struct s_draw *, int, int);
+void sol_bill(const struct s_draw *, const float *, float);
+void sol_shad(const struct s_draw *);
+
+/*---------------------------------------------------------------------------*/
+
+struct s_full
+{
+ struct s_base base;
+ struct s_vary vary;
+ struct s_draw draw;
+};
+
+int sol_load_full(struct s_full *, const char *, int);
+void sol_free_full(struct s_full *);
+
+/*---------------------------------------------------------------------------*/
+
+#endif
+++ /dev/null
-/*
- * Copyright (C) 2003 Robert Kooima
- *
- * NEVERBALL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#include <SDL.h>
-#include <SDL_rwops.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "glext.h"
-#include "vec3.h"
-#include "image.h"
-#include "base_image.h"
-#include "solid_gl.h"
-#include "solid_all.h"
-#include "base_config.h"
-#include "lang.h"
-
-/*---------------------------------------------------------------------------*/
-
-static int sol_enum_mtrl(const struct s_file *fp,
- const struct s_body *bp, int mi)
-{
- int li, gi, c = 0;
-
- /* Count all lump geoms with this material. */
-
- for (li = 0; li < bp->lc; li++)
- {
- int g0 = fp->lv[bp->l0 + li].g0;
- int gc = fp->lv[bp->l0 + li].gc;
-
- for (gi = 0; gi < gc; gi++)
- if (fp->gv[fp->iv[g0 + gi]].mi == mi)
- c++;
- }
-
- /* Count all body geoms with this material. */
-
- for (gi = 0; gi < bp->gc; gi++)
- if (fp->gv[fp->iv[bp->g0 + gi]].mi == mi)
- c++;
-
- return c;
-}
-
-static int sol_enum_body(const struct s_file *fp,
- const struct s_body *bp, int fl)
-{
- int mi, c = 0;
-
- /* Count all geoms with this flag. */
-
- for (mi = 0; mi < fp->mc; mi++)
- if (fp->mv[mi].fl & fl)
- c = c + sol_enum_mtrl(fp, bp, mi);
-
- return c;
-}
-
-/*---------------------------------------------------------------------------*/
-
-int sol_reflective(const struct s_file *fp)
-{
- int bi;
-
- for (bi = 0; bi < fp->bc; bi++)
- if (fp->bv[bi].rl)
- return 1;
-
- return 0;
-}
-
-/*---------------------------------------------------------------------------*/
-
-#define tobyte(f) ((GLubyte) (f * 255.0f))
-
-#define color_cmp(a, b) (tobyte((a)[0]) == tobyte((b)[0]) && \
- tobyte((a)[1]) == tobyte((b)[1]) && \
- tobyte((a)[2]) == tobyte((b)[2]) && \
- tobyte((a)[3]) == tobyte((b)[3]))
-
-static struct s_mtrl default_mtrl =
-{
- { 0.8f, 0.8f, 0.8f, 1.0f },
- { 0.2f, 0.2f, 0.2f, 1.0f },
- { 0.0f, 0.0f, 0.0f, 1.0f },
- { 0.0f, 0.0f, 0.0f, 1.0f },
- { 0.0f, }, 0.0f, M_OPAQUE, 0, ""
-};
-
-static const struct s_mtrl *sol_draw_mtrl(const struct s_file *fp,
- const struct s_mtrl *mp,
- const struct s_mtrl *mq)
-{
- /* Change material properties only as needed. */
-
- if (!color_cmp(mp->a, mq->a))
- glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mp->a);
- if (!color_cmp(mp->d, mq->d))
- glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->d);
- if (!color_cmp(mp->s, mq->s))
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mp->s);
- if (!color_cmp(mp->e, mq->e))
- glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mp->e);
- if (tobyte(mp->h[0]) != tobyte(mq->h[0]))
- glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mp->h);
-
- /* Bind the texture. */
-
- if (mp->o != mq->o)
- glBindTexture(GL_TEXTURE_2D, mp->o);
-
- /* Enable environment mapping. */
-
- if ((mp->fl & M_ENVIRONMENT) && !(mq->fl & M_ENVIRONMENT))
- {
- glEnable(GL_TEXTURE_GEN_S);
- glEnable(GL_TEXTURE_GEN_T);
-
- glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
- glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
- }
-
- /* Disable environment mapping. */
-
- if ((mq->fl & M_ENVIRONMENT) && !(mp->fl & M_ENVIRONMENT))
- {
- glDisable(GL_TEXTURE_GEN_S);
- glDisable(GL_TEXTURE_GEN_T);
- }
-
- /* Enable additive blending. */
-
- if ((mp->fl & M_ADDITIVE) && !(mq->fl & M_ADDITIVE))
- glBlendFunc(GL_ONE, GL_ONE);
-
- /* Enable standard blending. */
-
- if ((mq->fl & M_ADDITIVE) && !(mp->fl & M_ADDITIVE))
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- /* Enable visibility-from-behind. */
-
- if ((mp->fl & M_TWO_SIDED) && !(mq->fl & M_TWO_SIDED))
- {
- glDisable(GL_CULL_FACE);
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
- }
-
- /* Disable visibility-from-behind. */
-
- if ((mq->fl & M_TWO_SIDED) && !(mp->fl & M_TWO_SIDED))
- {
- glEnable(GL_CULL_FACE);
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
- }
-
- /* Enable decal offset. */
-
- if ((mp->fl & M_DECAL) && !(mq->fl & M_DECAL))
- {
- glEnable(GL_POLYGON_OFFSET_FILL);
- glPolygonOffset(-1.0f, -2.0f);
- }
-
- /* Disable decal offset. */
-
- if ((mq->fl & M_DECAL) && !(mp->fl & M_DECAL))
- glDisable(GL_POLYGON_OFFSET_FILL);
-
- return mp;
-}
-
-static const struct s_mtrl *sol_back_bill(const struct s_file *fp,
- const struct s_bill *rp,
- const struct s_mtrl *mp, float t)
-{
- float T = (rp->t > 0.0f) ? (fmodf(t, rp->t) - rp->t / 2) : 0.0f;
-
- float w = rp->w[0] + rp->w[1] * T + rp->w[2] * T * T;
- float h = rp->h[0] + rp->h[1] * T + rp->h[2] * T * T;
-
- if (w > 0 && h > 0)
- {
- float rx = rp->rx[0] + rp->rx[1] * T + rp->rx[2] * T * T;
- float ry = rp->ry[0] + rp->ry[1] * T + rp->ry[2] * T * T;
- float rz = rp->rz[0] + rp->rz[1] * T + rp->rz[2] * T * T;
-
- glPushMatrix();
- {
- float y0 = (rp->fl & B_EDGE) ? 0 : -h / 2;
- float y1 = (rp->fl & B_EDGE) ? h : +h / 2;
-
- glRotatef(ry, 0.0f, 1.0f, 0.0f);
- glRotatef(rx, 1.0f, 0.0f, 0.0f);
- glTranslatef(0.0f, 0.0f, -rp->d);
-
- if (rp->fl & B_FLAT)
- {
- glRotatef(-rx - 90.0f, 1.0f, 0.0f, 0.0f);
- glRotatef(-ry, 0.0f, 0.0f, 1.0f);
- }
- if (rp->fl & B_EDGE)
- glRotatef(-rx, 1.0f, 0.0f, 0.0f);
-
- glRotatef(rz, 0.0f, 0.0f, 1.0f);
-
- mp = sol_draw_mtrl(fp, fp->mv + rp->mi, mp);
-
- glBegin(GL_QUADS);
- {
- glTexCoord2f(0.0f, 0.0f); glVertex2f(-w / 2, y0);
- glTexCoord2f(1.0f, 0.0f); glVertex2f(+w / 2, y0);
- glTexCoord2f(1.0f, 1.0f); glVertex2f(+w / 2, y1);
- glTexCoord2f(0.0f, 1.0f); glVertex2f(-w / 2, y1);
- }
- glEnd();
- }
- glPopMatrix();
- }
-
- return mp;
-}
-
-/*---------------------------------------------------------------------------*/
-
-void sol_back(const struct s_file *fp, float n, float f, float t)
-{
- const struct s_mtrl *mp = &default_mtrl;
-
- int ri;
-
- /* Render all billboards in the given range. */
-
- glDisable(GL_LIGHTING);
- glDepthMask(GL_FALSE);
- {
- for (ri = 0; ri < fp->rc; ri++)
- if (n <= fp->rv[ri].d && fp->rv[ri].d < f)
- mp = sol_back_bill(fp, fp->rv + ri, mp, t);
-
- mp = sol_draw_mtrl(fp, &default_mtrl, mp);
- }
- glDepthMask(GL_TRUE);
- glEnable(GL_LIGHTING);
-}
-
-/*---------------------------------------------------------------------------*/
-/*
- * The following code renders a body in a ludicrously inefficient
- * manner. It iterates the materials and scans the data structure for
- * geometry using each. This has the effect of absolutely minimizing
- * material changes, texture bindings, and Begin/End pairs, but
- * maximizing trips through the data.
- *
- * However, this is only done once for each level. The results are
- * stored in display lists. Thus, it is well worth it.
- */
-
-static void sol_draw_geom(const struct s_file *fp,
- const struct s_geom *gp, int mi)
-{
- if (gp->mi == mi)
- {
- const float *ui = fp->tv[gp->ti].u;
- const float *uj = fp->tv[gp->tj].u;
- const float *uk = fp->tv[gp->tk].u;
-
- const float *ni = fp->sv[gp->si].n;
- const float *nj = fp->sv[gp->sj].n;
- const float *nk = fp->sv[gp->sk].n;
-
- const float *vi = fp->vv[gp->vi].p;
- const float *vj = fp->vv[gp->vj].p;
- const float *vk = fp->vv[gp->vk].p;
-
- glTexCoord2fv(ui);
- glNormal3fv(ni);
- glVertex3fv(vi);
-
- glTexCoord2fv(uj);
- glNormal3fv(nj);
- glVertex3fv(vj);
-
- glTexCoord2fv(uk);
- glNormal3fv(nk);
- glVertex3fv(vk);
- }
-}
-
-static void sol_draw_lump(const struct s_file *fp,
- const struct s_lump *lp, int mi)
-{
- int i;
-
- for (i = 0; i < lp->gc; i++)
- sol_draw_geom(fp, fp->gv + fp->iv[lp->g0 + i], mi);
-}
-
-static const struct s_mtrl *sol_draw_body(const struct s_file *fp,
- const struct s_body *bp,
- const struct s_mtrl *mp,
- int fl, int decal)
-{
- int mi, li, gi;
-
- /* Iterate all materials of the correct opacity. */
-
- for (mi = 0; mi < fp->mc; mi++)
- if ((fp->mv[mi].fl & fl) && (fp->mv[mi].fl & M_DECAL) == decal)
- {
- if (sol_enum_mtrl(fp, bp, mi))
- {
- /* Set the material state. */
-
- mp = sol_draw_mtrl(fp, fp->mv + mi, mp);
-
- /* Render all geometry of that material. */
-
- glBegin(GL_TRIANGLES);
- {
- for (li = 0; li < bp->lc; li++)
- sol_draw_lump(fp, fp->lv + bp->l0 + li, mi);
- for (gi = 0; gi < bp->gc; gi++)
- sol_draw_geom(fp, fp->gv + fp->iv[bp->g0 + gi], mi);
- }
- glEnd();
- }
- }
-
- return mp;
-}
-
-static void sol_draw_list(const struct s_file *fp,
- const struct s_body *bp, GLuint list)
-{
- float p[3], e[4], u[3], a;
-
- sol_body_p(p, fp, bp->pi, bp->t);
- sol_body_e(e, fp, bp, 0);
-
- q_as_axisangle(e, u, &a);
- a = V_DEG(a);
-
- glPushMatrix();
- {
- /* Translate and rotate a moving body. */
-
- glTranslatef(p[0], p[1], p[2]);
- glRotatef(a, u[0], u[1], u[2]);
-
- /* Draw the body. */
-
- glCallList(list);
- }
- glPopMatrix();
-}
-
-void sol_draw(const struct s_file *fp, int depthmask, int depthtest)
-{
- int bi;
-
- /* Render all opaque geometry into the color and depth buffers. */
-
- for (bi = 0; bi < fp->bc; bi++)
- if (fp->bv[bi].ol)
- sol_draw_list(fp, fp->bv + bi, fp->bv[bi].ol);
-
- /* Render all translucent geometry into only the color buffer. */
-
- if (depthtest == 0) glDisable(GL_DEPTH_TEST);
- if (depthmask == 0) glDepthMask(GL_FALSE);
- {
- for (bi = 0; bi < fp->bc; bi++)
- if (fp->bv[bi].tl)
- sol_draw_list(fp, fp->bv + bi, fp->bv[bi].tl);
- }
- if (depthmask == 0) glDepthMask(GL_TRUE);
- if (depthtest == 0) glEnable(GL_DEPTH_TEST);
-}
-
-void sol_bill(const struct s_file *fp, const float *M, float t)
-{
- const struct s_mtrl *mp = &default_mtrl;
-
- int ri;
-
- for (ri = 0; ri < fp->rc; ++ri)
- {
- const struct s_bill *rp = fp->rv + ri;
-
- float T = rp->t * t;
- float S = fsinf(T);
-
- float w = rp->w [0] + rp->w [1] * T + rp->w [2] * S;
- float h = rp->h [0] + rp->h [1] * T + rp->h [2] * S;
- float rx = rp->rx[0] + rp->rx[1] * T + rp->rx[2] * S;
- float ry = rp->ry[0] + rp->ry[1] * T + rp->ry[2] * S;
- float rz = rp->rz[0] + rp->rz[1] * T + rp->rz[2] * S;
-
- mp = sol_draw_mtrl(fp, fp->mv + rp->mi, mp);
-
- glPushMatrix();
- {
- glTranslatef(rp->p[0], rp->p[1], rp->p[2]);
-
- if (M && ((rp->fl & B_NOFACE) == 0)) glMultMatrixf(M);
-
- if (fabsf(rx) > 0.0f) glRotatef(rx, 1.0f, 0.0f, 0.0f);
- if (fabsf(ry) > 0.0f) glRotatef(ry, 0.0f, 1.0f, 0.0f);
- if (fabsf(rz) > 0.0f) glRotatef(rz, 0.0f, 0.0f, 1.0f);
-
- glBegin(GL_QUADS);
- {
- glTexCoord2f(0.0f, 0.0f); glVertex2f(-w / 2, -h / 2);
- glTexCoord2f(1.0f, 0.0f); glVertex2f(+w / 2, -h / 2);
- glTexCoord2f(1.0f, 1.0f); glVertex2f(+w / 2, +h / 2);
- glTexCoord2f(0.0f, 1.0f); glVertex2f(-w / 2, +h / 2);
- }
- glEnd();
- }
- glPopMatrix();
- }
-
- mp = sol_draw_mtrl(fp, &default_mtrl, mp);
-}
-
-void sol_refl(const struct s_file *fp)
-{
- int bi;
-
- /* Render all reflective geometry into the color and depth buffers. */
-
- for (bi = 0; bi < fp->bc; bi++)
- if (fp->bv[bi].rl)
- sol_draw_list(fp, fp->bv + bi, fp->bv[bi].rl);
-}
-
-/*---------------------------------------------------------------------------*/
-
-static void sol_shad_geom(const struct s_file *fp,
- const struct s_geom *gp, int mi)
-{
- if (gp->mi == mi)
- {
- const float *vi = fp->vv[gp->vi].p;
- const float *vj = fp->vv[gp->vj].p;
- const float *vk = fp->vv[gp->vk].p;
-
- glTexCoord2f(vi[0], vi[2]);
- glVertex3fv(vi);
-
- glTexCoord2f(vj[0], vj[2]);
- glVertex3fv(vj);
-
- glTexCoord2f(vk[0], vk[2]);
- glVertex3fv(vk);
- }
-}
-
-static void sol_shad_lump(const struct s_file *fp,
- const struct s_lump *lp, int mi)
-{
- int i;
-
- for (i = 0; i < lp->gc; i++)
- sol_shad_geom(fp, fp->gv + fp->iv[lp->g0 + i], mi);
-}
-
-static void sol_shad_body(const struct s_file *fp,
- const struct s_body *bp,
- int fl, int decal)
-{
- int mi, li, gi;
-
- if (decal)
- {
- glEnable(GL_POLYGON_OFFSET_FILL);
- glPolygonOffset(-1.0f, -2.0f);
- }
-
- glBegin(GL_TRIANGLES);
- {
- for (mi = 0; mi < fp->mc; mi++)
- if ((fp->mv[mi].fl & fl) && (fp->mv[mi].fl & M_DECAL) == decal)
- {
- for (li = 0; li < bp->lc; li++)
- sol_shad_lump(fp, fp->lv + bp->l0 + li, mi);
- for (gi = 0; gi < bp->gc; gi++)
- sol_shad_geom(fp, fp->gv + fp->iv[bp->g0 + gi], mi);
- }
- }
- glEnd();
-
- if (decal)
- glDisable(GL_POLYGON_OFFSET_FILL);
-}
-
-static void sol_shad_list(const struct s_file *fp,
- const struct s_body *bp, GLuint list)
-{
- float p[3], e[4], u[3], a;
-
- sol_body_p(p, fp, bp->pi, bp->t);
- sol_body_e(e, fp, bp, 0);
-
- q_as_axisangle(e, u, &a);
- a = V_DEG(a);
-
- glPushMatrix();
- {
- /* Translate and rotate a moving body. */
-
- glTranslatef(p[0], p[1], p[2]);
- glRotatef(a, u[0], u[1], u[2]);
-
- /* Translate the shadow on a moving body. */
-
- glMatrixMode(GL_TEXTURE);
- {
- glPushMatrix();
- glTranslatef(p[0], p[2], 0.0f);
- glRotatef(-a, u[0], u[2], u[1]);
- }
- glMatrixMode(GL_MODELVIEW);
-
- /* Draw the body. */
-
- glCallList(list);
-
- /* Pop the shadow translation. */
-
- glMatrixMode(GL_TEXTURE);
- {
- glPopMatrix();
- }
- glMatrixMode(GL_MODELVIEW);
- }
- glPopMatrix();
-}
-
-void sol_shad(const struct s_file *fp)
-{
- int bi;
-
- /* Render all shadowed geometry. */
-
- glDepthMask(GL_FALSE);
- {
- for (bi = 0; bi < fp->bc; bi++)
- if (fp->bv[bi].sl)
- sol_shad_list(fp, fp->bv + bi, fp->bv[bi].sl);
- }
- glDepthMask(GL_TRUE);
-}
-
-/*---------------------------------------------------------------------------*/
-
-static void sol_load_objects(struct s_file *fp, int s)
-{
- int i;
-
- /* Here we sort geometry into display lists by material type. */
-
- for (i = 0; i < fp->bc; i++)
- {
- struct s_body *bp = fp->bv + i;
-
- int on = sol_enum_body(fp, bp, M_OPAQUE);
- int tn = sol_enum_body(fp, bp, M_TRANSPARENT);
- int rn = sol_enum_body(fp, bp, M_REFLECTIVE);
- int dn = sol_enum_body(fp, bp, M_DECAL);
- int sn = sol_enum_body(fp, bp, M_SHADOWED);
-
- /* Draw all opaque geometry, decals last. */
-
- if (on)
- {
- fp->bv[i].ol = glGenLists(1);
-
- glNewList(fp->bv[i].ol, GL_COMPILE);
- {
- const struct s_mtrl *mp = &default_mtrl;
-
- mp = sol_draw_body(fp, fp->bv + i, mp, M_OPAQUE, 0);
- mp = sol_draw_body(fp, fp->bv + i, mp, M_OPAQUE, M_DECAL);
- mp = sol_draw_mtrl(fp, &default_mtrl, mp);
- }
- glEndList();
- }
- else fp->bv[i].ol = 0;
-
- /* Draw all translucent geometry, decals first. */
-
- if (tn)
- {
- fp->bv[i].tl = glGenLists(1);
-
- glNewList(fp->bv[i].tl, GL_COMPILE);
- {
- const struct s_mtrl *mp = &default_mtrl;
-
- mp = sol_draw_body(fp, fp->bv + i, mp, M_TRANSPARENT, M_DECAL);
- mp = sol_draw_body(fp, fp->bv + i, mp, M_TRANSPARENT, 0);
- mp = sol_draw_mtrl(fp, &default_mtrl, mp);
- }
- glEndList();
- }
- else fp->bv[i].tl = 0;
-
- /* Draw all reflective geometry. */
-
- if (rn)
- {
- fp->bv[i].rl = glGenLists(1);
-
- glNewList(fp->bv[i].rl, GL_COMPILE);
- {
- const struct s_mtrl *mp = &default_mtrl;
-
- mp = sol_draw_body(fp, fp->bv + i, mp, M_REFLECTIVE, 0);
- mp = sol_draw_mtrl(fp, &default_mtrl, mp);
- }
- glEndList();
- }
- else fp->bv[i].rl = 0;
-
- /* Draw all shadowed geometry. */
-
- if (s && (on || rn || sn))
- {
- fp->bv[i].sl = glGenLists(1);
-
- glNewList(fp->bv[i].sl, GL_COMPILE);
- {
- if (on) sol_shad_body(fp, fp->bv + i, M_OPAQUE, 0);
- if (rn) sol_shad_body(fp, fp->bv + i, M_REFLECTIVE, 0);
- if (dn) sol_shad_body(fp, fp->bv + i, M_OPAQUE, M_DECAL);
- if (sn)
- {
- /* Transparent shadowed geometry hack. */
-
- if (dn)
- sol_shad_body(fp, fp->bv + i, M_SHADOWED, M_DECAL);
-
- sol_shad_body(fp, fp->bv + i, M_SHADOWED, 0);
- }
- }
- glEndList();
- }
- else fp->bv[i].sl = 0;
- }
-}
-
-static GLuint sol_find_texture(const char *name)
-{
- char png[MAXSTR];
- char jpg[MAXSTR];
-
- GLuint o;
-
- /* Prefer a lossless copy of the texture over a lossy compression. */
-
- strncpy(png, name, PATHMAX); strcat(png, ".png");
- strncpy(jpg, name, PATHMAX); strcat(jpg, ".jpg");
-
- /* Check for a PNG. */
-
- if ((o = make_image_from_file(png)))
- return o;
-
- /* Check for a JPG. */
-
- if ((o = make_image_from_file(jpg)))
- return o;
-
- return 0;
-}
-
-static void sol_load_textures(struct s_file *fp)
-{
- int i;
-
- /* Load the image referenced by each material. */
-
- for (i = 0; i < fp->mc; i++)
- if ((fp->mv[i].o = sol_find_texture(_(fp->mv[i].f))))
- {
- /* Set the texture to clamp or repeat based on material type. */
-
- if (fp->mv[i].fl & M_CLAMPED)
- {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
- }
- else
- {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- }
- }
-}
-
-/*---------------------------------------------------------------------------*/
-
-int sol_load_gl(struct s_file *fp, const char *filename, int s)
-{
- if (sol_load_only_file(fp, filename))
- {
- sol_load_textures(fp);
- sol_load_objects (fp, s);
- return 1;
- }
- return 0;
-}
-
-/*---------------------------------------------------------------------------*/
-
-void sol_free_gl(struct s_file *fp)
-{
- int i;
-
- for (i = 0; i < fp->mc; i++)
- {
- if (glIsTexture(fp->mv[i].o))
- glDeleteTextures(1, &fp->mv[i].o);
- }
-
- for (i = 0; i < fp->bc; i++)
- {
- if (glIsList(fp->bv[i].ol))
- glDeleteLists(fp->bv[i].ol, 1);
- if (glIsList(fp->bv[i].tl))
- glDeleteLists(fp->bv[i].tl, 1);
- if (glIsList(fp->bv[i].rl))
- glDeleteLists(fp->bv[i].rl, 1);
- if (glIsList(fp->bv[i].sl))
- glDeleteLists(fp->bv[i].sl, 1);
- }
-
- sol_free(fp);
-}
-
-/*---------------------------------------------------------------------------*/
+++ /dev/null
-/*
- * Copyright (C) 2003 Robert Kooima
- *
- * NEVERBALL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#ifndef SOL_GL_H
-#define SOL_GL_H
-
-#include "solid.h"
-
-/*---------------------------------------------------------------------------*/
-
-int sol_load_gl(struct s_file *, const char *, int);
-void sol_free_gl(struct s_file *);
-
-int sol_reflective(const struct s_file *);
-
-void sol_back(const struct s_file *, float, float, float);
-void sol_refl(const struct s_file *);
-void sol_draw(const struct s_file *, int, int);
-void sol_bill(const struct s_file *, const float *, float);
-void sol_shad(const struct s_file *);
-
-/*---------------------------------------------------------------------------*/
-
-#endif
* General Public License for more details.
*/
-#ifndef SOL_SIM_H
-#define SOL_SIM_H
+#ifndef SOLID_SIM_H
+#define SOLID_SIM_H
-#include "solid.h"
+#include "solid_vary.h"
/*---------------------------------------------------------------------------*/
-void sol_init_sim(struct s_file *);
+void sol_init_sim(struct s_vary *);
void sol_quit_sim(void);
-float sol_step(struct s_file *, const float *, float, int, int *);
+float sol_step(struct s_vary *, const float *, float, int, int *);
/*---------------------------------------------------------------------------*/
#include "vec3.h"
#include "common.h"
-#include "solid.h"
+#include "solid_vary.h"
#include "solid_sim.h"
#include "solid_all.h"
#include "solid_cmd.h"
* Q gives the position of the point of impact and W gives the
* velocity of the object being impacted.
*/
-static float sol_bounce(struct s_ball *up,
+static float sol_bounce(struct v_ball *up,
const float q[3],
const float w[3], float dt)
{
static float sol_test_vert(float dt,
float T[3],
- const struct s_ball *up,
- const struct s_vert *vp,
+ const struct v_ball *up,
+ const struct b_vert *vp,
const float o[3],
const float w[3])
{
static float sol_test_edge(float dt,
float T[3],
- const struct s_ball *up,
- const struct s_file *fp,
- const struct s_edge *ep,
+ const struct v_ball *up,
+ const struct s_base *base,
+ const struct b_edge *ep,
const float o[3],
const float w[3])
{
float q[3];
float u[3];
- v_cpy(q, fp->vv[ep->vi].p);
- v_sub(u, fp->vv[ep->vj].p,
- fp->vv[ep->vi].p);
+ v_cpy(q, base->vv[ep->vi].p);
+ v_sub(u, base->vv[ep->vj].p, base->vv[ep->vi].p);
return v_edge(T, o, q, u, w, up->p, up->v, up->r);
}
static float sol_test_side(float dt,
float T[3],
- const struct s_ball *up,
- const struct s_file *fp,
- const struct s_lump *lp,
- const struct s_side *sp,
+ const struct v_ball *up,
+ const struct s_base *base,
+ const struct b_lump *lp,
+ const struct b_side *sp,
const float o[3],
const float w[3])
{
if (t < dt)
for (i = 0; i < lp->sc; i++)
{
- const struct s_side *sq = fp->sv + fp->iv[lp->s0 + i];
+ const struct b_side *sq = base->sv + base->iv[lp->s0 + i];
if (sp != sq &&
v_dot(T, sq->n) -
/*---------------------------------------------------------------------------*/
static int sol_test_fore(float dt,
- const struct s_ball *up,
- const struct s_side *sp,
+ const struct v_ball *up,
+ const struct b_side *sp,
const float o[3],
const float w[3])
{
}
static int sol_test_back(float dt,
- const struct s_ball *up,
- const struct s_side *sp,
+ const struct v_ball *up,
+ const struct b_side *sp,
const float o[3],
const float w[3])
{
static float sol_test_lump(float dt,
float T[3],
- const struct s_ball *up,
- const struct s_file *fp,
- const struct s_lump *lp,
+ const struct v_ball *up,
+ const struct s_base *base,
+ const struct b_lump *lp,
const float o[3],
const float w[3])
{
if (up->r > 0.0f)
for (i = 0; i < lp->vc; i++)
{
- const struct s_vert *vp = fp->vv + fp->iv[lp->v0 + i];
+ const struct b_vert *vp = base->vv + base->iv[lp->v0 + i];
if ((u = sol_test_vert(t, U, up, vp, o, w)) < t)
{
if (up->r > 0.0f)
for (i = 0; i < lp->ec; i++)
{
- const struct s_edge *ep = fp->ev + fp->iv[lp->e0 + i];
+ const struct b_edge *ep = base->ev + base->iv[lp->e0 + i];
- if ((u = sol_test_edge(t, U, up, fp, ep, o, w)) < t)
+ if ((u = sol_test_edge(t, U, up, base, ep, o, w)) < t)
{
v_cpy(T, U);
t = u;
for (i = 0; i < lp->sc; i++)
{
- const struct s_side *sp = fp->sv + fp->iv[lp->s0 + i];
+ const struct b_side *sp = base->sv + base->iv[lp->s0 + i];
- if ((u = sol_test_side(t, U, up, fp, lp, sp, o, w)) < t)
+ if ((u = sol_test_side(t, U, up, base, lp, sp, o, w)) < t)
{
v_cpy(T, U);
t = u;
static float sol_test_node(float dt,
float T[3],
- const struct s_ball *up,
- const struct s_file *fp,
- const struct s_node *np,
+ const struct v_ball *up,
+ const struct s_base *base,
+ const struct b_node *np,
const float o[3],
const float w[3])
{
for (i = 0; i < np->lc; i++)
{
- const struct s_lump *lp = fp->lv + np->l0 + i;
+ const struct b_lump *lp = base->lv + np->l0 + i;
- if ((u = sol_test_lump(t, U, up, fp, lp, o, w)) < t)
+ if ((u = sol_test_lump(t, U, up, base, lp, o, w)) < t)
{
v_cpy(T, U);
t = u;
/* Test in front of this node */
- if (np->ni >= 0 && sol_test_fore(t, up, fp->sv + np->si, o, w))
+ if (np->ni >= 0 && sol_test_fore(t, up, base->sv + np->si, o, w))
{
- const struct s_node *nq = fp->nv + np->ni;
+ const struct b_node *nq = base->nv + np->ni;
- if ((u = sol_test_node(t, U, up, fp, nq, o, w)) < t)
+ if ((u = sol_test_node(t, U, up, base, nq, o, w)) < t)
{
v_cpy(T, U);
t = u;
/* Test behind this node */
- if (np->nj >= 0 && sol_test_back(t, up, fp->sv + np->si, o, w))
+ if (np->nj >= 0 && sol_test_back(t, up, base->sv + np->si, o, w))
{
- const struct s_node *nq = fp->nv + np->nj;
+ const struct b_node *nq = base->nv + np->nj;
- if ((u = sol_test_node(t, U, up, fp, nq, o, w)) < t)
+ if ((u = sol_test_node(t, U, up, base, nq, o, w)) < t)
{
v_cpy(T, U);
t = u;
static float sol_test_body(float dt,
float T[3], float V[3],
- const struct s_ball *up,
- const struct s_file *fp,
- const struct s_body *bp)
+ const struct v_ball *up,
+ const struct s_vary *vary,
+ const struct v_body *bp)
{
float U[3], O[3], E[4], W[3], A[3], u;
- const struct s_node *np = fp->nv + bp->ni;
+ const struct b_node *np = vary->base->nv + bp->base->ni;
- sol_body_p(O, fp, bp->pi, bp->t);
- sol_body_v(W, fp, bp->pi, bp->t, dt);
- sol_body_e(E, fp, bp, 0);
- sol_body_w(A, fp, bp);
+ sol_body_p(O, vary, bp->pi, bp->t);
+ sol_body_v(W, vary, bp->pi, bp->t, dt);
+ sol_body_e(E, vary, bp, 0);
+ sol_body_w(A, vary, bp);
/*
* For rotating bodies, rather than rotate every normal and vertex
{
/* The body has a non-identity orientation or it is rotating. */
- struct s_ball ball;
+ struct v_ball ball;
float e[4], p0[3], p1[3];
const float z[3] = { 0 };
v_mad(p1, p1, up->v, dt);
v_mad(p1, p1, W, -dt);
- sol_body_e(e, fp, bp, dt);
+ sol_body_e(e, vary, bp, dt);
q_conj(e, e);
q_rot(p1, e, p1);
v_sub(ball.v, p1, p0);
v_scl(ball.v, ball.v, 1.0f / dt);
- if ((u = sol_test_node(dt, U, &ball, fp, np, z, z)) < dt)
+ if ((u = sol_test_node(dt, U, &ball, vary->base, np, z, z)) < dt)
{
float d[4];
}
else
{
- if ((u = sol_test_node(dt, U, up, fp, np, O, W)) < dt)
+ if ((u = sol_test_node(dt, U, up, vary->base, np, O, W)) < dt)
{
v_cpy(T, U);
v_cpy(V, W);
static float sol_test_file(float dt,
float T[3], float V[3],
- const struct s_ball *up,
- const struct s_file *fp)
+ const struct v_ball *up,
+ const struct s_vary *vary)
{
float U[3], W[3], u, t = dt;
int i;
- for (i = 0; i < fp->bc; i++)
+ for (i = 0; i < vary->bc; i++)
{
- const struct s_body *bp = fp->bv + i;
+ const struct v_body *bp = vary->bv + i;
- if ((u = sol_test_body(t, U, W, up, fp, bp)) < t)
+ if ((u = sol_test_body(t, U, W, up, vary, bp)) < t)
{
v_cpy(T, U);
v_cpy(V, W);
* iterations, punt it.
*/
-float sol_step(struct s_file *fp, const float *g, float dt, int ui, int *m)
+float sol_step(struct s_vary *vary, const float *g, float dt, int ui, int *m)
{
float P[3], V[3], v[3], r[3], a[3], d, e, nt, b = 0.0f, tt = dt;
int c;
union cmd cmd;
- if (ui < fp->uc)
+ if (ui < vary->uc)
{
- struct s_ball *up = fp->uv + ui;
+ struct v_ball *up = vary->uv + ui;
/* If the ball is in contact with a surface, apply friction. */
v_cpy(v, up->v);
v_cpy(up->v, g);
- if (m && sol_test_file(tt, P, V, up, fp) < 0.0005f)
+ if (m && sol_test_file(tt, P, V, up, vary) < 0.0005f)
{
v_cpy(up->v, v);
v_sub(r, P, up->p);
st = tt;
- for (bi = 0; bi < fp->bc; bi++)
+ for (bi = 0; bi < vary->bc; bi++)
{
- struct s_body *bp = fp->bv + bi;
+ struct v_body *bp = vary->bv + bi;
if (bp->pi >= 0)
{
- struct s_path *pp = fp->pv + bp->pi;
+ struct v_path *pp = vary->pv + bp->pi;
if (!pp->f)
continue;
- if (bp->tm + ms_peek(st) > pp->tm)
- st = MS_TO_TIME(pp->tm - bp->tm);
+ if (bp->tm + ms_peek(st) > pp->base->tm)
+ st = MS_TO_TIME(pp->base->tm - bp->tm);
}
}
/* Miss collisions if we reach the iteration limit. */
if (c > 1)
- nt = sol_test_file(st, P, V, up, fp);
+ nt = sol_test_file(st, P, V, up, vary);
else
nt = tt;
ms = ms_step(nt);
- sol_body_step(fp, nt, ms);
- sol_swch_step(fp, nt, ms);
- sol_ball_step(fp, nt);
+ sol_body_step(vary, nt, ms);
+ sol_swch_step(vary, nt, ms);
+ sol_ball_step(vary, nt);
if (nt < st)
if (b < (d = sol_bounce(up, P, V, nt)))
/*---------------------------------------------------------------------------*/
-void sol_init_sim(struct s_file *fp)
+void sol_init_sim(struct s_vary *vary)
{
ms_init();
}
--- /dev/null
+/*
+ * Copyright (C) 2003 Robert Kooima
+ *
+ * NEVERBALL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include <stdlib.h>
+
+#include "solid_vary.h"
+#include "common.h"
+#include "vec3.h"
+
+/*---------------------------------------------------------------------------*/
+
+int sol_load_vary(struct s_vary *fp, const struct s_base *base)
+{
+ int i;
+
+ memset(fp, 0, sizeof (*fp));
+
+ fp->base = base;
+
+ if (fp->base->pc)
+ {
+ fp->pv = calloc(fp->base->pc, sizeof (*fp->pv));
+ fp->pc = fp->base->pc;
+
+ for (i = 0; i < fp->base->pc; i++)
+ {
+ struct v_path *pp = fp->pv + i;
+ struct b_path *pq = fp->base->pv + i;
+
+ pp->base = pq;
+ pp->f = pq->f;
+ }
+ }
+
+ if (fp->base->bc)
+ {
+ fp->bv = calloc(fp->base->bc, sizeof (*fp->bv));
+ fp->bc = fp->base->bc;
+
+ for (i = 0; i < fp->base->bc; i++)
+ {
+ struct v_body *bp = fp->bv + i;
+ struct b_body *bq = fp->base->bv + i;
+
+ bp->base = bq;
+ bp->pi = bq->pi;
+ }
+ }
+
+ if (fp->base->hc)
+ {
+ fp->hv = calloc(fp->base->hc, sizeof (*fp->hv));
+ fp->hc = fp->base->hc;
+
+ for (i = 0; i < fp->base->hc; i++)
+ {
+ struct v_item *hp = fp->hv + i;
+ struct b_item *hq = fp->base->hv + i;
+
+ v_cpy(hp->p, hq->p);
+
+ hp->t = hq->t;
+ hp->n = hq->n;
+ }
+ }
+
+ if (fp->base->xc)
+ {
+ fp->xv = calloc(fp->base->xc, sizeof (*fp->xv));
+ fp->xc = fp->base->xc;
+
+ for (i = 0; i < fp->base->xc; i++)
+ {
+ struct v_swch *xp = fp->xv + i;
+ struct b_swch *xq = fp->base->xv + i;
+
+ xp->base = xq;
+ xp->t = xq->t;
+ xp->tm = xq->tm;
+ xp->f = xq->f;
+ }
+ }
+
+ if (fp->base->uc)
+ {
+ fp->uv = calloc(fp->base->uc, sizeof (*fp->uv));
+ fp->uc = fp->base->uc;
+
+ for (i = 0; i < fp->base->uc; i++)
+ {
+ struct v_ball *up = fp->uv + i;
+ struct b_ball *uq = fp->base->uv + i;
+
+ v_cpy(up->p, uq->p);
+
+ up->r = uq->r;
+
+ up->E[0][0] = up->e[0][0] = 1.0f;
+ up->E[0][1] = up->e[0][1] = 0.0f;
+ up->E[0][2] = up->e[0][2] = 0.0f;
+
+ up->E[1][0] = up->e[1][0] = 0.0f;
+ up->E[1][1] = up->e[1][1] = 1.0f;
+ up->E[1][2] = up->e[1][2] = 0.0f;
+
+ up->E[2][0] = up->e[2][0] = 0.0f;
+ up->E[2][1] = up->e[2][1] = 0.0f;
+ up->E[2][2] = up->e[2][2] = 1.0f;
+ }
+ }
+
+ return 1;
+}
+
+void sol_free_vary(struct s_vary *fp)
+{
+ if (fp->pv) free(fp->pv);
+ if (fp->bv) free(fp->bv);
+ if (fp->hv) free(fp->hv);
+ if (fp->xv) free(fp->xv);
+ if (fp->uv) free(fp->uv);
+
+ memset(fp, 0, sizeof (*fp));
+}
+
+/*---------------------------------------------------------------------------*/
--- /dev/null
+/*
+ * Copyright (C) 2003 Robert Kooima
+ *
+ * NEVERBALL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef SOLID_VARY_H
+#define SOLID_VARY_H
+
+#include "base_config.h"
+#include "solid_base.h"
+
+/*
+ * Varying solid data.
+ */
+
+/*---------------------------------------------------------------------------*/
+
+struct v_path
+{
+ const struct b_path *base;
+
+ int f; /* enable flag */
+};
+
+struct v_body
+{
+ const struct b_body *base;
+
+ float t; /* time on current path */
+ int tm; /* milliseconds */
+
+ int pi;
+};
+
+struct v_item
+{
+ float p[3]; /* position */
+ int t; /* type */
+ int n; /* value */
+};
+
+struct v_swch
+{
+ const struct b_swch *base;
+
+ float t; /* current timer */
+ int tm; /* milliseconds */
+ int f; /* current state */
+ int e; /* is a ball inside it? */
+};
+
+struct v_ball
+{
+ float e[3][3]; /* basis of orientation */
+ float p[3]; /* position vector */
+ float v[3]; /* velocity vector */
+ float w[3]; /* angular velocity vector */
+ float E[3][3]; /* basis of pendulum */
+ float W[3]; /* angular pendulum velocity */
+ float r; /* radius */
+};
+
+struct s_vary
+{
+ const struct s_base *base;
+
+ int pc;
+ int bc;
+ int hc;
+ int xc;
+ int uc;
+
+ struct v_path *pv;
+ struct v_body *bv;
+ struct v_item *hv;
+ struct v_swch *xv;
+ struct v_ball *uv;
+};
+
+/*---------------------------------------------------------------------------*/
+
+int sol_load_vary(struct s_vary *, const struct s_base *);
+void sol_free_vary(struct s_vary *);
+
+/*---------------------------------------------------------------------------*/
+
+#endif