2 ======================================================================
5 The entry point for loading LightWave object files.
8 ====================================================================== */
10 #include "../picointernal.h"
13 /* disable warnings */
15 #pragma warning( disable:4018 ) /* signed/unsigned mismatch */
20 ======================================================================
23 Free memory used by an lwLayer.
24 ====================================================================== */
26 void lwFreeLayer( lwLayer *layer )
29 if ( layer->name ) _pico_free( layer->name );
30 lwFreePoints( &layer->point );
31 lwFreePolygons( &layer->polygon );
32 lwListFree( layer->vmap, (void *) lwFreeVMap );
39 ======================================================================
42 Free memory used by an lwObject.
43 ====================================================================== */
45 void lwFreeObject( lwObject *object )
48 lwListFree( object->layer, (void *) lwFreeLayer );
49 lwListFree( object->env, (void *) lwFreeEnvelope );
50 lwListFree( object->clip, (void *) lwFreeClip );
51 lwListFree( object->surf, (void *) lwFreeSurface );
52 lwFreeTags( &object->taglist );
59 ======================================================================
62 Returns the contents of a LightWave object, given its filename, or
63 NULL if the file couldn't be loaded. On failure, failID and failpos
64 can be used to diagnose the cause.
66 1. If the file isn't an LWO2 or an LWOB, failpos will contain 12 and
67 failID will be unchanged.
69 2. If an error occurs while reading, failID will contain the most
70 recently read IFF chunk ID, and failpos will contain the value
71 returned by _pico_memstream_tell() at the time of the failure.
73 3. If the file couldn't be opened, or an error occurs while reading
74 the first 12 bytes, both failID and failpos will be unchanged.
76 If you don't need this information, failID and failpos can be NULL.
77 ====================================================================== */
79 lwObject *lwGetObject( const char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos )
84 unsigned int id, formsize, type;
89 if ( !fp ) return NULL;
91 /* read the first 12 bytes */
95 formsize = getU4( fp );
97 if ( 12 != get_flen() ) {
101 /* is this a LW object? */
103 if ( id != ID_FORM ) {
104 if ( failpos ) *failpos = 12;
108 if ( type != ID_LWO2 ) {
109 if ( type == ID_LWOB )
110 return lwGetObject5( filename, fp, failID, failpos );
112 if ( failpos ) *failpos = 12;
117 /* allocate an object and a default layer */
119 object = _pico_calloc( 1, sizeof( lwObject ));
120 if ( !object ) goto Fail;
122 layer = _pico_calloc( 1, sizeof( lwLayer ));
123 if ( !layer ) goto Fail;
124 object->layer = layer;
126 /* get the first chunk header */
129 cksize = getU4( fp );
130 if ( 0 > get_flen() ) goto Fail;
132 /* process chunks as they're encountered */
135 cksize += cksize & 1;
140 if ( object->nlayers > 0 ) {
141 layer = _pico_calloc( 1, sizeof( lwLayer ));
142 if ( !layer ) goto Fail;
143 lwListAdd( (void **) &object->layer, layer );
148 layer->index = getU2( fp );
149 layer->flags = getU2( fp );
150 layer->pivot[ 0 ] = getF4( fp );
151 layer->pivot[ 1 ] = getF4( fp );
152 layer->pivot[ 2 ] = getF4( fp );
153 layer->name = getS0( fp );
156 if ( rlen < 0 || rlen > cksize ) goto Fail;
157 if ( rlen <= cksize - 2 )
158 layer->parent = getU2( fp );
161 _pico_memstream_seek( fp, cksize - rlen, PICO_SEEK_CUR );
165 if ( !lwGetPoints( fp, cksize, &layer->point ))
170 if ( !lwGetPolygons( fp, cksize, &layer->polygon,
171 layer->point.offset ))
177 node = ( lwNode * ) lwGetVMap( fp, cksize, layer->point.offset,
178 layer->polygon.offset, id == ID_VMAD );
179 if ( !node ) goto Fail;
180 lwListAdd( (void **) &layer->vmap, node );
185 if ( !lwGetPolygonTags( fp, cksize, &object->taglist,
192 for ( i = 0; i < 6; i++ )
193 layer->bbox[ i ] = getF4( fp );
195 if ( rlen < 0 || rlen > cksize ) goto Fail;
197 _pico_memstream_seek( fp, cksize - rlen, PICO_SEEK_CUR );
201 if ( !lwGetTags( fp, cksize, &object->taglist ))
206 node = ( lwNode * ) lwGetEnvelope( fp, cksize );
207 if ( !node ) goto Fail;
208 lwListAdd( (void **) &object->env, node );
213 node = ( lwNode * ) lwGetClip( fp, cksize );
214 if ( !node ) goto Fail;
215 lwListAdd( (void **) &object->clip, node );
220 node = ( lwNode * ) lwGetSurface( fp, cksize );
221 if ( !node ) goto Fail;
222 lwListAdd( (void **) &object->surf, node );
230 _pico_memstream_seek( fp, cksize, PICO_SEEK_CUR );
234 /* end of the file? */
236 if ( formsize <= (unsigned int) (_pico_memstream_tell( fp ) - 8) ) break;
238 /* get the next chunk header */
242 cksize = getU4( fp );
243 if ( 8 != get_flen() ) goto Fail;
246 if ( object->nlayers == 0 )
249 layer = object->layer;
251 lwGetBoundingBox( &layer->point, layer->bbox );
252 lwGetPolyNormals( &layer->point, &layer->polygon );
253 if ( !lwGetPointPolygons( &layer->point, &layer->polygon )) goto Fail;
254 if ( !lwResolvePolySurfaces( &layer->polygon, &object->taglist,
255 &object->surf, &object->nsurfs )) goto Fail;
256 lwGetVertNormals( &layer->point, &layer->polygon );
257 if ( !lwGetPointVMaps( &layer->point, layer->vmap )) goto Fail;
258 if ( !lwGetPolyVMaps( &layer->polygon, layer->vmap )) goto Fail;
265 if ( failID ) *failID = id;
267 if ( failpos ) *failpos = _pico_memstream_tell( fp );
269 lwFreeObject( object );
273 int lwValidateObject( const char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos )
275 unsigned int id, type;
279 if ( !fp ) return PICO_PMV_ERROR_MEMORY;
281 /* read the first 12 bytes */
285 /* formsize = */ getU4( fp );
287 if ( 12 != get_flen() ) {
288 return PICO_PMV_ERROR_SIZE;
291 /* is this a LW object? */
293 if ( id != ID_FORM ) {
294 if ( failpos ) *failpos = 12;
295 return PICO_PMV_ERROR_SIZE;
298 if ( type != ID_LWO2 ) {
299 if ( type == ID_LWOB )
300 return lwValidateObject5( filename, fp, failID, failpos );
302 if ( failpos ) *failpos = 12;
303 return PICO_PMV_ERROR_IDENT;