lwTexture *lwGetTexture( picoMemStream_t *fp, int bloksz, unsigned int type ) { lwTexture *tex; unsigned short sz; int ok; tex = _pico_calloc( 1, sizeof( lwTexture ) ); if ( !tex ) { return NULL; } tex->type = type; 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; sz = getU2( fp ); if ( !lwGetTHeader( fp, sz, tex ) ) { _pico_free( tex ); return NULL; } sz = bloksz - sz - 6; switch ( type ) { case ID_IMAP: ok = lwGetImageMap( fp, sz, tex ); break; case ID_PROC: ok = lwGetProcedural( fp, sz, tex ); break; case ID_GRAD: ok = lwGetGradient( fp, sz, tex ); break; default: ok = !_pico_memstream_seek( fp, sz, PICO_SEEK_CUR ); } if ( !ok ) { lwFreeTexture( tex ); return NULL; } set_flen( bloksz ); return tex; }
lwSurface *lwGetSurface( picoMemStream_t *fp, int cksize ){ lwSurface *surf; lwTexture *tex; lwPlugin *shdr; unsigned int id, type; unsigned short sz; int pos, rlen; /* 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 ); /* names */ surf->name = getS0( fp ); surf->srcname = 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 ] = getF4( fp ); surf->color.rgb[ 1 ] = getF4( fp ); surf->color.rgb[ 2 ] = getF4( fp ); surf->color.eindex = getVX( fp ); break; case ID_LUMI: surf->luminosity.val = getF4( fp ); surf->luminosity.eindex = getVX( fp ); break; case ID_DIFF: surf->diffuse.val = getF4( fp ); surf->diffuse.eindex = getVX( fp ); break; case ID_SPEC: surf->specularity.val = getF4( fp ); surf->specularity.eindex = getVX( fp ); break; case ID_GLOS: surf->glossiness.val = getF4( fp ); surf->glossiness.eindex = getVX( fp ); break; case ID_REFL: surf->reflection.val.val = getF4( fp ); surf->reflection.val.eindex = getVX( fp ); break; case ID_RFOP: surf->reflection.options = getU2( fp ); break; case ID_RIMG: surf->reflection.cindex = getVX( fp ); break; case ID_RSAN: surf->reflection.seam_angle = getF4( fp ); break; case ID_TRAN: surf->transparency.val.val = getF4( fp ); surf->transparency.val.eindex = getVX( fp ); break; case ID_TROP: surf->transparency.options = getU2( fp ); break; case ID_TIMG: surf->transparency.cindex = getVX( fp ); break; case ID_RIND: surf->eta.val = getF4( fp ); surf->eta.eindex = getVX( fp ); break; case ID_TRNL: surf->translucency.val = getF4( fp ); surf->translucency.eindex = getVX( fp ); break; case ID_BUMP: surf->bump.val = getF4( fp ); surf->bump.eindex = getVX( fp ); break; case ID_SMAN: surf->smooth = getF4( fp ); break; case ID_SIDE: surf->sideflags = getU2( fp ); break; case ID_CLRH: surf->color_hilite.val = getF4( fp ); surf->color_hilite.eindex = getVX( fp ); break; case ID_CLRF: surf->color_filter.val = getF4( fp ); surf->color_filter.eindex = getVX( fp ); break; case ID_ADTR: surf->add_trans.val = getF4( fp ); surf->add_trans.eindex = getVX( fp ); break; case ID_SHRP: surf->dif_sharp.val = getF4( fp ); surf->dif_sharp.eindex = getVX( fp ); break; case ID_GVAL: surf->glow.val = getF4( fp ); surf->glow.eindex = getVX( fp ); break; case ID_LINE: surf->line.enabled = 1; if ( sz >= 2 ) { surf->line.flags = getU2( fp ); } if ( sz >= 6 ) { surf->line.size.val = getF4( fp ); } if ( sz >= 8 ) { surf->line.size.eindex = getVX( fp ); } break; case ID_ALPH: surf->alpha_mode = getU2( fp ); surf->alpha = getF4( fp ); break; case ID_AVAL: surf->alpha = getF4( fp ); break; case ID_BLOK: type = getU4( fp ); switch ( type ) { case ID_IMAP: case ID_PROC: case ID_GRAD: tex = lwGetTexture( fp, sz - 4, type ); if ( !tex ) { goto Fail; } if ( !add_texture( surf, tex ) ) { lwFreeTexture( tex ); } set_flen( 4 + get_flen() ); break; case ID_SHDR: shdr = lwGetShader( fp, sz - 4 ); if ( !shdr ) { goto Fail; } lwListInsert( (void **) &surf->shader, shdr, (void *) compare_shaders ); ++surf->nshaders; set_flen( 4 + get_flen() ); break; } 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; }