mirror of
https://github.com/id-Software/GtkRadiant.git
synced 2026-03-20 08:59:32 +01:00
The GtkRadiant sources as originally released under the GPL license.
This commit is contained in:
723
libs/picomodel/lwo/lwob.c
Normal file
723
libs/picomodel/lwo/lwob.c
Normal file
@@ -0,0 +1,723 @@
|
||||
/*
|
||||
======================================================================
|
||||
lwob.c
|
||||
|
||||
Functions for an LWOB reader. LWOB is the LightWave object format
|
||||
for versions of LW prior to 6.0.
|
||||
|
||||
Ernie Wright 17 Sep 00
|
||||
====================================================================== */
|
||||
|
||||
#include "../picointernal.h"
|
||||
#include "lwo2.h"
|
||||
|
||||
/* disable warnings */
|
||||
#ifdef WIN32
|
||||
#pragma warning( disable:4018 ) /* signed/unsigned mismatch */
|
||||
#endif
|
||||
|
||||
|
||||
/* 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')
|
||||
|
||||
|
||||
/*
|
||||
======================================================================
|
||||
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( (void *) 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( (void *) 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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
======================================================================
|
||||
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( (void *) &surf->bump.tex, tex );
|
||||
break;
|
||||
|
||||
case ID_CTEX:
|
||||
s = getbytes( fp, sz );
|
||||
tex = get_texture( s );
|
||||
lwListAdd( (void *) &surf->color.tex, tex );
|
||||
break;
|
||||
|
||||
case ID_DTEX:
|
||||
s = getbytes( fp, sz );
|
||||
tex = get_texture( s );
|
||||
lwListAdd( (void *) &surf->diffuse.tex, tex );
|
||||
break;
|
||||
|
||||
case ID_LTEX:
|
||||
s = getbytes( fp, sz );
|
||||
tex = get_texture( s );
|
||||
lwListAdd( (void *) &surf->luminosity.tex, tex );
|
||||
break;
|
||||
|
||||
case ID_RTEX:
|
||||
s = getbytes( fp, sz );
|
||||
tex = get_texture( s );
|
||||
lwListAdd( (void *) &surf->reflection.val.tex, tex );
|
||||
break;
|
||||
|
||||
case ID_STEX:
|
||||
s = getbytes( fp, sz );
|
||||
tex = get_texture( s );
|
||||
lwListAdd( (void *) &surf->specularity.tex, tex );
|
||||
break;
|
||||
|
||||
case ID_TTEX:
|
||||
s = getbytes( fp, sz );
|
||||
tex = get_texture( s );
|
||||
lwListAdd( (void *) &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( (void *) &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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
======================================================================
|
||||
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;
|
||||
|
||||
Fail:
|
||||
if ( buf ) _pico_free( buf );
|
||||
lwFreePolygons( plist );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
======================================================================
|
||||
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.
|
||||
|
||||
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
|
||||
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
|
||||
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( (void *) &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;
|
||||
}
|
||||
|
||||
int lwValidateObject5( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos )
|
||||
{
|
||||
unsigned int id, formsize, type;
|
||||
|
||||
|
||||
/* open the file */
|
||||
|
||||
if ( !fp ) return PICO_PMV_ERROR_MEMORY;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* LWOB? */
|
||||
|
||||
if ( id != ID_FORM || type != ID_LWOB ) {
|
||||
if ( failpos ) *failpos = 12;
|
||||
return PICO_PMV_ERROR_IDENT;
|
||||
}
|
||||
|
||||
return PICO_PMV_OK;
|
||||
}
|
||||
Reference in New Issue
Block a user