mirror of
https://github.com/TTimo/GtkRadiant.git
synced 2025-01-10 03:51:18 +00:00
Ported picomodel.c from 1.5
Improvements over 1.4/1.5 are in.
This commit is contained in:
parent
3fb0a994e2
commit
41f9d3a1e1
4 changed files with 593 additions and 222 deletions
|
@ -105,6 +105,7 @@ struct picoSurface_s
|
||||||
int numVertexes, maxVertexes;
|
int numVertexes, maxVertexes;
|
||||||
picoVec3_t *xyz;
|
picoVec3_t *xyz;
|
||||||
picoVec3_t *normal;
|
picoVec3_t *normal;
|
||||||
|
picoIndex_t *smoothingGroup;
|
||||||
|
|
||||||
int numSTArrays, maxSTArrays;
|
int numSTArrays, maxSTArrays;
|
||||||
picoVec2_t **st;
|
picoVec2_t **st;
|
||||||
|
@ -216,6 +217,9 @@ const picoModule_t **PicoModuleList( int *numModules );
|
||||||
|
|
||||||
picoModel_t *PicoLoadModel( char *name, int frameNum );
|
picoModel_t *PicoLoadModel( char *name, int frameNum );
|
||||||
|
|
||||||
|
typedef size_t(*PicoInputStreamReadFunc)(void* inputStream, unsigned char* buffer, size_t length);
|
||||||
|
picoModel_t* PicoModuleLoadModelStream(const picoModule_t* module, void* inputStream, PicoInputStreamReadFunc inputStreamRead, size_t streamLength, int frameNum);
|
||||||
|
|
||||||
|
|
||||||
/* model functions */
|
/* model functions */
|
||||||
picoModel_t *PicoNewModel( void );
|
picoModel_t *PicoNewModel( void );
|
||||||
|
|
|
@ -161,35 +161,22 @@ void *_pico_realloc( void **ptr, size_t oldSize, size_t newSize ){
|
||||||
* as custom clone size (the string is cropped to fit into mem
|
* as custom clone size (the string is cropped to fit into mem
|
||||||
* if needed). -sea
|
* if needed). -sea
|
||||||
*/
|
*/
|
||||||
char *_pico_clone_alloc( char *str, int size ){
|
char *_pico_clone_alloc(const char *str)
|
||||||
|
{
|
||||||
char* cloned;
|
char* cloned;
|
||||||
size_t cloneSize;
|
|
||||||
|
|
||||||
/* sanity check */
|
/* sanity check */
|
||||||
if ( str == NULL ) {
|
if (str == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
/* set real size of cloned string */
|
|
||||||
cloneSize = ( size < 0 ) ? strlen( str ) : size;
|
|
||||||
|
|
||||||
/* allocate memory */
|
/* allocate memory */
|
||||||
cloned = _pico_alloc( cloneSize + 1 ); /* bugfix! */
|
cloned = _pico_alloc(strlen(str) + 1);
|
||||||
if ( cloned == NULL ) {
|
if (cloned == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
/* zero out memory allocated by cloned string */
|
|
||||||
memset( cloned,0,cloneSize );
|
|
||||||
|
|
||||||
/* copy input string to cloned string */
|
/* copy input string to cloned string */
|
||||||
if ( cloneSize < strlen( str ) ) {
|
|
||||||
memcpy( cloned,str,cloneSize );
|
|
||||||
cloned[ cloneSize ] = '\0';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
strcpy(cloned, str);
|
strcpy(cloned, str);
|
||||||
}
|
|
||||||
/* return ptr to cloned string */
|
/* return ptr to cloned string */
|
||||||
return cloned;
|
return cloned;
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,7 +116,7 @@ extern void ( *_pico_ptr_print )( int, const char* );
|
||||||
void *_pico_alloc( size_t size );
|
void *_pico_alloc( size_t size );
|
||||||
void *_pico_calloc( size_t num, size_t size );
|
void *_pico_calloc( size_t num, size_t size );
|
||||||
void *_pico_realloc( void **ptr, size_t oldSize, size_t newSize );
|
void *_pico_realloc( void **ptr, size_t oldSize, size_t newSize );
|
||||||
char *_pico_clone_alloc( char *str, int size );
|
char *_pico_clone_alloc( char *str/*, int size*/ );
|
||||||
void _pico_free( void *ptr );
|
void _pico_free( void *ptr );
|
||||||
|
|
||||||
/* files */
|
/* files */
|
||||||
|
|
|
@ -143,7 +143,46 @@ void PicoSetPrintFunc( void ( *func )( int, const char* ) ){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
picoModel_t *PicoModuleLoadModel( const picoModule_t* pm, char* fileName, picoByte_t* buffer, int bufSize, int frameNum ){
|
||||||
|
char *modelFileName, *remapFileName;
|
||||||
|
|
||||||
|
/* see whether this module can load the model file or not */
|
||||||
|
if ( pm->canload( fileName, buffer, bufSize ) == PICO_PMV_OK ) {
|
||||||
|
/* use loader provided by module to read the model data */
|
||||||
|
picoModel_t* model = pm->load( fileName, frameNum, buffer, bufSize );
|
||||||
|
if ( model == NULL ) {
|
||||||
|
_pico_free_file( buffer );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* assign pointer to file format module */
|
||||||
|
model->module = pm;
|
||||||
|
|
||||||
|
/* get model file name */
|
||||||
|
modelFileName = PicoGetModelFileName( model );
|
||||||
|
|
||||||
|
/* apply model remappings from <model>.remap */
|
||||||
|
if ( strlen( modelFileName ) ) {
|
||||||
|
/* alloc copy of model file name */
|
||||||
|
remapFileName = _pico_alloc( strlen( modelFileName ) + 20 );
|
||||||
|
if ( remapFileName != NULL ) {
|
||||||
|
/* copy model file name and change extension */
|
||||||
|
strcpy( remapFileName, modelFileName );
|
||||||
|
_pico_setfext( remapFileName, "remap" );
|
||||||
|
|
||||||
|
/* try to remap model; we don't handle the result */
|
||||||
|
PicoRemapModel( model, remapFileName );
|
||||||
|
|
||||||
|
/* free the remap file name string */
|
||||||
|
_pico_free( remapFileName );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
PicoLoadModel()
|
PicoLoadModel()
|
||||||
|
@ -155,7 +194,6 @@ picoModel_t *PicoLoadModel( char *fileName, int frameNum ){
|
||||||
picoModel_t *model;
|
picoModel_t *model;
|
||||||
picoByte_t *buffer;
|
picoByte_t *buffer;
|
||||||
int bufSize;
|
int bufSize;
|
||||||
char *modelFileName, *remapFileName;
|
|
||||||
|
|
||||||
|
|
||||||
/* init */
|
/* init */
|
||||||
|
@ -194,38 +232,8 @@ picoModel_t *PicoLoadModel( char *fileName, int frameNum ){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* see whether this module can load the model file or not */
|
model = PicoModuleLoadModel( pm, fileName, buffer, bufSize, frameNum );
|
||||||
if ( pm->canload( fileName, buffer, bufSize ) == PICO_PMV_OK ) {
|
if ( model != NULL ) {
|
||||||
/* use loader provided by module to read the model data */
|
|
||||||
model = pm->load( fileName, frameNum, buffer, bufSize );
|
|
||||||
if ( model == NULL ) {
|
|
||||||
_pico_free_file( buffer );
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* assign pointer to file format module */
|
|
||||||
model->module = pm;
|
|
||||||
|
|
||||||
/* get model file name */
|
|
||||||
modelFileName = PicoGetModelFileName( model );
|
|
||||||
|
|
||||||
/* apply model remappings from <model>.remap */
|
|
||||||
if ( strlen( modelFileName ) ) {
|
|
||||||
/* alloc copy of model file name */
|
|
||||||
remapFileName = _pico_alloc( strlen( modelFileName ) + 20 );
|
|
||||||
if ( remapFileName != NULL ) {
|
|
||||||
/* copy model file name and change extension */
|
|
||||||
strcpy( remapFileName, modelFileName );
|
|
||||||
_pico_setfext( remapFileName, "remap" );
|
|
||||||
|
|
||||||
/* try to remap model; we don't handle the result */
|
|
||||||
PicoRemapModel( model, remapFileName );
|
|
||||||
|
|
||||||
/* free the remap file name string */
|
|
||||||
_pico_free( remapFileName );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* model was loaded, so break out of loop */
|
/* model was loaded, so break out of loop */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -236,7 +244,53 @@ picoModel_t *PicoLoadModel( char *fileName, int frameNum ){
|
||||||
_pico_free_file( buffer );
|
_pico_free_file( buffer );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return */
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
FIXME: From 1.5; Unused yet
|
||||||
|
*/
|
||||||
|
|
||||||
|
picoModel_t *PicoModuleLoadModelStream( const picoModule_t* module, void* inputStream, PicoInputStreamReadFunc inputStreamRead, size_t streamLength, int frameNum )
|
||||||
|
{
|
||||||
|
picoModel_t *model;
|
||||||
|
picoByte_t *buffer;
|
||||||
|
int bufSize;
|
||||||
|
|
||||||
|
/* init */
|
||||||
|
model = NULL;
|
||||||
|
|
||||||
|
if ( inputStream == NULL )
|
||||||
|
{
|
||||||
|
_pico_printf( PICO_ERROR, "PicoLoadModel: invalid input stream (inputStream == NULL)" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( inputStreamRead == NULL )
|
||||||
|
{
|
||||||
|
_pico_printf( PICO_ERROR, "PicoLoadModel: invalid input stream (inputStreamRead == NULL) ");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = _pico_alloc( streamLength + 1 );
|
||||||
|
|
||||||
|
bufSize = (int)inputStreamRead( inputStream, buffer, streamLength );
|
||||||
|
buffer[ bufSize ] = '\0';
|
||||||
|
|
||||||
|
{
|
||||||
|
// dummy filename
|
||||||
|
char fileName[128];
|
||||||
|
fileName[0] = '.';
|
||||||
|
strncpy( fileName + 1, module->defaultExts[ 0 ], 126 );
|
||||||
|
fileName[127] = '\0';
|
||||||
|
model = PicoModuleLoadModel( module, fileName, buffer, bufSize, frameNum );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free memory used by file buffer */
|
||||||
|
if ( model != 0 ) {
|
||||||
|
_pico_free( buffer );
|
||||||
|
}
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +337,6 @@ picoModel_t *PicoNewModel( void ){
|
||||||
void PicoFreeModel( picoModel_t *model ){
|
void PicoFreeModel( picoModel_t *model ){
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
||||||
/* sanity check */
|
/* sanity check */
|
||||||
if ( model == NULL ) {
|
if ( model == NULL ) {
|
||||||
return;
|
return;
|
||||||
|
@ -294,6 +347,10 @@ void PicoFreeModel( picoModel_t *model ){
|
||||||
_pico_free( model->name );
|
_pico_free( model->name );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( model->fileName ) {
|
||||||
|
_pico_free( model->fileName );
|
||||||
|
}
|
||||||
|
|
||||||
/* free shaders */
|
/* free shaders */
|
||||||
for ( i = 0; i < model->numShaders; i++ )
|
for ( i = 0; i < model->numShaders; i++ )
|
||||||
PicoFreeShader( model->shader[ i ] );
|
PicoFreeShader( model->shader[ i ] );
|
||||||
|
@ -444,7 +501,6 @@ void PicoFreeShader( picoShader_t *shader ){
|
||||||
picoShader_t *PicoFindShader( picoModel_t *model, char *name, int caseSensitive ){
|
picoShader_t *PicoFindShader( picoModel_t *model, char *name, int caseSensitive ){
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
||||||
/* sanity checks */
|
/* sanity checks */
|
||||||
if ( model == NULL || name == NULL ) { /* sea: null name fix */
|
if ( model == NULL || name == NULL ) { /* sea: null name fix */
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -535,9 +591,14 @@ void PicoFreeSurface( picoSurface_t *surface ){
|
||||||
/* free bits */
|
/* free bits */
|
||||||
_pico_free( surface->xyz );
|
_pico_free( surface->xyz );
|
||||||
_pico_free( surface->normal );
|
_pico_free( surface->normal );
|
||||||
|
_pico_free( surface->smoothingGroup );
|
||||||
_pico_free( surface->index );
|
_pico_free( surface->index );
|
||||||
_pico_free( surface->faceNormal );
|
_pico_free( surface->faceNormal );
|
||||||
|
|
||||||
|
if ( surface->name ) {
|
||||||
|
_pico_free( surface->name );
|
||||||
|
}
|
||||||
|
|
||||||
/* free arrays */
|
/* free arrays */
|
||||||
for ( i = 0; i < surface->numSTArrays; i++ )
|
for ( i = 0; i < surface->numSTArrays; i++ )
|
||||||
_pico_free( surface->st[ i ] );
|
_pico_free( surface->st[ i ] );
|
||||||
|
@ -591,6 +652,9 @@ int PicoAdjustSurface( picoSurface_t *surface, int numVertexes, int numSTArrays,
|
||||||
if ( !_pico_realloc( (void *) &surface->normal, surface->numVertexes * sizeof( *surface->normal ), surface->maxVertexes * sizeof( *surface->normal ) ) ) {
|
if ( !_pico_realloc( (void *) &surface->normal, surface->numVertexes * sizeof( *surface->normal ), surface->maxVertexes * sizeof( *surface->normal ) ) ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if ( !_pico_realloc( (void *) &surface->smoothingGroup, surface->numVertexes * sizeof( *surface->smoothingGroup ), surface->maxVertexes * sizeof( *surface->smoothingGroup ) ) ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
for ( i = 0; i < surface->numSTArrays; i++ )
|
for ( i = 0; i < surface->numSTArrays; i++ )
|
||||||
if ( !_pico_realloc( (void*) &surface->st[ i ], surface->numVertexes * sizeof( *surface->st[ i ] ), surface->maxVertexes * sizeof( *surface->st[ i ] ) ) ) {
|
if ( !_pico_realloc( (void*) &surface->st[ i ], surface->numVertexes * sizeof( *surface->st[ i ] ), surface->maxVertexes * sizeof( *surface->st[ i ] ) ) ) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -720,7 +784,7 @@ void PicoSetModelName( picoModel_t *model, char *name ){
|
||||||
_pico_free( model->name );
|
_pico_free( model->name );
|
||||||
}
|
}
|
||||||
|
|
||||||
model->name = _pico_clone_alloc( name,-1 );
|
model->name = _pico_clone_alloc( name/*,-1*/ );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -733,7 +797,7 @@ void PicoSetModelFileName( picoModel_t *model, char *fileName ){
|
||||||
_pico_free( model->fileName );
|
_pico_free( model->fileName );
|
||||||
}
|
}
|
||||||
|
|
||||||
model->fileName = _pico_clone_alloc( fileName,-1 );
|
model->fileName = _pico_clone_alloc( fileName/*,-1*/ );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -773,7 +837,7 @@ void PicoSetShaderName( picoShader_t *shader, char *name ){
|
||||||
_pico_free( shader->name );
|
_pico_free( shader->name );
|
||||||
}
|
}
|
||||||
|
|
||||||
shader->name = _pico_clone_alloc( name,-1 );
|
shader->name = _pico_clone_alloc( name/*,-1*/ );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -786,7 +850,7 @@ void PicoSetShaderMapName( picoShader_t *shader, char *mapName ){
|
||||||
_pico_free( shader->mapName );
|
_pico_free( shader->mapName );
|
||||||
}
|
}
|
||||||
|
|
||||||
shader->mapName = _pico_clone_alloc( mapName,-1 );
|
shader->mapName = _pico_clone_alloc( mapName/*,-1*/ );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -887,7 +951,7 @@ void PicoSetSurfaceName( picoSurface_t *surface, char *name ){
|
||||||
_pico_free( surface->name );
|
_pico_free( surface->name );
|
||||||
}
|
}
|
||||||
|
|
||||||
surface->name = _pico_clone_alloc( name,-1 );
|
surface->name = _pico_clone_alloc( name/*,-1*/ );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -990,6 +1054,15 @@ void PicoSetFaceNormal( picoSurface_t *surface, int num, picoVec3_t normal ){
|
||||||
_pico_copy_vec( normal, surface->faceNormal[ num ] );
|
_pico_copy_vec( normal, surface->faceNormal[ num ] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PicoSetSurfaceSmoothingGroup( picoSurface_t *surface, int num, picoIndex_t smoothingGroup ){
|
||||||
|
if ( num < 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
surface->smoothingGroup[ num ] = smoothingGroup;
|
||||||
|
}
|
||||||
|
|
||||||
void PicoSetSurfaceSpecial( picoSurface_t *surface, int num, int special ){
|
void PicoSetSurfaceSpecial( picoSurface_t *surface, int num, int special ){
|
||||||
if ( surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL ) {
|
if ( surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL ) {
|
||||||
|
@ -1335,6 +1408,12 @@ picoVec_t *PicoGetFaceNormal( picoSurface_t *surface, int num ){
|
||||||
return surface->faceNormal[ num ];
|
return surface->faceNormal[ num ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
picoIndex_t PicoGetSurfaceSmoothingGroup( picoSurface_t *surface, int num ){
|
||||||
|
if ( surface == NULL || num < 0 || num > surface->numVertexes ) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return surface->smoothingGroup[ num ];
|
||||||
|
}
|
||||||
|
|
||||||
int PicoGetSurfaceSpecial( picoSurface_t *surface, int num ){
|
int PicoGetSurfaceSpecial( picoSurface_t *surface, int num ){
|
||||||
if ( surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL ) {
|
if ( surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL ) {
|
||||||
|
@ -1535,7 +1614,7 @@ picoVertexCombinationHash_t *PicoAddVertexCombinationToHashTable( picoVertexComb
|
||||||
fixme: needs non-naive algorithm
|
fixme: needs non-naive algorithm
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int PicoFindSurfaceVertexNum( picoSurface_t *surface, picoVec3_t xyz, picoVec3_t normal, int numSTs, picoVec2_t *st, int numColors, picoColor_t *color ){
|
int PicoFindSurfaceVertexNum( picoSurface_t *surface, picoVec3_t xyz, picoVec3_t normal, int numSTs, picoVec2_t *st, int numColors, picoColor_t *color, picoIndex_t smoothingGroup ){
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1557,6 +1636,11 @@ int PicoFindSurfaceVertexNum( picoSurface_t *surface, picoVec3_t xyz, picoVec3_t
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check normal */
|
||||||
|
if ( surface->smoothingGroup[ i ] != smoothingGroup ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* check st */
|
/* check st */
|
||||||
if ( numSTs > 0 && st != NULL ) {
|
if ( numSTs > 0 && st != NULL ) {
|
||||||
for ( j = 0; j < numSTs; j++ )
|
for ( j = 0; j < numSTs; j++ )
|
||||||
|
@ -1598,126 +1682,420 @@ int PicoFindSurfaceVertexNum( picoSurface_t *surface, picoVec3_t xyz, picoVec3_t
|
||||||
fixes broken normals (certain formats bork normals)
|
fixes broken normals (certain formats bork normals)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MAX_NORMAL_VOTES 128
|
//#define MAX_NORMAL_VOTES 128
|
||||||
#define EQUAL_NORMAL_EPSILON 0.01
|
//#define EQUAL_NORMAL_EPSILON 0.01
|
||||||
#define BAD_NORMAL_EPSILON 0.5
|
//#define BAD_NORMAL_EPSILON 0.5
|
||||||
|
//
|
||||||
|
//void PicoFixSurfaceNormals( picoSurface_t *surface ){
|
||||||
|
// int i, j, k, a, b, c, numVotes, faceIndex;
|
||||||
|
// picoVec3_t votes[ MAX_NORMAL_VOTES ];
|
||||||
|
// picoVec3_t *normals, diff;
|
||||||
|
// picoVec4_t plane;
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// /* dummy check */
|
||||||
|
// if ( surface == NULL || surface->numVertexes == 0 ) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /* fixme: handle other surface types */
|
||||||
|
// if ( surface->type != PICO_TRIANGLES ) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /* allocate normal storage */
|
||||||
|
// normals = _pico_alloc( surface->numVertexes * sizeof( *normals ) );
|
||||||
|
// if ( normals == NULL ) {
|
||||||
|
// _pico_printf( PICO_ERROR, "PicoFixSurfaceNormals: Unable to allocate memory for temporary normal storage" );
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /* zero it out */
|
||||||
|
// memset( normals, 0, surface->numVertexes * sizeof( *normals ) );
|
||||||
|
//
|
||||||
|
// /* walk vertex list */
|
||||||
|
// for ( i = 0; i < surface->numVertexes; i++ )
|
||||||
|
// {
|
||||||
|
// /* zero out votes */
|
||||||
|
// numVotes = 0;
|
||||||
|
//
|
||||||
|
// /* find all the triangles that reference this vertex */
|
||||||
|
// for ( j = 0, faceIndex = 0; j < surface->numIndexes; j += 3, faceIndex++ )
|
||||||
|
// {
|
||||||
|
// /* get triangle */
|
||||||
|
// a = surface->index[ j ];
|
||||||
|
// b = surface->index[ j + 1 ];
|
||||||
|
// c = surface->index[ j + 2 ];
|
||||||
|
//
|
||||||
|
// /* ignore degenerate triangles */
|
||||||
|
// if ( a == b || b == c || c == a ) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /* ignore indexes out of range */
|
||||||
|
// if ( a < 0 || a >= surface->numVertexes ||
|
||||||
|
// b < 0 || b >= surface->numVertexes ||
|
||||||
|
// c < 0 || c >= surface->numVertexes ) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /* test triangle */
|
||||||
|
// if ( a == i || b == i || c == i ) {
|
||||||
|
// /* if this surface has face normals */
|
||||||
|
// if ( surface->numFaceNormals && faceIndex < surface->numFaceNormals ) {
|
||||||
|
// _pico_copy_vec( surface->faceNormal[ faceIndex ], plane );
|
||||||
|
// if ( plane[ 0 ] == 0.f && plane[ 1 ] == 0.f && plane[ 2 ] == 0.f ) {
|
||||||
|
// /* if null normal, make plane from the 3 points */
|
||||||
|
// if ( _pico_calc_plane( plane, surface->xyz[ a ], surface->xyz[ b ], surface->xyz[ c ] ) == 0 ) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// /* make a plane from the 3 points */
|
||||||
|
// else if ( _pico_calc_plane( plane, surface->xyz[ a ], surface->xyz[ b ], surface->xyz[ c ] ) == 0 ) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /* see if this normal has already been voted */
|
||||||
|
// for ( k = 0; k < numVotes; k++ )
|
||||||
|
// {
|
||||||
|
// _pico_subtract_vec( plane, votes[ k ], diff );
|
||||||
|
// if ( fabs( diff[ 0 ] ) < EQUAL_NORMAL_EPSILON &&
|
||||||
|
// fabs( diff[ 1 ] ) < EQUAL_NORMAL_EPSILON &&
|
||||||
|
// fabs( diff[ 2 ] ) < EQUAL_NORMAL_EPSILON ) {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /* add a new vote? */
|
||||||
|
// if ( k == numVotes && numVotes < MAX_NORMAL_VOTES ) {
|
||||||
|
// _pico_copy_vec( plane, votes[ numVotes ] );
|
||||||
|
// numVotes++;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /* tally votes */
|
||||||
|
// if ( numVotes > 0 ) {
|
||||||
|
// /* create average normal */
|
||||||
|
// _pico_zero_vec( normals[ i ] );
|
||||||
|
// for ( k = 0; k < numVotes; k++ )
|
||||||
|
// _pico_add_vec( normals[ i ], votes[ k ], normals[ i ] );
|
||||||
|
//
|
||||||
|
// /* normalize it */
|
||||||
|
// if ( _pico_normalize_vec( normals[ i ] ) ) {
|
||||||
|
// /* test against actual normal */
|
||||||
|
// if ( fabs( _pico_dot_vec( normals[ i ], surface->normal[ i ] ) - 1 ) > BAD_NORMAL_EPSILON ) {
|
||||||
|
// //% printf( "Normal %8d: (%f %f %f) -> (%f %f %f)\n", i,
|
||||||
|
// //% surface->normal[ i ][ 0 ], surface->normal[ i ][ 1 ], surface->normal[ i ][ 2 ],
|
||||||
|
// //% normals[ i ][ 0 ], normals[ i ][ 1 ], normals[ i ][ 2 ] );
|
||||||
|
// _pico_copy_vec( normals[ i ], surface->normal[ i ] );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /* free normal storage */
|
||||||
|
// _pico_free( normals );
|
||||||
|
//}
|
||||||
|
|
||||||
|
typedef struct _IndexArray IndexArray;
|
||||||
|
struct _IndexArray
|
||||||
|
{
|
||||||
|
picoIndex_t* data;
|
||||||
|
picoIndex_t* last;
|
||||||
|
};
|
||||||
|
|
||||||
|
void indexarray_push_back(IndexArray* self, picoIndex_t value) {
|
||||||
|
*self->last++ = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t indexarray_size(IndexArray* self) {
|
||||||
|
return self->last - self->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void indexarray_reserve(IndexArray* self, size_t size) {
|
||||||
|
self->data = self->last = _pico_calloc(size, sizeof(picoIndex_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void indexarray_clear(IndexArray* self) {
|
||||||
|
_pico_free(self->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct _BinaryTreeNode BinaryTreeNode;
|
||||||
|
struct _BinaryTreeNode
|
||||||
|
{
|
||||||
|
picoIndex_t left;
|
||||||
|
picoIndex_t right;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _BinaryTree BinaryTree;
|
||||||
|
struct _BinaryTree
|
||||||
|
{
|
||||||
|
BinaryTreeNode* data;
|
||||||
|
BinaryTreeNode* last;
|
||||||
|
};
|
||||||
|
|
||||||
|
void binarytree_extend(BinaryTree* self) {
|
||||||
|
self->last->left = 0;
|
||||||
|
self->last->right = 0;
|
||||||
|
++self->last;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t binarytree_size(BinaryTree* self) {
|
||||||
|
return self->last - self->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void binarytree_reserve(BinaryTree* self, size_t size) {
|
||||||
|
self->data = self->last = _pico_calloc(size, sizeof(BinaryTreeNode));
|
||||||
|
}
|
||||||
|
|
||||||
|
void binarytree_clear(BinaryTree* self) {
|
||||||
|
_pico_free(self->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef int(*LessFunc)(void*, picoIndex_t, picoIndex_t);
|
||||||
|
|
||||||
|
typedef struct _UniqueIndices UniqueIndices;
|
||||||
|
struct _UniqueIndices
|
||||||
|
{
|
||||||
|
BinaryTree tree;
|
||||||
|
IndexArray indices;
|
||||||
|
LessFunc lessFunc;
|
||||||
|
void* lessData;
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t UniqueIndices_size(UniqueIndices* self) {
|
||||||
|
return binarytree_size(&self->tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UniqueIndices_reserve(UniqueIndices* self, size_t size) {
|
||||||
|
binarytree_reserve(&self->tree, size);
|
||||||
|
indexarray_reserve(&self->indices, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UniqueIndices_init(UniqueIndices* self, LessFunc lessFunc, void* lessData) {
|
||||||
|
self->lessFunc = lessFunc;
|
||||||
|
self->lessData = lessData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UniqueIndices_destroy(UniqueIndices* self) {
|
||||||
|
binarytree_clear(&self->tree);
|
||||||
|
indexarray_clear(&self->indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
picoIndex_t UniqueIndices_find_or_insert(UniqueIndices* self, picoIndex_t value) {
|
||||||
|
picoIndex_t index = 0;
|
||||||
|
|
||||||
|
for (;; )
|
||||||
|
{
|
||||||
|
if (self->lessFunc(self->lessData, value, self->indices.data[index])) {
|
||||||
|
BinaryTreeNode* node = self->tree.data + index;
|
||||||
|
if (node->left != 0) {
|
||||||
|
index = node->left;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node->left = (picoIndex_t)binarytree_size(&self->tree);
|
||||||
|
binarytree_extend(&self->tree);
|
||||||
|
indexarray_push_back(&self->indices, value);
|
||||||
|
return node->left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (self->lessFunc(self->lessData, self->indices.data[index], value)) {
|
||||||
|
BinaryTreeNode* node = self->tree.data + index;
|
||||||
|
if (node->right != 0) {
|
||||||
|
index = node->right;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node->right = (picoIndex_t)binarytree_size(&self->tree);
|
||||||
|
binarytree_extend(&self->tree);
|
||||||
|
indexarray_push_back(&self->indices, value);
|
||||||
|
return node->right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
picoIndex_t UniqueIndices_insert(UniqueIndices* self, picoIndex_t value) {
|
||||||
|
if (self->tree.data == self->tree.last) {
|
||||||
|
binarytree_extend(&self->tree);
|
||||||
|
indexarray_push_back(&self->indices, value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return UniqueIndices_find_or_insert(self, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct picoSmoothVertices_s picoSmoothVertices_t;
|
||||||
|
struct picoSmoothVertices_s
|
||||||
|
{
|
||||||
|
picoVec3_t* xyz;
|
||||||
|
picoIndex_t* smoothingGroups;
|
||||||
|
};
|
||||||
|
|
||||||
|
int lessSmoothVertex(void* data, picoIndex_t first, picoIndex_t second) {
|
||||||
|
picoSmoothVertices_t* smoothVertices = data;
|
||||||
|
|
||||||
|
if (smoothVertices->xyz[first][0] != smoothVertices->xyz[second][0]) {
|
||||||
|
return smoothVertices->xyz[first][0] < smoothVertices->xyz[second][0];
|
||||||
|
}
|
||||||
|
if (smoothVertices->xyz[first][1] != smoothVertices->xyz[second][1]) {
|
||||||
|
return smoothVertices->xyz[first][1] < smoothVertices->xyz[second][1];
|
||||||
|
}
|
||||||
|
if (smoothVertices->xyz[first][2] != smoothVertices->xyz[second][2]) {
|
||||||
|
return smoothVertices->xyz[first][2] < smoothVertices->xyz[second][2];
|
||||||
|
}
|
||||||
|
if (smoothVertices->smoothingGroups[first] != smoothVertices->smoothingGroups[second]) {
|
||||||
|
return smoothVertices->smoothingGroups[first] < smoothVertices->smoothingGroups[second];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _pico_vertices_combine_shared_normals(picoVec3_t* xyz, picoIndex_t* smoothingGroups, picoVec3_t* normals, picoIndex_t numVertices) {
|
||||||
|
UniqueIndices vertices;
|
||||||
|
IndexArray indices;
|
||||||
|
picoSmoothVertices_t smoothVertices = { xyz, smoothingGroups };
|
||||||
|
UniqueIndices_init(&vertices, lessSmoothVertex, &smoothVertices);
|
||||||
|
UniqueIndices_reserve(&vertices, numVertices);
|
||||||
|
indexarray_reserve(&indices, numVertices);
|
||||||
|
|
||||||
|
{
|
||||||
|
picoIndex_t i = 0;
|
||||||
|
for (; i < numVertices; ++i)
|
||||||
|
{
|
||||||
|
size_t size = UniqueIndices_size(&vertices);
|
||||||
|
picoIndex_t index = UniqueIndices_insert(&vertices, i);
|
||||||
|
if ((size_t)index != size) {
|
||||||
|
float* normal = normals[vertices.indices.data[index]];
|
||||||
|
_pico_add_vec(normal, normals[i], normal);
|
||||||
|
}
|
||||||
|
indexarray_push_back(&indices, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
picoIndex_t maxIndex = 0;
|
||||||
|
picoIndex_t* i = indices.data;
|
||||||
|
for (; i != indices.last; ++i)
|
||||||
|
{
|
||||||
|
if (*i <= maxIndex) {
|
||||||
|
_pico_copy_vec(normals[vertices.indices.data[*i]], normals[i - indices.data]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
maxIndex = *i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UniqueIndices_destroy(&vertices);
|
||||||
|
indexarray_clear(&indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef picoVec3_t* picoNormalIter_t;
|
||||||
|
typedef picoIndex_t* picoIndexIter_t;
|
||||||
|
|
||||||
|
#define THE_CROSSPRODUCTS_OF_ANY_PAIR_OF_EDGES_OF_A_GIVEN_TRIANGLE_ARE_EQUAL 1
|
||||||
|
|
||||||
|
void _pico_triangles_generate_weighted_normals(picoIndexIter_t first, picoIndexIter_t end, picoVec3_t* xyz, picoVec3_t* normals) {
|
||||||
|
for (; first != end; first += 3)
|
||||||
|
{
|
||||||
|
#if (THE_CROSSPRODUCTS_OF_ANY_PAIR_OF_EDGES_OF_A_GIVEN_TRIANGLE_ARE_EQUAL)
|
||||||
|
picoVec3_t weightedNormal;
|
||||||
|
{
|
||||||
|
float* a = xyz[*(first + 0)];
|
||||||
|
float* b = xyz[*(first + 1)];
|
||||||
|
float* c = xyz[*(first + 2)];
|
||||||
|
picoVec3_t ba, ca;
|
||||||
|
_pico_subtract_vec(b, a, ba);
|
||||||
|
_pico_subtract_vec(c, a, ca);
|
||||||
|
_pico_cross_vec(ca, ba, weightedNormal);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
int j = 0;
|
||||||
|
for (; j < 3; ++j)
|
||||||
|
{
|
||||||
|
float* normal = normals[*(first + j)];
|
||||||
|
#if ( !THE_CROSSPRODUCTS_OF_ANY_PAIR_OF_EDGES_OF_A_GIVEN_TRIANGLE_ARE_EQUAL )
|
||||||
|
picoVec3_t weightedNormal;
|
||||||
|
{
|
||||||
|
float* a = xyz[*(first + ((j + 0) % 3))];
|
||||||
|
float* b = xyz[*(first + ((j + 1) % 3))];
|
||||||
|
float* c = xyz[*(first + ((j + 2) % 3))];
|
||||||
|
picoVec3_t ba, ca;
|
||||||
|
_pico_subtract_vec(b, a, ba);
|
||||||
|
_pico_subtract_vec(c, a, ca);
|
||||||
|
_pico_cross_vec(ca, ba, weightedNormal);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
_pico_add_vec(weightedNormal, normal, normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _pico_normals_zero(picoNormalIter_t first, picoNormalIter_t last) {
|
||||||
|
for (; first != last; ++first)
|
||||||
|
{
|
||||||
|
_pico_zero_vec(*first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _pico_normals_normalize(picoNormalIter_t first, picoNormalIter_t last) {
|
||||||
|
for (; first != last; ++first)
|
||||||
|
{
|
||||||
|
_pico_normalize_vec(*first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double _pico_length_vec(picoVec3_t vec) {
|
||||||
|
return sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NORMAL_UNIT_LENGTH_EPSILON 0.01
|
||||||
|
#define FLOAT_EQUAL_EPSILON( f, other, epsilon ) ( fabs( f - other ) < epsilon )
|
||||||
|
|
||||||
|
int _pico_normal_is_unit_length(picoVec3_t normal) {
|
||||||
|
return FLOAT_EQUAL_EPSILON(_pico_length_vec(normal), 1.0, NORMAL_UNIT_LENGTH_EPSILON);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _pico_normal_within_tolerance(picoVec3_t normal, picoVec3_t other) {
|
||||||
|
return _pico_dot_vec(normal, other) > 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _pico_normals_assign_generated_normals(picoNormalIter_t first, picoNormalIter_t last, picoNormalIter_t generated) {
|
||||||
|
for (; first != last; ++first, ++generated)
|
||||||
|
{
|
||||||
|
if (!_pico_normal_is_unit_length(*first) || !_pico_normal_within_tolerance(*first, *generated)) {
|
||||||
|
_pico_copy_vec(*generated, *first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PicoFixSurfaceNormals(picoSurface_t* surface) {
|
void PicoFixSurfaceNormals(picoSurface_t* surface) {
|
||||||
int i, j, k, a, b, c, numVotes, faceIndex;
|
picoVec3_t* normals = (picoVec3_t*)_pico_calloc(surface->numVertexes, sizeof(picoVec3_t));
|
||||||
picoVec3_t votes[ MAX_NORMAL_VOTES ];
|
|
||||||
picoVec3_t *normals, diff;
|
|
||||||
picoVec4_t plane;
|
|
||||||
|
|
||||||
|
_pico_normals_zero(normals, normals + surface->numVertexes);
|
||||||
|
|
||||||
/* dummy check */
|
_pico_triangles_generate_weighted_normals(surface->index, surface->index + surface->numIndexes, surface->xyz, normals);
|
||||||
if ( surface == NULL || surface->numVertexes == 0 ) {
|
_pico_vertices_combine_shared_normals(surface->xyz, surface->smoothingGroup, normals, surface->numVertexes);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fixme: handle other surface types */
|
_pico_normals_normalize(normals, normals + surface->numVertexes);
|
||||||
if ( surface->type != PICO_TRIANGLES ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allocate normal storage */
|
_pico_normals_assign_generated_normals(surface->normal, surface->normal + surface->numVertexes, normals);
|
||||||
normals = _pico_alloc( surface->numVertexes * sizeof( *normals ) );
|
|
||||||
if ( normals == NULL ) {
|
|
||||||
_pico_printf( PICO_ERROR, "PicoFixSurfaceNormals: Unable to allocate memory for temporary normal storage" );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* zero it out */
|
|
||||||
memset( normals, 0, surface->numVertexes * sizeof( *normals ) );
|
|
||||||
|
|
||||||
/* walk vertex list */
|
|
||||||
for ( i = 0; i < surface->numVertexes; i++ )
|
|
||||||
{
|
|
||||||
/* zero out votes */
|
|
||||||
numVotes = 0;
|
|
||||||
|
|
||||||
/* find all the triangles that reference this vertex */
|
|
||||||
for ( j = 0, faceIndex = 0; j < surface->numIndexes; j += 3, faceIndex++ )
|
|
||||||
{
|
|
||||||
/* get triangle */
|
|
||||||
a = surface->index[ j ];
|
|
||||||
b = surface->index[ j + 1 ];
|
|
||||||
c = surface->index[ j + 2 ];
|
|
||||||
|
|
||||||
/* ignore degenerate triangles */
|
|
||||||
if ( a == b || b == c || c == a ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ignore indexes out of range */
|
|
||||||
if ( a < 0 || a >= surface->numVertexes ||
|
|
||||||
b < 0 || b >= surface->numVertexes ||
|
|
||||||
c < 0 || c >= surface->numVertexes ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* test triangle */
|
|
||||||
if ( a == i || b == i || c == i ) {
|
|
||||||
/* if this surface has face normals */
|
|
||||||
if ( surface->numFaceNormals && faceIndex < surface->numFaceNormals ) {
|
|
||||||
_pico_copy_vec( surface->faceNormal[ faceIndex ], plane );
|
|
||||||
if ( plane[ 0 ] == 0.f && plane[ 1 ] == 0.f && plane[ 2 ] == 0.f ) {
|
|
||||||
/* if null normal, make plane from the 3 points */
|
|
||||||
if ( _pico_calc_plane( plane, surface->xyz[ a ], surface->xyz[ b ], surface->xyz[ c ] ) == 0 ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* make a plane from the 3 points */
|
|
||||||
else if ( _pico_calc_plane( plane, surface->xyz[ a ], surface->xyz[ b ], surface->xyz[ c ] ) == 0 ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* see if this normal has already been voted */
|
|
||||||
for ( k = 0; k < numVotes; k++ )
|
|
||||||
{
|
|
||||||
_pico_subtract_vec( plane, votes[ k ], diff );
|
|
||||||
if ( fabs( diff[ 0 ] ) < EQUAL_NORMAL_EPSILON &&
|
|
||||||
fabs( diff[ 1 ] ) < EQUAL_NORMAL_EPSILON &&
|
|
||||||
fabs( diff[ 2 ] ) < EQUAL_NORMAL_EPSILON ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add a new vote? */
|
|
||||||
if ( k == numVotes && numVotes < MAX_NORMAL_VOTES ) {
|
|
||||||
_pico_copy_vec( plane, votes[ numVotes ] );
|
|
||||||
numVotes++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* tally votes */
|
|
||||||
if ( numVotes > 0 ) {
|
|
||||||
/* create average normal */
|
|
||||||
_pico_zero_vec( normals[ i ] );
|
|
||||||
for ( k = 0; k < numVotes; k++ )
|
|
||||||
_pico_add_vec( normals[ i ], votes[ k ], normals[ i ] );
|
|
||||||
|
|
||||||
/* normalize it */
|
|
||||||
if ( _pico_normalize_vec( normals[ i ] ) ) {
|
|
||||||
/* test against actual normal */
|
|
||||||
if ( fabs( _pico_dot_vec( normals[ i ], surface->normal[ i ] ) - 1 ) > BAD_NORMAL_EPSILON ) {
|
|
||||||
//% printf( "Normal %8d: (%f %f %f) -> (%f %f %f)\n", i,
|
|
||||||
//% surface->normal[ i ][ 0 ], surface->normal[ i ][ 1 ], surface->normal[ i ][ 2 ],
|
|
||||||
//% normals[ i ][ 0 ], normals[ i ][ 1 ], normals[ i ][ 2 ] );
|
|
||||||
_pico_copy_vec( normals[ i ], surface->normal[ i ] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* free normal storage */
|
|
||||||
_pico_free(normals);
|
_pico_free(normals);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
PicoRemapModel() - sea
|
PicoRemapModel() - sea
|
||||||
remaps model material/etc. information using the remappings
|
remaps model material/etc. information using the remappings
|
||||||
|
@ -1799,7 +2177,7 @@ int PicoRemapModel( picoModel_t *model, char *remapFile ){
|
||||||
if ( !strlen( p->token ) ) {
|
if ( !strlen( p->token ) ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
materialName = _pico_clone_alloc( p->token,-1 );
|
materialName = _pico_clone_alloc( p->token/*,-1*/ );
|
||||||
if ( materialName == NULL ) {
|
if ( materialName == NULL ) {
|
||||||
_prm_error_return;
|
_prm_error_return;
|
||||||
}
|
}
|
||||||
|
@ -1857,7 +2235,7 @@ int PicoRemapModel( picoModel_t *model, char *remapFile ){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* temporary copy of material name */
|
/* temporary copy of material name */
|
||||||
tempMaterialName = _pico_clone_alloc( p->token,-1 );
|
tempMaterialName = _pico_clone_alloc( p->token/*,-1*/ );
|
||||||
if ( tempMaterialName == NULL ) {
|
if ( tempMaterialName == NULL ) {
|
||||||
_prm_error_return;
|
_prm_error_return;
|
||||||
}
|
}
|
||||||
|
@ -2002,7 +2380,7 @@ int PicoRemapModel( picoModel_t *model, char *remapFile ){
|
||||||
|
|
||||||
void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t** normals,
|
void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t** normals,
|
||||||
int numSTs, picoVec2_t **st, int numColors, picoColor_t **colors,
|
int numSTs, picoVec2_t **st, int numColors, picoColor_t **colors,
|
||||||
picoShader_t* shader ){
|
picoShader_t* shader, picoIndex_t* smoothingGroup ){
|
||||||
int i, j;
|
int i, j;
|
||||||
int vertDataIndex;
|
int vertDataIndex;
|
||||||
picoSurface_t* workSurface = NULL;
|
picoSurface_t* workSurface = NULL;
|
||||||
|
@ -2038,7 +2416,7 @@ void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t**
|
||||||
int newVertIndex = PicoGetSurfaceNumIndexes( workSurface );
|
int newVertIndex = PicoGetSurfaceNumIndexes( workSurface );
|
||||||
|
|
||||||
/* get the index of the vertex that we're going to store at newVertIndex */
|
/* get the index of the vertex that we're going to store at newVertIndex */
|
||||||
vertDataIndex = PicoFindSurfaceVertexNum( workSurface, *xyz[i], *normals[i], numSTs, st[i], numColors, colors[i] );
|
vertDataIndex = PicoFindSurfaceVertexNum( workSurface, *xyz[i], *normals[i], numSTs, st[i], numColors, colors[i], smoothingGroup[i] );
|
||||||
|
|
||||||
/* the vertex wasn't found, so create a new vertex in the pool from the data we have */
|
/* the vertex wasn't found, so create a new vertex in the pool from the data we have */
|
||||||
if ( vertDataIndex == -1 ) {
|
if ( vertDataIndex == -1 ) {
|
||||||
|
@ -2058,6 +2436,8 @@ void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t**
|
||||||
{
|
{
|
||||||
PicoSetSurfaceST( workSurface, j, vertDataIndex, st[i][j] );
|
PicoSetSurfaceST( workSurface, j, vertDataIndex, st[i][j] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PicoSetSurfaceSmoothingGroup( workSurface, vertDataIndex, smoothingGroup[ i ] );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add this vertex to the triangle */
|
/* add this vertex to the triangle */
|
||||||
|
|
Loading…
Reference in a new issue