2 ======================================================================
5 Surface functions for an LWO2 reader.
8 ====================================================================== */
10 #include "../picointernal.h"
15 ======================================================================
18 Free the memory used by an lwPlugin.
19 ====================================================================== */
21 void lwFreePlugin( lwPlugin *p ){
27 _pico_free( p->name );
30 _pico_free( p->data );
38 ======================================================================
41 Free the memory used by an lwTexture.
42 ====================================================================== */
44 void lwFreeTexture( lwTexture *t ){
51 if ( t->param.imap.vmap_name ) {
52 _pico_free( t->param.imap.vmap_name );
54 if ( t->tmap.ref_object ) {
55 _pico_free( t->tmap.ref_object );
59 if ( t->param.proc.name ) {
60 _pico_free( t->param.proc.name );
62 if ( t->param.proc.data ) {
63 _pico_free( t->param.proc.data );
67 if ( t->param.grad.key ) {
68 _pico_free( t->param.grad.key );
70 if ( t->param.grad.ikey ) {
71 _pico_free( t->param.grad.ikey );
81 ======================================================================
84 Free the memory used by an lwSurface.
85 ====================================================================== */
87 void lwFreeSurface( lwSurface *surf ){
90 _pico_free( surf->name );
92 if ( surf->srcname ) {
93 _pico_free( surf->srcname );
96 lwListFree( surf->shader, (void *) lwFreePlugin );
98 lwListFree( surf->color.tex, (void *) lwFreeTexture );
99 lwListFree( surf->luminosity.tex, (void *) lwFreeTexture );
100 lwListFree( surf->diffuse.tex, (void *) lwFreeTexture );
101 lwListFree( surf->specularity.tex, (void *) lwFreeTexture );
102 lwListFree( surf->glossiness.tex, (void *) lwFreeTexture );
103 lwListFree( surf->reflection.val.tex, (void *) lwFreeTexture );
104 lwListFree( surf->transparency.val.tex, (void *) lwFreeTexture );
105 lwListFree( surf->eta.tex, (void *) lwFreeTexture );
106 lwListFree( surf->translucency.tex, (void *) lwFreeTexture );
107 lwListFree( surf->bump.tex, (void *) lwFreeTexture );
115 ======================================================================
118 Read a texture map header from a SURF.BLOK in an LWO2 file. This is
119 the first subchunk in a BLOK, and its contents are common to all three
121 ====================================================================== */
123 int lwGetTHeader( picoMemStream_t *fp, int hsz, lwTexture *tex ){
129 /* remember where we started */
132 pos = _pico_memstream_tell( fp );
136 tex->ord = getS0( fp );
138 /* first subchunk header */
142 if ( 0 > get_flen() ) {
146 /* process subchunks as they're encountered */
154 tex->chan = getU4( fp );
158 tex->opac_type = getU2( fp );
159 tex->opacity.val = getF4( fp );
160 tex->opacity.eindex = getVX( fp );
164 tex->enabled = getU2( fp );
168 tex->negative = getU2( fp );
172 tex->axis = getU2( fp );
179 /* error while reading current subchunk? */
182 if ( rlen < 0 || rlen > sz ) {
186 /* skip unread parts of the current subchunk */
189 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
192 /* end of the texture header subchunk? */
194 if ( hsz <= _pico_memstream_tell( fp ) - pos ) {
198 /* get the next subchunk header */
203 if ( 6 != get_flen() ) {
208 set_flen( _pico_memstream_tell( fp ) - pos );
214 ======================================================================
217 Read a texture map from a SURF.BLOK in an LWO2 file. The TMAP
218 defines the mapping from texture to world or object coordinates.
219 ====================================================================== */
221 int lwGetTMap( picoMemStream_t *fp, int tmapsz, lwTMap *tmap ){
226 pos = _pico_memstream_tell( fp );
229 if ( 0 > get_flen() ) {
239 for ( i = 0; i < 3; i++ )
240 tmap->size.val[ i ] = getF4( fp );
241 tmap->size.eindex = getVX( fp );
245 for ( i = 0; i < 3; i++ )
246 tmap->center.val[ i ] = getF4( fp );
247 tmap->center.eindex = getVX( fp );
251 for ( i = 0; i < 3; i++ )
252 tmap->rotate.val[ i ] = getF4( fp );
253 tmap->rotate.eindex = getVX( fp );
257 tmap->fall_type = getU2( fp );
258 for ( i = 0; i < 3; i++ )
259 tmap->falloff.val[ i ] = getF4( fp );
260 tmap->falloff.eindex = getVX( fp );
264 tmap->ref_object = getS0( fp );
268 tmap->coord_sys = getU2( fp );
275 /* error while reading the current subchunk? */
278 if ( rlen < 0 || rlen > sz ) {
282 /* skip unread parts of the current subchunk */
285 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
288 /* end of the TMAP subchunk? */
290 if ( tmapsz <= _pico_memstream_tell( fp ) - pos ) {
294 /* get the next subchunk header */
299 if ( 6 != get_flen() ) {
304 set_flen( _pico_memstream_tell( fp ) - pos );
310 ======================================================================
313 Read an lwImageMap from a SURF.BLOK in an LWO2 file.
314 ====================================================================== */
316 int lwGetImageMap( picoMemStream_t *fp, int rsz, lwTexture *tex ){
321 pos = _pico_memstream_tell( fp );
324 if ( 0 > get_flen() ) {
334 if ( !lwGetTMap( fp, sz, &tex->tmap ) ) {
340 tex->param.imap.projection = getU2( fp );
344 tex->param.imap.vmap_name = getS0( fp );
348 tex->param.imap.axis = getU2( fp );
352 tex->param.imap.cindex = getVX( fp );
356 tex->param.imap.wrapw_type = getU2( fp );
357 tex->param.imap.wraph_type = getU2( fp );
361 tex->param.imap.wrapw.val = getF4( fp );
362 tex->param.imap.wrapw.eindex = getVX( fp );
366 tex->param.imap.wraph.val = getF4( fp );
367 tex->param.imap.wraph.eindex = getVX( fp );
371 tex->param.imap.aas_flags = getU2( fp );
372 tex->param.imap.aa_strength = getF4( fp );
376 tex->param.imap.pblend = getU2( fp );
380 tex->param.imap.stck.val = getF4( fp );
381 tex->param.imap.stck.eindex = getVX( fp );
385 tex->param.imap.amplitude.val = getF4( fp );
386 tex->param.imap.amplitude.eindex = getVX( fp );
393 /* error while reading the current subchunk? */
396 if ( rlen < 0 || rlen > sz ) {
400 /* skip unread parts of the current subchunk */
403 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
406 /* end of the image map? */
408 if ( rsz <= _pico_memstream_tell( fp ) - pos ) {
412 /* get the next subchunk header */
417 if ( 6 != get_flen() ) {
422 set_flen( _pico_memstream_tell( fp ) - pos );
428 ======================================================================
431 Read an lwProcedural from a SURF.BLOK in an LWO2 file.
432 ====================================================================== */
434 int lwGetProcedural( picoMemStream_t *fp, int rsz, lwTexture *tex ){
439 pos = _pico_memstream_tell( fp );
442 if ( 0 > get_flen() ) {
452 if ( !lwGetTMap( fp, sz, &tex->tmap ) ) {
458 tex->param.proc.axis = getU2( fp );
462 tex->param.proc.value[ 0 ] = getF4( fp );
464 tex->param.proc.value[ 1 ] = getF4( fp );
467 tex->param.proc.value[ 2 ] = getF4( fp );
472 tex->param.proc.name = getS0( fp );
474 tex->param.proc.data = getbytes( fp, sz - rlen );
481 /* error while reading the current subchunk? */
484 if ( rlen < 0 || rlen > sz ) {
488 /* skip unread parts of the current subchunk */
491 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
494 /* end of the procedural block? */
496 if ( rsz <= _pico_memstream_tell( fp ) - pos ) {
500 /* get the next subchunk header */
505 if ( 6 != get_flen() ) {
510 set_flen( _pico_memstream_tell( fp ) - pos );
516 ======================================================================
519 Read an lwGradient from a SURF.BLOK in an LWO2 file.
520 ====================================================================== */
522 int lwGetGradient( picoMemStream_t *fp, int rsz, lwTexture *tex ){
525 int rlen, pos, i, j, nkeys;
527 pos = _pico_memstream_tell( fp );
530 if ( 0 > get_flen() ) {
540 if ( !lwGetTMap( fp, sz, &tex->tmap ) ) {
546 tex->param.grad.paramname = getS0( fp );
550 tex->param.grad.itemname = getS0( fp );
554 tex->param.grad.start = getF4( fp );
558 tex->param.grad.end = getF4( fp );
562 tex->param.grad.repeat = getU2( fp );
566 nkeys = sz / sizeof( lwGradKey );
567 tex->param.grad.key = _pico_calloc( nkeys, sizeof( lwGradKey ) );
568 if ( !tex->param.grad.key ) {
571 for ( i = 0; i < nkeys; i++ ) {
572 tex->param.grad.key[ i ].value = getF4( fp );
573 for ( j = 0; j < 4; j++ )
574 tex->param.grad.key[ i ].rgba[ j ] = getF4( fp );
580 tex->param.grad.ikey = _pico_calloc( nkeys, sizeof( short ) );
581 if ( !tex->param.grad.ikey ) {
584 for ( i = 0; i < nkeys; i++ )
585 tex->param.grad.ikey[ i ] = getU2( fp );
592 /* error while reading the current subchunk? */
595 if ( rlen < 0 || rlen > sz ) {
599 /* skip unread parts of the current subchunk */
602 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
605 /* end of the gradient? */
607 if ( rsz <= _pico_memstream_tell( fp ) - pos ) {
611 /* get the next subchunk header */
616 if ( 6 != get_flen() ) {
621 set_flen( _pico_memstream_tell( fp ) - pos );
627 ======================================================================
630 Read an lwTexture from a SURF.BLOK in an LWO2 file.
631 ====================================================================== */
633 lwTexture *lwGetTexture( picoMemStream_t *fp, int bloksz, unsigned int type ){
638 tex = _pico_calloc( 1, sizeof( lwTexture ) );
644 tex->tmap.size.val[ 0 ] =
645 tex->tmap.size.val[ 1 ] =
646 tex->tmap.size.val[ 2 ] = 1.0f;
647 tex->opacity.val = 1.0f;
651 if ( !lwGetTHeader( fp, sz, tex ) ) {
656 sz = bloksz - sz - 6;
658 case ID_IMAP: ok = lwGetImageMap( fp, sz, tex ); break;
659 case ID_PROC: ok = lwGetProcedural( fp, sz, tex ); break;
660 case ID_GRAD: ok = lwGetGradient( fp, sz, tex ); break;
662 ok = !_pico_memstream_seek( fp, sz, PICO_SEEK_CUR );
666 lwFreeTexture( tex );
676 ======================================================================
679 Read a shader record from a SURF.BLOK in an LWO2 file.
680 ====================================================================== */
682 lwPlugin *lwGetShader( picoMemStream_t *fp, int bloksz ){
688 shdr = _pico_calloc( 1, sizeof( lwPlugin ) );
693 pos = _pico_memstream_tell( fp );
696 shdr->ord = getS0( fp );
699 if ( 0 > get_flen() ) {
706 if ( id == ID_ENAB ) {
707 shdr->flags = getU2( fp );
711 _pico_memstream_seek( fp, sz, PICO_SEEK_CUR );
719 if ( 0 > get_flen() ) {
729 shdr->name = getS0( fp );
731 shdr->data = getbytes( fp, sz - rlen );
738 /* error while reading the current subchunk? */
741 if ( rlen < 0 || rlen > sz ) {
745 /* skip unread parts of the current subchunk */
748 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
751 /* end of the shader block? */
753 if ( bloksz <= _pico_memstream_tell( fp ) - pos ) {
757 /* get the next subchunk header */
762 if ( 6 != get_flen() ) {
767 set_flen( _pico_memstream_tell( fp ) - pos );
771 lwFreePlugin( shdr );
777 ======================================================================
781 Callbacks for the lwListInsert() function, which is called to add
782 textures to surface channels and shaders to surfaces.
783 ====================================================================== */
785 static int compare_textures( lwTexture *a, lwTexture *b ){
786 return strcmp( a->ord, b->ord );
790 static int compare_shaders( lwPlugin *a, lwPlugin *b ){
791 return strcmp( a->ord, b->ord );
796 ======================================================================
799 Finds the surface channel (lwTParam or lwCParam) to which a texture is
800 applied, then calls lwListInsert().
801 ====================================================================== */
803 static int add_texture( lwSurface *surf, lwTexture *tex ){
806 switch ( tex->chan ) {
807 case ID_COLR: list = &surf->color.tex; break;
808 case ID_LUMI: list = &surf->luminosity.tex; break;
809 case ID_DIFF: list = &surf->diffuse.tex; break;
810 case ID_SPEC: list = &surf->specularity.tex; break;
811 case ID_GLOS: list = &surf->glossiness.tex; break;
812 case ID_REFL: list = &surf->reflection.val.tex; break;
813 case ID_TRAN: list = &surf->transparency.val.tex; break;
814 case ID_RIND: list = &surf->eta.tex; break;
815 case ID_TRNL: list = &surf->translucency.tex; break;
816 case ID_BUMP: list = &surf->bump.tex; break;
820 lwListInsert( (void **) list, tex, ( void *) compare_textures );
826 ======================================================================
829 Allocate and initialize a surface.
830 ====================================================================== */
832 lwSurface *lwDefaultSurface( void ){
835 surf = _pico_calloc( 1, sizeof( lwSurface ) );
840 surf->color.rgb[ 0 ] = 0.78431f;
841 surf->color.rgb[ 1 ] = 0.78431f;
842 surf->color.rgb[ 2 ] = 0.78431f;
843 surf->diffuse.val = 1.0f;
844 surf->glossiness.val = 0.4f;
845 surf->bump.val = 1.0f;
846 surf->eta.val = 1.0f;
854 ======================================================================
857 Read an lwSurface from an LWO2 file.
858 ====================================================================== */
860 lwSurface *lwGetSurface( picoMemStream_t *fp, int cksize ){
864 unsigned int id, type;
869 /* allocate the Surface structure */
871 surf = _pico_calloc( 1, sizeof( lwSurface ) );
876 /* non-zero defaults */
878 surf->color.rgb[ 0 ] = 0.78431f;
879 surf->color.rgb[ 1 ] = 0.78431f;
880 surf->color.rgb[ 2 ] = 0.78431f;
881 surf->diffuse.val = 1.0f;
882 surf->glossiness.val = 0.4f;
883 surf->bump.val = 1.0f;
884 surf->eta.val = 1.0f;
887 /* remember where we started */
890 pos = _pico_memstream_tell( fp );
894 surf->name = getS0( fp );
895 surf->srcname = getS0( fp );
897 /* first subchunk header */
901 if ( 0 > get_flen() ) {
905 /* process subchunks as they're encountered */
913 surf->color.rgb[ 0 ] = getF4( fp );
914 surf->color.rgb[ 1 ] = getF4( fp );
915 surf->color.rgb[ 2 ] = getF4( fp );
916 surf->color.eindex = getVX( fp );
920 surf->luminosity.val = getF4( fp );
921 surf->luminosity.eindex = getVX( fp );
925 surf->diffuse.val = getF4( fp );
926 surf->diffuse.eindex = getVX( fp );
930 surf->specularity.val = getF4( fp );
931 surf->specularity.eindex = getVX( fp );
935 surf->glossiness.val = getF4( fp );
936 surf->glossiness.eindex = getVX( fp );
940 surf->reflection.val.val = getF4( fp );
941 surf->reflection.val.eindex = getVX( fp );
945 surf->reflection.options = getU2( fp );
949 surf->reflection.cindex = getVX( fp );
953 surf->reflection.seam_angle = getF4( fp );
957 surf->transparency.val.val = getF4( fp );
958 surf->transparency.val.eindex = getVX( fp );
962 surf->transparency.options = getU2( fp );
966 surf->transparency.cindex = getVX( fp );
970 surf->eta.val = getF4( fp );
971 surf->eta.eindex = getVX( fp );
975 surf->translucency.val = getF4( fp );
976 surf->translucency.eindex = getVX( fp );
980 surf->bump.val = getF4( fp );
981 surf->bump.eindex = getVX( fp );
985 surf->smooth = getF4( fp );
989 surf->sideflags = getU2( fp );
993 surf->color_hilite.val = getF4( fp );
994 surf->color_hilite.eindex = getVX( fp );
998 surf->color_filter.val = getF4( fp );
999 surf->color_filter.eindex = getVX( fp );
1003 surf->add_trans.val = getF4( fp );
1004 surf->add_trans.eindex = getVX( fp );
1008 surf->dif_sharp.val = getF4( fp );
1009 surf->dif_sharp.eindex = getVX( fp );
1013 surf->glow.val = getF4( fp );
1014 surf->glow.eindex = getVX( fp );
1018 surf->line.enabled = 1;
1020 surf->line.flags = getU2( fp );
1023 surf->line.size.val = getF4( fp );
1026 surf->line.size.eindex = getVX( fp );
1031 surf->alpha_mode = getU2( fp );
1032 surf->alpha = getF4( fp );
1036 surf->alpha = getF4( fp );
1046 tex = lwGetTexture( fp, sz - 4, type );
1050 if ( !add_texture( surf, tex ) ) {
1051 lwFreeTexture( tex );
1053 set_flen( 4 + get_flen() );
1056 shdr = lwGetShader( fp, sz - 4 );
1060 lwListInsert( (void **) &surf->shader, shdr, (void *) compare_shaders );
1062 set_flen( 4 + get_flen() );
1071 /* error while reading current subchunk? */
1074 if ( rlen < 0 || rlen > sz ) {
1078 /* skip unread parts of the current subchunk */
1081 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
1084 /* end of the SURF chunk? */
1086 if ( cksize <= _pico_memstream_tell( fp ) - pos ) {
1090 /* get the next subchunk header */
1095 if ( 6 != get_flen() ) {
1104 lwFreeSurface( surf );