2 ======================================================================
5 The entry point for loading LightWave object files.
8 ====================================================================== */
10 #include "../picointernal.h"
12 #include "globaldefs.h"
14 /* disable warnings */
15 #if GDEF_COMPILER_MSVC
16 #pragma warning( disable:4018 ) /* signed/unsigned mismatch */
21 ======================================================================
24 Free memory used by an lwLayer.
25 ====================================================================== */
27 void lwFreeLayer( lwLayer *layer ){
30 _pico_free( layer->name );
32 lwFreePoints( &layer->point );
33 lwFreePolygons( &layer->polygon );
34 lwListFree(layer->vmap, (void (*)(void *)) lwFreeVMap);
41 ======================================================================
44 Free memory used by an lwObject.
45 ====================================================================== */
47 void lwFreeObject( lwObject *object ){
49 lwListFree(object->layer, (void (*)(void *)) lwFreeLayer);
50 lwListFree(object->env, (void (*)(void *)) lwFreeEnvelope);
51 lwListFree(object->clip, (void (*)(void *)) lwFreeClip);
52 lwListFree(object->surf, (void (*)(void *)) lwFreeSurface);
53 lwFreeTags( &object->taglist );
60 ======================================================================
63 Returns the contents of a LightWave object, given its filename, or
64 NULL if the file couldn't be loaded. On failure, failID and failpos
65 can be used to diagnose the cause.
67 1. If the file isn't an LWO2 or an LWOB, failpos will contain 12 and
68 failID will be unchanged.
70 2. If an error occurs while reading, failID will contain the most
71 recently read IFF chunk ID, and failpos will contain the value
72 returned by _pico_memstream_tell() at the time of the failure.
74 3. If the file couldn't be opened, or an error occurs while reading
75 the first 12 bytes, both failID and failpos will be unchanged.
77 If you don't need this information, failID and failpos can be NULL.
78 ====================================================================== */
80 lwObject *lwGetObject( const char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos ){
84 unsigned int id, formsize, type;
93 /* read the first 12 bytes */
97 formsize = getU4( fp );
99 if ( 12 != get_flen() ) {
103 /* is this a LW object? */
105 if ( id != ID_FORM ) {
112 if ( type != ID_LWO2 ) {
113 if ( type == ID_LWOB ) {
114 return lwGetObject5( filename, fp, failID, failpos );
124 /* allocate an object and a default layer */
126 object = _pico_calloc( 1, sizeof( lwObject ) );
131 layer = _pico_calloc( 1, sizeof( lwLayer ) );
135 object->layer = layer;
137 /* get the first chunk header */
140 cksize = getU4( fp );
141 if ( 0 > get_flen() ) {
145 /* process chunks as they're encountered */
148 cksize += cksize & 1;
153 if ( object->nlayers > 0 ) {
154 layer = _pico_calloc( 1, sizeof( lwLayer ) );
158 lwListAdd( (void **) &object->layer, layer );
163 layer->index = getU2( fp );
164 layer->flags = getU2( fp );
165 layer->pivot[ 0 ] = getF4( fp );
166 layer->pivot[ 1 ] = getF4( fp );
167 layer->pivot[ 2 ] = getF4( fp );
168 layer->name = getS0( fp );
171 if ( rlen < 0 || rlen > cksize ) {
174 if ( rlen <= cksize - 2 ) {
175 layer->parent = getU2( fp );
178 if ( rlen < cksize ) {
179 _pico_memstream_seek( fp, cksize - rlen, PICO_SEEK_CUR );
184 if ( !lwGetPoints( fp, cksize, &layer->point ) ) {
190 if ( !lwGetPolygons( fp, cksize, &layer->polygon,
191 layer->point.offset ) ) {
198 node = ( lwNode * ) lwGetVMap( fp, cksize, layer->point.offset,
199 layer->polygon.offset, id == ID_VMAD );
203 lwListAdd( (void **) &layer->vmap, node );
208 if ( !lwGetPolygonTags( fp, cksize, &object->taglist,
209 &layer->polygon ) ) {
216 for ( i = 0; i < 6; i++ )
217 layer->bbox[ i ] = getF4( fp );
219 if ( rlen < 0 || rlen > cksize ) {
222 if ( rlen < cksize ) {
223 _pico_memstream_seek( fp, cksize - rlen, PICO_SEEK_CUR );
228 if ( !lwGetTags( fp, cksize, &object->taglist ) ) {
234 node = ( lwNode * ) lwGetEnvelope( fp, cksize );
238 lwListAdd( (void **) &object->env, node );
243 node = ( lwNode * ) lwGetClip( fp, cksize );
247 lwListAdd( (void **) &object->clip, node );
252 node = ( lwNode * ) lwGetSurface( fp, cksize );
256 lwListAdd( (void **) &object->surf, node );
264 _pico_memstream_seek( fp, cksize, PICO_SEEK_CUR );
268 /* end of the file? */
270 if ( formsize <= (unsigned int) ( _pico_memstream_tell( fp ) - 8 ) ) {
274 /* get the next chunk header */
278 cksize = getU4( fp );
279 if ( 8 != get_flen() ) {
284 if ( object->nlayers == 0 ) {
288 layer = object->layer;
290 lwGetBoundingBox( &layer->point, layer->bbox );
291 lwGetPolyNormals( &layer->point, &layer->polygon );
292 if ( !lwGetPointPolygons( &layer->point, &layer->polygon ) ) {
295 if ( !lwResolvePolySurfaces( &layer->polygon, &object->taglist,
296 &object->surf, &object->nsurfs ) ) {
299 lwGetVertNormals( &layer->point, &layer->polygon );
300 if ( !lwGetPointVMaps( &layer->point, layer->vmap ) ) {
303 if ( !lwGetPolyVMaps( &layer->polygon, layer->vmap ) ) {
317 *failpos = _pico_memstream_tell( fp );
320 lwFreeObject( object );
324 int lwValidateObject( const char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos ){
325 unsigned int id, type;
330 return PICO_PMV_ERROR_MEMORY;
333 /* read the first 12 bytes */
337 /* formsize = */ getU4( fp );
339 if ( 12 != get_flen() ) {
340 return PICO_PMV_ERROR_SIZE;
343 /* is this a LW object? */
345 if ( id != ID_FORM ) {
349 return PICO_PMV_ERROR_SIZE;
352 if ( type != ID_LWO2 ) {
353 if ( type == ID_LWOB ) {
354 return lwValidateObject5( filename, fp, failID, failpos );
360 return PICO_PMV_ERROR_IDENT;