Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5131 | clevermous | 1 | /* |
2 | Copyright (C) 1996-1997 Id Software, Inc. |
||
3 | |||
4 | This program is free software; you can redistribute it and/or |
||
5 | modify it under the terms of the GNU General Public License |
||
6 | as published by the Free Software Foundation; either version 2 |
||
7 | of the License, or (at your option) any later version. |
||
8 | |||
9 | This program is distributed in the hope that it will be useful, |
||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||
12 | |||
13 | See the GNU General Public License for more details. |
||
14 | |||
15 | You should have received a copy of the GNU General Public License |
||
16 | along with this program; if not, write to the Free Software |
||
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||
18 | |||
19 | */ |
||
20 | // gl_mesh.c: triangle model functions |
||
21 | |||
22 | #include "quakedef.h" |
||
23 | |||
24 | /* |
||
25 | ================================================================= |
||
26 | |||
27 | ALIAS MODEL DISPLAY LIST GENERATION |
||
28 | |||
29 | ================================================================= |
||
30 | */ |
||
31 | |||
32 | model_t *aliasmodel; |
||
33 | aliashdr_t *paliashdr; |
||
34 | |||
35 | qboolean used[8192]; |
||
36 | |||
37 | // the command list holds counts and s/t values that are valid for |
||
38 | // every frame |
||
39 | int commands[8192]; |
||
40 | int numcommands; |
||
41 | |||
42 | // all frames will have their vertexes rearranged and expanded |
||
43 | // so they are in the order expected by the command list |
||
44 | int vertexorder[8192]; |
||
45 | int numorder; |
||
46 | |||
47 | int allverts, alltris; |
||
48 | |||
49 | int stripverts[128]; |
||
50 | int striptris[128]; |
||
51 | int stripcount; |
||
52 | |||
53 | /* |
||
54 | ================ |
||
55 | StripLength |
||
56 | ================ |
||
57 | */ |
||
58 | int StripLength (int starttri, int startv) |
||
59 | { |
||
60 | int m1, m2; |
||
61 | int j; |
||
62 | mtriangle_t *last, *check; |
||
63 | int k; |
||
64 | |||
65 | used[starttri] = 2; |
||
66 | |||
67 | last = &triangles[starttri]; |
||
68 | |||
69 | stripverts[0] = last->vertindex[(startv)%3]; |
||
70 | stripverts[1] = last->vertindex[(startv+1)%3]; |
||
71 | stripverts[2] = last->vertindex[(startv+2)%3]; |
||
72 | |||
73 | striptris[0] = starttri; |
||
74 | stripcount = 1; |
||
75 | |||
76 | m1 = last->vertindex[(startv+2)%3]; |
||
77 | m2 = last->vertindex[(startv+1)%3]; |
||
78 | |||
79 | // look for a matching triangle |
||
80 | nexttri: |
||
81 | for (j=starttri+1, check=&triangles[starttri+1] ; j |
||
82 | { |
||
83 | if (check->facesfront != last->facesfront) |
||
84 | continue; |
||
85 | for (k=0 ; k<3 ; k++) |
||
86 | { |
||
87 | if (check->vertindex[k] != m1) |
||
88 | continue; |
||
89 | if (check->vertindex[ (k+1)%3 ] != m2) |
||
90 | continue; |
||
91 | |||
92 | // this is the next part of the fan |
||
93 | |||
94 | // if we can't use this triangle, this tristrip is done |
||
95 | if (used[j]) |
||
96 | goto done; |
||
97 | |||
98 | // the new edge |
||
99 | if (stripcount & 1) |
||
100 | m2 = check->vertindex[ (k+2)%3 ]; |
||
101 | else |
||
102 | m1 = check->vertindex[ (k+2)%3 ]; |
||
103 | |||
104 | stripverts[stripcount+2] = check->vertindex[ (k+2)%3 ]; |
||
105 | striptris[stripcount] = j; |
||
106 | stripcount++; |
||
107 | |||
108 | used[j] = 2; |
||
109 | goto nexttri; |
||
110 | } |
||
111 | } |
||
112 | done: |
||
113 | |||
114 | // clear the temp used flags |
||
115 | for (j=starttri+1 ; j |
||
116 | if (used[j] == 2) |
||
117 | used[j] = 0; |
||
118 | |||
119 | return stripcount; |
||
120 | } |
||
121 | |||
122 | /* |
||
123 | =========== |
||
124 | FanLength |
||
125 | =========== |
||
126 | */ |
||
127 | int FanLength (int starttri, int startv) |
||
128 | { |
||
129 | int m1, m2; |
||
130 | int j; |
||
131 | mtriangle_t *last, *check; |
||
132 | int k; |
||
133 | |||
134 | used[starttri] = 2; |
||
135 | |||
136 | last = &triangles[starttri]; |
||
137 | |||
138 | stripverts[0] = last->vertindex[(startv)%3]; |
||
139 | stripverts[1] = last->vertindex[(startv+1)%3]; |
||
140 | stripverts[2] = last->vertindex[(startv+2)%3]; |
||
141 | |||
142 | striptris[0] = starttri; |
||
143 | stripcount = 1; |
||
144 | |||
145 | m1 = last->vertindex[(startv+0)%3]; |
||
146 | m2 = last->vertindex[(startv+2)%3]; |
||
147 | |||
148 | |||
149 | // look for a matching triangle |
||
150 | nexttri: |
||
151 | for (j=starttri+1, check=&triangles[starttri+1] ; j |
||
152 | { |
||
153 | if (check->facesfront != last->facesfront) |
||
154 | continue; |
||
155 | for (k=0 ; k<3 ; k++) |
||
156 | { |
||
157 | if (check->vertindex[k] != m1) |
||
158 | continue; |
||
159 | if (check->vertindex[ (k+1)%3 ] != m2) |
||
160 | continue; |
||
161 | |||
162 | // this is the next part of the fan |
||
163 | |||
164 | // if we can't use this triangle, this tristrip is done |
||
165 | if (used[j]) |
||
166 | goto done; |
||
167 | |||
168 | // the new edge |
||
169 | m2 = check->vertindex[ (k+2)%3 ]; |
||
170 | |||
171 | stripverts[stripcount+2] = m2; |
||
172 | striptris[stripcount] = j; |
||
173 | stripcount++; |
||
174 | |||
175 | used[j] = 2; |
||
176 | goto nexttri; |
||
177 | } |
||
178 | } |
||
179 | done: |
||
180 | |||
181 | // clear the temp used flags |
||
182 | for (j=starttri+1 ; j |
||
183 | if (used[j] == 2) |
||
184 | used[j] = 0; |
||
185 | |||
186 | return stripcount; |
||
187 | } |
||
188 | |||
189 | |||
190 | /* |
||
191 | ================ |
||
192 | BuildTris |
||
193 | |||
194 | Generate a list of trifans or strips |
||
195 | for the model, which holds for all frames |
||
196 | ================ |
||
197 | */ |
||
198 | void BuildTris (void) |
||
199 | { |
||
200 | int i, j, k; |
||
201 | int startv; |
||
202 | mtriangle_t *last, *check; |
||
203 | int m1, m2; |
||
204 | int striplength; |
||
205 | trivertx_t *v; |
||
206 | mtriangle_t *tv; |
||
207 | float s, t; |
||
208 | int index; |
||
209 | int len, bestlen, besttype; |
||
210 | int bestverts[1024]; |
||
211 | int besttris[1024]; |
||
212 | int type; |
||
213 | |||
214 | // |
||
215 | // build tristrips |
||
216 | // |
||
217 | numorder = 0; |
||
218 | numcommands = 0; |
||
219 | memset (used, 0, sizeof(used)); |
||
220 | for (i=0 ; i |
||
221 | { |
||
222 | // pick an unused triangle and start the trifan |
||
223 | if (used[i]) |
||
224 | continue; |
||
225 | |||
226 | bestlen = 0; |
||
227 | for (type = 0 ; type < 2 ; type++) |
||
228 | // type = 1; |
||
229 | { |
||
230 | for (startv =0 ; startv < 3 ; startv++) |
||
231 | { |
||
232 | if (type == 1) |
||
233 | len = StripLength (i, startv); |
||
234 | else |
||
235 | len = FanLength (i, startv); |
||
236 | if (len > bestlen) |
||
237 | { |
||
238 | besttype = type; |
||
239 | bestlen = len; |
||
240 | for (j=0 ; j |
||
241 | bestverts[j] = stripverts[j]; |
||
242 | for (j=0 ; j |
||
243 | besttris[j] = striptris[j]; |
||
244 | } |
||
245 | } |
||
246 | } |
||
247 | |||
248 | // mark the tris on the best strip as used |
||
249 | for (j=0 ; j |
||
250 | used[besttris[j]] = 1; |
||
251 | |||
252 | if (besttype == 1) |
||
253 | commands[numcommands++] = (bestlen+2); |
||
254 | else |
||
255 | commands[numcommands++] = -(bestlen+2); |
||
256 | |||
257 | for (j=0 ; j |
||
258 | { |
||
259 | // emit a vertex into the reorder buffer |
||
260 | k = bestverts[j]; |
||
261 | vertexorder[numorder++] = k; |
||
262 | |||
263 | // emit s/t coords into the commands stream |
||
264 | s = stverts[k].s; |
||
265 | t = stverts[k].t; |
||
266 | if (!triangles[besttris[0]].facesfront && stverts[k].onseam) |
||
267 | s += pheader->skinwidth / 2; // on back side |
||
268 | s = (s + 0.5) / pheader->skinwidth; |
||
269 | t = (t + 0.5) / pheader->skinheight; |
||
270 | |||
271 | *(float *)&commands[numcommands++] = s; |
||
272 | *(float *)&commands[numcommands++] = t; |
||
273 | } |
||
274 | } |
||
275 | |||
276 | commands[numcommands++] = 0; // end of list marker |
||
277 | |||
278 | Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands); |
||
279 | |||
280 | allverts += numorder; |
||
281 | alltris += pheader->numtris; |
||
282 | } |
||
283 | |||
284 | |||
285 | /* |
||
286 | ================ |
||
287 | GL_MakeAliasModelDisplayLists |
||
288 | ================ |
||
289 | */ |
||
290 | void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr) |
||
291 | { |
||
292 | int i, j; |
||
293 | maliasgroup_t *paliasgroup; |
||
294 | int *cmds; |
||
295 | trivertx_t *verts; |
||
296 | char cache[MAX_QPATH], fullpath[MAX_OSPATH], *c; |
||
297 | FILE *f; |
||
298 | int len; |
||
299 | byte *data; |
||
300 | |||
301 | aliasmodel = m; |
||
302 | paliashdr = hdr; // (aliashdr_t *)Mod_Extradata (m); |
||
303 | |||
304 | // |
||
305 | // look for a cached version |
||
306 | // |
||
307 | strcpy (cache, "glquake/"); |
||
308 | COM_StripExtension (m->name+strlen("progs/"), cache+strlen("glquake/")); |
||
309 | strcat (cache, ".ms2"); |
||
310 | |||
311 | COM_FOpenFile (cache, &f); |
||
312 | if (f) |
||
313 | { |
||
314 | fread (&numcommands, 4, 1, f); |
||
315 | fread (&numorder, 4, 1, f); |
||
316 | fread (&commands, numcommands * sizeof(commands[0]), 1, f); |
||
317 | fread (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f); |
||
318 | fclose (f); |
||
319 | } |
||
320 | else |
||
321 | { |
||
322 | // |
||
323 | // build it from scratch |
||
324 | // |
||
325 | Con_Printf ("meshing %s...\n",m->name); |
||
326 | |||
327 | BuildTris (); // trifans or lists |
||
328 | |||
329 | // |
||
330 | // save out the cached version |
||
331 | // |
||
332 | sprintf (fullpath, "%s/%s", com_gamedir, cache); |
||
333 | f = fopen (fullpath, "wb"); |
||
334 | if (f) |
||
335 | { |
||
336 | fwrite (&numcommands, 4, 1, f); |
||
337 | fwrite (&numorder, 4, 1, f); |
||
338 | fwrite (&commands, numcommands * sizeof(commands[0]), 1, f); |
||
339 | fwrite (&vertexorder, numorder * sizeof(vertexorder[0]), 1, f); |
||
340 | fclose (f); |
||
341 | } |
||
342 | } |
||
343 | |||
344 | |||
345 | // save the data out |
||
346 | |||
347 | paliashdr->poseverts = numorder; |
||
348 | |||
349 | cmds = Hunk_Alloc (numcommands * 4); |
||
350 | paliashdr->commands = (byte *)cmds - (byte *)paliashdr; |
||
351 | memcpy (cmds, commands, numcommands * 4); |
||
352 | |||
353 | verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts |
||
354 | * sizeof(trivertx_t) ); |
||
355 | paliashdr->posedata = (byte *)verts - (byte *)paliashdr; |
||
356 | for (i=0 ; i |
||
357 | for (j=0 ; j |
||
358 | *verts++ = poseverts[i][vertexorder[j]]; |
||
359 | }>>3>3> |
||
360 |