X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=share%2Fsolid.c;h=467da8774a9f613d18c763bf601813fda92688db;hb=90baa3b05af80b5996bb2eecebd58ca2ceb53acf;hp=9b4e8c3d848d9d037b1c51e826aa460e4133d04d;hpb=d614ac869e77fda0627a0814e49f7b129ac4dcdd;p=neverball diff --git a/share/solid.c b/share/solid.c index 9b4e8c3..467da87 100644 --- a/share/solid.c +++ b/share/solid.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2003 Robert Kooima * * NEVERBALL is free software; you can redistribute it and/or modify @@ -23,14 +23,14 @@ #include "glext.h" #include "vec3.h" -#include "geom.h" -#include "image.h" +#include "geom.h" /* Only for height constants! */ +#include "base_image.h" #include "solid.h" #include "base_config.h" #include "binary.h" -#define MAGIC 0x4F425251 /* Neverball sol file magic number (should not change) */ -#define SOL_VERSION 1 /* Neverball sol file format version (can change) */ +#define MAGIC 0x4c4f53af +#define SOL_VERSION 6 #define LARGE 1.0e+5f @@ -68,9 +68,9 @@ static void sol_body_v(float v[3], } } -static void sol_body_p(float p[3], - const struct s_file *fp, - const struct s_body *bp) +void sol_body_p(float p[3], + const struct s_file *fp, + const struct s_body *bp) { float v[3]; @@ -92,560 +92,6 @@ static void sol_body_p(float p[3], /*---------------------------------------------------------------------------*/ -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; -} - -/*---------------------------------------------------------------------------*/ - -static void sol_draw_mtrl(const struct s_file *fp, int i) -{ - const struct s_mtrl *mp = fp->mv + i; - - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mp->a); - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->d); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mp->s); - glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mp->e); - glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mp->h); - - if (mp->fl & M_ENVIRONMENT) - { - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - - glBindTexture(GL_TEXTURE_2D, mp->o); - - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - } - else - { - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - - glBindTexture(GL_TEXTURE_2D, mp->o); - } - - if (mp->fl & M_ADDITIVE) - glBlendFunc(GL_ONE, GL_ONE); - else - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - -} - -static void sol_draw_bill(const struct s_file *fp, - const struct s_bill *rp, float t) -{ - float T = fmodf(t, rp->t) - rp->t / 2; - - 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); - - sol_draw_mtrl(fp, rp->mi); - - glBegin(GL_QUADS); - { - glTexCoord2f(0.0f, 1.0f); glVertex2f(-w / 2, y0); - glTexCoord2f(1.0f, 1.0f); glVertex2f(+w / 2, y0); - glTexCoord2f(1.0f, 0.0f); glVertex2f(+w / 2, y1); - glTexCoord2f(0.0f, 0.0f); glVertex2f(-w / 2, y1); - } - glEnd(); - } - glPopMatrix(); - } -} - -void sol_back(const struct s_file *fp, float n, float f, float t) -{ - int ri; - - glPushAttrib(GL_LIGHTING_BIT | GL_DEPTH_BUFFER_BIT); - { - /* 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) - sol_draw_bill(fp, fp->rv + ri, t); - } - glPopAttrib(); -} - -/*---------------------------------------------------------------------------*/ -/* - * 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 void sol_draw_body(const struct s_file *fp, - const struct s_body *bp, int fl) -{ - int mi, li, gi; - - /* Iterate all materials of the correct opacity. */ - - for (mi = 0; mi < fp->mc; mi++) - if (fp->mv[mi].fl & fl) - { - if (sol_enum_mtrl(fp, bp, mi)) - { - /* Set the material state. */ - - sol_draw_mtrl(fp, mi); - - /* 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(); - } - } -} - -static void sol_draw_list(const struct s_file *fp, - const struct s_body *bp, GLuint list) -{ - float p[3]; - - sol_body_p(p, fp, bp); - - glPushMatrix(); - { - /* Translate a moving body. */ - - glTranslatef(p[0], p[1], p[2]); - - /* Draw the body. */ - - glCallList(list); - } - glPopMatrix(); -} - -void sol_draw(const struct s_file *fp) -{ - int bi; - - glPushAttrib(GL_TEXTURE_BIT | - GL_LIGHTING_BIT | - GL_COLOR_BUFFER_BIT | - GL_DEPTH_BUFFER_BIT); - { - /* Render all obaque 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. */ - - glDepthMask(GL_FALSE); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - for (bi = 0; bi < fp->bc; bi++) - if (fp->bv[bi].tl) - sol_draw_list(fp, fp->bv + bi, fp->bv[bi].tl); - } - glPopAttrib(); -} - -void sol_refl(const struct s_file *fp) -{ - int bi; - - glPushAttrib(GL_LIGHTING_BIT); - { - /* Render all reflective geometry into the color and depth buffers. */ - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - for (bi = 0; bi < fp->bc; bi++) - if (fp->bv[bi].rl) - sol_draw_list(fp, fp->bv + bi, fp->bv[bi].rl); - } - glPopAttrib(); -} - -/*---------------------------------------------------------------------------*/ - -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 mi, li, gi; - - glBegin(GL_TRIANGLES); - { - for (mi = 0; mi < fp->mc; mi++) - if (fp->mv[mi].fl & fl) - { - 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(); -} - -static void sol_shad_list(const struct s_file *fp, - const struct s_body *bp, GLuint list) -{ - float p[3]; - - sol_body_p(p, fp, bp); - - glPushMatrix(); - { - /* Translate a moving body. */ - - glTranslatef(p[0], p[1], p[2]); - - /* Translate the shadow on a moving body. */ - - glMatrixMode(GL_TEXTURE); - { - glPushMatrix(); - glTranslatef(p[0], p[2], 0.0f); - } - 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; - - glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_LIGHTING_BIT); - { - /* Render all shadowed geometry. */ - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDepthFunc(GL_LEQUAL); - 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); - } - glPopAttrib(); -} - -/*---------------------------------------------------------------------------*/ - -static void sol_load_objects(struct s_file *fp, int s) -{ - int i; - - for (i = 0; i < fp->bc; i++) - { - struct s_body *bp = fp->bv + i; - - /* Draw all opaque geometry. */ - - if (sol_enum_body(fp, bp, M_OPAQUE | M_ENVIRONMENT)) - { - fp->bv[i].ol = glGenLists(1); - - glNewList(fp->bv[i].ol, GL_COMPILE); - { - sol_draw_body(fp, fp->bv + i, M_OPAQUE | M_ENVIRONMENT); - } - glEndList(); - } - else fp->bv[i].ol = 0; - - /* Draw all translucent geometry. */ - - if (sol_enum_body(fp, bp, M_TRANSPARENT)) - { - fp->bv[i].tl = glGenLists(1); - - glNewList(fp->bv[i].tl, GL_COMPILE); - { - sol_draw_body(fp, fp->bv + i, M_TRANSPARENT); - } - glEndList(); - } - else fp->bv[i].tl = 0; - - /* Draw all reflective geometry. */ - - if (sol_enum_body(fp, bp, M_REFLECTIVE)) - { - fp->bv[i].rl = glGenLists(1); - - glNewList(fp->bv[i].rl, GL_COMPILE); - { - sol_draw_body(fp, fp->bv + i, M_REFLECTIVE); - } - glEndList(); - } - else fp->bv[i].rl = 0; - - /* Draw all shadowed geometry. */ - - if (s && sol_enum_body(fp, bp, M_SHADOWED)) - { - fp->bv[i].sl = glGenLists(1); - - glNewList(fp->bv[i].sl, GL_COMPILE); - { - sol_shad_body(fp, fp->bv + i, M_SHADOWED); - } - glEndList(); - } - else fp->bv[i].sl = 0; - } -} - -static SDL_Surface *sol_find_texture(const char *name) -{ - char png[MAXSTR]; - char tga[MAXSTR]; - char jpg[MAXSTR]; - SDL_Surface *s; - - /* Prefer a lossless copy of the texture over a lossy compression. */ - - strncpy(png, name, PATHMAX); strcat(png, ".png"); - strncpy(tga, name, PATHMAX); strcat(tga, ".tga"); - strncpy(jpg, name, PATHMAX); strcat(jpg, ".jpg"); - - /* Check for a PNG. */ - - if ((s = IMG_Load(config_data(png)))) - return s; - - /* Check for a TGA, swapping channels if found. */ - - if ((s = IMG_Load(config_data(tga)))) - { - image_swab(s); - return s; - } - - /* Check for a JPG. */ - - if ((s = IMG_Load(config_data(jpg)))) - return s; - - return NULL; -} - -static void sol_load_textures(struct s_file *fp, int k) -{ - SDL_Surface *s; - SDL_Surface *d; - - int i; - - for (i = 0; i < fp->mc; i++) - if ((s = sol_find_texture(fp->mv[i].f))) - { - GLenum f = (s->format->BitsPerPixel == 32) ? GL_RGBA : GL_RGB; - - glGenTextures(1, &fp->mv[i].o); - glBindTexture(GL_TEXTURE_2D, fp->mv[i].o); - - if (k > 1) - { - /* Create a new buffer and copy the scaled image to it. */ - - if ((d = image_scale(s, k))) - { - glTexImage2D(GL_TEXTURE_2D, 0, f, d->w, d->h, 0, f, - GL_UNSIGNED_BYTE, d->pixels); - SDL_FreeSurface(d); - } - } - else - glTexImage2D(GL_TEXTURE_2D, 0, f, s->w, s->h, 0, f, - GL_UNSIGNED_BYTE, s->pixels); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - /* 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); - } - - SDL_FreeSurface(s); - } -} - -/*---------------------------------------------------------------------------*/ - static void sol_load_mtrl(FILE *fin, struct s_mtrl *mp) { get_array(fin, mp->a, 4); @@ -734,16 +180,19 @@ static void sol_load_body(FILE *fin, struct s_body *bp) get_index(fin, &bp->gc); } -static void sol_load_coin(FILE *fin, struct s_coin *cp) +static void sol_load_item(FILE *fin, struct s_item *hp) { - get_array(fin, cp->p, 3); - get_index(fin, &cp->n); + get_array(fin, hp->p, 3); + get_index(fin, &hp->t); + get_index(fin, &hp->n); } static void sol_load_goal(FILE *fin, struct s_goal *zp) { get_array(fin, zp->p, 3); get_float(fin, &zp->r); + get_index(fin, &zp->s); + get_index(fin, &zp->c); } static void sol_load_swch(FILE *fin, struct s_swch *xp) @@ -755,6 +204,7 @@ static void sol_load_swch(FILE *fin, struct s_swch *xp) get_float(fin, &xp->t); get_index(fin, &xp->f0); get_index(fin, &xp->f); + get_index(fin, &xp->i); } static void sol_load_bill(FILE *fin, struct s_bill *rp) @@ -800,9 +250,11 @@ static int sol_load_file(FILE *fin, struct s_file *fp) get_index(fin, &magic); get_index(fin, &version); + if (magic != MAGIC || version != SOL_VERSION) return 0; + get_index(fin, &fp->ac); get_index(fin, &fp->mc); get_index(fin, &fp->vc); get_index(fin, &fp->ec); @@ -813,7 +265,7 @@ static int sol_load_file(FILE *fin, struct s_file *fp) get_index(fin, &fp->nc); get_index(fin, &fp->pc); get_index(fin, &fp->bc); - get_index(fin, &fp->cc); + get_index(fin, &fp->hc); get_index(fin, &fp->zc); get_index(fin, &fp->jc); get_index(fin, &fp->xc); @@ -821,8 +273,9 @@ static int sol_load_file(FILE *fin, struct s_file *fp) get_index(fin, &fp->uc); get_index(fin, &fp->wc); get_index(fin, &fp->ic); - get_index(fin, &fp->ac); + 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) @@ -843,8 +296,8 @@ static int sol_load_file(FILE *fin, struct s_file *fp) 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->cc) - fp->cv = (struct s_coin *) calloc(fp->cc, sizeof (struct s_coin)); + 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) @@ -859,8 +312,9 @@ static int sol_load_file(FILE *fin, struct s_file *fp) fp->wv = (struct s_view *) calloc(fp->wc, sizeof (struct s_view)); if (fp->ic) fp->iv = (int *) calloc(fp->ic, sizeof (int)); + if (fp->ac) - fp->av = (char *) calloc(fp->ac, sizeof (char)); + fread(fp->av, 1, fp->ac, fin); 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); @@ -872,7 +326,7 @@ static int sol_load_file(FILE *fin, struct s_file *fp) 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->cc; i++) sol_load_coin(fin, fp->cv + 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); @@ -881,8 +335,50 @@ static int sol_load_file(FILE *fin, struct s_file *fp) 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); - if (fp->ac) fread(fp->av, 1, fp->ac, fin); - + return 1; +} + +static int sol_load_head(FILE *fin, struct s_file *fp) +{ + int magic; + int version; + + get_index(fin, &magic); + get_index(fin, &version); + + if (magic != MAGIC || version != SOL_VERSION) + return 0; + + get_index(fin, &fp->ac); + +#if 0 + 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); +#endif + fseek(fin, 18 * 4, SEEK_CUR); + + if (fp->ac) + { + fp->av = (char *) calloc(fp->ac, sizeof (char)); + fread(fp->av, 1, fp->ac, fin); + } + return 1; } @@ -899,20 +395,14 @@ int sol_load_only_file(struct s_file *fp, const char *filename) return res; } -int sol_load(struct s_file *fp, const char *filename, int k, int s) +int sol_load_only_head(struct s_file *fp, const char *filename) { FILE *fin; int res = 0; if ((fin = fopen(filename, FMODE_RB))) { - if (sol_load_file(fin, fp)) - { - res = 1; - sol_load_textures(fp, k); - sol_load_objects (fp, s); - } - + res = sol_load_head(fin, fp); fclose(fin); } return res; @@ -1008,16 +498,19 @@ static void sol_stor_body(FILE *fout, struct s_body *bp) put_index(fout, &bp->gc); } -static void sol_stor_coin(FILE *fout, struct s_coin *cp) +static void sol_stor_item(FILE *fout, struct s_item *hp) { - put_array(fout, cp->p, 3); - put_index(fout, &cp->n); + put_array(fout, hp->p, 3); + put_index(fout, &hp->t); + put_index(fout, &hp->n); } static void sol_stor_goal(FILE *fout, struct s_goal *zp) { put_array(fout, zp->p, 3); put_float(fout, &zp->r); + put_index(fout, &zp->s); + put_index(fout, &zp->c); } static void sol_stor_swch(FILE *fout, struct s_swch *xp) @@ -1029,6 +522,7 @@ static void sol_stor_swch(FILE *fout, struct s_swch *xp) 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(FILE *fout, struct s_bill *rp) @@ -1074,7 +568,8 @@ static void sol_stor_file(FILE *fin, struct s_file *fp) put_index(fin, &magic); put_index(fin, &version); - + + put_index(fin, &fp->ac); put_index(fin, &fp->mc); put_index(fin, &fp->vc); put_index(fin, &fp->ec); @@ -1085,7 +580,7 @@ static void sol_stor_file(FILE *fin, struct s_file *fp) put_index(fin, &fp->nc); put_index(fin, &fp->pc); put_index(fin, &fp->bc); - put_index(fin, &fp->cc); + put_index(fin, &fp->hc); put_index(fin, &fp->zc); put_index(fin, &fp->jc); put_index(fin, &fp->xc); @@ -1093,8 +588,8 @@ static void sol_stor_file(FILE *fin, struct s_file *fp) put_index(fin, &fp->uc); put_index(fin, &fp->wc); put_index(fin, &fp->ic); - put_index(fin, &fp->ac); + fwrite(fp->av, 1, fp->ac, fin); for (i = 0; i < fp->mc; i++) sol_stor_mtrl(fin, fp->mv + i); for (i = 0; i < fp->vc; i++) sol_stor_vert(fin, fp->vv + i); for (i = 0; i < fp->ec; i++) sol_stor_edge(fin, fp->ev + i); @@ -1105,7 +600,7 @@ static void sol_stor_file(FILE *fin, struct s_file *fp) for (i = 0; i < fp->nc; i++) sol_stor_node(fin, fp->nv + i); for (i = 0; i < fp->pc; i++) sol_stor_path(fin, fp->pv + i); for (i = 0; i < fp->bc; i++) sol_stor_body(fin, fp->bv + i); - for (i = 0; i < fp->cc; i++) sol_stor_coin(fin, fp->cv + i); + for (i = 0; i < fp->hc; i++) sol_stor_item(fin, fp->hv + i); for (i = 0; i < fp->zc; i++) sol_stor_goal(fin, fp->zv + i); for (i = 0; i < fp->jc; i++) sol_stor_jump(fin, fp->jv + i); for (i = 0; i < fp->xc; i++) sol_stor_swch(fin, fp->xv + i); @@ -1113,8 +608,6 @@ static void sol_stor_file(FILE *fin, struct s_file *fp) for (i = 0; i < fp->uc; i++) sol_stor_ball(fin, fp->uv + i); for (i = 0; i < fp->wc; i++) sol_stor_view(fin, fp->wv + i); for (i = 0; i < fp->ic; i++) put_index(fin, fp->iv + i); - - fwrite(fp->av, 1, fp->ac, fin); } /*---------------------------------------------------------------------------*/ @@ -1135,24 +628,6 @@ int sol_stor(struct s_file *fp, const char *filename) void sol_free(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 (fp->mv) free(fp->mv); if (fp->vv) free(fp->vv); if (fp->ev) free(fp->ev); @@ -1163,7 +638,7 @@ void sol_free(struct s_file *fp) if (fp->nv) free(fp->nv); if (fp->pv) free(fp->pv); if (fp->bv) free(fp->bv); - if (fp->cv) free(fp->cv); + if (fp->hc) free(fp->hv); if (fp->zv) free(fp->zv); if (fp->jv) free(fp->jv); if (fp->xv) free(fp->xv); @@ -1366,7 +841,7 @@ static float sol_bounce(struct s_ball *up, v_mad(u, w, n, -wn); v_mad(v, v, n, -vn); v_mad(v, v, u, +km * dt); - v_mad(v, v, n, xn + yn); + v_mad(v, v, n, xn + yn); v_mad(p, q, n, up->r); @@ -1606,7 +1081,8 @@ static float sol_test_lump(float dt, const float o[3], const float w[3]) { - float U[3], u, t = dt; + float U[3] = {0.0f, 0.0f, 0.0f}; /* init value only to avoid gcc warnings */ + float u, t = dt; int i; /* Short circuit a non-solid lump. */ @@ -1626,7 +1102,7 @@ static float sol_test_lump(float dt, t = u; } } - + /* Test all edges */ if (up->r > 0.0f) @@ -1837,36 +1313,34 @@ float sol_step(struct s_file *fp, const float *g, float dt, int ui, int *m) /*---------------------------------------------------------------------------*/ -int sol_coin_test(struct s_file *fp, float *p, float coin_r) +struct s_item *sol_item_test(struct s_file *fp, float *p, float item_r) { const float *ball_p = fp->uv->p; const float ball_r = fp->uv->r; - int ci, n; - for (ci = 0; ci < fp->cc; ci++) + int hi; + + for (hi = 0; hi < fp->hc; hi++) { float r[3]; - r[0] = ball_p[0] - fp->cv[ci].p[0]; - r[1] = ball_p[1] - fp->cv[ci].p[1]; - r[2] = ball_p[2] - fp->cv[ci].p[2]; + r[0] = ball_p[0] - fp->hv[hi].p[0]; + r[1] = ball_p[1] - fp->hv[hi].p[1]; + r[2] = ball_p[2] - fp->hv[hi].p[2]; - if (fp->cv[ci].n > 0 && v_len(r) < ball_r + coin_r) + if (fp->hv[hi].t != ITEM_NONE && v_len(r) < ball_r + item_r) { - p[0] = fp->cv[ci].p[0]; - p[1] = fp->cv[ci].p[1]; - p[2] = fp->cv[ci].p[2]; - - n = fp->cv[ci].n; - fp->cv[ci].n = 0; + p[0] = fp->hv[hi].p[0]; + p[1] = fp->hv[hi].p[1]; + p[2] = fp->hv[hi].p[2]; - return n; + return &fp->hv[hi]; } } - return 0; + return NULL; } -int sol_goal_test(struct s_file *fp, float *p, int ui) +struct s_goal *sol_goal_test(struct s_file *fp, float *p, int ui) { const float *ball_p = fp->uv[ui].p; const float ball_r = fp->uv[ui].r; @@ -1888,17 +1362,23 @@ int sol_goal_test(struct s_file *fp, float *p, int ui) p[1] = fp->zv[zi].p[1]; p[2] = fp->zv[zi].p[2]; - return 1; + return &fp->zv[zi]; } } - return 0; + return NULL; } int sol_jump_test(struct s_file *fp, float *p, int ui) +/* Test if the ball ui is inside a jump. */ +/* Return 1 if yes and fill p with the destination position. */ +/* Return 0 if no. */ +/* Return 2 if the ball is on the border of a jump. */ { const float *ball_p = fp->uv[ui].p; const float ball_r = fp->uv[ui].r; int ji; + float l; + int res = 0; for (ji = 0; ji < fp->jc; ji++) { @@ -1908,26 +1388,36 @@ int sol_jump_test(struct s_file *fp, float *p, int ui) r[1] = ball_p[2] - fp->jv[ji].p[2]; r[2] = 0; - if (v_len(r) < fp->jv[ji].r - ball_r && + l = v_len(r) - fp->jv[ji].r; + if (l < 0 && ball_p[1] > fp->jv[ji].p[1] && ball_p[1] < fp->jv[ji].p[1] + JUMP_HEIGHT / 2) { - p[0] = fp->jv[ji].q[0] + (ball_p[0] - fp->jv[ji].p[0]); - p[1] = fp->jv[ji].q[1] + (ball_p[1] - fp->jv[ji].p[1]); - p[2] = fp->jv[ji].q[2] + (ball_p[2] - fp->jv[ji].p[2]); + if (l < - ball_r ) + { + p[0] = fp->jv[ji].q[0] + (ball_p[0] - fp->jv[ji].p[0]); + p[1] = fp->jv[ji].q[1] + (ball_p[1] - fp->jv[ji].p[1]); + p[2] = fp->jv[ji].q[2] + (ball_p[2] - fp->jv[ji].p[2]); - return 1; + return 1; + } + else + res = 2; } } - return 0; + return res; } -int sol_swch_test(struct s_file *fp, int flag, int ui) +int sol_swch_test(struct s_file *fp, int ui) +/* In the SOL fp, test and process the event the ball ui enters a switch. + * Return 1 if a visible switch is activated, return 0 otherwise (no switch is + * activated or only invisible switchs) */ { const float *ball_p = fp->uv[ui].p; const float ball_r = fp->uv[ui].r; int xi; - int f = 1; + float l; + int res = 0; /* result */ for (xi = 0; xi < fp->xc; xi++) { @@ -1941,15 +1431,20 @@ int sol_swch_test(struct s_file *fp, int flag, int ui) r[1] = ball_p[2] - xp->p[2]; r[2] = 0; - if (v_len(r) < xp->r - ball_r && + l = v_len(r) - xp->r; + if (l < ball_r && ball_p[1] > xp->p[1] && ball_p[1] < xp->p[1] + SWCH_HEIGHT / 2) { - if (flag) + if (!xp->e && l < - ball_r) { int pi = xp->pi; int pj = xp->pi; + /* The ball enter */ + if (xp->t0 == 0) + xp->e = 1; + /* Toggle the state, update the path. */ xp->f = xp->f ? 0 : 1; @@ -1969,12 +1464,18 @@ int sol_swch_test(struct s_file *fp, int flag, int ui) if (xp->f != xp->f0) xp->t = xp->t0; + + /* If visible, set the result */ + if (!xp->i) + res = 1; } - f = 0; } + else if (xp->e) + /* A ball go out */ + xp->e = 0; } } - return f; + return res; } /*---------------------------------------------------------------------------*/