/* ====================================================================== vmap.c Vertex map functions for an LWO2 reader. Ernie Wright 17 Sep 00 ====================================================================== */ #include "../picointernal.h" #include "lwo2.h" /* ====================================================================== lwFreeVMap() Free memory used by an lwVMap. ====================================================================== */ void lwFreeVMap( lwVMap *vmap ) { if ( vmap ) { if ( vmap->name ) _pico_free( vmap->name ); if ( vmap->vindex ) _pico_free( vmap->vindex ); if ( vmap->pindex ) _pico_free( vmap->pindex ); if ( vmap->val ) { if ( vmap->val[ 0 ] ) _pico_free( vmap->val[ 0 ] ); _pico_free( vmap->val ); } _pico_free( vmap ); } } /* ====================================================================== lwGetVMap() Read an lwVMap from a VMAP or VMAD chunk in an LWO2. ====================================================================== */ lwVMap *lwGetVMap( picoMemStream_t *fp, int cksize, int ptoffset, int poloffset, int perpoly ) { unsigned char *buf, *bp; lwVMap *vmap; float *f; int i, j, npts, rlen; /* read the whole chunk */ set_flen( 0 ); buf = getbytes( fp, cksize ); if ( !buf ) return NULL; vmap = _pico_calloc( 1, sizeof( lwVMap )); if ( !vmap ) { _pico_free( buf ); return NULL; } /* initialize the vmap */ vmap->perpoly = perpoly; bp = buf; set_flen( 0 ); vmap->type = sgetU4( &bp ); vmap->dim = sgetU2( &bp ); vmap->name = sgetS0( &bp ); rlen = get_flen(); /* count the vmap records */ npts = 0; while ( bp < buf + cksize ) { i = sgetVX( &bp ); if ( perpoly ) i = sgetVX( &bp ); bp += vmap->dim * sizeof( float ); ++npts; } /* allocate the vmap */ vmap->nverts = npts; vmap->vindex = _pico_calloc( npts, sizeof( int )); if ( !vmap->vindex ) goto Fail; if ( perpoly ) { vmap->pindex = _pico_calloc( npts, sizeof( int )); if ( !vmap->pindex ) goto Fail; } if ( vmap->dim > 0 ) { vmap->val = _pico_calloc( npts, sizeof( float * )); if ( !vmap->val ) goto Fail; f = _pico_alloc( npts * vmap->dim * sizeof( float )); if ( !f ) goto Fail; for ( i = 0; i < npts; i++ ) vmap->val[ i ] = f + i * vmap->dim; } /* fill in the vmap values */ bp = buf + rlen; for ( i = 0; i < npts; i++ ) { vmap->vindex[ i ] = sgetVX( &bp ); if ( perpoly ) vmap->pindex[ i ] = sgetVX( &bp ); for ( j = 0; j < vmap->dim; j++ ) vmap->val[ i ][ j ] = sgetF4( &bp ); } _pico_free( buf ); return vmap; Fail: if ( buf ) _pico_free( buf ); lwFreeVMap( vmap ); return NULL; } /* ====================================================================== lwGetPointVMaps() Fill in the lwVMapPt structure for each point. ====================================================================== */ int lwGetPointVMaps( lwPointList *point, lwVMap *vmap ) { lwVMap *vm; int i, j, n; /* count the number of vmap values for each point */ vm = vmap; while ( vm ) { if ( !vm->perpoly ) for ( i = 0; i < vm->nverts; i++ ) ++point->pt[ vm->vindex[ i ]].nvmaps; vm = vm->next; } /* allocate vmap references for each mapped point */ for ( i = 0; i < point->count; i++ ) { if ( point->pt[ i ].nvmaps ) { point->pt[ i ].vm = _pico_calloc( point->pt[ i ].nvmaps, sizeof( lwVMapPt )); if ( !point->pt[ i ].vm ) return 0; point->pt[ i ].nvmaps = 0; } } /* fill in vmap references for each mapped point */ vm = vmap; while ( vm ) { if ( !vm->perpoly ) { for ( i = 0; i < vm->nverts; i++ ) { j = vm->vindex[ i ]; n = point->pt[ j ].nvmaps; point->pt[ j ].vm[ n ].vmap = vm; point->pt[ j ].vm[ n ].index = i; ++point->pt[ j ].nvmaps; } } vm = vm->next; } return 1; } /* ====================================================================== lwGetPolyVMaps() Fill in the lwVMapPt structure for each polygon vertex. ====================================================================== */ int lwGetPolyVMaps( lwPolygonList *polygon, lwVMap *vmap ) { lwVMap *vm; lwPolVert *pv; int i, j; /* count the number of vmap values for each polygon vertex */ vm = vmap; while ( vm ) { if ( vm->perpoly ) { for ( i = 0; i < vm->nverts; i++ ) { for ( j = 0; j < polygon->pol[ vm->pindex[ i ]].nverts; j++ ) { pv = &polygon->pol[ vm->pindex[ i ]].v[ j ]; if ( vm->vindex[ i ] == pv->index ) { ++pv->nvmaps; break; } } } } vm = vm->next; } /* allocate vmap references for each mapped vertex */ for ( i = 0; i < polygon->count; i++ ) { for ( j = 0; j < polygon->pol[ i ].nverts; j++ ) { pv = &polygon->pol[ i ].v[ j ]; if ( pv->nvmaps ) { pv->vm = _pico_calloc( pv->nvmaps, sizeof( lwVMapPt )); if ( !pv->vm ) return 0; pv->nvmaps = 0; } } } /* fill in vmap references for each mapped point */ vm = vmap; while ( vm ) { if ( vm->perpoly ) { for ( i = 0; i < vm->nverts; i++ ) { for ( j = 0; j < polygon->pol[ vm->pindex[ i ]].nverts; j++ ) { pv = &polygon->pol[ vm->pindex[ i ]].v[ j ]; if ( vm->vindex[ i ] == pv->index ) { pv->vm[ pv->nvmaps ].vmap = vm; pv->vm[ pv->nvmaps ].index = i; ++pv->nvmaps; break; } } } } vm = vm->next; } return 1; }