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 (*)(void *)) lwFreePlugin);
98 void (*freeTexture)(void *) = (void (*)(void *)) lwFreeTexture;
99 lwListFree(surf->color.tex, freeTexture);
100 lwListFree(surf->luminosity.tex, freeTexture);
101 lwListFree(surf->diffuse.tex, freeTexture);
102 lwListFree(surf->specularity.tex, freeTexture);
103 lwListFree(surf->glossiness.tex, freeTexture);
104 lwListFree(surf->reflection.val.tex, freeTexture);
105 lwListFree(surf->transparency.val.tex, freeTexture);
106 lwListFree(surf->eta.tex, freeTexture);
107 lwListFree(surf->translucency.tex, freeTexture);
108 lwListFree(surf->bump.tex, freeTexture);
116 ======================================================================
119 Read a texture map header from a SURF.BLOK in an LWO2 file. This is
120 the first subchunk in a BLOK, and its contents are common to all three
122 ====================================================================== */
124 int lwGetTHeader( picoMemStream_t *fp, int hsz, lwTexture *tex ){
130 /* remember where we started */
133 pos = _pico_memstream_tell( fp );
137 tex->ord = getS0( fp );
139 /* first subchunk header */
143 if ( 0 > get_flen() ) {
147 /* process subchunks as they're encountered */
155 tex->chan = getU4( fp );
159 tex->opac_type = getU2( fp );
160 tex->opacity.val = getF4( fp );
161 tex->opacity.eindex = getVX( fp );
165 tex->enabled = getU2( fp );
169 tex->negative = getU2( fp );
173 tex->axis = getU2( fp );
180 /* error while reading current subchunk? */
183 if ( rlen < 0 || rlen > sz ) {
187 /* skip unread parts of the current subchunk */
190 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
193 /* end of the texture header subchunk? */
195 if ( hsz <= _pico_memstream_tell( fp ) - pos ) {
199 /* get the next subchunk header */
204 if ( 6 != get_flen() ) {
209 set_flen( _pico_memstream_tell( fp ) - pos );
215 ======================================================================
218 Read a texture map from a SURF.BLOK in an LWO2 file. The TMAP
219 defines the mapping from texture to world or object coordinates.
220 ====================================================================== */
222 int lwGetTMap( picoMemStream_t *fp, int tmapsz, lwTMap *tmap ){
227 pos = _pico_memstream_tell( fp );
230 if ( 0 > get_flen() ) {
240 for ( i = 0; i < 3; i++ )
241 tmap->size.val[ i ] = getF4( fp );
242 tmap->size.eindex = getVX( fp );
246 for ( i = 0; i < 3; i++ )
247 tmap->center.val[ i ] = getF4( fp );
248 tmap->center.eindex = getVX( fp );
252 for ( i = 0; i < 3; i++ )
253 tmap->rotate.val[ i ] = getF4( fp );
254 tmap->rotate.eindex = getVX( fp );
258 tmap->fall_type = getU2( fp );
259 for ( i = 0; i < 3; i++ )
260 tmap->falloff.val[ i ] = getF4( fp );
261 tmap->falloff.eindex = getVX( fp );
265 tmap->ref_object = getS0( fp );
269 tmap->coord_sys = getU2( fp );
276 /* error while reading the current subchunk? */
279 if ( rlen < 0 || rlen > sz ) {
283 /* skip unread parts of the current subchunk */
286 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
289 /* end of the TMAP subchunk? */
291 if ( tmapsz <= _pico_memstream_tell( fp ) - pos ) {
295 /* get the next subchunk header */
300 if ( 6 != get_flen() ) {
305 set_flen( _pico_memstream_tell( fp ) - pos );
311 ======================================================================
314 Read an lwImageMap from a SURF.BLOK in an LWO2 file.
315 ====================================================================== */
317 int lwGetImageMap( picoMemStream_t *fp, int rsz, lwTexture *tex ){
322 pos = _pico_memstream_tell( fp );
325 if ( 0 > get_flen() ) {
335 if ( !lwGetTMap( fp, sz, &tex->tmap ) ) {
341 tex->param.imap.projection = getU2( fp );
345 tex->param.imap.vmap_name = getS0( fp );
349 tex->param.imap.axis = getU2( fp );
353 tex->param.imap.cindex = getVX( fp );
357 tex->param.imap.wrapw_type = getU2( fp );
358 tex->param.imap.wraph_type = getU2( fp );
362 tex->param.imap.wrapw.val = getF4( fp );
363 tex->param.imap.wrapw.eindex = getVX( fp );
367 tex->param.imap.wraph.val = getF4( fp );
368 tex->param.imap.wraph.eindex = getVX( fp );
372 tex->param.imap.aas_flags = getU2( fp );
373 tex->param.imap.aa_strength = getF4( fp );
377 tex->param.imap.pblend = getU2( fp );
381 tex->param.imap.stck.val = getF4( fp );
382 tex->param.imap.stck.eindex = getVX( fp );
386 tex->param.imap.amplitude.val = getF4( fp );
387 tex->param.imap.amplitude.eindex = getVX( fp );
394 /* error while reading the current subchunk? */
397 if ( rlen < 0 || rlen > sz ) {
401 /* skip unread parts of the current subchunk */
404 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
407 /* end of the image map? */
409 if ( rsz <= _pico_memstream_tell( fp ) - pos ) {
413 /* get the next subchunk header */
418 if ( 6 != get_flen() ) {
423 set_flen( _pico_memstream_tell( fp ) - pos );
429 ======================================================================
432 Read an lwProcedural from a SURF.BLOK in an LWO2 file.
433 ====================================================================== */
435 int lwGetProcedural( picoMemStream_t *fp, int rsz, lwTexture *tex ){
440 pos = _pico_memstream_tell( fp );
443 if ( 0 > get_flen() ) {
453 if ( !lwGetTMap( fp, sz, &tex->tmap ) ) {
459 tex->param.proc.axis = getU2( fp );
463 tex->param.proc.value[ 0 ] = getF4( fp );
465 tex->param.proc.value[ 1 ] = getF4( fp );
468 tex->param.proc.value[ 2 ] = getF4( fp );
473 tex->param.proc.name = getS0( fp );
475 tex->param.proc.data = getbytes( fp, sz - rlen );
482 /* error while reading the current subchunk? */
485 if ( rlen < 0 || rlen > sz ) {
489 /* skip unread parts of the current subchunk */
492 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
495 /* end of the procedural block? */
497 if ( rsz <= _pico_memstream_tell( fp ) - pos ) {
501 /* get the next subchunk header */
506 if ( 6 != get_flen() ) {
511 set_flen( _pico_memstream_tell( fp ) - pos );
517 ======================================================================
520 Read an lwGradient from a SURF.BLOK in an LWO2 file.
521 ====================================================================== */
523 int lwGetGradient( picoMemStream_t *fp, int rsz, lwTexture *tex ){
526 int rlen, pos, i, j, nkeys;
528 pos = _pico_memstream_tell( fp );
531 if ( 0 > get_flen() ) {
541 if ( !lwGetTMap( fp, sz, &tex->tmap ) ) {
547 tex->param.grad.paramname = getS0( fp );
551 tex->param.grad.itemname = getS0( fp );
555 tex->param.grad.start = getF4( fp );
559 tex->param.grad.end = getF4( fp );
563 tex->param.grad.repeat = getU2( fp );
567 nkeys = sz / sizeof( lwGradKey );
568 tex->param.grad.key = _pico_calloc( nkeys, sizeof( lwGradKey ) );
569 if ( !tex->param.grad.key ) {
572 for ( i = 0; i < nkeys; i++ ) {
573 tex->param.grad.key[ i ].value = getF4( fp );
574 for ( j = 0; j < 4; j++ )
575 tex->param.grad.key[ i ].rgba[ j ] = getF4( fp );
581 tex->param.grad.ikey = _pico_calloc( nkeys, sizeof( short ) );
582 if ( !tex->param.grad.ikey ) {
585 for ( i = 0; i < nkeys; i++ )
586 tex->param.grad.ikey[ i ] = getU2( fp );
593 /* error while reading the current subchunk? */
596 if ( rlen < 0 || rlen > sz ) {
600 /* skip unread parts of the current subchunk */
603 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
606 /* end of the gradient? */
608 if ( rsz <= _pico_memstream_tell( fp ) - pos ) {
612 /* get the next subchunk header */
617 if ( 6 != get_flen() ) {
622 set_flen( _pico_memstream_tell( fp ) - pos );
628 ======================================================================
631 Read an lwTexture from a SURF.BLOK in an LWO2 file.
632 ====================================================================== */
634 lwTexture *lwGetTexture( picoMemStream_t *fp, int bloksz, unsigned int type ){
639 tex = _pico_calloc( 1, sizeof( lwTexture ) );
645 tex->tmap.size.val[ 0 ] =
646 tex->tmap.size.val[ 1 ] =
647 tex->tmap.size.val[ 2 ] = 1.0f;
648 tex->opacity.val = 1.0f;
652 if ( !lwGetTHeader( fp, sz, tex ) ) {
657 sz = bloksz - sz - 6;
659 case ID_IMAP: ok = lwGetImageMap( fp, sz, tex ); break;
660 case ID_PROC: ok = lwGetProcedural( fp, sz, tex ); break;
661 case ID_GRAD: ok = lwGetGradient( fp, sz, tex ); break;
663 ok = !_pico_memstream_seek( fp, sz, PICO_SEEK_CUR );
667 lwFreeTexture( tex );
677 ======================================================================
680 Read a shader record from a SURF.BLOK in an LWO2 file.
681 ====================================================================== */
683 lwPlugin *lwGetShader( picoMemStream_t *fp, int bloksz ){
689 shdr = _pico_calloc( 1, sizeof( lwPlugin ) );
694 pos = _pico_memstream_tell( fp );
697 shdr->ord = getS0( fp );
700 if ( 0 > get_flen() ) {
707 if ( id == ID_ENAB ) {
708 shdr->flags = getU2( fp );
712 _pico_memstream_seek( fp, sz, PICO_SEEK_CUR );
720 if ( 0 > get_flen() ) {
730 shdr->name = getS0( fp );
732 shdr->data = getbytes( fp, sz - rlen );
739 /* error while reading the current subchunk? */
742 if ( rlen < 0 || rlen > sz ) {
746 /* skip unread parts of the current subchunk */
749 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
752 /* end of the shader block? */
754 if ( bloksz <= _pico_memstream_tell( fp ) - pos ) {
758 /* get the next subchunk header */
763 if ( 6 != get_flen() ) {
768 set_flen( _pico_memstream_tell( fp ) - pos );
772 lwFreePlugin( shdr );
778 ======================================================================
782 Callbacks for the lwListInsert() function, which is called to add
783 textures to surface channels and shaders to surfaces.
784 ====================================================================== */
786 static int compare_textures( lwTexture *a, lwTexture *b ){
787 return strcmp( a->ord, b->ord );
791 static int compare_shaders( lwPlugin *a, lwPlugin *b ){
792 return strcmp( a->ord, b->ord );
797 ======================================================================
800 Finds the surface channel (lwTParam or lwCParam) to which a texture is
801 applied, then calls lwListInsert().
802 ====================================================================== */
804 static int add_texture( lwSurface *surf, lwTexture *tex ){
807 switch ( tex->chan ) {
808 case ID_COLR: list = &surf->color.tex; break;
809 case ID_LUMI: list = &surf->luminosity.tex; break;
810 case ID_DIFF: list = &surf->diffuse.tex; break;
811 case ID_SPEC: list = &surf->specularity.tex; break;
812 case ID_GLOS: list = &surf->glossiness.tex; break;
813 case ID_REFL: list = &surf->reflection.val.tex; break;
814 case ID_TRAN: list = &surf->transparency.val.tex; break;
815 case ID_RIND: list = &surf->eta.tex; break;
816 case ID_TRNL: list = &surf->translucency.tex; break;
817 case ID_BUMP: list = &surf->bump.tex; break;
821 lwListInsert((void **) list, tex, (int (*)(void *, void *)) compare_textures);
827 ======================================================================
830 Allocate and initialize a surface.
831 ====================================================================== */
833 lwSurface *lwDefaultSurface( void ){
836 surf = _pico_calloc( 1, sizeof( lwSurface ) );
841 surf->color.rgb[ 0 ] = 0.78431f;
842 surf->color.rgb[ 1 ] = 0.78431f;
843 surf->color.rgb[ 2 ] = 0.78431f;
844 surf->diffuse.val = 1.0f;
845 surf->glossiness.val = 0.4f;
846 surf->bump.val = 1.0f;
847 surf->eta.val = 1.0f;
855 ======================================================================
858 Read an lwSurface from an LWO2 file.
859 ====================================================================== */
861 lwSurface *lwGetSurface( picoMemStream_t *fp, int cksize ){
865 unsigned int id, type;
870 /* allocate the Surface structure */
872 surf = _pico_calloc( 1, sizeof( lwSurface ) );
877 /* non-zero defaults */
879 surf->color.rgb[ 0 ] = 0.78431f;
880 surf->color.rgb[ 1 ] = 0.78431f;
881 surf->color.rgb[ 2 ] = 0.78431f;
882 surf->diffuse.val = 1.0f;
883 surf->glossiness.val = 0.4f;
884 surf->bump.val = 1.0f;
885 surf->eta.val = 1.0f;
888 /* remember where we started */
891 pos = _pico_memstream_tell( fp );
895 surf->name = getS0( fp );
896 surf->srcname = getS0( fp );
898 /* first subchunk header */
902 if ( 0 > get_flen() ) {
906 /* process subchunks as they're encountered */
914 surf->color.rgb[ 0 ] = getF4( fp );
915 surf->color.rgb[ 1 ] = getF4( fp );
916 surf->color.rgb[ 2 ] = getF4( fp );
917 surf->color.eindex = getVX( fp );
921 surf->luminosity.val = getF4( fp );
922 surf->luminosity.eindex = getVX( fp );
926 surf->diffuse.val = getF4( fp );
927 surf->diffuse.eindex = getVX( fp );
931 surf->specularity.val = getF4( fp );
932 surf->specularity.eindex = getVX( fp );
936 surf->glossiness.val = getF4( fp );
937 surf->glossiness.eindex = getVX( fp );
941 surf->reflection.val.val = getF4( fp );
942 surf->reflection.val.eindex = getVX( fp );
946 surf->reflection.options = getU2( fp );
950 surf->reflection.cindex = getVX( fp );
954 surf->reflection.seam_angle = getF4( fp );
958 surf->transparency.val.val = getF4( fp );
959 surf->transparency.val.eindex = getVX( fp );
963 surf->transparency.options = getU2( fp );
967 surf->transparency.cindex = getVX( fp );
971 surf->eta.val = getF4( fp );
972 surf->eta.eindex = getVX( fp );
976 surf->translucency.val = getF4( fp );
977 surf->translucency.eindex = getVX( fp );
981 surf->bump.val = getF4( fp );
982 surf->bump.eindex = getVX( fp );
986 surf->smooth = getF4( fp );
990 surf->sideflags = getU2( fp );
994 surf->color_hilite.val = getF4( fp );
995 surf->color_hilite.eindex = getVX( fp );
999 surf->color_filter.val = getF4( fp );
1000 surf->color_filter.eindex = getVX( fp );
1004 surf->add_trans.val = getF4( fp );
1005 surf->add_trans.eindex = getVX( fp );
1009 surf->dif_sharp.val = getF4( fp );
1010 surf->dif_sharp.eindex = getVX( fp );
1014 surf->glow.val = getF4( fp );
1015 surf->glow.eindex = getVX( fp );
1019 surf->line.enabled = 1;
1021 surf->line.flags = getU2( fp );
1024 surf->line.size.val = getF4( fp );
1027 surf->line.size.eindex = getVX( fp );
1032 surf->alpha_mode = getU2( fp );
1033 surf->alpha = getF4( fp );
1037 surf->alpha = getF4( fp );
1047 tex = lwGetTexture( fp, sz - 4, type );
1051 if ( !add_texture( surf, tex ) ) {
1052 lwFreeTexture( tex );
1054 set_flen( 4 + get_flen() );
1057 shdr = lwGetShader( fp, sz - 4 );
1061 lwListInsert((void **) &surf->shader, shdr, (int (*)(void *, void *)) compare_shaders);
1063 set_flen( 4 + get_flen() );
1072 /* error while reading current subchunk? */
1075 if ( rlen < 0 || rlen > sz ) {
1079 /* skip unread parts of the current subchunk */
1082 _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
1085 /* end of the SURF chunk? */
1087 if ( cksize <= _pico_memstream_tell( fp ) - pos ) {
1091 /* get the next subchunk header */
1096 if ( 6 != get_flen() ) {
1105 lwFreeSurface( surf );