static lwTexture *get_texture( char *s ) { lwTexture *tex; tex = _pico_calloc( 1, sizeof( lwTexture )); if ( !tex ) return NULL; tex->tmap.size.val[ 0 ] = tex->tmap.size.val[ 1 ] = tex->tmap.size.val[ 2 ] = 1.0f; tex->opacity.val = 1.0f; tex->enabled = 1; if ( strstr( s, "Image Map" )) { tex->type = ID_IMAP; if ( strstr( s, "Planar" )) tex->param.imap.projection = 0; else if ( strstr( s, "Cylindrical" )) tex->param.imap.projection = 1; else if ( strstr( s, "Spherical" )) tex->param.imap.projection = 2; else if ( strstr( s, "Cubic" )) tex->param.imap.projection = 3; else if ( strstr( s, "Front" )) tex->param.imap.projection = 4; tex->param.imap.aa_strength = 1.0f; tex->param.imap.amplitude.val = 1.0f; _pico_free( s ); } else { tex->type = ID_PROC; tex->param.proc.name = s; } return tex; }
static int add_clip( char *s, lwClip **clist, int *nclips ) { lwClip *clip; char *p; clip = _pico_calloc( 1, sizeof( lwClip )); if ( !clip ) return 0; clip->contrast.val = 1.0f; clip->brightness.val = 1.0f; clip->saturation.val = 1.0f; clip->gamma.val = 1.0f; if ( (p = strstr( s, "(sequence)" ))) { p[ -1 ] = 0; clip->type = ID_ISEQ; clip->source.seq.prefix = s; clip->source.seq.digits = 3; } else { clip->type = ID_STIL; clip->source.still.name = s; } (*nclips)++; clip->index = *nclips; lwListAdd( (void *) clist, clip ); return clip->index; }
int lwGetPointPolygons( lwPointList *point, lwPolygonList *polygon ){ int i, j, k; /* count the number of polygons per point */ for ( i = 0; i < polygon->count; i++ ) for ( j = 0; j < polygon->pol[ i ].nverts; j++ ) ++point->pt[ polygon->pol[ i ].v[ j ].index ].npols; /* alloc per-point polygon arrays */ for ( i = 0; i < point->count; i++ ) { if ( point->pt[ i ].npols == 0 ) { continue; } point->pt[ i ].pol = _pico_calloc( point->pt[ i ].npols, sizeof( int ) ); if ( !point->pt[ i ].pol ) { return 0; } point->pt[ i ].npols = 0; } /* fill in polygon array for each point */ for ( i = 0; i < polygon->count; i++ ) { for ( j = 0; j < polygon->pol[ i ].nverts; j++ ) { k = polygon->pol[ i ].v[ j ].index; point->pt[ k ].pol[ point->pt[ k ].npols ] = i; ++point->pt[ k ].npols; } } return 1; }
static aseMaterial_t* _ase_add_material( aseMaterial_t **list, int mtlIdParent ) { aseMaterial_t *mtl = _pico_calloc( 1, sizeof( aseMaterial_t ) ); mtl->mtlId = mtlIdParent; mtl->subMtls = NULL; mtl->next = *list; *list = mtl; return mtl; }
static int add_tvel( float pos[], float vel[], lwEnvelope **elist, int *nenvs ) { lwEnvelope *env; lwKey *key0, *key1; int i; for ( i = 0; i < 3; i++ ) { env = _pico_calloc( 1, sizeof( lwEnvelope )); key0 = _pico_calloc( 1, sizeof( lwKey )); key1 = _pico_calloc( 1, sizeof( lwKey )); if ( !env || !key0 || !key1 ) return 0; key0->next = key1; key0->value = pos[ i ]; key0->time = 0.0f; key1->prev = key0; key1->value = pos[ i ] + vel[ i ] * 30.0f; key1->time = 1.0f; key0->shape = key1->shape = ID_LINE; env->index = *nenvs + i + 1; env->type = 0x0301 + i; env->name = _pico_alloc( 11 ); if ( env->name ) { strcpy( env->name, "Position.X" ); env->name[ 9 ] += i; } env->key = key0; env->nkeys = 2; env->behavior[ 0 ] = BEH_LINEAR; env->behavior[ 1 ] = BEH_LINEAR; lwListAdd( (void *) elist, env ); } *nenvs += 3; return env->index - 2; }
int lwResolvePolySurfaces( lwPolygonList *polygon, lwTagList *tlist, lwSurface **surf, int *nsurfs ){ lwSurface **s, *st; int i, index; if ( tlist->count == 0 ) { return 1; } s = _pico_calloc( tlist->count, sizeof( lwSurface * ) ); if ( !s ) { return 0; } for ( i = 0; i < tlist->count; i++ ) { st = *surf; while ( st ) { if ( !strcmp( st->name, tlist->tag[ i ] ) ) { s[ i ] = st; break; } st = st->next; } } for ( i = 0; i < polygon->count; i++ ) { index = ( int ) ( (size_t)polygon->pol[ i ].surf ); if ( index < 0 || index > tlist->count ) { return 0; } if ( !s[ index ] ) { s[ index ] = lwDefaultSurface(); if ( !s[ index ] ) { return 0; } s[ index ]->name = _pico_alloc( strlen( tlist->tag[ index ] ) + 1 ); if ( !s[ index ]->name ) { return 0; } strcpy( s[ index ]->name, tlist->tag[ index ] ); lwListAdd( (void **) surf, s[ index ] ); *nsurfs = *nsurfs + 1; } polygon->pol[ i ].surf = s[ index ]; } _pico_free( s ); return 1; }
void PicoFixSurfaceNormals (picoSurface_t* surface) { picoVec3_t* normals = (picoVec3_t*) _pico_calloc(surface->numVertexes, sizeof(picoVec3_t)); _pico_normals_zero(normals, normals + surface->numVertexes); _pico_triangles_generate_weighted_normals(surface->index, surface->index + surface->numIndexes, surface->xyz, normals); _pico_vertices_combine_shared_normals(surface->xyz, surface->smoothingGroup, normals, surface->numVertexes); _pico_normals_normalize(normals, normals + surface->numVertexes); _pico_normals_assign_generated_normals(surface->normal, surface->normal + surface->numVertexes, normals); _pico_free(normals); }
static aseSubMaterial_t* _ase_add_submaterial( aseMaterial_t **list, int mtlIdParent, int subMtlId, picoShader_t* shader ) { aseMaterial_t *parent = _ase_get_material( *list, mtlIdParent ); aseSubMaterial_t *subMtl = _pico_calloc( 1, sizeof ( aseSubMaterial_t ) ); if ( !parent ) { parent = _ase_add_material ( list , mtlIdParent ); } subMtl->shader = shader; subMtl->subMtlId = subMtlId; subMtl->next = parent->subMtls; parent->subMtls = subMtl; return subMtl; }
lwTexture *lwGetTexture( picoMemStream_t *fp, int bloksz, unsigned int type ) { lwTexture *tex; unsigned short sz; int ok; tex = _pico_calloc( 1, sizeof( lwTexture ) ); if ( !tex ) { return NULL; } tex->type = type; tex->tmap.size.val[ 0 ] = tex->tmap.size.val[ 1 ] = tex->tmap.size.val[ 2 ] = 1.0f; tex->opacity.val = 1.0f; tex->enabled = 1; sz = getU2( fp ); if ( !lwGetTHeader( fp, sz, tex ) ) { _pico_free( tex ); return NULL; } sz = bloksz - sz - 6; switch ( type ) { case ID_IMAP: ok = lwGetImageMap( fp, sz, tex ); break; case ID_PROC: ok = lwGetProcedural( fp, sz, tex ); break; case ID_GRAD: ok = lwGetGradient( fp, sz, tex ); break; default: ok = !_pico_memstream_seek( fp, sz, PICO_SEEK_CUR ); } if ( !ok ) { lwFreeTexture( tex ); return NULL; } set_flen( bloksz ); return tex; }
lwSurface *lwDefaultSurface( void ){ lwSurface *surf; surf = _pico_calloc( 1, sizeof( lwSurface ) ); if ( !surf ) { return NULL; } surf->color.rgb[ 0 ] = 0.78431f; surf->color.rgb[ 1 ] = 0.78431f; surf->color.rgb[ 2 ] = 0.78431f; surf->diffuse.val = 1.0f; surf->glossiness.val = 0.4f; surf->bump.val = 1.0f; surf->eta.val = 1.0f; surf->sideflags = 1; return surf; }
lwPlugin *lwGetShader( picoMemStream_t *fp, int bloksz ){ lwPlugin *shdr; unsigned int id; unsigned short sz; int hsz, rlen, pos; shdr = _pico_calloc( 1, sizeof( lwPlugin ) ); if ( !shdr ) { return NULL; } pos = _pico_memstream_tell( fp ); set_flen( 0 ); hsz = getU2( fp ); shdr->ord = getS0( fp ); id = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) { goto Fail; } while ( hsz > 0 ) { sz += sz & 1; hsz -= sz; if ( id == ID_ENAB ) { shdr->flags = getU2( fp ); break; } else { _pico_memstream_seek( fp, sz, PICO_SEEK_CUR ); id = getU4( fp ); sz = getU2( fp ); } } id = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) { goto Fail; } while ( 1 ) { sz += sz & 1; set_flen( 0 ); switch ( id ) { case ID_FUNC: shdr->name = getS0( fp ); rlen = get_flen(); shdr->data = getbytes( fp, sz - rlen ); break; default: break; } /* error while reading the current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > sz ) { goto Fail; } /* skip unread parts of the current subchunk */ if ( rlen < sz ) { _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR ); } /* end of the shader block? */ if ( bloksz <= _pico_memstream_tell( fp ) - pos ) { break; } /* get the next subchunk header */ set_flen( 0 ); id = getU4( fp ); sz = getU2( fp ); if ( 6 != get_flen() ) { goto Fail; } } set_flen( _pico_memstream_tell( fp ) - pos ); return shdr; Fail: lwFreePlugin( shdr ); return NULL; }
int lwGetGradient( picoMemStream_t *fp, int rsz, lwTexture *tex ){ unsigned int id; unsigned short sz; int rlen, pos, i, j, nkeys; pos = _pico_memstream_tell( fp ); id = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) { return 0; } while ( 1 ) { sz += sz & 1; set_flen( 0 ); switch ( id ) { case ID_TMAP: if ( !lwGetTMap( fp, sz, &tex->tmap ) ) { return 0; } break; case ID_PNAM: tex->param.grad.paramname = getS0( fp ); break; case ID_INAM: tex->param.grad.itemname = getS0( fp ); break; case ID_GRST: tex->param.grad.start = getF4( fp ); break; case ID_GREN: tex->param.grad.end = getF4( fp ); break; case ID_GRPT: tex->param.grad.repeat = getU2( fp ); break; case ID_FKEY: nkeys = sz / sizeof( lwGradKey ); tex->param.grad.key = _pico_calloc( nkeys, sizeof( lwGradKey ) ); if ( !tex->param.grad.key ) { return 0; } for ( i = 0; i < nkeys; i++ ) { tex->param.grad.key[ i ].value = getF4( fp ); for ( j = 0; j < 4; j++ ) tex->param.grad.key[ i ].rgba[ j ] = getF4( fp ); } break; case ID_IKEY: nkeys = sz / 2; tex->param.grad.ikey = _pico_calloc( nkeys, sizeof( short ) ); if ( !tex->param.grad.ikey ) { return 0; } for ( i = 0; i < nkeys; i++ ) tex->param.grad.ikey[ i ] = getU2( fp ); break; default: break; } /* error while reading the current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > sz ) { return 0; } /* skip unread parts of the current subchunk */ if ( rlen < sz ) { _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR ); } /* end of the gradient? */ if ( rsz <= _pico_memstream_tell( fp ) - pos ) { break; } /* get the next subchunk header */ set_flen( 0 ); id = getU4( fp ); sz = getU2( fp ); if ( 6 != get_flen() ) { return 0; } } set_flen( _pico_memstream_tell( fp ) - pos ); return 1; }
lwObject *lwGetObject5( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos ) { lwObject *object; lwLayer *layer; lwNode *node; unsigned int id, formsize, type, cksize; /* open the file */ if ( !fp ) return NULL; /* read the first 12 bytes */ set_flen( 0 ); id = getU4( fp ); formsize = getU4( fp ); type = getU4( fp ); if ( 12 != get_flen() ) { return NULL; } /* LWOB? */ if ( id != ID_FORM || type != ID_LWOB ) { if ( failpos ) *failpos = 12; return NULL; } /* allocate an object and a default layer */ object = _pico_calloc( 1, sizeof( lwObject )); if ( !object ) goto Fail; layer = _pico_calloc( 1, sizeof( lwLayer )); if ( !layer ) goto Fail; object->layer = layer; object->nlayers = 1; /* get the first chunk header */ id = getU4( fp ); cksize = getU4( fp ); if ( 0 > get_flen() ) goto Fail; /* process chunks as they're encountered */ while ( 1 ) { cksize += cksize & 1; switch ( id ) { case ID_PNTS: if ( !lwGetPoints( fp, cksize, &layer->point )) goto Fail; break; case ID_POLS: if ( !lwGetPolygons5( fp, cksize, &layer->polygon, layer->point.offset )) goto Fail; break; case ID_SRFS: if ( !lwGetTags( fp, cksize, &object->taglist )) goto Fail; break; case ID_SURF: node = ( lwNode * ) lwGetSurface5( fp, cksize, object ); if ( !node ) goto Fail; lwListAdd( (void *) &object->surf, node ); object->nsurfs++; break; default: _pico_memstream_seek( fp, cksize, PICO_SEEK_CUR ); break; } /* end of the file? */ if ( formsize <= _pico_memstream_tell( fp ) - 8 ) break; /* get the next chunk header */ set_flen( 0 ); id = getU4( fp ); cksize = getU4( fp ); if ( 8 != get_flen() ) goto Fail; } lwGetBoundingBox( &layer->point, layer->bbox ); lwGetPolyNormals( &layer->point, &layer->polygon ); if ( !lwGetPointPolygons( &layer->point, &layer->polygon )) goto Fail; if ( !lwResolvePolySurfaces( &layer->polygon, &object->taglist, &object->surf, &object->nsurfs )) goto Fail; lwGetVertNormals( &layer->point, &layer->polygon ); return object; Fail: if ( failID ) *failID = id; if ( fp ) { if ( failpos ) *failpos = _pico_memstream_tell( fp ); } lwFreeObject( object ); return NULL; }
lwSurface *lwGetSurface5( picoMemStream_t *fp, int cksize, lwObject *obj ) { lwSurface *surf; lwTexture *tex; lwPlugin *shdr; char *s; float v[ 3 ]; unsigned int id, flags; unsigned short sz; int pos, rlen, i; tex = NULL; shdr = NULL; /* allocate the Surface structure */ surf = _pico_calloc( 1, sizeof( lwSurface )); if ( !surf ) goto Fail; /* non-zero defaults */ surf->color.rgb[ 0 ] = 0.78431f; surf->color.rgb[ 1 ] = 0.78431f; surf->color.rgb[ 2 ] = 0.78431f; surf->diffuse.val = 1.0f; surf->glossiness.val = 0.4f; surf->bump.val = 1.0f; surf->eta.val = 1.0f; surf->sideflags = 1; /* remember where we started */ set_flen( 0 ); pos = _pico_memstream_tell( fp ); /* name */ surf->name = getS0( fp ); /* first subchunk header */ id = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) goto Fail; /* process subchunks as they're encountered */ while ( 1 ) { sz += sz & 1; set_flen( 0 ); switch ( id ) { case ID_COLR: surf->color.rgb[ 0 ] = getU1( fp ) / 255.0f; surf->color.rgb[ 1 ] = getU1( fp ) / 255.0f; surf->color.rgb[ 2 ] = getU1( fp ) / 255.0f; break; case ID_FLAG: flags = getU2( fp ); if ( flags & 4 ) surf->smooth = 1.56207f; if ( flags & 8 ) surf->color_hilite.val = 1.0f; if ( flags & 16 ) surf->color_filter.val = 1.0f; if ( flags & 128 ) surf->dif_sharp.val = 0.5f; if ( flags & 256 ) surf->sideflags = 3; if ( flags & 512 ) surf->add_trans.val = 1.0f; break; case ID_LUMI: surf->luminosity.val = getI2( fp ) / 256.0f; break; case ID_VLUM: surf->luminosity.val = getF4( fp ); break; case ID_DIFF: surf->diffuse.val = getI2( fp ) / 256.0f; break; case ID_VDIF: surf->diffuse.val = getF4( fp ); break; case ID_SPEC: surf->specularity.val = getI2( fp ) / 256.0f; break; case ID_VSPC: surf->specularity.val = getF4( fp ); break; case ID_GLOS: surf->glossiness.val = ( float ) log( getU2( fp )) / 20.7944f; break; case ID_SMAN: surf->smooth = getF4( fp ); break; case ID_REFL: surf->reflection.val.val = getI2( fp ) / 256.0f; break; case ID_RFLT: surf->reflection.options = getU2( fp ); break; case ID_RIMG: s = getS0( fp ); surf->reflection.cindex = add_clip( s, &obj->clip, &obj->nclips ); surf->reflection.options = 3; break; case ID_RSAN: surf->reflection.seam_angle = getF4( fp ); break; case ID_TRAN: surf->transparency.val.val = getI2( fp ) / 256.0f; break; case ID_RIND: surf->eta.val = getF4( fp ); break; case ID_BTEX: s = getbytes( fp, sz ); tex = get_texture( s ); lwListAdd( (void *) &surf->bump.tex, tex ); break; case ID_CTEX: s = getbytes( fp, sz ); tex = get_texture( s ); lwListAdd( (void *) &surf->color.tex, tex ); break; case ID_DTEX: s = getbytes( fp, sz ); tex = get_texture( s ); lwListAdd( (void *) &surf->diffuse.tex, tex ); break; case ID_LTEX: s = getbytes( fp, sz ); tex = get_texture( s ); lwListAdd( (void *) &surf->luminosity.tex, tex ); break; case ID_RTEX: s = getbytes( fp, sz ); tex = get_texture( s ); lwListAdd( (void *) &surf->reflection.val.tex, tex ); break; case ID_STEX: s = getbytes( fp, sz ); tex = get_texture( s ); lwListAdd( (void *) &surf->specularity.tex, tex ); break; case ID_TTEX: s = getbytes( fp, sz ); tex = get_texture( s ); lwListAdd( (void *) &surf->transparency.val.tex, tex ); break; case ID_TFLG: flags = getU2( fp ); i = 0; // greebo: initialise to fix compiler warnings if ( flags & 1 ) i = 0; if ( flags & 2 ) i = 1; if ( flags & 4 ) i = 2; tex->axis = i; if ( tex->type == ID_IMAP ) tex->param.imap.axis = i; else tex->param.proc.axis = i; if ( flags & 8 ) tex->tmap.coord_sys = 1; if ( flags & 16 ) tex->negative = 1; if ( flags & 32 ) tex->param.imap.pblend = 1; if ( flags & 64 ) { tex->param.imap.aa_strength = 1.0f; tex->param.imap.aas_flags = 1; } break; case ID_TSIZ: for ( i = 0; i < 3; i++ ) tex->tmap.size.val[ i ] = getF4( fp ); break; case ID_TCTR: for ( i = 0; i < 3; i++ ) tex->tmap.center.val[ i ] = getF4( fp ); break; case ID_TFAL: for ( i = 0; i < 3; i++ ) tex->tmap.falloff.val[ i ] = getF4( fp ); break; case ID_TVEL: for ( i = 0; i < 3; i++ ) v[ i ] = getF4( fp ); tex->tmap.center.eindex = add_tvel( tex->tmap.center.val, v, &obj->env, &obj->nenvs ); break; case ID_TCLR: if ( tex->type == ID_PROC ) for ( i = 0; i < 3; i++ ) tex->param.proc.value[ i ] = getU1( fp ) / 255.0f; break; case ID_TVAL: tex->param.proc.value[ 0 ] = getI2( fp ) / 256.0f; break; case ID_TAMP: if ( tex->type == ID_IMAP ) tex->param.imap.amplitude.val = getF4( fp ); break; case ID_TIMG: s = getS0( fp ); tex->param.imap.cindex = add_clip( s, &obj->clip, &obj->nclips ); break; case ID_TAAS: tex->param.imap.aa_strength = getF4( fp ); tex->param.imap.aas_flags = 1; break; case ID_TREF: tex->tmap.ref_object = getbytes( fp, sz ); break; case ID_TOPC: tex->opacity.val = getF4( fp ); break; case ID_TFP0: if ( tex->type == ID_IMAP ) tex->param.imap.wrapw.val = getF4( fp ); break; case ID_TFP1: if ( tex->type == ID_IMAP ) tex->param.imap.wraph.val = getF4( fp ); break; case ID_SHDR: shdr = _pico_calloc( 1, sizeof( lwPlugin )); if ( !shdr ) goto Fail; shdr->name = getbytes( fp, sz ); lwListAdd( (void *) &surf->shader, shdr ); surf->nshaders++; break; case ID_SDAT: shdr->data = getbytes( fp, sz ); break; default: break; } /* error while reading current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > sz ) goto Fail; /* skip unread parts of the current subchunk */ if ( rlen < sz ) _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR ); /* end of the SURF chunk? */ if ( cksize <= _pico_memstream_tell( fp ) - pos ) break; /* get the next subchunk header */ set_flen( 0 ); id = getU4( fp ); sz = getU2( fp ); if ( 6 != get_flen() ) goto Fail; } return surf; Fail: if ( surf ) lwFreeSurface( surf ); return NULL; }
lwClip *lwGetClip( picoMemStream_t *fp, int cksize ){ lwClip *clip; lwPlugin *filt; unsigned int id; unsigned short sz; int pos, rlen; /* allocate the Clip structure */ clip = _pico_calloc( 1, sizeof( lwClip ) ); if ( !clip ) { goto Fail; } clip->contrast.val = 1.0f; clip->brightness.val = 1.0f; clip->saturation.val = 1.0f; clip->gamma.val = 1.0f; /* remember where we started */ set_flen( 0 ); pos = _pico_memstream_tell( fp ); /* index */ clip->index = getI4( fp ); /* first subchunk header */ clip->type = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) { goto Fail; } sz += sz & 1; set_flen( 0 ); switch ( clip->type ) { case ID_STIL: clip->source.still.name = getS0( fp ); break; case ID_ISEQ: clip->source.seq.digits = getU1( fp ); clip->source.seq.flags = getU1( fp ); clip->source.seq.offset = getI2( fp ); getU2( fp ); /* not sure what this is yet */ clip->source.seq.start = getI2( fp ); clip->source.seq.end = getI2( fp ); clip->source.seq.prefix = getS0( fp ); clip->source.seq.suffix = getS0( fp ); break; case ID_ANIM: clip->source.anim.name = getS0( fp ); clip->source.anim.server = getS0( fp ); rlen = get_flen(); clip->source.anim.data = getbytes( fp, sz - rlen ); break; case ID_XREF: clip->source.xref.index = getI4( fp ); clip->source.xref.string = getS0( fp ); break; case ID_STCC: clip->source.cycle.lo = getI2( fp ); clip->source.cycle.hi = getI2( fp ); clip->source.cycle.name = getS0( fp ); break; default: break; } /* error while reading current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > sz ) { goto Fail; } /* skip unread parts of the current subchunk */ if ( rlen < sz ) { _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR ); } /* end of the CLIP chunk? */ rlen = _pico_memstream_tell( fp ) - pos; if ( cksize < rlen ) { goto Fail; } if ( cksize == rlen ) { return clip; } /* process subchunks as they're encountered */ id = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) { goto Fail; } while ( 1 ) { sz += sz & 1; set_flen( 0 ); switch ( id ) { case ID_TIME: clip->start_time = getF4( fp ); clip->duration = getF4( fp ); clip->frame_rate = getF4( fp ); break; case ID_CONT: clip->contrast.val = getF4( fp ); clip->contrast.eindex = getVX( fp ); break; case ID_BRIT: clip->brightness.val = getF4( fp ); clip->brightness.eindex = getVX( fp ); break; case ID_SATR: clip->saturation.val = getF4( fp ); clip->saturation.eindex = getVX( fp ); break; case ID_HUE: clip->hue.val = getF4( fp ); clip->hue.eindex = getVX( fp ); break; case ID_GAMM: clip->gamma.val = getF4( fp ); clip->gamma.eindex = getVX( fp ); break; case ID_NEGA: clip->negative = getU2( fp ); break; case ID_IFLT: case ID_PFLT: filt = _pico_calloc( 1, sizeof( lwPlugin ) ); if ( !filt ) { goto Fail; } filt->name = getS0( fp ); filt->flags = getU2( fp ); rlen = get_flen(); filt->data = getbytes( fp, sz - rlen ); if ( id == ID_IFLT ) { lwListAdd( &clip->ifilter, filt ); clip->nifilters++; } else { lwListAdd( &clip->pfilter, filt ); clip->npfilters++; } break; default: break; } /* error while reading current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > sz ) { goto Fail; } /* skip unread parts of the current subchunk */ if ( rlen < sz ) { _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR ); } /* end of the CLIP chunk? */ rlen = _pico_memstream_tell( fp ) - pos; if ( cksize < rlen ) { goto Fail; } if ( cksize == rlen ) { break; } /* get the next chunk header */ set_flen( 0 ); id = getU4( fp ); sz = getU2( fp ); if ( 6 != get_flen() ) { goto Fail; } } return clip; Fail: lwFreeClip( clip ); return NULL; }
lwObject *lwGetObject( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos ){ lwObject *object; lwLayer *layer; lwNode *node; unsigned int id, formsize, type, cksize; int i, rlen; /* open the file */ if ( !fp ) { return NULL; } /* read the first 12 bytes */ set_flen( 0 ); id = getU4( fp ); formsize = getU4( fp ); type = getU4( fp ); if ( 12 != get_flen() ) { return NULL; } /* is this a LW object? */ if ( id != ID_FORM ) { if ( failpos ) { *failpos = 12; } return NULL; } if ( type != ID_LWO2 ) { if ( type == ID_LWOB ) { return lwGetObject5( filename, fp, failID, failpos ); } else { if ( failpos ) { *failpos = 12; } return NULL; } } /* allocate an object and a default layer */ object = _pico_calloc( 1, sizeof( lwObject ) ); if ( !object ) { goto Fail; } layer = _pico_calloc( 1, sizeof( lwLayer ) ); if ( !layer ) { goto Fail; } object->layer = layer; /* get the first chunk header */ id = getU4( fp ); cksize = getU4( fp ); if ( 0 > get_flen() ) { goto Fail; } /* process chunks as they're encountered */ while ( 1 ) { cksize += cksize & 1; switch ( id ) { case ID_LAYR: if ( object->nlayers > 0 ) { layer = _pico_calloc( 1, sizeof( lwLayer ) ); if ( !layer ) { goto Fail; } lwListAdd( (void **) &object->layer, layer ); } object->nlayers++; set_flen( 0 ); layer->index = getU2( fp ); layer->flags = getU2( fp ); layer->pivot[ 0 ] = getF4( fp ); layer->pivot[ 1 ] = getF4( fp ); layer->pivot[ 2 ] = getF4( fp ); layer->name = getS0( fp ); rlen = get_flen(); if ( rlen < 0 || rlen > cksize ) { goto Fail; } if ( rlen <= cksize - 2 ) { layer->parent = getU2( fp ); } rlen = get_flen(); if ( rlen < cksize ) { _pico_memstream_seek( fp, cksize - rlen, PICO_SEEK_CUR ); } break; case ID_PNTS: if ( !lwGetPoints( fp, cksize, &layer->point ) ) { goto Fail; } break; case ID_POLS: if ( !lwGetPolygons( fp, cksize, &layer->polygon, layer->point.offset ) ) { goto Fail; } break; case ID_VMAP: case ID_VMAD: node = ( lwNode * ) lwGetVMap( fp, cksize, layer->point.offset, layer->polygon.offset, id == ID_VMAD ); if ( !node ) { goto Fail; } lwListAdd( (void **) &layer->vmap, node ); layer->nvmaps++; break; case ID_PTAG: if ( !lwGetPolygonTags( fp, cksize, &object->taglist, &layer->polygon ) ) { goto Fail; } break; case ID_BBOX: set_flen( 0 ); for ( i = 0; i < 6; i++ ) layer->bbox[ i ] = getF4( fp ); rlen = get_flen(); if ( rlen < 0 || rlen > cksize ) { goto Fail; } if ( rlen < cksize ) { _pico_memstream_seek( fp, cksize - rlen, PICO_SEEK_CUR ); } break; case ID_TAGS: if ( !lwGetTags( fp, cksize, &object->taglist ) ) { goto Fail; } break; case ID_ENVL: node = ( lwNode * ) lwGetEnvelope( fp, cksize ); if ( !node ) { goto Fail; } lwListAdd( (void **) &object->env, node ); object->nenvs++; break; case ID_CLIP: node = ( lwNode * ) lwGetClip( fp, cksize ); if ( !node ) { goto Fail; } lwListAdd( (void **) &object->clip, node ); object->nclips++; break; case ID_SURF: node = ( lwNode * ) lwGetSurface( fp, cksize ); if ( !node ) { goto Fail; } lwListAdd( (void **) &object->surf, node ); object->nsurfs++; break; case ID_DESC: case ID_TEXT: case ID_ICON: default: _pico_memstream_seek( fp, cksize, PICO_SEEK_CUR ); break; } /* end of the file? */ if ( formsize <= _pico_memstream_tell( fp ) - 8 ) { break; } /* get the next chunk header */ set_flen( 0 ); id = getU4( fp ); cksize = getU4( fp ); if ( 8 != get_flen() ) { goto Fail; } } if ( object->nlayers == 0 ) { object->nlayers = 1; } layer = object->layer; while ( layer ) { lwGetBoundingBox( &layer->point, layer->bbox ); lwGetPolyNormals( &layer->point, &layer->polygon ); if ( !lwGetPointPolygons( &layer->point, &layer->polygon ) ) { goto Fail; } if ( !lwResolvePolySurfaces( &layer->polygon, &object->taglist, &object->surf, &object->nsurfs ) ) { goto Fail; } lwGetVertNormals( &layer->point, &layer->polygon ); if ( !lwGetPointVMaps( &layer->point, layer->vmap ) ) { goto Fail; } if ( !lwGetPolyVMaps( &layer->polygon, layer->vmap ) ) { goto Fail; } layer = layer->next; } return object; Fail: if ( failID ) { *failID = id; } if ( fp ) { if ( failpos ) { *failpos = _pico_memstream_tell( fp ); } } lwFreeObject( object ); return NULL; }
static void binarytree_reserve (BinaryTree* self, size_t size) { self->data = self->last = _pico_calloc(size, sizeof(BinaryTreeNode)); }
/* _ase_load: * loads a 3dsmax ase model file. */ static picoModel_t *_ase_load( PM_PARAMS_LOAD ) { picoModel_t *model; picoParser_t *p; char lastNodeName[ 1024 ]; aseVertex_t* vertices = NULL; aseTexCoord_t* texcoords = NULL; aseColor_t* colors = NULL; aseFace_t* faces = NULL; int numVertices = 0; int numFaces = 0; int numTextureVertices = 0; int numTextureVertexFaces = 0; int numColorVertices = 0; int numColorVertexFaces = 0; int vertexId = 0; int currentVertexFace=0; int currentVertexIndex=0; int counter=0; int submodel=0; aseMaterial_t* materials = NULL; #ifdef DEBUG_PM_ASE clock_t start, finish; double elapsed; start = clock(); #endif /* helper */ #define _ase_error_return(m) \ { \ _pico_printf( PICO_ERROR,"%s in ASE, line %d.",m,p->curLine); \ _pico_free_parser( p ); \ PicoFreeModel( model ); \ return NULL; \ } /* create a new pico parser */ p = _pico_new_parser( (picoByte_t *)buffer,bufSize ); if (p == NULL) return NULL; /* create a new pico model */ model = PicoNewModel(); if (model == NULL) { _pico_free_parser( p ); return NULL; } /* do model setup */ PicoSetModelFrameNum( model, frameNum ); PicoSetModelName( model, fileName ); PicoSetModelFileName( model, fileName ); /* initialize some stuff */ memset( lastNodeName,0,sizeof(lastNodeName) ); /* parse ase model file */ while( 1 ) { /* get first token on line */ if (_pico_parse_first( p ) == NULL) break; /* we just skip empty lines */ if (p->token == NULL || !strlen( p->token )) continue; /* we skip invalid ase statements */ if (p->token[0] != '*' && p->token[0] != '{' && p->token[0] != '}') { _pico_parse_skip_rest( p ); continue; } /* remember node name */ if (!_pico_stricmp(p->token,"*node_name")) { /* read node name */ char *ptr = _pico_parse( p,0 ); if (ptr == NULL) _ase_error_return("Node name parse error"); /* remember node name */ strncpy( lastNodeName,ptr,sizeof(lastNodeName) ); } /* model mesh (originally contained within geomobject) */ else if (!_pico_stricmp(p->token,"*mesh")) { /* finish existing surface */ _ase_submit_triangles(model, materials, vertices, texcoords, colors, faces, numFaces,numVertices,submodel++); _pico_free(faces); _pico_free(vertices); _pico_free(texcoords); _pico_free(colors); } else if (!_pico_stricmp(p->token,"*mesh_numvertex")) { if (!_pico_parse_int( p, &numVertices) ) _ase_error_return("Missing MESH_NUMVERTEX value"); vertices = _pico_calloc(numVertices, sizeof(aseVertex_t)); currentVertexIndex=0; } else if (!_pico_stricmp(p->token,"*mesh_numfaces")) { if (!_pico_parse_int( p, &numFaces) ) _ase_error_return("Missing MESH_NUMFACES value"); faces = _pico_calloc(numFaces, sizeof(aseFace_t)); } else if (!_pico_stricmp(p->token,"*mesh_numtvertex")) { if (!_pico_parse_int( p, &numTextureVertices) ) _ase_error_return("Missing MESH_NUMTVERTEX value"); texcoords = _pico_calloc(numTextureVertices, sizeof(aseTexCoord_t)); } else if (!_pico_stricmp(p->token,"*mesh_numtvfaces")) { if (!_pico_parse_int( p, &numTextureVertexFaces) ) _ase_error_return("Missing MESH_NUMTVFACES value"); } else if (!_pico_stricmp(p->token,"*mesh_numcvertex")) { if (!_pico_parse_int( p, &numColorVertices) ) _ase_error_return("Missing MESH_NUMCVERTEX value"); colors = _pico_calloc(numColorVertices, sizeof(aseColor_t)); memset( colors, 255, numColorVertices * sizeof( aseColor_t ) ); /* ydnar: force colors to white initially */ } else if (!_pico_stricmp(p->token,"*mesh_numcvfaces")) { if (!_pico_parse_int( p, &numColorVertexFaces) ) _ase_error_return("Missing MESH_NUMCVFACES value"); } /* mesh material reference. this usually comes at the end of */ /* geomobjects after the mesh blocks. we must assume that the */ /* new mesh was already created so all we can do here is assign */ /* the material reference id (shader index) now. */ else if (!_pico_stricmp(p->token,"*material_ref")) { int mtlId; /* get the material ref (0..n) */ if (!_pico_parse_int( p,&mtlId) ) _ase_error_return("Missing material reference ID"); { int i = 0; /* fix up all of the aseFaceList in the surface to point to the parent material */ /* we've already saved off their subMtl */ for(; i < numFaces; ++i) { faces[i].materialId = mtlId; } } } /* model mesh vertex */ else if (!_pico_stricmp(p->token,"*mesh_vertex")) { int index; if( numVertices == 0 ) _ase_error_return("Vertex parse error"); /* get vertex data (orig: index +y -x +z) */ if (!_pico_parse_int( p,&index )) _ase_error_return("Vertex parse error"); if (!_pico_parse_vec( p,vertices[index].xyz )) _ase_error_return("Vertex parse error"); vertices[index].id = vertexId++; } else if (!_pico_stricmp(p->token,"*mesh_facenormal")) { //Grab the faceindex for the next vertex normals. if( numVertices == 0 ) _ase_error_return("Vertex parse error (facenormals)"); if (!_pico_parse_int( p,¤tVertexFace )) _ase_error_return("Vertex parse error"); if (!_pico_parse_vec( p,faces[currentVertexFace].facenormal )) _ase_error_return("Vertex parse error"); } /* model mesh vertex normal */ else if (!_pico_stricmp(p->token,"*mesh_vertexnormal")) { int index; if( numVertices == 0 ) _ase_error_return("Vertex parse error"); /* get vertex data (orig: index +y -x +z) */ if (!_pico_parse_int( p,&index )) _ase_error_return("Vertex parse error"); //^^ Index is 'wrong' in .ase models. they reference the same vert index with multiple normals.. // I've tried, this is a lost cause. Use the SG's // /* if (!_pico_parse_vec( p,vertices[counter].normal )) _ase_error_return("Vertex parse error"); vertices[counter].faceid=index; counter++; */ } /* model mesh face */ else if (!_pico_stricmp(p->token,"*mesh_normals")) { // counter=0; //part of the above vertex normals fix } /* model mesh face */ else if (!_pico_stricmp(p->token,"*mesh_face")) { picoIndex_t indexes[3]; int index; if( numFaces == 0 ) _ase_error_return("Face parse error"); /* get face index */ if (!_pico_parse_int( p,&index )) _ase_error_return("Face parse error"); /* get 1st vertex index */ _pico_parse( p,0 ); if (!_pico_parse_int( p,&indexes[0] )) _ase_error_return("Face parse error"); /* get 2nd vertex index */ _pico_parse( p,0 ); if (!_pico_parse_int( p,&indexes[1] )) _ase_error_return("Face parse error"); /* get 3rd vertex index */ _pico_parse( p,0 ); if (!_pico_parse_int( p,&indexes[2] )) _ase_error_return("Face parse error"); /* parse to the subMaterial ID */ while ( 1 ) { if (!_pico_parse (p,0)) /* EOL */ { break; } if (!_pico_stricmp (p->token,"*MESH_SMOOTHING" )) { int total=0; char* point; char* start; _pico_parse(p,0); point=p->token; start=point; faces[index].smoothingGroup=0; //Super dodgy comma delimited string parse while (*point<'A') { if (*point<=32 || *point==',') { total=atoi(start); if (total!=0) { faces[index].smoothingGroup+=1<<total; } start=point+1; } point++; } } if (!_pico_stricmp (p->token,"*MESH_MTLID" )) { _pico_parse_int ( p , &faces[index].subMaterialId ); } } faces[index].materialId = 0; faces[index].indices[0] = indexes[2]; faces[index].indices[1] = indexes[1]; faces[index].indices[2] = indexes[0]; } /* model texture vertex */ else if (!_pico_stricmp(p->token,"*mesh_tvert")) { int index; if( numVertices == 0 ) _ase_error_return("Vertex parse error"); /* get uv vertex index */ if (!_pico_parse_int( p,&index )) _ase_error_return("UV vertex parse error"); /* get uv vertex s */ if (!_pico_parse_float( p,&texcoords[index].texcoord[0] )) _ase_error_return("UV vertex parse error"); /* get uv vertex t */ if (!_pico_parse_float( p,&texcoords[index].texcoord[1] )) _ase_error_return("UV vertex parse error"); /* ydnar: invert t */ texcoords[index].texcoord[ 1 ] = 1.0f - texcoords[index].texcoord[ 1 ]; } /* ydnar: model mesh texture face */ else if( !_pico_stricmp( p->token, "*mesh_tface" ) ) { picoIndex_t indexes[3]; int index; if( numFaces == 0 ) _ase_error_return("Texture face parse error"); /* get face index */ if (!_pico_parse_int( p,&index )) _ase_error_return("Texture face parse error"); /* get 1st vertex index */ if (!_pico_parse_int( p,&indexes[0] )) _ase_error_return("Texture face parse error"); /* get 2nd vertex index */ if (!_pico_parse_int( p,&indexes[1] )) _ase_error_return("Texture face parse error"); /* get 3rd vertex index */ if (!_pico_parse_int( p,&indexes[2] )) _ase_error_return("Texture face parse error"); faces[index].indices[3] = indexes[2]; faces[index].indices[4] = indexes[1]; faces[index].indices[5] = indexes[0]; } /* model color vertex */ else if (!_pico_stricmp(p->token,"*mesh_vertcol")) { int index; float colorInput; if( numVertices == 0 ) _ase_error_return("Color Vertex parse error"); /* get color vertex index */ if (!_pico_parse_int( p,&index )) _ase_error_return("Color vertex parse error"); /* get R component */ if (!_pico_parse_float( p,&colorInput )) _ase_error_return("Color vertex parse error"); colors[index].color[0] = (picoByte_t)(colorInput * 255); /* get G component */ if (!_pico_parse_float( p,&colorInput )) _ase_error_return("Color vertex parse error"); colors[index].color[1] = (picoByte_t)(colorInput * 255); /* get B component */ if (!_pico_parse_float( p,&colorInput )) _ase_error_return("Color vertex parse error"); colors[index].color[2] = (picoByte_t)(colorInput * 255); /* leave alpha alone since we don't get any data from the ASE format */ colors[index].color[3] = 255; /* 27 hack, red as alpha */ colors[index].color[3]=colors[index].color[0]; colors[index].color[0]=255; colors[index].color[1]=255; colors[index].color[2]=255; } /* model color face */ else if (!_pico_stricmp(p->token,"*mesh_cface")) { picoIndex_t indexes[3]; int index; if( numFaces == 0 ) _ase_error_return("Face parse error"); /* get face index */ if (!_pico_parse_int( p,&index )) _ase_error_return("Face parse error"); /* get 1st cvertex index */ // _pico_parse( p,0 ); if (!_pico_parse_int( p,&indexes[0] )) _ase_error_return("Face parse error"); /* get 2nd cvertex index */ // _pico_parse( p,0 ); if (!_pico_parse_int( p,&indexes[1] )) _ase_error_return("Face parse error"); /* get 3rd cvertex index */ // _pico_parse( p,0 ); if (!_pico_parse_int( p,&indexes[2] )) _ase_error_return("Face parse error"); faces[index].indices[6] = indexes[2]; faces[index].indices[7] = indexes[1]; faces[index].indices[8] = indexes[0]; } /* model material */ else if( !_pico_stricmp( p->token, "*material" ) ) { aseSubMaterial_t* subMaterial = NULL; picoShader_t *shader; int level = 1, index; char materialName[ 1024 ]; float transValue = 0.0f, shineValue = 1.0f; picoColor_t ambientColor, diffuseColor, specularColor; char *mapname = NULL; int subMtlId, subMaterialLevel = -1; /* get material index */ _pico_parse_int( p,&index ); /* check brace */ if (!_pico_parse_check(p,1,"{")) _ase_error_return("Material missing opening brace"); /* parse material block */ while( 1 ) { /* get next token */ if (_pico_parse(p,1) == NULL) break; if (!strlen(p->token)) continue; /* handle levels */ if (p->token[0] == '{') level++; if (p->token[0] == '}') level--; if (!level) break; if( level == subMaterialLevel ) { /* set material name */ _pico_first_token( materialName ); PicoSetShaderName( shader, materialName); /* set shader's transparency */ PicoSetShaderTransparency( shader,transValue ); /* set shader's ambient color */ PicoSetShaderAmbientColor( shader,ambientColor ); /* set diffuse alpha to transparency */ diffuseColor[3] = (picoByte_t)( transValue * 255.0 ); /* set shader's diffuse color */ PicoSetShaderDiffuseColor( shader,diffuseColor ); /* set shader's specular color */ PicoSetShaderSpecularColor( shader,specularColor ); /* set shader's shininess */ PicoSetShaderShininess( shader,shineValue ); /* set material map name */ PicoSetShaderMapName( shader, mapname ); subMaterial = _ase_add_submaterial( &materials, index, subMtlId, shader ); subMaterialLevel = -1; } /* parse submaterial index */ if (!_pico_stricmp(p->token,"*submaterial")) { /* allocate new pico shader */ _pico_parse_int( p , &subMtlId ); shader = PicoNewShader( model ); if (shader == NULL) { PicoFreeModel( model ); return NULL; } subMaterialLevel = level; } /* parse material name */ else if (!_pico_stricmp(p->token,"*material_name")) { char* name = _pico_parse(p,0); if ( name == NULL) _ase_error_return("Missing material name"); strcpy ( materialName , name ); /* skip rest and continue with next token */ _pico_parse_skip_rest( p ); continue; } /* parse material transparency */ else if (!_pico_stricmp(p->token,"*material_transparency")) { /* get transparency value from ase */ if (!_pico_parse_float( p,&transValue )) _ase_error_return("Material transparency parse error"); /* skip rest and continue with next token */ _pico_parse_skip_rest( p ); continue; } /* parse material shininess */ else if (!_pico_stricmp(p->token,"*material_shine")) { /* remark: * - not sure but instead of '*material_shine' i might * need to use '*material_shinestrength' */ /* get shine value from ase */ if (!_pico_parse_float( p,&shineValue )) _ase_error_return("Material shine parse error"); /* scale ase shine range 0..1 to pico range 0..127 */ shineValue *= 128.0; /* skip rest and continue with next token */ _pico_parse_skip_rest( p ); continue; } /* parse ambient material color */ else if (!_pico_stricmp(p->token,"*material_ambient")) { picoVec3_t vec; /* get r,g,b float values from ase */ if (!_pico_parse_vec( p,vec )) _ase_error_return("Material color parse error"); /* setup 0..255 range color values */ ambientColor[ 0 ] = (int)( vec[ 0 ] * 255.0 ); ambientColor[ 1 ] = (int)( vec[ 1 ] * 255.0 ); ambientColor[ 2 ] = (int)( vec[ 2 ] * 255.0 ); ambientColor[ 3 ] = (int)( 255 ); /* skip rest and continue with next token */ _pico_parse_skip_rest( p ); continue; } /* parse diffuse material color */ else if (!_pico_stricmp(p->token,"*material_diffuse")) { picoVec3_t vec; /* get r,g,b float values from ase */ if (!_pico_parse_vec( p,vec )) _ase_error_return("Material color parse error"); /* setup 0..255 range color */ diffuseColor[ 0 ] = (int)( vec[ 0 ] * 255.0 ); diffuseColor[ 1 ] = (int)( vec[ 1 ] * 255.0 ); diffuseColor[ 2 ] = (int)( vec[ 2 ] * 255.0 ); diffuseColor[ 3 ] = (int)( 255 ); /* skip rest and continue with next token */ _pico_parse_skip_rest( p ); continue; } /* parse specular material color */ else if (!_pico_stricmp(p->token,"*material_specular")) { picoVec3_t vec; /* get r,g,b float values from ase */ if (!_pico_parse_vec( p,vec )) _ase_error_return("Material color parse error"); /* setup 0..255 range color */ specularColor[ 0 ] = (int)( vec[ 0 ] * 255 ); specularColor[ 1 ] = (int)( vec[ 1 ] * 255 ); specularColor[ 2 ] = (int)( vec[ 2 ] * 255 ); specularColor[ 3 ] = (int)( 255 ); /* skip rest and continue with next token */ _pico_parse_skip_rest( p ); continue; } /* material diffuse map */ else if (!_pico_stricmp(p->token,"*map_diffuse") ) { int sublevel = 0; /* parse material block */ while( 1 ) { /* get next token */ if (_pico_parse(p,1) == NULL) break; if (!strlen(p->token)) continue; /* handle levels */ if (p->token[0] == '{') sublevel++; if (p->token[0] == '}') sublevel--; if (!sublevel) break; /* parse diffuse map bitmap */ if (!_pico_stricmp(p->token,"*bitmap")) { char* name = _pico_parse(p,0); if (name == NULL) _ase_error_return("Missing material map bitmap name"); mapname = _pico_alloc ( strlen ( name ) + 1 ); strcpy ( mapname, name ); /* skip rest and continue with next token */ _pico_parse_skip_rest( p ); continue; } } } /* end map_diffuse block */ } /* end material block */ if( subMaterial == NULL ) { /* allocate new pico shader */ shader = PicoNewShader( model ); if (shader == NULL) { PicoFreeModel( model ); return NULL; } /* set material name */ PicoSetShaderName( shader,materialName ); /* set shader's transparency */ PicoSetShaderTransparency( shader,transValue ); /* set shader's ambient color */ PicoSetShaderAmbientColor( shader,ambientColor ); /* set diffuse alpha to transparency */ diffuseColor[3] = (picoByte_t)( transValue * 255.0 ); /* set shader's diffuse color */ PicoSetShaderDiffuseColor( shader,diffuseColor ); /* set shader's specular color */ PicoSetShaderSpecularColor( shader,specularColor ); /* set shader's shininess */ PicoSetShaderShininess( shader,shineValue ); /* set material map name */ PicoSetShaderMapName( shader, mapname ); /* extract shadername from bitmap path */ if(mapname != NULL) { char* p = mapname; /* convert to shader-name format */ { /* unix-style path separators */ char* s = mapname; for(; *s != '\0'; ++s) { if(*s == '\\') { *s = '/'; } } } { /* remove extension */ char* last_period = strrchr(p, '.'); if(last_period != NULL) { *last_period = '\0'; } } /* find game root */ for(; *p != '\0'; ++p) { if(_pico_strnicmp(p, "quake", 5) == 0 || _pico_strnicmp(p, "doom", 4) == 0) { break; } } /* root-relative */ for(; *p != '\0'; ++p) { if(*p == '/') { ++p; break; } } /* game-relative */ for(; *p != '\0'; ++p) { if(*p == '/') { ++p; break; } } if(*p != '\0') { /* set material name */ PicoSetShaderName( shader,p ); } } /* this is just a material with 1 submaterial */ subMaterial = _ase_add_submaterial( &materials, index, 0, shader ); } /* ydnar: free mapname */ if( mapname != NULL ) _pico_free( mapname ); } // !_pico_stricmp ( "*material" ) /* skip unparsed rest of line and continue */ _pico_parse_skip_rest( p ); } /* ydnar: finish existing surface */ _ase_submit_triangles(model, materials, vertices, texcoords, colors, faces, numFaces,numVertices,submodel++); _pico_free(faces); _pico_free(vertices); _pico_free(texcoords); _pico_free(colors); #ifdef DEBUG_PM_ASE _ase_print_materials(materials); finish = clock(); elapsed = (double)(finish - start) / CLOCKS_PER_SEC; _pico_printf( PICO_NORMAL, "Loaded model in in %-.2f second(s)\n", elapsed ); #endif //DEBUG_PM_ASE _ase_free_materials(&materials); _pico_free_parser( p ); /* return allocated pico model */ return model; }
void aseUniqueIndices_reserve(aseUniqueIndices_t* self, picoIndex_t size) { self->data = self->last = (picoIndex_t*)_pico_calloc(size, sizeof(picoIndex_t)); }
lwEnvelope *lwGetEnvelope( picoMemStream_t *fp, int cksize ) { lwEnvelope *env; lwKey *key; lwPlugin *plug; unsigned int id; unsigned short sz; float f[ 4 ]; int i, nparams, pos, rlen; key = NULL; /* allocate the Envelope structure */ env = _pico_calloc( 1, sizeof( lwEnvelope )); if ( !env ) goto Fail; /* remember where we started */ set_flen( 0 ); pos = (int)_pico_memstream_tell( fp ); /* index */ env->index = getVX( fp ); /* first subchunk header */ id = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) goto Fail; /* process subchunks as they're encountered */ while ( 1 ) { sz += sz & 1; set_flen( 0 ); switch ( id ) { case ID_TYPE: env->type = getU2( fp ); break; case ID_NAME: env->name = getS0( fp ); break; case ID_PRE: env->behavior[ 0 ] = getU2( fp ); break; case ID_POST: env->behavior[ 1 ] = getU2( fp ); break; case ID_KEY: key = _pico_calloc( 1, sizeof( lwKey )); if ( !key ) goto Fail; key->time = getF4( fp ); key->value = getF4( fp ); lwListInsert( (void **) &env->key, key, (int (*)(void *, void *))compare_keys ); env->nkeys++; break; case ID_SPAN: if ( !key ) goto Fail; key->shape = getU4( fp ); nparams = ( sz - 4 ) / 4; if ( nparams > 4 ) nparams = 4; for ( i = 0; i < nparams; i++ ) f[ i ] = getF4( fp ); switch ( key->shape ) { case ID_TCB: key->tension = f[ 0 ]; key->continuity = f[ 1 ]; key->bias = f[ 2 ]; break; case ID_BEZI: case ID_HERM: case ID_BEZ2: for ( i = 0; i < nparams; i++ ) key->param[ i ] = f[ i ]; break; } break; case ID_CHAN: plug = _pico_calloc( 1, sizeof( lwPlugin )); if ( !plug ) goto Fail; plug->name = getS0( fp ); plug->flags = getU2( fp ); plug->data = getbytes( fp, sz - get_flen() ); lwListAdd( (void *) &env->cfilter, plug ); env->ncfilters++; break; default: break; } /* error while reading current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > sz ) goto Fail; /* skip unread parts of the current subchunk */ if ( rlen < sz ) _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR ); /* end of the ENVL chunk? */ rlen = (int)_pico_memstream_tell( fp ) - pos; if ( cksize < rlen ) goto Fail; if ( cksize == rlen ) break; /* get the next subchunk header */ set_flen( 0 ); id = getU4( fp ); sz = getU2( fp ); if ( 6 != get_flen() ) goto Fail; } return env; Fail: lwFreeEnvelope( env ); return NULL; }
lwSurface *lwGetSurface( picoMemStream_t *fp, int cksize ){ lwSurface *surf; lwTexture *tex; lwPlugin *shdr; unsigned int id, type; unsigned short sz; int pos, rlen; /* allocate the Surface structure */ surf = _pico_calloc( 1, sizeof( lwSurface ) ); if ( !surf ) { goto Fail; } /* non-zero defaults */ surf->color.rgb[ 0 ] = 0.78431f; surf->color.rgb[ 1 ] = 0.78431f; surf->color.rgb[ 2 ] = 0.78431f; surf->diffuse.val = 1.0f; surf->glossiness.val = 0.4f; surf->bump.val = 1.0f; surf->eta.val = 1.0f; surf->sideflags = 1; /* remember where we started */ set_flen( 0 ); pos = _pico_memstream_tell( fp ); /* names */ surf->name = getS0( fp ); surf->srcname = getS0( fp ); /* first subchunk header */ id = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) { goto Fail; } /* process subchunks as they're encountered */ while ( 1 ) { sz += sz & 1; set_flen( 0 ); switch ( id ) { case ID_COLR: surf->color.rgb[ 0 ] = getF4( fp ); surf->color.rgb[ 1 ] = getF4( fp ); surf->color.rgb[ 2 ] = getF4( fp ); surf->color.eindex = getVX( fp ); break; case ID_LUMI: surf->luminosity.val = getF4( fp ); surf->luminosity.eindex = getVX( fp ); break; case ID_DIFF: surf->diffuse.val = getF4( fp ); surf->diffuse.eindex = getVX( fp ); break; case ID_SPEC: surf->specularity.val = getF4( fp ); surf->specularity.eindex = getVX( fp ); break; case ID_GLOS: surf->glossiness.val = getF4( fp ); surf->glossiness.eindex = getVX( fp ); break; case ID_REFL: surf->reflection.val.val = getF4( fp ); surf->reflection.val.eindex = getVX( fp ); break; case ID_RFOP: surf->reflection.options = getU2( fp ); break; case ID_RIMG: surf->reflection.cindex = getVX( fp ); break; case ID_RSAN: surf->reflection.seam_angle = getF4( fp ); break; case ID_TRAN: surf->transparency.val.val = getF4( fp ); surf->transparency.val.eindex = getVX( fp ); break; case ID_TROP: surf->transparency.options = getU2( fp ); break; case ID_TIMG: surf->transparency.cindex = getVX( fp ); break; case ID_RIND: surf->eta.val = getF4( fp ); surf->eta.eindex = getVX( fp ); break; case ID_TRNL: surf->translucency.val = getF4( fp ); surf->translucency.eindex = getVX( fp ); break; case ID_BUMP: surf->bump.val = getF4( fp ); surf->bump.eindex = getVX( fp ); break; case ID_SMAN: surf->smooth = getF4( fp ); break; case ID_SIDE: surf->sideflags = getU2( fp ); break; case ID_CLRH: surf->color_hilite.val = getF4( fp ); surf->color_hilite.eindex = getVX( fp ); break; case ID_CLRF: surf->color_filter.val = getF4( fp ); surf->color_filter.eindex = getVX( fp ); break; case ID_ADTR: surf->add_trans.val = getF4( fp ); surf->add_trans.eindex = getVX( fp ); break; case ID_SHRP: surf->dif_sharp.val = getF4( fp ); surf->dif_sharp.eindex = getVX( fp ); break; case ID_GVAL: surf->glow.val = getF4( fp ); surf->glow.eindex = getVX( fp ); break; case ID_LINE: surf->line.enabled = 1; if ( sz >= 2 ) { surf->line.flags = getU2( fp ); } if ( sz >= 6 ) { surf->line.size.val = getF4( fp ); } if ( sz >= 8 ) { surf->line.size.eindex = getVX( fp ); } break; case ID_ALPH: surf->alpha_mode = getU2( fp ); surf->alpha = getF4( fp ); break; case ID_AVAL: surf->alpha = getF4( fp ); break; case ID_BLOK: type = getU4( fp ); switch ( type ) { case ID_IMAP: case ID_PROC: case ID_GRAD: tex = lwGetTexture( fp, sz - 4, type ); if ( !tex ) { goto Fail; } if ( !add_texture( surf, tex ) ) { lwFreeTexture( tex ); } set_flen( 4 + get_flen() ); break; case ID_SHDR: shdr = lwGetShader( fp, sz - 4 ); if ( !shdr ) { goto Fail; } lwListInsert( (void **) &surf->shader, shdr, (void *) compare_shaders ); ++surf->nshaders; set_flen( 4 + get_flen() ); break; } break; default: break; } /* error while reading current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > sz ) { goto Fail; } /* skip unread parts of the current subchunk */ if ( rlen < sz ) { _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR ); } /* end of the SURF chunk? */ if ( cksize <= _pico_memstream_tell( fp ) - pos ) { break; } /* get the next subchunk header */ set_flen( 0 ); id = getU4( fp ); sz = getU2( fp ); if ( 6 != get_flen() ) { goto Fail; } } return surf; Fail: if ( surf ) { lwFreeSurface( surf ); } return NULL; }
static void indexarray_reserve (IndexArray* self, size_t size) { self->data = self->last = _pico_calloc(size, sizeof(picoIndex_t)); }