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 )
27 for ( i = 0; i < point->count; i++ ) {
28 if ( point->pt[ i ].pol ) _pico_free( point->pt[ i ].pol );
29 if ( point->pt[ i ].vm ) _pico_free( point->pt[ i ].vm );
31 _pico_free( point->pt );
33 memset( point, 0, sizeof( lwPointList ));
39 ======================================================================
42 Free the memory used by an lwPolygonList.
43 ====================================================================== */
45 void lwFreePolygons( lwPolygonList *plist )
51 for ( i = 0; i < plist->count; i++ ) {
52 if ( plist->pol[ i ].v ) {
53 for ( j = 0; j < plist->pol[ i ].nverts; j++ )
54 if ( plist->pol[ i ].v[ j ].vm )
55 _pico_free( plist->pol[ i ].v[ j ].vm );
58 if ( plist->pol[ 0 ].v )
59 _pico_free( plist->pol[ 0 ].v );
60 _pico_free( plist->pol );
62 memset( plist, 0, sizeof( lwPolygonList ));
68 ======================================================================
71 Read point records from a PNTS chunk in an LWO2 file. The points are
72 added to the array in the lwPointList.
73 ====================================================================== */
75 int lwGetPoints( picoMemStream_t *fp, int cksize, lwPointList *point )
80 if ( cksize == 1 ) return 1;
82 /* extend the point array to hold the new points */
85 point->offset = point->count;
87 if ( !_pico_realloc( (void *) &point->pt, (point->count - np) * sizeof( lwPoint ), point->count * sizeof( lwPoint )) )
89 memset( &point->pt[ point->offset ], 0, np * sizeof( lwPoint ));
91 /* read the whole chunk */
93 f = ( float * ) getbytes( fp, cksize );
95 revbytes( f, 4, np * 3 );
97 /* assign position values */
99 for ( i = 0, j = 0; i < np; i++, j += 3 ) {
100 point->pt[ i ].pos[ 0 ] = f[ j ];
101 point->pt[ i ].pos[ 1 ] = f[ j + 1 ];
102 point->pt[ i ].pos[ 2 ] = f[ j + 2 ];
111 ======================================================================
114 Calculate the bounding box for a point list, but only if the bounding
115 box hasn't already been initialized.
116 ====================================================================== */
118 void lwGetBoundingBox( lwPointList *point, float bbox[] )
122 if ( point->count == 0 ) return;
124 for ( i = 0; i < 6; i++ )
125 if ( bbox[ i ] != 0.0f ) return;
127 bbox[ 0 ] = bbox[ 1 ] = bbox[ 2 ] = 1e20f;
128 bbox[ 3 ] = bbox[ 4 ] = bbox[ 5 ] = -1e20f;
129 for ( i = 0; i < point->count; i++ ) {
130 for ( j = 0; j < 3; j++ ) {
131 if ( bbox[ j ] > point->pt[ i ].pos[ j ] )
132 bbox[ j ] = point->pt[ i ].pos[ j ];
133 if ( bbox[ j + 3 ] < point->pt[ i ].pos[ j ] )
134 bbox[ j + 3 ] = point->pt[ i ].pos[ j ];
141 ======================================================================
144 Allocate or extend the polygon arrays to hold new records.
145 ====================================================================== */
147 int lwAllocPolygons( lwPolygonList *plist, int npols, int nverts )
151 plist->offset = plist->count;
152 plist->count += npols;
153 if ( !_pico_realloc( (void *) &plist->pol, (plist->count - npols) * sizeof( lwPolygon ), plist->count * sizeof( lwPolygon )) )
155 memset( plist->pol + plist->offset, 0, npols * sizeof( lwPolygon ));
157 plist->voffset = plist->vcount;
158 plist->vcount += nverts;
159 if ( !_pico_realloc( (void *) &plist->pol[ 0 ].v, (plist->vcount - nverts) * sizeof( lwPolVert ), plist->vcount * sizeof( lwPolVert )) )
161 memset( plist->pol[ 0 ].v + plist->voffset, 0, nverts * sizeof( lwPolVert ));
163 /* fix up the old vertex pointers */
165 for ( i = 1; i < plist->offset; i++ )
166 plist->pol[ i ].v = plist->pol[ i - 1 ].v + plist->pol[ i - 1 ].nverts;
173 ======================================================================
176 Read polygon records from a POLS chunk in an LWO2 file. The polygons
177 are added to the array in the lwPolygonList.
178 ====================================================================== */
180 int lwGetPolygons( picoMemStream_t *fp, int cksize, lwPolygonList *plist, int ptoffset )
184 unsigned char *buf, *bp;
185 int i, j, flags, nv, nverts, npols;
189 if ( cksize == 0 ) return 1;
191 /* read the whole chunk */
195 buf = getbytes( fp, cksize - 4 );
196 if ( cksize != get_flen() ) goto Fail;
198 /* count the polygons and vertices */
204 while ( bp < buf + cksize - 4 ) {
209 for ( i = 0; i < nv; i++ )
213 if ( !lwAllocPolygons( plist, npols, nverts ))
216 /* fill in the new polygons */
219 pp = plist->pol + plist->offset;
220 pv = plist->pol[ 0 ].v + plist->voffset;
222 for ( i = 0; i < npols; i++ ) {
230 if ( !pp->v ) pp->v = pv;
231 for ( j = 0; j < nv; j++ )
232 pp->v[ j ].index = sgetVX( &bp ) + ptoffset;
242 if ( buf ) _pico_free( buf );
243 lwFreePolygons( plist );
249 ======================================================================
252 Calculate the polygon normals. By convention, LW's polygon normals
253 are found as the cross product of the first and last edges. It's
254 undefined for one- and two-point polygons.
255 ====================================================================== */
257 void lwGetPolyNormals( lwPointList *point, lwPolygonList *polygon )
260 float p1[ 3 ], p2[ 3 ], pn[ 3 ], v1[ 3 ], v2[ 3 ];
262 for ( i = 0; i < polygon->count; i++ ) {
263 if ( polygon->pol[ i ].nverts < 3 ) continue;
264 for ( j = 0; j < 3; j++ ) {
265 p1[ j ] = point->pt[ polygon->pol[ i ].v[ 0 ].index ].pos[ j ];
266 p2[ j ] = point->pt[ polygon->pol[ i ].v[ 1 ].index ].pos[ j ];
267 pn[ j ] = point->pt[ polygon->pol[ i ].v[
268 polygon->pol[ i ].nverts - 1 ].index ].pos[ j ];
271 for ( j = 0; j < 3; j++ ) {
272 v1[ j ] = p2[ j ] - p1[ j ];
273 v2[ j ] = pn[ j ] - p1[ j ];
276 cross( v1, v2, polygon->pol[ i ].norm );
277 normalize( polygon->pol[ i ].norm );
283 ======================================================================
286 For each point, fill in the indexes of the polygons that share the
287 point. Returns 0 if any of the memory allocations fail, otherwise
289 ====================================================================== */
291 int lwGetPointPolygons( lwPointList *point, lwPolygonList *polygon )
295 /* count the number of polygons per point */
297 for ( i = 0; i < polygon->count; i++ )
298 for ( j = 0; j < polygon->pol[ i ].nverts; j++ )
299 ++point->pt[ polygon->pol[ i ].v[ j ].index ].npols;
301 /* alloc per-point polygon arrays */
303 for ( i = 0; i < point->count; i++ ) {
304 if ( point->pt[ i ].npols == 0 ) continue;
305 point->pt[ i ].pol = _pico_calloc( point->pt[ i ].npols, sizeof( int ));
306 if ( !point->pt[ i ].pol ) return 0;
307 point->pt[ i ].npols = 0;
310 /* fill in polygon array for each point */
312 for ( i = 0; i < polygon->count; i++ ) {
313 for ( j = 0; j < polygon->pol[ i ].nverts; j++ ) {
314 k = polygon->pol[ i ].v[ j ].index;
315 point->pt[ k ].pol[ point->pt[ k ].npols ] = i;
316 ++point->pt[ k ].npols;
325 ======================================================================
326 lwResolvePolySurfaces()
328 Convert tag indexes into actual lwSurface pointers. If any polygons
329 point to tags for which no corresponding surface can be found, a
330 default surface is created.
331 ====================================================================== */
333 int lwResolvePolySurfaces( lwPolygonList *polygon, lwTagList *tlist,
334 lwSurface **surf, int *nsurfs )
339 if ( tlist->count == 0 ) return 1;
341 s = _pico_calloc( tlist->count, sizeof( lwSurface * ));
344 for ( i = 0; i < tlist->count; i++ ) {
347 if ( !strcmp( st->name, tlist->tag[ i ] )) {
355 for ( i = 0; i < polygon->count; i++ ) {
356 index = ( int ) polygon->pol[ i ].surf;
357 if ( index < 0 || index > tlist->count ) return 0;
359 s[ index ] = lwDefaultSurface();
360 if ( !s[ index ] ) return 0;
361 s[ index ]->name = _pico_alloc( strlen( tlist->tag[ index ] ) + 1 );
362 if ( !s[ index ]->name ) return 0;
363 strcpy( s[ index ]->name, tlist->tag[ index ] );
364 lwListAdd( surf, s[ index ] );
365 *nsurfs = *nsurfs + 1;
367 polygon->pol[ i ].surf = s[ index ];
376 ======================================================================
379 Calculate the vertex normals. For each polygon vertex, sum the
380 normals of the polygons that share the point. If the normals of the
381 current and adjacent polygons form an angle greater than the max
382 smoothing angle for the current polygon's surface, the normal of the
383 adjacent polygon is excluded from the sum. It's also excluded if the
384 polygons aren't in the same smoothing group.
386 Assumes that lwGetPointPolygons(), lwGetPolyNormals() and
387 lwResolvePolySurfaces() have already been called.
388 ====================================================================== */
390 void lwGetVertNormals( lwPointList *point, lwPolygonList *polygon )
392 int j, k, n, g, h, p;
395 for ( j = 0; j < polygon->count; j++ ) {
396 for ( n = 0; n < polygon->pol[ j ].nverts; n++ ) {
397 for ( k = 0; k < 3; k++ )
398 polygon->pol[ j ].v[ n ].norm[ k ] = polygon->pol[ j ].norm[ k ];
400 if ( polygon->pol[ j ].surf->smooth <= 0 ) continue;
402 p = polygon->pol[ j ].v[ n ].index;
404 for ( g = 0; g < point->pt[ p ].npols; g++ ) {
405 h = point->pt[ p ].pol[ g ];
406 if ( h == j ) continue;
408 if ( polygon->pol[ j ].smoothgrp != polygon->pol[ h ].smoothgrp )
410 a = vecangle( polygon->pol[ j ].norm, polygon->pol[ h ].norm );
411 if ( a > polygon->pol[ j ].surf->smooth ) continue;
413 for ( k = 0; k < 3; k++ )
414 polygon->pol[ j ].v[ n ].norm[ k ] += polygon->pol[ h ].norm[ k ];
417 normalize( polygon->pol[ j ].v[ n ].norm );
424 ======================================================================
427 Free memory used by an lwTagList.
428 ====================================================================== */
430 void lwFreeTags( lwTagList *tlist )
436 for ( i = 0; i < tlist->count; i++ )
437 if ( tlist->tag[ i ] ) _pico_free( tlist->tag[ i ] );
438 _pico_free( tlist->tag );
440 memset( tlist, 0, sizeof( lwTagList ));
446 ======================================================================
449 Read tag strings from a TAGS chunk in an LWO2 file. The tags are
450 added to the lwTagList array.
451 ====================================================================== */
453 int lwGetTags( picoMemStream_t *fp, int cksize, lwTagList *tlist )
458 if ( cksize == 0 ) return 1;
460 /* read the whole chunk */
463 buf = getbytes( fp, cksize );
464 if ( !buf ) return 0;
466 /* count the strings */
470 while ( bp < buf + cksize ) {
471 len = strlen( bp ) + 1;
477 /* expand the string array to hold the new tags */
479 tlist->offset = tlist->count;
480 tlist->count += ntags;
481 if ( !_pico_realloc( (void *) &tlist->tag, (tlist->count - ntags) * sizeof( char * ), tlist->count * sizeof( char * )) )
483 memset( &tlist->tag[ tlist->offset ], 0, ntags * sizeof( char * ));
485 /* copy the new tags to the tag array */
488 for ( i = 0; i < ntags; i++ )
489 tlist->tag[ i + tlist->offset ] = sgetS0( &bp );
495 if ( buf ) _pico_free( buf );
501 ======================================================================
504 Read polygon tags from a PTAG chunk in an LWO2 file.
505 ====================================================================== */
507 int lwGetPolygonTags( picoMemStream_t *fp, int cksize, lwTagList *tlist,
508 lwPolygonList *plist )
516 if ( rlen < 0 ) return 0;
518 if ( type != ID_SURF && type != ID_PART && type != ID_SMGP ) {
519 _pico_memstream_seek( fp, cksize - 4, PICO_SEEK_CUR );
523 while ( rlen < cksize ) {
524 i = getVX( fp ) + plist->offset;
525 j = getVX( fp ) + tlist->offset;
527 if ( rlen < 0 || rlen > cksize ) return 0;
530 case ID_SURF: plist->pol[ i ].surf = ( lwSurface * ) j; break;
531 case ID_PART: plist->pol[ i ].part = j; break;
532 case ID_SMGP: plist->pol[ i ].smoothgrp = j; break;