/* * libmorph -- 3d modeler object files loader/saver library. * * Copyright (C) 1999 Kuba Winnicki * */ /* * morph.c: Routines to manage MorphModel's */ #include #include #include #include "morph.h" #include void morph_model_destroy( MorphModel* m ) { MorphSurface* curr, * next; int i; /* printf( "%x\n", m->triangle_indices ); */ free( m->vertices ); free( m->vnormals ); free( m->polygon_indices ); free( m->triangle_indices ); free( m->triangle_normals ); for( i = m->surface_count - 1; i >= 0; i-- ) { printf( "Freeing %s\n", m->surfaces[ i ].name ); free( m->surfaces[ i ].name ); } next = m->surfaces; while( next ) { curr = next; next = curr->next; // free( curr->name ); free( curr ); }; free( m ); } MorphModel* morph_model_new( MorphUnrefFunc* unref_fn ) { MorphModel* m; m = malloc( sizeof( MorphModel ) ); m->ref_count = 1; m->unref_fn = unref_fn; m->vertices = NULL; m->vnormals = NULL; m->vertices_len = 0; m->polygon_indices = NULL; m->polygon_indices_len = 0; m->triangle_indices = NULL; m->triangle_normals = NULL; m->triangle_indices_len = 0; m->surfaces = NULL; m->surface_count = 0; /* m->surfaces->name = NULL; */ return m; } void morph_model_ref( MorphModel* m ) { if( !m ) return; if( m->ref_count <= 0 ) return; m->ref_count++; } void morph_model_unref( MorphModel* m ) { if( !m ) return; if( m->ref_count <= 0 ) return; m->ref_count--; if( m->ref_count == 0 ) morph_model_destroy( m ); } /* MorphModel* morph_model_duplicate( const MorphModel* m ) { MorphObject* copy = malloc( sizeof( MorphModel ) ); copy->ref_count = 1; copy->unref_fn = m->unref_fn; copy->other_stuff = m->other_stuff; return copy; } */ /* * Helpful routines to byte swap arrays of 16-bit and 32-bit words */ void morph_byteswap32( void* ptr, unsigned int size ) { unsigned int* ptr32 = (unsigned int* )ptr; unsigned char* ptr8 = (unsigned char* )ptr; for( size >>= 2; size > 0; size-- ) { *ptr32++ = ( ptr8[ 0 ] << 24 ) | ( ptr8[ 1 ] << 16 ) | ( ptr8[ 2 ] << 8 ) | ptr8[ 3 ]; ptr8 += 4; } } void morph_byteswap16( void* ptr, unsigned int size ) { unsigned short* ptr16 = (unsigned short* )ptr; unsigned short tmp; for( size >>= 1; size > 0; size-- ) { tmp = *ptr16; tmp = ( tmp << 8 ) | ( tmp >> 8 ); *ptr16++ = tmp; } } /* * Convert polygon indices array to triangle indices array * * TODO: Scanning index array twice is some performance hit. * Currently we need that first pass to calc how much memory * has to be malloc'ed... Is the better way? Mempools? */ unsigned short* morph_make_triangles( MorphModel* m ) { unsigned short* dst; unsigned short* src = m->polygon_indices; unsigned short t, idx1, idx2, idx3; unsigned int n = 0; unsigned int triangle_indices_len = 0; unsigned int len; if( m->triangle_indices ) return m->triangle_indices; if( m->polygon_indices == NULL ) return NULL; for( len = m->polygon_indices_len; len > 0; len -= 4 + ( t << 1 ) ) { t = *src++; n += ( t - 2 ) * 6; src += t + 2; } m->triangle_indices = malloc( n ); m->triangle_indices_len = n; dst = m->triangle_indices; for( len = m->polygon_indices_len; len > 0; len -= 4 ) { t = *src++; len -= t << 1; //surf_num = src[ t ]; idx1 = *src++; idx3 = *src++; for( t -= 2; t > 0; t-- ) { *dst++ = idx1; *dst++ = idx2 = idx3; *dst++ = idx3 = *src++; } src++; /* skip surface number */ } return m->triangle_indices; } /* * TODO: * - normalize normals for speedup in viewer, * - with glShadeModel( GL_FLAT ); and using vertice normals, * things don't look quite as they should, i.e. like with face normals. * - maybe create morph_calc_normals function for calcing only face normals */ void morph_calc_vnormals( MorphModel* m ) { float u1, u2, u3, v1, v2, v3; int i, idx1, idx2, idx3; float* normals; if( m->vnormals ) return; if( !m->triangle_normals ) normals = m->triangle_normals = malloc( m->triangle_indices_len * 2 ); m->vnormals = calloc( 1, m->vertices_len ); for( i = 0; i < m->triangle_indices_len / 6; i++ ) { idx1 = 3 * m->triangle_indices[ i * 3 ]; idx2 = 3 * m->triangle_indices[ i * 3 + 1 ]; idx3 = 3 * m->triangle_indices[ i * 3 + 2 ]; u1 = m->vertices[ idx2 ] - m->vertices[ idx1 ]; v1 = m->vertices[ idx3 ] - m->vertices[ idx1 ]; u2 = m->vertices[ idx2 + 1 ] - m->vertices[ idx1 + 1 ]; v2 = m->vertices[ idx3 + 1 ] - m->vertices[ idx1 + 1 ]; u3 = m->vertices[ idx2 + 2 ] - m->vertices[ idx1 + 2 ]; v3 = m->vertices[ idx3 + 2 ] - m->vertices[ idx1 + 2 ]; *normals = u2 * v3 - u3 * v2; m->vnormals[ idx1 ] += *normals; m->vnormals[ idx2 ] += *normals; m->vnormals[ idx3 ] += *normals++; *normals = u3 * v1 - u1 * v3; m->vnormals[ idx1 + 1 ] += *normals; m->vnormals[ idx2 + 1 ] += *normals; m->vnormals[ idx3 + 1 ] += *normals++; *normals = u1 * v2 - u2 * v1; m->vnormals[ idx1 + 2 ] += *normals; m->vnormals[ idx2 + 2 ] += *normals; m->vnormals[ idx3 + 2 ] += *normals++; } } /* Find scale and center for display normalization */ /* * Convert polygon indices array to triangle indices array * As you can see currently not supported */ /* unsigned short* morph_make_polygons( MorphModel* m ) { if( m->polygon_indices ) return m->polygon_indices; if( m->triangle_indices == NULL ) return NULL; //... return( m->polygon_indices ); } */