X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=libs%2Fpicomodel%2Flwo%2Flwob.c;h=3ae40b43e66974cdaf5a81f39ae267359fb519d9;hb=830125fad042fad35dc029b6eb57c8156ad7e176;hp=edf42cff06088aad197f7e82a123f41ac9441a32;hpb=5265d3cc1517566910718738ee6fa48e2466d3ea;p=xonotic%2Fnetradiant.git diff --git a/libs/picomodel/lwo/lwob.c b/libs/picomodel/lwo/lwob.c index edf42cff..3ae40b43 100644 --- a/libs/picomodel/lwo/lwob.c +++ b/libs/picomodel/lwo/lwob.c @@ -1,12 +1,12 @@ /* -====================================================================== -lwob.c + ====================================================================== + lwob.c -Functions for an LWOB reader. LWOB is the LightWave object format -for versions of LW prior to 6.0. + Functions for an LWOB reader. LWOB is the LightWave object format + for versions of LW prior to 6.0. -Ernie Wright 17 Sep 00 -====================================================================== */ + Ernie Wright 17 Sep 00 + ====================================================================== */ #include "../picointernal.h" #include "lwo2.h" @@ -19,705 +19,800 @@ Ernie Wright 17 Sep 00 /* IDs specific to LWOB */ -#define ID_SRFS LWID_('S','R','F','S') -#define ID_FLAG LWID_('F','L','A','G') -#define ID_VLUM LWID_('V','L','U','M') -#define ID_VDIF LWID_('V','D','I','F') -#define ID_VSPC LWID_('V','S','P','C') -#define ID_RFLT LWID_('R','F','L','T') -#define ID_BTEX LWID_('B','T','E','X') -#define ID_CTEX LWID_('C','T','E','X') -#define ID_DTEX LWID_('D','T','E','X') -#define ID_LTEX LWID_('L','T','E','X') -#define ID_RTEX LWID_('R','T','E','X') -#define ID_STEX LWID_('S','T','E','X') -#define ID_TTEX LWID_('T','T','E','X') -#define ID_TFLG LWID_('T','F','L','G') -#define ID_TSIZ LWID_('T','S','I','Z') -#define ID_TCTR LWID_('T','C','T','R') -#define ID_TFAL LWID_('T','F','A','L') -#define ID_TVEL LWID_('T','V','E','L') -#define ID_TCLR LWID_('T','C','L','R') -#define ID_TVAL LWID_('T','V','A','L') -#define ID_TAMP LWID_('T','A','M','P') -#define ID_TIMG LWID_('T','I','M','G') -#define ID_TAAS LWID_('T','A','A','S') -#define ID_TREF LWID_('T','R','E','F') -#define ID_TOPC LWID_('T','O','P','C') -#define ID_SDAT LWID_('S','D','A','T') -#define ID_TFP0 LWID_('T','F','P','0') -#define ID_TFP1 LWID_('T','F','P','1') +#define ID_SRFS LWID_( 'S','R','F','S' ) +#define ID_FLAG LWID_( 'F','L','A','G' ) +#define ID_VLUM LWID_( 'V','L','U','M' ) +#define ID_VDIF LWID_( 'V','D','I','F' ) +#define ID_VSPC LWID_( 'V','S','P','C' ) +#define ID_RFLT LWID_( 'R','F','L','T' ) +#define ID_BTEX LWID_( 'B','T','E','X' ) +#define ID_CTEX LWID_( 'C','T','E','X' ) +#define ID_DTEX LWID_( 'D','T','E','X' ) +#define ID_LTEX LWID_( 'L','T','E','X' ) +#define ID_RTEX LWID_( 'R','T','E','X' ) +#define ID_STEX LWID_( 'S','T','E','X' ) +#define ID_TTEX LWID_( 'T','T','E','X' ) +#define ID_TFLG LWID_( 'T','F','L','G' ) +#define ID_TSIZ LWID_( 'T','S','I','Z' ) +#define ID_TCTR LWID_( 'T','C','T','R' ) +#define ID_TFAL LWID_( 'T','F','A','L' ) +#define ID_TVEL LWID_( 'T','V','E','L' ) +#define ID_TCLR LWID_( 'T','C','L','R' ) +#define ID_TVAL LWID_( 'T','V','A','L' ) +#define ID_TAMP LWID_( 'T','A','M','P' ) +#define ID_TIMG LWID_( 'T','I','M','G' ) +#define ID_TAAS LWID_( 'T','A','A','S' ) +#define ID_TREF LWID_( 'T','R','E','F' ) +#define ID_TOPC LWID_( 'T','O','P','C' ) +#define ID_SDAT LWID_( 'S','D','A','T' ) +#define ID_TFP0 LWID_( 'T','F','P','0' ) +#define ID_TFP1 LWID_( 'T','F','P','1' ) /* -====================================================================== -add_clip() - -Add a clip to the clip list. Used to store the contents of an RIMG or -TIMG surface subchunk. -====================================================================== */ - -static int add_clip( char *s, lwClip **clist, int *nclips ) -{ - lwClip *clip; - char *p; - - clip = _pico_calloc( 1, sizeof( lwClip )); - if ( !clip ) return 0; - - clip->contrast.val = 1.0f; - clip->brightness.val = 1.0f; - clip->saturation.val = 1.0f; - clip->gamma.val = 1.0f; - - if ( p = strstr( s, "(sequence)" )) { - p[ -1 ] = 0; - clip->type = ID_ISEQ; - clip->source.seq.prefix = s; - clip->source.seq.digits = 3; - } - else { - clip->type = ID_STIL; - clip->source.still.name = s; - } - - *nclips++; - clip->index = *nclips; - - lwListAdd( clist, clip ); - - return clip->index; + ====================================================================== + add_clip() + + Add a clip to the clip list. Used to store the contents of an RIMG or + TIMG surface subchunk. + ====================================================================== */ + +static int add_clip( char *s, lwClip **clist, int *nclips ){ + lwClip *clip; + char *p; + + clip = _pico_calloc( 1, sizeof( lwClip ) ); + if ( !clip ) { + return 0; + } + + clip->contrast.val = 1.0f; + clip->brightness.val = 1.0f; + clip->saturation.val = 1.0f; + clip->gamma.val = 1.0f; + + if ( ( p = strstr( s, "(sequence)" ) ) != NULL ) { + p[ -1 ] = 0; + clip->type = ID_ISEQ; + clip->source.seq.prefix = s; + clip->source.seq.digits = 3; + } + else { + clip->type = ID_STIL; + clip->source.still.name = s; + } + + ( *nclips )++; + clip->index = *nclips; + + lwListAdd( clist, clip ); + + return clip->index; } /* -====================================================================== -add_tvel() - -Add a triple of envelopes to simulate the old texture velocity -parameters. -====================================================================== */ - -static int add_tvel( float pos[], float vel[], lwEnvelope **elist, int *nenvs ) -{ - lwEnvelope *env; - lwKey *key0, *key1; - int i; - - for ( i = 0; i < 3; i++ ) { - env = _pico_calloc( 1, sizeof( lwEnvelope )); - key0 = _pico_calloc( 1, sizeof( lwKey )); - key1 = _pico_calloc( 1, sizeof( lwKey )); - if ( !env || !key0 || !key1 ) return 0; - - key0->next = key1; - key0->value = pos[ i ]; - key0->time = 0.0f; - key1->prev = key0; - key1->value = pos[ i ] + vel[ i ] * 30.0f; - key1->time = 1.0f; - key0->shape = key1->shape = ID_LINE; - - env->index = *nenvs + i + 1; - env->type = 0x0301 + i; - env->name = _pico_alloc( 11 ); - if ( env->name ) { - strcpy( env->name, "Position.X" ); - env->name[ 9 ] += i; - } - env->key = key0; - env->nkeys = 2; - env->behavior[ 0 ] = BEH_LINEAR; - env->behavior[ 1 ] = BEH_LINEAR; - - lwListAdd( elist, env ); - } - - *nenvs += 3; - return env->index - 2; + ====================================================================== + add_tvel() + + Add a triple of envelopes to simulate the old texture velocity + parameters. + ====================================================================== */ + +static int add_tvel( float pos[], float vel[], lwEnvelope **elist, int *nenvs ){ + lwEnvelope *env; + lwKey *key0, *key1; + int i; + + for ( i = 0; i < 3; i++ ) { + env = _pico_calloc( 1, sizeof( lwEnvelope ) ); + key0 = _pico_calloc( 1, sizeof( lwKey ) ); + key1 = _pico_calloc( 1, sizeof( lwKey ) ); + if ( !env || !key0 || !key1 ) { + return 0; + } + + key0->next = key1; + key0->value = pos[ i ]; + key0->time = 0.0f; + key1->prev = key0; + key1->value = pos[ i ] + vel[ i ] * 30.0f; + key1->time = 1.0f; + key0->shape = key1->shape = ID_LINE; + + env->index = *nenvs + i + 1; + env->type = 0x0301 + i; + env->name = _pico_alloc( 11 ); + if ( env->name ) { + strcpy( env->name, "Position.X" ); + env->name[ 9 ] += i; + } + env->key = key0; + env->nkeys = 2; + env->behavior[ 0 ] = BEH_LINEAR; + env->behavior[ 1 ] = BEH_LINEAR; + + lwListAdd( elist, env ); + } + + *nenvs += 3; + return env->index - 2; } /* -====================================================================== -get_texture() - -Create a new texture for BTEX, CTEX, etc. subchunks. -====================================================================== */ - -static lwTexture *get_texture( char *s ) -{ - lwTexture *tex; - - tex = _pico_calloc( 1, sizeof( lwTexture )); - if ( !tex ) return NULL; - - tex->tmap.size.val[ 0 ] = - tex->tmap.size.val[ 1 ] = - tex->tmap.size.val[ 2 ] = 1.0f; - tex->opacity.val = 1.0f; - tex->enabled = 1; - - if ( strstr( s, "Image Map" )) { - tex->type = ID_IMAP; - if ( strstr( s, "Planar" )) tex->param.imap.projection = 0; - else if ( strstr( s, "Cylindrical" )) tex->param.imap.projection = 1; - else if ( strstr( s, "Spherical" )) tex->param.imap.projection = 2; - else if ( strstr( s, "Cubic" )) tex->param.imap.projection = 3; - else if ( strstr( s, "Front" )) tex->param.imap.projection = 4; - tex->param.imap.aa_strength = 1.0f; - tex->param.imap.amplitude.val = 1.0f; - _pico_free( s ); - } - else { - tex->type = ID_PROC; - tex->param.proc.name = s; - } - - return tex; + ====================================================================== + get_texture() + + Create a new texture for BTEX, CTEX, etc. subchunks. + ====================================================================== */ + +static lwTexture *get_texture( char *s ){ + lwTexture *tex; + + tex = _pico_calloc( 1, sizeof( lwTexture ) ); + if ( !tex ) { + return NULL; + } + + tex->tmap.size.val[ 0 ] = + tex->tmap.size.val[ 1 ] = + tex->tmap.size.val[ 2 ] = 1.0f; + tex->opacity.val = 1.0f; + tex->enabled = 1; + + if ( strstr( s, "Image Map" ) ) { + tex->type = ID_IMAP; + if ( strstr( s, "Planar" ) ) { + tex->param.imap.projection = 0; + } + else if ( strstr( s, "Cylindrical" ) ) { + tex->param.imap.projection = 1; + } + else if ( strstr( s, "Spherical" ) ) { + tex->param.imap.projection = 2; + } + else if ( strstr( s, "Cubic" ) ) { + tex->param.imap.projection = 3; + } + else if ( strstr( s, "Front" ) ) { + tex->param.imap.projection = 4; + } + tex->param.imap.aa_strength = 1.0f; + tex->param.imap.amplitude.val = 1.0f; + _pico_free( s ); + } + else { + tex->type = ID_PROC; + tex->param.proc.name = s; + } + + return tex; } /* -====================================================================== -lwGetSurface5() - -Read an lwSurface from an LWOB file. -====================================================================== */ - -lwSurface *lwGetSurface5( picoMemStream_t *fp, int cksize, lwObject *obj ) -{ - lwSurface *surf; - lwTexture *tex; - lwPlugin *shdr; - char *s; - float v[ 3 ]; - unsigned int id, flags; - unsigned short sz; - int pos, rlen, i; - - - /* allocate the Surface structure */ - - surf = _pico_calloc( 1, sizeof( lwSurface )); - if ( !surf ) goto Fail; - - /* non-zero defaults */ - - surf->color.rgb[ 0 ] = 0.78431f; - surf->color.rgb[ 1 ] = 0.78431f; - surf->color.rgb[ 2 ] = 0.78431f; - surf->diffuse.val = 1.0f; - surf->glossiness.val = 0.4f; - surf->bump.val = 1.0f; - surf->eta.val = 1.0f; - surf->sideflags = 1; - - /* remember where we started */ - - set_flen( 0 ); - pos = _pico_memstream_tell( fp ); - - /* name */ - - surf->name = getS0( fp ); - - /* first subchunk header */ - - id = getU4( fp ); - sz = getU2( fp ); - if ( 0 > get_flen() ) goto Fail; - - /* process subchunks as they're encountered */ - - while ( 1 ) { - sz += sz & 1; - set_flen( 0 ); - - switch ( id ) { - case ID_COLR: - surf->color.rgb[ 0 ] = getU1( fp ) / 255.0f; - surf->color.rgb[ 1 ] = getU1( fp ) / 255.0f; - surf->color.rgb[ 2 ] = getU1( fp ) / 255.0f; - break; - - case ID_FLAG: - flags = getU2( fp ); - if ( flags & 4 ) surf->smooth = 1.56207f; - if ( flags & 8 ) surf->color_hilite.val = 1.0f; - if ( flags & 16 ) surf->color_filter.val = 1.0f; - if ( flags & 128 ) surf->dif_sharp.val = 0.5f; - if ( flags & 256 ) surf->sideflags = 3; - if ( flags & 512 ) surf->add_trans.val = 1.0f; - break; - - case ID_LUMI: - surf->luminosity.val = getI2( fp ) / 256.0f; - break; - - case ID_VLUM: - surf->luminosity.val = getF4( fp ); - break; - - case ID_DIFF: - surf->diffuse.val = getI2( fp ) / 256.0f; - break; - - case ID_VDIF: - surf->diffuse.val = getF4( fp ); - break; - - case ID_SPEC: - surf->specularity.val = getI2( fp ) / 256.0f; - break; - - case ID_VSPC: - surf->specularity.val = getF4( fp ); - break; - - case ID_GLOS: - surf->glossiness.val = ( float ) log( getU2( fp )) / 20.7944f; - break; - - case ID_SMAN: - surf->smooth = getF4( fp ); - break; - - case ID_REFL: - surf->reflection.val.val = getI2( fp ) / 256.0f; - break; - - case ID_RFLT: - surf->reflection.options = getU2( fp ); - break; - - case ID_RIMG: - s = getS0( fp ); - surf->reflection.cindex = add_clip( s, &obj->clip, &obj->nclips ); - surf->reflection.options = 3; - break; - - case ID_RSAN: - surf->reflection.seam_angle = getF4( fp ); - break; - - case ID_TRAN: - surf->transparency.val.val = getI2( fp ) / 256.0f; - break; - - case ID_RIND: - surf->eta.val = getF4( fp ); - break; - - case ID_BTEX: - s = getbytes( fp, sz ); - tex = get_texture( s ); - lwListAdd( &surf->bump.tex, tex ); - break; - - case ID_CTEX: - s = getbytes( fp, sz ); - tex = get_texture( s ); - lwListAdd( &surf->color.tex, tex ); - break; - - case ID_DTEX: - s = getbytes( fp, sz ); - tex = get_texture( s ); - lwListAdd( &surf->diffuse.tex, tex ); - break; - - case ID_LTEX: - s = getbytes( fp, sz ); - tex = get_texture( s ); - lwListAdd( &surf->luminosity.tex, tex ); - break; - - case ID_RTEX: - s = getbytes( fp, sz ); - tex = get_texture( s ); - lwListAdd( &surf->reflection.val.tex, tex ); - break; - - case ID_STEX: - s = getbytes( fp, sz ); - tex = get_texture( s ); - lwListAdd( &surf->specularity.tex, tex ); - break; - - case ID_TTEX: - s = getbytes( fp, sz ); - tex = get_texture( s ); - lwListAdd( &surf->transparency.val.tex, tex ); - break; - - case ID_TFLG: - flags = getU2( fp ); - - if ( flags & 1 ) i = 0; - if ( flags & 2 ) i = 1; - if ( flags & 4 ) i = 2; - tex->axis = i; - if ( tex->type == ID_IMAP ) - tex->param.imap.axis = i; - else - tex->param.proc.axis = i; - - if ( flags & 8 ) tex->tmap.coord_sys = 1; - if ( flags & 16 ) tex->negative = 1; - if ( flags & 32 ) tex->param.imap.pblend = 1; - if ( flags & 64 ) { - tex->param.imap.aa_strength = 1.0f; - tex->param.imap.aas_flags = 1; - } - break; - - case ID_TSIZ: - for ( i = 0; i < 3; i++ ) - tex->tmap.size.val[ i ] = getF4( fp ); - break; - - case ID_TCTR: - for ( i = 0; i < 3; i++ ) - tex->tmap.center.val[ i ] = getF4( fp ); - break; - - case ID_TFAL: - for ( i = 0; i < 3; i++ ) - tex->tmap.falloff.val[ i ] = getF4( fp ); - break; - - case ID_TVEL: - for ( i = 0; i < 3; i++ ) - v[ i ] = getF4( fp ); - tex->tmap.center.eindex = add_tvel( tex->tmap.center.val, v, - &obj->env, &obj->nenvs ); - break; - - case ID_TCLR: - if ( tex->type == ID_PROC ) - for ( i = 0; i < 3; i++ ) - tex->param.proc.value[ i ] = getU1( fp ) / 255.0f; - break; - - case ID_TVAL: - tex->param.proc.value[ 0 ] = getI2( fp ) / 256.0f; - break; - - case ID_TAMP: - if ( tex->type == ID_IMAP ) - tex->param.imap.amplitude.val = getF4( fp ); - break; - - case ID_TIMG: - s = getS0( fp ); - tex->param.imap.cindex = add_clip( s, &obj->clip, &obj->nclips ); - break; - - case ID_TAAS: - tex->param.imap.aa_strength = getF4( fp ); - tex->param.imap.aas_flags = 1; - break; - - case ID_TREF: - tex->tmap.ref_object = getbytes( fp, sz ); - break; - - case ID_TOPC: - tex->opacity.val = getF4( fp ); - break; - - case ID_TFP0: - if ( tex->type == ID_IMAP ) - tex->param.imap.wrapw.val = getF4( fp ); - break; - - case ID_TFP1: - if ( tex->type == ID_IMAP ) - tex->param.imap.wraph.val = getF4( fp ); - break; - - case ID_SHDR: - shdr = _pico_calloc( 1, sizeof( lwPlugin )); - if ( !shdr ) goto Fail; - shdr->name = getbytes( fp, sz ); - lwListAdd( &surf->shader, shdr ); - surf->nshaders++; - break; - - case ID_SDAT: - shdr->data = getbytes( fp, sz ); - break; - - default: - break; - } - - /* error while reading current subchunk? */ - - rlen = get_flen(); - if ( rlen < 0 || rlen > sz ) goto Fail; - - /* skip unread parts of the current subchunk */ - - if ( rlen < sz ) - _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR ); - - /* end of the SURF chunk? */ - - if ( cksize <= _pico_memstream_tell( fp ) - pos ) - break; - - /* get the next subchunk header */ - - set_flen( 0 ); - id = getU4( fp ); - sz = getU2( fp ); - if ( 6 != get_flen() ) goto Fail; - } - - return surf; + ====================================================================== + lwGetSurface5() + + Read an lwSurface from an LWOB file. + ====================================================================== */ + +lwSurface *lwGetSurface5( picoMemStream_t *fp, int cksize, lwObject *obj ){ + lwSurface *surf; + lwTexture *tex; + lwPlugin *shdr; + char *s; + float v[ 3 ]; + unsigned int id, flags; + unsigned short sz; + int pos, rlen, i; + + + /* allocate the Surface structure */ + + surf = _pico_calloc( 1, sizeof( lwSurface ) ); + if ( !surf ) { + goto Fail; + } + + /* non-zero defaults */ + + surf->color.rgb[ 0 ] = 0.78431f; + surf->color.rgb[ 1 ] = 0.78431f; + surf->color.rgb[ 2 ] = 0.78431f; + surf->diffuse.val = 1.0f; + surf->glossiness.val = 0.4f; + surf->bump.val = 1.0f; + surf->eta.val = 1.0f; + surf->sideflags = 1; + + /* remember where we started */ + + set_flen( 0 ); + pos = _pico_memstream_tell( fp ); + + /* name */ + + surf->name = getS0( fp ); + + /* first subchunk header */ + + id = getU4( fp ); + sz = getU2( fp ); + if ( 0 > get_flen() ) { + goto Fail; + } + + /* process subchunks as they're encountered */ + + while ( 1 ) { + sz += sz & 1; + set_flen( 0 ); + + switch ( id ) { + case ID_COLR: + surf->color.rgb[ 0 ] = getU1( fp ) / 255.0f; + surf->color.rgb[ 1 ] = getU1( fp ) / 255.0f; + surf->color.rgb[ 2 ] = getU1( fp ) / 255.0f; + break; + + case ID_FLAG: + flags = getU2( fp ); + if ( flags & 4 ) { + surf->smooth = 1.56207f; + } + if ( flags & 8 ) { + surf->color_hilite.val = 1.0f; + } + if ( flags & 16 ) { + surf->color_filter.val = 1.0f; + } + if ( flags & 128 ) { + surf->dif_sharp.val = 0.5f; + } + if ( flags & 256 ) { + surf->sideflags = 3; + } + if ( flags & 512 ) { + surf->add_trans.val = 1.0f; + } + break; + + case ID_LUMI: + surf->luminosity.val = getI2( fp ) / 256.0f; + break; + + case ID_VLUM: + surf->luminosity.val = getF4( fp ); + break; + + case ID_DIFF: + surf->diffuse.val = getI2( fp ) / 256.0f; + break; + + case ID_VDIF: + surf->diffuse.val = getF4( fp ); + break; + + case ID_SPEC: + surf->specularity.val = getI2( fp ) / 256.0f; + break; + + case ID_VSPC: + surf->specularity.val = getF4( fp ); + break; + + case ID_GLOS: + surf->glossiness.val = ( float ) log( getU2( fp ) ) / 20.7944f; + break; + + case ID_SMAN: + surf->smooth = getF4( fp ); + break; + + case ID_REFL: + surf->reflection.val.val = getI2( fp ) / 256.0f; + break; + + case ID_RFLT: + surf->reflection.options = getU2( fp ); + break; + + case ID_RIMG: + s = getS0( fp ); + surf->reflection.cindex = add_clip( s, &obj->clip, &obj->nclips ); + surf->reflection.options = 3; + break; + + case ID_RSAN: + surf->reflection.seam_angle = getF4( fp ); + break; + + case ID_TRAN: + surf->transparency.val.val = getI2( fp ) / 256.0f; + break; + + case ID_RIND: + surf->eta.val = getF4( fp ); + break; + + case ID_BTEX: + s = getbytes( fp, sz ); + tex = get_texture( s ); + lwListAdd( &surf->bump.tex, tex ); + break; + + case ID_CTEX: + s = getbytes( fp, sz ); + tex = get_texture( s ); + lwListAdd( &surf->color.tex, tex ); + break; + + case ID_DTEX: + s = getbytes( fp, sz ); + tex = get_texture( s ); + lwListAdd( &surf->diffuse.tex, tex ); + break; + + case ID_LTEX: + s = getbytes( fp, sz ); + tex = get_texture( s ); + lwListAdd( &surf->luminosity.tex, tex ); + break; + + case ID_RTEX: + s = getbytes( fp, sz ); + tex = get_texture( s ); + lwListAdd( &surf->reflection.val.tex, tex ); + break; + + case ID_STEX: + s = getbytes( fp, sz ); + tex = get_texture( s ); + lwListAdd( &surf->specularity.tex, tex ); + break; + + case ID_TTEX: + s = getbytes( fp, sz ); + tex = get_texture( s ); + lwListAdd( &surf->transparency.val.tex, tex ); + break; + + case ID_TFLG: + flags = getU2( fp ); + + if ( flags & 1 ) { + i = 0; + } + if ( flags & 2 ) { + i = 1; + } + if ( flags & 4 ) { + i = 2; + } + tex->axis = i; + if ( tex->type == ID_IMAP ) { + tex->param.imap.axis = i; + } + else{ + tex->param.proc.axis = i; + } + + if ( flags & 8 ) { + tex->tmap.coord_sys = 1; + } + if ( flags & 16 ) { + tex->negative = 1; + } + if ( flags & 32 ) { + tex->param.imap.pblend = 1; + } + if ( flags & 64 ) { + tex->param.imap.aa_strength = 1.0f; + tex->param.imap.aas_flags = 1; + } + break; + + case ID_TSIZ: + for ( i = 0; i < 3; i++ ) + tex->tmap.size.val[ i ] = getF4( fp ); + break; + + case ID_TCTR: + for ( i = 0; i < 3; i++ ) + tex->tmap.center.val[ i ] = getF4( fp ); + break; + + case ID_TFAL: + for ( i = 0; i < 3; i++ ) + tex->tmap.falloff.val[ i ] = getF4( fp ); + break; + + case ID_TVEL: + for ( i = 0; i < 3; i++ ) + v[ i ] = getF4( fp ); + tex->tmap.center.eindex = add_tvel( tex->tmap.center.val, v, + &obj->env, &obj->nenvs ); + break; + + case ID_TCLR: + if ( tex->type == ID_PROC ) { + for ( i = 0; i < 3; i++ ) + tex->param.proc.value[ i ] = getU1( fp ) / 255.0f; + } + break; + + case ID_TVAL: + tex->param.proc.value[ 0 ] = getI2( fp ) / 256.0f; + break; + + case ID_TAMP: + if ( tex->type == ID_IMAP ) { + tex->param.imap.amplitude.val = getF4( fp ); + } + break; + + case ID_TIMG: + s = getS0( fp ); + tex->param.imap.cindex = add_clip( s, &obj->clip, &obj->nclips ); + break; + + case ID_TAAS: + tex->param.imap.aa_strength = getF4( fp ); + tex->param.imap.aas_flags = 1; + break; + + case ID_TREF: + tex->tmap.ref_object = getbytes( fp, sz ); + break; + + case ID_TOPC: + tex->opacity.val = getF4( fp ); + break; + + case ID_TFP0: + if ( tex->type == ID_IMAP ) { + tex->param.imap.wrapw.val = getF4( fp ); + } + break; + + case ID_TFP1: + if ( tex->type == ID_IMAP ) { + tex->param.imap.wraph.val = getF4( fp ); + } + break; + + case ID_SHDR: + shdr = _pico_calloc( 1, sizeof( lwPlugin ) ); + if ( !shdr ) { + goto Fail; + } + shdr->name = getbytes( fp, sz ); + lwListAdd( &surf->shader, shdr ); + surf->nshaders++; + break; + + case ID_SDAT: + shdr->data = getbytes( fp, sz ); + break; + + default: + break; + } + + /* error while reading current subchunk? */ + + rlen = get_flen(); + if ( rlen < 0 || rlen > sz ) { + goto Fail; + } + + /* skip unread parts of the current subchunk */ + + if ( rlen < sz ) { + _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR ); + } + + /* end of the SURF chunk? */ + + if ( cksize <= _pico_memstream_tell( fp ) - pos ) { + break; + } + + /* get the next subchunk header */ + + set_flen( 0 ); + id = getU4( fp ); + sz = getU2( fp ); + if ( 6 != get_flen() ) { + goto Fail; + } + } + + return surf; Fail: - if ( surf ) lwFreeSurface( surf ); - return NULL; + if ( surf ) { + lwFreeSurface( surf ); + } + return NULL; } /* -====================================================================== -lwGetPolygons5() - -Read polygon records from a POLS chunk in an LWOB file. The polygons -are added to the array in the lwPolygonList. -====================================================================== */ - -int lwGetPolygons5( picoMemStream_t *fp, int cksize, lwPolygonList *plist, int ptoffset ) -{ - lwPolygon *pp; - lwPolVert *pv; - unsigned char *buf, *bp; - int i, j, nv, nverts, npols; - - - if ( cksize == 0 ) return 1; - - /* read the whole chunk */ - - set_flen( 0 ); - buf = getbytes( fp, cksize ); - if ( !buf ) goto Fail; - - /* count the polygons and vertices */ - - nverts = 0; - npols = 0; - bp = buf; - - while ( bp < buf + cksize ) { - nv = sgetU2( &bp ); - nverts += nv; - npols++; - bp += 2 * nv; - i = sgetI2( &bp ); - if ( i < 0 ) bp += 2; /* detail polygons */ - } - - if ( !lwAllocPolygons( plist, npols, nverts )) - goto Fail; - - /* fill in the new polygons */ - - bp = buf; - pp = plist->pol + plist->offset; - pv = plist->pol[ 0 ].v + plist->voffset; - - for ( i = 0; i < npols; i++ ) { - nv = sgetU2( &bp ); - - pp->nverts = nv; - pp->type = ID_FACE; - if ( !pp->v ) pp->v = pv; - for ( j = 0; j < nv; j++ ) - pv[ j ].index = sgetU2( &bp ) + ptoffset; - j = sgetI2( &bp ); - if ( j < 0 ) { - j = -j; - bp += 2; - } - j -= 1; - pp->surf = ( lwSurface * ) j; - - pp++; - pv += nv; - } - - _pico_free( buf ); - return 1; + ====================================================================== + lwGetPolygons5() + + Read polygon records from a POLS chunk in an LWOB file. The polygons + are added to the array in the lwPolygonList. + ====================================================================== */ + +int lwGetPolygons5( picoMemStream_t *fp, int cksize, lwPolygonList *plist, int ptoffset ){ + lwPolygon *pp; + lwPolVert *pv; + unsigned char *buf, *bp; + int i, j, nv, nverts, npols; + + + if ( cksize == 0 ) { + return 1; + } + + /* read the whole chunk */ + + set_flen( 0 ); + buf = getbytes( fp, cksize ); + if ( !buf ) { + goto Fail; + } + + /* count the polygons and vertices */ + + nverts = 0; + npols = 0; + bp = buf; + + while ( bp < buf + cksize ) { + nv = sgetU2( &bp ); + nverts += nv; + npols++; + bp += 2 * nv; + i = sgetI2( &bp ); + if ( i < 0 ) { + bp += 2; /* detail polygons */ + } + } + + if ( !lwAllocPolygons( plist, npols, nverts ) ) { + goto Fail; + } + + /* fill in the new polygons */ + + bp = buf; + pp = plist->pol + plist->offset; + pv = plist->pol[ 0 ].v + plist->voffset; + + for ( i = 0; i < npols; i++ ) { + nv = sgetU2( &bp ); + + pp->nverts = nv; + pp->type = ID_FACE; + if ( !pp->v ) { + pp->v = pv; + } + for ( j = 0; j < nv; j++ ) + pv[ j ].index = sgetU2( &bp ) + ptoffset; + j = sgetI2( &bp ); + if ( j < 0 ) { + j = -j; + bp += 2; + } + j -= 1; + pp->surf = ( lwSurface * ) ( (size_t)j ); + + pp++; + pv += nv; + } + + _pico_free( buf ); + return 1; Fail: - if ( buf ) _pico_free( buf ); - lwFreePolygons( plist ); - return 0; + if ( buf ) { + _pico_free( buf ); + } + lwFreePolygons( plist ); + return 0; } /* -====================================================================== -getLWObject5() + ====================================================================== + getLWObject5() -Returns the contents of an LWOB, given its filename, or NULL if the -file couldn't be loaded. On failure, failID and failpos can be used -to diagnose the cause. + Returns the contents of an LWOB, given its filename, or NULL if the + file couldn't be loaded. On failure, failID and failpos can be used + to diagnose the cause. -1. If the file isn't an LWOB, failpos will contain 12 and failID will + 1. If the file isn't an LWOB, failpos will contain 12 and failID will be unchanged. -2. If an error occurs while reading an LWOB, failID will contain the + 2. If an error occurs while reading an LWOB, failID will contain the most recently read IFF chunk ID, and failpos will contain the value returned by _pico_memstream_tell() at the time of the failure. -3. If the file couldn't be opened, or an error occurs while reading + 3. If the file couldn't be opened, or an error occurs while reading the first 12 bytes, both failID and failpos will be unchanged. -If you don't need this information, failID and failpos can be NULL. -====================================================================== */ - -lwObject *lwGetObject5( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos ) -{ - lwObject *object; - lwLayer *layer; - lwNode *node; - unsigned int id, formsize, type, cksize; - - - /* open the file */ - - if ( !fp ) return NULL; - - /* read the first 12 bytes */ - - set_flen( 0 ); - id = getU4( fp ); - formsize = getU4( fp ); - type = getU4( fp ); - if ( 12 != get_flen() ) { - return NULL; - } - - /* LWOB? */ - - if ( id != ID_FORM || type != ID_LWOB ) { - if ( failpos ) *failpos = 12; - return NULL; - } - - /* allocate an object and a default layer */ - - object = _pico_calloc( 1, sizeof( lwObject )); - if ( !object ) goto Fail; - - layer = _pico_calloc( 1, sizeof( lwLayer )); - if ( !layer ) goto Fail; - object->layer = layer; - object->nlayers = 1; - - /* get the first chunk header */ - - id = getU4( fp ); - cksize = getU4( fp ); - if ( 0 > get_flen() ) goto Fail; - - /* process chunks as they're encountered */ - - while ( 1 ) { - cksize += cksize & 1; - - switch ( id ) - { - case ID_PNTS: - if ( !lwGetPoints( fp, cksize, &layer->point )) - goto Fail; - break; - - case ID_POLS: - if ( !lwGetPolygons5( fp, cksize, &layer->polygon, - layer->point.offset )) - goto Fail; - break; - - case ID_SRFS: - if ( !lwGetTags( fp, cksize, &object->taglist )) - goto Fail; - break; - - case ID_SURF: - node = ( lwNode * ) lwGetSurface5( fp, cksize, object ); - if ( !node ) goto Fail; - lwListAdd( &object->surf, node ); - object->nsurfs++; - break; - - default: - _pico_memstream_seek( fp, cksize, PICO_SEEK_CUR ); - break; - } - - /* end of the file? */ - - if ( formsize <= _pico_memstream_tell( fp ) - 8 ) break; - - /* get the next chunk header */ - - set_flen( 0 ); - id = getU4( fp ); - cksize = getU4( fp ); - if ( 8 != get_flen() ) goto Fail; - } - - lwGetBoundingBox( &layer->point, layer->bbox ); - lwGetPolyNormals( &layer->point, &layer->polygon ); - if ( !lwGetPointPolygons( &layer->point, &layer->polygon )) goto Fail; - if ( !lwResolvePolySurfaces( &layer->polygon, &object->taglist, - &object->surf, &object->nsurfs )) goto Fail; - lwGetVertNormals( &layer->point, &layer->polygon ); - - return object; + If you don't need this information, failID and failpos can be NULL. + ====================================================================== */ + +lwObject *lwGetObject5( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos ){ + lwObject *object; + lwLayer *layer; + lwNode *node; + unsigned int id, formsize, type, cksize; + + + /* open the file */ + + if ( !fp ) { + return NULL; + } + + /* read the first 12 bytes */ + + set_flen( 0 ); + id = getU4( fp ); + formsize = getU4( fp ); + type = getU4( fp ); + if ( 12 != get_flen() ) { + return NULL; + } + + /* LWOB? */ + + if ( id != ID_FORM || type != ID_LWOB ) { + if ( failpos ) { + *failpos = 12; + } + return NULL; + } + + /* allocate an object and a default layer */ + + object = _pico_calloc( 1, sizeof( lwObject ) ); + if ( !object ) { + goto Fail; + } + + layer = _pico_calloc( 1, sizeof( lwLayer ) ); + if ( !layer ) { + goto Fail; + } + object->layer = layer; + object->nlayers = 1; + + /* get the first chunk header */ + + id = getU4( fp ); + cksize = getU4( fp ); + if ( 0 > get_flen() ) { + goto Fail; + } + + /* process chunks as they're encountered */ + + while ( 1 ) { + cksize += cksize & 1; + + switch ( id ) + { + case ID_PNTS: + if ( !lwGetPoints( fp, cksize, &layer->point ) ) { + goto Fail; + } + break; + + case ID_POLS: + if ( !lwGetPolygons5( fp, cksize, &layer->polygon, + layer->point.offset ) ) { + goto Fail; + } + break; + + case ID_SRFS: + if ( !lwGetTags( fp, cksize, &object->taglist ) ) { + goto Fail; + } + break; + + case ID_SURF: + node = ( lwNode * ) lwGetSurface5( fp, cksize, object ); + if ( !node ) { + goto Fail; + } + lwListAdd( &object->surf, node ); + object->nsurfs++; + break; + + default: + _pico_memstream_seek( fp, cksize, PICO_SEEK_CUR ); + break; + } + + /* end of the file? */ + + if ( formsize <= _pico_memstream_tell( fp ) - 8 ) { + break; + } + + /* get the next chunk header */ + + set_flen( 0 ); + id = getU4( fp ); + cksize = getU4( fp ); + if ( 8 != get_flen() ) { + goto Fail; + } + } + + lwGetBoundingBox( &layer->point, layer->bbox ); + lwGetPolyNormals( &layer->point, &layer->polygon ); + if ( !lwGetPointPolygons( &layer->point, &layer->polygon ) ) { + goto Fail; + } + if ( !lwResolvePolySurfaces( &layer->polygon, &object->taglist, + &object->surf, &object->nsurfs ) ) { + goto Fail; + } + lwGetVertNormals( &layer->point, &layer->polygon ); + + return object; Fail: - if ( failID ) *failID = id; - if ( fp ) { - if ( failpos ) *failpos = _pico_memstream_tell( fp ); - } - lwFreeObject( object ); - return NULL; + if ( failID ) { + *failID = id; + } + if ( fp ) { + if ( failpos ) { + *failpos = _pico_memstream_tell( fp ); + } + } + lwFreeObject( object ); + return NULL; } -int lwValidateObject5( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos ) -{ - unsigned int id, formsize, type; +int lwValidateObject5( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos ){ + unsigned int id, formsize, type; - /* open the file */ + /* open the file */ - if ( !fp ) return PICO_PMV_ERROR_MEMORY; + if ( !fp ) { + return PICO_PMV_ERROR_MEMORY; + } - /* read the first 12 bytes */ + /* read the first 12 bytes */ - set_flen( 0 ); - id = getU4( fp ); - formsize = getU4( fp ); - type = getU4( fp ); - if ( 12 != get_flen() ) { - return PICO_PMV_ERROR_SIZE; - } + set_flen( 0 ); + id = getU4( fp ); + formsize = getU4( fp ); + type = getU4( fp ); + if ( 12 != get_flen() ) { + return PICO_PMV_ERROR_SIZE; + } - /* LWOB? */ + /* LWOB? */ - if ( id != ID_FORM || type != ID_LWOB ) { - if ( failpos ) *failpos = 12; - return PICO_PMV_ERROR_IDENT; - } + if ( id != ID_FORM || type != ID_LWOB ) { + if ( failpos ) { + *failpos = 12; + } + return PICO_PMV_ERROR_IDENT; + } - return PICO_PMV_OK; + return PICO_PMV_OK; }