1 /*
2 ===========================================================================
3 Copyright (C) 2000 - 2013, Raven Software, Inc.
4 Copyright (C) 2001 - 2013, Activision, Inc.
5 Copyright (C) 2013 - 2015, OpenJK contributors
6
7 This file is part of the OpenJK source code.
8
9 OpenJK is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, see <http://www.gnu.org/licenses/>.
20 ===========================================================================
21 */
22
23 #include "client/client.h" //FIXME!! EVIL - just include the definitions needed
24 #include "tr_local.h"
25 #include "qcommon/matcomp.h"
26 #include "qcommon/qcommon.h"
27 #include "ghoul2/G2.h"
28 #include "ghoul2/g2_local.h"
29 #ifdef _G2_GORE
30 #include "ghoul2/G2_gore.h"
31 #endif
32
33 #include "qcommon/disablewarnings.h"
34
35 #define LL(x) x=LittleLong(x)
36 #define LS(x) x=LittleShort(x)
37 #define LF(x) x=LittleFloat(x)
38
39 #ifdef G2_PERFORMANCE_ANALYSIS
40 #include "qcommon/timing.h"
41
42 timing_c G2PerformanceTimer_RenderSurfaces;
43 timing_c G2PerformanceTimer_R_AddGHOULSurfaces;
44 timing_c G2PerformanceTimer_G2_TransformGhoulBones;
45 timing_c G2PerformanceTimer_G2_ProcessGeneratedSurfaceBolts;
46 timing_c G2PerformanceTimer_ProcessModelBoltSurfaces;
47 timing_c G2PerformanceTimer_G2_ConstructGhoulSkeleton;
48 timing_c G2PerformanceTimer_RB_SurfaceGhoul;
49 timing_c G2PerformanceTimer_G2_SetupModelPointers;
50 timing_c G2PerformanceTimer_PreciseFrame;
51
52 int G2PerformanceCounter_G2_TransformGhoulBones = 0;
53
54 int G2Time_RenderSurfaces = 0;
55 int G2Time_R_AddGHOULSurfaces = 0;
56 int G2Time_G2_TransformGhoulBones = 0;
57 int G2Time_G2_ProcessGeneratedSurfaceBolts = 0;
58 int G2Time_ProcessModelBoltSurfaces = 0;
59 int G2Time_G2_ConstructGhoulSkeleton = 0;
60 int G2Time_RB_SurfaceGhoul = 0;
61 int G2Time_G2_SetupModelPointers = 0;
62 int G2Time_PreciseFrame = 0;
63
G2Time_ResetTimers(void)64 void G2Time_ResetTimers(void)
65 {
66 G2Time_RenderSurfaces = 0;
67 G2Time_R_AddGHOULSurfaces = 0;
68 G2Time_G2_TransformGhoulBones = 0;
69 G2Time_G2_ProcessGeneratedSurfaceBolts = 0;
70 G2Time_ProcessModelBoltSurfaces = 0;
71 G2Time_G2_ConstructGhoulSkeleton = 0;
72 G2Time_RB_SurfaceGhoul = 0;
73 G2Time_G2_SetupModelPointers = 0;
74 G2Time_PreciseFrame = 0;
75 G2PerformanceCounter_G2_TransformGhoulBones = 0;
76 }
77
G2Time_ReportTimers(void)78 void G2Time_ReportTimers(void)
79 {
80 ri.Printf( PRINT_ALL, "\n---------------------------------\nRenderSurfaces: %i\nR_AddGhoulSurfaces: %i\nG2_TransformGhoulBones: %i\nG2_ProcessGeneratedSurfaceBolts: %i\nProcessModelBoltSurfaces: %i\nG2_ConstructGhoulSkeleton: %i\nRB_SurfaceGhoul: %i\nG2_SetupModelPointers: %i\n\nPrecise frame time: %i\nTransformGhoulBones calls: %i\n---------------------------------\n\n",
81 G2Time_RenderSurfaces,
82 G2Time_R_AddGHOULSurfaces,
83 G2Time_G2_TransformGhoulBones,
84 G2Time_G2_ProcessGeneratedSurfaceBolts,
85 G2Time_ProcessModelBoltSurfaces,
86 G2Time_G2_ConstructGhoulSkeleton,
87 G2Time_RB_SurfaceGhoul,
88 G2Time_G2_SetupModelPointers,
89 G2Time_PreciseFrame,
90 G2PerformanceCounter_G2_TransformGhoulBones
91 );
92 }
93 #endif
94
95 //rww - RAGDOLL_BEGIN
96 #ifdef __linux__
97 #include <math.h>
98 #else
99 #include <float.h>
100 #endif
101
102 //rww - RAGDOLL_END
103
104 bool HackadelicOnClient=false; // means this is a render traversal
105
106 qboolean G2_SetupModelPointers(CGhoul2Info *ghlInfo);
107 qboolean G2_SetupModelPointers(CGhoul2Info_v &ghoul2);
108
109 extern cvar_t *r_Ghoul2AnimSmooth;
110 extern cvar_t *r_Ghoul2UnSqashAfterSmooth;
111
112 #if 0
113 static inline int G2_Find_Bone_ByNum(const model_t *mod, boneInfo_v &blist, const int boneNum)
114 {
115 size_t i = 0;
116
117 while (i < blist.size())
118 {
119 if (blist[i].boneNumber == boneNum)
120 {
121 return i;
122 }
123 i++;
124 }
125
126 return -1;
127 }
128 #endif
129
130 const static mdxaBone_t identityMatrix =
131 {
132 {
133 { 0.0f, -1.0f, 0.0f, 0.0f },
134 { 1.0f, 0.0f, 0.0f, 0.0f },
135 { 0.0f, 0.0f, 1.0f, 0.0f }
136 }
137 };
138
139 // I hate doing this, but this is the simplest way to get this into the routines it needs to be
140 mdxaBone_t worldMatrix;
141 mdxaBone_t worldMatrixInv;
142 #ifdef _G2_GORE
143 qhandle_t goreShader=-1;
144 #endif
145
146 class CConstructBoneList
147 {
148 public:
149 int surfaceNum;
150 int *boneUsedList;
151 surfaceInfo_v &rootSList;
152 model_t *currentModel;
153 boneInfo_v &boneList;
154
CConstructBoneList(int initsurfaceNum,int * initboneUsedList,surfaceInfo_v & initrootSList,model_t * initcurrentModel,boneInfo_v & initboneList)155 CConstructBoneList(
156 int initsurfaceNum,
157 int *initboneUsedList,
158 surfaceInfo_v &initrootSList,
159 model_t *initcurrentModel,
160 boneInfo_v &initboneList):
161
162 surfaceNum(initsurfaceNum),
163 boneUsedList(initboneUsedList),
164 rootSList(initrootSList),
165 currentModel(initcurrentModel),
166 boneList(initboneList) { }
167
168 };
169
170 class CTransformBone
171 {
172 public:
173 int touch; // for minimal recalculation
174 //rww - RAGDOLL_BEGIN
175 int touchRender;
176 //rww - RAGDOLL_END
177 mdxaBone_t boneMatrix; //final matrix
178 int parent; // only set once
179
CTransformBone()180 CTransformBone()
181 {
182 touch=0;
183 //rww - RAGDOLL_BEGIN
184 touchRender = 0;
185 //rww - RAGDOLL_END
186 }
187
188 };
189
190 struct SBoneCalc
191 {
192 int newFrame;
193 int currentFrame;
194 float backlerp;
195 float blendFrame;
196 int blendOldFrame;
197 bool blendMode;
198 float blendLerp;
199 };
200
201 class CBoneCache;
202 void G2_TransformBone(int index,CBoneCache &CB);
203
204 class CBoneCache
205 {
SetRenderMatrix(CTransformBone * bone)206 void SetRenderMatrix(CTransformBone *bone) {
207 }
208
EvalLow(int index)209 void EvalLow(int index)
210 {
211 assert(index>=0&&index<(int)mBones.size());
212 if (mFinalBones[index].touch!=mCurrentTouch)
213 {
214 // need to evaluate the bone
215 assert((mFinalBones[index].parent>=0&&mFinalBones[index].parent<(int)mFinalBones.size())||(index==0&&mFinalBones[index].parent==-1));
216 if (mFinalBones[index].parent>=0)
217 {
218 EvalLow(mFinalBones[index].parent); // make sure parent is evaluated
219 SBoneCalc &par=mBones[mFinalBones[index].parent];
220 mBones[index].newFrame=par.newFrame;
221 mBones[index].currentFrame=par.currentFrame;
222 mBones[index].backlerp=par.backlerp;
223 mBones[index].blendFrame=par.blendFrame;
224 mBones[index].blendOldFrame=par.blendOldFrame;
225 mBones[index].blendMode=par.blendMode;
226 mBones[index].blendLerp=par.blendLerp;
227 }
228 G2_TransformBone(index,*this);
229 mFinalBones[index].touch=mCurrentTouch;
230 }
231 }
232 //rww - RAGDOLL_BEGIN
SmoothLow(int index)233 void SmoothLow(int index)
234 {
235 if (mSmoothBones[index].touch==mLastTouch)
236 {
237 int i;
238 float *oldM=&mSmoothBones[index].boneMatrix.matrix[0][0];
239 float *newM=&mFinalBones[index].boneMatrix.matrix[0][0];
240 #if 0 //this is just too slow. I need a better way.
241 static float smoothFactor;
242
243 smoothFactor = mSmoothFactor;
244
245 //Special rag smoothing -rww
246 if (smoothFactor < 0)
247 { //I need a faster way to do this but I do not want to store more in the bonecache
248 static int blistIndex;
249 assert(mod);
250 assert(rootBoneList);
251 blistIndex = G2_Find_Bone_ByNum(mod, *rootBoneList, index);
252
253 assert(blistIndex != -1);
254
255 boneInfo_t &bone = (*rootBoneList)[blistIndex];
256
257 if (bone.flags & BONE_ANGLES_RAGDOLL)
258 {
259 if ((bone.RagFlags & (0x00008)) || //pelvis
260 (bone.RagFlags & (0x00004))) //model_root
261 { //pelvis and root do not smooth much
262 smoothFactor = 0.2f;
263 }
264 else if (bone.solidCount > 4)
265 { //if stuck in solid a lot then snap out quickly
266 smoothFactor = 0.1f;
267 }
268 else
269 { //otherwise smooth a bunch
270 smoothFactor = 0.8f;
271 }
272 }
273 else
274 { //not a rag bone
275 smoothFactor = 0.3f;
276 }
277 }
278 #endif
279
280 for (i=0;i<12;i++,oldM++,newM++)
281 {
282 *oldM=mSmoothFactor*(*oldM-*newM)+*newM;
283 }
284 }
285 else
286 {
287 memcpy(&mSmoothBones[index].boneMatrix,&mFinalBones[index].boneMatrix,sizeof(mdxaBone_t));
288 }
289 mdxaSkelOffsets_t *offsets = (mdxaSkelOffsets_t *)((byte *)header + sizeof(mdxaHeader_t));
290 mdxaSkel_t *skel = (mdxaSkel_t *)((byte *)header + sizeof(mdxaHeader_t) + offsets->offsets[index]);
291 mdxaBone_t tempMatrix;
292 Multiply_3x4Matrix(&tempMatrix,&mSmoothBones[index].boneMatrix, &skel->BasePoseMat);
293 float maxl;
294 maxl=VectorLength(&skel->BasePoseMat.matrix[0][0]);
295 VectorNormalize(&tempMatrix.matrix[0][0]);
296 VectorNormalize(&tempMatrix.matrix[1][0]);
297 VectorNormalize(&tempMatrix.matrix[2][0]);
298
299 VectorScale(&tempMatrix.matrix[0][0],maxl,&tempMatrix.matrix[0][0]);
300 VectorScale(&tempMatrix.matrix[1][0],maxl,&tempMatrix.matrix[1][0]);
301 VectorScale(&tempMatrix.matrix[2][0],maxl,&tempMatrix.matrix[2][0]);
302 Multiply_3x4Matrix(&mSmoothBones[index].boneMatrix,&tempMatrix,&skel->BasePoseMatInv);
303 mSmoothBones[index].touch=mCurrentTouch;
304 #ifdef _DEBUG
305 for ( int i = 0; i < 3; i++ )
306 {
307 for ( int j = 0; j < 4; j++ )
308 {
309 assert( !Q_isnan(mSmoothBones[index].boneMatrix.matrix[i][j]));
310 }
311 }
312 #endif// _DEBUG
313 }
314 //rww - RAGDOLL_END
315 public:
316 int frameSize;
317 const mdxaHeader_t *header;
318 const model_t *mod;
319
320 // these are split for better cpu cache behavior
321 std::vector<SBoneCalc> mBones;
322 std::vector<CTransformBone> mFinalBones;
323
324 std::vector<CTransformBone> mSmoothBones; // for render smoothing
325 //vector<mdxaSkel_t *> mSkels;
326
327 boneInfo_v *rootBoneList;
328 mdxaBone_t rootMatrix;
329 int incomingTime;
330
331 int mCurrentTouch;
332 //rww - RAGDOLL_BEGIN
333 int mCurrentTouchRender;
334 int mLastTouch;
335 int mLastLastTouch;
336 //rww - RAGDOLL_END
337
338 // for render smoothing
339 bool mSmoothingActive;
340 bool mUnsquash;
341 float mSmoothFactor;
342
CBoneCache(const model_t * amod,const mdxaHeader_t * aheader)343 CBoneCache(const model_t *amod,const mdxaHeader_t *aheader) :
344 header(aheader),
345 mod(amod)
346 {
347 assert(amod);
348 assert(aheader);
349 mSmoothingActive=false;
350 mUnsquash=false;
351 mSmoothFactor=0.0f;
352
353 int numBones=header->numBones;
354 mBones.resize(numBones);
355 mFinalBones.resize(numBones);
356 mSmoothBones.resize(numBones);
357 // mSkels.resize(numBones);
358 //rww - removed mSkels
359 mdxaSkelOffsets_t *offsets;
360 mdxaSkel_t *skel;
361 offsets = (mdxaSkelOffsets_t *)((byte *)header + sizeof(mdxaHeader_t));
362
363 int i;
364 for (i=0;i<numBones;i++)
365 {
366 skel = (mdxaSkel_t *)((byte *)header + sizeof(mdxaHeader_t) + offsets->offsets[i]);
367 //mSkels[i]=skel;
368 //ditto
369 mFinalBones[i].parent=skel->parent;
370 }
371 mCurrentTouch=3;
372 //rww - RAGDOLL_BEGIN
373 mLastTouch=2;
374 mLastLastTouch=1;
375 //rww - RAGDOLL_END
376 }
377
Root()378 SBoneCalc &Root()
379 {
380 assert(mBones.size());
381 return mBones[0];
382 }
EvalUnsmooth(int index)383 const mdxaBone_t &EvalUnsmooth(int index)
384 {
385 EvalLow(index);
386 if (mSmoothingActive&&mSmoothBones[index].touch)
387 {
388 return mSmoothBones[index].boneMatrix;
389 }
390 return mFinalBones[index].boneMatrix;
391 }
Eval(int index)392 const mdxaBone_t &Eval(int index)
393 {
394 /*
395 bool wasEval=EvalLow(index);
396 if (mSmoothingActive)
397 {
398 if (mSmoothBones[index].touch!=incomingTime||wasEval)
399 {
400 float dif=float(incomingTime)-float(mSmoothBones[index].touch);
401 if (mSmoothBones[index].touch&&dif<300.0f)
402 {
403
404 if (dif<16.0f) // 60 fps
405 {
406 dif=16.0f;
407 }
408 if (dif>100.0f) // 10 fps
409 {
410 dif=100.0f;
411 }
412 float f=1.0f-pow(1.0f-mSmoothFactor,16.0f/dif);
413
414 int i;
415 float *oldM=&mSmoothBones[index].boneMatrix.matrix[0][0];
416 float *newM=&mFinalBones[index].boneMatrix.matrix[0][0];
417 for (i=0;i<12;i++,oldM++,newM++)
418 {
419 *oldM=f*(*oldM-*newM)+*newM;
420 }
421 if (mUnsquash)
422 {
423 mdxaBone_t tempMatrix;
424 Multiply_3x4Matrix(&tempMatrix,&mSmoothBones[index].boneMatrix, &mSkels[index]->BasePoseMat);
425 float maxl;
426 maxl=VectorLength(&mSkels[index]->BasePoseMat.matrix[0][0]);
427 VectorNormalize(&tempMatrix.matrix[0][0]);
428 VectorNormalize(&tempMatrix.matrix[1][0]);
429 VectorNormalize(&tempMatrix.matrix[2][0]);
430
431 VectorScale(&tempMatrix.matrix[0][0],maxl,&tempMatrix.matrix[0][0]);
432 VectorScale(&tempMatrix.matrix[1][0],maxl,&tempMatrix.matrix[1][0]);
433 VectorScale(&tempMatrix.matrix[2][0],maxl,&tempMatrix.matrix[2][0]);
434 Multiply_3x4Matrix(&mSmoothBones[index].boneMatrix,&tempMatrix,&mSkels[index]->BasePoseMatInv);
435 }
436 }
437 else
438 {
439 memcpy(&mSmoothBones[index].boneMatrix,&mFinalBones[index].boneMatrix,sizeof(mdxaBone_t));
440 }
441 mSmoothBones[index].touch=incomingTime;
442 }
443 return mSmoothBones[index].boneMatrix;
444 }
445 return mFinalBones[index].boneMatrix;
446 */
447
448 //Hey, this is what sof2 does. Let's try it out.
449 assert(index>=0&&index<(int)mBones.size());
450 if (mFinalBones[index].touch!=mCurrentTouch)
451 {
452 EvalLow(index);
453 }
454 return mFinalBones[index].boneMatrix;
455 }
456 //rww - RAGDOLL_BEGIN
EvalRender(int index)457 const inline mdxaBone_t &EvalRender(int index)
458 {
459 assert(index>=0&&index<(int)mBones.size());
460 if (mFinalBones[index].touch!=mCurrentTouch)
461 {
462 mFinalBones[index].touchRender=mCurrentTouchRender;
463 EvalLow(index);
464 }
465 if (mSmoothingActive)
466 {
467 if (mSmoothBones[index].touch!=mCurrentTouch)
468 {
469 SmoothLow(index);
470 }
471 return mSmoothBones[index].boneMatrix;
472 }
473 return mFinalBones[index].boneMatrix;
474 }
475 //rww - RAGDOLL_END
476 //rww - RAGDOLL_BEGIN
WasRendered(int index)477 bool WasRendered(int index)
478 {
479 assert(index>=0&&index<(int)mBones.size());
480 return mFinalBones[index].touchRender==mCurrentTouchRender;
481 }
GetParent(int index)482 int GetParent(int index)
483 {
484 if (index==0)
485 {
486 return -1;
487 }
488 assert(index>=0&&index<(int)mBones.size());
489 return mFinalBones[index].parent;
490 }
491 //rww - RAGDOLL_END
492 };
493
RemoveBoneCache(CBoneCache * boneCache)494 void RemoveBoneCache(CBoneCache *boneCache)
495 {
496 #ifdef _FULL_G2_LEAK_CHECKING
497 g_Ghoul2Allocations -= sizeof(*boneCache);
498 #endif
499
500 delete boneCache;
501 }
502
503 #ifdef _G2_LISTEN_SERVER_OPT
CopyBoneCache(CBoneCache * to,CBoneCache * from)504 void CopyBoneCache(CBoneCache *to, CBoneCache *from)
505 {
506 memcpy(to, from, sizeof(CBoneCache));
507 }
508 #endif
509
EvalBoneCache(int index,CBoneCache * boneCache)510 const mdxaBone_t &EvalBoneCache(int index,CBoneCache *boneCache)
511 {
512 assert(boneCache);
513 return boneCache->Eval(index);
514 }
515
516 //rww - RAGDOLL_BEGIN
G2_GetModA(CGhoul2Info & ghoul2)517 const mdxaHeader_t *G2_GetModA(CGhoul2Info &ghoul2)
518 {
519 if (!ghoul2.mBoneCache)
520 {
521 return 0;
522 }
523
524 CBoneCache &boneCache=*ghoul2.mBoneCache;
525 return boneCache.header;
526 }
527
G2_GetBoneDependents(CGhoul2Info & ghoul2,int boneNum,int * tempDependents,int maxDep)528 int G2_GetBoneDependents(CGhoul2Info &ghoul2,int boneNum,int *tempDependents,int maxDep)
529 {
530 // fixme, these should be precomputed
531 if (!ghoul2.mBoneCache||!maxDep)
532 {
533 return 0;
534 }
535
536 CBoneCache &boneCache=*ghoul2.mBoneCache;
537 mdxaSkel_t *skel;
538 mdxaSkelOffsets_t *offsets;
539 offsets = (mdxaSkelOffsets_t *)((byte *)boneCache.header + sizeof(mdxaHeader_t));
540 skel = (mdxaSkel_t *)((byte *)boneCache.header + sizeof(mdxaHeader_t) + offsets->offsets[boneNum]);
541 int i;
542 int ret=0;
543 for (i=0;i<skel->numChildren;i++)
544 {
545 if (!maxDep)
546 {
547 return i; // number added
548 }
549 *tempDependents=skel->children[i];
550 assert(*tempDependents>0&&*tempDependents<boneCache.header->numBones);
551 maxDep--;
552 tempDependents++;
553 ret++;
554 }
555 for (i=0;i<skel->numChildren;i++)
556 {
557 int num=G2_GetBoneDependents(ghoul2,skel->children[i],tempDependents,maxDep);
558 tempDependents+=num;
559 ret+=num;
560 maxDep-=num;
561 assert(maxDep>=0);
562 if (!maxDep)
563 {
564 break;
565 }
566 }
567 return ret;
568 }
569
G2_WasBoneRendered(CGhoul2Info & ghoul2,int boneNum)570 bool G2_WasBoneRendered(CGhoul2Info &ghoul2,int boneNum)
571 {
572 if (!ghoul2.mBoneCache)
573 {
574 return false;
575 }
576 CBoneCache &boneCache=*ghoul2.mBoneCache;
577
578 return boneCache.WasRendered(boneNum);
579 }
580
G2_GetBoneBasepose(CGhoul2Info & ghoul2,int boneNum,mdxaBone_t * & retBasepose,mdxaBone_t * & retBaseposeInv)581 void G2_GetBoneBasepose(CGhoul2Info &ghoul2,int boneNum,mdxaBone_t *&retBasepose,mdxaBone_t *&retBaseposeInv)
582 {
583 if (!ghoul2.mBoneCache)
584 {
585 // yikes
586 retBasepose=const_cast<mdxaBone_t *>(&identityMatrix);
587 retBaseposeInv=const_cast<mdxaBone_t *>(&identityMatrix);
588 return;
589 }
590 assert(ghoul2.mBoneCache);
591 CBoneCache &boneCache=*ghoul2.mBoneCache;
592 assert(boneCache.mod);
593 assert(boneNum>=0&&boneNum<boneCache.header->numBones);
594
595 mdxaSkel_t *skel;
596 mdxaSkelOffsets_t *offsets;
597 offsets = (mdxaSkelOffsets_t *)((byte *)boneCache.header + sizeof(mdxaHeader_t));
598 skel = (mdxaSkel_t *)((byte *)boneCache.header + sizeof(mdxaHeader_t) + offsets->offsets[boneNum]);
599 retBasepose=&skel->BasePoseMat;
600 retBaseposeInv=&skel->BasePoseMatInv;
601 }
602
G2_GetBoneNameFromSkel(CGhoul2Info & ghoul2,int boneNum)603 char *G2_GetBoneNameFromSkel(CGhoul2Info &ghoul2, int boneNum)
604 {
605 if (!ghoul2.mBoneCache)
606 {
607 return NULL;
608 }
609 CBoneCache &boneCache=*ghoul2.mBoneCache;
610 assert(boneCache.mod);
611 assert(boneNum>=0&&boneNum<boneCache.header->numBones);
612
613 mdxaSkel_t *skel;
614 mdxaSkelOffsets_t *offsets;
615 offsets = (mdxaSkelOffsets_t *)((byte *)boneCache.header + sizeof(mdxaHeader_t));
616 skel = (mdxaSkel_t *)((byte *)boneCache.header + sizeof(mdxaHeader_t) + offsets->offsets[boneNum]);
617
618 return skel->name;
619 }
620
G2_RagGetBoneBasePoseMatrixLow(CGhoul2Info & ghoul2,int boneNum,mdxaBone_t & boneMatrix,mdxaBone_t & retMatrix,vec3_t scale)621 void G2_RagGetBoneBasePoseMatrixLow(CGhoul2Info &ghoul2, int boneNum, mdxaBone_t &boneMatrix, mdxaBone_t &retMatrix, vec3_t scale)
622 {
623 assert(ghoul2.mBoneCache);
624 CBoneCache &boneCache=*ghoul2.mBoneCache;
625 assert(boneCache.mod);
626 assert(boneNum>=0&&boneNum<boneCache.header->numBones);
627
628 mdxaSkel_t *skel;
629 mdxaSkelOffsets_t *offsets;
630 offsets = (mdxaSkelOffsets_t *)((byte *)boneCache.header + sizeof(mdxaHeader_t));
631 skel = (mdxaSkel_t *)((byte *)boneCache.header + sizeof(mdxaHeader_t) + offsets->offsets[boneNum]);
632 Multiply_3x4Matrix(&retMatrix, &boneMatrix, &skel->BasePoseMat);
633
634 if (scale[0])
635 {
636 retMatrix.matrix[0][3] *= scale[0];
637 }
638 if (scale[1])
639 {
640 retMatrix.matrix[1][3] *= scale[1];
641 }
642 if (scale[2])
643 {
644 retMatrix.matrix[2][3] *= scale[2];
645 }
646
647 VectorNormalize((float*)&retMatrix.matrix[0]);
648 VectorNormalize((float*)&retMatrix.matrix[1]);
649 VectorNormalize((float*)&retMatrix.matrix[2]);
650 }
651
G2_GetBoneMatrixLow(CGhoul2Info & ghoul2,int boneNum,const vec3_t scale,mdxaBone_t & retMatrix,mdxaBone_t * & retBasepose,mdxaBone_t * & retBaseposeInv)652 void G2_GetBoneMatrixLow(CGhoul2Info &ghoul2,int boneNum,const vec3_t scale,mdxaBone_t &retMatrix,mdxaBone_t *&retBasepose,mdxaBone_t *&retBaseposeInv)
653 {
654 if (!ghoul2.mBoneCache)
655 {
656 retMatrix=identityMatrix;
657 // yikes
658 retBasepose=const_cast<mdxaBone_t *>(&identityMatrix);
659 retBaseposeInv=const_cast<mdxaBone_t *>(&identityMatrix);
660 return;
661 }
662 mdxaBone_t bolt;
663 assert(ghoul2.mBoneCache);
664 CBoneCache &boneCache=*ghoul2.mBoneCache;
665 assert(boneCache.mod);
666 assert(boneNum>=0&&boneNum<boneCache.header->numBones);
667
668 mdxaSkel_t *skel;
669 mdxaSkelOffsets_t *offsets;
670 offsets = (mdxaSkelOffsets_t *)((byte *)boneCache.header + sizeof(mdxaHeader_t));
671 skel = (mdxaSkel_t *)((byte *)boneCache.header + sizeof(mdxaHeader_t) + offsets->offsets[boneNum]);
672 Multiply_3x4Matrix(&bolt, (mdxaBone_t *)&boneCache.Eval(boneNum), &skel->BasePoseMat); // DEST FIRST ARG
673 retBasepose=&skel->BasePoseMat;
674 retBaseposeInv=&skel->BasePoseMatInv;
675
676 if (scale[0])
677 {
678 bolt.matrix[0][3] *= scale[0];
679 }
680 if (scale[1])
681 {
682 bolt.matrix[1][3] *= scale[1];
683 }
684 if (scale[2])
685 {
686 bolt.matrix[2][3] *= scale[2];
687 }
688 VectorNormalize((float*)&bolt.matrix[0]);
689 VectorNormalize((float*)&bolt.matrix[1]);
690 VectorNormalize((float*)&bolt.matrix[2]);
691
692 Multiply_3x4Matrix(&retMatrix,&worldMatrix, &bolt);
693
694 #ifdef _DEBUG
695 for ( int i = 0; i < 3; i++ )
696 {
697 for ( int j = 0; j < 4; j++ )
698 {
699 assert( !Q_isnan(retMatrix.matrix[i][j]));
700 }
701 }
702 #endif// _DEBUG
703 }
704
G2_GetParentBoneMatrixLow(CGhoul2Info & ghoul2,int boneNum,const vec3_t scale,mdxaBone_t & retMatrix,mdxaBone_t * & retBasepose,mdxaBone_t * & retBaseposeInv)705 int G2_GetParentBoneMatrixLow(CGhoul2Info &ghoul2,int boneNum,const vec3_t scale,mdxaBone_t &retMatrix,mdxaBone_t *&retBasepose,mdxaBone_t *&retBaseposeInv)
706 {
707 int parent=-1;
708 if (ghoul2.mBoneCache)
709 {
710 CBoneCache &boneCache=*ghoul2.mBoneCache;
711 assert(boneCache.mod);
712 assert(boneNum>=0&&boneNum<boneCache.header->numBones);
713 parent=boneCache.GetParent(boneNum);
714 if (parent<0||parent>=boneCache.header->numBones)
715 {
716 parent=-1;
717 retMatrix=identityMatrix;
718 // yikes
719 retBasepose=const_cast<mdxaBone_t *>(&identityMatrix);
720 retBaseposeInv=const_cast<mdxaBone_t *>(&identityMatrix);
721 }
722 else
723 {
724 G2_GetBoneMatrixLow(ghoul2,parent,scale,retMatrix,retBasepose,retBaseposeInv);
725 }
726 }
727 return parent;
728 }
729 //rww - RAGDOLL_END
730
731 class CRenderSurface
732 {
733 public:
734 int surfaceNum;
735 surfaceInfo_v &rootSList;
736 shader_t *cust_shader;
737 int fogNum;
738 qboolean personalModel;
739 CBoneCache *boneCache;
740 int renderfx;
741 skin_t *skin;
742 model_t *currentModel;
743 int lod;
744 boltInfo_v &boltList;
745 #ifdef _G2_GORE
746 shader_t *gore_shader;
747 CGoreSet *gore_set;
748 #endif
749
CRenderSurface(int initsurfaceNum,surfaceInfo_v & initrootSList,shader_t * initcust_shader,int initfogNum,qboolean initpersonalModel,CBoneCache * initboneCache,int initrenderfx,skin_t * initskin,model_t * initcurrentModel,int initlod,boltInfo_v & initboltList,shader_t * initgore_shader,CGoreSet * initgore_set)750 CRenderSurface(
751 int initsurfaceNum,
752 surfaceInfo_v &initrootSList,
753 shader_t *initcust_shader,
754 int initfogNum,
755 qboolean initpersonalModel,
756 CBoneCache *initboneCache,
757 int initrenderfx,
758 skin_t *initskin,
759 model_t *initcurrentModel,
760 int initlod,
761 #ifdef _G2_GORE
762 boltInfo_v &initboltList,
763 shader_t *initgore_shader,
764 CGoreSet *initgore_set):
765 #else
766 boltInfo_v &initboltList):
767 #endif
768
769 surfaceNum(initsurfaceNum),
770 rootSList(initrootSList),
771 cust_shader(initcust_shader),
772 fogNum(initfogNum),
773 personalModel(initpersonalModel),
774 boneCache(initboneCache),
775 renderfx(initrenderfx),
776 skin(initskin),
777 currentModel(initcurrentModel),
778 lod(initlod),
779 #ifdef _G2_GORE
780 boltList(initboltList),
781 gore_shader(initgore_shader),
782 gore_set(initgore_set)
783 #else
784 boltList(initboltList)
785 #endif
786 {}
787 };
788
789 #ifdef _G2_GORE
790 #define MAX_RENDER_SURFACES (2048)
791 static CRenderableSurface RSStorage[MAX_RENDER_SURFACES];
792 static unsigned int NextRS=0;
793
AllocRS()794 CRenderableSurface *AllocRS()
795 {
796 CRenderableSurface *ret=&RSStorage[NextRS];
797 ret->Init();
798 NextRS++;
799 NextRS%=MAX_RENDER_SURFACES;
800 return ret;
801 }
802 #endif
803
804 /*
805
806 All bones should be an identity orientation to display the mesh exactly
807 as it is specified.
808
809 For all other frames, the bones represent the transformation from the
810 orientation of the bone in the base frame to the orientation in this
811 frame.
812
813 */
814
815
816 /*
817 =============
818 R_ACullModel
819 =============
820 */
R_GCullModel(trRefEntity_t * ent)821 static int R_GCullModel( trRefEntity_t *ent ) {
822
823 // scale the radius if need be
824 float largestScale = ent->e.modelScale[0];
825
826 if (ent->e.modelScale[1] > largestScale)
827 {
828 largestScale = ent->e.modelScale[1];
829 }
830 if (ent->e.modelScale[2] > largestScale)
831 {
832 largestScale = ent->e.modelScale[2];
833 }
834 if (!largestScale)
835 {
836 largestScale = 1;
837 }
838
839 // cull bounding sphere
840 switch ( R_CullLocalPointAndRadius( vec3_origin, ent->e.radius * largestScale) )
841 {
842 case CULL_OUT:
843 tr.pc.c_sphere_cull_md3_out++;
844 return CULL_OUT;
845
846 case CULL_IN:
847 tr.pc.c_sphere_cull_md3_in++;
848 return CULL_IN;
849
850 case CULL_CLIP:
851 tr.pc.c_sphere_cull_md3_clip++;
852 return CULL_IN;
853 }
854 return CULL_IN;
855 }
856
857
858 /*
859 =================
860 R_AComputeFogNum
861
862 =================
863 */
R_GComputeFogNum(trRefEntity_t * ent)864 static int R_GComputeFogNum( trRefEntity_t *ent ) {
865
866 int i, j;
867 fog_t *fog;
868
869 if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
870 return 0;
871 }
872
873 for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
874 fog = &tr.world->fogs[i];
875 for ( j = 0 ; j < 3 ; j++ ) {
876 if ( ent->e.origin[j] - ent->e.radius >= fog->bounds[1][j] ) {
877 break;
878 }
879 if ( ent->e.origin[j] + ent->e.radius <= fog->bounds[0][j] ) {
880 break;
881 }
882 }
883 if ( j == 3 ) {
884 return i;
885 }
886 }
887
888 return 0;
889 }
890
891 // work out lod for this entity.
G2_ComputeLOD(trRefEntity_t * ent,const model_t * currentModel,int lodBias)892 static int G2_ComputeLOD( trRefEntity_t *ent, const model_t *currentModel, int lodBias )
893 {
894 float flod, lodscale;
895 float projectedRadius;
896 int lod;
897
898 if ( currentModel->numLods < 2 )
899 { // model has only 1 LOD level, skip computations and bias
900 return(0);
901 }
902
903 if ( r_lodbias->integer > lodBias )
904 {
905 lodBias = r_lodbias->integer;
906 }
907
908 // scale the radius if need be
909 float largestScale = ent->e.modelScale[0];
910
911 if (ent->e.modelScale[1] > largestScale)
912 {
913 largestScale = ent->e.modelScale[1];
914 }
915 if (ent->e.modelScale[2] > largestScale)
916 {
917 largestScale = ent->e.modelScale[2];
918 }
919 if (!largestScale)
920 {
921 largestScale = 1;
922 }
923
924 if ( ( projectedRadius = ProjectRadius( 0.75*largestScale*ent->e.radius, ent->e.origin ) ) != 0 ) //we reduce the radius to make the LOD match other model types which use the actual bound box size
925 {
926 lodscale = (r_lodscale->value+r_autolodscalevalue->value);
927 if ( lodscale > 20 )
928 {
929 lodscale = 20;
930 }
931 else if ( lodscale < 0 )
932 {
933 lodscale = 0;
934 }
935 flod = 1.0f - projectedRadius * lodscale;
936 }
937 else
938 {
939 // object intersects near view plane, e.g. view weapon
940 flod = 0;
941 }
942 flod *= currentModel->numLods;
943 lod = Q_ftol( flod );
944
945 if ( lod < 0 )
946 {
947 lod = 0;
948 }
949 else if ( lod >= currentModel->numLods )
950 {
951 lod = currentModel->numLods - 1;
952 }
953
954
955 lod += lodBias;
956
957 if ( lod >= currentModel->numLods )
958 lod = currentModel->numLods - 1;
959 if ( lod < 0 )
960 lod = 0;
961
962 return lod;
963 }
964
965 //======================================================================
966 //
967 // Bone Manipulation code
968
969
G2_CreateQuaterion(mdxaBone_t * mat,vec4_t quat)970 void G2_CreateQuaterion(mdxaBone_t *mat, vec4_t quat)
971 {
972 // this is revised for the 3x4 matrix we use in G2.
973 float t = 1 + mat->matrix[0][0] + mat->matrix[1][1] + mat->matrix[2][2];
974 float s;
975
976 //If the trace of the matrix is greater than zero, then
977 //perform an "instant" calculation.
978 //Important note wrt. rouning errors:
979 //Test if ( T > 0.00000001 ) to avoid large distortions!
980 if (t > 0.00000001)
981 {
982 s = sqrt(t) * 2;
983 quat[0] = ( mat->matrix[1][2] - mat->matrix[2][1] ) / s;
984 quat[1] = ( mat->matrix[2][0] - mat->matrix[0][2] ) / s;
985 quat[2] = ( mat->matrix[0][1] - mat->matrix[1][0] ) / s;
986 quat[3] = 0.25 * s;
987 }
988 else
989 {
990 //If the trace of the matrix is equal to zero then identify
991 //which major diagonal element has the greatest value.
992
993 //Depending on this, calculate the following:
994
995 if ( mat->matrix[0][0] > mat->matrix[1][1] && mat->matrix[0][0] > mat->matrix[2][2] ) { // Column 0:
996 s = sqrt( 1.0 + mat->matrix[0][0] - mat->matrix[1][1] - mat->matrix[2][2])* 2;
997 quat[0] = 0.25 * s;
998 quat[1] = (mat->matrix[0][1] + mat->matrix[1][0] ) / s;
999 quat[2] = (mat->matrix[2][0] + mat->matrix[0][2] ) / s;
1000 quat[3] = (mat->matrix[1][2] - mat->matrix[2][1] ) / s;
1001
1002 } else if ( mat->matrix[1][1] > mat->matrix[2][2] ) { // Column 1:
1003 s = sqrt( 1.0 + mat->matrix[1][1] - mat->matrix[0][0] - mat->matrix[2][2] ) * 2;
1004 quat[0] = (mat->matrix[0][1] + mat->matrix[1][0] ) / s;
1005 quat[1] = 0.25 * s;
1006 quat[2] = (mat->matrix[1][2] + mat->matrix[2][1] ) / s;
1007 quat[3] = (mat->matrix[2][0] - mat->matrix[0][2] ) / s;
1008
1009 } else { // Column 2:
1010 s = sqrt( 1.0 + mat->matrix[2][2] - mat->matrix[0][0] - mat->matrix[1][1] ) * 2;
1011 quat[0] = (mat->matrix[2][0]+ mat->matrix[0][2] ) / s;
1012 quat[1] = (mat->matrix[1][2] + mat->matrix[2][1] ) / s;
1013 quat[2] = 0.25 * s;
1014 quat[3] = (mat->matrix[0][1] - mat->matrix[1][0] ) / s;
1015 }
1016 }
1017 }
1018
G2_CreateMatrixFromQuaterion(mdxaBone_t * mat,vec4_t quat)1019 void G2_CreateMatrixFromQuaterion(mdxaBone_t *mat, vec4_t quat)
1020 {
1021
1022 float xx = quat[0] * quat[0];
1023 float xy = quat[0] * quat[1];
1024 float xz = quat[0] * quat[2];
1025 float xw = quat[0] * quat[3];
1026
1027 float yy = quat[1] * quat[1];
1028 float yz = quat[1] * quat[2];
1029 float yw = quat[1] * quat[3];
1030
1031 float zz = quat[2] * quat[2];
1032 float zw = quat[2] * quat[3];
1033
1034 mat->matrix[0][0] = 1 - 2 * ( yy + zz );
1035 mat->matrix[1][0] = 2 * ( xy - zw );
1036 mat->matrix[2][0] = 2 * ( xz + yw );
1037
1038 mat->matrix[0][1] = 2 * ( xy + zw );
1039 mat->matrix[1][1] = 1 - 2 * ( xx + zz );
1040 mat->matrix[2][1] = 2 * ( yz - xw );
1041
1042 mat->matrix[0][2] = 2 * ( xz - yw );
1043 mat->matrix[1][2] = 2 * ( yz + xw );
1044 mat->matrix[2][2] = 1 - 2 * ( xx + yy );
1045
1046 mat->matrix[0][3] = mat->matrix[1][3] = mat->matrix[2][3] = 0;
1047 }
1048
1049 // nasty little matrix multiply going on here..
Multiply_3x4Matrix(mdxaBone_t * out,mdxaBone_t * in2,mdxaBone_t * in)1050 void Multiply_3x4Matrix(mdxaBone_t *out, mdxaBone_t *in2, mdxaBone_t *in)
1051 {
1052 // first row of out
1053 out->matrix[0][0] = (in2->matrix[0][0] * in->matrix[0][0]) + (in2->matrix[0][1] * in->matrix[1][0]) + (in2->matrix[0][2] * in->matrix[2][0]);
1054 out->matrix[0][1] = (in2->matrix[0][0] * in->matrix[0][1]) + (in2->matrix[0][1] * in->matrix[1][1]) + (in2->matrix[0][2] * in->matrix[2][1]);
1055 out->matrix[0][2] = (in2->matrix[0][0] * in->matrix[0][2]) + (in2->matrix[0][1] * in->matrix[1][2]) + (in2->matrix[0][2] * in->matrix[2][2]);
1056 out->matrix[0][3] = (in2->matrix[0][0] * in->matrix[0][3]) + (in2->matrix[0][1] * in->matrix[1][3]) + (in2->matrix[0][2] * in->matrix[2][3]) + in2->matrix[0][3];
1057 // second row of outf out
1058 out->matrix[1][0] = (in2->matrix[1][0] * in->matrix[0][0]) + (in2->matrix[1][1] * in->matrix[1][0]) + (in2->matrix[1][2] * in->matrix[2][0]);
1059 out->matrix[1][1] = (in2->matrix[1][0] * in->matrix[0][1]) + (in2->matrix[1][1] * in->matrix[1][1]) + (in2->matrix[1][2] * in->matrix[2][1]);
1060 out->matrix[1][2] = (in2->matrix[1][0] * in->matrix[0][2]) + (in2->matrix[1][1] * in->matrix[1][2]) + (in2->matrix[1][2] * in->matrix[2][2]);
1061 out->matrix[1][3] = (in2->matrix[1][0] * in->matrix[0][3]) + (in2->matrix[1][1] * in->matrix[1][3]) + (in2->matrix[1][2] * in->matrix[2][3]) + in2->matrix[1][3];
1062 // third row of out out
1063 out->matrix[2][0] = (in2->matrix[2][0] * in->matrix[0][0]) + (in2->matrix[2][1] * in->matrix[1][0]) + (in2->matrix[2][2] * in->matrix[2][0]);
1064 out->matrix[2][1] = (in2->matrix[2][0] * in->matrix[0][1]) + (in2->matrix[2][1] * in->matrix[1][1]) + (in2->matrix[2][2] * in->matrix[2][1]);
1065 out->matrix[2][2] = (in2->matrix[2][0] * in->matrix[0][2]) + (in2->matrix[2][1] * in->matrix[1][2]) + (in2->matrix[2][2] * in->matrix[2][2]);
1066 out->matrix[2][3] = (in2->matrix[2][0] * in->matrix[0][3]) + (in2->matrix[2][1] * in->matrix[1][3]) + (in2->matrix[2][2] * in->matrix[2][3]) + in2->matrix[2][3];
1067 }
1068
1069
G2_GetBonePoolIndex(const mdxaHeader_t * pMDXAHeader,int iFrame,int iBone)1070 static int G2_GetBonePoolIndex(const mdxaHeader_t *pMDXAHeader, int iFrame, int iBone)
1071 {
1072 const int iOffsetToIndex = (iFrame * pMDXAHeader->numBones * 3) + (iBone * 3);
1073 mdxaIndex_t *pIndex = (mdxaIndex_t *)((byte*)pMDXAHeader + pMDXAHeader->ofsFrames + iOffsetToIndex);
1074
1075 return (pIndex->iIndex[2] << 16) + (pIndex->iIndex[1] << 8) + (pIndex->iIndex[0]);
1076 }
1077
1078
UnCompressBone(float mat[3][4],int iBoneIndex,const mdxaHeader_t * pMDXAHeader,int iFrame)1079 /*static inline*/ void UnCompressBone(float mat[3][4], int iBoneIndex, const mdxaHeader_t *pMDXAHeader, int iFrame)
1080 {
1081 mdxaCompQuatBone_t *pCompBonePool = (mdxaCompQuatBone_t *) ((byte *)pMDXAHeader + pMDXAHeader->ofsCompBonePool);
1082 MC_UnCompressQuat(mat, pCompBonePool[ G2_GetBonePoolIndex( pMDXAHeader, iFrame, iBoneIndex ) ].Comp);
1083 }
1084
1085 #define DEBUG_G2_TIMING (0)
1086 #define DEBUG_G2_TIMING_RENDER_ONLY (1)
1087
G2_TimingModel(boneInfo_t & bone,int currentTime,int numFramesInFile,int & currentFrame,int & newFrame,float & lerp)1088 void G2_TimingModel(boneInfo_t &bone,int currentTime,int numFramesInFile,int ¤tFrame,int &newFrame,float &lerp)
1089 {
1090 assert(bone.startFrame>=0);
1091 assert(bone.startFrame<=numFramesInFile);
1092 assert(bone.endFrame>=0);
1093 assert(bone.endFrame<=numFramesInFile);
1094
1095 // yes - add in animation speed to current frame
1096 float animSpeed = bone.animSpeed;
1097 float time;
1098 if (bone.pauseTime)
1099 {
1100 time = (bone.pauseTime - bone.startTime) / 50.0f;
1101 }
1102 else
1103 {
1104 time = (currentTime - bone.startTime) / 50.0f;
1105 }
1106 if (time<0.0f)
1107 {
1108 time=0.0f;
1109 }
1110 float newFrame_g = bone.startFrame + (time * animSpeed);
1111
1112 int animSize = bone.endFrame - bone.startFrame;
1113 float endFrame = (float)bone.endFrame;
1114 // we are supposed to be animating right?
1115 if (animSize)
1116 {
1117 // did we run off the end?
1118 if (((animSpeed > 0.0f) && (newFrame_g > endFrame - 1)) ||
1119 ((animSpeed < 0.0f) && (newFrame_g < endFrame+1)))
1120 {
1121 // yep - decide what to do
1122 if (bone.flags & BONE_ANIM_OVERRIDE_LOOP)
1123 {
1124 // get our new animation frame back within the bounds of the animation set
1125 if (animSpeed < 0.0f)
1126 {
1127 // we don't use this case, or so I am told
1128 // if we do, let me know, I need to insure the mod works
1129
1130 // should we be creating a virtual frame?
1131 if ((newFrame_g < endFrame+1) && (newFrame_g >= endFrame))
1132 {
1133 // now figure out what we are lerping between
1134 // delta is the fraction between this frame and the next, since the new anim is always at a .0f;
1135 lerp = float(endFrame+1)-newFrame_g;
1136 // frames are easy to calculate
1137 currentFrame = endFrame;
1138 assert(currentFrame>=0&¤tFrame<numFramesInFile);
1139 newFrame = bone.startFrame;
1140 assert(newFrame>=0&&newFrame<numFramesInFile);
1141 }
1142 else
1143 {
1144 if (newFrame_g <= endFrame+1)
1145 {
1146 newFrame_g=endFrame+fmod(newFrame_g-endFrame,animSize)-animSize;
1147 }
1148 // now figure out what we are lerping between
1149 // delta is the fraction between this frame and the next, since the new anim is always at a .0f;
1150 lerp = (ceil(newFrame_g)-newFrame_g);
1151 // frames are easy to calculate
1152 currentFrame = ceil(newFrame_g);
1153 assert(currentFrame>=0&¤tFrame<numFramesInFile);
1154 // should we be creating a virtual frame?
1155 if (currentFrame <= endFrame+1 )
1156 {
1157 newFrame = bone.startFrame;
1158 assert(newFrame>=0&&newFrame<numFramesInFile);
1159 }
1160 else
1161 {
1162 newFrame = currentFrame - 1;
1163 assert(newFrame>=0&&newFrame<numFramesInFile);
1164 }
1165 }
1166 }
1167 else
1168 {
1169 // should we be creating a virtual frame?
1170 if ((newFrame_g > endFrame - 1) && (newFrame_g < endFrame))
1171 {
1172 // now figure out what we are lerping between
1173 // delta is the fraction between this frame and the next, since the new anim is always at a .0f;
1174 lerp = (newFrame_g - (int)newFrame_g);
1175 // frames are easy to calculate
1176 currentFrame = (int)newFrame_g;
1177 assert(currentFrame>=0&¤tFrame<numFramesInFile);
1178 newFrame = bone.startFrame;
1179 assert(newFrame>=0&&newFrame<numFramesInFile);
1180 }
1181 else
1182 {
1183 if (newFrame_g >= endFrame)
1184 {
1185 newFrame_g=endFrame+fmod(newFrame_g-endFrame,animSize)-animSize;
1186 }
1187 // now figure out what we are lerping between
1188 // delta is the fraction between this frame and the next, since the new anim is always at a .0f;
1189 lerp = (newFrame_g - (int)newFrame_g);
1190 // frames are easy to calculate
1191 currentFrame = (int)newFrame_g;
1192 assert(currentFrame>=0&¤tFrame<numFramesInFile);
1193 // should we be creating a virtual frame?
1194 if (newFrame_g >= endFrame - 1)
1195 {
1196 newFrame = bone.startFrame;
1197 assert(newFrame>=0&&newFrame<numFramesInFile);
1198 }
1199 else
1200 {
1201 newFrame = currentFrame + 1;
1202 assert(newFrame>=0&&newFrame<numFramesInFile);
1203 }
1204 }
1205 }
1206 // sanity check
1207 assert (((newFrame < endFrame) && (newFrame >= bone.startFrame)) || (animSize < 10));
1208 }
1209 else
1210 {
1211 if (((bone.flags & (BONE_ANIM_OVERRIDE_FREEZE)) == (BONE_ANIM_OVERRIDE_FREEZE)))
1212 {
1213 // if we are supposed to reset the default anim, then do so
1214 if (animSpeed > 0.0f)
1215 {
1216 currentFrame = bone.endFrame - 1;
1217 assert(currentFrame>=0&¤tFrame<numFramesInFile);
1218 }
1219 else
1220 {
1221 currentFrame = bone.endFrame+1;
1222 assert(currentFrame>=0&¤tFrame<numFramesInFile);
1223 }
1224
1225 newFrame = currentFrame;
1226 assert(newFrame>=0&&newFrame<numFramesInFile);
1227 lerp = 0;
1228 }
1229 else
1230 {
1231 bone.flags &= ~(BONE_ANIM_TOTAL);
1232 }
1233
1234 }
1235 }
1236 else
1237 {
1238 if (animSpeed> 0.0)
1239 {
1240 // frames are easy to calculate
1241 currentFrame = (int)newFrame_g;
1242
1243 // figure out the difference between the two frames - we have to decide what frame and what percentage of that
1244 // frame we want to display
1245 lerp = (newFrame_g - currentFrame);
1246
1247 assert(currentFrame>=0&¤tFrame<numFramesInFile);
1248
1249 newFrame = currentFrame + 1;
1250 // are we now on the end frame?
1251 assert((int)endFrame<=numFramesInFile);
1252 if (newFrame >= (int)endFrame)
1253 {
1254 // we only want to lerp with the first frame of the anim if we are looping
1255 if (bone.flags & BONE_ANIM_OVERRIDE_LOOP)
1256 {
1257 newFrame = bone.startFrame;
1258 assert(newFrame>=0&&newFrame<numFramesInFile);
1259 }
1260 // if we intend to end this anim or freeze after this, then just keep on the last frame
1261 else
1262 {
1263 newFrame = bone.endFrame-1;
1264 assert(newFrame>=0&&newFrame<numFramesInFile);
1265 }
1266 }
1267 assert(newFrame>=0&&newFrame<numFramesInFile);
1268 }
1269 else
1270 {
1271 lerp = (ceil(newFrame_g)-newFrame_g);
1272 // frames are easy to calculate
1273 currentFrame = ceil(newFrame_g);
1274 if (currentFrame>bone.startFrame)
1275 {
1276 currentFrame=bone.startFrame;
1277 newFrame = currentFrame;
1278 lerp=0.0f;
1279 }
1280 else
1281 {
1282 newFrame=currentFrame-1;
1283 // are we now on the end frame?
1284 if (newFrame < endFrame+1)
1285 {
1286 // we only want to lerp with the first frame of the anim if we are looping
1287 if (bone.flags & BONE_ANIM_OVERRIDE_LOOP)
1288 {
1289 newFrame = bone.startFrame;
1290 assert(newFrame>=0&&newFrame<numFramesInFile);
1291 }
1292 // if we intend to end this anim or freeze after this, then just keep on the last frame
1293 else
1294 {
1295 newFrame = bone.endFrame+1;
1296 assert(newFrame>=0&&newFrame<numFramesInFile);
1297 }
1298 }
1299 }
1300 assert(currentFrame>=0&¤tFrame<numFramesInFile);
1301 assert(newFrame>=0&&newFrame<numFramesInFile);
1302 }
1303 }
1304 }
1305 else
1306 {
1307 if (animSpeed<0.0)
1308 {
1309 currentFrame = bone.endFrame+1;
1310 }
1311 else
1312 {
1313 currentFrame = bone.endFrame-1;
1314 }
1315 if (currentFrame<0)
1316 {
1317 currentFrame=0;
1318 }
1319 assert(currentFrame>=0&¤tFrame<numFramesInFile);
1320 newFrame = currentFrame;
1321 assert(newFrame>=0&&newFrame<numFramesInFile);
1322 lerp = 0;
1323
1324 }
1325 assert(currentFrame>=0&¤tFrame<numFramesInFile);
1326 assert(newFrame>=0&&newFrame<numFramesInFile);
1327 assert(lerp>=0.0f&&lerp<=1.0f);
1328 }
1329
1330 #ifdef _RAG_PRINT_TEST
1331 void G2_RagPrintMatrix(mdxaBone_t *mat);
1332 #endif
1333 //basically construct a seperate skeleton with full hierarchy to store a matrix
1334 //off which will give us the desired settling position given the frame in the skeleton
1335 //that should be used -rww
1336 int G2_Add_Bone (const model_t *mod, boneInfo_v &blist, const char *boneName);
1337 int G2_Find_Bone(const model_t *mod, boneInfo_v &blist, const char *boneName);
G2_RagGetAnimMatrix(CGhoul2Info & ghoul2,const int boneNum,mdxaBone_t & matrix,const int frame)1338 void G2_RagGetAnimMatrix(CGhoul2Info &ghoul2, const int boneNum, mdxaBone_t &matrix, const int frame)
1339 {
1340 mdxaBone_t animMatrix;
1341 mdxaSkel_t *skel;
1342 mdxaSkel_t *pskel;
1343 mdxaSkelOffsets_t *offsets;
1344 int parent;
1345 int bListIndex;
1346 int parentBlistIndex;
1347 #ifdef _RAG_PRINT_TEST
1348 bool actuallySet = false;
1349 #endif
1350
1351 assert(ghoul2.mBoneCache);
1352 assert(ghoul2.animModel);
1353
1354 offsets = (mdxaSkelOffsets_t *)((byte *)ghoul2.mBoneCache->header + sizeof(mdxaHeader_t));
1355 skel = (mdxaSkel_t *)((byte *)ghoul2.mBoneCache->header + sizeof(mdxaHeader_t) + offsets->offsets[boneNum]);
1356
1357 //find/add the bone in the list
1358 if (!skel->name[0])
1359 {
1360 bListIndex = -1;
1361 }
1362 else
1363 {
1364 bListIndex = G2_Find_Bone(ghoul2.animModel, ghoul2.mBlist, skel->name);
1365 if (bListIndex == -1)
1366 {
1367 #ifdef _RAG_PRINT_TEST
1368 ri.Printf( PRINT_ALL, "Attempting to add %s\n", skel->name);
1369 #endif
1370 bListIndex = G2_Add_Bone(ghoul2.animModel, ghoul2.mBlist, skel->name);
1371 }
1372 }
1373
1374 assert(bListIndex != -1);
1375
1376 boneInfo_t &bone = ghoul2.mBlist[bListIndex];
1377
1378 if (bone.hasAnimFrameMatrix == frame)
1379 { //already calculated so just grab it
1380 matrix = bone.animFrameMatrix;
1381 return;
1382 }
1383
1384 //get the base matrix for the specified frame
1385 UnCompressBone(animMatrix.matrix, boneNum, ghoul2.mBoneCache->header, frame);
1386
1387 parent = skel->parent;
1388 if (boneNum > 0 && parent > -1)
1389 {
1390 //recursively call to assure all parent matrices are set up
1391 G2_RagGetAnimMatrix(ghoul2, parent, matrix, frame);
1392
1393 //assign the new skel ptr for our parent
1394 pskel = (mdxaSkel_t *)((byte *)ghoul2.mBoneCache->header + sizeof(mdxaHeader_t) + offsets->offsets[parent]);
1395
1396 //taking bone matrix for the skeleton frame and parent's animFrameMatrix into account, determine our final animFrameMatrix
1397 if (!pskel->name[0])
1398 {
1399 parentBlistIndex = -1;
1400 }
1401 else
1402 {
1403 parentBlistIndex = G2_Find_Bone(ghoul2.animModel, ghoul2.mBlist, pskel->name);
1404 if (parentBlistIndex == -1)
1405 {
1406 parentBlistIndex = G2_Add_Bone(ghoul2.animModel, ghoul2.mBlist, pskel->name);
1407 }
1408 }
1409
1410 assert(parentBlistIndex != -1);
1411
1412 boneInfo_t &pbone = ghoul2.mBlist[parentBlistIndex];
1413
1414 assert(pbone.hasAnimFrameMatrix == frame); //this should have been calc'd in the recursive call
1415
1416 Multiply_3x4Matrix(&bone.animFrameMatrix, &pbone.animFrameMatrix, &animMatrix);
1417
1418 #ifdef _RAG_PRINT_TEST
1419 if (parentBlistIndex != -1 && bListIndex != -1)
1420 {
1421 actuallySet = true;
1422 }
1423 else
1424 {
1425 ri.Printf( PRINT_ALL, "BAD LIST INDEX: %s, %s [%i]\n", skel->name, pskel->name, parent);
1426 }
1427 #endif
1428 }
1429 else
1430 { //root
1431 Multiply_3x4Matrix(&bone.animFrameMatrix, &ghoul2.mBoneCache->rootMatrix, &animMatrix);
1432 #ifdef _RAG_PRINT_TEST
1433 if (bListIndex != -1)
1434 {
1435 actuallySet = true;
1436 }
1437 else
1438 {
1439 ri.Printf( PRINT_ALL, "BAD LIST INDEX: %s\n", skel->name);
1440 }
1441 #endif
1442 //bone.animFrameMatrix = ghoul2.mBoneCache->mFinalBones[boneNum].boneMatrix;
1443 //Maybe use this for the root, so that the orientation is in sync with the current
1444 //root matrix? However this would require constant recalculation of this base
1445 //skeleton which I currently do not want.
1446 }
1447
1448 //never need to figure it out again
1449 bone.hasAnimFrameMatrix = frame;
1450
1451 #ifdef _RAG_PRINT_TEST
1452 if (!actuallySet)
1453 {
1454 ri.Printf( PRINT_ALL, "SET FAILURE\n");
1455 G2_RagPrintMatrix(&bone.animFrameMatrix);
1456 }
1457 #endif
1458
1459 matrix = bone.animFrameMatrix;
1460 }
1461
G2_TransformBone(int child,CBoneCache & BC)1462 void G2_TransformBone (int child,CBoneCache &BC)
1463 {
1464 SBoneCalc &TB=BC.mBones[child];
1465 static mdxaBone_t tbone[6];
1466 // mdxaFrame_t *aFrame=0;
1467 // mdxaFrame_t *bFrame=0;
1468 // mdxaFrame_t *aoldFrame=0;
1469 // mdxaFrame_t *boldFrame=0;
1470 static mdxaSkel_t *skel;
1471 static mdxaSkelOffsets_t *offsets;
1472 boneInfo_v &boneList = *BC.rootBoneList;
1473 static int j, boneListIndex;
1474 int angleOverride = 0;
1475
1476 #if DEBUG_G2_TIMING
1477 bool printTiming=false;
1478 #endif
1479 // should this bone be overridden by a bone in the bone list?
1480 boneListIndex = G2_Find_Bone_In_List(boneList, child);
1481 if (boneListIndex != -1)
1482 {
1483 // we found a bone in the list - we need to override something here.
1484
1485 // do we override the rotational angles?
1486 if ((boneList[boneListIndex].flags) & (BONE_ANGLES_TOTAL))
1487 {
1488 angleOverride = (boneList[boneListIndex].flags) & (BONE_ANGLES_TOTAL);
1489 }
1490
1491 // set blending stuff if we need to
1492 if (boneList[boneListIndex].flags & BONE_ANIM_BLEND)
1493 {
1494 float blendTime = BC.incomingTime - boneList[boneListIndex].blendStart;
1495 // only set up the blend anim if we actually have some blend time left on this bone anim - otherwise we might corrupt some blend higher up the hiearchy
1496 if (blendTime>=0.0f&&blendTime < boneList[boneListIndex].blendTime)
1497 {
1498 TB.blendFrame = boneList[boneListIndex].blendFrame;
1499 TB.blendOldFrame = boneList[boneListIndex].blendLerpFrame;
1500 TB.blendLerp = (blendTime / boneList[boneListIndex].blendTime);
1501 TB.blendMode = true;
1502 }
1503 else
1504 {
1505 TB.blendMode = false;
1506 }
1507 }
1508 else if (/*r_Ghoul2NoBlend->integer||*/((boneList[boneListIndex].flags) & (BONE_ANIM_OVERRIDE_LOOP | BONE_ANIM_OVERRIDE)))
1509 // turn off blending if we are just doing a straing animation override
1510 {
1511 TB.blendMode = false;
1512 }
1513
1514 // should this animation be overridden by an animation in the bone list?
1515 if ((boneList[boneListIndex].flags) & (BONE_ANIM_OVERRIDE_LOOP | BONE_ANIM_OVERRIDE))
1516 {
1517 G2_TimingModel(boneList[boneListIndex],BC.incomingTime,BC.header->numFrames,TB.currentFrame,TB.newFrame,TB.backlerp);
1518 }
1519 #if DEBUG_G2_TIMING
1520 printTiming=true;
1521 #endif
1522 /*
1523 if ((r_Ghoul2NoLerp->integer)||((boneList[boneListIndex].flags) & (BONE_ANIM_NO_LERP)))
1524 {
1525 TB.backlerp = 0.0f;
1526 }
1527 */
1528 //rwwFIXMEFIXME: Use?
1529 }
1530 // figure out where the location of the bone animation data is
1531 assert(TB.newFrame>=0&&TB.newFrame<BC.header->numFrames);
1532 if (!(TB.newFrame>=0&&TB.newFrame<BC.header->numFrames))
1533 {
1534 TB.newFrame=0;
1535 }
1536 // aFrame = (mdxaFrame_t *)((byte *)BC.header + BC.header->ofsFrames + TB.newFrame * BC.frameSize );
1537 assert(TB.currentFrame>=0&&TB.currentFrame<BC.header->numFrames);
1538 if (!(TB.currentFrame>=0&&TB.currentFrame<BC.header->numFrames))
1539 {
1540 TB.currentFrame=0;
1541 }
1542 // aoldFrame = (mdxaFrame_t *)((byte *)BC.header + BC.header->ofsFrames + TB.currentFrame * BC.frameSize );
1543
1544 // figure out where the location of the blended animation data is
1545 assert(!(TB.blendFrame < 0.0 || TB.blendFrame >= (BC.header->numFrames+1)));
1546 if (TB.blendFrame < 0.0 || TB.blendFrame >= (BC.header->numFrames+1) )
1547 {
1548 TB.blendFrame=0.0;
1549 }
1550 // bFrame = (mdxaFrame_t *)((byte *)BC.header + BC.header->ofsFrames + (int)TB.blendFrame * BC.frameSize );
1551 assert(TB.blendOldFrame>=0&&TB.blendOldFrame<BC.header->numFrames);
1552 if (!(TB.blendOldFrame>=0&&TB.blendOldFrame<BC.header->numFrames))
1553 {
1554 TB.blendOldFrame=0;
1555 }
1556 #if DEBUG_G2_TIMING
1557
1558 #if DEBUG_G2_TIMING_RENDER_ONLY
1559 if (!HackadelicOnClient)
1560 {
1561 printTiming=false;
1562 }
1563 #endif
1564 if (printTiming)
1565 {
1566 char mess[1000];
1567 if (TB.blendMode)
1568 {
1569 sprintf(mess,"b %2d %5d %4d %4d %4d %4d %f %f\n",boneListIndex,BC.incomingTime,(int)TB.newFrame,(int)TB.currentFrame,(int)TB.blendFrame,(int)TB.blendOldFrame,TB.backlerp,TB.blendLerp);
1570 }
1571 else
1572 {
1573 sprintf(mess,"a %2d %5d %4d %4d %f\n",boneListIndex,BC.incomingTime,TB.newFrame,TB.currentFrame,TB.backlerp);
1574 }
1575 Com_OPrintf("%s",mess);
1576 const boneInfo_t &bone=boneList[boneListIndex];
1577 if (bone.flags&BONE_ANIM_BLEND)
1578 {
1579 sprintf(mess," bfb[%2d] %5d %5d (%5d-%5d) %4.2f %4x bt(%5d-%5d) %7.2f %5d\n",
1580 boneListIndex,
1581 BC.incomingTime,
1582 bone.startTime,
1583 bone.startFrame,
1584 bone.endFrame,
1585 bone.animSpeed,
1586 bone.flags,
1587 bone.blendStart,
1588 bone.blendStart+bone.blendTime,
1589 bone.blendFrame,
1590 bone.blendLerpFrame
1591 );
1592 }
1593 else
1594 {
1595 sprintf(mess," bfa[%2d] %5d %5d (%5d-%5d) %4.2f %4x\n",
1596 boneListIndex,
1597 BC.incomingTime,
1598 bone.startTime,
1599 bone.startFrame,
1600 bone.endFrame,
1601 bone.animSpeed,
1602 bone.flags
1603 );
1604 }
1605 // Com_OPrintf("%s",mess);
1606 }
1607 #endif
1608 // boldFrame = (mdxaFrame_t *)((byte *)BC.header + BC.header->ofsFrames + TB.blendOldFrame * BC.frameSize );
1609
1610 // mdxaCompBone_t *compBonePointer = (mdxaCompBone_t *)((byte *)BC.header + BC.header->ofsCompBonePool);
1611
1612 assert(child>=0&&child<BC.header->numBones);
1613 // assert(bFrame->boneIndexes[child]>=0);
1614 // assert(boldFrame->boneIndexes[child]>=0);
1615 // assert(aFrame->boneIndexes[child]>=0);
1616 // assert(aoldFrame->boneIndexes[child]>=0);
1617
1618 // decide where the transformed bone is going
1619
1620 // are we blending with another frame of anim?
1621 if (TB.blendMode)
1622 {
1623 float backlerp = TB.blendFrame - (int)TB.blendFrame;
1624 float frontlerp = 1.0 - backlerp;
1625
1626 // MC_UnCompress(tbone[3].matrix,compBonePointer[bFrame->boneIndexes[child]].Comp);
1627 // MC_UnCompress(tbone[4].matrix,compBonePointer[boldFrame->boneIndexes[child]].Comp);
1628 UnCompressBone(tbone[3].matrix, child, BC.header, TB.blendFrame);
1629 UnCompressBone(tbone[4].matrix, child, BC.header, TB.blendOldFrame);
1630
1631 for ( j = 0 ; j < 12 ; j++ )
1632 {
1633 ((float *)&tbone[5])[j] = (backlerp * ((float *)&tbone[3])[j])
1634 + (frontlerp * ((float *)&tbone[4])[j]);
1635 }
1636 }
1637
1638 //
1639 // lerp this bone - use the temp space on the ref entity to put the bone transforms into
1640 //
1641 if (!TB.backlerp)
1642 {
1643 // MC_UnCompress(tbone[2].matrix,compBonePointer[aoldFrame->boneIndexes[child]].Comp);
1644 UnCompressBone(tbone[2].matrix, child, BC.header, TB.currentFrame);
1645
1646 // blend in the other frame if we need to
1647 if (TB.blendMode)
1648 {
1649 float blendFrontlerp = 1.0 - TB.blendLerp;
1650 for ( j = 0 ; j < 12 ; j++ )
1651 {
1652 ((float *)&tbone[2])[j] = (TB.blendLerp * ((float *)&tbone[2])[j])
1653 + (blendFrontlerp * ((float *)&tbone[5])[j]);
1654 }
1655 }
1656
1657 if (!child)
1658 {
1659 // now multiply by the root matrix, so we can offset this model should we need to
1660 Multiply_3x4Matrix(&BC.mFinalBones[child].boneMatrix, &BC.rootMatrix, &tbone[2]);
1661 }
1662 }
1663 else
1664 {
1665 float frontlerp = 1.0 - TB.backlerp;
1666 // MC_UnCompress(tbone[0].matrix,compBonePointer[aFrame->boneIndexes[child]].Comp);
1667 // MC_UnCompress(tbone[1].matrix,compBonePointer[aoldFrame->boneIndexes[child]].Comp);
1668 UnCompressBone(tbone[0].matrix, child, BC.header, TB.newFrame);
1669 UnCompressBone(tbone[1].matrix, child, BC.header, TB.currentFrame);
1670
1671 for ( j = 0 ; j < 12 ; j++ )
1672 {
1673 ((float *)&tbone[2])[j] = (TB.backlerp * ((float *)&tbone[0])[j])
1674 + (frontlerp * ((float *)&tbone[1])[j]);
1675 }
1676
1677 // blend in the other frame if we need to
1678 if (TB.blendMode)
1679 {
1680 float blendFrontlerp = 1.0 - TB.blendLerp;
1681 for ( j = 0 ; j < 12 ; j++ )
1682 {
1683 ((float *)&tbone[2])[j] = (TB.blendLerp * ((float *)&tbone[2])[j])
1684 + (blendFrontlerp * ((float *)&tbone[5])[j]);
1685 }
1686 }
1687
1688 if (!child)
1689 {
1690 // now multiply by the root matrix, so we can offset this model should we need to
1691 Multiply_3x4Matrix(&BC.mFinalBones[child].boneMatrix, &BC.rootMatrix, &tbone[2]);
1692 }
1693 }
1694 // figure out where the bone hirearchy info is
1695 offsets = (mdxaSkelOffsets_t *)((byte *)BC.header + sizeof(mdxaHeader_t));
1696 skel = (mdxaSkel_t *)((byte *)BC.header + sizeof(mdxaHeader_t) + offsets->offsets[child]);
1697 // skel = BC.mSkels[child];
1698 //rww - removed mSkels
1699
1700 int parent=BC.mFinalBones[child].parent;
1701 assert((parent==-1&&child==0)||(parent>=0&&parent<(int)BC.mBones.size()));
1702 if (angleOverride & BONE_ANGLES_REPLACE)
1703 {
1704 bool isRag=!!(angleOverride & BONE_ANGLES_RAGDOLL);
1705 if (!isRag)
1706 { //do the same for ik.. I suppose.
1707 isRag = !!(angleOverride & BONE_ANGLES_IK);
1708 }
1709
1710 mdxaBone_t &bone = BC.mFinalBones[child].boneMatrix;
1711 boneInfo_t &boneOverride = boneList[boneListIndex];
1712
1713 if (isRag)
1714 {
1715 mdxaBone_t temp, firstPass;
1716 // give us the matrix the animation thinks we should have, so we can get the correct X&Y coors
1717 Multiply_3x4Matrix(&firstPass, &BC.mFinalBones[parent].boneMatrix, &tbone[2]);
1718 // this is crazy, we are gonna drive the animation to ID while we are doing post mults to compensate.
1719 Multiply_3x4Matrix(&temp,&firstPass, &skel->BasePoseMat);
1720 float matrixScale = VectorLength((float*)&temp);
1721 static mdxaBone_t toMatrix =
1722 {
1723 {
1724 { 1.0f, 0.0f, 0.0f, 0.0f },
1725 { 0.0f, 1.0f, 0.0f, 0.0f },
1726 { 0.0f, 0.0f, 1.0f, 0.0f }
1727 }
1728 };
1729 toMatrix.matrix[0][0]=matrixScale;
1730 toMatrix.matrix[1][1]=matrixScale;
1731 toMatrix.matrix[2][2]=matrixScale;
1732 toMatrix.matrix[0][3]=temp.matrix[0][3];
1733 toMatrix.matrix[1][3]=temp.matrix[1][3];
1734 toMatrix.matrix[2][3]=temp.matrix[2][3];
1735
1736 Multiply_3x4Matrix(&temp, &toMatrix,&skel->BasePoseMatInv); //dest first arg
1737
1738 float blendTime = BC.incomingTime - boneList[boneListIndex].boneBlendStart;
1739 float blendLerp = (blendTime / boneList[boneListIndex].boneBlendTime);
1740 if (blendLerp>0.0f)
1741 {
1742 // has started
1743 if (blendLerp>1.0f)
1744 {
1745 // done
1746 // Multiply_3x4Matrix(&bone, &BC.mFinalBones[parent].boneMatrix,&temp);
1747 memcpy (&bone,&temp, sizeof(mdxaBone_t));
1748 }
1749 else
1750 {
1751 // mdxaBone_t lerp;
1752 // now do the blend into the destination
1753 float blendFrontlerp = 1.0 - blendLerp;
1754 for ( j = 0 ; j < 12 ; j++ )
1755 {
1756 ((float *)&bone)[j] = (blendLerp * ((float *)&temp)[j])
1757 + (blendFrontlerp * ((float *)&tbone[2])[j]);
1758 }
1759 // Multiply_3x4Matrix(&bone, &BC.mFinalBones[parent].boneMatrix,&lerp);
1760 }
1761 }
1762 }
1763 else
1764 {
1765 mdxaBone_t temp, firstPass;
1766
1767 // give us the matrix the animation thinks we should have, so we can get the correct X&Y coors
1768 Multiply_3x4Matrix(&firstPass, &BC.mFinalBones[parent].boneMatrix, &tbone[2]);
1769
1770 // are we attempting to blend with the base animation? and still within blend time?
1771 if (boneOverride.boneBlendTime && (((boneOverride.boneBlendTime + boneOverride.boneBlendStart) < BC.incomingTime)))
1772 {
1773 // ok, we are supposed to be blending. Work out lerp
1774 float blendTime = BC.incomingTime - boneList[boneListIndex].boneBlendStart;
1775 float blendLerp = (blendTime / boneList[boneListIndex].boneBlendTime);
1776
1777 if (blendLerp <= 1)
1778 {
1779 if (blendLerp < 0)
1780 {
1781 assert(0);
1782 }
1783
1784 // now work out the matrix we want to get *to* - firstPass is where we are coming *from*
1785 Multiply_3x4Matrix(&temp, &firstPass, &skel->BasePoseMat);
1786
1787 float matrixScale = VectorLength((float*)&temp);
1788
1789 mdxaBone_t newMatrixTemp;
1790
1791 if (HackadelicOnClient)
1792 {
1793 for (int i=0; i<3;i++)
1794 {
1795 for(int x=0;x<3; x++)
1796 {
1797 newMatrixTemp.matrix[i][x] = boneOverride.newMatrix.matrix[i][x]*matrixScale;
1798 }
1799 }
1800
1801 newMatrixTemp.matrix[0][3] = temp.matrix[0][3];
1802 newMatrixTemp.matrix[1][3] = temp.matrix[1][3];
1803 newMatrixTemp.matrix[2][3] = temp.matrix[2][3];
1804 }
1805 else
1806 {
1807 for (int i=0; i<3;i++)
1808 {
1809 for(int x=0;x<3; x++)
1810 {
1811 newMatrixTemp.matrix[i][x] = boneOverride.matrix.matrix[i][x]*matrixScale;
1812 }
1813 }
1814
1815 newMatrixTemp.matrix[0][3] = temp.matrix[0][3];
1816 newMatrixTemp.matrix[1][3] = temp.matrix[1][3];
1817 newMatrixTemp.matrix[2][3] = temp.matrix[2][3];
1818 }
1819
1820 Multiply_3x4Matrix(&temp, &newMatrixTemp,&skel->BasePoseMatInv);
1821
1822 // now do the blend into the destination
1823 float blendFrontlerp = 1.0 - blendLerp;
1824 for ( j = 0 ; j < 12 ; j++ )
1825 {
1826 ((float *)&bone)[j] = (blendLerp * ((float *)&temp)[j])
1827 + (blendFrontlerp * ((float *)&firstPass)[j]);
1828 }
1829 }
1830 else
1831 {
1832 bone = firstPass;
1833 }
1834 }
1835 // no, so just override it directly
1836 else
1837 {
1838
1839 Multiply_3x4Matrix(&temp,&firstPass, &skel->BasePoseMat);
1840 float matrixScale = VectorLength((float*)&temp);
1841
1842 mdxaBone_t newMatrixTemp;
1843
1844 if (HackadelicOnClient)
1845 {
1846 for (int i=0; i<3;i++)
1847 {
1848 for(int x=0;x<3; x++)
1849 {
1850 newMatrixTemp.matrix[i][x] = boneOverride.newMatrix.matrix[i][x]*matrixScale;
1851 }
1852 }
1853
1854 newMatrixTemp.matrix[0][3] = temp.matrix[0][3];
1855 newMatrixTemp.matrix[1][3] = temp.matrix[1][3];
1856 newMatrixTemp.matrix[2][3] = temp.matrix[2][3];
1857 }
1858 else
1859 {
1860 for (int i=0; i<3;i++)
1861 {
1862 for(int x=0;x<3; x++)
1863 {
1864 newMatrixTemp.matrix[i][x] = boneOverride.matrix.matrix[i][x]*matrixScale;
1865 }
1866 }
1867
1868 newMatrixTemp.matrix[0][3] = temp.matrix[0][3];
1869 newMatrixTemp.matrix[1][3] = temp.matrix[1][3];
1870 newMatrixTemp.matrix[2][3] = temp.matrix[2][3];
1871 }
1872
1873 Multiply_3x4Matrix(&bone, &newMatrixTemp,&skel->BasePoseMatInv);
1874 }
1875 }
1876 }
1877 else if (angleOverride & BONE_ANGLES_PREMULT)
1878 {
1879 if ((angleOverride&BONE_ANGLES_RAGDOLL) || (angleOverride&BONE_ANGLES_IK))
1880 {
1881 mdxaBone_t tmp;
1882 if (!child)
1883 {
1884 if (HackadelicOnClient)
1885 {
1886 Multiply_3x4Matrix(&tmp, &BC.rootMatrix, &boneList[boneListIndex].newMatrix);
1887 }
1888 else
1889 {
1890 Multiply_3x4Matrix(&tmp, &BC.rootMatrix, &boneList[boneListIndex].matrix);
1891 }
1892 }
1893 else
1894 {
1895 if (HackadelicOnClient)
1896 {
1897 Multiply_3x4Matrix(&tmp, &BC.mFinalBones[parent].boneMatrix, &boneList[boneListIndex].newMatrix);
1898 }
1899 else
1900 {
1901 Multiply_3x4Matrix(&tmp, &BC.mFinalBones[parent].boneMatrix, &boneList[boneListIndex].matrix);
1902 }
1903 }
1904 Multiply_3x4Matrix(&BC.mFinalBones[child].boneMatrix,&tmp, &tbone[2]);
1905 }
1906 else
1907 {
1908 if (!child)
1909 {
1910 // use the in coming root matrix as our basis
1911 if (HackadelicOnClient)
1912 {
1913 Multiply_3x4Matrix(&BC.mFinalBones[child].boneMatrix, &BC.rootMatrix, &boneList[boneListIndex].newMatrix);
1914 }
1915 else
1916 {
1917 Multiply_3x4Matrix(&BC.mFinalBones[child].boneMatrix, &BC.rootMatrix, &boneList[boneListIndex].matrix);
1918 }
1919 }
1920 else
1921 {
1922 // convert from 3x4 matrix to a 4x4 matrix
1923 if (HackadelicOnClient)
1924 {
1925 Multiply_3x4Matrix(&BC.mFinalBones[child].boneMatrix, &BC.mFinalBones[parent].boneMatrix, &boneList[boneListIndex].newMatrix);
1926 }
1927 else
1928 {
1929 Multiply_3x4Matrix(&BC.mFinalBones[child].boneMatrix, &BC.mFinalBones[parent].boneMatrix, &boneList[boneListIndex].matrix);
1930 }
1931 }
1932 }
1933 }
1934 else
1935 // now transform the matrix by it's parent, asumming we have a parent, and we aren't overriding the angles absolutely
1936 if (child)
1937 {
1938 Multiply_3x4Matrix(&BC.mFinalBones[child].boneMatrix, &BC.mFinalBones[parent].boneMatrix, &tbone[2]);
1939 }
1940
1941 // now multiply our resulting bone by an override matrix should we need to
1942 if (angleOverride & BONE_ANGLES_POSTMULT)
1943 {
1944 mdxaBone_t tempMatrix;
1945 memcpy (&tempMatrix,&BC.mFinalBones[child].boneMatrix, sizeof(mdxaBone_t));
1946 if (HackadelicOnClient)
1947 {
1948 Multiply_3x4Matrix(&BC.mFinalBones[child].boneMatrix, &tempMatrix, &boneList[boneListIndex].newMatrix);
1949 }
1950 else
1951 {
1952 Multiply_3x4Matrix(&BC.mFinalBones[child].boneMatrix, &tempMatrix, &boneList[boneListIndex].matrix);
1953 }
1954 }
1955 /*
1956 if (r_Ghoul2UnSqash->integer)
1957 {
1958 mdxaBone_t tempMatrix;
1959 Multiply_3x4Matrix(&tempMatrix,&BC.mFinalBones[child].boneMatrix, &skel->BasePoseMat);
1960 float maxl;
1961 maxl=VectorLength(&skel->BasePoseMat.matrix[0][0]);
1962 VectorNormalize(&tempMatrix.matrix[0][0]);
1963 VectorNormalize(&tempMatrix.matrix[1][0]);
1964 VectorNormalize(&tempMatrix.matrix[2][0]);
1965
1966 VectorScale(&tempMatrix.matrix[0][0],maxl,&tempMatrix.matrix[0][0]);
1967 VectorScale(&tempMatrix.matrix[1][0],maxl,&tempMatrix.matrix[1][0]);
1968 VectorScale(&tempMatrix.matrix[2][0],maxl,&tempMatrix.matrix[2][0]);
1969 Multiply_3x4Matrix(&BC.mFinalBones[child].boneMatrix,&tempMatrix,&skel->BasePoseMatInv);
1970 }
1971 */
1972 //rwwFIXMEFIXME: Care?
1973
1974 }
1975
G2_SetUpBolts(mdxaHeader_t * header,CGhoul2Info & ghoul2,mdxaBone_v & bonePtr,boltInfo_v & boltList)1976 void G2_SetUpBolts( mdxaHeader_t *header, CGhoul2Info &ghoul2, mdxaBone_v &bonePtr, boltInfo_v &boltList)
1977 {
1978 mdxaSkel_t *skel;
1979 mdxaSkelOffsets_t *offsets;
1980 offsets = (mdxaSkelOffsets_t *)((byte *)header + sizeof(mdxaHeader_t));
1981
1982 for (size_t i=0; i<boltList.size(); i++)
1983 {
1984 if (boltList[i].boneNumber != -1)
1985 {
1986 // figure out where the bone hirearchy info is
1987 skel = (mdxaSkel_t *)((byte *)header + sizeof(mdxaHeader_t) + offsets->offsets[boltList[i].boneNumber]);
1988 Multiply_3x4Matrix(&boltList[i].position, &bonePtr[boltList[i].boneNumber].second, &skel->BasePoseMat);
1989 }
1990 }
1991 }
1992
1993 //rww - RAGDOLL_BEGIN
1994 #define GHOUL2_RAG_STARTED 0x0010
1995 //rww - RAGDOLL_END
1996 //rwwFIXMEFIXME: Move this into the stupid header or something.
1997
G2_TransformGhoulBones(boneInfo_v & rootBoneList,mdxaBone_t & rootMatrix,CGhoul2Info & ghoul2,int time,bool smooth=true)1998 void G2_TransformGhoulBones(boneInfo_v &rootBoneList,mdxaBone_t &rootMatrix, CGhoul2Info &ghoul2, int time,bool smooth=true)
1999 {
2000 #ifdef G2_PERFORMANCE_ANALYSIS
2001 G2PerformanceTimer_G2_TransformGhoulBones.Start();
2002 G2PerformanceCounter_G2_TransformGhoulBones++;
2003 #endif
2004
2005 /*
2006 model_t *currentModel;
2007 model_t *animModel;
2008 mdxaHeader_t *aHeader;
2009
2010 //currentModel = R_GetModelByHandle(RE_RegisterModel(ghoul2.mFileName));
2011 currentModel = R_GetModelByHandle(ghoul2.mModel);
2012 assert(currentModel);
2013 assert(currentModel->mdxm);
2014
2015 animModel = R_GetModelByHandle(currentModel->mdxm->animIndex);
2016 assert(animModel);
2017 aHeader = animModel->mdxa;
2018 assert(aHeader);
2019 */
2020 model_t *currentModel = (model_t *)ghoul2.currentModel;
2021 mdxaHeader_t *aHeader = (mdxaHeader_t *)ghoul2.aHeader;
2022
2023
2024 assert(ghoul2.aHeader);
2025 assert(ghoul2.currentModel);
2026 assert(ghoul2.currentModel->mdxm);
2027 if (!aHeader->numBones)
2028 {
2029 assert(0); // this would be strange
2030 return;
2031 }
2032 if (!ghoul2.mBoneCache)
2033 {
2034 ghoul2.mBoneCache=new CBoneCache(currentModel,aHeader);
2035
2036 #ifdef _FULL_G2_LEAK_CHECKING
2037 g_Ghoul2Allocations += sizeof(*ghoul2.mBoneCache);
2038 #endif
2039 }
2040 ghoul2.mBoneCache->mod=currentModel;
2041 ghoul2.mBoneCache->header=aHeader;
2042 assert(ghoul2.mBoneCache->mBones.size()==(unsigned)aHeader->numBones);
2043
2044 ghoul2.mBoneCache->mSmoothingActive=false;
2045 ghoul2.mBoneCache->mUnsquash=false;
2046
2047 // master smoothing control
2048 if (HackadelicOnClient && smooth && !ri.Cvar_VariableIntegerValue( "dedicated" ))
2049 {
2050 ghoul2.mBoneCache->mLastTouch=ghoul2.mBoneCache->mLastLastTouch;
2051 /*
2052 float val=r_Ghoul2AnimSmooth->value;
2053 if (smooth&&val>0.0f&&val<1.0f)
2054 {
2055 // if (HackadelicOnClient)
2056 // {
2057 ghoul2.mBoneCache->mLastTouch=ghoul2.mBoneCache->mLastLastTouch;
2058 // }
2059
2060 ghoul2.mBoneCache->mSmoothFactor=val;
2061 ghoul2.mBoneCache->mSmoothingActive=true;
2062 if (r_Ghoul2UnSqashAfterSmooth->integer)
2063 {
2064 ghoul2.mBoneCache->mUnsquash=true;
2065 }
2066 }
2067 else
2068 {
2069 ghoul2.mBoneCache->mSmoothFactor=1.0f;
2070 }
2071 */
2072
2073 // master smoothing control
2074 float val=r_Ghoul2AnimSmooth->value;
2075 if (val>0.0f&&val<1.0f)
2076 {
2077 //if (ghoul2.mFlags&GHOUL2_RESERVED_FOR_RAGDOLL)
2078 #if 1
2079 if(ghoul2.mFlags & GHOUL2_CRAZY_SMOOTH)
2080 {
2081 val = 0.9f;
2082 }
2083 else if(ghoul2.mFlags & GHOUL2_RAG_STARTED)
2084 {
2085 for (size_t k=0;k<rootBoneList.size();k++)
2086 {
2087 boneInfo_t &bone=rootBoneList[k];
2088 if (bone.flags&BONE_ANGLES_RAGDOLL)
2089 {
2090 if (bone.firstCollisionTime &&
2091 bone.firstCollisionTime>time-250 &&
2092 bone.firstCollisionTime<time)
2093 {
2094 val=0.9f;//(val+0.8f)/2.0f;
2095 }
2096 else if (bone.airTime > time)
2097 {
2098 val = 0.2f;
2099 }
2100 else
2101 {
2102 val = 0.8f;
2103 }
2104 break;
2105 }
2106 }
2107 }
2108 #endif
2109
2110 // ghoul2.mBoneCache->mSmoothFactor=(val + 1.0f-pow(1.0f-val,50.0f/dif))/2.0f; // meaningless formula
2111 ghoul2.mBoneCache->mSmoothFactor=val; // meaningless formula
2112 ghoul2.mBoneCache->mSmoothingActive=true;
2113
2114 if (r_Ghoul2UnSqashAfterSmooth->integer)
2115 {
2116 ghoul2.mBoneCache->mUnsquash=true;
2117 }
2118 }
2119 }
2120 else
2121 {
2122 ghoul2.mBoneCache->mSmoothFactor=1.0f;
2123 }
2124
2125 ghoul2.mBoneCache->mCurrentTouch++;
2126
2127 //rww - RAGDOLL_BEGIN
2128 if (HackadelicOnClient)
2129 {
2130 ghoul2.mBoneCache->mLastLastTouch=ghoul2.mBoneCache->mCurrentTouch;
2131 ghoul2.mBoneCache->mCurrentTouchRender=ghoul2.mBoneCache->mCurrentTouch;
2132 }
2133 else
2134 {
2135 ghoul2.mBoneCache->mCurrentTouchRender=0;
2136 }
2137 //rww - RAGDOLL_END
2138
2139 ghoul2.mBoneCache->frameSize = 0;// can be deleted in new G2 format //(size_t)( &((mdxaFrame_t *)0)->boneIndexes[ ghoul2.aHeader->numBones ] );
2140
2141 ghoul2.mBoneCache->rootBoneList=&rootBoneList;
2142 ghoul2.mBoneCache->rootMatrix=rootMatrix;
2143 ghoul2.mBoneCache->incomingTime=time;
2144
2145 SBoneCalc &TB=ghoul2.mBoneCache->Root();
2146 TB.newFrame=0;
2147 TB.currentFrame=0;
2148 TB.backlerp=0.0f;
2149 TB.blendFrame=0;
2150 TB.blendOldFrame=0;
2151 TB.blendMode=false;
2152 TB.blendLerp=0;
2153
2154 #ifdef G2_PERFORMANCE_ANALYSIS
2155 G2Time_G2_TransformGhoulBones += G2PerformanceTimer_G2_TransformGhoulBones.End();
2156 #endif
2157 }
2158
2159
2160 #define MDX_TAG_ORIGIN 2
2161
2162 //======================================================================
2163 //
2164 // Surface Manipulation code
2165
2166
2167 // We've come across a surface that's designated as a bolt surface, process it and put it in the appropriate bolt place
G2_ProcessSurfaceBolt(mdxaBone_v & bonePtr,mdxmSurface_t * surface,int boltNum,boltInfo_v & boltList,surfaceInfo_t * surfInfo,model_t * mod)2168 void G2_ProcessSurfaceBolt(mdxaBone_v &bonePtr, mdxmSurface_t *surface, int boltNum, boltInfo_v &boltList, surfaceInfo_t *surfInfo, model_t *mod)
2169 {
2170 mdxmVertex_t *v, *vert0, *vert1, *vert2;
2171 matrix3_t axes, sides;
2172 float pTri[3][3], d;
2173 int j, k;
2174
2175 // now there are two types of tag surface - model ones and procedural generated types - lets decide which one we have here.
2176 if (surfInfo && surfInfo->offFlags == G2SURFACEFLAG_GENERATED)
2177 {
2178 int surfNumber = surfInfo->genPolySurfaceIndex & 0x0ffff;
2179 int polyNumber = (surfInfo->genPolySurfaceIndex >> 16) & 0x0ffff;
2180
2181 // find original surface our original poly was in.
2182 mdxmSurface_t *originalSurf = (mdxmSurface_t *)G2_FindSurface((void*)mod, surfNumber, surfInfo->genLod);
2183 mdxmTriangle_t *originalTriangleIndexes = (mdxmTriangle_t *)((byte*)originalSurf + originalSurf->ofsTriangles);
2184
2185 // get the original polys indexes
2186 int index0 = originalTriangleIndexes[polyNumber].indexes[0];
2187 int index1 = originalTriangleIndexes[polyNumber].indexes[1];
2188 int index2 = originalTriangleIndexes[polyNumber].indexes[2];
2189
2190 // decide where the original verts are
2191
2192 vert0 = (mdxmVertex_t *) ((byte *)originalSurf + originalSurf->ofsVerts);
2193 vert0+= index0;
2194
2195 vert1 = (mdxmVertex_t *) ((byte *)originalSurf + originalSurf->ofsVerts);
2196 vert1+= index1;
2197
2198 vert2 = (mdxmVertex_t *) ((byte *)originalSurf + originalSurf->ofsVerts);
2199 vert2+= index2;
2200
2201 // clear out the triangle verts to be
2202 VectorClear( pTri[0] );
2203 VectorClear( pTri[1] );
2204 VectorClear( pTri[2] );
2205
2206 // mdxmWeight_t *w;
2207
2208 int *piBoneRefs = (int*) ((byte*)originalSurf + originalSurf->ofsBoneReferences);
2209
2210 // now go and transform just the points we need from the surface that was hit originally
2211 // w = vert0->weights;
2212 float fTotalWeight = 0.0f;
2213 int iNumWeights = G2_GetVertWeights( vert0 );
2214 for ( k = 0 ; k < iNumWeights ; k++ )
2215 {
2216 int iBoneIndex = G2_GetVertBoneIndex( vert0, k );
2217 float fBoneWeight = G2_GetVertBoneWeight( vert0, k, fTotalWeight, iNumWeights );
2218
2219 pTri[0][0] += fBoneWeight * ( DotProduct( bonePtr[piBoneRefs[iBoneIndex]].second.matrix[0], vert0->vertCoords ) + bonePtr[piBoneRefs[iBoneIndex]].second.matrix[0][3] );
2220 pTri[0][1] += fBoneWeight * ( DotProduct( bonePtr[piBoneRefs[iBoneIndex]].second.matrix[1], vert0->vertCoords ) + bonePtr[piBoneRefs[iBoneIndex]].second.matrix[1][3] );
2221 pTri[0][2] += fBoneWeight * ( DotProduct( bonePtr[piBoneRefs[iBoneIndex]].second.matrix[2], vert0->vertCoords ) + bonePtr[piBoneRefs[iBoneIndex]].second.matrix[2][3] );
2222 }
2223 // w = vert1->weights;
2224 fTotalWeight = 0.0f;
2225 iNumWeights = G2_GetVertWeights( vert1 );
2226 for ( k = 0 ; k < iNumWeights ; k++ )
2227 {
2228 int iBoneIndex = G2_GetVertBoneIndex( vert1, k );
2229 float fBoneWeight = G2_GetVertBoneWeight( vert1, k, fTotalWeight, iNumWeights );
2230
2231 pTri[1][0] += fBoneWeight * ( DotProduct( bonePtr[piBoneRefs[iBoneIndex]].second.matrix[0], vert1->vertCoords ) + bonePtr[piBoneRefs[iBoneIndex]].second.matrix[0][3] );
2232 pTri[1][1] += fBoneWeight * ( DotProduct( bonePtr[piBoneRefs[iBoneIndex]].second.matrix[1], vert1->vertCoords ) + bonePtr[piBoneRefs[iBoneIndex]].second.matrix[1][3] );
2233 pTri[1][2] += fBoneWeight * ( DotProduct( bonePtr[piBoneRefs[iBoneIndex]].second.matrix[2], vert1->vertCoords ) + bonePtr[piBoneRefs[iBoneIndex]].second.matrix[2][3] );
2234 }
2235 // w = vert2->weights;
2236 fTotalWeight = 0.0f;
2237 iNumWeights = G2_GetVertWeights( vert2 );
2238 for ( k = 0 ; k < iNumWeights ; k++ )
2239 {
2240 int iBoneIndex = G2_GetVertBoneIndex( vert2, k );
2241 float fBoneWeight = G2_GetVertBoneWeight( vert2, k, fTotalWeight, iNumWeights );
2242
2243 pTri[2][0] += fBoneWeight * ( DotProduct( bonePtr[piBoneRefs[iBoneIndex]].second.matrix[0], vert2->vertCoords ) + bonePtr[piBoneRefs[iBoneIndex]].second.matrix[0][3] );
2244 pTri[2][1] += fBoneWeight * ( DotProduct( bonePtr[piBoneRefs[iBoneIndex]].second.matrix[1], vert2->vertCoords ) + bonePtr[piBoneRefs[iBoneIndex]].second.matrix[1][3] );
2245 pTri[2][2] += fBoneWeight * ( DotProduct( bonePtr[piBoneRefs[iBoneIndex]].second.matrix[2], vert2->vertCoords ) + bonePtr[piBoneRefs[iBoneIndex]].second.matrix[2][3] );
2246 }
2247
2248 vec3_t normal;
2249 vec3_t up;
2250 vec3_t right;
2251 vec3_t vec0, vec1;
2252 // work out baryCentricK
2253 float baryCentricK = 1.0 - (surfInfo->genBarycentricI + surfInfo->genBarycentricJ);
2254
2255 // now we have the model transformed into model space, now generate an origin.
2256 boltList[boltNum].position.matrix[0][3] = (pTri[0][0] * surfInfo->genBarycentricI) + (pTri[1][0] * surfInfo->genBarycentricJ) + (pTri[2][0] * baryCentricK);
2257 boltList[boltNum].position.matrix[1][3] = (pTri[0][1] * surfInfo->genBarycentricI) + (pTri[1][1] * surfInfo->genBarycentricJ) + (pTri[2][1] * baryCentricK);
2258 boltList[boltNum].position.matrix[2][3] = (pTri[0][2] * surfInfo->genBarycentricI) + (pTri[1][2] * surfInfo->genBarycentricJ) + (pTri[2][2] * baryCentricK);
2259
2260 // generate a normal to this new triangle
2261 VectorSubtract(pTri[0], pTri[1], vec0);
2262 VectorSubtract(pTri[2], pTri[1], vec1);
2263
2264 CrossProduct(vec0, vec1, normal);
2265 VectorNormalize(normal);
2266
2267 // forward vector
2268 boltList[boltNum].position.matrix[0][0] = normal[0];
2269 boltList[boltNum].position.matrix[1][0] = normal[1];
2270 boltList[boltNum].position.matrix[2][0] = normal[2];
2271
2272 // up will be towards point 0 of the original triangle.
2273 // so lets work it out. Vector is hit point - point 0
2274 up[0] = boltList[boltNum].position.matrix[0][3] - pTri[0][0];
2275 up[1] = boltList[boltNum].position.matrix[1][3] - pTri[0][1];
2276 up[2] = boltList[boltNum].position.matrix[2][3] - pTri[0][2];
2277
2278 // normalise it
2279 VectorNormalize(up);
2280
2281 // that's the up vector
2282 boltList[boltNum].position.matrix[0][1] = up[0];
2283 boltList[boltNum].position.matrix[1][1] = up[1];
2284 boltList[boltNum].position.matrix[2][1] = up[2];
2285
2286 // right is always straight
2287
2288 CrossProduct( normal, up, right );
2289 // that's the up vector
2290 boltList[boltNum].position.matrix[0][2] = right[0];
2291 boltList[boltNum].position.matrix[1][2] = right[1];
2292 boltList[boltNum].position.matrix[2][2] = right[2];
2293
2294
2295 }
2296 // no, we are looking at a normal model tag
2297 else
2298 {
2299 int *piBoneRefs = (int*) ((byte*)surface + surface->ofsBoneReferences);
2300
2301 // whip through and actually transform each vertex
2302 v = (mdxmVertex_t *) ((byte *)surface + surface->ofsVerts);
2303 for ( j = 0; j < 3; j++ )
2304 {
2305 // mdxmWeight_t *w;
2306
2307 VectorClear( pTri[j] );
2308 // w = v->weights;
2309
2310 const int iNumWeights = G2_GetVertWeights( v );
2311 float fTotalWeight = 0.0f;
2312 for ( k = 0 ; k < iNumWeights ; k++ )
2313 {
2314 int iBoneIndex = G2_GetVertBoneIndex( v, k );
2315 float fBoneWeight = G2_GetVertBoneWeight( v, k, fTotalWeight, iNumWeights );
2316
2317 //bone = bonePtr + piBoneRefs[w->boneIndex];
2318 pTri[j][0] += fBoneWeight * ( DotProduct( bonePtr[piBoneRefs[iBoneIndex]].second.matrix[0], v->vertCoords ) + bonePtr[piBoneRefs[iBoneIndex]].second.matrix[0][3] );
2319 pTri[j][1] += fBoneWeight * ( DotProduct( bonePtr[piBoneRefs[iBoneIndex]].second.matrix[1], v->vertCoords ) + bonePtr[piBoneRefs[iBoneIndex]].second.matrix[1][3] );
2320 pTri[j][2] += fBoneWeight * ( DotProduct( bonePtr[piBoneRefs[iBoneIndex]].second.matrix[2], v->vertCoords ) + bonePtr[piBoneRefs[iBoneIndex]].second.matrix[2][3] );
2321 }
2322
2323 v++;// = (mdxmVertex_t *)&v->weights[/*v->numWeights*/surface->maxVertBoneWeights];
2324 }
2325
2326 // clear out used arrays
2327 memset( axes, 0, sizeof( axes ) );
2328 memset( sides, 0, sizeof( sides ) );
2329
2330 // work out actual sides of the tag triangle
2331 for ( j = 0; j < 3; j++ )
2332 {
2333 sides[j][0] = pTri[(j+1)%3][0] - pTri[j][0];
2334 sides[j][1] = pTri[(j+1)%3][1] - pTri[j][1];
2335 sides[j][2] = pTri[(j+1)%3][2] - pTri[j][2];
2336 }
2337
2338 // do math trig to work out what the matrix will be from this triangle's translated position
2339 VectorNormalize2( sides[iG2_TRISIDE_LONGEST], axes[0] );
2340 VectorNormalize2( sides[iG2_TRISIDE_SHORTEST], axes[1] );
2341
2342 // project shortest side so that it is exactly 90 degrees to the longer side
2343 d = DotProduct( axes[0], axes[1] );
2344 VectorMA( axes[0], -d, axes[1], axes[0] );
2345 VectorNormalize2( axes[0], axes[0] );
2346
2347 CrossProduct( sides[iG2_TRISIDE_LONGEST], sides[iG2_TRISIDE_SHORTEST], axes[2] );
2348 VectorNormalize2( axes[2], axes[2] );
2349
2350 // set up location in world space of the origin point in out going matrix
2351 boltList[boltNum].position.matrix[0][3] = pTri[MDX_TAG_ORIGIN][0];
2352 boltList[boltNum].position.matrix[1][3] = pTri[MDX_TAG_ORIGIN][1];
2353 boltList[boltNum].position.matrix[2][3] = pTri[MDX_TAG_ORIGIN][2];
2354
2355 // copy axis to matrix - do some magic to orient minus Y to positive X and so on so bolt on stuff is oriented correctly
2356 boltList[boltNum].position.matrix[0][0] = axes[1][0];
2357 boltList[boltNum].position.matrix[0][1] = axes[0][0];
2358 boltList[boltNum].position.matrix[0][2] = -axes[2][0];
2359
2360 boltList[boltNum].position.matrix[1][0] = axes[1][1];
2361 boltList[boltNum].position.matrix[1][1] = axes[0][1];
2362 boltList[boltNum].position.matrix[1][2] = -axes[2][1];
2363
2364 boltList[boltNum].position.matrix[2][0] = axes[1][2];
2365 boltList[boltNum].position.matrix[2][1] = axes[0][2];
2366 boltList[boltNum].position.matrix[2][2] = -axes[2][2];
2367 }
2368
2369 }
2370
2371
2372 // now go through all the generated surfaces that aren't included in the model surface hierarchy and create the correct bolt info for them
G2_ProcessGeneratedSurfaceBolts(CGhoul2Info & ghoul2,mdxaBone_v & bonePtr,model_t * mod_t)2373 void G2_ProcessGeneratedSurfaceBolts(CGhoul2Info &ghoul2, mdxaBone_v &bonePtr, model_t *mod_t)
2374 {
2375 #ifdef G2_PERFORMANCE_ANALYSIS
2376 G2PerformanceTimer_G2_ProcessGeneratedSurfaceBolts.Start();
2377 #endif
2378 // look through the surfaces off the end of the pre-defined model surfaces
2379 for (size_t i=0; i< ghoul2.mSlist.size(); i++)
2380 {
2381 // only look for bolts if we are actually a generated surface, and not just an overriden one
2382 if (ghoul2.mSlist[i].offFlags & G2SURFACEFLAG_GENERATED)
2383 {
2384 // well alrighty then. Lets see if there is a bolt that is attempting to use it
2385 int boltNum = G2_Find_Bolt_Surface_Num(ghoul2.mBltlist, i, G2SURFACEFLAG_GENERATED);
2386 // yes - ok, processing time.
2387 if (boltNum != -1)
2388 {
2389 G2_ProcessSurfaceBolt(bonePtr, NULL, boltNum, ghoul2.mBltlist, &ghoul2.mSlist[i], mod_t);
2390 }
2391 }
2392 }
2393 #ifdef G2_PERFORMANCE_ANALYSIS
2394 G2Time_G2_ProcessGeneratedSurfaceBolts += G2PerformanceTimer_G2_ProcessGeneratedSurfaceBolts.End();
2395 #endif
2396 }
2397
RenderSurfaces(CRenderSurface & RS)2398 void RenderSurfaces(CRenderSurface &RS) //also ended up just ripping right from SP.
2399 {
2400 #ifdef G2_PERFORMANCE_ANALYSIS
2401 G2PerformanceTimer_RenderSurfaces.Start();
2402 #endif
2403 int i;
2404 const shader_t *shader = 0;
2405 int offFlags = 0;
2406 #ifdef _G2_GORE
2407 bool drawGore = true;
2408 #endif
2409
2410 assert(RS.currentModel);
2411 assert(RS.currentModel->mdxm);
2412 // back track and get the surfinfo struct for this surface
2413 mdxmSurface_t *surface = (mdxmSurface_t *)G2_FindSurface(RS.currentModel, RS.surfaceNum, RS.lod);
2414 mdxmHierarchyOffsets_t *surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)RS.currentModel->mdxm + sizeof(mdxmHeader_t));
2415 mdxmSurfHierarchy_t *surfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surface->thisSurfaceIndex]);
2416
2417 // see if we have an override surface in the surface list
2418 const surfaceInfo_t *surfOverride = G2_FindOverrideSurface(RS.surfaceNum, RS.rootSList);
2419
2420 // really, we should use the default flags for this surface unless it's been overriden
2421 offFlags = surfInfo->flags;
2422
2423 // set the off flags if we have some
2424 if (surfOverride)
2425 {
2426 offFlags = surfOverride->offFlags;
2427 }
2428
2429 // if this surface is not off, add it to the shader render list
2430 if (!offFlags)
2431 {
2432 if ( RS.cust_shader )
2433 {
2434 shader = RS.cust_shader;
2435 }
2436 else if ( RS.skin )
2437 {
2438 int j;
2439
2440 // match the surface name to something in the skin file
2441 shader = tr.defaultShader;
2442 for ( j = 0 ; j < RS.skin->numSurfaces ; j++ )
2443 {
2444 // the names have both been lowercased
2445 if ( !strcmp( RS.skin->surfaces[j]->name, surfInfo->name ) )
2446 {
2447 shader = (shader_t*)RS.skin->surfaces[j]->shader;
2448 break;
2449 }
2450 }
2451 }
2452 else
2453 {
2454 shader = R_GetShaderByHandle( surfInfo->shaderIndex );
2455 }
2456
2457 //rww - catch surfaces with bad shaders
2458 //assert(shader != tr.defaultShader);
2459 //Alright, this is starting to annoy me because of the state of the assets. Disabling for now.
2460 // we will add shadows even if the main object isn't visible in the view
2461 // stencil shadows can't do personal models unless I polyhedron clip
2462 //using z-fail now so can do personal models -rww
2463 if ( /*!RS.personalModel
2464 && */r_shadows->integer == 2
2465 // && RS.fogNum == 0
2466 && (RS.renderfx & RF_SHADOW_PLANE )
2467 && !(RS.renderfx & ( RF_NOSHADOW | RF_DEPTHHACK ) )
2468 && shader->sort == SS_OPAQUE )
2469 { // set the surface info to point at the where the transformed bone list is going to be for when the surface gets rendered out
2470 CRenderableSurface *newSurf = new CRenderableSurface;
2471 if (surface->numVerts >= SHADER_MAX_VERTEXES/2)
2472 { //we need numVerts*2 xyz slots free in tess to do shadow, if this surf is going to exceed that then let's try the lowest lod -rww
2473 mdxmSurface_t *lowsurface = (mdxmSurface_t *)G2_FindSurface(RS.currentModel, RS.surfaceNum, RS.currentModel->numLods-1);
2474 newSurf->surfaceData = lowsurface;
2475 }
2476 else
2477 {
2478 newSurf->surfaceData = surface;
2479 }
2480 newSurf->boneCache = RS.boneCache;
2481 R_AddDrawSurf( (surfaceType_t *)newSurf, tr.shadowShader, 0, qfalse );
2482 }
2483
2484 // projection shadows work fine with personal models
2485 if ( r_shadows->integer == 3
2486 // && RS.fogNum == 0
2487 && (RS.renderfx & RF_SHADOW_PLANE )
2488 && shader->sort == SS_OPAQUE )
2489 { // set the surface info to point at the where the transformed bone list is going to be for when the surface gets rendered out
2490 CRenderableSurface *newSurf = new CRenderableSurface;
2491 newSurf->surfaceData = surface;
2492 newSurf->boneCache = RS.boneCache;
2493 R_AddDrawSurf( (surfaceType_t *)newSurf, tr.projectionShadowShader, 0, qfalse );
2494 }
2495
2496 // don't add third_person objects if not viewing through a portal
2497 if ( !RS.personalModel )
2498 { // set the surface info to point at the where the transformed bone list is going to be for when the surface gets rendered out
2499 CRenderableSurface *newSurf = new CRenderableSurface;
2500 newSurf->surfaceData = surface;
2501 newSurf->boneCache = RS.boneCache;
2502 R_AddDrawSurf( (surfaceType_t *)newSurf, (shader_t *)shader, RS.fogNum, qfalse );
2503
2504 #ifdef _G2_GORE
2505 if (RS.gore_set && drawGore)
2506 {
2507 int curTime = G2API_GetTime(tr.refdef.time);
2508 std::pair<std::multimap<int,SGoreSurface>::iterator,std::multimap<int,SGoreSurface>::iterator> range=
2509 RS.gore_set->mGoreRecords.equal_range(RS.surfaceNum);
2510 std::multimap<int,SGoreSurface>::iterator k,kcur;
2511 CRenderableSurface *last=newSurf;
2512 for (k=range.first;k!=range.second;)
2513 {
2514 kcur=k;
2515 ++k;
2516 GoreTextureCoordinates *tex=FindGoreRecord((*kcur).second.mGoreTag);
2517 if (!tex || // it is gone, lets get rid of it
2518 (kcur->second.mDeleteTime && curTime>=kcur->second.mDeleteTime)) // out of time
2519 {
2520 if (tex)
2521 {
2522 (*tex).~GoreTextureCoordinates();
2523 //I don't know what's going on here, it should call the destructor for
2524 //this when it erases the record but sometimes it doesn't. -rww
2525 }
2526
2527 RS.gore_set->mGoreRecords.erase(kcur);
2528 }
2529 else if (tex->tex[RS.lod])
2530 {
2531 CRenderableSurface *newSurf2 = AllocRS();
2532 *newSurf2=*newSurf;
2533 newSurf2->goreChain=0;
2534 newSurf2->alternateTex=tex->tex[RS.lod];
2535 newSurf2->scale=1.0f;
2536 newSurf2->fade=1.0f;
2537 newSurf2->impactTime=1.0f; // done with
2538 int magicFactor42=500; // ms, impact time
2539 if (curTime>(*kcur).second.mGoreGrowStartTime && curTime<(*kcur).second.mGoreGrowStartTime+magicFactor42)
2540 {
2541 newSurf2->impactTime=float(curTime-(*kcur).second.mGoreGrowStartTime)/float(magicFactor42); // linear
2542 }
2543 if (curTime<(*kcur).second.mGoreGrowEndTime)
2544 {
2545 newSurf2->scale=1.0f/((curTime-(*kcur).second.mGoreGrowStartTime)*(*kcur).second.mGoreGrowFactor + (*kcur).second.mGoreGrowOffset);
2546 if (newSurf2->scale<1.0f)
2547 {
2548 newSurf2->scale=1.0f;
2549 }
2550 }
2551 shader_t *gshader;
2552 if ((*kcur).second.shader)
2553 {
2554 gshader=R_GetShaderByHandle((*kcur).second.shader);
2555 }
2556 else
2557 {
2558 gshader=R_GetShaderByHandle(goreShader);
2559 }
2560
2561 // Set fade on surf.
2562 //Only if we have a fade time set, and let us fade on rgb if we want -rww
2563 if ((*kcur).second.mDeleteTime && (*kcur).second.mFadeTime)
2564 {
2565 if ((*kcur).second.mDeleteTime - curTime < (*kcur).second.mFadeTime)
2566 {
2567 newSurf2->fade=(float)((*kcur).second.mDeleteTime - curTime)/(*kcur).second.mFadeTime;
2568 if ((*kcur).second.mFadeRGB)
2569 { //RGB fades are scaled from 2.0f to 3.0f (simply to differentiate)
2570 newSurf2->fade += 2.0f;
2571
2572 if (newSurf2->fade < 2.01f)
2573 {
2574 newSurf2->fade = 2.01f;
2575 }
2576 }
2577 }
2578 }
2579
2580 last->goreChain=newSurf2;
2581 last=newSurf2;
2582 R_AddDrawSurf( (surfaceType_t *)newSurf2,gshader, RS.fogNum, qfalse );
2583 }
2584 }
2585 }
2586 #endif
2587 }
2588 }
2589
2590 // if we are turning off all descendants, then stop this recursion now
2591 if (offFlags & G2SURFACEFLAG_NODESCENDANTS)
2592 {
2593 return;
2594 }
2595
2596 // now recursively call for the children
2597 for (i=0; i< surfInfo->numChildren; i++)
2598 {
2599 RS.surfaceNum = surfInfo->childIndexes[i];
2600 RenderSurfaces(RS);
2601 }
2602
2603 #ifdef G2_PERFORMANCE_ANALYSIS
2604 G2Time_RenderSurfaces += G2PerformanceTimer_RenderSurfaces.End();
2605 #endif
2606 }
2607
2608 // Go through the model and deal with just the surfaces that are tagged as bolt on points - this is for the server side skeleton construction
ProcessModelBoltSurfaces(int surfaceNum,surfaceInfo_v & rootSList,mdxaBone_v & bonePtr,model_t * currentModel,int lod,boltInfo_v & boltList)2609 void ProcessModelBoltSurfaces(int surfaceNum, surfaceInfo_v &rootSList,
2610 mdxaBone_v &bonePtr, model_t *currentModel, int lod, boltInfo_v &boltList)
2611 {
2612 #ifdef G2_PERFORMANCE_ANALYSIS
2613 G2PerformanceTimer_ProcessModelBoltSurfaces.Start();
2614 #endif
2615 int i;
2616 int offFlags = 0;
2617
2618 // back track and get the surfinfo struct for this surface
2619 mdxmSurface_t *surface = (mdxmSurface_t *)G2_FindSurface((void *)currentModel, surfaceNum, 0);
2620 mdxmHierarchyOffsets_t *surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)currentModel->mdxm + sizeof(mdxmHeader_t));
2621 mdxmSurfHierarchy_t *surfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surface->thisSurfaceIndex]);
2622
2623 // see if we have an override surface in the surface list
2624 surfaceInfo_t *surfOverride = G2_FindOverrideSurface(surfaceNum, rootSList);
2625
2626 // really, we should use the default flags for this surface unless it's been overriden
2627 offFlags = surfInfo->flags;
2628
2629 // set the off flags if we have some
2630 if (surfOverride)
2631 {
2632 offFlags = surfOverride->offFlags;
2633 }
2634
2635 // is this surface considered a bolt surface?
2636 if (surfInfo->flags & G2SURFACEFLAG_ISBOLT)
2637 {
2638 // well alrighty then. Lets see if there is a bolt that is attempting to use it
2639 int boltNum = G2_Find_Bolt_Surface_Num(boltList, surfaceNum, 0);
2640 // yes - ok, processing time.
2641 if (boltNum != -1)
2642 {
2643 G2_ProcessSurfaceBolt(bonePtr, surface, boltNum, boltList, surfOverride, currentModel);
2644 }
2645 }
2646
2647 // if we are turning off all descendants, then stop this recursion now
2648 if (offFlags & G2SURFACEFLAG_NODESCENDANTS)
2649 {
2650 return;
2651 }
2652
2653 // now recursively call for the children
2654 for (i=0; i< surfInfo->numChildren; i++)
2655 {
2656 ProcessModelBoltSurfaces(surfInfo->childIndexes[i], rootSList, bonePtr, currentModel, lod, boltList);
2657 }
2658
2659 #ifdef G2_PERFORMANCE_ANALYSIS
2660 G2Time_ProcessModelBoltSurfaces += G2PerformanceTimer_ProcessModelBoltSurfaces.End();
2661 #endif
2662 }
2663
2664
2665 // build the used bone list so when doing bone transforms we can determine if we need to do it or not
G2_ConstructUsedBoneList(CConstructBoneList & CBL)2666 void G2_ConstructUsedBoneList(CConstructBoneList &CBL)
2667 {
2668 int i, j;
2669 int offFlags = 0;
2670
2671 // back track and get the surfinfo struct for this surface
2672 const mdxmSurface_t *surface = (mdxmSurface_t *)G2_FindSurface((void *)CBL.currentModel, CBL.surfaceNum, 0);
2673 const mdxmHierarchyOffsets_t *surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)CBL.currentModel->mdxm + sizeof(mdxmHeader_t));
2674 const mdxmSurfHierarchy_t *surfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surface->thisSurfaceIndex]);
2675 const model_t *mod_a = R_GetModelByHandle(CBL.currentModel->mdxm->animIndex);
2676 const mdxaSkelOffsets_t *offsets = (mdxaSkelOffsets_t *)((byte *)mod_a->mdxa + sizeof(mdxaHeader_t));
2677 const mdxaSkel_t *skel, *childSkel;
2678
2679 // see if we have an override surface in the surface list
2680 const surfaceInfo_t *surfOverride = G2_FindOverrideSurface(CBL.surfaceNum, CBL.rootSList);
2681
2682 // really, we should use the default flags for this surface unless it's been overriden
2683 offFlags = surfInfo->flags;
2684
2685 // set the off flags if we have some
2686 if (surfOverride)
2687 {
2688 offFlags = surfOverride->offFlags;
2689 }
2690
2691 // if this surface is not off, add it to the shader render list
2692 if (!(offFlags & G2SURFACEFLAG_OFF))
2693 {
2694 int *bonesReferenced = (int *)((byte*)surface + surface->ofsBoneReferences);
2695 // now whip through the bones this surface uses
2696 for (i=0; i<surface->numBoneReferences;i++)
2697 {
2698 int iBoneIndex = bonesReferenced[i];
2699 CBL.boneUsedList[iBoneIndex] = 1;
2700
2701 // now go and check all the descendant bones attached to this bone and see if any have the always flag on them. If so, activate them
2702 skel = (mdxaSkel_t *)((byte *)mod_a->mdxa + sizeof(mdxaHeader_t) + offsets->offsets[iBoneIndex]);
2703
2704 // for every child bone...
2705 for (j=0; j< skel->numChildren; j++)
2706 {
2707 // get the skel data struct for each child bone of the referenced bone
2708 childSkel = (mdxaSkel_t *)((byte *)mod_a->mdxa + sizeof(mdxaHeader_t) + offsets->offsets[skel->children[j]]);
2709
2710 // does it have the always on flag on?
2711 if (childSkel->flags & G2BONEFLAG_ALWAYSXFORM)
2712 {
2713 // yes, make sure it's in the list of bones to be transformed.
2714 CBL.boneUsedList[skel->children[j]] = 1;
2715 }
2716 }
2717
2718 // now we need to ensure that the parents of this bone are actually active...
2719 //
2720 int iParentBone = skel->parent;
2721 while (iParentBone != -1)
2722 {
2723 if (CBL.boneUsedList[iParentBone]) // no need to go higher
2724 break;
2725 CBL.boneUsedList[iParentBone] = 1;
2726 skel = (mdxaSkel_t *)((byte *)mod_a->mdxa + sizeof(mdxaHeader_t) + offsets->offsets[iParentBone]);
2727 iParentBone = skel->parent;
2728 }
2729 }
2730 }
2731 else
2732 // if we are turning off all descendants, then stop this recursion now
2733 if (offFlags & G2SURFACEFLAG_NODESCENDANTS)
2734 {
2735 return;
2736 }
2737
2738 // now recursively call for the children
2739 for (i=0; i< surfInfo->numChildren; i++)
2740 {
2741 CBL.surfaceNum = surfInfo->childIndexes[i];
2742 G2_ConstructUsedBoneList(CBL);
2743 }
2744 }
2745
2746
2747 // sort all the ghoul models in this list so if they go in reference order. This will ensure the bolt on's are attached to the right place
2748 // on the previous model, since it ensures the model being attached to is built and rendered first.
2749
2750 // NOTE!! This assumes at least one model will NOT have a parent. If it does - we are screwed
G2_Sort_Models(CGhoul2Info_v & ghoul2,int * const modelList,int * const modelCount)2751 static void G2_Sort_Models(CGhoul2Info_v &ghoul2, int * const modelList, int * const modelCount)
2752 {
2753 int startPoint, endPoint;
2754 int i, boltTo, j;
2755
2756 *modelCount = 0;
2757
2758 // first walk all the possible ghoul2 models, and stuff the out array with those with no parents
2759 for (i=0; i<ghoul2.size();i++)
2760 {
2761 // have a ghoul model here?
2762 if (ghoul2[i].mModelindex == -1)
2763 {
2764 continue;
2765 }
2766
2767 if (!ghoul2[i].mValid)
2768 {
2769 continue;
2770 }
2771
2772 // are we attached to anything?
2773 if (ghoul2[i].mModelBoltLink == -1)
2774 {
2775 // no, insert us first
2776 modelList[(*modelCount)++] = i;
2777 }
2778 }
2779
2780 startPoint = 0;
2781 endPoint = *modelCount;
2782
2783 // now, using that list of parentless models, walk the descendant tree for each of them, inserting the descendents in the list
2784 while (startPoint != endPoint)
2785 {
2786 for (i=0; i<ghoul2.size(); i++)
2787 {
2788 // have a ghoul model here?
2789 if (ghoul2[i].mModelindex == -1)
2790 {
2791 continue;
2792 }
2793
2794 if (!ghoul2[i].mValid)
2795 {
2796 continue;
2797 }
2798
2799 // what does this model think it's attached to?
2800 if (ghoul2[i].mModelBoltLink != -1)
2801 {
2802 boltTo = (ghoul2[i].mModelBoltLink >> MODEL_SHIFT) & MODEL_AND;
2803 // is it any of the models we just added to the list?
2804 for (j=startPoint; j<endPoint; j++)
2805 {
2806 // is this my parent model?
2807 if (boltTo == modelList[j])
2808 {
2809 // yes, insert into list and exit now
2810 modelList[(*modelCount)++] = i;
2811 break;
2812 }
2813 }
2814 }
2815 }
2816 // update start and end points
2817 startPoint = endPoint;
2818 endPoint = *modelCount;
2819 }
2820 }
2821
G2_FindSurface_BC(const model_s * mod,int index,int lod)2822 void *G2_FindSurface_BC(const model_s *mod, int index, int lod)
2823 {
2824 assert(mod);
2825 assert(mod->mdxm);
2826
2827 // point at first lod list
2828 byte *current = (byte*)((intptr_t)mod->mdxm + (intptr_t)mod->mdxm->ofsLODs);
2829 int i;
2830
2831 //walk the lods
2832 assert(lod>=0&&lod<mod->mdxm->numLODs);
2833 for (i=0; i<lod; i++)
2834 {
2835 mdxmLOD_t *lodData = (mdxmLOD_t *)current;
2836 current += lodData->ofsEnd;
2837 }
2838
2839 // avoid the lod pointer data structure
2840 current += sizeof(mdxmLOD_t);
2841
2842 mdxmLODSurfOffset_t *indexes = (mdxmLODSurfOffset_t *)current;
2843 // we are now looking at the offset array
2844 assert(index>=0&&index<mod->mdxm->numSurfaces);
2845 current += indexes->offsets[index];
2846
2847 return (void *)current;
2848 }
2849
2850 //#define G2EVALRENDER
2851
2852 // We've come across a surface that's designated as a bolt surface, process it and put it in the appropriate bolt place
G2_ProcessSurfaceBolt2(CBoneCache & boneCache,const mdxmSurface_t * surface,int boltNum,boltInfo_v & boltList,const surfaceInfo_t * surfInfo,const model_t * mod,mdxaBone_t & retMatrix)2853 void G2_ProcessSurfaceBolt2(CBoneCache &boneCache, const mdxmSurface_t *surface, int boltNum, boltInfo_v &boltList, const surfaceInfo_t *surfInfo, const model_t *mod,mdxaBone_t &retMatrix)
2854 {
2855 mdxmVertex_t *v, *vert0, *vert1, *vert2;
2856 matrix3_t axes, sides;
2857 float pTri[3][3], d;
2858 int j, k;
2859
2860 // now there are two types of tag surface - model ones and procedural generated types - lets decide which one we have here.
2861 if (surfInfo && surfInfo->offFlags == G2SURFACEFLAG_GENERATED)
2862 {
2863 int surfNumber = surfInfo->genPolySurfaceIndex & 0x0ffff;
2864 int polyNumber = (surfInfo->genPolySurfaceIndex >> 16) & 0x0ffff;
2865
2866 // find original surface our original poly was in.
2867 mdxmSurface_t *originalSurf = (mdxmSurface_t *)G2_FindSurface_BC(mod, surfNumber, surfInfo->genLod);
2868 mdxmTriangle_t *originalTriangleIndexes = (mdxmTriangle_t *)((byte*)originalSurf + originalSurf->ofsTriangles);
2869
2870 // get the original polys indexes
2871 int index0 = originalTriangleIndexes[polyNumber].indexes[0];
2872 int index1 = originalTriangleIndexes[polyNumber].indexes[1];
2873 int index2 = originalTriangleIndexes[polyNumber].indexes[2];
2874
2875 // decide where the original verts are
2876 vert0 = (mdxmVertex_t *) ((byte *)originalSurf + originalSurf->ofsVerts);
2877 vert0+=index0;
2878
2879 vert1 = (mdxmVertex_t *) ((byte *)originalSurf + originalSurf->ofsVerts);
2880 vert1+=index1;
2881
2882 vert2 = (mdxmVertex_t *) ((byte *)originalSurf + originalSurf->ofsVerts);
2883 vert2+=index2;
2884
2885 // clear out the triangle verts to be
2886 VectorClear( pTri[0] );
2887 VectorClear( pTri[1] );
2888 VectorClear( pTri[2] );
2889 int *piBoneReferences = (int*) ((byte*)originalSurf + originalSurf->ofsBoneReferences);
2890
2891 // mdxmWeight_t *w;
2892
2893 // now go and transform just the points we need from the surface that was hit originally
2894 // w = vert0->weights;
2895 float fTotalWeight = 0.0f;
2896 int iNumWeights = G2_GetVertWeights( vert0 );
2897 for ( k = 0 ; k < iNumWeights ; k++ )
2898 {
2899 int iBoneIndex = G2_GetVertBoneIndex( vert0, k );
2900 float fBoneWeight = G2_GetVertBoneWeight( vert0, k, fTotalWeight, iNumWeights );
2901
2902 #ifdef G2EVALRENDER
2903 const mdxaBone_t &bone=boneCache.EvalRender(piBoneReferences[iBoneIndex]);
2904 #else
2905 const mdxaBone_t &bone=boneCache.Eval(piBoneReferences[iBoneIndex]);
2906 #endif
2907
2908 pTri[0][0] += fBoneWeight * ( DotProduct( bone.matrix[0], vert0->vertCoords ) + bone.matrix[0][3] );
2909 pTri[0][1] += fBoneWeight * ( DotProduct( bone.matrix[1], vert0->vertCoords ) + bone.matrix[1][3] );
2910 pTri[0][2] += fBoneWeight * ( DotProduct( bone.matrix[2], vert0->vertCoords ) + bone.matrix[2][3] );
2911 }
2912
2913 // w = vert1->weights;
2914 fTotalWeight = 0.0f;
2915 iNumWeights = G2_GetVertWeights( vert1 );
2916 for ( k = 0 ; k < iNumWeights ; k++)
2917 {
2918 int iBoneIndex = G2_GetVertBoneIndex( vert1, k );
2919 float fBoneWeight = G2_GetVertBoneWeight( vert1, k, fTotalWeight, iNumWeights );
2920
2921 #ifdef G2EVALRENDER
2922 const mdxaBone_t &bone=boneCache.EvalRender(piBoneReferences[iBoneIndex]);
2923 #else
2924 const mdxaBone_t &bone=boneCache.Eval(piBoneReferences[iBoneIndex]);
2925 #endif
2926
2927 pTri[1][0] += fBoneWeight * ( DotProduct( bone.matrix[0], vert1->vertCoords ) + bone.matrix[0][3] );
2928 pTri[1][1] += fBoneWeight * ( DotProduct( bone.matrix[1], vert1->vertCoords ) + bone.matrix[1][3] );
2929 pTri[1][2] += fBoneWeight * ( DotProduct( bone.matrix[2], vert1->vertCoords ) + bone.matrix[2][3] );
2930 }
2931
2932 // w = vert2->weights;
2933 fTotalWeight = 0.0f;
2934 iNumWeights = G2_GetVertWeights( vert2 );
2935 for ( k = 0 ; k < iNumWeights ; k++)
2936 {
2937 int iBoneIndex = G2_GetVertBoneIndex( vert2, k );
2938 float fBoneWeight = G2_GetVertBoneWeight( vert2, k, fTotalWeight, iNumWeights );
2939
2940 #ifdef G2EVALRENDER
2941 const mdxaBone_t &bone=boneCache.EvalRender(piBoneReferences[iBoneIndex]);
2942 #else
2943 const mdxaBone_t &bone=boneCache.Eval(piBoneReferences[iBoneIndex]);
2944 #endif
2945
2946 pTri[2][0] += fBoneWeight * ( DotProduct( bone.matrix[0], vert2->vertCoords ) + bone.matrix[0][3] );
2947 pTri[2][1] += fBoneWeight * ( DotProduct( bone.matrix[1], vert2->vertCoords ) + bone.matrix[1][3] );
2948 pTri[2][2] += fBoneWeight * ( DotProduct( bone.matrix[2], vert2->vertCoords ) + bone.matrix[2][3] );
2949 }
2950
2951 vec3_t normal;
2952 vec3_t up;
2953 vec3_t right;
2954 vec3_t vec0, vec1;
2955 // work out baryCentricK
2956 float baryCentricK = 1.0 - (surfInfo->genBarycentricI + surfInfo->genBarycentricJ);
2957
2958 // now we have the model transformed into model space, now generate an origin.
2959 retMatrix.matrix[0][3] = (pTri[0][0] * surfInfo->genBarycentricI) + (pTri[1][0] * surfInfo->genBarycentricJ) + (pTri[2][0] * baryCentricK);
2960 retMatrix.matrix[1][3] = (pTri[0][1] * surfInfo->genBarycentricI) + (pTri[1][1] * surfInfo->genBarycentricJ) + (pTri[2][1] * baryCentricK);
2961 retMatrix.matrix[2][3] = (pTri[0][2] * surfInfo->genBarycentricI) + (pTri[1][2] * surfInfo->genBarycentricJ) + (pTri[2][2] * baryCentricK);
2962
2963 // generate a normal to this new triangle
2964 VectorSubtract(pTri[0], pTri[1], vec0);
2965 VectorSubtract(pTri[2], pTri[1], vec1);
2966
2967 CrossProduct(vec0, vec1, normal);
2968 VectorNormalize(normal);
2969
2970 // forward vector
2971 retMatrix.matrix[0][0] = normal[0];
2972 retMatrix.matrix[1][0] = normal[1];
2973 retMatrix.matrix[2][0] = normal[2];
2974
2975 // up will be towards point 0 of the original triangle.
2976 // so lets work it out. Vector is hit point - point 0
2977 up[0] = retMatrix.matrix[0][3] - pTri[0][0];
2978 up[1] = retMatrix.matrix[1][3] - pTri[0][1];
2979 up[2] = retMatrix.matrix[2][3] - pTri[0][2];
2980
2981 // normalise it
2982 VectorNormalize(up);
2983
2984 // that's the up vector
2985 retMatrix.matrix[0][1] = up[0];
2986 retMatrix.matrix[1][1] = up[1];
2987 retMatrix.matrix[2][1] = up[2];
2988
2989 // right is always straight
2990
2991 CrossProduct( normal, up, right );
2992 // that's the up vector
2993 retMatrix.matrix[0][2] = right[0];
2994 retMatrix.matrix[1][2] = right[1];
2995 retMatrix.matrix[2][2] = right[2];
2996
2997
2998 }
2999 // no, we are looking at a normal model tag
3000 else
3001 {
3002 // whip through and actually transform each vertex
3003 v = (mdxmVertex_t *) ((byte *)surface + surface->ofsVerts);
3004 int *piBoneReferences = (int*) ((byte*)surface + surface->ofsBoneReferences);
3005 for ( j = 0; j < 3; j++ )
3006 {
3007 // mdxmWeight_t *w;
3008
3009 VectorClear( pTri[j] );
3010 // w = v->weights;
3011
3012 const int iNumWeights = G2_GetVertWeights( v );
3013
3014 float fTotalWeight = 0.0f;
3015 for ( k = 0 ; k < iNumWeights ; k++)
3016 {
3017 int iBoneIndex = G2_GetVertBoneIndex( v, k );
3018 float fBoneWeight = G2_GetVertBoneWeight( v, k, fTotalWeight, iNumWeights );
3019
3020 #ifdef G2EVALRENDER
3021 const mdxaBone_t &bone=boneCache.EvalRender(piBoneReferences[iBoneIndex]);
3022 #else
3023 const mdxaBone_t &bone=boneCache.Eval(piBoneReferences[iBoneIndex]);
3024 #endif
3025
3026 pTri[j][0] += fBoneWeight * ( DotProduct( bone.matrix[0], v->vertCoords ) + bone.matrix[0][3] );
3027 pTri[j][1] += fBoneWeight * ( DotProduct( bone.matrix[1], v->vertCoords ) + bone.matrix[1][3] );
3028 pTri[j][2] += fBoneWeight * ( DotProduct( bone.matrix[2], v->vertCoords ) + bone.matrix[2][3] );
3029 }
3030
3031 v++;// = (mdxmVertex_t *)&v->weights[/*v->numWeights*/surface->maxVertBoneWeights];
3032 }
3033
3034 // clear out used arrays
3035 memset( axes, 0, sizeof( axes ) );
3036 memset( sides, 0, sizeof( sides ) );
3037
3038 // work out actual sides of the tag triangle
3039 for ( j = 0; j < 3; j++ )
3040 {
3041 sides[j][0] = pTri[(j+1)%3][0] - pTri[j][0];
3042 sides[j][1] = pTri[(j+1)%3][1] - pTri[j][1];
3043 sides[j][2] = pTri[(j+1)%3][2] - pTri[j][2];
3044 }
3045
3046 // do math trig to work out what the matrix will be from this triangle's translated position
3047 VectorNormalize2( sides[iG2_TRISIDE_LONGEST], axes[0] );
3048 VectorNormalize2( sides[iG2_TRISIDE_SHORTEST], axes[1] );
3049
3050 // project shortest side so that it is exactly 90 degrees to the longer side
3051 d = DotProduct( axes[0], axes[1] );
3052 VectorMA( axes[0], -d, axes[1], axes[0] );
3053 VectorNormalize2( axes[0], axes[0] );
3054
3055 CrossProduct( sides[iG2_TRISIDE_LONGEST], sides[iG2_TRISIDE_SHORTEST], axes[2] );
3056 VectorNormalize2( axes[2], axes[2] );
3057
3058 // set up location in world space of the origin point in out going matrix
3059 retMatrix.matrix[0][3] = pTri[MDX_TAG_ORIGIN][0];
3060 retMatrix.matrix[1][3] = pTri[MDX_TAG_ORIGIN][1];
3061 retMatrix.matrix[2][3] = pTri[MDX_TAG_ORIGIN][2];
3062
3063 // copy axis to matrix - do some magic to orient minus Y to positive X and so on so bolt on stuff is oriented correctly
3064 retMatrix.matrix[0][0] = axes[1][0];
3065 retMatrix.matrix[0][1] = axes[0][0];
3066 retMatrix.matrix[0][2] = -axes[2][0];
3067
3068 retMatrix.matrix[1][0] = axes[1][1];
3069 retMatrix.matrix[1][1] = axes[0][1];
3070 retMatrix.matrix[1][2] = -axes[2][1];
3071
3072 retMatrix.matrix[2][0] = axes[1][2];
3073 retMatrix.matrix[2][1] = axes[0][2];
3074 retMatrix.matrix[2][2] = -axes[2][2];
3075 }
3076
3077 }
3078
G2_GetBoltMatrixLow(CGhoul2Info & ghoul2,int boltNum,const vec3_t scale,mdxaBone_t & retMatrix)3079 void G2_GetBoltMatrixLow(CGhoul2Info &ghoul2,int boltNum,const vec3_t scale,mdxaBone_t &retMatrix)
3080 {
3081 if (!ghoul2.mBoneCache)
3082 {
3083 retMatrix=identityMatrix;
3084 return;
3085 }
3086 assert(ghoul2.mBoneCache);
3087 CBoneCache &boneCache=*ghoul2.mBoneCache;
3088 assert(boneCache.mod);
3089 boltInfo_v &boltList=ghoul2.mBltlist;
3090
3091 //Raz: This was causing a client crash when rendering a model with no valid g2 bolts, such as Ragnos =]
3092 if ( boltList.size() < 1 ) {
3093 retMatrix=identityMatrix;
3094 return;
3095 }
3096
3097 assert(boltNum>=0&&boltNum<(int)boltList.size());
3098 #if 0 //rwwFIXMEFIXME: Disable this before release!!!!!! I am just trying to find a crash bug.
3099 if (boltNum < 0 || boltNum >= boltList.size())
3100 {
3101 char fName[MAX_QPATH];
3102 char mName[MAX_QPATH];
3103 int bLink = ghoul2.mModelBoltLink;
3104
3105 if (ghoul2.currentModel)
3106 {
3107 strcpy(mName, ghoul2.currentModel->name);
3108 }
3109 else
3110 {
3111 strcpy(mName, "NULL!");
3112 }
3113
3114 if (ghoul2.mFileName && ghoul2.mFileName[0])
3115 {
3116 strcpy(fName, ghoul2.mFileName);
3117 }
3118 else
3119 {
3120 strcpy(fName, "None?!");
3121 }
3122
3123 Com_Error(ERR_DROP, "Write down or save this error message, show it to Rich\nBad bolt index on model %s (filename %s), index %i boltlink %i\n", mName, fName, boltNum, bLink);
3124 }
3125 #endif
3126 if (boltList[boltNum].boneNumber>=0)
3127 {
3128 mdxaSkel_t *skel;
3129 mdxaSkelOffsets_t *offsets;
3130 offsets = (mdxaSkelOffsets_t *)((byte *)boneCache.header + sizeof(mdxaHeader_t));
3131 skel = (mdxaSkel_t *)((byte *)boneCache.header + sizeof(mdxaHeader_t) + offsets->offsets[boltList[boltNum].boneNumber]);
3132 Multiply_3x4Matrix(&retMatrix, (mdxaBone_t *)&boneCache.EvalUnsmooth(boltList[boltNum].boneNumber), &skel->BasePoseMat);
3133 }
3134 else if (boltList[boltNum].surfaceNumber>=0)
3135 {
3136 const surfaceInfo_t *surfInfo=0;
3137 {
3138 for (size_t i=0;i<ghoul2.mSlist.size();i++)
3139 {
3140 surfaceInfo_t &t=ghoul2.mSlist[i];
3141 if (t.surface==boltList[boltNum].surfaceNumber)
3142 {
3143 surfInfo=&t;
3144 }
3145 }
3146 }
3147 mdxmSurface_t *surface = 0;
3148 if (!surfInfo)
3149 {
3150 surface = (mdxmSurface_t *)G2_FindSurface_BC(boneCache.mod,boltList[boltNum].surfaceNumber, 0);
3151 }
3152 if (!surface&&surfInfo&&surfInfo->surface<10000)
3153 {
3154 surface = (mdxmSurface_t *)G2_FindSurface_BC(boneCache.mod,surfInfo->surface, 0);
3155 }
3156 G2_ProcessSurfaceBolt2(boneCache,surface,boltNum,boltList,surfInfo,(model_t *)boneCache.mod,retMatrix);
3157 }
3158 else
3159 {
3160 // we have a bolt without a bone or surface, not a huge problem but we ought to at least clear the bolt matrix
3161 retMatrix=identityMatrix;
3162 }
3163 }
3164
RootMatrix(CGhoul2Info_v & ghoul2,int time,const vec3_t scale,mdxaBone_t & retMatrix)3165 static void RootMatrix(CGhoul2Info_v &ghoul2,int time,const vec3_t scale,mdxaBone_t &retMatrix)
3166 {
3167 int i;
3168 for (i=0; i<ghoul2.size(); i++)
3169 {
3170 if (ghoul2[i].mModelindex != -1 && ghoul2[i].mValid)
3171 {
3172 if (ghoul2[i].mFlags & GHOUL2_NEWORIGIN)
3173 {
3174 mdxaBone_t bolt;
3175 mdxaBone_t tempMatrix;
3176
3177 G2_ConstructGhoulSkeleton(ghoul2,time,false,scale);
3178 G2_GetBoltMatrixLow(ghoul2[i],ghoul2[i].mNewOrigin,scale,bolt);
3179 tempMatrix.matrix[0][0]=1.0f;
3180 tempMatrix.matrix[0][1]=0.0f;
3181 tempMatrix.matrix[0][2]=0.0f;
3182 tempMatrix.matrix[0][3]=-bolt.matrix[0][3];
3183 tempMatrix.matrix[1][0]=0.0f;
3184 tempMatrix.matrix[1][1]=1.0f;
3185 tempMatrix.matrix[1][2]=0.0f;
3186 tempMatrix.matrix[1][3]=-bolt.matrix[1][3];
3187 tempMatrix.matrix[2][0]=0.0f;
3188 tempMatrix.matrix[2][1]=0.0f;
3189 tempMatrix.matrix[2][2]=1.0f;
3190 tempMatrix.matrix[2][3]=-bolt.matrix[2][3];
3191 // Inverse_Matrix(&bolt, &tempMatrix);
3192 Multiply_3x4Matrix(&retMatrix, &tempMatrix, (mdxaBone_t*)&identityMatrix);
3193 return;
3194 }
3195 }
3196 }
3197 retMatrix=identityMatrix;
3198 }
3199
3200 extern cvar_t *r_shadowRange;
bInShadowRange(vec3_t location)3201 static inline bool bInShadowRange(vec3_t location)
3202 {
3203 const float c = DotProduct( tr.viewParms.ori.axis[0], tr.viewParms.ori.origin );
3204 const float dist = DotProduct( tr.viewParms.ori.axis[0], location ) - c;
3205
3206 // return (dist < tr.distanceCull/1.5f);
3207 return (dist < r_shadowRange->value);
3208 }
3209
3210 /*
3211 ==============
3212 R_AddGHOULSurfaces
3213 ==============
3214 */
R_AddGhoulSurfaces(trRefEntity_t * ent)3215 void R_AddGhoulSurfaces( trRefEntity_t *ent ) {
3216 #ifdef G2_PERFORMANCE_ANALYSIS
3217 G2PerformanceTimer_R_AddGHOULSurfaces.Start();
3218 #endif
3219 shader_t *cust_shader = 0;
3220 #ifdef _G2_GORE
3221 shader_t *gore_shader = 0;
3222 #endif
3223 int fogNum = 0;
3224 qboolean personalModel;
3225 int cull;
3226 int i, whichLod, j;
3227 skin_t *skin;
3228 int modelCount;
3229 mdxaBone_t rootMatrix;
3230 CGhoul2Info_v &ghoul2 = *((CGhoul2Info_v *)ent->e.ghoul2);
3231
3232 if ( !ghoul2.IsValid() )
3233 {
3234 return;
3235 }
3236 // if we don't want server ghoul2 models and this is one, or we just don't want ghoul2 models at all, then return
3237 if (r_noServerGhoul2->integer)
3238 {
3239 return;
3240 }
3241 if (!G2_SetupModelPointers(ghoul2))
3242 {
3243 return;
3244 }
3245
3246 int currentTime=G2API_GetTime(tr.refdef.time);
3247
3248
3249 // cull the entire model if merged bounding box of both frames
3250 // is outside the view frustum.
3251 cull = R_GCullModel (ent );
3252 if ( cull == CULL_OUT )
3253 {
3254 return;
3255 }
3256 HackadelicOnClient=true;
3257 // are any of these models setting a new origin?
3258 RootMatrix(ghoul2,currentTime, ent->e.modelScale,rootMatrix);
3259
3260 // don't add third_person objects if not in a portal
3261 personalModel = (qboolean)((ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal);
3262
3263 int modelList[256];
3264 assert(ghoul2.size()<=255);
3265 modelList[255]=548;
3266
3267 // set up lighting now that we know we aren't culled
3268 if ( !personalModel || r_shadows->integer > 1 ) {
3269 R_SetupEntityLighting( &tr.refdef, ent );
3270 }
3271
3272 // see if we are in a fog volume
3273 fogNum = R_GComputeFogNum( ent );
3274
3275 // order sort the ghoul 2 models so bolt ons get bolted to the right model
3276 G2_Sort_Models(ghoul2, modelList, &modelCount);
3277 assert(modelList[255]==548);
3278
3279 #ifdef _G2_GORE
3280 if (goreShader == -1)
3281 {
3282 goreShader=RE_RegisterShader("gfx/damage/burnmark1");
3283 }
3284 #endif
3285
3286 // construct a world matrix for this entity
3287 G2_GenerateWorldMatrix(ent->e.angles, ent->e.origin);
3288
3289 // walk each possible model for this entity and try rendering it out
3290 for (j=0; j<modelCount; j++)
3291 {
3292 i = modelList[j];
3293 if (ghoul2[i].mValid&&!(ghoul2[i].mFlags & GHOUL2_NOMODEL)&&!(ghoul2[i].mFlags & GHOUL2_NORENDER))
3294 {
3295 //
3296 // figure out whether we should be using a custom shader for this model
3297 //
3298 skin = NULL;
3299 if (ent->e.customShader)
3300 {
3301 cust_shader = R_GetShaderByHandle(ent->e.customShader );
3302 }
3303 else
3304 {
3305 cust_shader = NULL;
3306 // figure out the custom skin thing
3307 if (ghoul2[i].mCustomSkin)
3308 {
3309 skin = R_GetSkinByHandle(ghoul2[i].mCustomSkin );
3310 }
3311 else if (ent->e.customSkin)
3312 {
3313 skin = R_GetSkinByHandle(ent->e.customSkin );
3314 }
3315 else if ( ghoul2[i].mSkin > 0 && ghoul2[i].mSkin < tr.numSkins )
3316 {
3317 skin = R_GetSkinByHandle( ghoul2[i].mSkin );
3318 }
3319 }
3320
3321 if (j&&ghoul2[i].mModelBoltLink != -1)
3322 {
3323 int boltMod = (ghoul2[i].mModelBoltLink >> MODEL_SHIFT) & MODEL_AND;
3324 int boltNum = (ghoul2[i].mModelBoltLink >> BOLT_SHIFT) & BOLT_AND;
3325 mdxaBone_t bolt;
3326 G2_GetBoltMatrixLow(ghoul2[boltMod],boltNum,ent->e.modelScale,bolt);
3327 G2_TransformGhoulBones(ghoul2[i].mBlist,bolt, ghoul2[i],currentTime);
3328 }
3329 else
3330 {
3331 G2_TransformGhoulBones(ghoul2[i].mBlist, rootMatrix, ghoul2[i],currentTime);
3332 }
3333 whichLod = G2_ComputeLOD( ent, ghoul2[i].currentModel, ghoul2[i].mLodBias );
3334 G2_FindOverrideSurface(-1,ghoul2[i].mSlist); //reset the quick surface override lookup;
3335
3336 #ifdef _G2_GORE
3337 CGoreSet *gore=0;
3338 if (ghoul2[i].mGoreSetTag)
3339 {
3340 gore=FindGoreSet(ghoul2[i].mGoreSetTag);
3341 if (!gore) // my gore is gone, so remove it
3342 {
3343 ghoul2[i].mGoreSetTag=0;
3344 }
3345 }
3346
3347 CRenderSurface RS(ghoul2[i].mSurfaceRoot, ghoul2[i].mSlist, cust_shader, fogNum, personalModel, ghoul2[i].mBoneCache, ent->e.renderfx, skin, (model_t *)ghoul2[i].currentModel, whichLod, ghoul2[i].mBltlist, gore_shader, gore);
3348 #else
3349 CRenderSurface RS(ghoul2[i].mSurfaceRoot, ghoul2[i].mSlist, cust_shader, fogNum, personalModel, ghoul2[i].mBoneCache, ent->e.renderfx, skin, (model_t *)ghoul2[i].currentModel, whichLod, ghoul2[i].mBltlist);
3350 #endif
3351 if (!personalModel && (RS.renderfx & RF_SHADOW_PLANE) && !bInShadowRange(ent->e.origin))
3352 {
3353 RS.renderfx |= RF_NOSHADOW;
3354 }
3355 RenderSurfaces(RS);
3356 }
3357 }
3358 HackadelicOnClient=false;
3359
3360 #ifdef G2_PERFORMANCE_ANALYSIS
3361 G2Time_R_AddGHOULSurfaces += G2PerformanceTimer_R_AddGHOULSurfaces.End();
3362 #endif
3363 }
3364
3365 #ifdef _G2_LISTEN_SERVER_OPT
3366 qboolean G2API_OverrideServerWithClientData(CGhoul2Info *serverInstance);
3367 #endif
3368
G2_NeedsRecalc(CGhoul2Info * ghlInfo,int frameNum)3369 bool G2_NeedsRecalc(CGhoul2Info *ghlInfo,int frameNum)
3370 {
3371 G2_SetupModelPointers(ghlInfo);
3372 // not sure if I still need this test, probably
3373 if (ghlInfo->mSkelFrameNum!=frameNum||
3374 !ghlInfo->mBoneCache||
3375 ghlInfo->mBoneCache->mod!=ghlInfo->currentModel)
3376 {
3377 #ifdef _G2_LISTEN_SERVER_OPT
3378 if (ghlInfo->entityNum != ENTITYNUM_NONE &&
3379 G2API_OverrideServerWithClientData(ghlInfo))
3380 { //if we can manage this, then we don't have to reconstruct
3381 return false;
3382 }
3383 #endif
3384 ghlInfo->mSkelFrameNum=frameNum;
3385 return true;
3386 }
3387 return false;
3388 }
3389
3390 /*
3391 ==============
3392 G2_ConstructGhoulSkeleton - builds a complete skeleton for all ghoul models in a CGhoul2Info_v class - using LOD 0
3393 ==============
3394 */
G2_ConstructGhoulSkeleton(CGhoul2Info_v & ghoul2,const int frameNum,bool checkForNewOrigin,const vec3_t scale)3395 void G2_ConstructGhoulSkeleton( CGhoul2Info_v &ghoul2,const int frameNum,bool checkForNewOrigin,const vec3_t scale)
3396 {
3397 #ifdef G2_PERFORMANCE_ANALYSIS
3398 G2PerformanceTimer_G2_ConstructGhoulSkeleton.Start();
3399 #endif
3400 int i, j;
3401 int modelCount;
3402 mdxaBone_t rootMatrix;
3403
3404 int modelList[256];
3405 assert(ghoul2.size()<=255);
3406 modelList[255]=548;
3407
3408 if (checkForNewOrigin)
3409 {
3410 RootMatrix(ghoul2,frameNum,scale,rootMatrix);
3411 }
3412 else
3413 {
3414 rootMatrix = identityMatrix;
3415 }
3416
3417 G2_Sort_Models(ghoul2, modelList, &modelCount);
3418 assert(modelList[255]==548);
3419
3420 for (j=0; j<modelCount; j++)
3421 {
3422 // get the sorted model to play with
3423 i = modelList[j];
3424
3425 if (ghoul2[i].mValid)
3426 {
3427 if (j&&ghoul2[i].mModelBoltLink != -1)
3428 {
3429 int boltMod = (ghoul2[i].mModelBoltLink >> MODEL_SHIFT) & MODEL_AND;
3430 int boltNum = (ghoul2[i].mModelBoltLink >> BOLT_SHIFT) & BOLT_AND;
3431
3432 mdxaBone_t bolt;
3433 G2_GetBoltMatrixLow(ghoul2[boltMod],boltNum,scale,bolt);
3434 G2_TransformGhoulBones(ghoul2[i].mBlist,bolt,ghoul2[i],frameNum,checkForNewOrigin);
3435 }
3436 #ifdef _G2_LISTEN_SERVER_OPT
3437 else if (ghoul2[i].entityNum == ENTITYNUM_NONE || ghoul2[i].mSkelFrameNum != frameNum)
3438 #else
3439 else
3440 #endif
3441 {
3442 G2_TransformGhoulBones(ghoul2[i].mBlist,rootMatrix,ghoul2[i],frameNum,checkForNewOrigin);
3443 }
3444 }
3445 }
3446 #ifdef G2_PERFORMANCE_ANALYSIS
3447 G2Time_G2_ConstructGhoulSkeleton += G2PerformanceTimer_G2_ConstructGhoulSkeleton.End();
3448 #endif
3449 }
3450
G2_GetVertBoneWeightNotSlow(const mdxmVertex_t * pVert,const int iWeightNum)3451 static inline float G2_GetVertBoneWeightNotSlow( const mdxmVertex_t *pVert, const int iWeightNum)
3452 {
3453 float fBoneWeight;
3454
3455 int iTemp = pVert->BoneWeightings[iWeightNum];
3456
3457 iTemp|= (pVert->uiNmWeightsAndBoneIndexes >> (iG2_BONEWEIGHT_TOPBITS_SHIFT+(iWeightNum*2)) ) & iG2_BONEWEIGHT_TOPBITS_AND;
3458
3459 fBoneWeight = fG2_BONEWEIGHT_RECIPROCAL_MULT * iTemp;
3460
3461 return fBoneWeight;
3462 }
3463
3464 //This is a slightly mangled version of the same function from the sof2sp base.
3465 //It provides a pretty significant performance increase over the existing one.
RB_SurfaceGhoul(CRenderableSurface * surf)3466 void RB_SurfaceGhoul( CRenderableSurface *surf )
3467 {
3468 #ifdef G2_PERFORMANCE_ANALYSIS
3469 G2PerformanceTimer_RB_SurfaceGhoul.Start();
3470 #endif
3471
3472 static int j, k;
3473 static int baseIndex, baseVertex;
3474 static int numVerts;
3475 static mdxmVertex_t *v;
3476 static int *triangles;
3477 static int indexes;
3478 static glIndex_t *tessIndexes;
3479 static mdxmVertexTexCoord_t *pTexCoords;
3480 static int *piBoneReferences;
3481
3482 #ifdef _G2_GORE
3483 if (surf->alternateTex)
3484 {
3485 // a gore surface ready to go.
3486
3487 /*
3488 sizeof(int)+ // num verts
3489 sizeof(int)+ // num tris
3490 sizeof(int)*newNumVerts+ // which verts to copy from original surface
3491 sizeof(float)*4*newNumVerts+ // storgage for deformed verts
3492 sizeof(float)*4*newNumVerts+ // storgage for deformed normal
3493 sizeof(float)*2*newNumVerts+ // texture coordinates
3494 sizeof(int)*newNumTris*3; // new indecies
3495 */
3496
3497 int *data=(int *)surf->alternateTex;
3498 numVerts=*data++;
3499 indexes=(*data++);
3500 // first up, sanity check our numbers
3501 RB_CheckOverflow(numVerts,indexes);
3502 indexes*=3;
3503
3504 data+=numVerts;
3505
3506 baseIndex = tess.numIndexes;
3507 baseVertex = tess.numVertexes;
3508
3509 memcpy(&tess.xyz[baseVertex][0],data,sizeof(float)*4*numVerts);
3510 data+=4*numVerts;
3511 memcpy(&tess.normal[baseVertex][0],data,sizeof(float)*4*numVerts);
3512 data+=4*numVerts;
3513 assert(numVerts>0);
3514
3515 //float *texCoords = tess.texCoords[0][baseVertex];
3516 float *texCoords = tess.texCoords[baseVertex][0];
3517 int hack = baseVertex;
3518 //rww - since the array is arranged as such we cannot increment
3519 //the relative memory position to get where we want. Maybe this
3520 //is why sof2 has the texCoords array reversed. In any case, I
3521 //am currently too lazy to get around it.
3522 //Or can you += array[.][x]+2?
3523 if (surf->scale>1.0f)
3524 {
3525 for ( j = 0; j < numVerts; j++)
3526 {
3527 texCoords[0]=((*(float *)data)-0.5f)*surf->scale+0.5f;
3528 data++;
3529 texCoords[1]=((*(float *)data)-0.5f)*surf->scale+0.5f;
3530 data++;
3531 //texCoords+=2;// Size of gore (s,t).
3532 hack++;
3533 texCoords = tess.texCoords[hack][0];
3534 }
3535 }
3536 else
3537 {
3538 for (j=0;j<numVerts;j++)
3539 {
3540 texCoords[0]=*(float *)(data++);
3541 texCoords[1]=*(float *)(data++);
3542 // texCoords+=2;// Size of gore (s,t).
3543 hack++;
3544 texCoords = tess.texCoords[hack][0];
3545 }
3546 }
3547
3548 //now check for fade overrides -rww
3549 if (surf->fade)
3550 {
3551 static int lFade;
3552 static int j;
3553
3554 if (surf->fade<1.0)
3555 {
3556 tess.fading = true;
3557 lFade = Q_ftol(254.4f*surf->fade);
3558
3559 for (j=0;j<numVerts;j++)
3560 {
3561 tess.svars.colors[j+baseVertex][3] = lFade;
3562 }
3563 }
3564 else if (surf->fade > 2.0f && surf->fade < 3.0f)
3565 { //hack to fade out on RGB if desired (don't want to add more to CRenderableSurface) -rww
3566 tess.fading = true;
3567 lFade = Q_ftol(254.4f*(surf->fade-2.0f));
3568
3569 for (j=0;j<numVerts;j++)
3570 {
3571 if (lFade < tess.svars.colors[j+baseVertex][0])
3572 { //don't set it unless the fade is less than the current r value (to avoid brightening suddenly before we start fading)
3573 tess.svars.colors[j+baseVertex][0] = tess.svars.colors[j+baseVertex][1] = tess.svars.colors[j+baseVertex][2] = lFade;
3574 }
3575
3576 //Set the alpha as well I suppose, no matter what
3577 tess.svars.colors[j+baseVertex][3] = lFade;
3578 }
3579 }
3580 }
3581
3582 glIndex_t *indexPtr = &tess.indexes[baseIndex];
3583 triangles = data;
3584 for (j = indexes ; j ; j--)
3585 {
3586 *indexPtr++ = baseVertex + (*triangles++);
3587 }
3588 tess.numIndexes += indexes;
3589 tess.numVertexes += numVerts;
3590 return;
3591 }
3592 #endif
3593
3594 // grab the pointer to the surface info within the loaded mesh file
3595 mdxmSurface_t *surface = surf->surfaceData;
3596
3597 CBoneCache *bones = surf->boneCache;
3598
3599 #ifndef _G2_GORE //we use this later, for gore
3600 delete surf;
3601 #endif
3602
3603 // first up, sanity check our numbers
3604 RB_CheckOverflow( surface->numVerts, surface->numTriangles );
3605
3606 //
3607 // deform the vertexes by the lerped bones
3608 //
3609
3610 // first up, sanity check our numbers
3611 baseVertex = tess.numVertexes;
3612 triangles = (int *) ((byte *)surface + surface->ofsTriangles);
3613 baseIndex = tess.numIndexes;
3614 #if 0
3615 indexes = surface->numTriangles * 3;
3616 for (j = 0 ; j < indexes ; j++) {
3617 tess.indexes[baseIndex + j] = baseVertex + triangles[j];
3618 }
3619 tess.numIndexes += indexes;
3620 #else
3621 indexes = surface->numTriangles; //*3; //unrolled 3 times, don't multiply
3622 tessIndexes = &tess.indexes[baseIndex];
3623 for (j = 0 ; j < indexes ; j++) {
3624 *tessIndexes++ = baseVertex + *triangles++;
3625 *tessIndexes++ = baseVertex + *triangles++;
3626 *tessIndexes++ = baseVertex + *triangles++;
3627 }
3628 tess.numIndexes += indexes*3;
3629 #endif
3630
3631 numVerts = surface->numVerts;
3632
3633 piBoneReferences = (int*) ((byte*)surface + surface->ofsBoneReferences);
3634 baseVertex = tess.numVertexes;
3635 v = (mdxmVertex_t *) ((byte *)surface + surface->ofsVerts);
3636 pTexCoords = (mdxmVertexTexCoord_t *) &v[numVerts];
3637
3638 // if (r_ghoul2fastnormals&&r_ghoul2fastnormals->integer==0)
3639 #if 0
3640 if (0)
3641 {
3642 for ( j = 0; j < numVerts; j++, baseVertex++,v++ )
3643 {
3644 const int iNumWeights = G2_GetVertWeights( v );
3645
3646 float fTotalWeight = 0.0f;
3647
3648 k=0;
3649 int iBoneIndex = G2_GetVertBoneIndex( v, k );
3650 float fBoneWeight = G2_GetVertBoneWeight( v, k, fTotalWeight, iNumWeights );
3651 const mdxaBone_t *bone = &bones->EvalRender(piBoneReferences[iBoneIndex]);
3652
3653 tess.xyz[baseVertex][0] = fBoneWeight * ( DotProduct( bone->matrix[0], v->vertCoords ) + bone->matrix[0][3] );
3654 tess.xyz[baseVertex][1] = fBoneWeight * ( DotProduct( bone->matrix[1], v->vertCoords ) + bone->matrix[1][3] );
3655 tess.xyz[baseVertex][2] = fBoneWeight * ( DotProduct( bone->matrix[2], v->vertCoords ) + bone->matrix[2][3] );
3656
3657 tess.normal[baseVertex][0] = fBoneWeight * DotProduct( bone->matrix[0], v->normal );
3658 tess.normal[baseVertex][1] = fBoneWeight * DotProduct( bone->matrix[1], v->normal );
3659 tess.normal[baseVertex][2] = fBoneWeight * DotProduct( bone->matrix[2], v->normal );
3660
3661 for ( k++ ; k < iNumWeights ; k++)
3662 {
3663 iBoneIndex = G2_GetVertBoneIndex( v, k );
3664 fBoneWeight = G2_GetVertBoneWeight( v, k, fTotalWeight, iNumWeights );
3665
3666 bone = &bones->EvalRender(piBoneReferences[iBoneIndex]);
3667
3668 tess.xyz[baseVertex][0] += fBoneWeight * ( DotProduct( bone->matrix[0], v->vertCoords ) + bone->matrix[0][3] );
3669 tess.xyz[baseVertex][1] += fBoneWeight * ( DotProduct( bone->matrix[1], v->vertCoords ) + bone->matrix[1][3] );
3670 tess.xyz[baseVertex][2] += fBoneWeight * ( DotProduct( bone->matrix[2], v->vertCoords ) + bone->matrix[2][3] );
3671
3672 tess.normal[baseVertex][0] += fBoneWeight * DotProduct( bone->matrix[0], v->normal );
3673 tess.normal[baseVertex][1] += fBoneWeight * DotProduct( bone->matrix[1], v->normal );
3674 tess.normal[baseVertex][2] += fBoneWeight * DotProduct( bone->matrix[2], v->normal );
3675 }
3676
3677 tess.texCoords[baseVertex][0][0] = pTexCoords[j].texCoords[0];
3678 tess.texCoords[baseVertex][0][1] = pTexCoords[j].texCoords[1];
3679 }
3680 }
3681 else
3682 {
3683 #endif
3684 float fTotalWeight;
3685 float fBoneWeight;
3686 float t1;
3687 float t2;
3688 const mdxaBone_t *bone;
3689 const mdxaBone_t *bone2;
3690 for ( j = 0; j < numVerts; j++, baseVertex++,v++ )
3691 {
3692
3693 bone = &bones->EvalRender(piBoneReferences[G2_GetVertBoneIndex( v, 0 )]);
3694 int iNumWeights = G2_GetVertWeights( v );
3695 tess.normal[baseVertex][0] = DotProduct( bone->matrix[0], v->normal );
3696 tess.normal[baseVertex][1] = DotProduct( bone->matrix[1], v->normal );
3697 tess.normal[baseVertex][2] = DotProduct( bone->matrix[2], v->normal );
3698
3699 if (iNumWeights==1)
3700 {
3701 tess.xyz[baseVertex][0] = ( DotProduct( bone->matrix[0], v->vertCoords ) + bone->matrix[0][3] );
3702 tess.xyz[baseVertex][1] = ( DotProduct( bone->matrix[1], v->vertCoords ) + bone->matrix[1][3] );
3703 tess.xyz[baseVertex][2] = ( DotProduct( bone->matrix[2], v->vertCoords ) + bone->matrix[2][3] );
3704 }
3705 else
3706 {
3707 fBoneWeight = G2_GetVertBoneWeightNotSlow( v, 0);
3708 if (iNumWeights==2)
3709 {
3710 bone2 = &bones->EvalRender(piBoneReferences[G2_GetVertBoneIndex( v, 1 )]);
3711 /*
3712 useless transposition
3713 tess.xyz[baseVertex][0] =
3714 v[0]*(w*(bone->matrix[0][0]-bone2->matrix[0][0])+bone2->matrix[0][0])+
3715 v[1]*(w*(bone->matrix[0][1]-bone2->matrix[0][1])+bone2->matrix[0][1])+
3716 v[2]*(w*(bone->matrix[0][2]-bone2->matrix[0][2])+bone2->matrix[0][2])+
3717 w*(bone->matrix[0][3]-bone2->matrix[0][3]) + bone2->matrix[0][3];
3718 */
3719 t1 = ( DotProduct( bone->matrix[0], v->vertCoords ) + bone->matrix[0][3] );
3720 t2 = ( DotProduct( bone2->matrix[0], v->vertCoords ) + bone2->matrix[0][3] );
3721 tess.xyz[baseVertex][0] = fBoneWeight * (t1-t2) + t2;
3722 t1 = ( DotProduct( bone->matrix[1], v->vertCoords ) + bone->matrix[1][3] );
3723 t2 = ( DotProduct( bone2->matrix[1], v->vertCoords ) + bone2->matrix[1][3] );
3724 tess.xyz[baseVertex][1] = fBoneWeight * (t1-t2) + t2;
3725 t1 = ( DotProduct( bone->matrix[2], v->vertCoords ) + bone->matrix[2][3] );
3726 t2 = ( DotProduct( bone2->matrix[2], v->vertCoords ) + bone2->matrix[2][3] );
3727 tess.xyz[baseVertex][2] = fBoneWeight * (t1-t2) + t2;
3728 }
3729 else
3730 {
3731
3732 tess.xyz[baseVertex][0] = fBoneWeight * ( DotProduct( bone->matrix[0], v->vertCoords ) + bone->matrix[0][3] );
3733 tess.xyz[baseVertex][1] = fBoneWeight * ( DotProduct( bone->matrix[1], v->vertCoords ) + bone->matrix[1][3] );
3734 tess.xyz[baseVertex][2] = fBoneWeight * ( DotProduct( bone->matrix[2], v->vertCoords ) + bone->matrix[2][3] );
3735
3736 fTotalWeight=fBoneWeight;
3737 for (k=1; k < iNumWeights-1 ; k++)
3738 {
3739 bone = &bones->EvalRender(piBoneReferences[G2_GetVertBoneIndex( v, k )]);
3740 fBoneWeight = G2_GetVertBoneWeightNotSlow( v, k);
3741 fTotalWeight += fBoneWeight;
3742
3743 tess.xyz[baseVertex][0] += fBoneWeight * ( DotProduct( bone->matrix[0], v->vertCoords ) + bone->matrix[0][3] );
3744 tess.xyz[baseVertex][1] += fBoneWeight * ( DotProduct( bone->matrix[1], v->vertCoords ) + bone->matrix[1][3] );
3745 tess.xyz[baseVertex][2] += fBoneWeight * ( DotProduct( bone->matrix[2], v->vertCoords ) + bone->matrix[2][3] );
3746 }
3747 bone = &bones->EvalRender(piBoneReferences[G2_GetVertBoneIndex( v, k )]);
3748 fBoneWeight = 1.0f-fTotalWeight;
3749
3750 tess.xyz[baseVertex][0] += fBoneWeight * ( DotProduct( bone->matrix[0], v->vertCoords ) + bone->matrix[0][3] );
3751 tess.xyz[baseVertex][1] += fBoneWeight * ( DotProduct( bone->matrix[1], v->vertCoords ) + bone->matrix[1][3] );
3752 tess.xyz[baseVertex][2] += fBoneWeight * ( DotProduct( bone->matrix[2], v->vertCoords ) + bone->matrix[2][3] );
3753 }
3754 }
3755
3756 tess.texCoords[baseVertex][0][0] = pTexCoords[j].texCoords[0];
3757 tess.texCoords[baseVertex][0][1] = pTexCoords[j].texCoords[1];
3758 }
3759 #if 0
3760 }
3761 #endif
3762
3763 #ifdef _G2_GORE
3764 CRenderableSurface *storeSurf = surf;
3765
3766 while (surf->goreChain)
3767 {
3768 surf=(CRenderableSurface *)surf->goreChain;
3769 if (surf->alternateTex)
3770 {
3771 // get a gore surface ready to go.
3772
3773 /*
3774 sizeof(int)+ // num verts
3775 sizeof(int)+ // num tris
3776 sizeof(int)*newNumVerts+ // which verts to copy from original surface
3777 sizeof(float)*4*newNumVerts+ // storgage for deformed verts
3778 sizeof(float)*4*newNumVerts+ // storgage for deformed normal
3779 sizeof(float)*2*newNumVerts+ // texture coordinates
3780 sizeof(int)*newNumTris*3; // new indecies
3781 */
3782
3783 int *data=(int *)surf->alternateTex;
3784 int gnumVerts=*data++;
3785 data++;
3786
3787 float *fdata=(float *)data;
3788 fdata+=gnumVerts;
3789 for (j=0;j<gnumVerts;j++)
3790 {
3791 assert(data[j]>=0&&data[j]<numVerts);
3792 memcpy(fdata,&tess.xyz[tess.numVertexes+data[j]][0],sizeof(float)*3);
3793 fdata+=4;
3794 }
3795 for (j=0;j<gnumVerts;j++)
3796 {
3797 assert(data[j]>=0&&data[j]<numVerts);
3798 memcpy(fdata,&tess.normal[tess.numVertexes+data[j]][0],sizeof(float)*3);
3799 fdata+=4;
3800 }
3801 }
3802 else
3803 {
3804 assert(0);
3805 }
3806
3807 }
3808
3809 // NOTE: This is required because a ghoul model might need to be rendered twice a frame (don't cringe,
3810 // it's not THAT bad), so we only delete it when doing the glow pass. Warning though, this assumes that
3811 // the glow is rendered _second_!!! If that changes, change this!
3812 extern bool g_bRenderGlowingObjects;
3813 extern bool g_bDynamicGlowSupported;
3814 if ( !tess.shader->hasGlow || g_bRenderGlowingObjects || !g_bDynamicGlowSupported || !r_DynamicGlow->integer )
3815 {
3816 delete storeSurf;
3817 }
3818 #endif
3819
3820 tess.numVertexes += surface->numVerts;
3821
3822 #ifdef G2_PERFORMANCE_ANALYSIS
3823 G2Time_RB_SurfaceGhoul += G2PerformanceTimer_RB_SurfaceGhoul.End();
3824 #endif
3825 }
3826
3827 /*
3828 =================
3829 R_LoadMDXM - load a Ghoul 2 Mesh file
3830 =================
3831 */
3832
3833 /*
3834
3835 Some information used in the creation of the JK2 - JKA bone remap table
3836
3837 These are the old bones:
3838 Complete list of all 72 bones:
3839
3840 */
3841
3842 int OldToNewRemapTable[72] = {
3843 0,// Bone 0: "model_root": Parent: "" (index -1)
3844 1,// Bone 1: "pelvis": Parent: "model_root" (index 0)
3845 2,// Bone 2: "Motion": Parent: "pelvis" (index 1)
3846 3,// Bone 3: "lfemurYZ": Parent: "pelvis" (index 1)
3847 4,// Bone 4: "lfemurX": Parent: "pelvis" (index 1)
3848 5,// Bone 5: "ltibia": Parent: "pelvis" (index 1)
3849 6,// Bone 6: "ltalus": Parent: "pelvis" (index 1)
3850 6,// Bone 7: "ltarsal": Parent: "pelvis" (index 1)
3851 7,// Bone 8: "rfemurYZ": Parent: "pelvis" (index 1)
3852 8,// Bone 9: "rfemurX": Parent: "pelvis" (index 1)
3853 9,// Bone10: "rtibia": Parent: "pelvis" (index 1)
3854 10,// Bone11: "rtalus": Parent: "pelvis" (index 1)
3855 10,// Bone12: "rtarsal": Parent: "pelvis" (index 1)
3856 11,// Bone13: "lower_lumbar": Parent: "pelvis" (index 1)
3857 12,// Bone14: "upper_lumbar": Parent: "lower_lumbar" (index 13)
3858 13,// Bone15: "thoracic": Parent: "upper_lumbar" (index 14)
3859 14,// Bone16: "cervical": Parent: "thoracic" (index 15)
3860 15,// Bone17: "cranium": Parent: "cervical" (index 16)
3861 16,// Bone18: "ceyebrow": Parent: "face_always_" (index 71)
3862 17,// Bone19: "jaw": Parent: "face_always_" (index 71)
3863 18,// Bone20: "lblip2": Parent: "face_always_" (index 71)
3864 19,// Bone21: "leye": Parent: "face_always_" (index 71)
3865 20,// Bone22: "rblip2": Parent: "face_always_" (index 71)
3866 21,// Bone23: "ltlip2": Parent: "face_always_" (index 71)
3867 22,// Bone24: "rtlip2": Parent: "face_always_" (index 71)
3868 23,// Bone25: "reye": Parent: "face_always_" (index 71)
3869 24,// Bone26: "rclavical": Parent: "thoracic" (index 15)
3870 25,// Bone27: "rhumerus": Parent: "thoracic" (index 15)
3871 26,// Bone28: "rhumerusX": Parent: "thoracic" (index 15)
3872 27,// Bone29: "rradius": Parent: "thoracic" (index 15)
3873 28,// Bone30: "rradiusX": Parent: "thoracic" (index 15)
3874 29,// Bone31: "rhand": Parent: "thoracic" (index 15)
3875 29,// Bone32: "mc7": Parent: "thoracic" (index 15)
3876 34,// Bone33: "r_d5_j1": Parent: "thoracic" (index 15)
3877 35,// Bone34: "r_d5_j2": Parent: "thoracic" (index 15)
3878 35,// Bone35: "r_d5_j3": Parent: "thoracic" (index 15)
3879 30,// Bone36: "r_d1_j1": Parent: "thoracic" (index 15)
3880 31,// Bone37: "r_d1_j2": Parent: "thoracic" (index 15)
3881 31,// Bone38: "r_d1_j3": Parent: "thoracic" (index 15)
3882 32,// Bone39: "r_d2_j1": Parent: "thoracic" (index 15)
3883 33,// Bone40: "r_d2_j2": Parent: "thoracic" (index 15)
3884 33,// Bone41: "r_d2_j3": Parent: "thoracic" (index 15)
3885 32,// Bone42: "r_d3_j1": Parent: "thoracic" (index 15)
3886 33,// Bone43: "r_d3_j2": Parent: "thoracic" (index 15)
3887 33,// Bone44: "r_d3_j3": Parent: "thoracic" (index 15)
3888 34,// Bone45: "r_d4_j1": Parent: "thoracic" (index 15)
3889 35,// Bone46: "r_d4_j2": Parent: "thoracic" (index 15)
3890 35,// Bone47: "r_d4_j3": Parent: "thoracic" (index 15)
3891 36,// Bone48: "rhang_tag_bone": Parent: "thoracic" (index 15)
3892 37,// Bone49: "lclavical": Parent: "thoracic" (index 15)
3893 38,// Bone50: "lhumerus": Parent: "thoracic" (index 15)
3894 39,// Bone51: "lhumerusX": Parent: "thoracic" (index 15)
3895 40,// Bone52: "lradius": Parent: "thoracic" (index 15)
3896 41,// Bone53: "lradiusX": Parent: "thoracic" (index 15)
3897 42,// Bone54: "lhand": Parent: "thoracic" (index 15)
3898 42,// Bone55: "mc5": Parent: "thoracic" (index 15)
3899 43,// Bone56: "l_d5_j1": Parent: "thoracic" (index 15)
3900 44,// Bone57: "l_d5_j2": Parent: "thoracic" (index 15)
3901 44,// Bone58: "l_d5_j3": Parent: "thoracic" (index 15)
3902 43,// Bone59: "l_d4_j1": Parent: "thoracic" (index 15)
3903 44,// Bone60: "l_d4_j2": Parent: "thoracic" (index 15)
3904 44,// Bone61: "l_d4_j3": Parent: "thoracic" (index 15)
3905 45,// Bone62: "l_d3_j1": Parent: "thoracic" (index 15)
3906 46,// Bone63: "l_d3_j2": Parent: "thoracic" (index 15)
3907 46,// Bone64: "l_d3_j3": Parent: "thoracic" (index 15)
3908 45,// Bone65: "l_d2_j1": Parent: "thoracic" (index 15)
3909 46,// Bone66: "l_d2_j2": Parent: "thoracic" (index 15)
3910 46,// Bone67: "l_d2_j3": Parent: "thoracic" (index 15)
3911 47,// Bone68: "l_d1_j1": Parent: "thoracic" (index 15)
3912 48,// Bone69: "l_d1_j2": Parent: "thoracic" (index 15)
3913 48,// Bone70: "l_d1_j3": Parent: "thoracic" (index 15)
3914 52// Bone71: "face_always_": Parent: "cranium" (index 17)
3915 };
3916
3917
3918 /*
3919
3920 Bone 0: "model_root":
3921 Parent: "" (index -1)
3922 #Kids: 1
3923 Child 0: (index 1), name "pelvis"
3924
3925 Bone 1: "pelvis":
3926 Parent: "model_root" (index 0)
3927 #Kids: 4
3928 Child 0: (index 2), name "Motion"
3929 Child 1: (index 3), name "lfemurYZ"
3930 Child 2: (index 7), name "rfemurYZ"
3931 Child 3: (index 11), name "lower_lumbar"
3932
3933 Bone 2: "Motion":
3934 Parent: "pelvis" (index 1)
3935 #Kids: 0
3936
3937 Bone 3: "lfemurYZ":
3938 Parent: "pelvis" (index 1)
3939 #Kids: 3
3940 Child 0: (index 4), name "lfemurX"
3941 Child 1: (index 5), name "ltibia"
3942 Child 2: (index 49), name "ltail"
3943
3944 Bone 4: "lfemurX":
3945 Parent: "lfemurYZ" (index 3)
3946 #Kids: 0
3947
3948 Bone 5: "ltibia":
3949 Parent: "lfemurYZ" (index 3)
3950 #Kids: 1
3951 Child 0: (index 6), name "ltalus"
3952
3953 Bone 6: "ltalus":
3954 Parent: "ltibia" (index 5)
3955 #Kids: 0
3956
3957 Bone 7: "rfemurYZ":
3958 Parent: "pelvis" (index 1)
3959 #Kids: 3
3960 Child 0: (index 8), name "rfemurX"
3961 Child 1: (index 9), name "rtibia"
3962 Child 2: (index 50), name "rtail"
3963
3964 Bone 8: "rfemurX":
3965 Parent: "rfemurYZ" (index 7)
3966 #Kids: 0
3967
3968 Bone 9: "rtibia":
3969 Parent: "rfemurYZ" (index 7)
3970 #Kids: 1
3971 Child 0: (index 10), name "rtalus"
3972
3973 Bone 10: "rtalus":
3974 Parent: "rtibia" (index 9)
3975 #Kids: 0
3976
3977 Bone 11: "lower_lumbar":
3978 Parent: "pelvis" (index 1)
3979 #Kids: 1
3980 Child 0: (index 12), name "upper_lumbar"
3981
3982 Bone 12: "upper_lumbar":
3983 Parent: "lower_lumbar" (index 11)
3984 #Kids: 1
3985 Child 0: (index 13), name "thoracic"
3986
3987 Bone 13: "thoracic":
3988 Parent: "upper_lumbar" (index 12)
3989 #Kids: 5
3990 Child 0: (index 14), name "cervical"
3991 Child 1: (index 24), name "rclavical"
3992 Child 2: (index 25), name "rhumerus"
3993 Child 3: (index 37), name "lclavical"
3994 Child 4: (index 38), name "lhumerus"
3995
3996 Bone 14: "cervical":
3997 Parent: "thoracic" (index 13)
3998 #Kids: 1
3999 Child 0: (index 15), name "cranium"
4000
4001 Bone 15: "cranium":
4002 Parent: "cervical" (index 14)
4003 #Kids: 1
4004 Child 0: (index 52), name "face_always_"
4005
4006 Bone 16: "ceyebrow":
4007 Parent: "face_always_" (index 52)
4008 #Kids: 0
4009
4010 Bone 17: "jaw":
4011 Parent: "face_always_" (index 52)
4012 #Kids: 0
4013
4014 Bone 18: "lblip2":
4015 Parent: "face_always_" (index 52)
4016 #Kids: 0
4017
4018 Bone 19: "leye":
4019 Parent: "face_always_" (index 52)
4020 #Kids: 0
4021
4022 Bone 20: "rblip2":
4023 Parent: "face_always_" (index 52)
4024 #Kids: 0
4025
4026 Bone 21: "ltlip2":
4027 Parent: "face_always_" (index 52)
4028 #Kids: 0
4029
4030 Bone 22: "rtlip2":
4031 Parent: "face_always_" (index 52)
4032 #Kids: 0
4033
4034 Bone 23: "reye":
4035 Parent: "face_always_" (index 52)
4036 #Kids: 0
4037
4038 Bone 24: "rclavical":
4039 Parent: "thoracic" (index 13)
4040 #Kids: 0
4041
4042 Bone 25: "rhumerus":
4043 Parent: "thoracic" (index 13)
4044 #Kids: 2
4045 Child 0: (index 26), name "rhumerusX"
4046 Child 1: (index 27), name "rradius"
4047
4048 Bone 26: "rhumerusX":
4049 Parent: "rhumerus" (index 25)
4050 #Kids: 0
4051
4052 Bone 27: "rradius":
4053 Parent: "rhumerus" (index 25)
4054 #Kids: 9
4055 Child 0: (index 28), name "rradiusX"
4056 Child 1: (index 29), name "rhand"
4057 Child 2: (index 30), name "r_d1_j1"
4058 Child 3: (index 31), name "r_d1_j2"
4059 Child 4: (index 32), name "r_d2_j1"
4060 Child 5: (index 33), name "r_d2_j2"
4061 Child 6: (index 34), name "r_d4_j1"
4062 Child 7: (index 35), name "r_d4_j2"
4063 Child 8: (index 36), name "rhang_tag_bone"
4064
4065 Bone 28: "rradiusX":
4066 Parent: "rradius" (index 27)
4067 #Kids: 0
4068
4069 Bone 29: "rhand":
4070 Parent: "rradius" (index 27)
4071 #Kids: 0
4072
4073 Bone 30: "r_d1_j1":
4074 Parent: "rradius" (index 27)
4075 #Kids: 0
4076
4077 Bone 31: "r_d1_j2":
4078 Parent: "rradius" (index 27)
4079 #Kids: 0
4080
4081 Bone 32: "r_d2_j1":
4082 Parent: "rradius" (index 27)
4083 #Kids: 0
4084
4085 Bone 33: "r_d2_j2":
4086 Parent: "rradius" (index 27)
4087 #Kids: 0
4088
4089 Bone 34: "r_d4_j1":
4090 Parent: "rradius" (index 27)
4091 #Kids: 0
4092
4093 Bone 35: "r_d4_j2":
4094 Parent: "rradius" (index 27)
4095 #Kids: 0
4096
4097 Bone 36: "rhang_tag_bone":
4098 Parent: "rradius" (index 27)
4099 #Kids: 0
4100
4101 Bone 37: "lclavical":
4102 Parent: "thoracic" (index 13)
4103 #Kids: 0
4104
4105 Bone 38: "lhumerus":
4106 Parent: "thoracic" (index 13)
4107 #Kids: 2
4108 Child 0: (index 39), name "lhumerusX"
4109 Child 1: (index 40), name "lradius"
4110
4111 Bone 39: "lhumerusX":
4112 Parent: "lhumerus" (index 38)
4113 #Kids: 0
4114
4115 Bone 40: "lradius":
4116 Parent: "lhumerus" (index 38)
4117 #Kids: 9
4118 Child 0: (index 41), name "lradiusX"
4119 Child 1: (index 42), name "lhand"
4120 Child 2: (index 43), name "l_d4_j1"
4121 Child 3: (index 44), name "l_d4_j2"
4122 Child 4: (index 45), name "l_d2_j1"
4123 Child 5: (index 46), name "l_d2_j2"
4124 Child 6: (index 47), name "l_d1_j1"
4125 Child 7: (index 48), name "l_d1_j2"
4126 Child 8: (index 51), name "lhang_tag_bone"
4127
4128 Bone 41: "lradiusX":
4129 Parent: "lradius" (index 40)
4130 #Kids: 0
4131
4132 Bone 42: "lhand":
4133 Parent: "lradius" (index 40)
4134 #Kids: 0
4135
4136 Bone 43: "l_d4_j1":
4137 Parent: "lradius" (index 40)
4138 #Kids: 0
4139
4140 Bone 44: "l_d4_j2":
4141 Parent: "lradius" (index 40)
4142 #Kids: 0
4143
4144 Bone 45: "l_d2_j1":
4145 Parent: "lradius" (index 40)
4146 #Kids: 0
4147
4148 Bone 46: "l_d2_j2":
4149 Parent: "lradius" (index 40)
4150 #Kids: 0
4151
4152 Bone 47: "l_d1_j1":
4153 Parent: "lradius" (index 40)
4154 #Kids: 0
4155
4156 Bone 48: "l_d1_j2":
4157 Parent: "lradius" (index 40)
4158 #Kids: 0
4159
4160 Bone 49: "ltail":
4161 Parent: "lfemurYZ" (index 3)
4162 #Kids: 0
4163
4164 Bone 50: "rtail":
4165 Parent: "rfemurYZ" (index 7)
4166 #Kids: 0
4167
4168 Bone 51: "lhang_tag_bone":
4169 Parent: "lradius" (index 40)
4170 #Kids: 0
4171
4172 Bone 52: "face_always_":
4173 Parent: "cranium" (index 15)
4174 #Kids: 8
4175 Child 0: (index 16), name "ceyebrow"
4176 Child 1: (index 17), name "jaw"
4177 Child 2: (index 18), name "lblip2"
4178 Child 3: (index 19), name "leye"
4179 Child 4: (index 20), name "rblip2"
4180 Child 5: (index 21), name "ltlip2"
4181 Child 6: (index 22), name "rtlip2"
4182 Child 7: (index 23), name "reye"
4183
4184
4185
4186 */
4187
4188
R_LoadMDXM(model_t * mod,void * buffer,const char * mod_name,qboolean & bAlreadyCached)4189 qboolean R_LoadMDXM( model_t *mod, void *buffer, const char *mod_name, qboolean &bAlreadyCached ) {
4190 int i,l, j;
4191 mdxmHeader_t *pinmodel, *mdxm;
4192 mdxmLOD_t *lod;
4193 mdxmSurface_t *surf;
4194 int version;
4195 int size;
4196 mdxmSurfHierarchy_t *surfInfo;
4197
4198 #ifdef Q3_BIG_ENDIAN
4199 int k;
4200 mdxmTriangle_t *tri;
4201 mdxmVertex_t *v;
4202 int *boneRef;
4203 mdxmLODSurfOffset_t *indexes;
4204 mdxmVertexTexCoord_t *pTexCoords;
4205 mdxmHierarchyOffsets_t *surfIndexes;
4206 #endif
4207
4208 pinmodel= (mdxmHeader_t *)buffer;
4209 //
4210 // read some fields from the binary, but only LittleLong() them when we know this wasn't an already-cached model...
4211 //
4212 version = (pinmodel->version);
4213 size = (pinmodel->ofsEnd);
4214
4215 if (!bAlreadyCached)
4216 {
4217 LL(version);
4218 LL(size);
4219 }
4220
4221 if (version != MDXM_VERSION) {
4222 ri.Printf( PRINT_ALL, S_COLOR_YELLOW "R_LoadMDXM: %s has wrong version (%i should be %i)\n",
4223 mod_name, version, MDXM_VERSION);
4224 return qfalse;
4225 }
4226
4227 mod->type = MOD_MDXM;
4228 mod->dataSize += size;
4229
4230 qboolean bAlreadyFound = qfalse;
4231 mdxm = mod->mdxm = (mdxmHeader_t*) //Hunk_Alloc( size );
4232 RE_RegisterModels_Malloc(size, buffer, mod_name, &bAlreadyFound, TAG_MODEL_GLM);
4233
4234 assert(bAlreadyCached == bAlreadyFound);
4235
4236 if (!bAlreadyFound)
4237 {
4238 // horrible new hackery, if !bAlreadyFound then we've just done a tag-morph, so we need to set the
4239 // bool reference passed into this function to true, to tell the caller NOT to do an ri.FS_Freefile since
4240 // we've hijacked that memory block...
4241 //
4242 // Aaaargh. Kill me now...
4243 //
4244 bAlreadyCached = qtrue;
4245 assert( mdxm == buffer );
4246 // memcpy( mdxm, buffer, size ); // and don't do this now, since it's the same thing
4247
4248 LL(mdxm->ident);
4249 LL(mdxm->version);
4250 LL(mdxm->numBones);
4251 LL(mdxm->numLODs);
4252 LL(mdxm->ofsLODs);
4253 LL(mdxm->numSurfaces);
4254 LL(mdxm->ofsSurfHierarchy);
4255 LL(mdxm->ofsEnd);
4256 }
4257
4258 // first up, go load in the animation file we need that has the skeletal animation info for this model
4259 mdxm->animIndex = RE_RegisterModel(va ("%s.gla",mdxm->animName));
4260
4261 if (!mdxm->animIndex)
4262 {
4263 ri.Printf( PRINT_ALL, S_COLOR_YELLOW "R_LoadMDXM: missing animation file %s for mesh %s\n", mdxm->animName, mdxm->name);
4264 return qfalse;
4265 }
4266
4267 mod->numLods = mdxm->numLODs -1 ; //copy this up to the model for ease of use - it wil get inced after this.
4268
4269 if (bAlreadyFound)
4270 {
4271 return qtrue; // All done. Stop, go no further, do not LittleLong(), do not pass Go...
4272 }
4273
4274 bool isAnOldModelFile = false;
4275 if (mdxm->numBones == 72 && strstr(mdxm->animName,"_humanoid") )
4276 {
4277 isAnOldModelFile = true;
4278 }
4279
4280 surfInfo = (mdxmSurfHierarchy_t *)( (byte *)mdxm + mdxm->ofsSurfHierarchy);
4281 #ifdef Q3_BIG_ENDIAN
4282 surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)mdxm + sizeof(mdxmHeader_t));
4283 #endif
4284 for ( i = 0 ; i < mdxm->numSurfaces ; i++)
4285 {
4286 LL(surfInfo->flags);
4287 LL(surfInfo->numChildren);
4288 LL(surfInfo->parentIndex);
4289
4290 Q_strlwr(surfInfo->name); //just in case
4291 if ( !strcmp( &surfInfo->name[strlen(surfInfo->name)-4],"_off") )
4292 {
4293 surfInfo->name[strlen(surfInfo->name)-4]=0; //remove "_off" from name
4294 }
4295
4296 // do all the children indexs
4297 for (j=0; j<surfInfo->numChildren; j++)
4298 {
4299 LL(surfInfo->childIndexes[j]);
4300 }
4301
4302 shader_t *sh;
4303 // get the shader name
4304 sh = R_FindShader( surfInfo->shader, lightmapsNone, stylesDefault, qtrue );
4305 // insert it in the surface list
4306 if ( sh->defaultShader )
4307 {
4308 surfInfo->shaderIndex = 0;
4309 }
4310 else
4311 {
4312 surfInfo->shaderIndex = sh->index;
4313 }
4314
4315 RE_RegisterModels_StoreShaderRequest(mod_name, &surfInfo->shader[0], &surfInfo->shaderIndex);
4316
4317 #ifdef Q3_BIG_ENDIAN
4318 // swap the surface offset
4319 LL(surfIndexes->offsets[i]);
4320 assert(surfInfo == (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[i]));
4321 #endif
4322
4323 // find the next surface
4324 surfInfo = (mdxmSurfHierarchy_t *)( (byte *)surfInfo + (size_t)( &((mdxmSurfHierarchy_t *)0)->childIndexes[ surfInfo->numChildren ] ));
4325 }
4326
4327 // swap all the LOD's (we need to do the middle part of this even for intel, because of shader reg and err-check)
4328 lod = (mdxmLOD_t *) ( (byte *)mdxm + mdxm->ofsLODs );
4329 for ( l = 0 ; l < mdxm->numLODs ; l++)
4330 {
4331 int triCount = 0;
4332
4333 LL(lod->ofsEnd);
4334 // swap all the surfaces
4335 surf = (mdxmSurface_t *) ( (byte *)lod + sizeof (mdxmLOD_t) + (mdxm->numSurfaces * sizeof(mdxmLODSurfOffset_t)) );
4336 for ( i = 0 ; i < mdxm->numSurfaces ; i++)
4337 {
4338 LL(surf->thisSurfaceIndex);
4339 LL(surf->ofsHeader);
4340 LL(surf->numVerts);
4341 LL(surf->ofsVerts);
4342 LL(surf->numTriangles);
4343 LL(surf->ofsTriangles);
4344 LL(surf->numBoneReferences);
4345 LL(surf->ofsBoneReferences);
4346 LL(surf->ofsEnd);
4347
4348 triCount += surf->numTriangles;
4349
4350 if ( surf->numVerts > SHADER_MAX_VERTEXES ) {
4351 Com_Error (ERR_DROP, "R_LoadMDXM: %s has more than %i verts on a surface (%i)",
4352 mod_name, SHADER_MAX_VERTEXES, surf->numVerts );
4353 }
4354 if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) {
4355 Com_Error (ERR_DROP, "R_LoadMDXM: %s has more than %i triangles on a surface (%i)",
4356 mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles );
4357 }
4358
4359 // change to surface identifier
4360 surf->ident = SF_MDX;
4361 // register the shaders
4362 #ifdef Q3_BIG_ENDIAN
4363 // swap the LOD offset
4364 indexes = (mdxmLODSurfOffset_t *)((byte *)lod + sizeof(mdxmLOD_t));
4365 LL(indexes->offsets[surf->thisSurfaceIndex]);
4366
4367 // do all the bone reference data
4368 boneRef = (int *) ( (byte *)surf + surf->ofsBoneReferences );
4369 for ( j = 0 ; j < surf->numBoneReferences ; j++ )
4370 {
4371 LL(boneRef[j]);
4372 }
4373
4374 // swap all the triangles
4375 tri = (mdxmTriangle_t *) ( (byte *)surf + surf->ofsTriangles );
4376 for ( j = 0 ; j < surf->numTriangles ; j++, tri++ )
4377 {
4378 LL(tri->indexes[0]);
4379 LL(tri->indexes[1]);
4380 LL(tri->indexes[2]);
4381 }
4382
4383 // swap all the vertexes
4384 v = (mdxmVertex_t *) ( (byte *)surf + surf->ofsVerts );
4385 pTexCoords = (mdxmVertexTexCoord_t *) &v[surf->numVerts];
4386
4387 for ( j = 0 ; j < surf->numVerts ; j++ )
4388 {
4389 LF(v->normal[0]);
4390 LF(v->normal[1]);
4391 LF(v->normal[2]);
4392
4393 LF(v->vertCoords[0]);
4394 LF(v->vertCoords[1]);
4395 LF(v->vertCoords[2]);
4396
4397 LF(pTexCoords[j].texCoords[0]);
4398 LF(pTexCoords[j].texCoords[1]);
4399
4400 LL(v->uiNmWeightsAndBoneIndexes);
4401
4402 v++;
4403 }
4404 #endif
4405
4406 if (isAnOldModelFile)
4407 {
4408 int *boneRef = (int *) ( (byte *)surf + surf->ofsBoneReferences );
4409 for ( j = 0 ; j < surf->numBoneReferences ; j++ )
4410 {
4411 assert(boneRef[j] >= 0 && boneRef[j] < 72);
4412 if (boneRef[j] >= 0 && boneRef[j] < 72)
4413 {
4414 boneRef[j]=OldToNewRemapTable[boneRef[j]];
4415 }
4416 else
4417 {
4418 boneRef[j]=0;
4419 }
4420 }
4421 }
4422 // find the next surface
4423 surf = (mdxmSurface_t *)( (byte *)surf + surf->ofsEnd );
4424 }
4425 // find the next LOD
4426 lod = (mdxmLOD_t *)( (byte *)lod + lod->ofsEnd );
4427 }
4428 return qtrue;
4429 }
4430
4431 //#define CREATE_LIMB_HIERARCHY
4432
4433 #ifdef CREATE_LIMB_HIERARCHY
4434
4435 #define NUM_ROOTPARENTS 4
4436 #define NUM_OTHERPARENTS 12
4437 #define NUM_BOTTOMBONES 4
4438
4439 #define CHILD_PADDING 4 //I don't know, I guess this can be changed.
4440
4441 static const char *rootParents[NUM_ROOTPARENTS] =
4442 {
4443 "rfemurYZ",
4444 "rhumerus",
4445 "lfemurYZ",
4446 "lhumerus"
4447 };
4448
4449 static const char *otherParents[NUM_OTHERPARENTS] =
4450 {
4451 "rhumerusX",
4452 "rradius",
4453 "rradiusX",
4454 "lhumerusX",
4455 "lradius",
4456 "lradiusX",
4457 "rfemurX",
4458 "rtibia",
4459 "rtalus",
4460 "lfemurX",
4461 "ltibia",
4462 "ltalus"
4463 };
4464
4465 static const char *bottomBones[NUM_BOTTOMBONES] =
4466 {
4467 "rtarsal",
4468 "rhand",
4469 "ltarsal",
4470 "lhand"
4471 };
4472
BoneIsRootParent(char * name)4473 qboolean BoneIsRootParent(char *name)
4474 {
4475 int i = 0;
4476
4477 while (i < NUM_ROOTPARENTS)
4478 {
4479 if (!Q_stricmp(name, rootParents[i]))
4480 {
4481 return qtrue;
4482 }
4483
4484 i++;
4485 }
4486
4487 return qfalse;
4488 }
4489
BoneIsOtherParent(char * name)4490 qboolean BoneIsOtherParent(char *name)
4491 {
4492 int i = 0;
4493
4494 while (i < NUM_OTHERPARENTS)
4495 {
4496 if (!Q_stricmp(name, otherParents[i]))
4497 {
4498 return qtrue;
4499 }
4500
4501 i++;
4502 }
4503
4504 return qfalse;
4505 }
4506
BoneIsBottom(char * name)4507 qboolean BoneIsBottom(char *name)
4508 {
4509 int i = 0;
4510
4511 while (i < NUM_BOTTOMBONES)
4512 {
4513 if (!Q_stricmp(name, bottomBones[i]))
4514 {
4515 return qtrue;
4516 }
4517
4518 i++;
4519 }
4520
4521 return qfalse;
4522 }
4523
ShiftMemoryDown(mdxaSkelOffsets_t * offsets,mdxaHeader_t * mdxa,int boneIndex,byte ** endMarker)4524 void ShiftMemoryDown(mdxaSkelOffsets_t *offsets, mdxaHeader_t *mdxa, int boneIndex, byte **endMarker)
4525 {
4526 int i = 0;
4527
4528 //where the next bone starts
4529 byte *nextBone = ((byte *)mdxa + sizeof(mdxaHeader_t) + offsets->offsets[boneIndex+1]);
4530 int size = (*endMarker - nextBone);
4531
4532 memmove((nextBone+CHILD_PADDING), nextBone, size);
4533 memset(nextBone, 0, CHILD_PADDING);
4534 *endMarker += CHILD_PADDING;
4535 //Move the whole thing down CHILD_PADDING amount in memory, clear the new preceding space, and increment the end pointer.
4536
4537 i = boneIndex+1;
4538
4539 //Now add CHILD_PADDING amount to every offset beginning at the offset of the bone that was moved.
4540 while (i < mdxa->numBones)
4541 {
4542 offsets->offsets[i] += CHILD_PADDING;
4543 i++;
4544 }
4545
4546 mdxa->ofsFrames += CHILD_PADDING;
4547 mdxa->ofsCompBonePool += CHILD_PADDING;
4548 mdxa->ofsEnd += CHILD_PADDING;
4549 //ofsSkel does not need to be updated because we are only moving memory after that point.
4550 }
4551
4552 //Proper/desired hierarchy list
4553 static const char *BoneHierarchyList[] =
4554 {
4555 "lfemurYZ",
4556 "lfemurX",
4557 "ltibia",
4558 "ltalus",
4559 "ltarsal",
4560
4561 "rfemurYZ",
4562 "rfemurX",
4563 "rtibia",
4564 "rtalus",
4565 "rtarsal",
4566
4567 "lhumerus",
4568 "lhumerusX",
4569 "lradius",
4570 "lradiusX",
4571 "lhand",
4572
4573 "rhumerus",
4574 "rhumerusX",
4575 "rradius",
4576 "rradiusX",
4577 "rhand",
4578
4579 0
4580 };
4581
4582 //Gets the index of a child or parent. If child is passed as qfalse then parent is assumed.
BoneParentChildIndex(mdxaHeader_t * mdxa,mdxaSkelOffsets_t * offsets,mdxaSkel_t * boneInfo,qboolean child)4583 int BoneParentChildIndex(mdxaHeader_t *mdxa, mdxaSkelOffsets_t *offsets, mdxaSkel_t *boneInfo, qboolean child)
4584 {
4585 int i = 0;
4586 int matchindex = -1;
4587 mdxaSkel_t *bone;
4588 const char *match = NULL;
4589
4590 while (BoneHierarchyList[i])
4591 {
4592 if (!Q_stricmp(boneInfo->name, BoneHierarchyList[i]))
4593 { //we have a match, the slot above this will be our desired parent. (or below for child)
4594 if (child)
4595 {
4596 match = BoneHierarchyList[i+1];
4597 }
4598 else
4599 {
4600 match = BoneHierarchyList[i-1];
4601 }
4602 break;
4603 }
4604 i++;
4605 }
4606
4607 if (!match)
4608 { //no good
4609 return -1;
4610 }
4611
4612 i = 0;
4613
4614 while (i < mdxa->numBones)
4615 {
4616 bone = (mdxaSkel_t *)((byte *)mdxa + sizeof(mdxaHeader_t) + offsets->offsets[i]);
4617
4618 if (bone && !Q_stricmp(bone->name, match))
4619 { //this is the one
4620 matchindex = i;
4621 break;
4622 }
4623
4624 i++;
4625 }
4626
4627 return matchindex;
4628 }
4629 #endif //CREATE_LIMB_HIERARCHY
4630
4631 /*
4632 =================
4633 R_LoadMDXA - load a Ghoul 2 animation file
4634 =================
4635 */
R_LoadMDXA(model_t * mod,void * buffer,const char * mod_name,qboolean & bAlreadyCached)4636 qboolean R_LoadMDXA( model_t *mod, void *buffer, const char *mod_name, qboolean &bAlreadyCached ) {
4637
4638 mdxaHeader_t *pinmodel, *mdxa;
4639 int version;
4640 int size;
4641 #ifdef CREATE_LIMB_HIERARCHY
4642 int oSize = 0;
4643 byte *sizeMarker;
4644 #endif
4645 #ifdef Q3_BIG_ENDIAN
4646 int j, k, i;
4647 mdxaSkel_t *boneInfo;
4648 mdxaSkelOffsets_t *offsets;
4649 int maxBoneIndex = 0;
4650 mdxaCompQuatBone_t *pCompBonePool;
4651 unsigned short *pwIn;
4652 mdxaIndex_t *pIndex;
4653 int tmp;
4654 #endif
4655
4656 pinmodel = (mdxaHeader_t *)buffer;
4657 //
4658 // read some fields from the binary, but only LittleLong() them when we know this wasn't an already-cached model...
4659 //
4660 version = (pinmodel->version);
4661 size = (pinmodel->ofsEnd);
4662
4663 if (!bAlreadyCached)
4664 {
4665 LL(version);
4666 LL(size);
4667 }
4668
4669 if (version != MDXA_VERSION) {
4670 ri.Printf( PRINT_ALL, S_COLOR_YELLOW "R_LoadMDXA: %s has wrong version (%i should be %i)\n",
4671 mod_name, version, MDXA_VERSION);
4672 return qfalse;
4673 }
4674
4675 mod->type = MOD_MDXA;
4676 mod->dataSize += size;
4677
4678 qboolean bAlreadyFound = qfalse;
4679
4680 #ifdef CREATE_LIMB_HIERARCHY
4681 oSize = size;
4682
4683 int childNumber = (NUM_ROOTPARENTS + NUM_OTHERPARENTS);
4684 size += (childNumber*(CHILD_PADDING*8)); //Allocate us some extra space so we can shift memory down.
4685 #endif //CREATE_LIMB_HIERARCHY
4686
4687 mdxa = mod->mdxa = (mdxaHeader_t*) //Hunk_Alloc( size );
4688 RE_RegisterModels_Malloc(size,
4689 #ifdef CREATE_LIMB_HIERARCHY
4690 NULL, // I think this'll work, can't really test on PC
4691 #else
4692 buffer,
4693 #endif
4694 mod_name, &bAlreadyFound, TAG_MODEL_GLA);
4695
4696 assert(bAlreadyCached == bAlreadyFound); // I should probably eliminate 'bAlreadyFound', but wtf?
4697
4698 if (!bAlreadyFound)
4699 {
4700 #ifdef CREATE_LIMB_HIERARCHY
4701 memcpy( mdxa, buffer, oSize );
4702 #else
4703 // horrible new hackery, if !bAlreadyFound then we've just done a tag-morph, so we need to set the
4704 // bool reference passed into this function to true, to tell the caller NOT to do an ri.FS_Freefile since
4705 // we've hijacked that memory block...
4706 //
4707 // Aaaargh. Kill me now...
4708 //
4709 bAlreadyCached = qtrue;
4710 assert( mdxa == buffer );
4711 // memcpy( mdxa, buffer, size ); // and don't do this now, since it's the same thing
4712 #endif
4713 LL(mdxa->ident);
4714 LL(mdxa->version);
4715 //LF(mdxa->fScale);
4716 LL(mdxa->numFrames);
4717 LL(mdxa->ofsFrames);
4718 LL(mdxa->numBones);
4719 LL(mdxa->ofsCompBonePool);
4720 LL(mdxa->ofsSkel);
4721 LL(mdxa->ofsEnd);
4722 }
4723
4724 #ifdef CREATE_LIMB_HIERARCHY
4725 if (!bAlreadyFound)
4726 {
4727 mdxaSkel_t *boneParent;
4728 #if 0 //#ifdef _M_IX86
4729 mdxaSkel_t *boneInfo;
4730 int i, k;
4731 #endif
4732
4733 sizeMarker = (byte *)mdxa + mdxa->ofsEnd;
4734
4735 //rww - This is probably temporary until we put actual hierarchy in for the models.
4736 //It is necessary for the correct operation of ragdoll.
4737 mdxaSkelOffsets_t *offsets = (mdxaSkelOffsets_t *)((byte *)mdxa + sizeof(mdxaHeader_t));
4738
4739 for ( i = 0 ; i < mdxa->numBones ; i++)
4740 {
4741 boneInfo = (mdxaSkel_t *)((byte *)mdxa + sizeof(mdxaHeader_t) + offsets->offsets[i]);
4742
4743 if (boneInfo)
4744 {
4745 char *bname = boneInfo->name;
4746
4747 if (BoneIsRootParent(bname))
4748 { //These are the main parent bones. We don't want to change their parents, but we want to give them children.
4749 ShiftMemoryDown(offsets, mdxa, i, &sizeMarker);
4750
4751 boneInfo = (mdxaSkel_t *)((byte *)mdxa + sizeof(mdxaHeader_t) + offsets->offsets[i]);
4752
4753 int newChild = BoneParentChildIndex(mdxa, offsets, boneInfo, qtrue);
4754
4755 if (newChild != -1)
4756 {
4757 boneInfo->numChildren++;
4758 boneInfo->children[boneInfo->numChildren-1] = newChild;
4759 }
4760 else
4761 {
4762 assert(!"Failed to find matching child for bone in hierarchy creation");
4763 }
4764 }
4765 else if (BoneIsOtherParent(bname) || BoneIsBottom(bname))
4766 {
4767 if (!BoneIsBottom(bname))
4768 { //unless it's last in the chain it has the next bone as a child.
4769 ShiftMemoryDown(offsets, mdxa, i, &sizeMarker);
4770
4771 boneInfo = (mdxaSkel_t *)((byte *)mdxa + sizeof(mdxaHeader_t) + offsets->offsets[i]);
4772
4773 int newChild = BoneParentChildIndex(mdxa, offsets, boneInfo, qtrue);
4774
4775 if (newChild != -1)
4776 {
4777 boneInfo->numChildren++;
4778 boneInfo->children[boneInfo->numChildren-1] = newChild;
4779 }
4780 else
4781 {
4782 assert(!"Failed to find matching child for bone in hierarchy creation");
4783 }
4784 }
4785
4786 //Before we set the parent we want to remove this as a child for whoever was parenting it.
4787 int oldParent = boneInfo->parent;
4788
4789 if (oldParent > -1)
4790 {
4791 boneParent = (mdxaSkel_t *)((byte *)mdxa + sizeof(mdxaHeader_t) + offsets->offsets[oldParent]);
4792 }
4793 else
4794 {
4795 boneParent = NULL;
4796 }
4797
4798 if (boneParent)
4799 {
4800 k = 0;
4801
4802 while (k < boneParent->numChildren)
4803 {
4804 if (boneParent->children[k] == i)
4805 { //this bone is the child
4806 k++;
4807 while (k < boneParent->numChildren)
4808 {
4809 boneParent->children[k-1] = boneParent->children[k];
4810 k++;
4811 }
4812 boneParent->children[k-1] = 0;
4813 boneParent->numChildren--;
4814 break;
4815 }
4816 k++;
4817 }
4818 }
4819
4820 //Now that we have cleared the original parent of ownership, mark the bone's new parent.
4821 int newParent = BoneParentChildIndex(mdxa, offsets, boneInfo, qfalse);
4822
4823 if (newParent != -1)
4824 {
4825 boneInfo->parent = newParent;
4826 }
4827 else
4828 {
4829 assert(!"Failed to find matching parent for bone in hierarchy creation");
4830 }
4831 }
4832 }
4833 }
4834 }
4835 #endif //CREATE_LIMB_HIERARCHY
4836
4837 if ( mdxa->numFrames < 1 ) {
4838 ri.Printf( PRINT_ALL, S_COLOR_YELLOW "R_LoadMDXA: %s has no frames\n", mod_name );
4839 return qfalse;
4840 }
4841
4842 if (bAlreadyFound)
4843 {
4844 return qtrue; // All done, stop here, do not LittleLong() etc. Do not pass go...
4845 }
4846
4847 #ifdef Q3_BIG_ENDIAN
4848 // swap the bone info
4849 offsets = (mdxaSkelOffsets_t *)((byte *)mdxa + sizeof(mdxaHeader_t));
4850 for ( i = 0; i < mdxa->numBones ; i++ )
4851 {
4852 LL(offsets->offsets[i]);
4853 boneInfo = (mdxaSkel_t *)((byte *)mdxa + sizeof(mdxaHeader_t) + offsets->offsets[i]);
4854 LL(boneInfo->flags);
4855 LL(boneInfo->parent);
4856 for ( j = 0; j < 3; j++ )
4857 {
4858 for ( k = 0; k < 4; k++)
4859 {
4860 LF(boneInfo->BasePoseMat.matrix[j][k]);
4861 LF(boneInfo->BasePoseMatInv.matrix[j][k]);
4862 }
4863 }
4864 LL(boneInfo->numChildren);
4865
4866 for (k=0; k<boneInfo->numChildren; k++)
4867 {
4868 LL(boneInfo->children[k]);
4869 }
4870 }
4871
4872 // Determine the amount of compressed bones.
4873
4874 // Find the largest index by iterating through all frames.
4875 // It is not guaranteed that the compressed bone pool resides
4876 // at the end of the file.
4877 for(i = 0; i < mdxa->numFrames; i++){
4878 for(j = 0; j < mdxa->numBones; j++){
4879 k = (i * mdxa->numBones * 3) + (j * 3); // iOffsetToIndex
4880 pIndex = (mdxaIndex_t *) ((byte *)mdxa + mdxa->ofsFrames + k);
4881 tmp = (pIndex->iIndex[2] << 16) + (pIndex->iIndex[1] << 8) + (pIndex->iIndex[0]);
4882
4883 if(maxBoneIndex < tmp){
4884 maxBoneIndex = tmp;
4885 }
4886 }
4887 }
4888
4889 // Swap the compressed bones.
4890 pCompBonePool = (mdxaCompQuatBone_t *) ((byte *)mdxa + mdxa->ofsCompBonePool);
4891 for ( i = 0 ; i <= maxBoneIndex ; i++ )
4892 {
4893 pwIn = (unsigned short *) pCompBonePool[i].Comp;
4894
4895 for ( k = 0 ; k < 7 ; k++ )
4896 LS(pwIn[k]);
4897 }
4898 #endif
4899 return qtrue;
4900 }
4901
4902
4903
4904
4905
4906
4907
4908