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