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