Bug Summary

File:client/renderer/r_model_alias.cpp
Location:line 500, column 20
Description:Array subscript is undefined

Annotated Source Code

1/**
2 * @file
3 * @brief shared alias model loading code (md2, md3)
4 */
5
6/*
7Copyright (C) 1997-2001 Id Software, Inc.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24*/
25
26#include "r_local.h"
27#include "../../shared/parse.h"
28#include "r_state.h"
29
30/*
31==============================================================================
32ALIAS MODELS
33==============================================================================
34*/
35
36void R_ModLoadAnims (mAliasModel_t *mod, const char *animname)
37{
38 const char *text, *token;
39 mAliasAnim_t *anim;
40 int n;
41 /* load the tags */
42 byte *animbuf = NULL__null;
43 const char *buffer;
44
45 FS_LoadFile(animname, &animbuf);
46
47 buffer = (const char *)animbuf;
48
49 /* count the animations */
50 n = Com_CountTokensInBuffer(buffer);
51
52 if ((n % 4) != 0) {
53 FS_FreeFile(animbuf);
54 Com_Error(ERR_DROP1, "invalid syntax: %s", animname);
55 }
56
57 /* each animation definition is made out of 4 tokens */
58 n /= 4;
59 if (n > MAX_ANIMS128)
60 n = MAX_ANIMS128;
61
62 mod->animdata = Mem_PoolAllocTypeN(mAliasAnim_t, n, vid_modelPool)static_cast<mAliasAnim_t*>(_Mem_Alloc((sizeof(mAliasAnim_t
) * (n)),true,((vid_modelPool)),(0),"src/client/renderer/r_model_alias.cpp"
,62))
;
63 anim = mod->animdata;
64 text = buffer;
65 mod->num_anims = 0;
66
67 do {
68 /* get the name */
69 token = Com_Parse(&text);
70 if (!text)
71 break;
72 Q_strncpyz(anim->name, token, sizeof(anim->name))Q_strncpyzDebug( anim->name, token, sizeof(anim->name),
"src/client/renderer/r_model_alias.cpp", 72 )
;
73
74 /* get the start */
75 token = Com_Parse(&text);
76 if (!text)
77 break;
78 anim->from = atoi(token);
79 if (anim->from < 0)
80 Com_Error(ERR_FATAL0, "R_ModLoadAnims: negative start frame for %s", animname);
81 else if (anim->from > mod->num_frames)
82 Com_Error(ERR_FATAL0, "R_ModLoadAnims: start frame is higher than models frame count (%i) (model: %s)",
83 mod->num_frames, animname);
84
85 /* get the end */
86 token = Com_Parse(&text);
87 if (!text)
88 break;
89 anim->to = atoi(token);
90 if (anim->to < 0)
91 Com_Error(ERR_FATAL0, "R_ModLoadAnims: negative start frame for %s", animname);
92 else if (anim->to > mod->num_frames)
93 Com_Error(ERR_FATAL0, "R_ModLoadAnims: end frame is higher than models frame count (%i) (model: %s)",
94 mod->num_frames, animname);
95
96 /* get the fps */
97 token = Com_Parse(&text);
98 if (!text)
99 break;
100 anim->time = (atof(token) > 0.01) ? (1000.0 / atof(token)) : (1000.0 / 0.01);
101
102 /* add it */
103 mod->num_anims++;
104 anim++;
105 } while (mod->num_anims < n);
106
107 FS_FreeFile(animbuf);
108}
109
110
111/**
112 * @brief Calculates a per-vertex tangentspace basis and stores it in GL arrays attached to the mesh
113 * @param mesh The mesh to calculate normals for
114 * @param framenum The animation frame to calculate normals for
115 * @param translate The frame translation for the given animation frame
116 * @param backlerp Whether to store the results in the GL arrays for the previous keyframe or the next keyframe
117 * @sa R_ModCalcUniqueNormalsAndTangents
118 */
119static void R_ModCalcNormalsAndTangents (mAliasMesh_t *mesh, int framenum, const vec3_t translate, bool backlerp)
120{
121 int i, j;
122 mAliasVertex_t *vertexes = &mesh->vertexes[framenum * mesh->num_verts];
123 mAliasCoord_tvec2_t *stcoords = mesh->stcoords;
124 const int numIndexes = mesh->num_tris * 3;
125 const int32_t *indexArray = mesh->indexes;
126 vec3_t triangleNormals[MAX_ALIAS_TRIS4096];
127 vec3_t triangleTangents[MAX_ALIAS_TRIS4096];
128 vec3_t triangleBitangents[MAX_ALIAS_TRIS4096];
129 float *texcoords, *verts, *normals, *tangents;
130
131 /* set up array pointers for either the previous keyframe or the next keyframe */
132 texcoords = mesh->texcoords;
133 if (backlerp) {
134 verts = mesh->verts;
135 normals = mesh->normals;
136 tangents = mesh->tangents;
137 } else {
138 verts = mesh->next_verts;
139 normals = mesh->next_normals;
140 tangents = mesh->next_tangents;
141 }
142
143 /* calculate per-triangle surface normals and tangents*/
144 for (i = 0, j = 0; i < numIndexes; i += 3, j++) {
145 vec3_t dir1, dir2;
146 vec2_t dir1uv, dir2uv;
147
148 /* calculate two mostly perpendicular edge directions */
149 VectorSubtract(vertexes[indexArray[i + 0]].point, vertexes[indexArray[i + 1]].point, dir1)((dir1)[0]=(vertexes[indexArray[i + 0]].point)[0]-(vertexes[indexArray
[i + 1]].point)[0],(dir1)[1]=(vertexes[indexArray[i + 0]].point
)[1]-(vertexes[indexArray[i + 1]].point)[1],(dir1)[2]=(vertexes
[indexArray[i + 0]].point)[2]-(vertexes[indexArray[i + 1]].point
)[2])
;
150 VectorSubtract(vertexes[indexArray[i + 2]].point, vertexes[indexArray[i + 1]].point, dir2)((dir2)[0]=(vertexes[indexArray[i + 2]].point)[0]-(vertexes[indexArray
[i + 1]].point)[0],(dir2)[1]=(vertexes[indexArray[i + 2]].point
)[1]-(vertexes[indexArray[i + 1]].point)[1],(dir2)[2]=(vertexes
[indexArray[i + 2]].point)[2]-(vertexes[indexArray[i + 1]].point
)[2])
;
151 Vector2Subtract(stcoords[indexArray[i + 0]], stcoords[indexArray[i + 1]], dir1uv)((dir1uv)[0]=(stcoords[indexArray[i + 0]])[0]-(stcoords[indexArray
[i + 1]])[0],(dir1uv)[1]=(stcoords[indexArray[i + 0]])[1]-(stcoords
[indexArray[i + 1]])[1])
;
152 Vector2Subtract(stcoords[indexArray[i + 2]], stcoords[indexArray[i + 1]], dir2uv)((dir2uv)[0]=(stcoords[indexArray[i + 2]])[0]-(stcoords[indexArray
[i + 1]])[0],(dir2uv)[1]=(stcoords[indexArray[i + 2]])[1]-(stcoords
[indexArray[i + 1]])[1])
;
153
154 /* we have two edge directions, we can calculate a third vector from
155 * them, which is the direction of the surface normal */
156 CrossProduct(dir1, dir2, triangleNormals[j]);
157 /* normalize */
158 VectorNormalizeFast(triangleNormals[j]);
159
160 /* then we use the texture coordinates to calculate a tangent space */
161 if ((dir1uv[1] * dir2uv[0] - dir1uv[0] * dir2uv[1]) != 0.0) {
162 const float frac = 1.0 / (dir1uv[1] * dir2uv[0] - dir1uv[0] * dir2uv[1]);
163 vec3_t tmp1, tmp2;
164
165 /* calculate tangent */
166 VectorMul(-1.0 * dir2uv[1] * frac, dir1, tmp1)((tmp1)[0]=(-1.0 * dir2uv[1] * frac)*(dir1)[0],(tmp1)[1]=(-1.0
* dir2uv[1] * frac)*(dir1)[1],(tmp1)[2]=(-1.0 * dir2uv[1] * frac
)*(dir1)[2])
;
167 VectorMul(dir1uv[1] * frac, dir2, tmp2)((tmp2)[0]=(dir1uv[1] * frac)*(dir2)[0],(tmp2)[1]=(dir1uv[1] *
frac)*(dir2)[1],(tmp2)[2]=(dir1uv[1] * frac)*(dir2)[2])
;
168 VectorAdd(tmp1, tmp2, triangleTangents[j])((triangleTangents[j])[0]=(tmp1)[0]+(tmp2)[0],(triangleTangents
[j])[1]=(tmp1)[1]+(tmp2)[1],(triangleTangents[j])[2]=(tmp1)[2
]+(tmp2)[2])
;
169
170 /* calculate bitangent */
171 VectorMul(-1.0 * dir2uv[0] * frac, dir1, tmp1)((tmp1)[0]=(-1.0 * dir2uv[0] * frac)*(dir1)[0],(tmp1)[1]=(-1.0
* dir2uv[0] * frac)*(dir1)[1],(tmp1)[2]=(-1.0 * dir2uv[0] * frac
)*(dir1)[2])
;
172 VectorMul(dir1uv[0] * frac, dir2, tmp2)((tmp2)[0]=(dir1uv[0] * frac)*(dir2)[0],(tmp2)[1]=(dir1uv[0] *
frac)*(dir2)[1],(tmp2)[2]=(dir1uv[0] * frac)*(dir2)[2])
;
173 VectorAdd(tmp1, tmp2, triangleBitangents[j])((triangleBitangents[j])[0]=(tmp1)[0]+(tmp2)[0],(triangleBitangents
[j])[1]=(tmp1)[1]+(tmp2)[1],(triangleBitangents[j])[2]=(tmp1)
[2]+(tmp2)[2])
;
174
175 /* normalize */
176 VectorNormalizeFast(triangleTangents[j]);
177 VectorNormalizeFast(triangleBitangents[j]);
178 } else {
179 VectorClear(triangleTangents[j])((triangleTangents[j])[0]=(triangleTangents[j])[1]=(triangleTangents
[j])[2]=0)
;
180 VectorClear(triangleBitangents[j])((triangleBitangents[j])[0]=(triangleBitangents[j])[1]=(triangleBitangents
[j])[2]=0)
;
181 }
182 }
183
184 /* for each vertex */
185 for (i = 0; i < mesh->num_verts; i++) {
186 vec3_t n, b, v;
187 vec4_t t;
188 const int len = mesh->revIndexes[i].length;
189 const int32_t *list = mesh->revIndexes[i].list;
190
191 VectorClear(n)((n)[0]=(n)[1]=(n)[2]=0);
192 VectorClear(t)((t)[0]=(t)[1]=(t)[2]=0);
193 VectorClear(b)((b)[0]=(b)[1]=(b)[2]=0);
194
195 /* for each vertex that got mapped to this one (ie. for each triangle this vertex is a part of) */
196 for (j = 0; j < len; j++) {
197 const int32_t idx = list[j] / 3;
198 VectorAdd(n, triangleNormals[idx], n)((n)[0]=(n)[0]+(triangleNormals[idx])[0],(n)[1]=(n)[1]+(triangleNormals
[idx])[1],(n)[2]=(n)[2]+(triangleNormals[idx])[2])
;
199 VectorAdd(t, triangleTangents[idx], t)((t)[0]=(t)[0]+(triangleTangents[idx])[0],(t)[1]=(t)[1]+(triangleTangents
[idx])[1],(t)[2]=(t)[2]+(triangleTangents[idx])[2])
;
200 VectorAdd(b, triangleBitangents[idx], b)((b)[0]=(b)[0]+(triangleBitangents[idx])[0],(b)[1]=(b)[1]+(triangleBitangents
[idx])[1],(b)[2]=(b)[2]+(triangleBitangents[idx])[2])
;
201 }
202
203 /* normalization here does shared-vertex smoothing */
204 VectorNormalizeFast(n);
205 VectorNormalizeFast(t);
206 VectorNormalizeFast(b);
207
208 /* Grahm-Schmidt orthogonalization */
209 Orthogonalize(t, n);
210
211 /* calculate handedness */
212 CrossProduct(n, t, v);
213 t[3] = (DotProduct(v, b)((v)[0]*(b)[0]+(v)[1]*(b)[1]+(v)[2]*(b)[2]) < 0.0) ? -1.0 : 1.0;
214
215 /* copy this vertex's info to all the right places in the arrays */
216 for (j = 0; j < len; j++) {
217 const int32_t idx = list[j];
218 const int meshIndex = mesh->indexes[list[j]];
219 Vector2Copy(stcoords[meshIndex], (texcoords + (2 * idx)))(((texcoords + (2 * idx)))[0]=(stcoords[meshIndex])[0],((texcoords
+ (2 * idx)))[1]=(stcoords[meshIndex])[1])
;
220 VectorAdd(vertexes[meshIndex].point, translate, (verts + (3 * idx)))(((verts + (3 * idx)))[0]=(vertexes[meshIndex].point)[0]+(translate
)[0],((verts + (3 * idx)))[1]=(vertexes[meshIndex].point)[1]+
(translate)[1],((verts + (3 * idx)))[2]=(vertexes[meshIndex].
point)[2]+(translate)[2])
;
221 VectorCopy(n, (normals + (3 * idx)))(((normals + (3 * idx)))[0]=(n)[0],((normals + (3 * idx)))[1]
=(n)[1],((normals + (3 * idx)))[2]=(n)[2])
;
222 Vector4Copy(t, (tangents + (4 * idx)))(((tangents + (4 * idx)))[0]=(t)[0],((tangents + (4 * idx)))[
1]=(t)[1],((tangents + (4 * idx)))[2]=(t)[2],((tangents + (4 *
idx)))[3]=(t)[3])
;
223 }
224 }
225}
226
227/**
228 * @brief Tries to load a mdx file that contains the normals and the tangents for a model.
229 * @sa R_ModCalcNormalsAndTangents
230 * @sa R_ModCalcUniqueNormalsAndTangents
231 * @param mod The model to load the mdx file for
232 */
233bool R_ModLoadMDX (model_t *mod)
234{
235 int i;
236 for (i = 0; i < mod->alias.num_meshes; i++) {
237 mAliasMesh_t *mesh = &mod->alias.meshes[i];
238 char mdxFileName[MAX_QPATH64];
239 byte *buffer = NULL__null, *buf;
240 const int32_t *intbuf;
241 uint32_t version;
242 int sharedTris[MAX_ALIAS_VERTS8192];
243
244 Com_StripExtension(mod->name, mdxFileName, sizeof(mdxFileName));
245 Com_DefaultExtension(mdxFileName, sizeof(mdxFileName), ".mdx");
246
247 if (FS_LoadFile(mdxFileName, &buffer) == -1)
248 return false;
249
250 buf = buffer;
251 if (strncmp((const char *) buf, IDMDXHEADER"UFOMDX", strlen(IDMDXHEADER"UFOMDX"))) {
252 FS_FreeFile(buf);
253 Com_Error(ERR_DROP1, "No mdx file buffer given");
254 }
255 buffer += strlen(IDMDXHEADER"UFOMDX") * sizeof(char);
256 version = LittleLong(*(uint32_t*) buffer)(int)(*(uint32_t*) buffer);
257 if (version != MDX_VERSION1) {
258 FS_FreeFile(buf);
259 Com_Error(ERR_DROP1, "Invalid version of the mdx file, expected %i, found %i",
260 MDX_VERSION1, version);
261 }
262 buffer += sizeof(uint32_t);
263
264 intbuf = (const int32_t *) buffer;
265
266 mesh->num_verts = LittleLong(*intbuf)(int)(*intbuf);
267 if (mesh->num_verts <= 0 || mesh->num_verts > MAX_ALIAS_VERTS8192) {
268 FS_FreeFile(buf);
269 Com_Error(ERR_DROP1, "mdx file for %s has to many (or no) vertices: %i", mod->name, mesh->num_verts);
270 }
271 intbuf++;
272 mesh->num_indexes = LittleLong(*intbuf)(int)(*intbuf);
273 intbuf++;
274
275 mesh->indexes = Mem_PoolAllocTypeN(int32_t, mesh->num_indexes, vid_modelPool)static_cast<int32_t*>(_Mem_Alloc((sizeof(int32_t) * (mesh
->num_indexes)),true,((vid_modelPool)),(0),"src/client/renderer/r_model_alias.cpp"
,275))
;
276 mesh->revIndexes = Mem_PoolAllocTypeN(mIndexList_t, mesh->num_verts, vid_modelPool)static_cast<mIndexList_t*>(_Mem_Alloc((sizeof(mIndexList_t
) * (mesh->num_verts)),true,((vid_modelPool)),(0),"src/client/renderer/r_model_alias.cpp"
,276))
;
277 mesh->vertexes = Mem_PoolAllocTypeN(mAliasVertex_t, mesh->num_verts * mod->alias.num_frames, vid_modelPool)static_cast<mAliasVertex_t*>(_Mem_Alloc((sizeof(mAliasVertex_t
) * (mesh->num_verts * mod->alias.num_frames)),true,((vid_modelPool
)),(0),"src/client/renderer/r_model_alias.cpp",277))
;
278
279 /* load index that maps triangle verts to Vertex objects */
280 for (i = 0; i < mesh->num_indexes; i++) {
281 mesh->indexes[i] = LittleLong(*intbuf)(int)(*intbuf);
282 intbuf++;
283 }
284
285 for (i = 0; i < mesh->num_verts; i++)
286 sharedTris[i] = 0;
287
288 /* set up reverse-index that maps Vertex objects to a list of triangle verts */
289 for (i = 0; i < mesh->num_indexes; i++)
290 sharedTris[mesh->indexes[i]]++;
291
292 for (i = 0; i < mesh->num_verts; i++) {
293 mesh->revIndexes[i].length = 0;
294 mesh->revIndexes[i].list = Mem_PoolAllocTypeN(int32_t, sharedTris[i], vid_modelPool)static_cast<int32_t*>(_Mem_Alloc((sizeof(int32_t) * (sharedTris
[i])),true,((vid_modelPool)),(0),"src/client/renderer/r_model_alias.cpp"
,294))
;
295 }
296
297 for (i = 0; i < mesh->num_indexes; i++)
298 mesh->revIndexes[mesh->indexes[i]].list[mesh->revIndexes[mesh->indexes[i]].length++] = i;
299
300 FS_FreeFile(buf);
301 }
302
303 return true;
304}
305
306/**
307 * @brief Calculates normals and tangents for all frames and does vertex merging based on smoothness
308 * @param mesh The mesh to calculate normals for
309 * @param nFrames How many frames the mesh has
310 * @param smoothness How aggressively should normals be smoothed; value is compared with dotproduct of vectors to decide if they should be merged
311 * @sa R_ModCalcNormalsAndTangents
312 */
313void R_ModCalcUniqueNormalsAndTangents (mAliasMesh_t *mesh, int nFrames, float smoothness)
314{
315 int i, j;
316 vec3_t triangleNormals[MAX_ALIAS_TRIS4096];
317 vec3_t triangleTangents[MAX_ALIAS_TRIS4096];
318 vec3_t triangleBitangents[MAX_ALIAS_TRIS4096];
319 const mAliasVertex_t *vertexes = mesh->vertexes;
320 mAliasCoord_tvec2_t *stcoords = mesh->stcoords;
321 mAliasComplexVertex_t tmpVertexes[MAX_ALIAS_VERTS8192];
322 vec3_t tmpBitangents[MAX_ALIAS_VERTS8192];
323 const int numIndexes = mesh->num_tris * 3;
324 const int32_t *indexArray = mesh->indexes;
325 int indRemap[MAX_ALIAS_VERTS8192];
326 int sharedTris[MAX_ALIAS_VERTS8192];
327 int numVerts = 0;
328
329 if (numIndexes >= MAX_ALIAS_VERTS8192)
1
Taking false branch
330 Com_Error(ERR_DROP1, "model %s has too many tris", mesh->name);
331
332 int32_t* const newIndexArray = Mem_PoolAllocTypeN(int32_t, numIndexes, vid_modelPool)static_cast<int32_t*>(_Mem_Alloc((sizeof(int32_t) * (numIndexes
)),true,((vid_modelPool)),(0),"src/client/renderer/r_model_alias.cpp"
,332))
;
333
334 /* calculate per-triangle surface normals */
335 for (i = 0, j = 0; i < numIndexes; i += 3, j++) {
2
Loop condition is true. Entering loop body
4
Loop condition is false. Execution continues on line 387
336 vec3_t dir1, dir2;
337 vec2_t dir1uv, dir2uv;
338
339 /* calculate two mostly perpendicular edge directions */
340 VectorSubtract(vertexes[indexArray[i + 0]].point, vertexes[indexArray[i + 1]].point, dir1)((dir1)[0]=(vertexes[indexArray[i + 0]].point)[0]-(vertexes[indexArray
[i + 1]].point)[0],(dir1)[1]=(vertexes[indexArray[i + 0]].point
)[1]-(vertexes[indexArray[i + 1]].point)[1],(dir1)[2]=(vertexes
[indexArray[i + 0]].point)[2]-(vertexes[indexArray[i + 1]].point
)[2])
;
341 VectorSubtract(vertexes[indexArray[i + 2]].point, vertexes[indexArray[i + 1]].point, dir2)((dir2)[0]=(vertexes[indexArray[i + 2]].point)[0]-(vertexes[indexArray
[i + 1]].point)[0],(dir2)[1]=(vertexes[indexArray[i + 2]].point
)[1]-(vertexes[indexArray[i + 1]].point)[1],(dir2)[2]=(vertexes
[indexArray[i + 2]].point)[2]-(vertexes[indexArray[i + 1]].point
)[2])
;
342 Vector2Subtract(stcoords[indexArray[i + 0]], stcoords[indexArray[i + 1]], dir1uv)((dir1uv)[0]=(stcoords[indexArray[i + 0]])[0]-(stcoords[indexArray
[i + 1]])[0],(dir1uv)[1]=(stcoords[indexArray[i + 0]])[1]-(stcoords
[indexArray[i + 1]])[1])
;
343 Vector2Subtract(stcoords[indexArray[i + 2]], stcoords[indexArray[i + 1]], dir2uv)((dir2uv)[0]=(stcoords[indexArray[i + 2]])[0]-(stcoords[indexArray
[i + 1]])[0],(dir2uv)[1]=(stcoords[indexArray[i + 2]])[1]-(stcoords
[indexArray[i + 1]])[1])
;
344
345 /* we have two edge directions, we can calculate a third vector from
346 * them, which is the direction of the surface normal */
347 CrossProduct(dir1, dir2, triangleNormals[j]);
348
349 /* then we use the texture coordinates to calculate a tangent space */
350 if ((dir1uv[1] * dir2uv[0] - dir1uv[0] * dir2uv[1]) != 0.0) {
3
Taking false branch
351 const float frac = 1.0 / (dir1uv[1] * dir2uv[0] - dir1uv[0] * dir2uv[1]);
352 vec3_t tmp1, tmp2;
353
354 /* calculate tangent */
355 VectorMul(-1.0 * dir2uv[1] * frac, dir1, tmp1)((tmp1)[0]=(-1.0 * dir2uv[1] * frac)*(dir1)[0],(tmp1)[1]=(-1.0
* dir2uv[1] * frac)*(dir1)[1],(tmp1)[2]=(-1.0 * dir2uv[1] * frac
)*(dir1)[2])
;
356 VectorMul(dir1uv[1] * frac, dir2, tmp2)((tmp2)[0]=(dir1uv[1] * frac)*(dir2)[0],(tmp2)[1]=(dir1uv[1] *
frac)*(dir2)[1],(tmp2)[2]=(dir1uv[1] * frac)*(dir2)[2])
;
357 VectorAdd(tmp1, tmp2, triangleTangents[j])((triangleTangents[j])[0]=(tmp1)[0]+(tmp2)[0],(triangleTangents
[j])[1]=(tmp1)[1]+(tmp2)[1],(triangleTangents[j])[2]=(tmp1)[2
]+(tmp2)[2])
;
358
359 /* calculate bitangent */
360 VectorMul(-1.0 * dir2uv[0] * frac, dir1, tmp1)((tmp1)[0]=(-1.0 * dir2uv[0] * frac)*(dir1)[0],(tmp1)[1]=(-1.0
* dir2uv[0] * frac)*(dir1)[1],(tmp1)[2]=(-1.0 * dir2uv[0] * frac
)*(dir1)[2])
;
361 VectorMul(dir1uv[0] * frac, dir2, tmp2)((tmp2)[0]=(dir1uv[0] * frac)*(dir2)[0],(tmp2)[1]=(dir1uv[0] *
frac)*(dir2)[1],(tmp2)[2]=(dir1uv[0] * frac)*(dir2)[2])
;
362 VectorAdd(tmp1, tmp2, triangleBitangents[j])((triangleBitangents[j])[0]=(tmp1)[0]+(tmp2)[0],(triangleBitangents
[j])[1]=(tmp1)[1]+(tmp2)[1],(triangleBitangents[j])[2]=(tmp1)
[2]+(tmp2)[2])
;
363 } else {
364 const float frac = 1.0 / (0.00001);
365 vec3_t tmp1, tmp2;
366
367 /* calculate tangent */
368 VectorMul(-1.0 * dir2uv[1] * frac, dir1, tmp1)((tmp1)[0]=(-1.0 * dir2uv[1] * frac)*(dir1)[0],(tmp1)[1]=(-1.0
* dir2uv[1] * frac)*(dir1)[1],(tmp1)[2]=(-1.0 * dir2uv[1] * frac
)*(dir1)[2])
;
369 VectorMul(dir1uv[1] * frac, dir2, tmp2)((tmp2)[0]=(dir1uv[1] * frac)*(dir2)[0],(tmp2)[1]=(dir1uv[1] *
frac)*(dir2)[1],(tmp2)[2]=(dir1uv[1] * frac)*(dir2)[2])
;
370 VectorAdd(tmp1, tmp2, triangleTangents[j])((triangleTangents[j])[0]=(tmp1)[0]+(tmp2)[0],(triangleTangents
[j])[1]=(tmp1)[1]+(tmp2)[1],(triangleTangents[j])[2]=(tmp1)[2
]+(tmp2)[2])
;
371
372 /* calculate bitangent */
373 VectorMul(-1.0 * dir2uv[0] * frac, dir1, tmp1)((tmp1)[0]=(-1.0 * dir2uv[0] * frac)*(dir1)[0],(tmp1)[1]=(-1.0
* dir2uv[0] * frac)*(dir1)[1],(tmp1)[2]=(-1.0 * dir2uv[0] * frac
)*(dir1)[2])
;
374 VectorMul(dir1uv[0] * frac, dir2, tmp2)((tmp2)[0]=(dir1uv[0] * frac)*(dir2)[0],(tmp2)[1]=(dir1uv[0] *
frac)*(dir2)[1],(tmp2)[2]=(dir1uv[0] * frac)*(dir2)[2])
;
375 VectorAdd(tmp1, tmp2, triangleBitangents[j])((triangleBitangents[j])[0]=(tmp1)[0]+(tmp2)[0],(triangleBitangents
[j])[1]=(tmp1)[1]+(tmp2)[1],(triangleBitangents[j])[2]=(tmp1)
[2]+(tmp2)[2])
;
376 }
377
378 /* normalize */
379 VectorNormalizeFast(triangleNormals[j]);
380 VectorNormalizeFast(triangleTangents[j]);
381 VectorNormalizeFast(triangleBitangents[j]);
382
383 Orthogonalize(triangleTangents[j], triangleBitangents[j]);
384 }
385
386 /* do smoothing */
387 for (i = 0; i < numIndexes; i++) {
5
Loop condition is true. Entering loop body
10
Loop condition is false. Execution continues on line 428
388 const int idx = (i - i % 3) / 3;
389 VectorCopy(triangleNormals[idx], tmpVertexes[i].normal)((tmpVertexes[i].normal)[0]=(triangleNormals[idx])[0],(tmpVertexes
[i].normal)[1]=(triangleNormals[idx])[1],(tmpVertexes[i].normal
)[2]=(triangleNormals[idx])[2])
;
390 VectorCopy(triangleTangents[idx], tmpVertexes[i].tangent)((tmpVertexes[i].tangent)[0]=(triangleTangents[idx])[0],(tmpVertexes
[i].tangent)[1]=(triangleTangents[idx])[1],(tmpVertexes[i].tangent
)[2]=(triangleTangents[idx])[2])
;
391 VectorCopy(triangleBitangents[idx], tmpBitangents[i])((tmpBitangents[i])[0]=(triangleBitangents[idx])[0],(tmpBitangents
[i])[1]=(triangleBitangents[idx])[1],(tmpBitangents[i])[2]=(triangleBitangents
[idx])[2])
;
392
393 for (j = 0; j < numIndexes; j++) {
6
Loop condition is true. Entering loop body
9
Loop condition is false. Execution continues on line 422
394 const int idx2 = (j - j % 3) / 3;
395 /* don't add a vertex with itself */
396 if (j == i)
7
Taking true branch
397 continue;
8
Execution continues on line 393
398
399 /* only average normals if vertices have the same position
400 * and the normals aren't too far apart to start with */
401 if (VectorEqual(vertexes[indexArray[i]].point, vertexes[indexArray[j]].point)((fabs(((vertexes[indexArray[i]].point)[0])-((vertexes[indexArray
[j]].point)[0]))<0.0000000001)?(fabs(((vertexes[indexArray
[i]].point)[1])-((vertexes[indexArray[j]].point)[1]))<0.0000000001
)?(fabs(((vertexes[indexArray[i]].point)[2])-((vertexes[indexArray
[j]].point)[2]))<0.0000000001)?1:0:0:0)
402 && DotProduct(triangleNormals[idx], triangleNormals[idx2])((triangleNormals[idx])[0]*(triangleNormals[idx2])[0]+(triangleNormals
[idx])[1]*(triangleNormals[idx2])[1]+(triangleNormals[idx])[2
]*(triangleNormals[idx2])[2])
> smoothness) {
403 /* average the normals */
404 VectorAdd(tmpVertexes[i].normal, triangleNormals[idx2], tmpVertexes[i].normal)((tmpVertexes[i].normal)[0]=(tmpVertexes[i].normal)[0]+(triangleNormals
[idx2])[0],(tmpVertexes[i].normal)[1]=(tmpVertexes[i].normal)
[1]+(triangleNormals[idx2])[1],(tmpVertexes[i].normal)[2]=(tmpVertexes
[i].normal)[2]+(triangleNormals[idx2])[2])
;
405
406 /* if the tangents match as well, average them too.
407 * Note that having matching normals without matching tangents happens
408 * when the order of vertices in two triangles sharing the vertex
409 * in question is different. This happens quite frequently if the
410 * modeler does not go out of their way to avoid it. */
411
412 if (Vector2Equal(stcoords[indexArray[i]], stcoords[indexArray[j]])((fabs(((stcoords[indexArray[i]])[0])-((stcoords[indexArray[j
]])[0]))<0.0000000001)?(fabs(((stcoords[indexArray[i]])[1]
)-((stcoords[indexArray[j]])[1]))<0.0000000001)?1:0:0)
413 && DotProduct(triangleTangents[idx], triangleTangents[idx2])((triangleTangents[idx])[0]*(triangleTangents[idx2])[0]+(triangleTangents
[idx])[1]*(triangleTangents[idx2])[1]+(triangleTangents[idx])
[2]*(triangleTangents[idx2])[2])
> smoothness
414 && DotProduct(triangleBitangents[idx], triangleBitangents[idx2])((triangleBitangents[idx])[0]*(triangleBitangents[idx2])[0]+(
triangleBitangents[idx])[1]*(triangleBitangents[idx2])[1]+(triangleBitangents
[idx])[2]*(triangleBitangents[idx2])[2])
> smoothness) {
415 /* average the tangents */
416 VectorAdd(tmpVertexes[i].tangent, triangleTangents[idx2], tmpVertexes[i].tangent)((tmpVertexes[i].tangent)[0]=(tmpVertexes[i].tangent)[0]+(triangleTangents
[idx2])[0],(tmpVertexes[i].tangent)[1]=(tmpVertexes[i].tangent
)[1]+(triangleTangents[idx2])[1],(tmpVertexes[i].tangent)[2]=
(tmpVertexes[i].tangent)[2]+(triangleTangents[idx2])[2])
;
417 VectorAdd(tmpBitangents[i], triangleBitangents[idx2], tmpBitangents[i])((tmpBitangents[i])[0]=(tmpBitangents[i])[0]+(triangleBitangents
[idx2])[0],(tmpBitangents[i])[1]=(tmpBitangents[i])[1]+(triangleBitangents
[idx2])[1],(tmpBitangents[i])[2]=(tmpBitangents[i])[2]+(triangleBitangents
[idx2])[2])
;
418 }
419 }
420 }
421
422 VectorNormalizeFast(tmpVertexes[i].normal);
423 VectorNormalizeFast(tmpVertexes[i].tangent);
424 VectorNormalizeFast(tmpBitangents[i]);
425 }
426
427 /* assume all vertices are unique until proven otherwise */
428 for (i = 0; i < numIndexes; i++)
11
Loop condition is true. Entering loop body
12
Loop condition is false. Execution continues on line 432
429 indRemap[i] = -1;
430
431 /* merge vertices that have become identical */
432 for (i = 0; i < numIndexes; i++) {
13
Loop condition is true. Entering loop body
17
Loop condition is false. Execution continues on line 471
433 vec3_t n, b, t, v;
434 if (indRemap[i] != -1)
14
Taking false branch
435 continue;
436
437 for (j = i + 1; j < numIndexes; j++) {
15
Loop condition is false. Execution continues on line 447
438 if (Vector2Equal(stcoords[indexArray[i]], stcoords[indexArray[j]])((fabs(((stcoords[indexArray[i]])[0])-((stcoords[indexArray[j
]])[0]))<0.0000000001)?(fabs(((stcoords[indexArray[i]])[1]
)-((stcoords[indexArray[j]])[1]))<0.0000000001)?1:0:0)
439 && VectorEqual(vertexes[indexArray[i]].point, vertexes[indexArray[j]].point)((fabs(((vertexes[indexArray[i]].point)[0])-((vertexes[indexArray
[j]].point)[0]))<0.0000000001)?(fabs(((vertexes[indexArray
[i]].point)[1])-((vertexes[indexArray[j]].point)[1]))<0.0000000001
)?(fabs(((vertexes[indexArray[i]].point)[2])-((vertexes[indexArray
[j]].point)[2]))<0.0000000001)?1:0:0:0)
440 && (DotProduct(tmpVertexes[i].normal, tmpVertexes[j].normal)((tmpVertexes[i].normal)[0]*(tmpVertexes[j].normal)[0]+(tmpVertexes
[i].normal)[1]*(tmpVertexes[j].normal)[1]+(tmpVertexes[i].normal
)[2]*(tmpVertexes[j].normal)[2])
> smoothness)
441 && (DotProduct(tmpVertexes[i].tangent, tmpVertexes[j].tangent)((tmpVertexes[i].tangent)[0]*(tmpVertexes[j].tangent)[0]+(tmpVertexes
[i].tangent)[1]*(tmpVertexes[j].tangent)[1]+(tmpVertexes[i].tangent
)[2]*(tmpVertexes[j].tangent)[2])
> smoothness)) {
442 indRemap[j] = i;
443 newIndexArray[j] = numVerts;
444 }
445 }
446
447 VectorCopy(tmpVertexes[i].normal, n)((n)[0]=(tmpVertexes[i].normal)[0],(n)[1]=(tmpVertexes[i].normal
)[1],(n)[2]=(tmpVertexes[i].normal)[2])
;
448 VectorCopy(tmpVertexes[i].tangent, t)((t)[0]=(tmpVertexes[i].tangent)[0],(t)[1]=(tmpVertexes[i].tangent
)[1],(t)[2]=(tmpVertexes[i].tangent)[2])
;
449 VectorCopy(tmpBitangents[i], b)((b)[0]=(tmpBitangents[i])[0],(b)[1]=(tmpBitangents[i])[1],(b
)[2]=(tmpBitangents[i])[2])
;
450
451 /* normalization here does shared-vertex smoothing */
452 VectorNormalizeFast(n);
453 VectorNormalizeFast(t);
454 VectorNormalizeFast(b);
455
456 /* Grahm-Schmidt orthogonalization */
457 VectorMul(DotProduct(t, n), n, v)((v)[0]=(((t)[0]*(n)[0]+(t)[1]*(n)[1]+(t)[2]*(n)[2]))*(n)[0],
(v)[1]=(((t)[0]*(n)[0]+(t)[1]*(n)[1]+(t)[2]*(n)[2]))*(n)[1],(
v)[2]=(((t)[0]*(n)[0]+(t)[1]*(n)[1]+(t)[2]*(n)[2]))*(n)[2])
;
458 VectorSubtract(t, v, t)((t)[0]=(t)[0]-(v)[0],(t)[1]=(t)[1]-(v)[1],(t)[2]=(t)[2]-(v)[
2])
;
459 VectorNormalizeFast(t);
460
461 /* calculate handedness */
462 CrossProduct(n, t, v);
463 tmpVertexes[i].tangent[3] = (DotProduct(v, b)((v)[0]*(b)[0]+(v)[1]*(b)[1]+(v)[2]*(b)[2]) < 0.0) ? -1.0 : 1.0;
16
'?' condition is false
464 VectorCopy(n, tmpVertexes[i].normal)((tmpVertexes[i].normal)[0]=(n)[0],(tmpVertexes[i].normal)[1]
=(n)[1],(tmpVertexes[i].normal)[2]=(n)[2])
;
465 VectorCopy(t, tmpVertexes[i].tangent)((tmpVertexes[i].tangent)[0]=(t)[0],(tmpVertexes[i].tangent)[
1]=(t)[1],(tmpVertexes[i].tangent)[2]=(t)[2])
;
466
467 newIndexArray[i] = numVerts++;
468 indRemap[i] = i;
469 }
470
471 for (i = 0; i < numVerts; i++)
18
Loop condition is true. Entering loop body
19
Loop condition is false. Execution continues on line 474
472 sharedTris[i] = 0;
473
474 for (i = 0; i < numIndexes; i++)
20
Loop condition is false. Execution continues on line 478
475 sharedTris[newIndexArray[i]]++;
476
477 /* set up reverse-index that maps Vertex objects to a list of triangle verts */
478 mesh->revIndexes = Mem_PoolAllocTypeN(mIndexList_t, numVerts, vid_modelPool)static_cast<mIndexList_t*>(_Mem_Alloc((sizeof(mIndexList_t
) * (numVerts)),true,((vid_modelPool)),(0),"src/client/renderer/r_model_alias.cpp"
,478))
;
479 for (i = 0; i < numVerts; i++) {
21
Loop condition is true. Entering loop body
22
Loop condition is false. Execution continues on line 485
480 mesh->revIndexes[i].length = 0;
481 mesh->revIndexes[i].list = Mem_PoolAllocTypeN(int32_t, sharedTris[i], vid_modelPool)static_cast<int32_t*>(_Mem_Alloc((sizeof(int32_t) * (sharedTris
[i])),true,((vid_modelPool)),(0),"src/client/renderer/r_model_alias.cpp"
,481))
;
482 }
483
484 /* merge identical vertexes, storing only unique ones */
485 mAliasVertex_t* const newVertexes = Mem_PoolAllocTypeN(mAliasVertex_t, numVerts * nFrames, vid_modelPool)static_cast<mAliasVertex_t*>(_Mem_Alloc((sizeof(mAliasVertex_t
) * (numVerts * nFrames)),true,((vid_modelPool)),(0),"src/client/renderer/r_model_alias.cpp"
,485))
;
486 mAliasCoord_tvec2_t* const newStcoords = Mem_PoolAllocTypeN(mAliasCoord_t, numVerts, vid_modelPool)static_cast<vec2_t*>(_Mem_Alloc((sizeof(vec2_t) * (numVerts
)),true,((vid_modelPool)),(0),"src/client/renderer/r_model_alias.cpp"
,486))
;
487 for (i = 0; i < numIndexes; i++) {
23
Loop condition is true. Entering loop body
24
Loop condition is false. Execution continues on line 498
488 const int idx = indexArray[indRemap[i]];
489 const int idx2 = newIndexArray[i];
490
491 /* add vertex to new vertex array */
492 VectorCopy(vertexes[idx].point, newVertexes[idx2].point)((newVertexes[idx2].point)[0]=(vertexes[idx].point)[0],(newVertexes
[idx2].point)[1]=(vertexes[idx].point)[1],(newVertexes[idx2].
point)[2]=(vertexes[idx].point)[2])
;
493 Vector2Copy(stcoords[idx], newStcoords[idx2])((newStcoords[idx2])[0]=(stcoords[idx])[0],(newStcoords[idx2]
)[1]=(stcoords[idx])[1])
;
494 mesh->revIndexes[idx2].list[mesh->revIndexes[idx2].length++] = i;
495 }
496
497 /* copy over the points from successive frames */
498 for (i = 1; i < nFrames; i++) {
25
Loop condition is true. Entering loop body
499 for (j = 0; j < numIndexes; j++) {
26
Loop condition is true. Entering loop body
27
Loop condition is true. Entering loop body
500 const int idx = indexArray[indRemap[j]] + (mesh->num_verts * i);
28
Array subscript is undefined
501 const int idx2 = newIndexArray[j] + (numVerts * i);
502
503 VectorCopy(vertexes[idx].point, newVertexes[idx2].point)((newVertexes[idx2].point)[0]=(vertexes[idx].point)[0],(newVertexes
[idx2].point)[1]=(vertexes[idx].point)[1],(newVertexes[idx2].
point)[2]=(vertexes[idx].point)[2])
;
504 }
505 }
506
507 /* copy new arrays back into original mesh */
508 Mem_Free(mesh->stcoords)_Mem_Free((mesh->stcoords),"src/client/renderer/r_model_alias.cpp"
,508)
;
509 Mem_Free(mesh->indexes)_Mem_Free((mesh->indexes),"src/client/renderer/r_model_alias.cpp"
,509)
;
510 Mem_Free(mesh->vertexes)_Mem_Free((mesh->vertexes),"src/client/renderer/r_model_alias.cpp"
,510)
;
511
512 mesh->num_verts = numVerts;
513 mesh->vertexes = newVertexes;
514 mesh->stcoords = newStcoords;
515 mesh->indexes = newIndexArray;
516}
517
518image_t* R_AliasModelGetSkin (const char *modelFileName, const char *skin)
519{
520 image_t* result;
521 if (skin[0] != '.')
522 result = R_FindImage(skin, it_skin);
523 else {
524 char path[MAX_QPATH64];
525 Com_ReplaceFilename(modelFileName, skin + 1, path, sizeof(path));
526 result = R_FindImage(path, it_skin);
527 }
528 return result;
529}
530
531image_t* R_AliasModelState (const model_t *mod, int *mesh, int *frame, int *oldFrame, int *skin)
532{
533 /* check animations */
534 if ((*frame >= mod->alias.num_frames) || *frame < 0) {
535 Com_Printf("R_AliasModelState %s: no such frame %d (# %i)\n", mod->name, *frame, mod->alias.num_frames);
536 *frame = 0;
537 }
538 if ((*oldFrame >= mod->alias.num_frames) || *oldFrame < 0) {
539 Com_Printf("R_AliasModelState %s: no such oldframe %d (# %i)\n", mod->name, *oldFrame, mod->alias.num_frames);
540 *oldFrame = 0;
541 }
542
543 if (*mesh < 0 || *mesh >= mod->alias.num_meshes)
544 *mesh = 0;
545
546 if (!mod->alias.meshes)
547 return NULL__null;
548
549 /* use default skin - this is never null - but maybe the placeholder texture */
550 if (*skin < 0 || *skin >= mod->alias.meshes[*mesh].num_skins)
551 *skin = 0;
552
553 if (!mod->alias.meshes[*mesh].num_skins)
554 Com_Error(ERR_DROP1, "Model with no skins");
555
556 if (mod->alias.meshes[*mesh].skins[*skin].skin->texnum <= 0)
557 Com_Error(ERR_DROP1, "Texture is already freed and no longer uploaded, texnum is invalid for model %s",
558 mod->name);
559
560 return mod->alias.meshes[*mesh].skins[*skin].skin;
561}
562
563/**
564 * @brief Converts the model data into the opengl arrays
565 * @param mod The model to convert
566 * @param mesh The particular mesh of the model to convert
567 * @param backlerp The linear back interpolation when loading the data
568 * @param framenum The frame number of the mesh to load (if animated)
569 * @param oldframenum The old frame number (used to interpolate)
570 * @param prerender If this is @c true, all data is filled to the arrays. If @c false, then
571 * e.g. the normals are only filled to the arrays if the lighting is activated.
572 *
573 * @note If GLSL programs are enabled, the actual interpolation will be done on the GPU, but
574 * this function is still needed to fill the GL arrays for the keyframes
575 */
576void R_FillArrayData (mAliasModel_t* mod, mAliasMesh_t *mesh, float backlerp, int framenum, int oldframenum, bool prerender)
577{
578 const mAliasFrame_t *frame, *oldframe;
579 vec3_t move;
580 const float frontlerp = 1.0 - backlerp;
581 vec3_t r_mesh_verts[MAX_ALIAS_VERTS8192];
582 vec_t *texcoord_array, *vertex_array_3d;
583
584 frame = mod->frames + framenum;
585 oldframe = mod->frames + oldframenum;
586
587 /* try to do keyframe-interpolation on the GPU if possible*/
588 if (r_state.lighting_enabled) {
589 /* we only need to change the array data if we've switched to a new keyframe */
590 if (mod->curFrame != framenum) {
591 /* if we're rendering frames in order, the "next" keyframe from the previous
592 * time through will be our "previous" keyframe now, so we can swap pointers
593 * instead of generating it again from scratch */
594 if (mod->curFrame == oldframenum) {
595 vec_t *tmp1 = mesh->verts;
596 vec_t *tmp2 = mesh->normals;
597 vec_t *tmp3 = mesh->tangents;
598
599 mesh->verts = mesh->next_verts;
600 mesh->next_verts = tmp1;
601
602 mesh->normals = mesh->next_normals;
603 mesh->next_normals = tmp2;
604
605 mesh->tangents = mesh->next_tangents;
606 mesh->next_tangents = tmp3;
607
608 /* if we're alternating between two keyframes, we don't need to generate
609 * anything; otherwise, generate the "next" keyframe*/
610 if (mod->oldFrame != framenum)
611 R_ModCalcNormalsAndTangents(mesh, framenum, frame->translate, false);
612 } else {
613 /* if we're starting a new animation or otherwise not rendering keyframes
614 * in order, we need to fill the arrays for both keyframes */
615 R_ModCalcNormalsAndTangents(mesh, oldframenum, oldframe->translate, true);
616 R_ModCalcNormalsAndTangents(mesh, framenum, frame->translate, false);
617 }
618 /* keep track of which keyframes are currently stored in our arrays */
619 mod->oldFrame = oldframenum;
620 mod->curFrame = framenum;
621 }
622 } else { /* otherwise, we have to do it on the CPU */
623 const mAliasVertex_t *v, *ov;
624 int i;
625 assert(mesh->num_verts < lengthof(r_mesh_verts))(__builtin_expect(!(mesh->num_verts < (sizeof(r_mesh_verts
) / sizeof(*(r_mesh_verts)))), 0) ? __assert_rtn(__func__, "src/client/renderer/r_model_alias.cpp"
, 625, "mesh->num_verts < lengthof(r_mesh_verts)") : (void
)0)
;
626 v = &mesh->vertexes[framenum * mesh->num_verts];
627 ov = &mesh->vertexes[oldframenum * mesh->num_verts];
628
629 if (prerender)
630 R_ModCalcNormalsAndTangents(mesh, 0, oldframe->translate, true);
631
632 for (i = 0; i < 3; i++)
633 move[i] = backlerp * oldframe->translate[i] + frontlerp * frame->translate[i];
634
635 for (i = 0; i < mesh->num_verts; i++, v++, ov++) { /* lerp the verts */
636 VectorSet(r_mesh_verts[i],((r_mesh_verts[i])[0]=(move[0] + ov->point[0] * backlerp +
v->point[0] * frontlerp), (r_mesh_verts[i])[1]=(move[1] +
ov->point[1] * backlerp + v->point[1] * frontlerp), (r_mesh_verts
[i])[2]=(move[2] + ov->point[2] * backlerp + v->point[2
] * frontlerp))
637 move[0] + ov->point[0] * backlerp + v->point[0] * frontlerp,((r_mesh_verts[i])[0]=(move[0] + ov->point[0] * backlerp +
v->point[0] * frontlerp), (r_mesh_verts[i])[1]=(move[1] +
ov->point[1] * backlerp + v->point[1] * frontlerp), (r_mesh_verts
[i])[2]=(move[2] + ov->point[2] * backlerp + v->point[2
] * frontlerp))
638 move[1] + ov->point[1] * backlerp + v->point[1] * frontlerp,((r_mesh_verts[i])[0]=(move[0] + ov->point[0] * backlerp +
v->point[0] * frontlerp), (r_mesh_verts[i])[1]=(move[1] +
ov->point[1] * backlerp + v->point[1] * frontlerp), (r_mesh_verts
[i])[2]=(move[2] + ov->point[2] * backlerp + v->point[2
] * frontlerp))
639 move[2] + ov->point[2] * backlerp + v->point[2] * frontlerp)((r_mesh_verts[i])[0]=(move[0] + ov->point[0] * backlerp +
v->point[0] * frontlerp), (r_mesh_verts[i])[1]=(move[1] +
ov->point[1] * backlerp + v->point[1] * frontlerp), (r_mesh_verts
[i])[2]=(move[2] + ov->point[2] * backlerp + v->point[2
] * frontlerp))
;
640 }
641
642 R_ReallocateStateArrays(mesh->num_tris * 3);
643 R_ReallocateTexunitArray(&texunit_diffuser_state.texunits[0], mesh->num_tris * 3);
644 texcoord_array = texunit_diffuser_state.texunits[0].texcoord_array;
645 vertex_array_3d = r_state.vertex_array_3d;
646
647 /** @todo damn slow - optimize this */
648 for (i = 0; i < mesh->num_tris; i++) { /* draw the tris */
649 int j;
650 for (j = 0; j < 3; j++) {
651 const int arrayIndex = 3 * i + j;
652 const int meshIndex = mesh->indexes[arrayIndex];
653 Vector2Copy(mesh->stcoords[meshIndex], texcoord_array)((texcoord_array)[0]=(mesh->stcoords[meshIndex])[0],(texcoord_array
)[1]=(mesh->stcoords[meshIndex])[1])
;
654 VectorCopy(r_mesh_verts[meshIndex], vertex_array_3d)((vertex_array_3d)[0]=(r_mesh_verts[meshIndex])[0],(vertex_array_3d
)[1]=(r_mesh_verts[meshIndex])[1],(vertex_array_3d)[2]=(r_mesh_verts
[meshIndex])[2])
;
655
656 texcoord_array += 2;
657 vertex_array_3d += 3;
658 }
659 }
660 }
661}
662
663/**
664 * @brief Allocates data arrays for animated models. Only called once at loading time.
665 */
666void R_ModLoadArrayData (mAliasModel_t *mod, mAliasMesh_t *mesh, bool loadNormals)
667{
668 const int v = mesh->num_tris * 3 * 3;
669 const int t = mesh->num_tris * 3 * 4;
670 const int st = mesh->num_tris * 3 * 2;
671
672 assert(mesh->verts == NULL)(__builtin_expect(!(mesh->verts == __null), 0) ? __assert_rtn
(__func__, "src/client/renderer/r_model_alias.cpp", 672, "mesh->verts == NULL"
) : (void)0)
;
673 assert(mesh->texcoords == NULL)(__builtin_expect(!(mesh->texcoords == __null), 0) ? __assert_rtn
(__func__, "src/client/renderer/r_model_alias.cpp", 673, "mesh->texcoords == NULL"
) : (void)0)
;
674 assert(mesh->normals == NULL)(__builtin_expect(!(mesh->normals == __null), 0) ? __assert_rtn
(__func__, "src/client/renderer/r_model_alias.cpp", 674, "mesh->normals == NULL"
) : (void)0)
;
675 assert(mesh->tangents == NULL)(__builtin_expect(!(mesh->tangents == __null), 0) ? __assert_rtn
(__func__, "src/client/renderer/r_model_alias.cpp", 675, "mesh->tangents == NULL"
) : (void)0)
;
676 assert(mesh->next_verts == NULL)(__builtin_expect(!(mesh->next_verts == __null), 0) ? __assert_rtn
(__func__, "src/client/renderer/r_model_alias.cpp", 676, "mesh->next_verts == NULL"
) : (void)0)
;
677 assert(mesh->next_normals == NULL)(__builtin_expect(!(mesh->next_normals == __null), 0) ? __assert_rtn
(__func__, "src/client/renderer/r_model_alias.cpp", 677, "mesh->next_normals == NULL"
) : (void)0)
;
678 assert(mesh->next_tangents == NULL)(__builtin_expect(!(mesh->next_tangents == __null), 0) ? __assert_rtn
(__func__, "src/client/renderer/r_model_alias.cpp", 678, "mesh->next_tangents == NULL"
) : (void)0)
;
679
680 mesh->verts = Mem_PoolAllocTypeN(float, v, vid_modelPool)static_cast<float*>(_Mem_Alloc((sizeof(float) * (v)),true
,((vid_modelPool)),(0),"src/client/renderer/r_model_alias.cpp"
,680))
;
681 mesh->normals = Mem_PoolAllocTypeN(float, v, vid_modelPool)static_cast<float*>(_Mem_Alloc((sizeof(float) * (v)),true
,((vid_modelPool)),(0),"src/client/renderer/r_model_alias.cpp"
,681))
;
682 mesh->tangents = Mem_PoolAllocTypeN(float, t, vid_modelPool)static_cast<float*>(_Mem_Alloc((sizeof(float) * (t)),true
,((vid_modelPool)),(0),"src/client/renderer/r_model_alias.cpp"
,682))
;
683 mesh->texcoords = Mem_PoolAllocTypeN(float, st, vid_modelPool)static_cast<float*>(_Mem_Alloc((sizeof(float) * (st)),true
,((vid_modelPool)),(0),"src/client/renderer/r_model_alias.cpp"
,683))
;
684 if (mod->num_frames == 1) {
685 R_FillArrayData(mod, mesh, 0.0, 0, 0, loadNormals);
686 } else {
687 mesh->next_verts = Mem_PoolAllocTypeN(float, v, vid_modelPool)static_cast<float*>(_Mem_Alloc((sizeof(float) * (v)),true
,((vid_modelPool)),(0),"src/client/renderer/r_model_alias.cpp"
,687))
;
688 mesh->next_normals = Mem_PoolAllocTypeN(float, v, vid_modelPool)static_cast<float*>(_Mem_Alloc((sizeof(float) * (v)),true
,((vid_modelPool)),(0),"src/client/renderer/r_model_alias.cpp"
,688))
;
689 mesh->next_tangents = Mem_PoolAllocTypeN(float, t, vid_modelPool)static_cast<float*>(_Mem_Alloc((sizeof(float) * (t)),true
,((vid_modelPool)),(0),"src/client/renderer/r_model_alias.cpp"
,689))
;
690
691 mod->curFrame = -1;
692 mod->oldFrame = -1;
693 }
694}