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 &currentFrame,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&&currentFrame<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&&currentFrame<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&&currentFrame<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&&currentFrame<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&&currentFrame<numFramesInFile);
1218 					}
1219 					else
1220 					{
1221 						currentFrame = bone.endFrame+1;
1222 						assert(currentFrame>=0&&currentFrame<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&&currentFrame<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&&currentFrame<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&&currentFrame<numFramesInFile);
1320 		newFrame = currentFrame;
1321 		assert(newFrame>=0&&newFrame<numFramesInFile);
1322 		lerp = 0;
1323 
1324 	}
1325 	assert(currentFrame>=0&&currentFrame<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