예제 #1
0
파일: lwob.c 프로젝트: Asvarox/Unvanquished
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;
}
예제 #2
0
파일: lwo2.c 프로젝트: 2asoft/xray
lwObject *lwGetObject( char *filename, unsigned int *failID, int *failpos )
{
   FILE *fp = NULL;
   lwObject *object;
   lwLayer *layer;
   lwNode *node;
   unsigned int id, formsize, type, cksize;
   int i, rlen;

   /* open the file */

   fp = fopen( filename, "rb" );
   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() ) {
      fclose( fp );
      return NULL;
   }

   /* is this a LW object? */

   if ( id != ID_FORM ) {
      fclose( fp );
      if ( failpos ) *failpos = 12;
      return NULL;
   }

   if ( type != ID_LWO2 ) {
      fclose( fp );
      if ( type == ID_LWOB )
         return lwGetObject5( filename, failID, failpos );
      else {
         if ( failpos ) *failpos = 12;
         return NULL;
      }
   }

   /* allocate an object and a default layer */

   object = calloc( 1, sizeof( lwObject ));
   if ( !object ) goto Fail;

   layer = 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 = 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 );
            if ( rlen < cksize )
               fseek( fp, cksize - rlen, 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 )
               fseek( fp, cksize - rlen, 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:
            fseek( fp, cksize, SEEK_CUR );
            break;
      }

      /* end of the file? */

      if ( formsize <= ftell( fp ) - 8 ) break;

      /* get the next chunk header */

      set_flen( 0 );
      id = getU4( fp );
      cksize = getU4( fp );
      if ( 8 != get_flen() ) goto Fail;
   }

   fclose( fp );
   fp = NULL;

   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 = ftell( fp );
      fclose( fp );
   }
   lwFreeObject( object );
   return NULL;
}