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 );
56 if ( t->param.proc.name ) {
57 _pico_free( t->param.proc.name );
59 if ( t->param.proc.data ) {
60 _pico_free( t->param.proc.data );
64 if ( t->param.grad.key ) {
65 _pico_free( t->param.grad.key );
67 if ( t->param.grad.ikey ) {
68 _pico_free( t->param.grad.ikey );
78 ======================================================================
81 Free the memory used by an lwSurface.
82 ====================================================================== */
84 void lwFreeSurface( lwSurface *surf ){
87 _pico_free( surf->name );
89 if ( surf->srcname ) {
90 _pico_free( surf->srcname );
93 lwListFree( surf->shader, lwFreePlugin );
95 lwListFree( surf->color.tex, lwFreeTexture );
96 lwListFree( surf->luminosity.tex, lwFreeTexture );
97 lwListFree( surf->diffuse.tex, lwFreeTexture );
98 lwListFree( surf->specularity.tex, lwFreeTexture );
99 lwListFree( surf->glossiness.tex, lwFreeTexture );
100 lwListFree( surf->reflection.val.tex, lwFreeTexture );
101 lwListFree( surf->transparency.val.tex, lwFreeTexture );
102 lwListFree( surf->eta.tex, lwFreeTexture );
103 lwListFree( surf->translucency.tex, lwFreeTexture );
104 lwListFree( surf->bump.tex, lwFreeTexture );
112 ======================================================================
115 Read a texture map header from a SURF.BLOK in an LWO2 file. This is
116 the first subchunk in a BLOK, and its contents are common to all three
118 ====================================================================== */
120 int lwGetTHeader( picoMemStream_t *fp, int hsz, lwTexture *tex ){
126 /* remember where we started */
129 pos = _pico_memstream_tell( fp );
133 tex->ord = getS0( fp );
135 /* first subchunk header */
139 if ( 0 > get_flen() ) {
143 /* process subchunks as they're encountered */
151 tex->chan = getU4( fp );
155 tex->opac_type = getU2( fp );
156 tex->opacity.val = getF4( fp );
157 tex->opacity.eindex = getVX( fp );
161 tex->enabled = getU2( fp );
165 tex->negative = getU2( fp );
169 tex->axis = getU2( fp );
176 /* error while reading current subchunk? */
179 if ( rlen < 0 || rlen > sz ) {
183 /* skip unread parts of the current subchunk */
186 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
189 /* end of the texture header subchunk? */
191 if ( hsz <= _pico_memstream_tell( fp ) - pos ) {
195 /* get the next subchunk header */
200 if ( 6 != get_flen() ) {
205 set_flen( _pico_memstream_tell( fp ) - pos );
211 ======================================================================
214 Read a texture map from a SURF.BLOK in an LWO2 file. The TMAP
215 defines the mapping from texture to world or object coordinates.
216 ====================================================================== */
218 int lwGetTMap( picoMemStream_t *fp, int tmapsz, lwTMap *tmap ){
223 pos = _pico_memstream_tell( fp );
226 if ( 0 > get_flen() ) {
236 for ( i = 0; i < 3; i++ )
237 tmap->size.val[ i ] = getF4( fp );
238 tmap->size.eindex = getVX( fp );
242 for ( i = 0; i < 3; i++ )
243 tmap->center.val[ i ] = getF4( fp );
244 tmap->center.eindex = getVX( fp );
248 for ( i = 0; i < 3; i++ )
249 tmap->rotate.val[ i ] = getF4( fp );
250 tmap->rotate.eindex = getVX( fp );
254 tmap->fall_type = getU2( fp );
255 for ( i = 0; i < 3; i++ )
256 tmap->falloff.val[ i ] = getF4( fp );
257 tmap->falloff.eindex = getVX( fp );
261 tmap->ref_object = getS0( fp );
265 tmap->coord_sys = getU2( fp );
272 /* error while reading the current subchunk? */
275 if ( rlen < 0 || rlen > sz ) {
279 /* skip unread parts of the current subchunk */
282 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
285 /* end of the TMAP subchunk? */
287 if ( tmapsz <= _pico_memstream_tell( fp ) - pos ) {
291 /* get the next subchunk header */
296 if ( 6 != get_flen() ) {
301 set_flen( _pico_memstream_tell( fp ) - pos );
307 ======================================================================
310 Read an lwImageMap from a SURF.BLOK in an LWO2 file.
311 ====================================================================== */
313 int lwGetImageMap( picoMemStream_t *fp, int rsz, lwTexture *tex ){
318 pos = _pico_memstream_tell( fp );
321 if ( 0 > get_flen() ) {
331 if ( !lwGetTMap( fp, sz, &tex->tmap ) ) {
337 tex->param.imap.projection = getU2( fp );
341 tex->param.imap.vmap_name = getS0( fp );
345 tex->param.imap.axis = getU2( fp );
349 tex->param.imap.cindex = getVX( fp );
353 tex->param.imap.wrapw_type = getU2( fp );
354 tex->param.imap.wraph_type = getU2( fp );
358 tex->param.imap.wrapw.val = getF4( fp );
359 tex->param.imap.wrapw.eindex = getVX( fp );
363 tex->param.imap.wraph.val = getF4( fp );
364 tex->param.imap.wraph.eindex = getVX( fp );
368 tex->param.imap.aas_flags = getU2( fp );
369 tex->param.imap.aa_strength = getF4( fp );
373 tex->param.imap.pblend = getU2( fp );
377 tex->param.imap.stck.val = getF4( fp );
378 tex->param.imap.stck.eindex = getVX( fp );
382 tex->param.imap.amplitude.val = getF4( fp );
383 tex->param.imap.amplitude.eindex = getVX( fp );
390 /* error while reading the current subchunk? */
393 if ( rlen < 0 || rlen > sz ) {
397 /* skip unread parts of the current subchunk */
400 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
403 /* end of the image map? */
405 if ( rsz <= _pico_memstream_tell( fp ) - pos ) {
409 /* get the next subchunk header */
414 if ( 6 != get_flen() ) {
419 set_flen( _pico_memstream_tell( fp ) - pos );
425 ======================================================================
428 Read an lwProcedural from a SURF.BLOK in an LWO2 file.
429 ====================================================================== */
431 int lwGetProcedural( picoMemStream_t *fp, int rsz, lwTexture *tex ){
436 pos = _pico_memstream_tell( fp );
439 if ( 0 > get_flen() ) {
449 if ( !lwGetTMap( fp, sz, &tex->tmap ) ) {
455 tex->param.proc.axis = getU2( fp );
459 tex->param.proc.value[ 0 ] = getF4( fp );
461 tex->param.proc.value[ 1 ] = getF4( fp );
464 tex->param.proc.value[ 2 ] = getF4( fp );
469 tex->param.proc.name = getS0( fp );
471 tex->param.proc.data = getbytes( fp, sz - rlen );
478 /* error while reading the current subchunk? */
481 if ( rlen < 0 || rlen > sz ) {
485 /* skip unread parts of the current subchunk */
488 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
491 /* end of the procedural block? */
493 if ( rsz <= _pico_memstream_tell( fp ) - pos ) {
497 /* get the next subchunk header */
502 if ( 6 != get_flen() ) {
507 set_flen( _pico_memstream_tell( fp ) - pos );
513 ======================================================================
516 Read an lwGradient from a SURF.BLOK in an LWO2 file.
517 ====================================================================== */
519 int lwGetGradient( picoMemStream_t *fp, int rsz, lwTexture *tex ){
522 int rlen, pos, i, j, nkeys;
524 pos = _pico_memstream_tell( fp );
527 if ( 0 > get_flen() ) {
537 if ( !lwGetTMap( fp, sz, &tex->tmap ) ) {
543 tex->param.grad.paramname = getS0( fp );
547 tex->param.grad.itemname = getS0( fp );
551 tex->param.grad.start = getF4( fp );
555 tex->param.grad.end = getF4( fp );
559 tex->param.grad.repeat = getU2( fp );
563 nkeys = sz / sizeof( lwGradKey );
564 tex->param.grad.key = _pico_calloc( nkeys, sizeof( lwGradKey ) );
565 if ( !tex->param.grad.key ) {
568 for ( i = 0; i < nkeys; i++ ) {
569 tex->param.grad.key[ i ].value = getF4( fp );
570 for ( j = 0; j < 4; j++ )
571 tex->param.grad.key[ i ].rgba[ j ] = getF4( fp );
577 tex->param.grad.ikey = _pico_calloc( nkeys, sizeof( short ) );
578 if ( !tex->param.grad.ikey ) {
581 for ( i = 0; i < nkeys; i++ )
582 tex->param.grad.ikey[ i ] = getU2( fp );
589 /* error while reading the current subchunk? */
592 if ( rlen < 0 || rlen > sz ) {
596 /* skip unread parts of the current subchunk */
599 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
602 /* end of the gradient? */
604 if ( rsz <= _pico_memstream_tell( fp ) - pos ) {
608 /* get the next subchunk header */
613 if ( 6 != get_flen() ) {
618 set_flen( _pico_memstream_tell( fp ) - pos );
624 ======================================================================
627 Read an lwTexture from a SURF.BLOK in an LWO2 file.
628 ====================================================================== */
630 lwTexture *lwGetTexture( picoMemStream_t *fp, int bloksz, unsigned int type ){
635 tex = _pico_calloc( 1, sizeof( lwTexture ) );
641 tex->tmap.size.val[ 0 ] =
642 tex->tmap.size.val[ 1 ] =
643 tex->tmap.size.val[ 2 ] = 1.0f;
644 tex->opacity.val = 1.0f;
648 if ( !lwGetTHeader( fp, sz, tex ) ) {
653 sz = bloksz - sz - 6;
655 case ID_IMAP: ok = lwGetImageMap( fp, sz, tex ); break;
656 case ID_PROC: ok = lwGetProcedural( fp, sz, tex ); break;
657 case ID_GRAD: ok = lwGetGradient( fp, sz, tex ); break;
659 ok = !_pico_memstream_seek( fp, sz, PICO_SEEK_CUR );
663 lwFreeTexture( tex );
673 ======================================================================
676 Read a shader record from a SURF.BLOK in an LWO2 file.
677 ====================================================================== */
679 lwPlugin *lwGetShader( picoMemStream_t *fp, int bloksz ){
685 shdr = _pico_calloc( 1, sizeof( lwPlugin ) );
690 pos = _pico_memstream_tell( fp );
693 shdr->ord = getS0( fp );
696 if ( 0 > get_flen() ) {
703 if ( id == ID_ENAB ) {
704 shdr->flags = getU2( fp );
708 _pico_memstream_seek( fp, sz, PICO_SEEK_CUR );
716 if ( 0 > get_flen() ) {
726 shdr->name = getS0( fp );
728 shdr->data = getbytes( fp, sz - rlen );
735 /* error while reading the current subchunk? */
738 if ( rlen < 0 || rlen > sz ) {
742 /* skip unread parts of the current subchunk */
745 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
748 /* end of the shader block? */
750 if ( bloksz <= _pico_memstream_tell( fp ) - pos ) {
754 /* get the next subchunk header */
759 if ( 6 != get_flen() ) {
764 set_flen( _pico_memstream_tell( fp ) - pos );
768 lwFreePlugin( shdr );
774 ======================================================================
778 Callbacks for the lwListInsert() function, which is called to add
779 textures to surface channels and shaders to surfaces.
780 ====================================================================== */
782 static int compare_textures( lwTexture *a, lwTexture *b ){
783 return strcmp( a->ord, b->ord );
787 static int compare_shaders( lwPlugin *a, lwPlugin *b ){
788 return strcmp( a->ord, b->ord );
793 ======================================================================
796 Finds the surface channel (lwTParam or lwCParam) to which a texture is
797 applied, then calls lwListInsert().
798 ====================================================================== */
800 static int add_texture( lwSurface *surf, lwTexture *tex ){
803 switch ( tex->chan ) {
804 case ID_COLR: list = &surf->color.tex; break;
805 case ID_LUMI: list = &surf->luminosity.tex; break;
806 case ID_DIFF: list = &surf->diffuse.tex; break;
807 case ID_SPEC: list = &surf->specularity.tex; break;
808 case ID_GLOS: list = &surf->glossiness.tex; break;
809 case ID_REFL: list = &surf->reflection.val.tex; break;
810 case ID_TRAN: list = &surf->transparency.val.tex; break;
811 case ID_RIND: list = &surf->eta.tex; break;
812 case ID_TRNL: list = &surf->translucency.tex; break;
813 case ID_BUMP: list = &surf->bump.tex; break;
817 lwListInsert( list, tex, compare_textures );
823 ======================================================================
826 Allocate and initialize a surface.
827 ====================================================================== */
829 lwSurface *lwDefaultSurface( void ){
832 surf = _pico_calloc( 1, sizeof( lwSurface ) );
837 surf->color.rgb[ 0 ] = 0.78431f;
838 surf->color.rgb[ 1 ] = 0.78431f;
839 surf->color.rgb[ 2 ] = 0.78431f;
840 surf->diffuse.val = 1.0f;
841 surf->glossiness.val = 0.4f;
842 surf->bump.val = 1.0f;
843 surf->eta.val = 1.0f;
851 ======================================================================
854 Read an lwSurface from an LWO2 file.
855 ====================================================================== */
857 lwSurface *lwGetSurface( picoMemStream_t *fp, int cksize ){
861 unsigned int id, type;
866 /* allocate the Surface structure */
868 surf = _pico_calloc( 1, sizeof( lwSurface ) );
873 /* non-zero defaults */
875 surf->color.rgb[ 0 ] = 0.78431f;
876 surf->color.rgb[ 1 ] = 0.78431f;
877 surf->color.rgb[ 2 ] = 0.78431f;
878 surf->diffuse.val = 1.0f;
879 surf->glossiness.val = 0.4f;
880 surf->bump.val = 1.0f;
881 surf->eta.val = 1.0f;
884 /* remember where we started */
887 pos = _pico_memstream_tell( fp );
891 surf->name = getS0( fp );
892 surf->srcname = getS0( fp );
894 /* first subchunk header */
898 if ( 0 > get_flen() ) {
902 /* process subchunks as they're encountered */
910 surf->color.rgb[ 0 ] = getF4( fp );
911 surf->color.rgb[ 1 ] = getF4( fp );
912 surf->color.rgb[ 2 ] = getF4( fp );
913 surf->color.eindex = getVX( fp );
917 surf->luminosity.val = getF4( fp );
918 surf->luminosity.eindex = getVX( fp );
922 surf->diffuse.val = getF4( fp );
923 surf->diffuse.eindex = getVX( fp );
927 surf->specularity.val = getF4( fp );
928 surf->specularity.eindex = getVX( fp );
932 surf->glossiness.val = getF4( fp );
933 surf->glossiness.eindex = getVX( fp );
937 surf->reflection.val.val = getF4( fp );
938 surf->reflection.val.eindex = getVX( fp );
942 surf->reflection.options = getU2( fp );
946 surf->reflection.cindex = getVX( fp );
950 surf->reflection.seam_angle = getF4( fp );
954 surf->transparency.val.val = getF4( fp );
955 surf->transparency.val.eindex = getVX( fp );
959 surf->transparency.options = getU2( fp );
963 surf->transparency.cindex = getVX( fp );
967 surf->eta.val = getF4( fp );
968 surf->eta.eindex = getVX( fp );
972 surf->translucency.val = getF4( fp );
973 surf->translucency.eindex = getVX( fp );
977 surf->bump.val = getF4( fp );
978 surf->bump.eindex = getVX( fp );
982 surf->smooth = getF4( fp );
986 surf->sideflags = getU2( fp );
990 surf->color_hilite.val = getF4( fp );
991 surf->color_hilite.eindex = getVX( fp );
995 surf->color_filter.val = getF4( fp );
996 surf->color_filter.eindex = getVX( fp );
1000 surf->add_trans.val = getF4( fp );
1001 surf->add_trans.eindex = getVX( fp );
1005 surf->dif_sharp.val = getF4( fp );
1006 surf->dif_sharp.eindex = getVX( fp );
1010 surf->glow.val = getF4( fp );
1011 surf->glow.eindex = getVX( fp );
1015 surf->line.enabled = 1;
1017 surf->line.flags = getU2( fp );
1020 surf->line.size.val = getF4( fp );
1023 surf->line.size.eindex = getVX( fp );
1028 surf->alpha_mode = getU2( fp );
1029 surf->alpha = getF4( fp );
1033 surf->alpha = getF4( fp );
1043 tex = lwGetTexture( fp, sz - 4, type );
1047 if ( !add_texture( surf, tex ) ) {
1048 lwFreeTexture( tex );
1050 set_flen( 4 + get_flen() );
1053 shdr = lwGetShader( fp, sz - 4 );
1057 lwListInsert( &surf->shader, shdr, compare_shaders );
1059 set_flen( 4 + get_flen() );
1068 /* error while reading current subchunk? */
1071 if ( rlen < 0 || rlen > sz ) {
1075 /* skip unread parts of the current subchunk */
1078 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
1081 /* end of the SURF chunk? */
1083 if ( cksize <= _pico_memstream_tell( fp ) - pos ) {
1087 /* get the next subchunk header */
1092 if ( 6 != get_flen() ) {
1101 lwFreeSurface( surf );