2 ======================================================================
5 Point and polygon functions for an LWO2 reader.
8 ====================================================================== */
10 #include "../picointernal.h"
15 ======================================================================
18 Free the memory used by an lwPointList.
19 ====================================================================== */
21 void lwFreePoints( lwPointList *point ){
26 for ( i = 0; i < point->count; i++ ) {
27 if ( point->pt[ i ].pol ) {
28 _pico_free( point->pt[ i ].pol );
30 if ( point->pt[ i ].vm ) {
31 _pico_free( point->pt[ i ].vm );
34 _pico_free( point->pt );
36 memset( point, 0, sizeof( lwPointList ) );
42 ======================================================================
45 Free the memory used by an lwPolygonList.
46 ====================================================================== */
48 void lwFreePolygons( lwPolygonList *plist ){
53 for ( i = 0; i < plist->count; i++ ) {
54 if ( plist->pol[ i ].v ) {
55 for ( j = 0; j < plist->pol[ i ].nverts; j++ )
56 if ( plist->pol[ i ].v[ j ].vm ) {
57 _pico_free( plist->pol[ i ].v[ j ].vm );
61 if ( plist->pol[ 0 ].v ) {
62 _pico_free( plist->pol[ 0 ].v );
64 _pico_free( plist->pol );
66 memset( plist, 0, sizeof( lwPolygonList ) );
72 ======================================================================
75 Read point records from a PNTS chunk in an LWO2 file. The points are
76 added to the array in the lwPointList.
77 ====================================================================== */
79 int lwGetPoints( picoMemStream_t *fp, int cksize, lwPointList *point ){
87 /* extend the point array to hold the new points */
90 point->offset = point->count;
92 if ( !_pico_realloc( (void *) &point->pt, ( point->count - np ) * sizeof( lwPoint ), point->count * sizeof( lwPoint ) ) ) {
95 memset( &point->pt[ point->offset ], 0, np * sizeof( lwPoint ) );
97 /* read the whole chunk */
99 f = ( float * ) getbytes( fp, cksize );
103 revbytes( f, 4, np * 3 );
105 /* assign position values */
107 for ( i = 0, j = 0; i < np; i++, j += 3 ) {
108 point->pt[ i ].pos[ 0 ] = f[ j ];
109 point->pt[ i ].pos[ 1 ] = f[ j + 1 ];
110 point->pt[ i ].pos[ 2 ] = f[ j + 2 ];
119 ======================================================================
122 Calculate the bounding box for a point list, but only if the bounding
123 box hasn't already been initialized.
124 ====================================================================== */
126 void lwGetBoundingBox( lwPointList *point, float bbox[] ){
129 if ( point->count == 0 ) {
133 for ( i = 0; i < 6; i++ )
134 if ( bbox[ i ] != 0.0f ) {
138 bbox[ 0 ] = bbox[ 1 ] = bbox[ 2 ] = 1e20f;
139 bbox[ 3 ] = bbox[ 4 ] = bbox[ 5 ] = -1e20f;
140 for ( i = 0; i < point->count; i++ ) {
141 for ( j = 0; j < 3; j++ ) {
142 if ( bbox[ j ] > point->pt[ i ].pos[ j ] ) {
143 bbox[ j ] = point->pt[ i ].pos[ j ];
145 if ( bbox[ j + 3 ] < point->pt[ i ].pos[ j ] ) {
146 bbox[ j + 3 ] = point->pt[ i ].pos[ j ];
154 ======================================================================
157 Allocate or extend the polygon arrays to hold new records.
158 ====================================================================== */
160 int lwAllocPolygons( lwPolygonList *plist, int npols, int nverts ){
163 plist->offset = plist->count;
164 plist->count += npols;
165 if ( !_pico_realloc( (void *) &plist->pol, ( plist->count - npols ) * sizeof( lwPolygon ), plist->count * sizeof( lwPolygon ) ) ) {
168 memset( plist->pol + plist->offset, 0, npols * sizeof( lwPolygon ) );
170 plist->voffset = plist->vcount;
171 plist->vcount += nverts;
172 if ( !_pico_realloc( (void *) &plist->pol[ 0 ].v, ( plist->vcount - nverts ) * sizeof( lwPolVert ), plist->vcount * sizeof( lwPolVert ) ) ) {
175 memset( plist->pol[ 0 ].v + plist->voffset, 0, nverts * sizeof( lwPolVert ) );
177 /* fix up the old vertex pointers */
179 for ( i = 1; i < plist->offset; i++ )
180 plist->pol[ i ].v = plist->pol[ i - 1 ].v + plist->pol[ i - 1 ].nverts;
187 ======================================================================
190 Read polygon records from a POLS chunk in an LWO2 file. The polygons
191 are added to the array in the lwPolygonList.
192 ====================================================================== */
194 int lwGetPolygons( picoMemStream_t *fp, int cksize, lwPolygonList *plist, int ptoffset ){
197 unsigned char *buf, *bp;
198 int i, j, flags, nv, nverts, npols;
206 /* read the whole chunk */
210 buf = getbytes( fp, cksize - 4 );
211 if ( cksize != get_flen() ) {
215 /* count the polygons and vertices */
221 while ( bp < buf + cksize - 4 ) {
226 for ( i = 0; i < nv; i++ )
230 if ( !lwAllocPolygons( plist, npols, nverts ) ) {
234 /* fill in the new polygons */
237 pp = plist->pol + plist->offset;
238 pv = plist->pol[ 0 ].v + plist->voffset;
240 for ( i = 0; i < npols; i++ ) {
251 for ( j = 0; j < nv; j++ )
252 pp->v[ j ].index = sgetVX( &bp ) + ptoffset;
265 lwFreePolygons( plist );
271 ======================================================================
274 Calculate the polygon normals. By convention, LW's polygon normals
275 are found as the cross product of the first and last edges. It's
276 undefined for one- and two-point polygons.
277 ====================================================================== */
279 void lwGetPolyNormals( lwPointList *point, lwPolygonList *polygon ){
281 float p1[ 3 ], p2[ 3 ], pn[ 3 ], v1[ 3 ], v2[ 3 ];
283 for ( i = 0; i < polygon->count; i++ ) {
284 if ( polygon->pol[ i ].nverts < 3 ) {
287 for ( j = 0; j < 3; j++ ) {
288 p1[ j ] = point->pt[ polygon->pol[ i ].v[ 0 ].index ].pos[ j ];
289 p2[ j ] = point->pt[ polygon->pol[ i ].v[ 1 ].index ].pos[ j ];
290 pn[ j ] = point->pt[ polygon->pol[ i ].v[
291 polygon->pol[ i ].nverts - 1 ].index ].pos[ j ];
294 for ( j = 0; j < 3; j++ ) {
295 v1[ j ] = p2[ j ] - p1[ j ];
296 v2[ j ] = pn[ j ] - p1[ j ];
299 cross( v1, v2, polygon->pol[ i ].norm );
300 normalize( polygon->pol[ i ].norm );
306 ======================================================================
309 For each point, fill in the indexes of the polygons that share the
310 point. Returns 0 if any of the memory allocations fail, otherwise
312 ====================================================================== */
314 int lwGetPointPolygons( lwPointList *point, lwPolygonList *polygon ){
317 /* count the number of polygons per point */
319 for ( i = 0; i < polygon->count; i++ )
320 for ( j = 0; j < polygon->pol[ i ].nverts; j++ )
321 ++point->pt[ polygon->pol[ i ].v[ j ].index ].npols;
323 /* alloc per-point polygon arrays */
325 for ( i = 0; i < point->count; i++ ) {
326 if ( point->pt[ i ].npols == 0 ) {
329 point->pt[ i ].pol = _pico_calloc( point->pt[ i ].npols, sizeof( int ) );
330 if ( !point->pt[ i ].pol ) {
333 point->pt[ i ].npols = 0;
336 /* fill in polygon array for each point */
338 for ( i = 0; i < polygon->count; i++ ) {
339 for ( j = 0; j < polygon->pol[ i ].nverts; j++ ) {
340 k = polygon->pol[ i ].v[ j ].index;
341 point->pt[ k ].pol[ point->pt[ k ].npols ] = i;
342 ++point->pt[ k ].npols;
351 ======================================================================
352 lwResolvePolySurfaces()
354 Convert tag indexes into actual lwSurface pointers. If any polygons
355 point to tags for which no corresponding surface can be found, a
356 default surface is created.
357 ====================================================================== */
359 int lwResolvePolySurfaces( lwPolygonList *polygon, lwTagList *tlist,
360 lwSurface **surf, int *nsurfs ){
364 if ( tlist->count == 0 ) {
368 s = _pico_calloc( tlist->count, sizeof( lwSurface * ) );
373 for ( i = 0; i < tlist->count; i++ ) {
376 if ( !strcmp( st->name, tlist->tag[ i ] ) ) {
384 for ( i = 0; i < polygon->count; i++ ) {
385 index = ( size_t ) polygon->pol[ i ].surf;
386 if ( index < 0 || index > tlist->count ) {
390 s[ index ] = lwDefaultSurface();
394 s[ index ]->name = _pico_alloc( strlen( tlist->tag[ index ] ) + 1 );
395 if ( !s[ index ]->name ) {
398 strcpy( s[ index ]->name, tlist->tag[ index ] );
399 lwListAdd( (void *) surf, s[ index ] );
400 *nsurfs = *nsurfs + 1;
402 polygon->pol[ i ].surf = s[ index ];
411 ======================================================================
414 Calculate the vertex normals. For each polygon vertex, sum the
415 normals of the polygons that share the point. If the normals of the
416 current and adjacent polygons form an angle greater than the max
417 smoothing angle for the current polygon's surface, the normal of the
418 adjacent polygon is excluded from the sum. It's also excluded if the
419 polygons aren't in the same smoothing group.
421 Assumes that lwGetPointPolygons(), lwGetPolyNormals() and
422 lwResolvePolySurfaces() have already been called.
423 ====================================================================== */
425 void lwGetVertNormals( lwPointList *point, lwPolygonList *polygon ){
426 int j, k, n, g, h, p;
429 for ( j = 0; j < polygon->count; j++ ) {
430 for ( n = 0; n < polygon->pol[ j ].nverts; n++ ) {
431 for ( k = 0; k < 3; k++ )
432 polygon->pol[ j ].v[ n ].norm[ k ] = polygon->pol[ j ].norm[ k ];
434 if ( polygon->pol[ j ].surf->smooth <= 0 ) {
438 p = polygon->pol[ j ].v[ n ].index;
440 for ( g = 0; g < point->pt[ p ].npols; g++ ) {
441 h = point->pt[ p ].pol[ g ];
446 if ( polygon->pol[ j ].smoothgrp != polygon->pol[ h ].smoothgrp ) {
449 a = vecangle( polygon->pol[ j ].norm, polygon->pol[ h ].norm );
450 if ( a > polygon->pol[ j ].surf->smooth ) {
454 for ( k = 0; k < 3; k++ )
455 polygon->pol[ j ].v[ n ].norm[ k ] += polygon->pol[ h ].norm[ k ];
458 normalize( polygon->pol[ j ].v[ n ].norm );
465 ======================================================================
468 Free memory used by an lwTagList.
469 ====================================================================== */
471 void lwFreeTags( lwTagList *tlist ){
476 for ( i = 0; i < tlist->count; i++ )
477 if ( tlist->tag[ i ] ) {
478 _pico_free( tlist->tag[ i ] );
480 _pico_free( tlist->tag );
482 memset( tlist, 0, sizeof( lwTagList ) );
488 ======================================================================
491 Read tag strings from a TAGS chunk in an LWO2 file. The tags are
492 added to the lwTagList array.
493 ====================================================================== */
495 int lwGetTags( picoMemStream_t *fp, int cksize, lwTagList *tlist ){
503 /* read the whole chunk */
506 buf = getbytes( fp, cksize );
511 /* count the strings */
515 while ( bp < buf + cksize ) {
516 len = strlen( bp ) + 1;
522 /* expand the string array to hold the new tags */
524 tlist->offset = tlist->count;
525 tlist->count += ntags;
526 if ( !_pico_realloc( (void *) &tlist->tag, ( tlist->count - ntags ) * sizeof( char * ), tlist->count * sizeof( char * ) ) ) {
529 memset( &tlist->tag[ tlist->offset ], 0, ntags * sizeof( char * ) );
531 /* copy the new tags to the tag array */
534 for ( i = 0; i < ntags; i++ )
535 tlist->tag[ i + tlist->offset ] = sgetS0( (unsigned char **) &bp );
549 ======================================================================
552 Read polygon tags from a PTAG chunk in an LWO2 file.
553 ====================================================================== */
555 int lwGetPolygonTags( picoMemStream_t *fp, int cksize, lwTagList *tlist,
556 lwPolygonList *plist ){
567 if ( type != ID_SURF && type != ID_PART && type != ID_SMGP ) {
568 _pico_memstream_seek( fp, cksize - 4, PICO_SEEK_CUR );
572 while ( rlen < cksize ) {
573 i = getVX( fp ) + plist->offset;
574 j = getVX( fp ) + tlist->offset;
576 if ( rlen < 0 || rlen > cksize ) {
581 case ID_SURF: plist->pol[ i ].surf = ( lwSurface * ) (size_t) j; break;
582 case ID_PART: plist->pol[ i ].part = j; break;
583 case ID_SMGP: plist->pol[ i ].smoothgrp = j; break;