1 /*
2    ======================================================================
3    vmap.c
4 
5    Vertex map functions for an LWO2 reader.
6 
7    Ernie Wright  17 Sep 00
8    ====================================================================== */
9 
10 #include "../picointernal.h"
11 #include "lwo2.h"
12 
13 
14 /*
15    ======================================================================
16    lwFreeVMap()
17 
18    Free memory used by an lwVMap.
19    ====================================================================== */
20 
lwFreeVMap(lwVMap * vmap)21 void lwFreeVMap( lwVMap *vmap ){
22 	if ( vmap ) {
23 		if ( vmap->name ) {
24 			_pico_free( vmap->name );
25 		}
26 		if ( vmap->vindex ) {
27 			_pico_free( vmap->vindex );
28 		}
29 		if ( vmap->pindex ) {
30 			_pico_free( vmap->pindex );
31 		}
32 		if ( vmap->val ) {
33 			if ( vmap->val[ 0 ] ) {
34 				_pico_free( vmap->val[ 0 ] );
35 			}
36 			_pico_free( vmap->val );
37 		}
38 		_pico_free( vmap );
39 	}
40 }
41 
42 
43 /*
44    ======================================================================
45    lwGetVMap()
46 
47    Read an lwVMap from a VMAP or VMAD chunk in an LWO2.
48    ====================================================================== */
49 
lwGetVMap(picoMemStream_t * fp,int cksize,int ptoffset,int poloffset,int perpoly)50 lwVMap *lwGetVMap( picoMemStream_t *fp, int cksize, int ptoffset, int poloffset,
51 				   int perpoly ){
52 	unsigned char *buf, *bp;
53 	lwVMap *vmap;
54 	float *f;
55 	int i, j, npts, rlen;
56 
57 
58 	/* read the whole chunk */
59 
60 	set_flen( 0 );
61 	buf = getbytes( fp, cksize );
62 	if ( !buf ) {
63 		return NULL;
64 	}
65 
66 	vmap = _pico_calloc( 1, sizeof( lwVMap ) );
67 	if ( !vmap ) {
68 		_pico_free( buf );
69 		return NULL;
70 	}
71 
72 	/* initialize the vmap */
73 
74 	vmap->perpoly = perpoly;
75 
76 	bp = buf;
77 	set_flen( 0 );
78 	vmap->type = sgetU4( &bp );
79 	vmap->dim  = sgetU2( &bp );
80 	vmap->name = sgetS0( &bp );
81 	rlen = get_flen();
82 
83 	/* count the vmap records */
84 
85 	npts = 0;
86 	while ( bp < buf + cksize ) {
87 		i = sgetVX( &bp );
88 		if ( perpoly ) {
89 			i = sgetVX( &bp );
90 		}
91 		bp += vmap->dim * sizeof( float );
92 		++npts;
93 	}
94 
95 	/* allocate the vmap */
96 
97 	vmap->nverts = npts;
98 	vmap->vindex = _pico_calloc( npts, sizeof( int ) );
99 	if ( !vmap->vindex ) {
100 		goto Fail;
101 	}
102 	if ( perpoly ) {
103 		vmap->pindex = _pico_calloc( npts, sizeof( int ) );
104 		if ( !vmap->pindex ) {
105 			goto Fail;
106 		}
107 	}
108 
109 	if ( vmap->dim > 0 ) {
110 		vmap->val = _pico_calloc( npts, sizeof( float * ) );
111 		if ( !vmap->val ) {
112 			goto Fail;
113 		}
114 		f = _pico_alloc( npts * vmap->dim * sizeof( float ) );
115 		if ( !f ) {
116 			goto Fail;
117 		}
118 		for ( i = 0; i < npts; i++ )
119 			vmap->val[ i ] = f + i * vmap->dim;
120 	}
121 
122 	/* fill in the vmap values */
123 
124 	bp = buf + rlen;
125 	for ( i = 0; i < npts; i++ ) {
126 		vmap->vindex[ i ] = sgetVX( &bp );
127 		if ( perpoly ) {
128 			vmap->pindex[ i ] = sgetVX( &bp );
129 		}
130 		for ( j = 0; j < vmap->dim; j++ )
131 			vmap->val[ i ][ j ] = sgetF4( &bp );
132 	}
133 
134 	_pico_free( buf );
135 	return vmap;
136 
137 Fail:
138 	if ( buf ) {
139 		_pico_free( buf );
140 	}
141 	lwFreeVMap( vmap );
142 	return NULL;
143 }
144 
145 
146 /*
147    ======================================================================
148    lwGetPointVMaps()
149 
150    Fill in the lwVMapPt structure for each point.
151    ====================================================================== */
152 
lwGetPointVMaps(lwPointList * point,lwVMap * vmap)153 int lwGetPointVMaps( lwPointList *point, lwVMap *vmap ){
154 	lwVMap *vm;
155 	int i, j, n;
156 
157 	/* count the number of vmap values for each point */
158 
159 	vm = vmap;
160 	while ( vm ) {
161 		if ( !vm->perpoly ) {
162 			for ( i = 0; i < vm->nverts; i++ )
163 				++point->pt[ vm->vindex[ i ]].nvmaps;
164 		}
165 		vm = vm->next;
166 	}
167 
168 	/* allocate vmap references for each mapped point */
169 
170 	for ( i = 0; i < point->count; i++ ) {
171 		if ( point->pt[ i ].nvmaps ) {
172 			point->pt[ i ].vm = _pico_calloc( point->pt[ i ].nvmaps, sizeof( lwVMapPt ) );
173 			if ( !point->pt[ i ].vm ) {
174 				return 0;
175 			}
176 			point->pt[ i ].nvmaps = 0;
177 		}
178 	}
179 
180 	/* fill in vmap references for each mapped point */
181 
182 	vm = vmap;
183 	while ( vm ) {
184 		if ( !vm->perpoly ) {
185 			for ( i = 0; i < vm->nverts; i++ ) {
186 				j = vm->vindex[ i ];
187 				n = point->pt[ j ].nvmaps;
188 				point->pt[ j ].vm[ n ].vmap = vm;
189 				point->pt[ j ].vm[ n ].index = i;
190 				++point->pt[ j ].nvmaps;
191 			}
192 		}
193 		vm = vm->next;
194 	}
195 
196 	return 1;
197 }
198 
199 
200 /*
201    ======================================================================
202    lwGetPolyVMaps()
203 
204    Fill in the lwVMapPt structure for each polygon vertex.
205    ====================================================================== */
206 
lwGetPolyVMaps(lwPolygonList * polygon,lwVMap * vmap)207 int lwGetPolyVMaps( lwPolygonList *polygon, lwVMap *vmap ){
208 	lwVMap *vm;
209 	lwPolVert *pv;
210 	int i, j;
211 
212 	/* count the number of vmap values for each polygon vertex */
213 
214 	vm = vmap;
215 	while ( vm ) {
216 		if ( vm->perpoly ) {
217 			for ( i = 0; i < vm->nverts; i++ ) {
218 				for ( j = 0; j < polygon->pol[ vm->pindex[ i ]].nverts; j++ ) {
219 					pv = &polygon->pol[ vm->pindex[ i ]].v[ j ];
220 					if ( vm->vindex[ i ] == pv->index ) {
221 						++pv->nvmaps;
222 						break;
223 					}
224 				}
225 			}
226 		}
227 		vm = vm->next;
228 	}
229 
230 	/* allocate vmap references for each mapped vertex */
231 
232 	for ( i = 0; i < polygon->count; i++ ) {
233 		for ( j = 0; j < polygon->pol[ i ].nverts; j++ ) {
234 			pv = &polygon->pol[ i ].v[ j ];
235 			if ( pv->nvmaps ) {
236 				pv->vm = _pico_calloc( pv->nvmaps, sizeof( lwVMapPt ) );
237 				if ( !pv->vm ) {
238 					return 0;
239 				}
240 				pv->nvmaps = 0;
241 			}
242 		}
243 	}
244 
245 	/* fill in vmap references for each mapped point */
246 
247 	vm = vmap;
248 	while ( vm ) {
249 		if ( vm->perpoly ) {
250 			for ( i = 0; i < vm->nverts; i++ ) {
251 				for ( j = 0; j < polygon->pol[ vm->pindex[ i ]].nverts; j++ ) {
252 					pv = &polygon->pol[ vm->pindex[ i ]].v[ j ];
253 					if ( vm->vindex[ i ] == pv->index ) {
254 						pv->vm[ pv->nvmaps ].vmap = vm;
255 						pv->vm[ pv->nvmaps ].index = i;
256 						++pv->nvmaps;
257 						break;
258 					}
259 				}
260 			}
261 		}
262 		vm = vm->next;
263 	}
264 
265 	return 1;
266 }
267