-/*\r
-======================================================================\r
-lwo2.c\r
-\r
-The entry point for loading LightWave object files.\r
-\r
-Ernie Wright 17 Sep 00\r
-====================================================================== */\r
-\r
-#include "../picointernal.h"\r
-#include "lwo2.h"\r
-\r
-/* disable warnings */\r
-#ifdef _WIN32\r
-#pragma warning( disable:4018 ) /* signed/unsigned mismatch */\r
-#endif\r
-\r
-\r
-/*\r
-======================================================================\r
-lwFreeLayer()\r
-\r
-Free memory used by an lwLayer.\r
-====================================================================== */\r
-\r
-void lwFreeLayer( lwLayer *layer )\r
-{\r
- if ( layer ) {\r
- if ( layer->name ) _pico_free( layer->name );\r
- lwFreePoints( &layer->point );\r
- lwFreePolygons( &layer->polygon );\r
- lwListFree( layer->vmap, lwFreeVMap );\r
- _pico_free( layer );\r
- }\r
-}\r
-\r
-\r
-/*\r
-======================================================================\r
-lwFreeObject()\r
-\r
-Free memory used by an lwObject.\r
-====================================================================== */\r
-\r
-void lwFreeObject( lwObject *object )\r
-{\r
- if ( object ) {\r
- lwListFree( object->layer, lwFreeLayer );\r
- lwListFree( object->env, lwFreeEnvelope );\r
- lwListFree( object->clip, lwFreeClip );\r
- lwListFree( object->surf, lwFreeSurface );\r
- lwFreeTags( &object->taglist );\r
- _pico_free( object );\r
- }\r
-}\r
-\r
-\r
-/*\r
-======================================================================\r
-lwGetObject()\r
-\r
-Returns the contents of a LightWave object, given its filename, or\r
-NULL if the file couldn't be loaded. On failure, failID and failpos\r
-can be used to diagnose the cause.\r
-\r
-1. If the file isn't an LWO2 or an LWOB, failpos will contain 12 and\r
- failID will be unchanged.\r
-\r
-2. If an error occurs while reading, failID will contain the most\r
- recently read IFF chunk ID, and failpos will contain the value\r
- returned by _pico_memstream_tell() at the time of the failure.\r
-\r
-3. If the file couldn't be opened, or an error occurs while reading\r
- the first 12 bytes, both failID and failpos will be unchanged.\r
-\r
-If you don't need this information, failID and failpos can be NULL.\r
-====================================================================== */\r
-\r
-lwObject *lwGetObject( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos )\r
-{\r
- lwObject *object;\r
- lwLayer *layer;\r
- lwNode *node;\r
- unsigned int id, formsize, type, cksize;\r
- int i, rlen;\r
-\r
- /* open the file */\r
-\r
- if ( !fp ) return NULL;\r
-\r
- /* read the first 12 bytes */\r
-\r
- set_flen( 0 );\r
- id = getU4( fp );\r
- formsize = getU4( fp );\r
- type = getU4( fp );\r
- if ( 12 != get_flen() ) {\r
- return NULL;\r
- }\r
-\r
- /* is this a LW object? */\r
-\r
- if ( id != ID_FORM ) {\r
- if ( failpos ) *failpos = 12;\r
- return NULL;\r
- }\r
-\r
- if ( type != ID_LWO2 ) {\r
- if ( type == ID_LWOB )\r
- return lwGetObject5( filename, fp, failID, failpos );\r
- else {\r
- if ( failpos ) *failpos = 12;\r
- return NULL;\r
- }\r
- }\r
-\r
- /* allocate an object and a default layer */\r
-\r
- object = _pico_calloc( 1, sizeof( lwObject ));\r
- if ( !object ) goto Fail;\r
-\r
- layer = _pico_calloc( 1, sizeof( lwLayer ));\r
- if ( !layer ) goto Fail;\r
- object->layer = layer;\r
-\r
- /* get the first chunk header */\r
-\r
- id = getU4( fp );\r
- cksize = getU4( fp );\r
- if ( 0 > get_flen() ) goto Fail;\r
-\r
- /* process chunks as they're encountered */\r
-\r
- while ( 1 ) {\r
- cksize += cksize & 1;\r
-\r
- switch ( id )\r
- {\r
- case ID_LAYR:\r
- if ( object->nlayers > 0 ) {\r
- layer = _pico_calloc( 1, sizeof( lwLayer ));\r
- if ( !layer ) goto Fail;\r
- lwListAdd( &object->layer, layer );\r
- }\r
- object->nlayers++;\r
-\r
- set_flen( 0 );\r
- layer->index = getU2( fp );\r
- layer->flags = getU2( fp );\r
- layer->pivot[ 0 ] = getF4( fp );\r
- layer->pivot[ 1 ] = getF4( fp );\r
- layer->pivot[ 2 ] = getF4( fp );\r
- layer->name = getS0( fp );\r
-\r
- rlen = get_flen();\r
- if ( rlen < 0 || rlen > cksize ) goto Fail;\r
- if ( rlen <= cksize - 2 )\r
- layer->parent = getU2( fp );\r
- rlen = get_flen();\r
- if ( rlen < cksize )\r
- _pico_memstream_seek( fp, cksize - rlen, PICO_SEEK_CUR );\r
- break;\r
-\r
- case ID_PNTS:\r
- if ( !lwGetPoints( fp, cksize, &layer->point ))\r
- goto Fail;\r
- break;\r
-\r
- case ID_POLS:\r
- if ( !lwGetPolygons( fp, cksize, &layer->polygon,\r
- layer->point.offset ))\r
- goto Fail;\r
- break;\r
-\r
- case ID_VMAP:\r
- case ID_VMAD:\r
- node = ( lwNode * ) lwGetVMap( fp, cksize, layer->point.offset,\r
- layer->polygon.offset, id == ID_VMAD );\r
- if ( !node ) goto Fail;\r
- lwListAdd( &layer->vmap, node );\r
- layer->nvmaps++;\r
- break;\r
-\r
- case ID_PTAG:\r
- if ( !lwGetPolygonTags( fp, cksize, &object->taglist,\r
- &layer->polygon ))\r
- goto Fail;\r
- break;\r
-\r
- case ID_BBOX:\r
- set_flen( 0 );\r
- for ( i = 0; i < 6; i++ )\r
- layer->bbox[ i ] = getF4( fp );\r
- rlen = get_flen();\r
- if ( rlen < 0 || rlen > cksize ) goto Fail;\r
- if ( rlen < cksize )\r
- _pico_memstream_seek( fp, cksize - rlen, PICO_SEEK_CUR );\r
- break;\r
-\r
- case ID_TAGS:\r
- if ( !lwGetTags( fp, cksize, &object->taglist ))\r
- goto Fail;\r
- break;\r
-\r
- case ID_ENVL:\r
- node = ( lwNode * ) lwGetEnvelope( fp, cksize );\r
- if ( !node ) goto Fail;\r
- lwListAdd( &object->env, node );\r
- object->nenvs++;\r
- break;\r
-\r
- case ID_CLIP:\r
- node = ( lwNode * ) lwGetClip( fp, cksize );\r
- if ( !node ) goto Fail;\r
- lwListAdd( &object->clip, node );\r
- object->nclips++;\r
- break;\r
-\r
- case ID_SURF:\r
- node = ( lwNode * ) lwGetSurface( fp, cksize );\r
- if ( !node ) goto Fail;\r
- lwListAdd( &object->surf, node );\r
- object->nsurfs++;\r
- break;\r
-\r
- case ID_DESC:\r
- case ID_TEXT:\r
- case ID_ICON:\r
- default:\r
- _pico_memstream_seek( fp, cksize, PICO_SEEK_CUR );\r
- break;\r
- }\r
-\r
- /* end of the file? */\r
-\r
- if ( formsize <= _pico_memstream_tell( fp ) - 8 ) break;\r
-\r
- /* get the next chunk header */\r
-\r
- set_flen( 0 );\r
- id = getU4( fp );\r
- cksize = getU4( fp );\r
- if ( 8 != get_flen() ) goto Fail;\r
- }\r
-\r
- if ( object->nlayers == 0 )\r
- object->nlayers = 1;\r
-\r
- layer = object->layer;\r
- while ( layer ) {\r
- lwGetBoundingBox( &layer->point, layer->bbox );\r
- lwGetPolyNormals( &layer->point, &layer->polygon );\r
- if ( !lwGetPointPolygons( &layer->point, &layer->polygon )) goto Fail;\r
- if ( !lwResolvePolySurfaces( &layer->polygon, &object->taglist,\r
- &object->surf, &object->nsurfs )) goto Fail;\r
- lwGetVertNormals( &layer->point, &layer->polygon );\r
- if ( !lwGetPointVMaps( &layer->point, layer->vmap )) goto Fail;\r
- if ( !lwGetPolyVMaps( &layer->polygon, layer->vmap )) goto Fail;\r
- layer = layer->next;\r
- }\r
-\r
- return object;\r
-\r
-Fail:\r
- if ( failID ) *failID = id;\r
- if ( fp ) {\r
- if ( failpos ) *failpos = _pico_memstream_tell( fp );\r
- }\r
- lwFreeObject( object );\r
- return NULL;\r
-}\r
-\r
-int lwValidateObject( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos )\r
-{\r
- unsigned int id, formsize, type;\r
-\r
- /* open the file */\r
-\r
- if ( !fp ) return PICO_PMV_ERROR_MEMORY;\r
-\r
- /* read the first 12 bytes */\r
-\r
- set_flen( 0 );\r
- id = getU4( fp );\r
- formsize = getU4( fp );\r
- type = getU4( fp );\r
- if ( 12 != get_flen() ) {\r
- return PICO_PMV_ERROR_SIZE;\r
- }\r
-\r
- /* is this a LW object? */\r
-\r
- if ( id != ID_FORM ) {\r
- if ( failpos ) *failpos = 12;\r
- return PICO_PMV_ERROR_SIZE;\r
- }\r
-\r
- if ( type != ID_LWO2 ) {\r
- if ( type == ID_LWOB )\r
- return lwValidateObject5( filename, fp, failID, failpos );\r
- else {\r
- if ( failpos ) *failpos = 12;\r
- return PICO_PMV_ERROR_IDENT;\r
- }\r
- }\r
-\r
- return PICO_PMV_OK;\r
-}\r
+/*
+======================================================================
+lwo2.c
+
+The entry point for loading LightWave object files.
+
+Ernie Wright 17 Sep 00
+====================================================================== */
+
+#include "../picointernal.h"
+#include "lwo2.h"
+
+/* disable warnings */
+#ifdef _WIN32
+#pragma warning( disable:4018 ) /* signed/unsigned mismatch */
+#endif
+
+
+/*
+======================================================================
+lwFreeLayer()
+
+Free memory used by an lwLayer.
+====================================================================== */
+
+void lwFreeLayer( lwLayer *layer )
+{
+ if ( layer ) {
+ if ( layer->name ) _pico_free( layer->name );
+ lwFreePoints( &layer->point );
+ lwFreePolygons( &layer->polygon );
+ lwListFree( layer->vmap, lwFreeVMap );
+ _pico_free( layer );
+ }
+}
+
+
+/*
+======================================================================
+lwFreeObject()
+
+Free memory used by an lwObject.
+====================================================================== */
+
+void lwFreeObject( lwObject *object )
+{
+ if ( object ) {
+ lwListFree( object->layer, lwFreeLayer );
+ lwListFree( object->env, lwFreeEnvelope );
+ lwListFree( object->clip, lwFreeClip );
+ lwListFree( object->surf, lwFreeSurface );
+ lwFreeTags( &object->taglist );
+ _pico_free( object );
+ }
+}
+
+
+/*
+======================================================================
+lwGetObject()
+
+Returns the contents of a LightWave object, 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 LWO2 or an LWOB, failpos will contain 12 and
+ failID will be unchanged.
+
+2. If an error occurs while reading, 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 *lwGetObject( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos )
+{
+ lwObject *object;
+ lwLayer *layer;
+ lwNode *node;
+ unsigned int id, formsize, type, cksize;
+ int i, rlen;
+
+ /* 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;
+ }
+
+ /* is this a LW object? */
+
+ if ( id != ID_FORM ) {
+ if ( failpos ) *failpos = 12;
+ return NULL;
+ }
+
+ if ( type != ID_LWO2 ) {
+ if ( type == ID_LWOB )
+ return lwGetObject5( filename, fp, failID, failpos );
+ else {
+ 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;
+
+ /* 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_LAYR:
+ if ( object->nlayers > 0 ) {
+ layer = _pico_calloc( 1, sizeof( lwLayer ));
+ if ( !layer ) goto Fail;
+ lwListAdd( &object->layer, layer );
+ }
+ object->nlayers++;
+
+ set_flen( 0 );
+ layer->index = getU2( fp );
+ layer->flags = getU2( fp );
+ layer->pivot[ 0 ] = getF4( fp );
+ layer->pivot[ 1 ] = getF4( fp );
+ layer->pivot[ 2 ] = getF4( fp );
+ layer->name = getS0( fp );
+
+ rlen = get_flen();
+ if ( rlen < 0 || rlen > cksize ) goto Fail;
+ if ( rlen <= cksize - 2 )
+ layer->parent = getU2( fp );
+ rlen = get_flen();
+ if ( rlen < cksize )
+ _pico_memstream_seek( fp, cksize - rlen, PICO_SEEK_CUR );
+ break;
+
+ case ID_PNTS:
+ if ( !lwGetPoints( fp, cksize, &layer->point ))
+ goto Fail;
+ break;
+
+ case ID_POLS:
+ if ( !lwGetPolygons( fp, cksize, &layer->polygon,
+ layer->point.offset ))
+ goto Fail;
+ break;
+
+ case ID_VMAP:
+ case ID_VMAD:
+ node = ( lwNode * ) lwGetVMap( fp, cksize, layer->point.offset,
+ layer->polygon.offset, id == ID_VMAD );
+ if ( !node ) goto Fail;
+ lwListAdd( &layer->vmap, node );
+ layer->nvmaps++;
+ break;
+
+ case ID_PTAG:
+ if ( !lwGetPolygonTags( fp, cksize, &object->taglist,
+ &layer->polygon ))
+ goto Fail;
+ break;
+
+ case ID_BBOX:
+ set_flen( 0 );
+ for ( i = 0; i < 6; i++ )
+ layer->bbox[ i ] = getF4( fp );
+ rlen = get_flen();
+ if ( rlen < 0 || rlen > cksize ) goto Fail;
+ if ( rlen < cksize )
+ _pico_memstream_seek( fp, cksize - rlen, PICO_SEEK_CUR );
+ break;
+
+ case ID_TAGS:
+ if ( !lwGetTags( fp, cksize, &object->taglist ))
+ goto Fail;
+ break;
+
+ case ID_ENVL:
+ node = ( lwNode * ) lwGetEnvelope( fp, cksize );
+ if ( !node ) goto Fail;
+ lwListAdd( &object->env, node );
+ object->nenvs++;
+ break;
+
+ case ID_CLIP:
+ node = ( lwNode * ) lwGetClip( fp, cksize );
+ if ( !node ) goto Fail;
+ lwListAdd( &object->clip, node );
+ object->nclips++;
+ break;
+
+ case ID_SURF:
+ node = ( lwNode * ) lwGetSurface( fp, cksize );
+ if ( !node ) goto Fail;
+ lwListAdd( &object->surf, node );
+ object->nsurfs++;
+ break;
+
+ case ID_DESC:
+ case ID_TEXT:
+ case ID_ICON:
+ 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;
+ }
+
+ if ( object->nlayers == 0 )
+ object->nlayers = 1;
+
+ layer = object->layer;
+ while ( layer ) {
+ 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 );
+ if ( !lwGetPointVMaps( &layer->point, layer->vmap )) goto Fail;
+ if ( !lwGetPolyVMaps( &layer->polygon, layer->vmap )) goto Fail;
+ layer = layer->next;
+ }
+
+ return object;
+
+Fail:
+ if ( failID ) *failID = id;
+ if ( fp ) {
+ if ( failpos ) *failpos = _pico_memstream_tell( fp );
+ }
+ lwFreeObject( object );
+ return NULL;
+}
+
+int lwValidateObject( 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;
+ }
+
+ /* is this a LW object? */
+
+ if ( id != ID_FORM ) {
+ if ( failpos ) *failpos = 12;
+ return PICO_PMV_ERROR_SIZE;
+ }
+
+ if ( type != ID_LWO2 ) {
+ if ( type == ID_LWOB )
+ return lwValidateObject5( filename, fp, failID, failpos );
+ else {
+ if ( failpos ) *failpos = 12;
+ return PICO_PMV_ERROR_IDENT;
+ }
+ }
+
+ return PICO_PMV_OK;
+}