gtkradiant/libs/picomodel/lwo/vmap.c

244 lines
5.8 KiB
C
Raw Normal View History

/*
======================================================================
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;
}