DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
model_alias.c File Reference
#include "quakedef.h"
#include "image.h"
#include "r_shadow.h"
#include "mod_skeletal_animatevertices_generic.h"
+ Include dependency graph for model_alias.c:

Go to the source code of this file.

Macros

#define BOUNDF(VALUE, MIN, MAX)
 
#define BOUNDI(VALUE, MIN, MAX)
 
#define PSKQUATNEGATIONS
 

Functions

static qbool Mod_Alias_CalculateBoundingBox (void)
 
int Mod_Alias_GetExtendedTagInfoForIndex (const model_t *model, unsigned int skin, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
 
int Mod_Alias_GetTagIndexForName (const model_t *model, unsigned int skin, const char *tagname)
 
int Mod_Alias_GetTagMatrix (const model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
 
static void Mod_Alias_MorphMesh_CompileFrames (void)
 
void Mod_AliasInit (void)
 
void Mod_BuildAliasSkinsFromSkinFiles (texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
 
static void Mod_BuildBaseBonePoses (void)
 
static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
 
void Mod_DARKPLACESMODEL_Load (model_t *mod, void *buffer, void *bufferend)
 
void Mod_IDP0_Load (model_t *mod, void *buffer, void *bufferend)
 
void Mod_IDP2_Load (model_t *mod, void *buffer, void *bufferend)
 
void Mod_IDP3_Load (model_t *mod, void *buffer, void *bufferend)
 
void Mod_INTERQUAKEMODEL_Load (model_t *mod, void *buffer, void *bufferend)
 
static void Mod_MD3_AnimateVertices (const model_t *RESTRICT model, const frameblend_t *RESTRICT frameblend, const skeleton_t *skeleton, float *RESTRICT vertex3f, float *RESTRICT normal3f, float *RESTRICT svector3f, float *RESTRICT tvector3f)
 
static void Mod_MDL_AnimateVertices (const model_t *RESTRICT model, const frameblend_t *RESTRICT frameblend, const skeleton_t *skeleton, float *RESTRICT vertex3f, float *RESTRICT normal3f, float *RESTRICT svector3f, float *RESTRICT tvector3f)
 
static void Mod_MDL_LoadFrames (unsigned char *datapointer, int inverts, int *vertremap)
 
static void Mod_MDLMD2MD3_TraceBox (model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
 
static void Mod_MDLMD2MD3_TraceLine (model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
 
void Mod_PSKMODEL_Load (model_t *mod, void *buffer, void *bufferend)
 
static int Mod_Skeletal_AddBlend (model_t *model, const blendweights_t *newweights)
 
static void Mod_Skeletal_AnimateVertices (const model_t *RESTRICT model, const frameblend_t *RESTRICT frameblend, const skeleton_t *skeleton, float *RESTRICT vertex3f, float *RESTRICT normal3f, float *RESTRICT svector3f, float *RESTRICT tvector3f)
 
voidMod_Skeletal_AnimateVertices_AllocBuffers (size_t nbytes)
 
void Mod_Skeletal_BuildTransforms (const model_t *RESTRICT model, const frameblend_t *RESTRICT frameblend, const skeleton_t *skeleton, float *RESTRICT bonepose, float *RESTRICT boneposerelative)
 
static int Mod_Skeletal_CompressBlend (model_t *model, const int *newindex, const float *newinfluence)
 
void Mod_Skeletal_FreeBuffers (void)
 
void Mod_ZYMOTICMODEL_Load (model_t *mod, void *buffer, void *bufferend)
 

Variables

cvar_t mod_alias_force_animated = {CF_CLIENT | CF_SERVER, "mod_alias_force_animated", "", "if set to an non-empty string, overrides the is-animated flag of any alias models (for benchmarking)"}
 
cvar_t mod_alias_supporttagscale = {CF_CLIENT | CF_SERVER, "mod_alias_supporttagscale", "1", "support scaling factors in bone/tag attachment matrices as supported by MD3"}
 
float mod_md3_sin [320]
 
static voidMod_Skeletal_AnimateVertices_bonepose = NULL
 
static size_t Mod_Skeletal_AnimateVertices_maxbonepose = 0
 
cvar_t r_nolerp_list
 
cvar_t r_skeletal_debugbone = {CF_CLIENT, "r_skeletal_debugbone", "-1", "development cvar for testing skeletal model code"}
 
cvar_t r_skeletal_debugbonecomponent = {CF_CLIENT, "r_skeletal_debugbonecomponent", "3", "development cvar for testing skeletal model code"}
 
cvar_t r_skeletal_debugbonevalue = {CF_CLIENT, "r_skeletal_debugbonevalue", "100", "development cvar for testing skeletal model code"}
 
cvar_t r_skeletal_debugtranslatex = {CF_CLIENT, "r_skeletal_debugtranslatex", "1", "development cvar for testing skeletal model code"}
 
cvar_t r_skeletal_debugtranslatey = {CF_CLIENT, "r_skeletal_debugtranslatey", "1", "development cvar for testing skeletal model code"}
 
cvar_t r_skeletal_debugtranslatez = {CF_CLIENT, "r_skeletal_debugtranslatez", "1", "development cvar for testing skeletal model code"}
 

Macro Definition Documentation

◆ BOUNDF

#define BOUNDF ( VALUE,
MIN,
MAX )
Value:
if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%f exceeds %f - %f)", loadmodel->name, VALUE, MIN, MAX);
void Host_Error(const char *error,...)
Definition host.c:85
model_t * loadmodel
char name[MAX_QPATH]

Definition at line 971 of file model_alias.c.

◆ BOUNDI

#define BOUNDI ( VALUE,
MIN,
MAX )
Value:
if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%d exceeds %d - %d)", loadmodel->name, VALUE, MIN, MAX);

Definition at line 970 of file model_alias.c.

Referenced by Mod_IDP0_Load().

◆ PSKQUATNEGATIONS

#define PSKQUATNEGATIONS

Definition at line 2539 of file model_alias.c.

Function Documentation

◆ Mod_Alias_CalculateBoundingBox()

static qbool Mod_Alias_CalculateBoundingBox ( void )
static

Definition at line 626 of file model_alias.c.

627{
628 int vnum;
629 qbool firstvertex = true;
630 float dist, yawradius, radius;
631 float *v;
632 qbool isanimated = false;
635 yawradius = 0;
636 radius = 0;
638 {
639 float *vertex3f, *refvertex3f;
640 frameblend_t frameblend[MAX_FRAMEBLENDS];
641 memset(frameblend, 0, sizeof(frameblend));
642 frameblend[0].lerp = 1;
643 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]) * 2);
644 refvertex3f = NULL;
645 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
646 {
647 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
648 if (!refvertex3f)
649 {
650 // make a copy of the first frame for comparing all others
651 refvertex3f = vertex3f + loadmodel->surfmesh.num_vertices * 3;
652 memcpy(refvertex3f, vertex3f, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
653 }
654 else
655 {
656 if (!isanimated && memcmp(refvertex3f, vertex3f, loadmodel->surfmesh.num_vertices * sizeof(float[3])))
657 isanimated = true;
658 }
659 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
660 {
661 if (firstvertex)
662 {
663 firstvertex = false;
666 }
667 else
668 {
669 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
670 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
671 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
672 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
673 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
674 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
675 }
676 dist = v[0] * v[0] + v[1] * v[1];
677 if (yawradius < dist)
678 yawradius = dist;
679 dist += v[2] * v[2];
680 if (radius < dist)
681 radius = dist;
682 }
683 }
684 if (vertex3f)
685 Mem_Free(vertex3f);
686 }
687 else
688 {
689 for (vnum = 0, v = loadmodel->surfmesh.data_vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
690 {
691 if (firstvertex)
692 {
693 firstvertex = false;
696 }
697 else
698 {
699 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
700 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
701 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
702 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
703 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
704 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
705 }
706 dist = v[0] * v[0] + v[1] * v[1];
707 if (yawradius < dist)
708 yawradius = dist;
709 dist += v[2] * v[2];
710 if (radius < dist)
711 radius = dist;
712 }
713 }
714 radius = sqrt(radius);
715 yawradius = sqrt(yawradius);
716 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
717 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
722 loadmodel->radius = radius;
723 loadmodel->radius2 = radius * radius;
724 return isanimated;
725}
#define MAX_FRAMEBLENDS
Definition client.h:309
const GLdouble * v
Definition glquake.h:762
#define VectorClear(a)
Definition mathlib.h:97
#define VectorCopy(in, out)
Definition mathlib.h:101
float sqrt(float f)
#define NULL
Definition qtypes.h:12
bool qbool
Definition qtypes.h:9
float lerp
Definition client.h:313
int subframe
Definition client.h:312
float radius2
void(* AnimateVertices)(const struct model_s *RESTRICT model, const struct frameblend_s *RESTRICT frameblend, const struct skeleton_s *skeleton, float *RESTRICT vertex3f, float *RESTRICT normal3f, float *RESTRICT svector3f, float *RESTRICT tvector3f)
surfmesh_t surfmesh
vec3_t rotatedmins
vec3_t yawmaxs
vec3_t rotatedmaxs
float radius
vec3_t normalmaxs
int num_poses
struct mempool_s * mempool
vec3_t yawmins
vec3_t normalmins
float * data_vertex3f
#define Mem_Free(mem)
Definition zone.h:96
#define Mem_Alloc(pool, size)
Definition zone.h:92

References model_t::AnimateVertices, surfmesh_t::data_vertex3f, frameblend_t::lerp, loadmodel, MAX_FRAMEBLENDS, Mem_Alloc, Mem_Free, model_t::mempool, model_t::normalmaxs, model_t::normalmins, NULL, model_t::num_poses, surfmesh_t::num_vertices, model_t::radius, model_t::radius2, model_t::rotatedmaxs, model_t::rotatedmins, sqrt(), frameblend_t::subframe, model_t::surfmesh, v, VectorClear, VectorCopy, model_t::yawmaxs, and model_t::yawmins.

Referenced by Mod_DARKPLACESMODEL_Load(), Mod_IDP0_Load(), Mod_IDP2_Load(), Mod_IDP3_Load(), Mod_INTERQUAKEMODEL_Load(), Mod_PSKMODEL_Load(), and Mod_ZYMOTICMODEL_Load().

◆ Mod_Alias_GetExtendedTagInfoForIndex()

int Mod_Alias_GetExtendedTagInfoForIndex ( const model_t * model,
unsigned int skin,
const frameblend_t * frameblend,
const skeleton_t * skeleton,
int tagindex,
int * parentindex,
const char ** tagname,
matrix4x4_t * tag_localmatrix )

Definition at line 528 of file model_alias.c.

529{
530 int blendindex;
531 int k;
532 float lerp;
533 matrix4x4_t bonematrix;
534 matrix4x4_t blendmatrix;
535 const float *input;
536 float blendtag[12];
537
538 if (skeleton && skeleton->relativetransforms)
539 {
540 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
541 return 1;
542 *parentindex = skeleton->model->data_bones[tagindex].parent;
543 *tagname = skeleton->model->data_bones[tagindex].name;
544 *tag_localmatrix = skeleton->relativetransforms[tagindex];
545 return 0;
546 }
547 else if (model->num_bones)
548 {
549 if (tagindex < 0 || tagindex >= model->num_bones)
550 return 1;
551 *parentindex = model->data_bones[tagindex].parent;
552 *tagname = model->data_bones[tagindex].name;
553 Matrix4x4_Clear(&blendmatrix);
554 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
555 {
556 lerp = frameblend[blendindex].lerp;
557 Matrix4x4_FromBonePose7s(&bonematrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
558 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
559 }
560 *tag_localmatrix = blendmatrix;
561 return 0;
562 }
563 else if (model->num_tags)
564 {
565 if (tagindex < 0 || tagindex >= model->num_tags)
566 return 1;
567 *parentindex = -1;
568 *tagname = model->data_tags[tagindex].name;
569 for (k = 0;k < 12;k++)
570 blendtag[k] = 0;
571 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
572 {
573 lerp = frameblend[blendindex].lerp;
574 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
575 for (k = 0;k < 12;k++)
576 blendtag[k] += input[k] * lerp;
577 }
578 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
579 return 0;
580 }
581
582 return 2;
583}
string model
void Matrix4x4_FromBonePose7s(matrix4x4_t *m, float originscale, const short *pose7s)
Definition matrixlib.c:1599
void Matrix4x4_Clear(matrix4x4_t *out)
Definition matrixlib.c:483
void Matrix4x4_FromArray12FloatGL(matrix4x4_t *out, const float in[12])
Definition matrixlib.c:1352
void Matrix4x4_Accumulate(matrix4x4_t *out, matrix4x4_t *in, double weight)
Definition matrixlib.c:491
const struct model_s * model
Definition protocol.h:425
struct matrix4x4_s * relativetransforms
Definition protocol.h:426

References frameblend_t::lerp, Matrix4x4_Accumulate(), Matrix4x4_Clear(), Matrix4x4_FromArray12FloatGL(), Matrix4x4_FromBonePose7s(), MAX_FRAMEBLENDS, model, skeleton_t::model, skeleton_t::relativetransforms, and frameblend_t::subframe.

Referenced by CL_GetExtendedTagInfo(), and SV_GetExtendedTagInfo().

◆ Mod_Alias_GetTagIndexForName()

int Mod_Alias_GetTagIndexForName ( const model_t * model,
unsigned int skin,
const char * tagname )

Definition at line 585 of file model_alias.c.

586{
587 int i;
588 if(skin >= (unsigned int)model->numskins)
589 skin = 0;
590 if (model->num_bones)
591 for (i = 0;i < model->num_bones;i++)
592 if (!strcasecmp(tagname, model->data_bones[i].name))
593 return i + 1;
594 if (model->num_tags)
595 for (i = 0;i < model->num_tags;i++)
596 if (!strcasecmp(tagname, model->data_tags[i].name))
597 return i + 1;
598 return 0;
599}
float skin
int i

References i, model, and skin.

Referenced by CL_GetTagIndex(), SV_GetTagIndex(), VM_CL_setattachment(), VM_CL_skel_find_bone(), VM_SV_setattachment(), and VM_SV_skel_find_bone().

◆ Mod_Alias_GetTagMatrix()

int Mod_Alias_GetTagMatrix ( const model_t * model,
const frameblend_t * frameblend,
const skeleton_t * skeleton,
int tagindex,
matrix4x4_t * outmatrix )

Definition at line 461 of file model_alias.c.

462{
463 matrix4x4_t temp;
464 matrix4x4_t parentbonematrix;
465 matrix4x4_t tempbonematrix;
466 matrix4x4_t bonematrix;
467 matrix4x4_t blendmatrix;
468 int blendindex;
469 int parenttagindex;
470 int k;
471 float lerp;
472 const float *input;
473 float blendtag[12];
474 *outmatrix = identitymatrix;
475 if (skeleton && skeleton->relativetransforms)
476 {
477 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
478 return 4;
479 *outmatrix = skeleton->relativetransforms[tagindex];
480 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
481 {
482 temp = *outmatrix;
483 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
484 }
485 }
486 else if (model->num_bones)
487 {
488 if (tagindex < 0 || tagindex >= model->num_bones)
489 return 4;
490 Matrix4x4_Clear(&blendmatrix);
491 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
492 {
493 lerp = frameblend[blendindex].lerp;
494 Matrix4x4_FromBonePose7s(&bonematrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
495 parenttagindex = tagindex;
496 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
497 {
498 Matrix4x4_FromBonePose7s(&parentbonematrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
499 tempbonematrix = bonematrix;
500 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
501 }
502 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
503 }
504 *outmatrix = blendmatrix;
505 }
506 else if (model->num_tags)
507 {
508 if (tagindex < 0 || tagindex >= model->num_tags)
509 return 4;
510 for (k = 0;k < 12;k++)
511 blendtag[k] = 0;
512 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
513 {
514 lerp = frameblend[blendindex].lerp;
515 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
516 for (k = 0;k < 12;k++)
517 blendtag[k] += input[k] * lerp;
518 }
519 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
520 }
521
523 Matrix4x4_Normalize3(outmatrix, outmatrix);
524
525 return 0;
526}
void Matrix4x4_Concat(matrix4x4_t *out, const matrix4x4_t *in1, const matrix4x4_t *in2)
Definition matrixlib.c:83
void Matrix4x4_Normalize3(matrix4x4_t *out, matrix4x4_t *in1)
Definition matrixlib.c:508
const matrix4x4_t identitymatrix
Definition matrixlib.c:9
cvar_t mod_alias_supporttagscale
Definition model_alias.c:39
int integer
Definition cvar.h:73

References identitymatrix, cvar_t::integer, frameblend_t::lerp, Matrix4x4_Accumulate(), Matrix4x4_Clear(), Matrix4x4_Concat(), Matrix4x4_FromArray12FloatGL(), Matrix4x4_FromBonePose7s(), Matrix4x4_Normalize3(), MAX_FRAMEBLENDS, mod_alias_supporttagscale, model, skeleton_t::model, skeleton_t::relativetransforms, and frameblend_t::subframe.

Referenced by CL_GetEntityLocalTagMatrix(), CL_UpdateNetworkEntity(), and SV_GetEntityLocalTagMatrix().

◆ Mod_Alias_MorphMesh_CompileFrames()

static void Mod_Alias_MorphMesh_CompileFrames ( void )
static

Definition at line 727 of file model_alias.c.

728{
729 int i, j;
730 frameblend_t frameblend[MAX_FRAMEBLENDS];
731 unsigned char *datapointer;
732 memset(frameblend, 0, sizeof(frameblend));
733 frameblend[0].lerp = 1;
734 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
735 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
736 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
737 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
738 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
740 // this counts down from the last frame to the first so that the final data in surfmesh is for frame zero (which is what the renderer expects to be there)
741 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
742 {
743 frameblend[0].subframe = i;
746 // encode the svector and tvector in 3 byte format for permanent storage
747 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
748 {
751 }
752 }
753}
cvar_t r_smoothnormals_areaweighting
Definition gl_rmain.c:229
#define VectorScaleCast(in, scale, outtype, out)
Definition mathlib.h:112
void Mod_BuildTextureVectorsFromNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const float *texcoord2f, const float *normal3f, const int *elements, float *svector3f, float *tvector3f, qbool areaweighting)
struct texvecvertex_s * data_morphtexvecvertex
float * data_svector3f
int * data_element3i
float * data_tvector3f
int num_triangles
int num_morphframes
float * data_texcoordtexture2f
float * data_normal3f

References model_t::AnimateVertices, surfmesh_t::data_element3i, surfmesh_t::data_morphtexvecvertex, surfmesh_t::data_normal3f, surfmesh_t::data_svector3f, surfmesh_t::data_texcoordtexture2f, surfmesh_t::data_tvector3f, surfmesh_t::data_vertex3f, i, cvar_t::integer, frameblend_t::lerp, loadmodel, MAX_FRAMEBLENDS, Mem_Alloc, model_t::mempool, Mod_BuildTextureVectorsFromNormals(), NULL, surfmesh_t::num_morphframes, surfmesh_t::num_triangles, surfmesh_t::num_vertices, r_smoothnormals_areaweighting, frameblend_t::subframe, model_t::surfmesh, and VectorScaleCast.

Referenced by Mod_IDP0_Load(), Mod_IDP2_Load(), and Mod_IDP3_Load().

◆ Mod_AliasInit()

void Mod_AliasInit ( void )

Definition at line 189 of file model_alias.c.

190{
191 int i;
200 for (i = 0;i < 320;i++)
201 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
202#ifdef SSE_POSSIBLE
203 if(Sys_HaveSSE())
204 {
205 Con_Printf("Skeletal animation uses SSE code path\n");
206 r_skeletal_use_sse_defined = true;
207 Cvar_RegisterVariable(&r_skeletal_use_sse);
208 }
209 else
210 Con_Printf("Skeletal animation uses generic code path (SSE disabled or not detected)\n");
211#else
212 Con_Printf("Skeletal animation uses generic code path (SSE not compiled in)\n");
213#endif
214}
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
void Cvar_RegisterVariable(cvar_t *variable)
registers a cvar that already has the name, string, and optionally the archive elements set.
Definition cvar.c:599
#define M_PI
Definition mathlib.h:28
float sin(float f)
cvar_t r_skeletal_debugbone
Definition model_alias.c:33
cvar_t r_skeletal_debugtranslatey
Definition model_alias.c:37
cvar_t r_skeletal_debugbonecomponent
Definition model_alias.c:34
cvar_t mod_alias_force_animated
Definition model_alias.c:40
cvar_t r_skeletal_debugtranslatez
Definition model_alias.c:38
cvar_t r_skeletal_debugtranslatex
Definition model_alias.c:36
float mod_md3_sin[320]
Definition model_alias.c:42
cvar_t r_skeletal_debugbonevalue
Definition model_alias.c:35
#define Sys_HaveSSE()
Definition sys.h:140

References Con_Printf(), Cvar_RegisterVariable(), i, M_PI, mod_alias_force_animated, mod_alias_supporttagscale, mod_md3_sin, r_skeletal_debugbone, r_skeletal_debugbonecomponent, r_skeletal_debugbonevalue, r_skeletal_debugtranslatex, r_skeletal_debugtranslatey, r_skeletal_debugtranslatez, sin(), and Sys_HaveSSE.

Referenced by Mod_Init().

◆ Mod_BuildAliasSkinsFromSkinFiles()

void Mod_BuildAliasSkinsFromSkinFiles ( texture_t * skin,
skinfile_t * skinfile,
const char * meshname,
const char * shadername )

Definition at line 925 of file model_alias.c.

926{
927 int i;
928 char stripbuf[MAX_QPATH];
929 skinfileitem_t *skinfileitem;
931 Con_DPrintf("Looking up texture for %s (default: %s)\n", meshname, shadername);
932 if (skinfile)
933 {
934 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
935 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
936 {
937 memset(skin, 0, sizeof(*skin));
938 // see if a mesh
939 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
940 {
941 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
942 if (!strcmp(skinfileitem->name, meshname))
943 {
944 Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
946 Con_DPrintf("--> got %s from skin file\n", stripbuf);
948 break;
949 }
950 }
951 if (!skinfileitem)
952 {
953 // don't render unmentioned meshes
956 Con_DPrintf("--> skipping\n");
957 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
958 }
959 }
960 }
961 else
962 {
964 Con_DPrintf("--> using default\n");
965 Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
967 }
968}
#define SUPERCONTENTS_SOLID
Definition bspfile.h:196
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
Definition console.c:1544
skinframe_t * R_SkinFrame_LoadMissing(void)
Definition gl_rmain.c:2804
cvar_t developer_extra
Definition host.c:49
void Image_StripImageExtension(const char *in, char *out, size_t size_out)
Definition image.c:913
#define MATERIALFLAG_NODRAW
Definition model_brush.h:96
#define MATERIALFLAG_WALL
Definition model_brush.h:89
#define MATERIALFLAG_NOSHADOW
qbool Mod_LoadTextureFromQ3Shader(mempool_t *mempool, const char *modelname, texture_t *texture, const char *name, qbool warnmissing, qbool fallback, int defaulttexflags, int defaultmaterialflags)
void Mod_LoadCustomMaterial(mempool_t *mempool, texture_t *texture, const char *name, int supercontents, int materialflags, skinframe_t *skinframe)
cvar_t r_mipskins
#define MAX_QPATH
max length of a quake game pathname
Definition qdefs.h:169
#define TEXF_PICMIP
Definition r_textures.h:21
#define TEXF_ALPHA
Definition r_textures.h:9
#define TEXF_MIPMAP
Definition r_textures.h:11
#define TEXF_COMPRESS
Definition r_textures.h:23
int num_surfaces
struct skinfile_s * next
skinfileitem_t * items
char name[MAX_QPATH]
char replacement[MAX_QPATH]
struct skinfileitem_s * next

References Con_DPrintf(), developer_extra, i, Image_StripImageExtension(), cvar_t::integer, skinfile_t::items, loadmodel, MATERIALFLAG_NODRAW, MATERIALFLAG_NOSHADOW, MATERIALFLAG_WALL, MAX_QPATH, model_t::mempool, Mod_LoadCustomMaterial(), Mod_LoadTextureFromQ3Shader(), model_t::name, skinfileitem_t::name, skinfile_t::next, skinfileitem_t::next, model_t::num_surfaces, r_mipskins, R_SkinFrame_LoadMissing(), skinfileitem_t::replacement, skin, SUPERCONTENTS_SOLID, TEXF_ALPHA, TEXF_COMPRESS, TEXF_MIPMAP, and TEXF_PICMIP.

Referenced by Mod_DARKPLACESMODEL_Load(), Mod_IDP0_Load(), Mod_IDP2_Load(), Mod_IDP3_Load(), Mod_INTERQUAKEMODEL_Load(), Mod_OBJ_Load(), Mod_PSKMODEL_Load(), and Mod_ZYMOTICMODEL_Load().

◆ Mod_BuildBaseBonePoses()

static void Mod_BuildBaseBonePoses ( void )
static

Definition at line 601 of file model_alias.c.

602{
603 int boneindex;
604 matrix4x4_t *basebonepose;
605 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
606 matrix4x4_t bonematrix;
607 matrix4x4_t tempbonematrix;
608 if (!loadmodel->num_bones)
609 return;
610 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
611 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
612 {
614 if (loadmodel->data_bones[boneindex].parent >= 0)
615 {
616 tempbonematrix = bonematrix;
617 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
618 }
619 basebonepose[boneindex] = bonematrix;
620 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
621 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
622 }
623 Mem_Free(basebonepose);
624}
void Matrix4x4_ToArray12FloatD3D(const matrix4x4_t *in, float out[12])
Definition matrixlib.c:1391
void Matrix4x4_Invert_Simple(matrix4x4_t *out, const matrix4x4_t *in1)
Definition matrixlib.c:422
float * data_baseboneposeinverse
float num_posescale
aliasbone_t * data_bones
short * data_poses7s
int num_bones
mempool_t * tempmempool
Definition zone.c:794

References model_t::data_baseboneposeinverse, model_t::data_bones, model_t::data_poses7s, loadmodel, Matrix4x4_Concat(), Matrix4x4_FromBonePose7s(), Matrix4x4_Invert_Simple(), Matrix4x4_ToArray12FloatD3D(), Mem_Alloc, Mem_Free, model_t::num_bones, model_t::num_posescale, aliasbone_t::parent, and tempmempool.

Referenced by Mod_DARKPLACESMODEL_Load(), and Mod_ZYMOTICMODEL_Load().

◆ Mod_ConvertAliasVerts()

static void Mod_ConvertAliasVerts ( int inverts,
trivertx_t * v,
trivertx_t * out,
int * vertremap )
static

Definition at line 848 of file model_alias.c.

849{
850 int i, j;
851 for (i = 0;i < inverts;i++)
852 {
853 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
854 continue;
855 j = vertremap[i]; // not onseam
856 if (j >= 0)
857 out[j] = v[i];
858 j = vertremap[i+inverts]; // onseam
859 if (j >= 0)
860 out[j] = v[i];
861 }
862}

References i, and v.

Referenced by Mod_MDL_LoadFrames().

◆ Mod_DARKPLACESMODEL_Load()

void Mod_DARKPLACESMODEL_Load ( model_t * mod,
void * buffer,
void * bufferend )

Definition at line 2163 of file model_alias.c.

2164{
2165 dpmheader_t *pheader;
2166 dpmframe_t *frames;
2167 dpmbone_t *bone;
2168 dpmmesh_t *dpmmesh;
2169 unsigned char *pbase;
2170 int i, j, k, meshvertices, meshtriangles;
2171 skinfile_t *skinfiles;
2172 unsigned char *data;
2173 float *bonepose;
2174 float biggestorigin, tempvec[3], modelscale;
2175 float f;
2176 float *poses;
2177
2178 pheader = (dpmheader_t *)buffer;
2179 pbase = (unsigned char *)buffer;
2180 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2181 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2182 if (BigLong(pheader->type) != 2)
2183 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2184
2186
2189
2190 // byteswap header
2191 pheader->type = BigLong(pheader->type);
2192 pheader->filesize = BigLong(pheader->filesize);
2193 pheader->mins[0] = BigFloat(pheader->mins[0]);
2194 pheader->mins[1] = BigFloat(pheader->mins[1]);
2195 pheader->mins[2] = BigFloat(pheader->mins[2]);
2196 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2197 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2198 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2199 pheader->yawradius = BigFloat(pheader->yawradius);
2200 pheader->allradius = BigFloat(pheader->allradius);
2201 pheader->num_bones = BigLong(pheader->num_bones);
2202 pheader->num_meshs = BigLong(pheader->num_meshs);
2203 pheader->num_frames = BigLong(pheader->num_frames);
2204 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2205 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2206 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2207
2208 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2209 {
2210 Con_Printf("%s has no geometry\n", loadmodel->name);
2211 return;
2212 }
2213 if (pheader->num_frames < 1)
2214 {
2215 Con_Printf("%s has no frames\n", loadmodel->name);
2216 return;
2217 }
2218
2230
2231 // model bbox
2232 // LadyHavoc: actually we blow this away later with Mod_Alias_CalculateBoundingBox()
2233 for (i = 0;i < 3;i++)
2234 {
2235 loadmodel->normalmins[i] = pheader->mins[i];
2236 loadmodel->normalmaxs[i] = pheader->maxs[i];
2237 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2238 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2239 loadmodel->rotatedmins[i] = -pheader->allradius;
2240 loadmodel->rotatedmaxs[i] = pheader->allradius;
2241 }
2242 loadmodel->radius = pheader->allradius;
2243 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2244
2245 // load external .skin files if present
2246 skinfiles = Mod_LoadSkinFiles();
2247 if (loadmodel->numskins < 1)
2248 loadmodel->numskins = 1;
2249
2250 meshvertices = 0;
2251 meshtriangles = 0;
2252
2253 // gather combined statistics from the meshes
2254 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2255 for (i = 0;i < (int)pheader->num_meshs;i++)
2256 {
2257 int numverts = BigLong(dpmmesh->num_verts);
2258 meshvertices += numverts;
2259 meshtriangles += BigLong(dpmmesh->num_tris);
2260 dpmmesh++;
2261 }
2262
2263 loadmodel->numframes = pheader->num_frames;
2264 loadmodel->num_bones = pheader->num_bones;
2270 loadmodel->surfmesh.num_vertices = meshvertices;
2271 loadmodel->surfmesh.num_triangles = meshtriangles;
2273
2274 // do most allocations as one merged chunk
2275 // This is only robust for C standard types!
2276 data = (unsigned char *)Mem_Alloc(loadmodel->mempool,
2277 loadmodel->num_surfaces * sizeof(int)
2278 + meshtriangles * sizeof(int[3])
2279 + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0)
2280 + meshvertices * (sizeof(float[14]) + sizeof(unsigned short) + sizeof(unsigned char[2][4]))
2281 + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7])
2282 + loadmodel->num_bones * sizeof(float[12]));
2283 // Pointers must be taken in descending order of alignment requirement!
2284 loadmodel->surfmesh.data_vertex3f = (float *)data; data += meshvertices * sizeof(float[3]);
2285 loadmodel->surfmesh.data_svector3f = (float *)data; data += meshvertices * sizeof(float[3]);
2286 loadmodel->surfmesh.data_tvector3f = (float *)data; data += meshvertices * sizeof(float[3]);
2287 loadmodel->surfmesh.data_normal3f = (float *)data; data += meshvertices * sizeof(float[3]);
2288 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data; data += meshvertices * sizeof(float[2]);
2289 loadmodel->data_baseboneposeinverse = (float *)data; data += loadmodel->num_bones * sizeof(float[12]);
2291 loadmodel->surfmesh.data_element3i = (int *)data; data += meshtriangles * sizeof(int[3]);
2292 loadmodel->surfmesh.blends = (unsigned short *)data; data += meshvertices * sizeof(unsigned short);
2293 if (meshvertices <= 65536)
2294 {
2295 loadmodel->surfmesh.data_element3s = (unsigned short *)data; data += meshtriangles * sizeof(unsigned short[3]);
2296 }
2297 loadmodel->data_poses7s = (short *)data; data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
2298 loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data; data += meshvertices * sizeof(unsigned char[4]);
2299 loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data; data += meshvertices * sizeof(unsigned char[4]);
2300 // Struct alignment requirements could change so we can't assume them here
2301 // otherwise a safe-looking commit could introduce undefined behaviour!
2308
2309 for (i = 0;i < loadmodel->numskins;i++)
2310 {
2313 loadmodel->skinscenes[i].loop = true;
2315 }
2316
2317 // load the bone info
2318 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2319 for (i = 0;i < loadmodel->num_bones;i++)
2320 {
2321 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2323 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2324 if (loadmodel->data_bones[i].parent >= i)
2325 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2326 }
2327
2328 // load the frames
2329 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2330 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2331 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2332 tempvec[0] = BigFloat(poses[0]);
2333 tempvec[1] = BigFloat(poses[1]);
2334 tempvec[2] = BigFloat(poses[2]);
2335 modelscale = VectorLength(tempvec);
2336 biggestorigin = 0;
2337 for (i = 0;i < loadmodel->numframes;i++)
2338 {
2339 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2342 loadmodel->animscenes[i].loop = true;
2344 // load the bone poses for this frame
2345 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2346 for (j = 0;j < loadmodel->num_bones*12;j++)
2347 {
2348 f = fabs(BigFloat(poses[j]));
2349 biggestorigin = max(biggestorigin, f);
2350 }
2351 // stuff not processed here: mins, maxs, yawradius, allradius
2352 }
2353 loadmodel->num_posescale = biggestorigin / 32767.0f;
2355 for (i = 0;i < loadmodel->numframes;i++)
2356 {
2357 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2358 for (j = 0;j < loadmodel->num_bones;j++)
2359 {
2360 float pose[12];
2361 matrix4x4_t posematrix;
2362 for (k = 0;k < 12;k++)
2363 pose[k] = BigFloat(frameposes[j*12+k]);
2364 // scale child bones to match the root scale
2365 if (loadmodel->data_bones[j].parent >= 0)
2366 {
2367 pose[3] *= modelscale;
2368 pose[7] *= modelscale;
2369 pose[11] *= modelscale;
2370 }
2371 // normalize rotation matrix
2372 VectorNormalize(pose + 0);
2373 VectorNormalize(pose + 4);
2374 VectorNormalize(pose + 8);
2375 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2377 }
2378 }
2379
2380 // load the meshes now
2381 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2382 meshvertices = 0;
2383 meshtriangles = 0;
2384 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2385 // (converting from weight-blending skeletal animation to
2386 // deformation-based skeletal animation)
2387 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2388 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2389 for (i = 0;i < loadmodel->num_bones;i++)
2390 {
2391 float m[12];
2392 for (k = 0;k < 12;k++)
2393 m[k] = BigFloat(poses[i*12+k]);
2394 if (loadmodel->data_bones[i].parent >= 0)
2395 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2396 else
2397 for (k = 0;k < 12;k++)
2398 bonepose[12*i+k] = m[k];
2399 }
2400 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2401 {
2402 const int *inelements;
2403 int *outelement3i;
2404 unsigned short *outelement3s;
2405 const float *intexcoord;
2406 msurface_t *surface;
2407
2409 surface = loadmodel->data_surfaces + i;
2410 surface->texture = loadmodel->data_textures + i;
2411 surface->num_firsttriangle = meshtriangles;
2412 surface->num_triangles = BigLong(dpmmesh->num_tris);
2413 surface->num_firstvertex = meshvertices;
2414 surface->num_vertices = BigLong(dpmmesh->num_verts);
2415 meshvertices += surface->num_vertices;
2416 meshtriangles += surface->num_triangles;
2417
2418 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2419 outelement3i = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2421 for (j = 0;j < surface->num_triangles;j++)
2422 {
2423 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2424 outelement3i[j * 3 + 0] = surface->num_firstvertex + BigLong(inelements[j * 3 + 2]);
2425 outelement3i[j * 3 + 1] = surface->num_firstvertex + BigLong(inelements[j * 3 + 1]);
2426 outelement3i[j * 3 + 2] = surface->num_firstvertex + BigLong(inelements[j * 3 + 0]);
2427 if (outelement3s)
2428 {
2429 outelement3s[j * 3 + 0] = outelement3i[j * 3 + 0];
2430 outelement3s[j * 3 + 1] = outelement3i[j * 3 + 1];
2431 outelement3s[j * 3 + 2] = outelement3i[j * 3 + 2];
2432 }
2433 }
2434
2435 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2436 for (j = 0;j < surface->num_vertices*2;j++)
2437 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2438
2439 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2440 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2441 {
2442 int weightindex[4] = { 0, 0, 0, 0 };
2443 float weightinfluence[4] = { 0, 0, 0, 0 };
2444 int l;
2445 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2446 data += sizeof(dpmvertex_t);
2447 for (k = 0;k < numweights;k++)
2448 {
2449 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2450 int boneindex = BigLong(vert->bonenum);
2451 const float *m = bonepose + 12 * boneindex;
2452 float influence = BigFloat(vert->influence);
2453 float relativeorigin[3], relativenormal[3];
2454 relativeorigin[0] = BigFloat(vert->origin[0]);
2455 relativeorigin[1] = BigFloat(vert->origin[1]);
2456 relativeorigin[2] = BigFloat(vert->origin[2]);
2457 relativenormal[0] = BigFloat(vert->normal[0]);
2458 relativenormal[1] = BigFloat(vert->normal[1]);
2459 relativenormal[2] = BigFloat(vert->normal[2]);
2460 // blend the vertex bone weights into the base mesh
2461 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2462 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2463 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2464 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2465 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2466 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2467 if (!k)
2468 {
2469 // store the first (and often only) weight
2470 weightinfluence[0] = influence;
2471 weightindex[0] = boneindex;
2472 }
2473 else
2474 {
2475 // sort the new weight into this vertex's weight table
2476 // (which only accepts up to 4 bones per vertex)
2477 for (l = 0;l < 4;l++)
2478 {
2479 if (weightinfluence[l] < influence)
2480 {
2481 // move weaker influence weights out of the way first
2482 int l2;
2483 for (l2 = 3;l2 > l;l2--)
2484 {
2485 weightinfluence[l2] = weightinfluence[l2-1];
2486 weightindex[l2] = weightindex[l2-1];
2487 }
2488 // store the new weight
2489 weightinfluence[l] = influence;
2490 weightindex[l] = boneindex;
2491 break;
2492 }
2493 }
2494 }
2495 data += sizeof(dpmbonevert_t);
2496 }
2497 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2498 loadmodel->surfmesh.data_skeletalindex4ub[j*4 ] = weightindex[0];
2499 loadmodel->surfmesh.data_skeletalindex4ub[j*4+1] = weightindex[1];
2500 loadmodel->surfmesh.data_skeletalindex4ub[j*4+2] = weightindex[2];
2501 loadmodel->surfmesh.data_skeletalindex4ub[j*4+3] = weightindex[3];
2502 loadmodel->surfmesh.data_skeletalweight4ub[j*4 ] = (unsigned char)(weightinfluence[0]*255.0f);
2503 loadmodel->surfmesh.data_skeletalweight4ub[j*4+1] = (unsigned char)(weightinfluence[1]*255.0f);
2504 loadmodel->surfmesh.data_skeletalweight4ub[j*4+2] = (unsigned char)(weightinfluence[2]*255.0f);
2505 loadmodel->surfmesh.data_skeletalweight4ub[j*4+3] = (unsigned char)(weightinfluence[3]*255.0f);
2506 }
2507
2508 // since dpm models do not have named sections, reuse their shader name as the section name
2510
2512 }
2513 if (loadmodel->surfmesh.num_blends < meshvertices)
2515 Z_Free(bonepose);
2516 Mod_FreeSkinFiles(skinfiles);
2518
2519 // compute all the mesh information that was not loaded from the file
2525
2526 // Always make a BIH for the first frame, we can use it where possible.
2529 {
2535 }
2536}
#define BigLong(l)
Definition common.h:91
#define BigFloat(l)
Definition common.h:93
float flags
static int(ZEXPORT *qz_inflate)(z_stream *strm
void R_Mod_CompileShadowMap(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativelightdirection, float lightradius, int numsurfaces, const int *surfacelist)
Definition gl_rsurf.c:1286
void R_Mod_DrawDebug(entity_render_t *ent)
Definition gl_rsurf.c:660
void R_Mod_DrawLight(entity_render_t *ent, int numsurfaces, const int *surfacelist, const unsigned char *lighttrispvs)
Definition gl_rsurf.c:1399
void R_Mod_Draw(entity_render_t *ent)
Definition gl_rsurf.c:637
void R_Mod_DrawShadowMap(int side, entity_render_t *ent, const vec3_t relativelightorigin, const vec3_t relativelightdirection, float lightradius, int modelnumsurfaces, const int *modelsurfacelist, const unsigned char *surfacesides, const vec3_t lightmins, const vec3_t lightmaxs)
Definition gl_rsurf.c:1320
void R_Mod_DrawDepth(entity_render_t *ent)
Definition gl_rsurf.c:645
void R_Mod_DrawPrepass(entity_render_t *ent)
Definition gl_rsurf.c:667
GLuint buffer
Definition glquake.h:630
GLsizeiptr const GLvoid * data
Definition glquake.h:639
void R_ConcatTransforms(const float in1[3 *4], const float in2[3 *4], float out[3 *4])
Definition mathlib.c:800
#define max(A, B)
Definition mathlib.h:38
#define VectorNormalize(v)
Definition mathlib.h:104
#define VectorLength(a)
Definition mathlib.h:109
void Matrix4x4_FromArray12FloatD3D(matrix4x4_t *out, const float in[12])
Definition matrixlib.c:1422
void Matrix4x4_ToBonePose7s(const matrix4x4_t *m, float origininvscale, short *pose7s)
Definition matrixlib.c:1614
float fabs(float f)
static void Mod_MDLMD2MD3_TraceBox(model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
static void Mod_Skeletal_AnimateVertices(const model_t *RESTRICT model, const frameblend_t *RESTRICT frameblend, const skeleton_t *skeleton, float *RESTRICT vertex3f, float *RESTRICT normal3f, float *RESTRICT svector3f, float *RESTRICT tvector3f)
void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
static int Mod_Skeletal_CompressBlend(model_t *model, const int *newindex, const float *newinfluence)
static void Mod_MDLMD2MD3_TraceLine(model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
static void Mod_BuildBaseBonePoses(void)
static qbool Mod_Alias_CalculateBoundingBox(void)
int Mod_CollisionBIH_PointSuperContents_Mesh(struct model_s *model, int frame, const vec3_t start)
void Mod_CollisionBIH_TracePoint_Mesh(model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
void Mod_CollisionBIH_TraceBox(model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
void Mod_CollisionBIH_TraceLine(model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
bih_t * Mod_MakeCollisionBIH(model_t *model, qbool userendersurfaces, bih_t *out)
void Mod_CollisionBIH_TraceBrush(model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, colbrushf_t *thisbrush_start, colbrushf_t *thisbrush_end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
skinfile_t * Mod_LoadSkinFiles(void)
void Mod_FreeSkinFiles(skinfile_t *skinfile)
void Mod_MakeSortedSurfaces(model_t *mod)
qbool Mod_ValidateElements(int *element3i, unsigned short *element3s, int numtriangles, int firstvertex, int numvertices, const char *filename, int fileline)
@ ST_RAND
@ mod_alias
float f
char name[MD3NAME]
char name[32]
float framerate
const char * string
Definition cvar.h:71
unsigned int bonenum
unsigned int num_meshs
float mins[3]
unsigned int ofs_frames
unsigned int ofs_bones
unsigned int type
float maxs[3]
unsigned int filesize
unsigned int ofs_meshs
unsigned int num_bones
char id[16]
unsigned int num_frames
unsigned int ofs_indices
unsigned int ofs_verts
unsigned int num_verts
unsigned int num_tris
unsigned int ofs_texcoords
char shadername[32]
void(* DrawDepth)(struct entity_render_s *ent)
modtype_t type
int(* PointSuperContents)(struct model_s *model, int frame, const vec3_t point)
int * modelsurfaces_sorted
surface indices of model in an optimal draw order (submodelindex -> texture -> lightmap -> index)
bih_t collision_bih
int submodelsurfaces_end
msurface_t * data_surfaces
void(* Draw)(struct entity_render_s *ent)
int submodelsurfaces_start
synctype_t synctype
void(* DrawPrepass)(struct entity_render_s *ent)
void(* TraceBox)(struct model_s *model, const struct frameblend_s *frameblend, const struct skeleton_s *skeleton, struct trace_s *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
void(* DrawShadowMap)(int side, struct entity_render_s *ent, const vec3_t relativelightorigin, const vec3_t relativelightdirection, float lightradius, int numsurfaces, const int *surfacelist, const unsigned char *surfacesides, const vec3_t lightmins, const vec3_t lightmaxs)
void(* TracePoint)(struct model_s *model, const struct frameblend_s *frameblend, const struct skeleton_s *skeleton, struct trace_s *trace, const vec3_t start, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
void(* DrawDebug)(struct entity_render_s *ent)
animscene_t * animscenes
void(* TraceBrush)(struct model_s *model, const struct frameblend_s *frameblend, const struct skeleton_s *skeleton, struct trace_s *trace, struct colbrushf_s *start, struct colbrushf_s *end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
int numframes
float num_poseinvscale
void(* CompileShadowMap)(struct entity_render_s *ent, vec3_t relativelightorigin, vec3_t relativelightdirection, float lightradius, int numsurfaces, const int *surfacelist)
int num_textures
const char * modeldatatypestring
texture_t * data_textures
animscene_t * skinscenes
void(* DrawLight)(struct entity_render_s *ent, int numsurfaces, const int *surfacelist, const unsigned char *trispvs)
int num_texturesperskin
void(* TraceLine)(struct model_s *model, const struct frameblend_s *frameblend, const struct skeleton_s *skeleton, struct trace_s *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
describes the textures to use on a range of triangles in the model, and mins/maxs (AABB) for culling.
int num_firsttriangle
int num_triangles
range of triangles and vertices in model->surfmesh
texture_t * texture
the texture to use on the surface
int num_firstvertex
qbool isanimated
unsigned char * data_skeletalweight4ub
unsigned char * data_skeletalindex4ub
unsigned short * data_element3s
struct blendweights_s * data_blendweights
unsigned short * blends
#define Z_Malloc(size)
Definition zone.h:161
#define Mem_ReallocType(pool, data, type, size)
Definition zone.h:95
#define Z_Free(data)
Definition zone.h:164
#define Mem_AllocType(pool, type, size)
Definition zone.h:93

References dpmheader_t::allradius, model_t::AnimateVertices, model_t::animscenes, BigFloat, BigLong, surfmesh_t::blends, dpmbonevert_t::bonenum, buffer, model_t::collision_bih, model_t::CompileShadowMap, Con_Printf(), data, model_t::data_baseboneposeinverse, surfmesh_t::data_blendweights, model_t::data_bones, surfmesh_t::data_element3i, surfmesh_t::data_element3s, surfmesh_t::data_normal3f, model_t::data_poses7s, surfmesh_t::data_skeletalindex4ub, surfmesh_t::data_skeletalweight4ub, model_t::data_surfaces, surfmesh_t::data_svector3f, surfmesh_t::data_texcoordtexture2f, model_t::data_textures, surfmesh_t::data_tvector3f, surfmesh_t::data_vertex3f, model_t::Draw, model_t::DrawDebug, model_t::DrawDepth, model_t::DrawLight, model_t::DrawPrepass, model_t::DrawShadowMap, f, fabs(), dpmheader_t::filesize, animscene_t::firstframe, aliasbone_t::flags, flags, animscene_t::framecount, animscene_t::framerate, Host_Error(), i, dpmheader_t::id, dpmbonevert_t::influence, int(), cvar_t::integer, surfmesh_t::isanimated, loadmodel, animscene_t::loop, Matrix4x4_FromArray12FloatD3D(), Matrix4x4_ToBonePose7s(), max, dpmheader_t::maxs, Mem_Alloc, Mem_AllocType, Mem_ReallocType, model_t::mempool, dpmheader_t::mins, mod_alias, Mod_Alias_CalculateBoundingBox(), mod_alias_force_animated, Mod_BuildAliasSkinsFromSkinFiles(), Mod_BuildBaseBonePoses(), Mod_BuildTextureVectorsFromNormals(), Mod_CollisionBIH_PointSuperContents_Mesh(), Mod_CollisionBIH_TraceBox(), Mod_CollisionBIH_TraceBrush(), Mod_CollisionBIH_TraceLine(), Mod_CollisionBIH_TracePoint_Mesh(), Mod_FreeSkinFiles(), Mod_LoadSkinFiles(), Mod_MakeCollisionBIH(), Mod_MakeSortedSurfaces(), Mod_MDLMD2MD3_TraceBox(), Mod_MDLMD2MD3_TraceLine(), Mod_Skeletal_AnimateVertices(), Mod_Skeletal_CompressBlend(), Mod_ValidateElements(), model_t::modeldatatypestring, model_t::modelsurfaces_sorted, aliasbone_t::name, animscene_t::name, dpmbone_t::name, dpmframe_t::name, model_t::name, dpmbonevert_t::normal, model_t::normalmaxs, model_t::normalmins, NULL, surfmesh_t::num_blends, dpmheader_t::num_bones, model_t::num_bones, msurface_t::num_firsttriangle, msurface_t::num_firstvertex, dpmheader_t::num_frames, dpmheader_t::num_meshs, model_t::num_poseinvscale, model_t::num_poses, model_t::num_posescale, model_t::num_surfaces, model_t::num_textures, model_t::num_texturesperskin, msurface_t::num_triangles, surfmesh_t::num_triangles, dpmmesh_t::num_tris, msurface_t::num_vertices, surfmesh_t::num_vertices, dpmmesh_t::num_verts, model_t::numframes, model_t::numskins, dpmheader_t::ofs_bones, dpmheader_t::ofs_frames, dpmmesh_t::ofs_indices, dpmheader_t::ofs_meshs, dpmmesh_t::ofs_texcoords, dpmmesh_t::ofs_verts, dpmbonevert_t::origin, aliasbone_t::parent, model_t::PointSuperContents, R_ConcatTransforms(), R_Mod_CompileShadowMap(), R_Mod_Draw(), R_Mod_DrawDebug(), R_Mod_DrawDepth(), R_Mod_DrawLight(), R_Mod_DrawPrepass(), R_Mod_DrawShadowMap(), r_smoothnormals_areaweighting, model_t::radius, model_t::radius2, model_t::rotatedmaxs, model_t::rotatedmins, dpmmesh_t::shadername, model_t::skinscenes, ST_RAND, cvar_t::string, model_t::submodelsurfaces_end, model_t::submodelsurfaces_start, model_t::surfmesh, model_t::synctype, msurface_t::texture, model_t::TraceBox, model_t::TraceBrush, model_t::TraceLine, model_t::TracePoint, dpmheader_t::type, model_t::type, VectorLength, VectorNormalize, model_t::yawmaxs, model_t::yawmins, dpmheader_t::yawradius, Z_Free, and Z_Malloc.

◆ Mod_IDP0_Load()

void Mod_IDP0_Load ( model_t * mod,
void * buffer,
void * bufferend )

Definition at line 972 of file model_alias.c.

973{
974 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
975 float scales, scalet, interval;
976 msurface_t *surface;
977 unsigned char *data;
978 mdl_t *pinmodel;
979 stvert_t *pinstverts;
980 dtriangle_t *pintriangles;
981 daliasskintype_t *pinskintype;
982 daliasskingroup_t *pinskingroup;
983 daliasskininterval_t *pinskinintervals;
984 daliasframetype_t *pinframetype;
985 daliasgroup_t *pinframegroup;
986 unsigned char *datapointer, *startframes, *startskins;
987 char name[MAX_QPATH];
988 skinframe_t *tempskinframe;
989 animscene_t *tempskinscenes;
990 texture_t *tempaliasskins;
991 float *vertst;
992 int *vertonseam, *vertremap;
993 skinfile_t *skinfiles;
994
995 datapointer = (unsigned char *)buffer;
996 pinmodel = (mdl_t *)datapointer;
997 datapointer += sizeof(mdl_t);
998
999 version = LittleLong (pinmodel->version);
1000 if (version != ALIAS_VERSION)
1001 Host_Error ("%s has wrong version number (%i should be %i)",
1003
1005
1016 // FIXME add TraceBrush!
1019
1023 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
1027
1028 loadmodel->numskins = LittleLong(pinmodel->numskins);
1029 BOUNDI(loadmodel->numskins,0,65536);
1030 skinwidth = LittleLong (pinmodel->skinwidth);
1031 BOUNDI(skinwidth,0,65536);
1032 skinheight = LittleLong (pinmodel->skinheight);
1033 BOUNDI(skinheight,0,65536);
1034 numverts = LittleLong(pinmodel->numverts);
1035 BOUNDI(numverts,0,65536);
1039 BOUNDI(loadmodel->numframes,0,65536);
1041 BOUNDI((int)loadmodel->synctype,0,2);
1042 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1043 i = LittleLong (pinmodel->flags);
1044 loadmodel->effects = (((unsigned)i & 255) << 24) | (i & 0x00FFFF00);
1045
1046 if (strstr(r_nolerp_list.string, loadmodel->name))
1047 loadmodel->nolerp = true;
1048
1049 for (i = 0;i < 3;i++)
1050 {
1053 }
1054
1055 startskins = datapointer;
1056 totalskins = 0;
1057 for (i = 0;i < loadmodel->numskins;i++)
1058 {
1059 pinskintype = (daliasskintype_t *)datapointer;
1060 datapointer += sizeof(daliasskintype_t);
1061 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
1062 groupskins = 1;
1063 else
1064 {
1065 pinskingroup = (daliasskingroup_t *)datapointer;
1066 datapointer += sizeof(daliasskingroup_t);
1067 groupskins = LittleLong(pinskingroup->numskins);
1068 datapointer += sizeof(daliasskininterval_t) * groupskins;
1069 }
1070
1071 for (j = 0;j < groupskins;j++)
1072 {
1073 datapointer += skinwidth * skinheight;
1074 totalskins++;
1075 }
1076 }
1077
1078 pinstverts = (stvert_t *)datapointer;
1079 datapointer += sizeof(stvert_t) * numverts;
1080
1081 pintriangles = (dtriangle_t *)datapointer;
1082 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1083
1084 startframes = datapointer;
1086 for (i = 0;i < loadmodel->numframes;i++)
1087 {
1088 pinframetype = (daliasframetype_t *)datapointer;
1089 datapointer += sizeof(daliasframetype_t);
1090 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1091 groupframes = 1;
1092 else
1093 {
1094 pinframegroup = (daliasgroup_t *)datapointer;
1095 datapointer += sizeof(daliasgroup_t);
1096 groupframes = LittleLong(pinframegroup->numframes);
1097 datapointer += sizeof(daliasinterval_t) * groupframes;
1098 }
1099
1100 for (j = 0;j < groupframes;j++)
1101 {
1102 datapointer += sizeof(daliasframe_t);
1103 datapointer += sizeof(trivertx_t) * numverts;
1105 }
1106 }
1108
1109 // store texture coordinates into temporary array, they will be stored
1110 // after usage is determined (triangle data)
1111 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1112 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1113 vertonseam = vertremap + numverts * 2;
1114
1115 scales = 1.0 / skinwidth;
1116 scalet = 1.0 / skinheight;
1117 for (i = 0;i < numverts;i++)
1118 {
1119 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1120 vertst[i*2+0] = LittleLong(pinstverts[i].s) * scales;
1121 vertst[i*2+1] = LittleLong(pinstverts[i].t) * scalet;
1122 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1123 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1124 }
1125
1126// load triangle data
1128
1129 // read the triangle elements
1130 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1131 for (j = 0;j < 3;j++)
1132 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1133 // validate (note numverts is used because this is the original data)
1135 // now butcher the elements according to vertonseam and tri->facesfront
1136 // and then compact the vertex set to remove duplicates
1137 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1138 if (!LittleLong(pintriangles[i].facesfront)) // backface
1139 for (j = 0;j < 3;j++)
1140 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1141 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1142 // count the usage
1143 // (this uses vertremap to count usage to save some memory)
1144 for (i = 0;i < numverts*2;i++)
1145 vertremap[i] = 0;
1146 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1147 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1148 // build remapping table and compact array
1150 for (i = 0;i < numverts*2;i++)
1151 {
1152 if (vertremap[i])
1153 {
1154 vertremap[i] = loadmodel->surfmesh.num_vertices;
1155 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1156 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1158 }
1159 else
1160 vertremap[i] = -1; // not used at all
1161 }
1162 // remap the elements to the new vertex set
1163 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1165 // store the texture coordinates
1167 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1168 {
1169 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1170 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1171 }
1172
1173 // generate ushort elements array if possible
1174 if (loadmodel->surfmesh.num_vertices <= 65536)
1175 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1177 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1179
1180// load the frames
1183 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1186
1187 Mem_Free(vertst);
1188 Mem_Free(vertremap);
1189
1190 // load the skins
1191 skinfiles = Mod_LoadSkinFiles();
1192 if (skinfiles)
1193 {
1198 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1199 Mod_FreeSkinFiles(skinfiles);
1200 for (i = 0;i < loadmodel->numskins;i++)
1201 {
1204 loadmodel->skinscenes[i].loop = true;
1206 }
1207 }
1208 else
1209 {
1214 totalskins = 0;
1215 datapointer = startskins;
1216 for (i = 0;i < loadmodel->numskins;i++)
1217 {
1218 pinskintype = (daliasskintype_t *)datapointer;
1219 datapointer += sizeof(daliasskintype_t);
1220
1221 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1222 {
1223 groupskins = 1;
1224 interval = 0.1f;
1225 }
1226 else
1227 {
1228 pinskingroup = (daliasskingroup_t *)datapointer;
1229 datapointer += sizeof(daliasskingroup_t);
1230
1231 groupskins = LittleLong (pinskingroup->numskins);
1232
1233 pinskinintervals = (daliasskininterval_t *)datapointer;
1234 datapointer += sizeof(daliasskininterval_t) * groupskins;
1235
1236 interval = LittleFloat(pinskinintervals[0].interval);
1237 if (interval < 0.01f)
1238 {
1239 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1240 interval = 0.1f;
1241 }
1242 }
1243
1244 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1245 loadmodel->skinscenes[i].firstframe = totalskins;
1246 loadmodel->skinscenes[i].framecount = groupskins;
1247 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1248 loadmodel->skinscenes[i].loop = true;
1249
1250 for (j = 0;j < groupskins;j++)
1251 {
1252 if (groupskins > 1)
1253 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1254 else
1255 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1258 datapointer += skinwidth * skinheight;
1259 totalskins++;
1260 }
1261 }
1262 // check for skins that don't exist in the model, but do exist as external images
1263 // (this was added because yummyluv kept pestering me about support for it)
1264 // TODO: support shaders here?
1265 for (;;)
1266 {
1267 dpsnprintf(name, sizeof(name), "%s_%i", loadmodel->name, loadmodel->numskins);
1268 tempskinframe = R_SkinFrame_LoadExternal(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false, false);
1269 if (!tempskinframe)
1270 break;
1271 // expand the arrays to make room
1272 tempskinscenes = loadmodel->skinscenes;
1274 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1275 Mem_Free(tempskinscenes);
1276
1277 tempaliasskins = loadmodel->data_textures;
1279 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1280 Mem_Free(tempaliasskins);
1281
1282 // store the info about the new skin
1289
1290 //increase skin counts
1293 totalskins++;
1294
1295 // fix up the pointers since they are pointing at the old textures array
1296 // FIXME: this is a hack!
1297 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1299 }
1300 }
1301
1302 surface = loadmodel->data_surfaces;
1303 surface->texture = loadmodel->data_textures;
1304 surface->num_firsttriangle = 0;
1306 surface->num_firstvertex = 0;
1308
1311
1312 // Always make a BIH for the first frame, we can use it where possible.
1315 {
1321 }
1322}
int dpsnprintf(char *buffer, size_t buffersize, const char *format,...)
Returns the number of printed characters, excluding the final '\0' or returns -1 if the buffer isn't ...
Definition common.c:997
#define LittleLong(l)
Definition common.h:92
#define dp_strlcpy(dst, src, dsize)
Definition common.h:303
#define LittleFloat(l)
Definition common.h:94
static int const char * version
Definition fs.c:479
skinframe_t * R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
Definition gl_rmain.c:2616
cvar_t r_fullbrights
Definition gl_rmain.c:122
skinframe_t * R_SkinFrame_LoadExternal(const char *name, int textureflags, qbool complain, qbool fallbacknotexture)
Definition gl_rmain.c:2314
const GLchar * name
Definition glquake.h:601
static void Mod_Alias_MorphMesh_CompileFrames(void)
cvar_t r_nolerp_list
Definition gl_rmain.c:204
static void Mod_MDL_AnimateVertices(const model_t *RESTRICT model, const frameblend_t *RESTRICT frameblend, const skeleton_t *skeleton, float *RESTRICT vertex3f, float *RESTRICT normal3f, float *RESTRICT svector3f, float *RESTRICT tvector3f)
#define BOUNDI(VALUE, MIN, MAX)
static void Mod_MDL_LoadFrames(unsigned char *datapointer, int inverts, int *vertremap)
synctype_t
@ ALIAS_SINGLE
Definition modelgen.h:39
@ ALIAS_SKIN_SINGLE
Definition modelgen.h:41
#define ALIAS_VERSION
Definition modelgen.h:35
aliasframetype_t type
Definition modelgen.h:128
aliasskintype_t type
Definition modelgen.h:134
int numskins
Definition modelgen.h:51
int version
Definition modelgen.h:46
int numverts
Definition modelgen.h:54
vec3_t scale
Definition modelgen.h:47
vec3_t scale_origin
Definition modelgen.h:48
int flags
Definition modelgen.h:58
int synctype
Definition modelgen.h:57
int numtris
Definition modelgen.h:55
int skinwidth
Definition modelgen.h:52
int numframes
Definition modelgen.h:56
int skinheight
Definition modelgen.h:53
unsigned effects
qbool nolerp
float num_morphmdlframetranslate[3]
float num_morphmdlframescale[3]
struct trivertx_s * data_morphmdlvertex
struct texture_s * currentframe

References ALIAS_SINGLE, ALIAS_SKIN_SINGLE, ALIAS_VERSION, model_t::AnimateVertices, model_t::animscenes, BOUNDI, buffer, model_t::collision_bih, model_t::CompileShadowMap, Con_Printf(), texture_t::currentframe, data, surfmesh_t::data_element3i, surfmesh_t::data_element3s, surfmesh_t::data_morphmdlvertex, model_t::data_surfaces, surfmesh_t::data_texcoordtexture2f, model_t::data_textures, dp_strlcpy, dpsnprintf(), model_t::Draw, model_t::DrawDebug, model_t::DrawDepth, model_t::DrawLight, model_t::DrawPrepass, model_t::DrawShadowMap, model_t::effects, animscene_t::firstframe, mdl_t::flags, animscene_t::framecount, animscene_t::framerate, Host_Error(), i, int(), cvar_t::integer, surfmesh_t::isanimated, LittleFloat, LittleLong, loadmodel, animscene_t::loop, MATERIALFLAG_WALL, MAX_QPATH, Mem_Alloc, Mem_Free, model_t::mempool, mod_alias, Mod_Alias_CalculateBoundingBox(), mod_alias_force_animated, Mod_Alias_MorphMesh_CompileFrames(), Mod_BuildAliasSkinsFromSkinFiles(), Mod_CollisionBIH_PointSuperContents_Mesh(), Mod_CollisionBIH_TraceBox(), Mod_CollisionBIH_TraceBrush(), Mod_CollisionBIH_TraceLine(), Mod_CollisionBIH_TracePoint_Mesh(), Mod_FreeSkinFiles(), Mod_LoadCustomMaterial(), Mod_LoadSkinFiles(), Mod_LoadTextureFromQ3Shader(), Mod_MakeCollisionBIH(), Mod_MDL_AnimateVertices(), Mod_MDL_LoadFrames(), Mod_MDLMD2MD3_TraceBox(), Mod_MDLMD2MD3_TraceLine(), Mod_ValidateElements(), model_t::modeldatatypestring, model_t::modelsurfaces_sorted, animscene_t::name, model_t::name, name, model_t::nolerp, NULL, msurface_t::num_firsttriangle, msurface_t::num_firstvertex, surfmesh_t::num_morphframes, surfmesh_t::num_morphmdlframescale, surfmesh_t::num_morphmdlframetranslate, model_t::num_poses, model_t::num_surfaces, model_t::num_textures, model_t::num_texturesperskin, msurface_t::num_triangles, surfmesh_t::num_triangles, msurface_t::num_vertices, surfmesh_t::num_vertices, daliasgroup_t::numframes, mdl_t::numframes, model_t::numframes, daliasskingroup_t::numskins, mdl_t::numskins, model_t::numskins, mdl_t::numtris, mdl_t::numverts, model_t::PointSuperContents, r_fullbrights, r_mipskins, R_Mod_CompileShadowMap(), R_Mod_Draw(), R_Mod_DrawDebug(), R_Mod_DrawDepth(), R_Mod_DrawLight(), R_Mod_DrawPrepass(), R_Mod_DrawShadowMap(), r_nolerp_list, R_SkinFrame_LoadExternal(), R_SkinFrame_LoadInternalQuake(), mdl_t::scale, mdl_t::scale_origin, mdl_t::skinheight, model_t::skinscenes, mdl_t::skinwidth, cvar_t::string, model_t::submodelsurfaces_end, model_t::submodelsurfaces_start, SUPERCONTENTS_SOLID, model_t::surfmesh, mdl_t::synctype, model_t::synctype, tempmempool, TEXF_ALPHA, TEXF_COMPRESS, TEXF_MIPMAP, TEXF_PICMIP, msurface_t::texture, model_t::TraceBox, model_t::TraceBrush, model_t::TraceLine, model_t::TracePoint, daliasframetype_t::type, daliasskintype_t::type, model_t::type, mdl_t::version, and version.

◆ Mod_IDP2_Load()

void Mod_IDP2_Load ( model_t * mod,
void * buffer,
void * bufferend )

Definition at line 1324 of file model_alias.c.

1325{
1326 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1327 float iskinwidth, iskinheight;
1328 unsigned char *data;
1329 msurface_t *surface;
1330 md2_t *pinmodel;
1331 unsigned char *base, *datapointer;
1332 md2frame_t *pinframe;
1333 char *inskin;
1334 md2triangle_t *intri;
1335 unsigned short *inst;
1336 struct md2verthash_s
1337 {
1338 struct md2verthash_s *next;
1339 unsigned short xyz;
1340 unsigned short st;
1341 }
1342 *hash, **md2verthash, *md2verthashdata;
1343 skinfile_t *skinfiles;
1344
1345 pinmodel = (md2_t *)buffer;
1346 base = (unsigned char *)buffer;
1347
1348 version = LittleLong (pinmodel->version);
1350 Host_Error ("%s has wrong version number (%i should be %i)",
1352
1354
1367
1368 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1369 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1370 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1371 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1372 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1373 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1374 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1375 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1376
1377 end = LittleLong(pinmodel->ofs_end);
1378 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1379 Host_Error ("%s is not a valid model", loadmodel->name);
1380 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1381 Host_Error ("%s is not a valid model", loadmodel->name);
1382 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1383 Host_Error ("%s is not a valid model", loadmodel->name);
1384 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1385 Host_Error ("%s is not a valid model", loadmodel->name);
1386 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1387 Host_Error ("%s is not a valid model", loadmodel->name);
1388
1389 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1390 numxyz = LittleLong(pinmodel->num_xyz);
1391 numst = LittleLong(pinmodel->num_st);
1396 skinwidth = LittleLong(pinmodel->skinwidth);
1397 skinheight = LittleLong(pinmodel->skinheight);
1398 iskinwidth = 1.0f / skinwidth;
1399 iskinheight = 1.0f / skinheight;
1400
1404 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->numframes * sizeof(animscene_t) + loadmodel->numframes * sizeof(float[6]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1409 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1411
1413
1414 // load the skins
1415 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1416 skinfiles = Mod_LoadSkinFiles();
1417 if (skinfiles)
1418 {
1422 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1423 Mod_FreeSkinFiles(skinfiles);
1424 }
1425 else if (loadmodel->numskins)
1426 {
1427 // skins found (most likely not a player model)
1431 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1433 }
1434 else
1435 {
1436 // no skins (most likely a player model)
1437 loadmodel->numskins = 1;
1442 }
1443
1445 for (i = 0;i < loadmodel->numskins;i++)
1446 {
1449 loadmodel->skinscenes[i].loop = true;
1451 }
1452
1453 // load the triangles and stvert data
1454 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1455 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1456 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1457 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1458 // swap the triangle list
1460 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1461 {
1462 for (j = 0;j < 3;j++)
1463 {
1464 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1465 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1466 if (xyz >= numxyz)
1467 {
1468 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1469 xyz = 0;
1470 }
1471 if (st >= numst)
1472 {
1473 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1474 st = 0;
1475 }
1476 hashindex = (xyz * 256 + st) & 65535;
1477 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1478 if (hash->xyz == xyz && hash->st == st)
1479 break;
1480 if (hash == NULL)
1481 {
1482 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1483 hash->xyz = xyz;
1484 hash->st = st;
1485 hash->next = md2verthash[hashindex];
1486 md2verthash[hashindex] = hash;
1487 }
1488 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1489 }
1490 }
1491
1492 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1496 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1497 {
1498 int sts, stt;
1499 hash = md2verthashdata + i;
1500 vertremap[i] = hash->xyz;
1501 sts = LittleShort(inst[hash->st*2+0]);
1502 stt = LittleShort(inst[hash->st*2+1]);
1503 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1504 {
1505 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1506 sts = 0;
1507 stt = 0;
1508 }
1509 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1510 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1511 }
1512
1513 Mem_Free(md2verthash);
1514 Mem_Free(md2verthashdata);
1515
1516 // generate ushort elements array if possible
1517 if (loadmodel->surfmesh.num_vertices <= 65536)
1518 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1520 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1522
1523 // load the frames
1524 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1525 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1526 {
1527 int k;
1528 trivertx_t *v;
1529 trivertx_t *out;
1530 pinframe = (md2frame_t *)datapointer;
1531 datapointer += sizeof(md2frame_t);
1532 // store the frame scale/translate into the appropriate array
1533 for (j = 0;j < 3;j++)
1534 {
1537 }
1538 // convert the vertices
1539 v = (trivertx_t *)datapointer;
1541 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1542 out[k] = v[vertremap[k]];
1543 datapointer += numxyz * sizeof(trivertx_t);
1544
1549 loadmodel->animscenes[i].loop = true;
1550 }
1551
1552 Mem_Free(vertremap);
1553
1558
1559 surface = loadmodel->data_surfaces;
1560 surface->texture = loadmodel->data_textures;
1561 surface->num_firsttriangle = 0;
1563 surface->num_firstvertex = 0;
1565
1566 // Always make a BIH for the first frame, we can use it where possible.
1569 {
1575 }
1576}
#define LittleShort(l)
Definition common.h:90
#define MD2_SKINNAME
Definition model_alias.h:69
#define MD2ALIAS_VERSION
Definition model_alias.h:68
ret xyz
int num_st
int skinheight
int ofs_skins
int ofs_frames
int ofs_glcmds
int num_frames
int num_tris
int num_skins
int ofs_st
int ofs_tris
int ofs_end
int skinwidth
int version
int num_xyz
float translate[3]
Definition model_alias.h:86
float scale[3]
Definition model_alias.h:85
char name[16]
Definition model_alias.h:87
float * data_morphmd2framesize6f

References model_t::AnimateVertices, model_t::animscenes, buffer, model_t::collision_bih, model_t::CompileShadowMap, Con_Printf(), data, surfmesh_t::data_element3i, surfmesh_t::data_element3s, surfmesh_t::data_morphmd2framesize6f, surfmesh_t::data_morphmdlvertex, model_t::data_surfaces, surfmesh_t::data_texcoordtexture2f, model_t::data_textures, dp_strlcpy, model_t::Draw, model_t::DrawDebug, model_t::DrawDepth, model_t::DrawLight, model_t::DrawPrepass, model_t::DrawShadowMap, animscene_t::firstframe, animscene_t::framecount, animscene_t::framerate, Host_Error(), i, int(), cvar_t::integer, surfmesh_t::isanimated, LittleFloat, LittleLong, LittleShort, loadmodel, animscene_t::loop, MATERIALFLAG_WALL, MD2_SKINNAME, MD2ALIAS_VERSION, Mem_Alloc, Mem_Free, model_t::mempool, mod_alias, Mod_Alias_CalculateBoundingBox(), mod_alias_force_animated, Mod_Alias_MorphMesh_CompileFrames(), Mod_BuildAliasSkinsFromSkinFiles(), Mod_CollisionBIH_PointSuperContents_Mesh(), Mod_CollisionBIH_TraceBox(), Mod_CollisionBIH_TraceBrush(), Mod_CollisionBIH_TraceLine(), Mod_CollisionBIH_TracePoint_Mesh(), Mod_FreeSkinFiles(), Mod_LoadCustomMaterial(), Mod_LoadSkinFiles(), Mod_LoadTextureFromQ3Shader(), Mod_MakeCollisionBIH(), Mod_MDL_AnimateVertices(), Mod_MDLMD2MD3_TraceBox(), Mod_MDLMD2MD3_TraceLine(), model_t::modeldatatypestring, model_t::modelsurfaces_sorted, animscene_t::name, md2frame_t::name, model_t::name, NULL, msurface_t::num_firsttriangle, msurface_t::num_firstvertex, md2_t::num_frames, surfmesh_t::num_morphframes, model_t::num_poses, md2_t::num_skins, md2_t::num_st, model_t::num_surfaces, model_t::num_textures, model_t::num_texturesperskin, msurface_t::num_triangles, surfmesh_t::num_triangles, md2_t::num_tris, msurface_t::num_vertices, surfmesh_t::num_vertices, md2_t::num_xyz, model_t::numframes, model_t::numskins, md2_t::ofs_end, md2_t::ofs_frames, md2_t::ofs_glcmds, md2_t::ofs_skins, md2_t::ofs_st, md2_t::ofs_tris, model_t::PointSuperContents, r_mipskins, R_Mod_CompileShadowMap(), R_Mod_Draw(), R_Mod_DrawDebug(), R_Mod_DrawDepth(), R_Mod_DrawLight(), R_Mod_DrawPrepass(), R_Mod_DrawShadowMap(), R_SkinFrame_LoadMissing(), md2frame_t::scale, md2_t::skinheight, model_t::skinscenes, md2_t::skinwidth, ST_RAND, cvar_t::string, model_t::submodelsurfaces_end, model_t::submodelsurfaces_start, SUPERCONTENTS_SOLID, model_t::surfmesh, model_t::synctype, tempmempool, TEXF_ALPHA, TEXF_COMPRESS, TEXF_MIPMAP, TEXF_PICMIP, msurface_t::texture, model_t::TraceBox, model_t::TraceBrush, model_t::TraceLine, model_t::TracePoint, md2frame_t::translate, model_t::type, v, md2_t::version, version, and xyz.

◆ Mod_IDP3_Load()

void Mod_IDP3_Load ( model_t * mod,
void * buffer,
void * bufferend )

Definition at line 1578 of file model_alias.c.

1579{
1580 int i, j, k, version, meshvertices, meshtriangles;
1581 unsigned char *data;
1582 msurface_t *surface;
1583 md3modelheader_t *pinmodel;
1584 md3frameinfo_t *pinframe;
1585 md3mesh_t *pinmesh;
1586 md3tag_t *pintag;
1587 skinfile_t *skinfiles;
1588
1589 pinmodel = (md3modelheader_t *)buffer;
1590
1591 if (memcmp(pinmodel->identifier, "IDP3", 4))
1592 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1593 version = LittleLong (pinmodel->version);
1594 if (version != MD3VERSION)
1595 Host_Error ("%s has wrong version number (%i should be %i)",
1597
1598 skinfiles = Mod_LoadSkinFiles();
1599 if (loadmodel->numskins < 1)
1600 loadmodel->numskins = 1;
1601
1603
1617 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1618 i = LittleLong (pinmodel->flags);
1619 loadmodel->effects = (((unsigned)i & 255) << 24) | (i & 0x00FFFF00);
1620
1621 // set up some global info about the model
1624
1625 // make skinscenes for the skins (no groups)
1627 for (i = 0;i < loadmodel->numskins;i++)
1628 {
1631 loadmodel->skinscenes[i].loop = true;
1633 }
1634
1635 // load frameinfo
1637 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1638 {
1643 loadmodel->animscenes[i].loop = true;
1644 }
1645
1646 // load tags
1648 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1650 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1651 {
1653 for (j = 0;j < 9;j++)
1655 for (j = 0;j < 3;j++)
1656 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1657 //Con_Printf("model \"%s\" frame #%i tag #%i \"%s\"\n", loadmodel->name, i / loadmodel->num_tags, i % loadmodel->num_tags, loadmodel->data_tags[i].name);
1658 }
1659
1660 // load meshes
1661 meshvertices = 0;
1662 meshtriangles = 0;
1663 for (i = 0, pinmesh = (md3mesh_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_meshes));i < loadmodel->num_surfaces;i++, pinmesh = (md3mesh_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_end)))
1664 {
1665 if (memcmp(pinmesh->identifier, "IDP3", 4))
1666 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1667 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1668 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1669 meshvertices += LittleLong(pinmesh->num_vertices);
1670 meshtriangles += LittleLong(pinmesh->num_triangles);
1671 }
1672
1677 loadmodel->surfmesh.num_vertices = meshvertices;
1678 loadmodel->surfmesh.num_triangles = meshtriangles;
1681
1682 // do most allocations as one merged chunk
1683 // This is only robust for C standard types!
1684 data = (unsigned char *)Mem_Alloc(loadmodel->mempool,
1685 meshvertices * sizeof(float[2])
1686 + loadmodel->num_surfaces * sizeof(int)
1687 + meshtriangles * sizeof(int[3])
1688 + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0));
1689 // Pointers must be taken in descending order of alignment requirement!
1690 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data; data += meshvertices * sizeof(float[2]);
1692 loadmodel->surfmesh.data_element3i = (int *)data; data += meshtriangles * sizeof(int[3]);
1693 if (meshvertices <= 65536)
1694 {
1695 loadmodel->surfmesh.data_element3s = (unsigned short *)data; data += meshtriangles * sizeof(unsigned short[3]);
1696 }
1697 // Struct alignment requirements could change so we can't assume them here
1698 // otherwise a safe-looking commit could introduce undefined behaviour!
1702
1703 meshvertices = 0;
1704 meshtriangles = 0;
1705 for (i = 0, pinmesh = (md3mesh_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_meshes));i < loadmodel->num_surfaces;i++, pinmesh = (md3mesh_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_end)))
1706 {
1707 if (memcmp(pinmesh->identifier, "IDP3", 4))
1708 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1710 surface = loadmodel->data_surfaces + i;
1711 surface->texture = loadmodel->data_textures + i;
1712 surface->num_firsttriangle = meshtriangles;
1713 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1714 surface->num_firstvertex = meshvertices;
1715 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1716 meshvertices += surface->num_vertices;
1717 meshtriangles += surface->num_triangles;
1718
1719 for (j = 0;j < surface->num_triangles * 3;j++)
1720 {
1721 int e = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1722 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = e;
1724 loadmodel->surfmesh.data_element3s[j + surface->num_firsttriangle * 3] = e;
1725 }
1726 for (j = 0;j < surface->num_vertices;j++)
1727 {
1728 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1729 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1730 }
1731 for (j = 0;j < loadmodel->numframes;j++)
1732 {
1733 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1735 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1736 {
1737 out->origin[0] = LittleShort(in->origin[0]);
1738 out->origin[1] = LittleShort(in->origin[1]);
1739 out->origin[2] = LittleShort(in->origin[2]);
1740 out->pitch = in->pitch;
1741 out->yaw = in->yaw;
1742 }
1743 }
1744
1745 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1746
1748 }
1751 Mod_FreeSkinFiles(skinfiles);
1755
1756 // Always make a BIH for the first frame, we can use it where possible.
1759 {
1765 }
1766}
static void Mod_MD3_AnimateVertices(const model_t *RESTRICT model, const frameblend_t *RESTRICT frameblend, const skeleton_t *skeleton, float *RESTRICT vertex3f, float *RESTRICT normal3f, float *RESTRICT svector3f, float *RESTRICT tvector3f)
#define MD3VERSION
char name[MD3NAME]
float matrixgl[12]
char name[MD3FRAMENAME]
int lump_elements
int num_shaders
char identifier[4]
int num_triangles
int lump_shaders
int num_vertices
char name[MD3NAME]
int lump_framevertices
int lump_texcoords
float rotationmatrix[9]
char name[MD3NAME]
float origin[3]
unsigned char pitch
unsigned char yaw
short origin[3]
int num_tagframes
aliastag_t * data_tags
struct md3vertex_s * data_morphmd3vertex

References model_t::AnimateVertices, model_t::animscenes, buffer, model_t::collision_bih, model_t::CompileShadowMap, data, surfmesh_t::data_element3i, surfmesh_t::data_element3s, surfmesh_t::data_morphmd3vertex, model_t::data_surfaces, model_t::data_tags, surfmesh_t::data_texcoordtexture2f, model_t::data_textures, dp_strlcpy, model_t::Draw, model_t::DrawDebug, model_t::DrawDepth, model_t::DrawLight, model_t::DrawPrepass, model_t::DrawShadowMap, model_t::effects, animscene_t::firstframe, md3modelheader_t::flags, animscene_t::framecount, animscene_t::framerate, Host_Error(), i, md3mesh_t::identifier, md3modelheader_t::identifier, int(), cvar_t::integer, surfmesh_t::isanimated, LittleFloat, LittleLong, LittleShort, loadmodel, animscene_t::loop, md3mesh_t::lump_elements, md3mesh_t::lump_end, md3modelheader_t::lump_frameinfo, md3mesh_t::lump_framevertices, md3modelheader_t::lump_meshes, md3mesh_t::lump_shaders, md3modelheader_t::lump_tags, md3mesh_t::lump_texcoords, aliastag_t::matrixgl, MD3VERSION, Mem_Alloc, Mem_AllocType, model_t::mempool, mod_alias, Mod_Alias_CalculateBoundingBox(), mod_alias_force_animated, Mod_Alias_MorphMesh_CompileFrames(), Mod_BuildAliasSkinsFromSkinFiles(), Mod_CollisionBIH_PointSuperContents_Mesh(), Mod_CollisionBIH_TraceBox(), Mod_CollisionBIH_TraceBrush(), Mod_CollisionBIH_TraceLine(), Mod_CollisionBIH_TracePoint_Mesh(), Mod_FreeSkinFiles(), Mod_LoadSkinFiles(), Mod_MakeCollisionBIH(), Mod_MakeSortedSurfaces(), Mod_MD3_AnimateVertices(), Mod_MDLMD2MD3_TraceBox(), Mod_MDLMD2MD3_TraceLine(), Mod_ValidateElements(), model_t::modeldatatypestring, model_t::modelsurfaces_sorted, aliastag_t::name, animscene_t::name, md3frameinfo_t::name, md3mesh_t::name, md3tag_t::name, model_t::name, NULL, msurface_t::num_firsttriangle, msurface_t::num_firstvertex, md3mesh_t::num_frames, md3modelheader_t::num_frames, md3modelheader_t::num_meshes, surfmesh_t::num_morphframes, model_t::num_poses, md3mesh_t::num_shaders, model_t::num_surfaces, model_t::num_tagframes, md3modelheader_t::num_tags, model_t::num_tags, model_t::num_textures, model_t::num_texturesperskin, md3mesh_t::num_triangles, msurface_t::num_triangles, surfmesh_t::num_triangles, md3mesh_t::num_vertices, msurface_t::num_vertices, surfmesh_t::num_vertices, model_t::numframes, model_t::numskins, md3tag_t::origin, md3vertex_t::origin, md3vertex_t::pitch, model_t::PointSuperContents, R_Mod_CompileShadowMap(), R_Mod_Draw(), R_Mod_DrawDebug(), R_Mod_DrawDepth(), R_Mod_DrawLight(), R_Mod_DrawPrepass(), R_Mod_DrawShadowMap(), md3tag_t::rotationmatrix, model_t::skinscenes, ST_RAND, cvar_t::string, model_t::submodelsurfaces_end, model_t::submodelsurfaces_start, model_t::surfmesh, model_t::synctype, msurface_t::texture, model_t::TraceBox, model_t::TraceBrush, model_t::TraceLine, model_t::TracePoint, model_t::type, md3modelheader_t::version, version, and md3vertex_t::yaw.

◆ Mod_INTERQUAKEMODEL_Load()

void Mod_INTERQUAKEMODEL_Load ( model_t * mod,
void * buffer,
void * bufferend )

Definition at line 3219 of file model_alias.c.

3220{
3221 unsigned char *data;
3222 const char *text;
3223 const unsigned char *pbase, *pend;
3224 iqmheader_t header;
3225 skinfile_t *skinfiles;
3226 int i, j, k;
3227 float biggestorigin;
3228 const unsigned int *inelements;
3229 int *outelements;
3230 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector, *outcolor;
3231 // this pointers into the file data are read only through Little* functions so they can be unaligned memory
3232 const float *vnormal = NULL;
3233 const float *vposition = NULL;
3234 const float *vtangent = NULL;
3235 const float *vtexcoord = NULL;
3236 const float *vcolor4f = NULL;
3237 const unsigned char *vblendindexes = NULL;
3238 const unsigned char *vblendweights = NULL;
3239 const unsigned char *vcolor4ub = NULL;
3240 const unsigned short *framedata = NULL;
3241 // temporary memory allocations (because the data in the file may be misaligned)
3242 iqmanim_t *anims = NULL;
3243 iqmbounds_t *bounds = NULL;
3244 iqmjoint1_t *joint1 = NULL;
3245 iqmjoint_t *joint = NULL;
3246 iqmmesh_t *meshes = NULL;
3247 iqmpose1_t *pose1 = NULL;
3248 iqmpose_t *pose = NULL;
3249 iqmvertexarray_t *vas = NULL;
3250
3251 pbase = (unsigned char *)buffer;
3252 pend = (unsigned char *)bufferend;
3253
3254 if (pbase + sizeof(iqmheader_t) > pend)
3255 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model %d", loadmodel->name, (int)(pend - pbase));
3256
3257 // copy struct (otherwise it may be misaligned)
3258 // LadyHavoc: okay it's definitely not misaligned here, but for consistency...
3259 memcpy(&header, pbase, sizeof(iqmheader_t));
3260
3261 if (memcmp(header.id, "INTERQUAKEMODEL", 16))
3262 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3263 if (LittleLong(header.version) != 1 && LittleLong(header.version) != 2)
3264 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 and 2 models are currently supported (name = %s)", loadmodel->name);
3265
3267
3270
3271 // byteswap header
3272 header.version = LittleLong(header.version);
3273 header.filesize = LittleLong(header.filesize);
3274 header.flags = LittleLong(header.flags);
3275 header.num_text = LittleLong(header.num_text);
3276 header.ofs_text = LittleLong(header.ofs_text);
3277 header.num_meshes = LittleLong(header.num_meshes);
3278 header.ofs_meshes = LittleLong(header.ofs_meshes);
3280 header.num_vertexes = LittleLong(header.num_vertexes);
3282 header.num_triangles = LittleLong(header.num_triangles);
3283 header.ofs_triangles = LittleLong(header.ofs_triangles);
3284 header.ofs_neighbors = LittleLong(header.ofs_neighbors);
3285 header.num_joints = LittleLong(header.num_joints);
3286 header.ofs_joints = LittleLong(header.ofs_joints);
3287 header.num_poses = LittleLong(header.num_poses);
3288 header.ofs_poses = LittleLong(header.ofs_poses);
3289 header.num_anims = LittleLong(header.num_anims);
3290 header.ofs_anims = LittleLong(header.ofs_anims);
3291 header.num_frames = LittleLong(header.num_frames);
3293 header.ofs_frames = LittleLong(header.ofs_frames);
3294 header.ofs_bounds = LittleLong(header.ofs_bounds);
3295 header.num_comment = LittleLong(header.num_comment);
3296 header.ofs_comment = LittleLong(header.ofs_comment);
3297 header.num_extensions = LittleLong(header.num_extensions);
3298 header.ofs_extensions = LittleLong(header.ofs_extensions);
3299
3300 if (header.version == 1)
3301 {
3302 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend ||
3303 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose1_t) > pend)
3304 {
3305 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3306 return;
3307 }
3308 }
3309 else
3310 {
3311 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint_t) > pend ||
3312 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose_t) > pend)
3313 {
3314 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3315 return;
3316 }
3317 }
3318 if (pbase + header.ofs_text + header.num_text > pend ||
3319 pbase + header.ofs_meshes + header.num_meshes*sizeof(iqmmesh_t) > pend ||
3320 pbase + header.ofs_vertexarrays + header.num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3321 pbase + header.ofs_triangles + header.num_triangles*sizeof(int[3]) > pend ||
3322 (header.ofs_neighbors && pbase + header.ofs_neighbors + header.num_triangles*sizeof(int[3]) > pend) ||
3323 pbase + header.ofs_anims + header.num_anims*sizeof(iqmanim_t) > pend ||
3324 pbase + header.ofs_frames + header.num_frames*header.num_framechannels*sizeof(unsigned short) > pend ||
3325 (header.ofs_bounds && pbase + header.ofs_bounds + header.num_frames*sizeof(iqmbounds_t) > pend) ||
3326 pbase + header.ofs_comment + header.num_comment > pend)
3327 {
3328 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3329 return;
3330 }
3331
3332 // Structs will be copied for alignment in memory, otherwise we crash on Sparc, PowerPC and others
3333 // and get big spam from UBSan, because these offsets may not be aligned.
3334 if (header.num_vertexarrays)
3335 vas = (iqmvertexarray_t *)(pbase + header.ofs_vertexarrays);
3336 if (header.num_anims)
3337 anims = (iqmanim_t *)(pbase + header.ofs_anims);
3338 if (header.ofs_bounds)
3339 bounds = (iqmbounds_t *)(pbase + header.ofs_bounds);
3340 if (header.num_meshes)
3341 meshes = (iqmmesh_t *)(pbase + header.ofs_meshes);
3342
3343 for (i = 0;i < (int)header.num_vertexarrays;i++)
3344 {
3346 size_t vsize;
3347
3348 memcpy(&va, &vas[i], sizeof(iqmvertexarray_t));
3349 va.type = LittleLong(va.type);
3350 va.flags = LittleLong(va.flags);
3351 va.format = LittleLong(va.format);
3352 va.size = LittleLong(va.size);
3353 va.offset = LittleLong(va.offset);
3354 vsize = header.num_vertexes*va.size;
3355 switch (va.format)
3356 {
3357 case IQM_FLOAT: vsize *= sizeof(float); break;
3358 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3359 default: continue;
3360 }
3361 if (pbase + va.offset + vsize > pend)
3362 continue;
3363 // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
3364 switch (va.type)
3365 {
3366 case IQM_POSITION:
3367 if (va.format == IQM_FLOAT && va.size == 3)
3368 vposition = (const float *)(pbase + va.offset);
3369 break;
3370 case IQM_TEXCOORD:
3371 if (va.format == IQM_FLOAT && va.size == 2)
3372 vtexcoord = (const float *)(pbase + va.offset);
3373 break;
3374 case IQM_NORMAL:
3375 if (va.format == IQM_FLOAT && va.size == 3)
3376 vnormal = (const float *)(pbase + va.offset);
3377 break;
3378 case IQM_TANGENT:
3379 if (va.format == IQM_FLOAT && va.size == 4)
3380 vtangent = (const float *)(pbase + va.offset);
3381 break;
3382 case IQM_BLENDINDEXES:
3383 if (va.format == IQM_UBYTE && va.size == 4)
3384 vblendindexes = (const unsigned char *)(pbase + va.offset);
3385 break;
3386 case IQM_BLENDWEIGHTS:
3387 if (va.format == IQM_UBYTE && va.size == 4)
3388 vblendweights = (const unsigned char *)(pbase + va.offset);
3389 break;
3390 case IQM_COLOR:
3391 if (va.format == IQM_FLOAT && va.size == 4)
3392 vcolor4f = (const float *)(pbase + va.offset);
3393 if (va.format == IQM_UBYTE && va.size == 4)
3394 vcolor4ub = (const unsigned char *)(pbase + va.offset);
3395 break;
3396 }
3397 }
3398 if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights))))
3399 {
3400 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3401 return;
3402 }
3403
3404 text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
3405
3417
3418 // load external .skin files if present
3419 skinfiles = Mod_LoadSkinFiles();
3420 if (loadmodel->numskins < 1)
3421 loadmodel->numskins = 1;
3422
3423 loadmodel->numframes = max(header.num_anims, 1);
3424 loadmodel->num_bones = header.num_joints;
3425 loadmodel->num_poses = max(header.num_frames, 1);
3432
3433 // do most allocations as one merged chunk
3434 // This is only robust for C standard types!
3435 data = (unsigned char *)Mem_Alloc(loadmodel->mempool,
3436 loadmodel->surfmesh.num_vertices * (sizeof(float[14]) + (vcolor4f || vcolor4ub ? sizeof(float[4]) : 0))
3437 + loadmodel->num_bones * sizeof(float[12])
3438 + loadmodel->num_surfaces * sizeof(int)
3439 + loadmodel->surfmesh.num_triangles * sizeof(int[3])
3440 + (loadmodel->surfmesh.num_vertices <= 65536 ? loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]) : 0)
3441 + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7])
3442 + (vblendindexes && vblendweights ? loadmodel->surfmesh.num_vertices * (sizeof(unsigned short) + sizeof(unsigned char[2][4])) : 0));
3443 // Pointers must be taken in descending order of alignment requirement!
3444 loadmodel->surfmesh.data_vertex3f = (float *)data; data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
3445 loadmodel->surfmesh.data_svector3f = (float *)data; data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
3446 loadmodel->surfmesh.data_tvector3f = (float *)data; data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
3447 loadmodel->surfmesh.data_normal3f = (float *)data; data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
3449 if (vcolor4f || vcolor4ub)
3450 {
3451 loadmodel->surfmesh.data_lightmapcolor4f = (float *)data; data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
3452 }
3453 loadmodel->data_baseboneposeinverse = (float *)data; data += loadmodel->num_bones * sizeof(float[12]);
3455 loadmodel->surfmesh.data_element3i = (int *)data; data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
3456 loadmodel->data_poses7s = (short *)data; data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
3457 if (loadmodel->surfmesh.num_vertices <= 65536)
3458 {
3459 loadmodel->surfmesh.data_element3s = (unsigned short *)data; data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
3460 }
3461 if (vblendindexes && vblendweights)
3462 {
3464 loadmodel->surfmesh.blends = (unsigned short *)data; data += loadmodel->surfmesh.num_vertices * sizeof(unsigned short);
3465 loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data; data += loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]);
3466 loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data; data += loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]);
3467 }
3468 // Struct alignment requirements could change so we can't assume them here
3469 // otherwise a safe-looking commit could introduce undefined behaviour!
3475 if (vblendindexes && vblendweights)
3477
3478 for (i = 0;i < loadmodel->numskins;i++)
3479 {
3482 loadmodel->skinscenes[i].loop = true;
3484 }
3485
3486 // load the bone info
3487 if (header.version == 1)
3488 {
3489 iqmjoint1_t *injoints1 = (iqmjoint1_t *)(pbase + header.ofs_joints);
3490
3491 if (loadmodel->num_bones)
3493 for (i = 0;i < loadmodel->num_bones;i++)
3494 {
3495 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3496 iqmjoint1_t injoint1;
3497
3498 memcpy(&injoint1, &injoints1[i], sizeof(iqmjoint1_t));
3499 joint1[i].name = LittleLong(injoint1.name);
3500 joint1[i].parent = LittleLong(injoint1.parent);
3501 for (j = 0;j < 3;j++)
3502 {
3503 joint1[i].origin[j] = LittleFloat(injoint1.origin[j]);
3504 joint1[i].rotation[j] = LittleFloat(injoint1.rotation[j]);
3505 joint1[i].scale[j] = LittleFloat(injoint1.scale[j]);
3506 }
3507 dp_strlcpy(loadmodel->data_bones[i].name, &text[joint1[i].name], sizeof(loadmodel->data_bones[i].name));
3508 loadmodel->data_bones[i].parent = joint1[i].parent;
3509 if (loadmodel->data_bones[i].parent >= i)
3510 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3511 Matrix4x4_FromDoom3Joint(&relbase, joint1[i].origin[0], joint1[i].origin[1], joint1[i].origin[2], joint1[i].rotation[0], joint1[i].rotation[1], joint1[i].rotation[2]);
3512 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3513 if (loadmodel->data_bones[i].parent >= 0)
3514 {
3516 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3518 }
3520 }
3521 }
3522 else
3523 {
3524 iqmjoint_t *injoints = (iqmjoint_t *)(pbase + header.ofs_joints);
3525
3526 if (header.num_joints)
3528 for (i = 0;i < loadmodel->num_bones;i++)
3529 {
3530 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3531 iqmjoint_t injoint;
3532
3533 memcpy(&injoint, &injoints[i], sizeof(iqmjoint_t));
3534 joint[i].name = LittleLong(injoint.name);
3535 joint[i].parent = LittleLong(injoint.parent);
3536 for (j = 0;j < 3;j++)
3537 {
3538 joint[i].origin[j] = LittleFloat(injoint.origin[j]);
3539 joint[i].rotation[j] = LittleFloat(injoint.rotation[j]);
3540 joint[i].scale[j] = LittleFloat(injoint.scale[j]);
3541 }
3542 joint[i].rotation[3] = LittleFloat(injoint.rotation[3]);
3543 dp_strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3544 loadmodel->data_bones[i].parent = joint[i].parent;
3545 if (loadmodel->data_bones[i].parent >= i)
3546 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3547 if (joint[i].rotation[3] > 0)
3548 Vector4Negate(joint[i].rotation, joint[i].rotation);
3549 Vector4Normalize2(joint[i].rotation, joint[i].rotation);
3550 Matrix4x4_FromDoom3Joint(&relbase, joint[i].origin[0], joint[i].origin[1], joint[i].origin[2], joint[i].rotation[0], joint[i].rotation[1], joint[i].rotation[2]);
3551 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3552 if (loadmodel->data_bones[i].parent >= 0)
3553 {
3555 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3557 }
3559 }
3560 }
3561
3562 // set up the animscenes based on the anims
3563 for (i = 0;i < (int)header.num_anims;i++)
3564 {
3565 iqmanim_t anim;
3566
3567 memcpy(&anim, &anims[i], sizeof(iqmanim_t));
3568 anim.name = LittleLong(anim.name);
3569 anim.first_frame = LittleLong(anim.first_frame);
3570 anim.num_frames = LittleLong(anim.num_frames);
3571 anim.framerate = LittleFloat(anim.framerate);
3572 anim.flags = LittleLong(anim.flags);
3573 dp_strlcpy(loadmodel->animscenes[i].name, &text[anim.name], sizeof(loadmodel->animscenes[i].name));
3576 loadmodel->animscenes[i].loop = ((anim.flags & IQM_LOOP) != 0);
3578 }
3579 if (header.num_anims <= 0)
3580 {
3581 dp_strlcpy(loadmodel->animscenes[0].name, "static", sizeof(loadmodel->animscenes[0].name));
3584 loadmodel->animscenes[0].loop = true;
3586 }
3587
3591
3592 biggestorigin = 0;
3593 if (header.version == 1)
3594 {
3595 iqmpose1_t *inposes1 = (iqmpose1_t *)(pbase + header.ofs_poses);
3596
3597 if (header.num_poses)
3598 pose1 = (iqmpose1_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose1_t));
3599 for (i = 0;i < (int)header.num_poses;i++)
3600 {
3601 float f;
3602 iqmpose1_t inpose;
3603
3604 memcpy(&inpose, &inposes1[i], sizeof(iqmpose1_t));
3605 pose1[i].parent = LittleLong(inpose.parent);
3606 pose1[i].channelmask = LittleLong(inpose.channelmask);
3607 for (j = 0;j < 9;j++)
3608 {
3609 pose1[i].channeloffset[j] = LittleFloat(inpose.channeloffset[j]);
3610 pose1[i].channelscale[j] = LittleFloat(inpose.channelscale[j]);
3611 }
3612 f = fabs(pose1[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3613 f = fabs(pose1[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3614 f = fabs(pose1[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3615 f = fabs(pose1[i].channeloffset[0] + 0xFFFF*pose1[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3616 f = fabs(pose1[i].channeloffset[1] + 0xFFFF*pose1[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3617 f = fabs(pose1[i].channeloffset[2] + 0xFFFF*pose1[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3618 }
3619 if (header.num_frames <= 0)
3620 {
3621 for (i = 0;i < loadmodel->num_bones;i++)
3622 {
3623 float f;
3624 f = fabs(joint1[i].origin[0]); biggestorigin = max(biggestorigin, f);
3625 f = fabs(joint1[i].origin[1]); biggestorigin = max(biggestorigin, f);
3626 f = fabs(joint1[i].origin[2]); biggestorigin = max(biggestorigin, f);
3627 }
3628 }
3629 }
3630 else
3631 {
3632 iqmpose_t *inposes = (iqmpose_t *)(pbase + header.ofs_poses);
3633
3634 if (header.num_poses)
3635 pose = (iqmpose_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose_t));
3636 for (i = 0;i < (int)header.num_poses;i++)
3637 {
3638 float f;
3639 iqmpose_t inpose;
3640
3641 memcpy(&inpose, &inposes[i], sizeof(iqmpose_t));
3642 pose[i].parent = LittleLong(inpose.parent);
3643 pose[i].channelmask = LittleLong(inpose.channelmask);
3644 for (j = 0;j < 10;j++)
3645 {
3646 pose[i].channeloffset[j] = LittleFloat(inpose.channeloffset[j]);
3647 pose[i].channelscale[j] = LittleFloat(inpose.channelscale[j]);
3648 }
3649 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3650 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3651 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3652 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3653 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3654 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3655 }
3656 if (header.num_frames <= 0)
3657 {
3658 for (i = 0;i < loadmodel->num_bones;i++)
3659 {
3660 float f;
3661 f = fabs(joint[i].origin[0]); biggestorigin = max(biggestorigin, f);
3662 f = fabs(joint[i].origin[1]); biggestorigin = max(biggestorigin, f);
3663 f = fabs(joint[i].origin[2]); biggestorigin = max(biggestorigin, f);
3664 }
3665 }
3666 }
3667 loadmodel->num_posescale = biggestorigin / 32767.0f;
3669
3670 // load the pose data
3671 // this unaligned memory access is safe (LittleShort reads as bytes)
3672 framedata = (const unsigned short *)(pbase + header.ofs_frames);
3673 if (header.version == 1)
3674 {
3675 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3676 {
3677 for (j = 0;j < (int)header.num_poses;j++, k++)
3678 {
3679 float qx, qy, qz, qw;
3680 loadmodel->data_poses7s[k*7 + 0] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[0] + (pose1[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[0] : 0));
3681 loadmodel->data_poses7s[k*7 + 1] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[1] + (pose1[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[1] : 0));
3682 loadmodel->data_poses7s[k*7 + 2] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[2] + (pose1[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[2] : 0));
3683 qx = pose1[j].channeloffset[3] + (pose1[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[3] : 0);
3684 qy = pose1[j].channeloffset[4] + (pose1[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[4] : 0);
3685 qz = pose1[j].channeloffset[5] + (pose1[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[5] : 0);
3686 qw = 1.0f - (qx*qx + qy*qy + qz*qz);
3687 qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
3688 loadmodel->data_poses7s[k*7 + 3] = 32767.0f * qx;
3689 loadmodel->data_poses7s[k*7 + 4] = 32767.0f * qy;
3690 loadmodel->data_poses7s[k*7 + 5] = 32767.0f * qz;
3691 loadmodel->data_poses7s[k*7 + 6] = 32767.0f * qw;
3692 // skip scale data for now
3693 if(pose1[j].channelmask&64) framedata++;
3694 if(pose1[j].channelmask&128) framedata++;
3695 if(pose1[j].channelmask&256) framedata++;
3696 }
3697 }
3698 if (header.num_frames <= 0)
3699 {
3700 for (i = 0;i < loadmodel->num_bones;i++)
3701 {
3702 float qx, qy, qz, qw;
3703 loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
3704 loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
3705 loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
3706 qx = joint1[i].rotation[0];
3707 qy = joint1[i].rotation[1];
3708 qz = joint1[i].rotation[2];
3709 qw = 1.0f - (qx*qx + qy*qy + qz*qz);
3710 qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
3711 loadmodel->data_poses7s[i*7 + 3] = 32767.0f * qx;
3712 loadmodel->data_poses7s[i*7 + 4] = 32767.0f * qy;
3713 loadmodel->data_poses7s[i*7 + 5] = 32767.0f * qz;
3714 loadmodel->data_poses7s[i*7 + 6] = 32767.0f * qw;
3715 }
3716 }
3717 }
3718 else
3719 {
3720 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3721 {
3722 for (j = 0;j < (int)header.num_poses;j++, k++)
3723 {
3724 float rot[4];
3725 loadmodel->data_poses7s[k*7 + 0] = loadmodel->num_poseinvscale * (pose[j].channeloffset[0] + (pose[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[0] : 0));
3726 loadmodel->data_poses7s[k*7 + 1] = loadmodel->num_poseinvscale * (pose[j].channeloffset[1] + (pose[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[1] : 0));
3727 loadmodel->data_poses7s[k*7 + 2] = loadmodel->num_poseinvscale * (pose[j].channeloffset[2] + (pose[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[2] : 0));
3728 rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
3729 rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
3730 rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
3731 rot[3] = pose[j].channeloffset[6] + (pose[j].channelmask&64 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[6] : 0);
3732 if (rot[3] > 0)
3733 Vector4Negate(rot, rot);
3734 Vector4Normalize2(rot, rot);
3735 loadmodel->data_poses7s[k*7 + 3] = 32767.0f * rot[0];
3736 loadmodel->data_poses7s[k*7 + 4] = 32767.0f * rot[1];
3737 loadmodel->data_poses7s[k*7 + 5] = 32767.0f * rot[2];
3738 loadmodel->data_poses7s[k*7 + 6] = 32767.0f * rot[3];
3739 // skip scale data for now
3740 if(pose[j].channelmask&128) framedata++;
3741 if(pose[j].channelmask&256) framedata++;
3742 if(pose[j].channelmask&512) framedata++;
3743 }
3744 }
3745 if (header.num_frames <= 0)
3746 {
3747 for (i = 0;i < loadmodel->num_bones;i++)
3748 {
3749 loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
3750 loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
3751 loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
3752 loadmodel->data_poses7s[i*7 + 3] = 32767.0f * joint[i].rotation[0];
3753 loadmodel->data_poses7s[i*7 + 4] = 32767.0f * joint[i].rotation[1];
3754 loadmodel->data_poses7s[i*7 + 5] = 32767.0f * joint[i].rotation[2];
3755 loadmodel->data_poses7s[i*7 + 6] = 32767.0f * joint[i].rotation[3];
3756 }
3757 }
3758 }
3759
3760 // load bounding box data
3761 if (header.ofs_bounds)
3762 {
3763 float xyradius = 0, radius = 0;
3766 for (i = 0; i < (int)header.num_frames;i++)
3767 {
3769 bound.mins[0] = LittleFloat(bounds[i].mins[0]);
3770 bound.mins[1] = LittleFloat(bounds[i].mins[1]);
3771 bound.mins[2] = LittleFloat(bounds[i].mins[2]);
3772 bound.maxs[0] = LittleFloat(bounds[i].maxs[0]);
3773 bound.maxs[1] = LittleFloat(bounds[i].maxs[1]);
3774 bound.maxs[2] = LittleFloat(bounds[i].maxs[2]);
3775 bound.xyradius = LittleFloat(bounds[i].xyradius);
3776 bound.radius = LittleFloat(bounds[i].radius);
3777 if (!i)
3778 {
3781 }
3782 else
3783 {
3784 if (loadmodel->normalmins[0] > bound.mins[0]) loadmodel->normalmins[0] = bound.mins[0];
3785 if (loadmodel->normalmins[1] > bound.mins[1]) loadmodel->normalmins[1] = bound.mins[1];
3786 if (loadmodel->normalmins[2] > bound.mins[2]) loadmodel->normalmins[2] = bound.mins[2];
3787 if (loadmodel->normalmaxs[0] < bound.maxs[0]) loadmodel->normalmaxs[0] = bound.maxs[0];
3788 if (loadmodel->normalmaxs[1] < bound.maxs[1]) loadmodel->normalmaxs[1] = bound.maxs[1];
3789 if (loadmodel->normalmaxs[2] < bound.maxs[2]) loadmodel->normalmaxs[2] = bound.maxs[2];
3790 }
3791 if (bound.xyradius > xyradius)
3792 xyradius = bound.xyradius;
3793 if (bound.radius > radius)
3794 radius = bound.radius;
3795 }
3796 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3797 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3802 loadmodel->radius = radius;
3803 loadmodel->radius2 = radius * radius;
3804 }
3805
3806 // load triangle data
3807 // this unaligned memory access is safe (LittleLong reads as bytes)
3808 inelements = (const unsigned int *)(pbase + header.ofs_triangles);
3809 outelements = loadmodel->surfmesh.data_element3i;
3810 for (i = 0;i < (int)header.num_triangles;i++)
3811 {
3812 outelements[0] = LittleLong(inelements[0]);
3813 outelements[1] = LittleLong(inelements[1]);
3814 outelements[2] = LittleLong(inelements[2]);
3815 outelements += 3;
3816 inelements += 3;
3817 }
3819 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3822
3823 // load vertex data
3824 // this unaligned memory access is safe (LittleFloat reads as bytes)
3825 outvertex = loadmodel->surfmesh.data_vertex3f;
3826 for (i = 0;i < (int)header.num_vertexes;i++)
3827 {
3828 outvertex[0] = LittleFloat(vposition[0]);
3829 outvertex[1] = LittleFloat(vposition[1]);
3830 outvertex[2] = LittleFloat(vposition[2]);
3831 vposition += 3;
3832 outvertex += 3;
3833 }
3834
3836 // this unaligned memory access is safe (LittleFloat reads as bytes)
3837 for (i = 0;i < (int)header.num_vertexes;i++)
3838 {
3839 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3840 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3841 vtexcoord += 2;
3842 outtexcoord += 2;
3843 }
3844
3845 // this unaligned memory access is safe (LittleFloat reads as bytes)
3846 if(vnormal)
3847 {
3848 outnormal = loadmodel->surfmesh.data_normal3f;
3849 for (i = 0;i < (int)header.num_vertexes;i++)
3850 {
3851 outnormal[0] = LittleFloat(vnormal[0]);
3852 outnormal[1] = LittleFloat(vnormal[1]);
3853 outnormal[2] = LittleFloat(vnormal[2]);
3854 vnormal += 3;
3855 outnormal += 3;
3856 }
3857 }
3858
3859 // this unaligned memory access is safe (LittleFloat reads as bytes)
3860 if(vnormal && vtangent)
3861 {
3862 outnormal = loadmodel->surfmesh.data_normal3f;
3863 outsvector = loadmodel->surfmesh.data_svector3f;
3864 outtvector = loadmodel->surfmesh.data_tvector3f;
3865 for (i = 0;i < (int)header.num_vertexes;i++)
3866 {
3867 outsvector[0] = LittleFloat(vtangent[0]);
3868 outsvector[1] = LittleFloat(vtangent[1]);
3869 outsvector[2] = LittleFloat(vtangent[2]);
3870 if(LittleFloat(vtangent[3]) < 0)
3871 CrossProduct(outsvector, outnormal, outtvector);
3872 else
3873 CrossProduct(outnormal, outsvector, outtvector);
3874 vtangent += 4;
3875 outnormal += 3;
3876 outsvector += 3;
3877 outtvector += 3;
3878 }
3879 }
3880
3881 // this unaligned memory access is safe (all bytes)
3882 if (vblendindexes && vblendweights)
3883 {
3884 for (i = 0; i < (int)header.num_vertexes;i++)
3885 {
3886 blendweights_t weights;
3887 memcpy(weights.index, vblendindexes + i*4, 4);
3888 memcpy(weights.influence, vblendweights + i*4, 4);
3891 loadmodel->surfmesh.data_skeletalindex4ub[i*4+1] = weights.index[1];
3892 loadmodel->surfmesh.data_skeletalindex4ub[i*4+2] = weights.index[2];
3893 loadmodel->surfmesh.data_skeletalindex4ub[i*4+3] = weights.index[3];
3898 }
3899 }
3900
3901 if (vcolor4f)
3902 {
3904 // this unaligned memory access is safe (LittleFloat reads as bytes)
3905 for (i = 0;i < (int)header.num_vertexes;i++)
3906 {
3907 outcolor[0] = LittleFloat(vcolor4f[0]);
3908 outcolor[1] = LittleFloat(vcolor4f[1]);
3909 outcolor[2] = LittleFloat(vcolor4f[2]);
3910 outcolor[3] = LittleFloat(vcolor4f[3]);
3911 vcolor4f += 4;
3912 outcolor += 4;
3913 }
3914 }
3915 else if (vcolor4ub)
3916 {
3918 // this unaligned memory access is safe (all bytes)
3919 for (i = 0;i < (int)header.num_vertexes;i++)
3920 {
3921 outcolor[0] = vcolor4ub[0] * (1.0f / 255.0f);
3922 outcolor[1] = vcolor4ub[1] * (1.0f / 255.0f);
3923 outcolor[2] = vcolor4ub[2] * (1.0f / 255.0f);
3924 outcolor[3] = vcolor4ub[3] * (1.0f / 255.0f);
3925 vcolor4ub += 4;
3926 outcolor += 4;
3927 }
3928 }
3929
3930 // load meshes
3931 for (i = 0;i < (int)header.num_meshes;i++)
3932 {
3933 iqmmesh_t mesh;
3934 msurface_t *surface;
3935
3936 memcpy(&mesh, &meshes[i], sizeof(iqmmesh_t));
3937 mesh.name = LittleLong(mesh.name);
3938 mesh.material = LittleLong(mesh.material);
3943
3945 surface = loadmodel->data_surfaces + i;
3946 surface->texture = loadmodel->data_textures + i;
3947 surface->num_firsttriangle = mesh.first_triangle;
3948 surface->num_triangles = mesh.num_triangles;
3949 surface->num_firstvertex = mesh.first_vertex;
3950 surface->num_vertices = mesh.num_vertexes;
3951
3952 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh.name], &text[mesh.material]);
3953 }
3954
3955 Mod_FreeSkinFiles(skinfiles);
3957
3958 // compute all the mesh information that was not loaded from the file
3959 if (!vnormal)
3961 if (!vnormal || !vtangent)
3963 if (!header.ofs_bounds)
3965
3966 // Always make a BIH for the first frame, we can use it where possible.
3969 {
3975 }
3976
3977 if (joint) { Mem_Free(joint); joint = NULL; }
3978 if (joint1) { Mem_Free(joint1); joint1 = NULL; }
3979 if (pose) { Mem_Free(pose); pose = NULL; }
3980 if (pose1) { Mem_Free(pose1); pose1 = NULL; }
3981}
char * va(char *buf, size_t buflen, const char *format,...)
Definition common.c:972
vector mins
vector maxs
vector origin
#define Vector4Normalize2(v, dest)
Definition mathlib.h:87
#define bound(min, num, max)
Definition mathlib.h:34
#define CrossProduct(a, b, out)
Definition mathlib.h:103
#define Vector4Negate(in, out)
Definition mathlib.h:85
void Matrix4x4_FromDoom3Joint(matrix4x4_t *m, double ox, double oy, double oz, double x, double y, double z)
Definition matrixlib.c:1582
static int Mod_Skeletal_AddBlend(model_t *model, const blendweights_t *newweights)
#define IQM_TANGENT
Definition model_iqm.h:35
#define IQM_TEXCOORD
Definition model_iqm.h:33
#define IQM_NORMAL
Definition model_iqm.h:34
#define IQM_UBYTE
Definition model_iqm.h:42
#define IQM_FLOAT
Definition model_iqm.h:48
#define IQM_COLOR
Definition model_iqm.h:38
#define IQM_BLENDINDEXES
Definition model_iqm.h:36
#define IQM_BLENDWEIGHTS
Definition model_iqm.h:37
#define IQM_POSITION
Definition model_iqm.h:32
#define IQM_LOOP
Definition model_iqm.h:52
void Mod_BuildNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const int *elements, float *normal3f, qbool areaweighting)
precision highp float
Definition shader_glsl.h:53
unsigned char index[4]
unsigned char influence[4]
float framerate
Definition model_iqm.h:96
unsigned int first_frame
Definition model_iqm.h:95
unsigned int name
Definition model_iqm.h:94
unsigned int flags
Definition model_iqm.h:97
unsigned int num_frames
Definition model_iqm.h:95
float mins[3]
Definition model_iqm.h:121
unsigned int ofs_extensions
Definition model_iqm.h:19
unsigned int ofs_frames
Definition model_iqm.h:17
unsigned int ofs_anims
Definition model_iqm.h:16
unsigned int ofs_vertexarrays
Definition model_iqm.h:12
unsigned int filesize
Definition model_iqm.h:8
unsigned int ofs_text
Definition model_iqm.h:10
unsigned int num_frames
Definition model_iqm.h:17
unsigned int num_comment
Definition model_iqm.h:18
unsigned int ofs_joints
Definition model_iqm.h:14
unsigned int num_triangles
Definition model_iqm.h:13
unsigned int num_vertexarrays
Definition model_iqm.h:12
unsigned int num_text
Definition model_iqm.h:10
unsigned int ofs_bounds
Definition model_iqm.h:17
unsigned int num_framechannels
Definition model_iqm.h:17
unsigned int num_anims
Definition model_iqm.h:16
unsigned int ofs_neighbors
Definition model_iqm.h:13
char id[16]
Definition model_iqm.h:6
unsigned int num_joints
Definition model_iqm.h:14
unsigned int num_vertexes
Definition model_iqm.h:12
unsigned int ofs_meshes
Definition model_iqm.h:11
unsigned int ofs_poses
Definition model_iqm.h:15
unsigned int num_poses
Definition model_iqm.h:15
unsigned int flags
Definition model_iqm.h:9
unsigned int ofs_comment
Definition model_iqm.h:18
unsigned int num_meshes
Definition model_iqm.h:11
unsigned int version
Definition model_iqm.h:7
unsigned int num_extensions
Definition model_iqm.h:19
unsigned int ofs_triangles
Definition model_iqm.h:13
float rotation[3]
Definition model_iqm.h:64
float origin[3]
Definition model_iqm.h:64
float scale[3]
Definition model_iqm.h:64
signed int parent
Definition model_iqm.h:63
unsigned int name
Definition model_iqm.h:62
float scale[3]
Definition model_iqm.h:72
float origin[3]
Definition model_iqm.h:72
unsigned int name
Definition model_iqm.h:70
signed int parent
Definition model_iqm.h:71
float rotation[4]
Definition model_iqm.h:72
unsigned int num_triangles
Definition model_iqm.h:28
unsigned int num_vertexes
Definition model_iqm.h:27
unsigned int material
Definition model_iqm.h:26
unsigned int name
Definition model_iqm.h:25
unsigned int first_vertex
Definition model_iqm.h:27
unsigned int first_triangle
Definition model_iqm.h:28
unsigned int channelmask
Definition model_iqm.h:79
float channeloffset[9]
Definition model_iqm.h:80
float channelscale[9]
Definition model_iqm.h:80
signed int parent
Definition model_iqm.h:78
unsigned int channelmask
Definition model_iqm.h:87
float channelscale[10]
Definition model_iqm.h:88
signed int parent
Definition model_iqm.h:86
float channeloffset[10]
Definition model_iqm.h:88
float * data_lightmapcolor4f

References model_t::AnimateVertices, model_t::animscenes, surfmesh_t::blends, bound, buffer, iqmpose1_t::channelmask, iqmpose_t::channelmask, iqmpose1_t::channeloffset, iqmpose_t::channeloffset, iqmpose1_t::channelscale, iqmpose_t::channelscale, model_t::collision_bih, model_t::CompileShadowMap, Con_Printf(), CrossProduct, data, model_t::data_baseboneposeinverse, surfmesh_t::data_blendweights, model_t::data_bones, surfmesh_t::data_element3i, surfmesh_t::data_element3s, surfmesh_t::data_lightmapcolor4f, surfmesh_t::data_normal3f, model_t::data_poses7s, surfmesh_t::data_skeletalindex4ub, surfmesh_t::data_skeletalweight4ub, model_t::data_surfaces, surfmesh_t::data_svector3f, surfmesh_t::data_texcoordtexture2f, model_t::data_textures, surfmesh_t::data_tvector3f, surfmesh_t::data_vertex3f, dp_strlcpy, model_t::Draw, model_t::DrawDebug, model_t::DrawDepth, model_t::DrawLight, model_t::DrawPrepass, model_t::DrawShadowMap, f, fabs(), iqmheader_t::filesize, iqmanim_t::first_frame, iqmmesh_t::first_triangle, iqmmesh_t::first_vertex, animscene_t::firstframe, iqmanim_t::flags, iqmheader_t::flags, float, animscene_t::framecount, animscene_t::framerate, iqmanim_t::framerate, Host_Error(), i, iqmheader_t::id, blendweights_t::index, blendweights_t::influence, int(), cvar_t::integer, IQM_BLENDINDEXES, IQM_BLENDWEIGHTS, IQM_COLOR, IQM_FLOAT, IQM_LOOP, IQM_NORMAL, IQM_POSITION, IQM_TANGENT, IQM_TEXCOORD, IQM_UBYTE, surfmesh_t::isanimated, LittleFloat, LittleLong, LittleShort, loadmodel, animscene_t::loop, iqmmesh_t::material, Matrix4x4_Concat(), Matrix4x4_FromArray12FloatD3D(), Matrix4x4_FromDoom3Joint(), Matrix4x4_Invert_Simple(), Matrix4x4_ToArray12FloatD3D(), max, maxs, Mem_Alloc, Mem_AllocType, Mem_Free, model_t::mempool, iqmbounds_t::mins, mins, mod_alias, Mod_Alias_CalculateBoundingBox(), mod_alias_force_animated, Mod_BuildAliasSkinsFromSkinFiles(), Mod_BuildNormals(), Mod_BuildTextureVectorsFromNormals(), Mod_CollisionBIH_PointSuperContents_Mesh(), Mod_CollisionBIH_TraceBox(), Mod_CollisionBIH_TraceBrush(), Mod_CollisionBIH_TraceLine(), Mod_CollisionBIH_TracePoint_Mesh(), Mod_FreeSkinFiles(), Mod_LoadSkinFiles(), Mod_MakeCollisionBIH(), Mod_MakeSortedSurfaces(), Mod_MDLMD2MD3_TraceBox(), Mod_MDLMD2MD3_TraceLine(), Mod_Skeletal_AddBlend(), Mod_Skeletal_AnimateVertices(), Mod_ValidateElements(), model_t::modeldatatypestring, model_t::modelsurfaces_sorted, aliasbone_t::name, animscene_t::name, iqmanim_t::name, iqmjoint1_t::name, iqmjoint_t::name, iqmmesh_t::name, model_t::name, model_t::normalmaxs, model_t::normalmins, NULL, iqmheader_t::num_anims, surfmesh_t::num_blends, model_t::num_bones, iqmheader_t::num_comment, iqmheader_t::num_extensions, msurface_t::num_firsttriangle, msurface_t::num_firstvertex, iqmheader_t::num_framechannels, iqmanim_t::num_frames, iqmheader_t::num_frames, iqmheader_t::num_joints, iqmheader_t::num_meshes, model_t::num_poseinvscale, iqmheader_t::num_poses, model_t::num_poses, model_t::num_posescale, model_t::num_surfaces, iqmheader_t::num_text, model_t::num_textures, model_t::num_texturesperskin, iqmheader_t::num_triangles, iqmmesh_t::num_triangles, msurface_t::num_triangles, surfmesh_t::num_triangles, iqmheader_t::num_vertexarrays, iqmheader_t::num_vertexes, iqmmesh_t::num_vertexes, msurface_t::num_vertices, surfmesh_t::num_vertices, model_t::numframes, model_t::numskins, iqmheader_t::ofs_anims, iqmheader_t::ofs_bounds, iqmheader_t::ofs_comment, iqmheader_t::ofs_extensions, iqmheader_t::ofs_frames, iqmheader_t::ofs_joints, iqmheader_t::ofs_meshes, iqmheader_t::ofs_neighbors, iqmheader_t::ofs_poses, iqmheader_t::ofs_text, iqmheader_t::ofs_triangles, iqmheader_t::ofs_vertexarrays, iqmjoint1_t::origin, iqmjoint_t::origin, origin, aliasbone_t::parent, iqmjoint1_t::parent, iqmjoint_t::parent, iqmpose1_t::parent, iqmpose_t::parent, model_t::PointSuperContents, R_Mod_CompileShadowMap(), R_Mod_Draw(), R_Mod_DrawDebug(), R_Mod_DrawDepth(), R_Mod_DrawLight(), R_Mod_DrawPrepass(), R_Mod_DrawShadowMap(), r_smoothnormals_areaweighting, model_t::radius, model_t::radius2, model_t::rotatedmaxs, model_t::rotatedmins, iqmjoint1_t::rotation, iqmjoint_t::rotation, iqmjoint1_t::scale, iqmjoint_t::scale, model_t::skinscenes, sqrt(), ST_RAND, cvar_t::string, model_t::submodelsurfaces_end, model_t::submodelsurfaces_start, model_t::surfmesh, model_t::synctype, msurface_t::texture, model_t::TraceBox, model_t::TraceBrush, model_t::TraceLine, model_t::TracePoint, model_t::type, va(), Vector4Negate, Vector4Normalize2, VectorClear, VectorCopy, iqmheader_t::version, model_t::yawmaxs, and model_t::yawmins.

◆ Mod_MD3_AnimateVertices()

static void Mod_MD3_AnimateVertices ( const model_t *RESTRICT model,
const frameblend_t *RESTRICT frameblend,
const skeleton_t * skeleton,
float *RESTRICT vertex3f,
float *RESTRICT normal3f,
float *RESTRICT svector3f,
float *RESTRICT tvector3f )
static

Definition at line 276 of file model_alias.c.

277{
278 // vertex morph
279 int i, numblends, blendnum;
280 int numverts = model->surfmesh.num_vertices;
281 numblends = 0;
282 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
283 {
284 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
285 if (frameblend[blendnum].lerp > 0)
286 numblends = blendnum + 1;
287 }
288 // special case for the first blend because it avoids some adds and the need to memset the arrays first
289 for (blendnum = 0;blendnum < numblends;blendnum++)
290 {
291 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
292 if (vertex3f)
293 {
294 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
295 if (blendnum == 0)
296 {
297 for (i = 0;i < numverts;i++)
298 {
299 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
300 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
301 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
302 }
303 }
304 else
305 {
306 for (i = 0;i < numverts;i++)
307 {
308 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
309 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
310 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
311 }
312 }
313 }
314 // the yaw and pitch stored in md3 models are 8bit quantized angles
315 // (0-255), and as such a lookup table is very well suited to
316 // decoding them, and since cosine is equivalent to sine with an
317 // extra 45 degree rotation, this uses one lookup table for both
318 // sine and cosine with a +64 bias to get cosine.
319 if (normal3f)
320 {
321 float lerp = frameblend[blendnum].lerp;
322 if (blendnum == 0)
323 {
324 for (i = 0;i < numverts;i++)
325 {
326 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
327 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
328 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
329 }
330 }
331 else
332 {
333 for (i = 0;i < numverts;i++)
334 {
335 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
336 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
337 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
338 }
339 }
340 }
341 if (svector3f)
342 {
343 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
344 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
345 if (blendnum == 0)
346 {
347 for (i = 0;i < numverts;i++, texvecvert++)
348 {
349 VectorScale(texvecvert->svec, f, svector3f + i*3);
350 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
351 }
352 }
353 else
354 {
355 for (i = 0;i < numverts;i++, texvecvert++)
356 {
357 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
358 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
359 }
360 }
361 }
362 }
363}
float scale
#define VectorScale(in, scale, out)
Definition mathlib.h:111
#define VectorMA(a, scale, b, out)
Definition mathlib.h:114
signed char tvec[3]
signed char svec[3]

References f, i, MAX_FRAMEBLENDS, mod_md3_sin, model, md3vertex_t::origin, md3vertex_t::pitch, scale, texvecvertex_t::svec, texvecvertex_t::tvec, VectorMA, VectorScale, and md3vertex_t::yaw.

Referenced by Mod_IDP3_Load().

◆ Mod_MDL_AnimateVertices()

static void Mod_MDL_AnimateVertices ( const model_t *RESTRICT model,
const frameblend_t *RESTRICT frameblend,
const skeleton_t * skeleton,
float *RESTRICT vertex3f,
float *RESTRICT normal3f,
float *RESTRICT svector3f,
float *RESTRICT tvector3f )
static

Definition at line 364 of file model_alias.c.

365{
366 // vertex morph
367 int i, numblends, blendnum;
368 int numverts = model->surfmesh.num_vertices;
369 float translate[3];
370 VectorClear(translate);
371 numblends = 0;
372 // blend the frame translates to avoid redundantly doing so on each vertex
373 // (a bit of a brain twister but it works)
374 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
375 {
376 if (model->surfmesh.data_morphmd2framesize6f)
377 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
378 else
379 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
380 if (frameblend[blendnum].lerp > 0)
381 numblends = blendnum + 1;
382 }
383 // special case for the first blend because it avoids some adds and the need to memset the arrays first
384 for (blendnum = 0;blendnum < numblends;blendnum++)
385 {
386 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
387 if (vertex3f)
388 {
389 float scale[3];
390 if (model->surfmesh.data_morphmd2framesize6f)
391 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
392 else
393 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
394 if (blendnum == 0)
395 {
396 for (i = 0;i < numverts;i++)
397 {
398 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
399 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
400 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
401 }
402 }
403 else
404 {
405 for (i = 0;i < numverts;i++)
406 {
407 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
408 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
409 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
410 }
411 }
412 }
413 // the vertex normals in mdl models are an index into a table of
414 // 162 unique values, this very crude quantization reduces the
415 // vertex normal to only one byte, which saves a lot of space but
416 // also makes lighting pretty coarse
417 if (normal3f)
418 {
419 float lerp = frameblend[blendnum].lerp;
420 if (blendnum == 0)
421 {
422 for (i = 0;i < numverts;i++)
423 {
424 const float *vn = m_bytenormals[verts[i].lightnormalindex];
425 VectorScale(vn, lerp, normal3f + i*3);
426 }
427 }
428 else
429 {
430 for (i = 0;i < numverts;i++)
431 {
432 const float *vn = m_bytenormals[verts[i].lightnormalindex];
433 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
434 }
435 }
436 }
437 if (svector3f)
438 {
439 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
440 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
441 if (blendnum == 0)
442 {
443 for (i = 0;i < numverts;i++, texvecvert++)
444 {
445 VectorScale(texvecvert->svec, f, svector3f + i*3);
446 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
447 }
448 }
449 else
450 {
451 for (i = 0;i < numverts;i++, texvecvert++)
452 {
453 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
454 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
455 }
456 }
457 }
458 }
459}
float m_bytenormals[NUMVERTEXNORMALS][3]
Definition mathlib.c:31
unsigned char v[3]
Definition modelgen.h:87
unsigned char lightnormalindex
Definition modelgen.h:88

References f, i, trivertx_t::lightnormalindex, m_bytenormals, MAX_FRAMEBLENDS, model, scale, texvecvertex_t::svec, texvecvertex_t::tvec, trivertx_t::v, VectorClear, VectorMA, and VectorScale.

Referenced by Mod_IDP0_Load(), and Mod_IDP2_Load().

◆ Mod_MDL_LoadFrames()

static void Mod_MDL_LoadFrames ( unsigned char * datapointer,
int inverts,
int * vertremap )
static

Definition at line 864 of file model_alias.c.

865{
866 int i, f, pose, groupframes;
867 float interval;
868 daliasframetype_t *pframetype;
869 daliasframe_t *pinframe;
870 daliasgroup_t *group;
871 daliasinterval_t *intervals;
872 animscene_t *scene;
873 pose = 0;
874 scene = loadmodel->animscenes;
875 for (f = 0;f < loadmodel->numframes;f++)
876 {
877 pframetype = (daliasframetype_t *)datapointer;
878 datapointer += sizeof(daliasframetype_t);
879 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
880 {
881 // a single frame is still treated as a group
882 interval = 0.1f;
883 groupframes = 1;
884 }
885 else
886 {
887 // read group header
888 group = (daliasgroup_t *)datapointer;
889 datapointer += sizeof(daliasgroup_t);
890 groupframes = LittleLong (group->numframes);
891
892 // intervals (time per frame)
893 intervals = (daliasinterval_t *)datapointer;
894 datapointer += sizeof(daliasinterval_t) * groupframes;
895
896 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
897 if (interval < 0.01f)
898 {
899 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
900 interval = 0.1f;
901 }
902 }
903
904 // get scene name from first frame
905 pinframe = (daliasframe_t *)datapointer;
906
907 dp_strlcpy(scene->name, pinframe->name, sizeof(scene->name));
908 scene->firstframe = pose;
909 scene->framecount = groupframes;
910 scene->framerate = 1.0f / interval;
911 scene->loop = true;
912 scene++;
913
914 // read frames
915 for (i = 0;i < groupframes;i++)
916 {
917 datapointer += sizeof(daliasframe_t);
919 datapointer += sizeof(trivertx_t) * inverts;
920 pose++;
921 }
922 }
923}
static void Mod_ConvertAliasVerts(int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
char name[16]
Definition modelgen.h:96

References ALIAS_SINGLE, model_t::animscenes, Con_Printf(), surfmesh_t::data_morphmdlvertex, dp_strlcpy, f, animscene_t::firstframe, animscene_t::framecount, animscene_t::framerate, i, daliasinterval_t::interval, LittleFloat, LittleLong, loadmodel, animscene_t::loop, Mod_ConvertAliasVerts(), animscene_t::name, daliasframe_t::name, model_t::name, surfmesh_t::num_vertices, daliasgroup_t::numframes, model_t::numframes, model_t::surfmesh, and daliasframetype_t::type.

Referenced by Mod_IDP0_Load().

◆ Mod_MDLMD2MD3_TraceBox()

static void Mod_MDLMD2MD3_TraceBox ( model_t * model,
const frameblend_t * frameblend,
const skeleton_t * skeleton,
trace_t * trace,
const vec3_t start,
const vec3_t boxmins,
const vec3_t boxmaxs,
const vec3_t end,
int hitsupercontentsmask,
int skipsupercontentsmask,
int skipmaterialflagsmask )
static

Definition at line 794 of file model_alias.c.

795{
796 int i;
797 vec3_t shiftstart, shiftend;
798 float segmentmins[3], segmentmaxs[3];
799 msurface_t *surface;
800 float vertex3fbuf[1024*3];
801 float *vertex3f = vertex3fbuf;
802 colboxbrushf_t thisbrush_start, thisbrush_end;
803 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
804
805 if (VectorCompare(boxmins, boxmaxs))
806 {
807 VectorAdd(start, boxmins, shiftstart);
808 VectorAdd(end, boxmins, shiftend);
809 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
810 VectorSubtract(trace->endpos, boxmins, trace->endpos);
811 return;
812 }
813
814 // for static cases we can just call CollisionBIH which is much faster
815 if ((frameblend == NULL || (frameblend[0].subframe == 0 && frameblend[1].lerp == 0)) && (skeleton == NULL || skeleton->relativetransforms == NULL))
816 {
817 Mod_CollisionBIH_TraceBox(model, frameblend, skeleton, trace, start, boxmins, boxmaxs, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
818 return;
819 }
820
821 // box trace, performed as brush trace
822 memset(trace, 0, sizeof(*trace));
823 trace->fraction = 1;
824 trace->hitsupercontentsmask = hitsupercontentsmask;
825 trace->skipsupercontentsmask = skipsupercontentsmask;
826 trace->skipmaterialflagsmask = skipmaterialflagsmask;
827 if (model->surfmesh.num_vertices > 1024)
828 vertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
829 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
830 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
831 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
832 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
833 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
834 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
835 VectorAdd(start, boxmins, boxstartmins);
836 VectorAdd(start, boxmaxs, boxstartmaxs);
837 VectorAdd(end, boxmins, boxendmins);
838 VectorAdd(end, boxmaxs, boxendmaxs);
839 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
840 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
841 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
842 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
843 Collision_TraceBrushTriangleMeshFloat(trace, &thisbrush_start.brush, &thisbrush_end.brush, surface->num_triangles, model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
844 if (vertex3f != vertex3fbuf)
845 Mem_Free(vertex3f);
846}
#define SUPERCONTENTS_OPAQUE
Definition bspfile.h:208
void Collision_TraceBrushTriangleMeshFloat(trace_t *trace, const colbrushf_t *thisbrush_start, const colbrushf_t *thisbrush_end, int numtriangles, const int *element3i, const float *vertex3f, int stride, float *bbox6f, int supercontents, int q3surfaceflags, const texture_t *texture, const vec3_t segmentmins, const vec3_t segmentmaxs)
Definition collision.c:996
void Collision_BrushForBox(colboxbrushf_t *boxbrush, const vec3_t mins, const vec3_t maxs, int supercontents, int q3surfaceflags, const texture_t *texture)
Definition collision.c:1141
#define min(A, B)
Definition mathlib.h:37
#define VectorSubtract(a, b, out)
Definition mathlib.h:99
#define VectorCompare(a, b)
Definition mathlib.h:113
#define VectorAdd(a, b, out)
Definition mathlib.h:100
#define MATERIALFLAGMASK_TRANSLUCENT
vec_t vec3_t[3]
Definition qtypes.h:71
colbrushf_t brush
Definition collision.h:139
int basematerialflags
int hitsupercontentsmask
Definition collision.h:50
double fraction
Definition collision.h:40
double endpos[3]
Definition collision.h:42
int skipsupercontentsmask
Definition collision.h:52
int skipmaterialflagsmask
Definition collision.h:54

References texture_t::basematerialflags, colboxbrushf_t::brush, Collision_BrushForBox(), Collision_TraceBrushTriangleMeshFloat(), trace_t::endpos, trace_t::fraction, trace_t::hitsupercontentsmask, i, MATERIALFLAGMASK_TRANSLUCENT, max, Mem_Alloc, Mem_Free, min, Mod_CollisionBIH_TraceBox(), Mod_MDLMD2MD3_TraceLine(), model, NULL, msurface_t::num_firsttriangle, msurface_t::num_triangles, skeleton_t::relativetransforms, trace_t::skipmaterialflagsmask, trace_t::skipsupercontentsmask, SUPERCONTENTS_OPAQUE, SUPERCONTENTS_SOLID, tempmempool, msurface_t::texture, VectorAdd, VectorCompare, and VectorSubtract.

Referenced by Mod_DARKPLACESMODEL_Load(), Mod_IDP0_Load(), Mod_IDP2_Load(), Mod_IDP3_Load(), Mod_INTERQUAKEMODEL_Load(), Mod_PSKMODEL_Load(), and Mod_ZYMOTICMODEL_Load().

◆ Mod_MDLMD2MD3_TraceLine()

static void Mod_MDLMD2MD3_TraceLine ( model_t * model,
const frameblend_t * frameblend,
const skeleton_t * skeleton,
trace_t * trace,
const vec3_t start,
const vec3_t end,
int hitsupercontentsmask,
int skipsupercontentsmask,
int skipmaterialflagsmask )
static

Definition at line 755 of file model_alias.c.

756{
757 int i;
758 float segmentmins[3], segmentmaxs[3];
759 msurface_t *surface;
760 float vertex3fbuf[1024 * 3];
761 float *vertex3f = vertex3fbuf;
762 float *freevertex3f = NULL;
763 // for static cases we can just call CollisionBIH which is much faster
764 if ((frameblend == NULL || (frameblend[0].subframe == 0 && frameblend[1].lerp == 0)) && (skeleton == NULL || skeleton->relativetransforms == NULL))
765 {
766 Mod_CollisionBIH_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
767 return;
768 }
769 memset(trace, 0, sizeof(*trace));
770 trace->fraction = 1;
771 trace->hitsupercontentsmask = hitsupercontentsmask;
772 trace->skipsupercontentsmask = skipsupercontentsmask;
773 trace->skipmaterialflagsmask = skipmaterialflagsmask;
774 segmentmins[0] = min(start[0], end[0]) - 1;
775 segmentmins[1] = min(start[1], end[1]) - 1;
776 segmentmins[2] = min(start[2], end[2]) - 1;
777 segmentmaxs[0] = max(start[0], end[0]) + 1;
778 segmentmaxs[1] = max(start[1], end[1]) + 1;
779 segmentmaxs[2] = max(start[2], end[2]) + 1;
780 if (frameblend == NULL || frameblend[0].subframe != 0 || frameblend[0].lerp != 0 || skeleton != NULL)
781 {
782 if (model->surfmesh.num_vertices > 1024)
783 vertex3f = freevertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
784 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
785 }
786 else
787 vertex3f = model->surfmesh.data_vertex3f;
788 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
789 Collision_TraceLineTriangleMeshFloat(trace, start, end, surface->num_triangles, model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
790 if (freevertex3f)
791 Mem_Free(freevertex3f);
792}
void Collision_TraceLineTriangleMeshFloat(trace_t *trace, const vec3_t linestart, const vec3_t lineend, int numtriangles, const int *element3i, const float *vertex3f, int stride, float *bbox6f, int supercontents, int q3surfaceflags, const texture_t *texture, const vec3_t segmentmins, const vec3_t segmentmaxs)
Definition collision.c:1078

References texture_t::basematerialflags, Collision_TraceLineTriangleMeshFloat(), trace_t::fraction, trace_t::hitsupercontentsmask, i, MATERIALFLAGMASK_TRANSLUCENT, max, Mem_Alloc, Mem_Free, min, Mod_CollisionBIH_TraceLine(), model, NULL, msurface_t::num_firsttriangle, msurface_t::num_triangles, skeleton_t::relativetransforms, trace_t::skipmaterialflagsmask, trace_t::skipsupercontentsmask, SUPERCONTENTS_OPAQUE, SUPERCONTENTS_SOLID, tempmempool, and msurface_t::texture.

Referenced by Mod_DARKPLACESMODEL_Load(), Mod_IDP0_Load(), Mod_IDP2_Load(), Mod_IDP3_Load(), Mod_INTERQUAKEMODEL_Load(), Mod_MDLMD2MD3_TraceBox(), Mod_PSKMODEL_Load(), and Mod_ZYMOTICMODEL_Load().

◆ Mod_PSKMODEL_Load()

void Mod_PSKMODEL_Load ( model_t * mod,
void * buffer,
void * bufferend )

Definition at line 2540 of file model_alias.c.

2541{
2542 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2543 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2544 fs_offset_t filesize;
2545 pskpnts_t *pnts;
2546 pskvtxw_t *vtxw;
2547 pskface_t *faces;
2548 pskmatt_t *matts;
2549 pskboneinfo_t *bones;
2550 pskrawweights_t *rawweights;
2551 //pskboneinfo_t *animbones;
2552 pskaniminfo_t *anims;
2553 pskanimkeys_t *animkeys;
2554 void *animfilebuffer, *animbuffer, *animbufferend;
2555 unsigned char *data;
2556 pskchunk_t *pchunk;
2557 skinfile_t *skinfiles;
2558 char animname[MAX_QPATH];
2559 float biggestorigin;
2560
2561 pchunk = (pskchunk_t *)buffer;
2562 if (strcmp(pchunk->id, "ACTRHEAD"))
2563 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2564
2566
2580
2581 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2582 dp_strlcat(animname, ".psa", sizeof(animname));
2583 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2584 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2585 if (!animbuffer)
2586 animbufferend = animbuffer;
2587
2588 numpnts = 0;
2589 pnts = NULL;
2590 numvtxw = 0;
2591 vtxw = NULL;
2592 numfaces = 0;
2593 faces = NULL;
2594 nummatts = 0;
2595 matts = NULL;
2596 numbones = 0;
2597 bones = NULL;
2598 numrawweights = 0;
2599 rawweights = NULL;
2600 numanims = 0;
2601 anims = NULL;
2602 numanimkeys = 0;
2603 animkeys = NULL;
2604
2605 while (buffer < bufferend)
2606 {
2607 pchunk = (pskchunk_t *)buffer;
2608 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2609 version = LittleLong(pchunk->version);
2610 recordsize = LittleLong(pchunk->recordsize);
2611 numrecords = LittleLong(pchunk->numrecords);
2613 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2614 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2615 Con_Printf ("%s: chunk %s has unknown version %x (0x1e83b9, 0x1e9179, 0x2e, 0x12f2bc, 0x12f2f0 are currently supported), trying to load anyway!\n", loadmodel->name, pchunk->id, version);
2616 if (!strcmp(pchunk->id, "ACTRHEAD"))
2617 {
2618 // nothing to do
2619 }
2620 else if (!strcmp(pchunk->id, "PNTS0000"))
2621 {
2622 pskpnts_t *p;
2623 if (recordsize != sizeof(*p))
2624 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2625 // byteswap in place and keep the pointer
2626 numpnts = numrecords;
2627 pnts = (pskpnts_t *)buffer;
2628 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2629 {
2630 p->origin[0] = LittleFloat(p->origin[0]);
2631 p->origin[1] = LittleFloat(p->origin[1]);
2632 p->origin[2] = LittleFloat(p->origin[2]);
2633 }
2634 buffer = p;
2635 }
2636 else if (!strcmp(pchunk->id, "VTXW0000"))
2637 {
2638 pskvtxw_t *p;
2639 if (recordsize != sizeof(*p))
2640 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2641 // byteswap in place and keep the pointer
2642 numvtxw = numrecords;
2643 vtxw = (pskvtxw_t *)buffer;
2644 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2645 {
2647 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2648 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2649 if (p->pntsindex >= numpnts)
2650 {
2651 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2652 p->pntsindex = 0;
2653 }
2654 }
2655 buffer = p;
2656 }
2657 else if (!strcmp(pchunk->id, "FACE0000"))
2658 {
2659 pskface_t *p;
2660 if (recordsize != sizeof(*p))
2661 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2662 // byteswap in place and keep the pointer
2663 numfaces = numrecords;
2664 faces = (pskface_t *)buffer;
2665 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2666 {
2667 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2668 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2669 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2670 p->group = LittleLong(p->group);
2671 if (p->vtxwindex[0] >= numvtxw)
2672 {
2673 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2674 p->vtxwindex[0] = 0;
2675 }
2676 if (p->vtxwindex[1] >= numvtxw)
2677 {
2678 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2679 p->vtxwindex[1] = 0;
2680 }
2681 if (p->vtxwindex[2] >= numvtxw)
2682 {
2683 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2684 p->vtxwindex[2] = 0;
2685 }
2686 }
2687 buffer = p;
2688 }
2689 else if (!strcmp(pchunk->id, "MATT0000"))
2690 {
2691 pskmatt_t *p;
2692 if (recordsize != sizeof(*p))
2693 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2694 // byteswap in place and keep the pointer
2695 nummatts = numrecords;
2696 matts = (pskmatt_t *)buffer;
2697 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2698 {
2699 // nothing to do
2700 }
2701 buffer = p;
2702 }
2703 else if (!strcmp(pchunk->id, "REFSKELT"))
2704 {
2705 pskboneinfo_t *p;
2706 if (recordsize != sizeof(*p))
2707 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2708 // byteswap in place and keep the pointer
2709 numbones = numrecords;
2710 bones = (pskboneinfo_t *)buffer;
2711 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2712 {
2714 p->parent = LittleLong(p->parent);
2715 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2716 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2717 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2718 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2719 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2720 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2721 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2723 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2724 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2725 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2726#ifdef PSKQUATNEGATIONS
2727 if (index)
2728 {
2729 p->basepose.quat[0] *= -1;
2730 p->basepose.quat[1] *= -1;
2731 p->basepose.quat[2] *= -1;
2732 }
2733 else
2734 {
2735 p->basepose.quat[0] *= 1;
2736 p->basepose.quat[1] *= -1;
2737 p->basepose.quat[2] *= 1;
2738 }
2739#endif
2740 if (p->parent < 0 || p->parent >= numbones)
2741 {
2742 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2743 p->parent = 0;
2744 }
2745 }
2746 buffer = p;
2747 }
2748 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2749 {
2750 pskrawweights_t *p;
2751 if (recordsize != sizeof(*p))
2752 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2753 // byteswap in place and keep the pointer
2754 numrawweights = numrecords;
2755 rawweights = (pskrawweights_t *)buffer;
2756 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2757 {
2758 p->weight = LittleFloat(p->weight);
2761 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2762 {
2763 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2764 p->pntsindex = 0;
2765 }
2766 if (p->boneindex < 0 || p->boneindex >= numbones)
2767 {
2768 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2769 p->boneindex = 0;
2770 }
2771 }
2772 buffer = p;
2773 }
2774 }
2775
2776 while (animbuffer < animbufferend)
2777 {
2778 pchunk = (pskchunk_t *)animbuffer;
2779 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2780 version = LittleLong(pchunk->version);
2781 recordsize = LittleLong(pchunk->recordsize);
2782 numrecords = LittleLong(pchunk->numrecords);
2784 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2785 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2786 Con_Printf ("%s: chunk %s has unknown version %x (0x1e83b9, 0x1e9179, 0x2e, 0x12f2bc, 0x12f2f0 are currently supported), trying to load anyway!\n", animname, pchunk->id, version);
2787 if (!strcmp(pchunk->id, "ANIMHEAD"))
2788 {
2789 // nothing to do
2790 }
2791 else if (!strcmp(pchunk->id, "BONENAMES"))
2792 {
2793 pskboneinfo_t *p;
2794 if (recordsize != sizeof(*p))
2795 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2796 // byteswap in place and keep the pointer
2797 numanimbones = numrecords;
2798 //animbones = (pskboneinfo_t *)animbuffer;
2799 // NOTE: supposedly psa does not need to match the psk model, the
2800 // bones missing from the psa would simply use their base
2801 // positions from the psk, but this is hard for me to implement
2802 // and people can easily make animations that match.
2803 if (numanimbones != numbones)
2804 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2805 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2806 {
2808 p->parent = LittleLong(p->parent);
2809 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2810 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2811 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2812 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2813 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2814 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2815 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2817 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2818 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2819 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2820#ifdef PSKQUATNEGATIONS
2821 if (index)
2822 {
2823 p->basepose.quat[0] *= -1;
2824 p->basepose.quat[1] *= -1;
2825 p->basepose.quat[2] *= -1;
2826 }
2827 else
2828 {
2829 p->basepose.quat[0] *= 1;
2830 p->basepose.quat[1] *= -1;
2831 p->basepose.quat[2] *= 1;
2832 }
2833#endif
2834 if (p->parent < 0 || p->parent >= numanimbones)
2835 {
2836 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2837 p->parent = 0;
2838 }
2839 // check that bones are the same as in the base
2840 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2841 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2842 }
2843 animbuffer = p;
2844 }
2845 else if (!strcmp(pchunk->id, "ANIMINFO"))
2846 {
2847 pskaniminfo_t *p;
2848 if (recordsize != sizeof(*p))
2849 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2850 // byteswap in place and keep the pointer
2851 numanims = numrecords;
2852 anims = (pskaniminfo_t *)animbuffer;
2853 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2854 {
2855 p->numbones = LittleLong(p->numbones);
2856 p->playtime = LittleFloat(p->playtime);
2857 p->fps = LittleFloat(p->fps);
2860 if (p->numbones != numbones)
2861 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2862 }
2863 animbuffer = p;
2864 }
2865 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2866 {
2867 pskanimkeys_t *p;
2868 if (recordsize != sizeof(*p))
2869 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2870 numanimkeys = numrecords;
2871 animkeys = (pskanimkeys_t *)animbuffer;
2872 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2873 {
2874 p->origin[0] = LittleFloat(p->origin[0]);
2875 p->origin[1] = LittleFloat(p->origin[1]);
2876 p->origin[2] = LittleFloat(p->origin[2]);
2877 p->quat[0] = LittleFloat(p->quat[0]);
2878 p->quat[1] = LittleFloat(p->quat[1]);
2879 p->quat[2] = LittleFloat(p->quat[2]);
2880 p->quat[3] = LittleFloat(p->quat[3]);
2882#ifdef PSKQUATNEGATIONS
2883 if (index % numbones)
2884 {
2885 p->quat[0] *= -1;
2886 p->quat[1] *= -1;
2887 p->quat[2] *= -1;
2888 }
2889 else
2890 {
2891 p->quat[0] *= 1;
2892 p->quat[1] *= -1;
2893 p->quat[2] *= 1;
2894 }
2895#endif
2896 }
2897 animbuffer = p;
2898 // TODO: allocate bonepose stuff
2899 }
2900 else
2901 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2902 }
2903
2904 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights)
2905 Host_Error("%s: missing required chunks", loadmodel->name);
2906
2907 if (numanims)
2908 {
2909 loadmodel->numframes = 0;
2910 for (index = 0;index < numanims;index++)
2911 loadmodel->numframes += anims[index].numframes;
2912 if (numanimkeys != numbones * loadmodel->numframes)
2913 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2914 }
2915 else
2917
2918 meshvertices = numvtxw;
2919 meshtriangles = numfaces;
2920
2921 // load external .skin files if present
2922 skinfiles = Mod_LoadSkinFiles();
2923 if (loadmodel->numskins < 1)
2924 loadmodel->numskins = 1;
2925 loadmodel->num_bones = numbones;
2931 loadmodel->surfmesh.num_vertices = meshvertices;
2932 loadmodel->surfmesh.num_triangles = meshtriangles;
2933
2934 // do most allocations as one merged chunk
2935 // This is only robust for C standard types!
2936 data = (unsigned char *)Mem_Alloc(loadmodel->mempool,
2937 loadmodel->surfmesh.num_vertices * sizeof(float[3])
2938 + loadmodel->surfmesh.num_vertices * sizeof(float[3])
2939 + loadmodel->surfmesh.num_vertices * sizeof(float[3])
2940 + loadmodel->surfmesh.num_vertices * sizeof(float[3])
2941 + loadmodel->surfmesh.num_vertices * sizeof(float[2])
2942 + loadmodel->num_bones * sizeof(float[12])
2943 + loadmodel->num_surfaces * sizeof(int)
2944 + loadmodel->surfmesh.num_triangles * sizeof(int[3])
2945 + loadmodel->surfmesh.num_vertices * sizeof(unsigned short)
2946 + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0)
2947 + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7])
2948 + loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4])
2949 + loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]));
2950 // Pointers must be taken in descending order of alignment requirement!
2951 loadmodel->surfmesh.data_vertex3f = (float *)data; data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2952 loadmodel->surfmesh.data_svector3f = (float *)data; data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2953 loadmodel->surfmesh.data_tvector3f = (float *)data; data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2954 loadmodel->surfmesh.data_normal3f = (float *)data; data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2956 loadmodel->data_baseboneposeinverse = (float *)data; data += loadmodel->num_bones * sizeof(float[12]);
2958 loadmodel->surfmesh.data_element3i = (int *)data; data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2960 loadmodel->surfmesh.blends = (unsigned short *)data; data += loadmodel->surfmesh.num_vertices * sizeof(unsigned short);
2961 if (loadmodel->surfmesh.num_vertices <= 65536)
2962 {
2963 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2964 }
2965 loadmodel->data_poses7s = (short *)data; data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
2966 loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data; data += loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]);
2967 loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data; data += loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]);
2968 // Struct alignment requirements could change so we can't assume them here
2969 // otherwise a safe-looking commit could introduce undefined behaviour!
2976
2977 for (i = 0;i < loadmodel->numskins;i++)
2978 {
2981 loadmodel->skinscenes[i].loop = true;
2983 }
2984
2985 // create surfaces
2986 for (index = 0, i = 0;index < nummatts;index++)
2987 {
2988 // since psk models do not have named sections, reuse their shader name as the section name
2989 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2994 }
2995
2996 // copy over the vertex locations and texcoords
2997 for (index = 0;index < numvtxw;index++)
2998 {
3004 }
3005
3006 // loading the faces is complicated because we need to sort them into surfaces by mattindex
3007 for (index = 0;index < numfaces;index++)
3008 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
3009 for (index = 0, i = 0;index < nummatts;index++)
3010 {
3014 }
3015 for (index = 0;index < numfaces;index++)
3016 {
3021 }
3022
3023 // copy over the bones
3024 for (index = 0;index < numbones;index++)
3025 {
3027 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
3029 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
3030 }
3031
3032 // convert the basepose data
3033 if (loadmodel->num_bones)
3034 {
3035 int boneindex;
3036 matrix4x4_t *basebonepose;
3037 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
3038 matrix4x4_t bonematrix;
3039 matrix4x4_t tempbonematrix;
3040 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
3041 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
3042 {
3043 Matrix4x4_FromOriginQuat(&bonematrix, bones[boneindex].basepose.origin[0], bones[boneindex].basepose.origin[1], bones[boneindex].basepose.origin[2], bones[boneindex].basepose.quat[0], bones[boneindex].basepose.quat[1], bones[boneindex].basepose.quat[2], bones[boneindex].basepose.quat[3]);
3044 if (loadmodel->data_bones[boneindex].parent >= 0)
3045 {
3046 tempbonematrix = bonematrix;
3047 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
3048 }
3049 basebonepose[boneindex] = bonematrix;
3050 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
3051 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
3052 }
3053 Mem_Free(basebonepose);
3054 }
3055
3056 // sort the psk point weights into the vertex weight tables
3057 // (which only accept up to 4 bones per vertex)
3058 for (index = 0;index < numvtxw;index++)
3059 {
3060 int weightindex[4] = { 0, 0, 0, 0 };
3061 float weightinfluence[4] = { 0, 0, 0, 0 };
3062 int l;
3063 for (j = 0;j < numrawweights;j++)
3064 {
3065 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
3066 {
3067 int boneindex = rawweights[j].boneindex;
3068 float influence = rawweights[j].weight;
3069 for (l = 0;l < 4;l++)
3070 {
3071 if (weightinfluence[l] < influence)
3072 {
3073 // move lower influence weights out of the way first
3074 int l2;
3075 for (l2 = 3;l2 > l;l2--)
3076 {
3077 weightinfluence[l2] = weightinfluence[l2-1];
3078 weightindex[l2] = weightindex[l2-1];
3079 }
3080 // store the new weight
3081 weightinfluence[l] = influence;
3082 weightindex[l] = boneindex;
3083 break;
3084 }
3085 }
3086 }
3087 }
3088 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
3089 loadmodel->surfmesh.data_skeletalindex4ub[index*4 ] = weightindex[0];
3090 loadmodel->surfmesh.data_skeletalindex4ub[index*4+1] = weightindex[1];
3091 loadmodel->surfmesh.data_skeletalindex4ub[index*4+2] = weightindex[2];
3092 loadmodel->surfmesh.data_skeletalindex4ub[index*4+3] = weightindex[3];
3093 loadmodel->surfmesh.data_skeletalweight4ub[index*4 ] = (unsigned char)(weightinfluence[0]*255.0f);
3094 loadmodel->surfmesh.data_skeletalweight4ub[index*4+1] = (unsigned char)(weightinfluence[1]*255.0f);
3095 loadmodel->surfmesh.data_skeletalweight4ub[index*4+2] = (unsigned char)(weightinfluence[2]*255.0f);
3096 loadmodel->surfmesh.data_skeletalweight4ub[index*4+3] = (unsigned char)(weightinfluence[3]*255.0f);
3097 }
3100
3101 // set up the animscenes based on the anims
3102 if (numanims)
3103 {
3104 for (index = 0, i = 0;index < numanims;index++)
3105 {
3106 for (j = 0;j < anims[index].numframes;j++, i++)
3107 {
3108 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
3111 loadmodel->animscenes[i].loop = true;
3113 }
3114 }
3115 // calculate the scaling value for bone origins so they can be compressed to short
3116 biggestorigin = 0;
3117 for (index = 0;index < numanimkeys;index++)
3118 {
3119 pskanimkeys_t *k = animkeys + index;
3120 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
3121 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
3122 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
3123 }
3124 loadmodel->num_posescale = biggestorigin / 32767.0f;
3125 if (loadmodel->num_posescale == 0) // don't divide by zero
3126 loadmodel->num_posescale = 1.0;
3128
3129 // load the poses from the animkeys
3130 for (index = 0;index < numanimkeys;index++)
3131 {
3132 pskanimkeys_t *k = animkeys + index;
3133 float quat[4];
3134 Vector4Copy(k->quat, quat);
3135 if (quat[3] > 0)
3136 Vector4Negate(quat, quat);
3137 Vector4Normalize2(quat, quat);
3138 // compress poses to the short[7] format for longterm storage
3142 loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f;
3143 loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f;
3144 loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f;
3145 loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f;
3146 }
3147 }
3148 else
3149 {
3150 dp_strlcpy(loadmodel->animscenes[0].name, "base", sizeof(loadmodel->animscenes[0].name));
3153 loadmodel->animscenes[0].loop = true;
3155
3156 // calculate the scaling value for bone origins so they can be compressed to short
3157 biggestorigin = 0;
3158 for (index = 0;index < numbones;index++)
3159 {
3160 pskboneinfo_t *p = bones + index;
3161 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[0]));
3162 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[1]));
3163 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[2]));
3164 }
3165 loadmodel->num_posescale = biggestorigin / 32767.0f;
3166 if (loadmodel->num_posescale == 0) // don't divide by zero
3167 loadmodel->num_posescale = 1.0;
3169
3170 // load the basepose as a frame
3171 for (index = 0;index < numbones;index++)
3172 {
3173 pskboneinfo_t *p = bones + index;
3174 float quat[4];
3175 Vector4Copy(p->basepose.quat, quat);
3176 if (quat[3] > 0)
3177 Vector4Negate(quat, quat);
3178 Vector4Normalize2(quat, quat);
3179 // compress poses to the short[7] format for longterm storage
3183 loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f;
3184 loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f;
3185 loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f;
3186 loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f;
3187 }
3188 }
3189
3190 Mod_FreeSkinFiles(skinfiles);
3191 if (animfilebuffer)
3192 Mem_Free(animfilebuffer);
3194
3195 // compute all the mesh information that was not loaded from the file
3196 // TODO: honor smoothing groups somehow?
3198 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3206
3207 // Always make a BIH for the first frame, we can use it where possible.
3210 {
3216 }
3217}
#define dp_strlcat(dst, src, dsize)
Definition common.h:304
unsigned char * FS_LoadFile(const char *path, mempool_t *pool, qbool quiet, fs_offset_t *filesizepointer)
Definition fs.c:3540
void FS_StripExtension(const char *in, char *out, size_t size_out)
Definition fs.c:3611
int64_t fs_offset_t
Definition fs.h:37
GLuint index
Definition glquake.h:629
#define Vector4Copy(in, out)
Definition mathlib.h:84
void Matrix4x4_FromOriginQuat(matrix4x4_t *m, double ox, double oy, double oz, double x, double y, double z, double w)
Definition matrixlib.c:1461
float playtime
Definition model_psk.h:99
float frametime
Definition model_psk.h:112
float quat[4]
Definition model_psk.h:111
float origin[3]
Definition model_psk.h:110
pskpose_t basepose
Definition model_psk.h:78
char name[64]
Definition model_psk.h:74
int version
Definition model_psk.h:24
int numrecords
Definition model_psk.h:26
char id[20]
Definition model_psk.h:21
int recordsize
Definition model_psk.h:25
unsigned char mattindex
Definition model_psk.h:50
unsigned int group
Definition model_psk.h:52
unsigned short vtxwindex[3]
Definition model_psk.h:49
float origin[3]
Definition model_psk.h:32
float size[3]
Definition model_psk.h:68
float quat[4]
Definition model_psk.h:65
float origin[3]
Definition model_psk.h:66
float unknown
Definition model_psk.h:67
unsigned short pntsindex
Definition model_psk.h:38
float texcoord[2]
Definition model_psk.h:40

References model_t::AnimateVertices, model_t::animscenes, pskboneinfo_t::basepose, surfmesh_t::blends, pskrawweights_t::boneindex, buffer, model_t::collision_bih, model_t::CompileShadowMap, Con_DPrintf(), Con_Printf(), data, model_t::data_baseboneposeinverse, surfmesh_t::data_blendweights, model_t::data_bones, surfmesh_t::data_element3i, surfmesh_t::data_element3s, surfmesh_t::data_normal3f, model_t::data_poses7s, surfmesh_t::data_skeletalindex4ub, surfmesh_t::data_skeletalweight4ub, model_t::data_surfaces, surfmesh_t::data_svector3f, surfmesh_t::data_texcoordtexture2f, model_t::data_textures, surfmesh_t::data_tvector3f, surfmesh_t::data_vertex3f, developer_extra, dp_strlcat, dp_strlcpy, dpsnprintf(), model_t::Draw, model_t::DrawDebug, model_t::DrawDepth, model_t::DrawLight, model_t::DrawPrepass, model_t::DrawShadowMap, fabs(), animscene_t::firstframe, pskaniminfo_t::firstframe, pskaniminfo_t::fps, animscene_t::framecount, animscene_t::framerate, pskanimkeys_t::frametime, FS_LoadFile(), FS_StripExtension(), pskface_t::group, Host_Error(), i, pskchunk_t::id, index, int(), cvar_t::integer, surfmesh_t::isanimated, LittleFloat, LittleLong, LittleShort, loadmodel, animscene_t::loop, Matrix4x4_Concat(), Matrix4x4_FromOriginQuat(), Matrix4x4_Invert_Simple(), Matrix4x4_ToArray12FloatD3D(), pskface_t::mattindex, max, MAX_QPATH, Mem_Alloc, Mem_AllocType, Mem_Free, Mem_ReallocType, model_t::mempool, mod_alias, Mod_Alias_CalculateBoundingBox(), mod_alias_force_animated, Mod_BuildAliasSkinsFromSkinFiles(), Mod_BuildNormals(), Mod_BuildTextureVectorsFromNormals(), Mod_CollisionBIH_PointSuperContents_Mesh(), Mod_CollisionBIH_TraceBox(), Mod_CollisionBIH_TraceBrush(), Mod_CollisionBIH_TraceLine(), Mod_CollisionBIH_TracePoint_Mesh(), Mod_FreeSkinFiles(), Mod_LoadSkinFiles(), Mod_MakeCollisionBIH(), Mod_MakeSortedSurfaces(), Mod_MDLMD2MD3_TraceBox(), Mod_MDLMD2MD3_TraceLine(), Mod_Skeletal_AnimateVertices(), Mod_Skeletal_CompressBlend(), Mod_ValidateElements(), model_t::modeldatatypestring, model_t::modelsurfaces_sorted, aliasbone_t::name, animscene_t::name, model_t::name, pskaniminfo_t::name, pskboneinfo_t::name, pskmatt_t::name, NULL, surfmesh_t::num_blends, model_t::num_bones, msurface_t::num_firsttriangle, msurface_t::num_firstvertex, model_t::num_poseinvscale, model_t::num_poses, model_t::num_posescale, model_t::num_surfaces, model_t::num_textures, model_t::num_texturesperskin, msurface_t::num_triangles, surfmesh_t::num_triangles, msurface_t::num_vertices, surfmesh_t::num_vertices, pskaniminfo_t::numbones, pskboneinfo_t::numchildren, model_t::numframes, pskaniminfo_t::numframes, pskchunk_t::numrecords, model_t::numskins, pskanimkeys_t::origin, pskpnts_t::origin, pskpose_t::origin, aliasbone_t::parent, pskboneinfo_t::parent, pskaniminfo_t::playtime, pskrawweights_t::pntsindex, pskvtxw_t::pntsindex, model_t::PointSuperContents, pskanimkeys_t::quat, pskpose_t::quat, R_Mod_CompileShadowMap(), R_Mod_Draw(), R_Mod_DrawDebug(), R_Mod_DrawDepth(), R_Mod_DrawLight(), R_Mod_DrawPrepass(), R_Mod_DrawShadowMap(), r_smoothnormals_areaweighting, pskchunk_t::recordsize, pskpose_t::size, model_t::skinscenes, ST_RAND, cvar_t::string, model_t::submodelsurfaces_end, model_t::submodelsurfaces_start, model_t::surfmesh, model_t::synctype, tempmempool, pskvtxw_t::texcoord, msurface_t::texture, model_t::TraceBox, model_t::TraceBrush, model_t::TraceLine, model_t::TracePoint, model_t::type, pskpose_t::unknown, Vector4Copy, Vector4Negate, Vector4Normalize2, pskchunk_t::version, version, pskface_t::vtxwindex, and pskrawweights_t::weight.

◆ Mod_Skeletal_AddBlend()

static int Mod_Skeletal_AddBlend ( model_t * model,
const blendweights_t * newweights )
static

Definition at line 216 of file model_alias.c.

217{
218 int i;
219 blendweights_t *weights;
220 if(!newweights->influence[1])
221 return newweights->index[0];
222 weights = model->surfmesh.data_blendweights;
223 for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
224 {
225 if (!memcmp(weights, newweights, sizeof(blendweights_t)))
226 return model->num_bones + i;
227 }
228 model->surfmesh.num_blends++;
229 memcpy(weights, newweights, sizeof(blendweights_t));
230 return model->num_bones + i;
231}

References i, blendweights_t::index, blendweights_t::influence, and model.

Referenced by Mod_INTERQUAKEMODEL_Load(), and Mod_Skeletal_CompressBlend().

◆ Mod_Skeletal_AnimateVertices()

static void Mod_Skeletal_AnimateVertices ( const model_t *RESTRICT model,
const frameblend_t *RESTRICT frameblend,
const skeleton_t * skeleton,
float *RESTRICT vertex3f,
float *RESTRICT normal3f,
float *RESTRICT svector3f,
float *RESTRICT tvector3f )
static

Definition at line 163 of file model_alias.c.

164{
165
166 if (!model->surfmesh.num_vertices)
167 return;
168
169 if (!model->num_bones)
170 {
171 if (vertex3f) memcpy(vertex3f, model->surfmesh.data_vertex3f, model->surfmesh.num_vertices*sizeof(float[3]));
172 if (normal3f) memcpy(normal3f, model->surfmesh.data_normal3f, model->surfmesh.num_vertices*sizeof(float[3]));
173 if (svector3f) memcpy(svector3f, model->surfmesh.data_svector3f, model->surfmesh.num_vertices*sizeof(float[3]));
174 if (tvector3f) memcpy(tvector3f, model->surfmesh.data_tvector3f, model->surfmesh.num_vertices*sizeof(float[3]));
175 return;
176 }
177
178#ifdef SSE_POSSIBLE
179 if(r_skeletal_use_sse_defined)
180 if(r_skeletal_use_sse.integer)
181 {
182 Mod_Skeletal_AnimateVertices_SSE(model, frameblend, skeleton, vertex3f, normal3f, svector3f, tvector3f);
183 return;
184 }
185#endif
186 Mod_Skeletal_AnimateVertices_Generic(model, frameblend, skeleton, vertex3f, normal3f, svector3f, tvector3f);
187}
void Mod_Skeletal_AnimateVertices_Generic(const model_t *RESTRICT model, const frameblend_t *RESTRICT frameblend, const skeleton_t *skeleton, float *RESTRICT vertex3f, float *RESTRICT normal3f, float *RESTRICT svector3f, float *RESTRICT tvector3f)

References cvar_t::integer, Mod_Skeletal_AnimateVertices_Generic(), and model.

Referenced by Mod_DARKPLACESMODEL_Load(), Mod_INTERQUAKEMODEL_Load(), Mod_PSKMODEL_Load(), and Mod_ZYMOTICMODEL_Load().

◆ Mod_Skeletal_AnimateVertices_AllocBuffers()

void * Mod_Skeletal_AnimateVertices_AllocBuffers ( size_t nbytes)

◆ Mod_Skeletal_BuildTransforms()

void Mod_Skeletal_BuildTransforms ( const model_t *RESTRICT model,
const frameblend_t *RESTRICT frameblend,
const skeleton_t * skeleton,
float *RESTRICT bonepose,
float *RESTRICT boneposerelative )

Definition at line 65 of file model_alias.c.

66{
67 int i, blends;
68 float m[12];
69
70 if (!bonepose)
71 bonepose = (float * RESTRICT) Mod_Skeletal_AnimateVertices_AllocBuffers(sizeof(float[12]) * model->num_bones);
72
73 if (skeleton && !skeleton->relativetransforms)
74 skeleton = NULL;
75
76 // interpolate matrices
77 if (skeleton)
78 {
79 for (i = 0;i < model->num_bones;i++)
80 {
82 if (model->data_bones[i].parent >= 0)
83 R_ConcatTransforms(bonepose + model->data_bones[i].parent * 12, m, bonepose + i * 12);
84 else
85 memcpy(bonepose + i * 12, m, sizeof(m));
86
87 // create a relative deformation matrix to describe displacement
88 // from the base mesh, which is used by the actual weighting
89 R_ConcatTransforms(bonepose + i * 12, model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
90 }
91 }
92 else
93 {
94 for (i = 0;i < model->num_bones;i++)
95 {
96 // blend by transform each quaternion/translation into a dual-quaternion first, then blending
97 const short * RESTRICT firstpose7s = model->data_poses7s + 7 * (frameblend[0].subframe * model->num_bones + i);
98 float firstlerp = frameblend[0].lerp,
99 firsttx = firstpose7s[0], firstty = firstpose7s[1], firsttz = firstpose7s[2],
100 rx = firstpose7s[3] * firstlerp,
101 ry = firstpose7s[4] * firstlerp,
102 rz = firstpose7s[5] * firstlerp,
103 rw = firstpose7s[6] * firstlerp,
104 dx = firsttx*rw + firstty*rz - firsttz*ry,
105 dy = -firsttx*rz + firstty*rw + firsttz*rx,
106 dz = firsttx*ry - firstty*rx + firsttz*rw,
107 dw = -firsttx*rx - firstty*ry - firsttz*rz,
108 scale, sx, sy, sz, sw;
109 for (blends = 1;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
110 {
111 const short * RESTRICT blendpose7s = model->data_poses7s + 7 * (frameblend[blends].subframe * model->num_bones + i);
112 float blendlerp = frameblend[blends].lerp,
113 blendtx = blendpose7s[0], blendty = blendpose7s[1], blendtz = blendpose7s[2],
114 qx = blendpose7s[3], qy = blendpose7s[4], qz = blendpose7s[5], qw = blendpose7s[6];
115 if(rx*qx + ry*qy + rz*qz + rw*qw < 0) blendlerp = -blendlerp;
116 qx *= blendlerp;
117 qy *= blendlerp;
118 qz *= blendlerp;
119 qw *= blendlerp;
120 rx += qx;
121 ry += qy;
122 rz += qz;
123 rw += qw;
124 dx += blendtx*qw + blendty*qz - blendtz*qy;
125 dy += -blendtx*qz + blendty*qw + blendtz*qx;
126 dz += blendtx*qy - blendty*qx + blendtz*qw;
127 dw += -blendtx*qx - blendty*qy - blendtz*qz;
128 }
129 // generate a matrix from the dual-quaternion, implicitly normalizing it in the process
130 scale = 1.0f / (rx*rx + ry*ry + rz*rz + rw*rw);
131 sx = rx * scale;
132 sy = ry * scale;
133 sz = rz * scale;
134 sw = rw * scale;
135 m[0] = sw*rw + sx*rx - sy*ry - sz*rz;
136 m[1] = 2*(sx*ry - sw*rz);
137 m[2] = 2*(sx*rz + sw*ry);
138 m[3] = model->num_posescale*(dx*sw - dy*sz + dz*sy - dw*sx);
139 m[4] = 2*(sx*ry + sw*rz);
140 m[5] = sw*rw + sy*ry - sx*rx - sz*rz;
141 m[6] = 2*(sy*rz - sw*rx);
142 m[7] = model->num_posescale*(dx*sz + dy*sw - dz*sx - dw*sy);
143 m[8] = 2*(sx*rz - sw*ry);
144 m[9] = 2*(sy*rz + sw*rx);
145 m[10] = sw*rw + sz*rz - sx*rx - sy*ry;
146 m[11] = model->num_posescale*(dy*sx + dz*sw - dx*sy - dw*sz);
152 if (model->data_bones[i].parent >= 0)
153 R_ConcatTransforms(bonepose + model->data_bones[i].parent * 12, m, bonepose + i * 12);
154 else
155 memcpy(bonepose + i * 12, m, sizeof(m));
156 // create a relative deformation matrix to describe displacement
157 // from the base mesh, which is used by the actual weighting
158 R_ConcatTransforms(bonepose + i * 12, model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
159 }
160 }
161}
void * Mod_Skeletal_AnimateVertices_AllocBuffers(size_t nbytes)
Definition model_alias.c:53
#define RESTRICT
Definition qtypes.h:27
vec4 sw
float value
Definition cvar.h:74

References i, cvar_t::integer, Matrix4x4_ToArray12FloatD3D(), MAX_FRAMEBLENDS, Mod_Skeletal_AnimateVertices_AllocBuffers(), model, NULL, R_ConcatTransforms(), r_skeletal_debugbone, r_skeletal_debugbonecomponent, r_skeletal_debugbonevalue, r_skeletal_debugtranslatex, r_skeletal_debugtranslatey, r_skeletal_debugtranslatez, skeleton_t::relativetransforms, RESTRICT, scale, sw, and cvar_t::value.

Referenced by Mod_Skeletal_AnimateVertices_Generic(), and R_AnimCache_GetEntity().

◆ Mod_Skeletal_CompressBlend()

static int Mod_Skeletal_CompressBlend ( model_t * model,
const int * newindex,
const float * newinfluence )
static

Definition at line 233 of file model_alias.c.

234{
235 int i, total;
236 float scale;
237 blendweights_t newweights;
238 if(!newinfluence[1])
239 return newindex[0];
240 scale = 0;
241 for (i = 0;i < 4;i++)
242 scale += newinfluence[i];
243 scale = 255.0f / scale;
244 total = 0;
245 for (i = 0;i < 4;i++)
246 {
247 newweights.index[i] = newindex[i];
248 newweights.influence[i] = (unsigned char)(newinfluence[i] * scale);
249 total += newweights.influence[i];
250 }
251 while (total > 255)
252 {
253 for (i = 0;i < 4;i++)
254 {
255 if(newweights.influence[i] > 0 && total > 255)
256 {
257 newweights.influence[i]--;
258 total--;
259 }
260 }
261 }
262 while (total < 255)
263 {
264 for (i = 0; i < 4;i++)
265 {
266 if(newweights.influence[i] < 255 && total < 255)
267 {
268 newweights.influence[i]++;
269 total++;
270 }
271 }
272 }
273 return Mod_Skeletal_AddBlend(model, &newweights);
274}

References i, blendweights_t::index, blendweights_t::influence, Mod_Skeletal_AddBlend(), model, and scale.

Referenced by Mod_DARKPLACESMODEL_Load(), and Mod_PSKMODEL_Load().

◆ Mod_Skeletal_FreeBuffers()

◆ Mod_ZYMOTICMODEL_Load()

void Mod_ZYMOTICMODEL_Load ( model_t * mod,
void * buffer,
void * bufferend )

Definition at line 1768 of file model_alias.c.

1769{
1770 zymtype1header_t *pinmodel, *pheader;
1771 unsigned char *pbase;
1772 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1773 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1774 zymvertex_t *verts, *vertdata;
1775 zymscene_t *scene;
1776 zymbone_t *bone;
1777 char *shadername;
1778 skinfile_t *skinfiles;
1779 unsigned char *data;
1780 msurface_t *surface;
1781
1782 pinmodel = (zymtype1header_t *)buffer;
1783 pbase = (unsigned char *)buffer;
1784 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1785 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1786 if (BigLong(pinmodel->type) != 1)
1787 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1788
1790
1793
1794 // byteswap header
1795 pheader = pinmodel;
1796 pheader->type = BigLong(pinmodel->type);
1797 pheader->filesize = BigLong(pinmodel->filesize);
1798 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1799 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1800 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1801 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1802 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1803 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1804 pheader->radius = BigFloat(pinmodel->radius);
1805 pheader->numverts = BigLong(pinmodel->numverts);
1806 pheader->numtris = BigLong(pinmodel->numtris);
1807 pheader->numshaders = BigLong(pinmodel->numshaders);
1808 pheader->numbones = BigLong(pinmodel->numbones);
1809 pheader->numscenes = BigLong(pinmodel->numscenes);
1810 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1811 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1812 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1813 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1814 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1815 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1818 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1819 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1820 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1821 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1822 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1823 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1824 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1825 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1826 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1827 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1828
1829 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1830 {
1831 Con_Printf("%s has no geometry\n", loadmodel->name);
1832 return;
1833 }
1834 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1835 {
1836 Con_Printf("%s has no animations\n", loadmodel->name);
1837 return;
1838 }
1839
1851
1852 loadmodel->numframes = pheader->numscenes;
1853 loadmodel->num_surfaces = pheader->numshaders;
1854
1855 skinfiles = Mod_LoadSkinFiles();
1856 if (loadmodel->numskins < 1)
1857 loadmodel->numskins = 1;
1858
1859 // make skinscenes for the skins (no groups)
1861 for (i = 0;i < loadmodel->numskins;i++)
1862 {
1865 loadmodel->skinscenes[i].loop = true;
1867 }
1868
1869 // model bbox
1870 // LadyHavoc: actually we blow this away later with Mod_Alias_CalculateBoundingBox()
1871 modelradius = pheader->radius;
1872 for (i = 0;i < 3;i++)
1873 {
1874 loadmodel->normalmins[i] = pheader->mins[i];
1875 loadmodel->normalmaxs[i] = pheader->maxs[i];
1876 loadmodel->rotatedmins[i] = -modelradius;
1877 loadmodel->rotatedmaxs[i] = modelradius;
1878 }
1879 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1880 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1881 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1882 if (loadmodel->yawmaxs[0] > modelradius)
1883 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1887 loadmodel->radius = modelradius;
1888 loadmodel->radius2 = modelradius * modelradius;
1889
1890 // go through the lumps, swapping things
1891
1892 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1894 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1895 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1896 for (i = 0;i < pheader->numscenes;i++)
1897 {
1898 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1903 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1904 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1905 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1906 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1907 if (loadmodel->animscenes[i].framerate < 0)
1908 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1909 scene++;
1910 }
1911
1912 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1913 loadmodel->num_bones = pheader->numbones;
1915 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1916 for (i = 0;i < pheader->numbones;i++)
1917 {
1918 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1920 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1921 if (loadmodel->data_bones[i].parent >= i)
1922 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1923 }
1924
1925 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1926 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1927 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1928 for (i = 0;i < pheader->numverts;i++)
1929 {
1930 vertbonecounts[i] = BigLong(bonecount[i]);
1931 if (vertbonecounts[i] != 1)
1932 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1933 }
1934
1935 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1936
1937 meshvertices = pheader->numverts;
1938 meshtriangles = pheader->numtris;
1939
1944 loadmodel->surfmesh.num_vertices = meshvertices;
1945 loadmodel->surfmesh.num_triangles = meshtriangles;
1948
1949 // do most allocations as one merged chunk
1950 // This is only robust for C standard types!
1951 data = (unsigned char *)Mem_Alloc(loadmodel->mempool,
1952 loadmodel->num_surfaces * sizeof(int)
1953 + meshtriangles * sizeof(int[3])
1954 + (meshvertices <= 65536 ? loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]) : 0)
1955 + meshvertices * (sizeof(float[14]) + sizeof(unsigned short) + sizeof(unsigned char[2][4]))
1956 + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7])
1957 + loadmodel->num_bones * sizeof(float[12]));
1958 // Pointers must be taken in descending order of alignment requirement!
1959 loadmodel->surfmesh.data_vertex3f = (float *)data; data += meshvertices * sizeof(float[3]);
1960 loadmodel->surfmesh.data_svector3f = (float *)data; data += meshvertices * sizeof(float[3]);
1961 loadmodel->surfmesh.data_tvector3f = (float *)data; data += meshvertices * sizeof(float[3]);
1962 loadmodel->surfmesh.data_normal3f = (float *)data; data += meshvertices * sizeof(float[3]);
1963 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data; data += meshvertices * sizeof(float[2]);
1964 loadmodel->data_baseboneposeinverse = (float *)data; data += loadmodel->num_bones * sizeof(float[12]);
1966 loadmodel->surfmesh.data_element3i = (int *)data; data += meshtriangles * sizeof(int[3]);
1967 loadmodel->surfmesh.blends = (unsigned short *)data; data += meshvertices * sizeof(unsigned short);
1968 if (loadmodel->surfmesh.num_vertices <= 65536)
1969 {
1970 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1971 }
1972 loadmodel->data_poses7s = (short *)data; data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
1973 loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data; data += meshvertices * sizeof(unsigned char[4]);
1974 loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data; data += meshvertices * sizeof(unsigned char[4]);
1975 // Struct alignment requirements could change so we can't assume them here
1976 // otherwise a safe-looking commit could introduce undefined behaviour!
1979
1980 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1981 poses = (float *) (pheader->lump_poses.start + pbase);
1982 // figure out scale of model from root bone, for compatibility with old zmodel versions
1983 tempvec[0] = BigFloat(poses[0]);
1984 tempvec[1] = BigFloat(poses[1]);
1985 tempvec[2] = BigFloat(poses[2]);
1986 modelscale = VectorLength(tempvec);
1987 biggestorigin = 0;
1988 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1989 {
1990 f = fabs(BigFloat(poses[i]));
1991 biggestorigin = max(biggestorigin, f);
1992 }
1993 loadmodel->num_posescale = biggestorigin / 32767.0f;
1995 for (i = 0;i < numposes;i++)
1996 {
1997 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1998 for (j = 0;j < loadmodel->num_bones;j++)
1999 {
2000 float pose[12];
2001 matrix4x4_t posematrix;
2002 for (k = 0;k < 12;k++)
2003 pose[k] = BigFloat(frameposes[j*12+k]);
2004 //if (j < loadmodel->num_bones)
2005 // Con_Printf("%s: bone %i = %f %f %f %f : %f %f %f %f : %f %f %f %f : scale = %f\n", loadmodel->name, j, pose[0], pose[1], pose[2], pose[3], pose[4], pose[5], pose[6], pose[7], pose[8], pose[9], pose[10], pose[11], VectorLength(pose));
2006 // scale child bones to match the root scale
2007 if (loadmodel->data_bones[j].parent >= 0)
2008 {
2009 pose[3] *= modelscale;
2010 pose[7] *= modelscale;
2011 pose[11] *= modelscale;
2012 }
2013 // normalize rotation matrix
2014 VectorNormalize(pose + 0);
2015 VectorNormalize(pose + 4);
2016 VectorNormalize(pose + 8);
2017 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2019 }
2020 }
2021
2022 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
2023 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
2024 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
2025 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2026 // (converting from weight-blending skeletal animation to
2027 // deformation-based skeletal animation)
2028 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2029 for (i = 0;i < loadmodel->num_bones;i++)
2030 {
2031 float m[12];
2032 for (k = 0;k < 12;k++)
2033 m[k] = BigFloat(poses[i*12+k]);
2034 if (loadmodel->data_bones[i].parent >= 0)
2035 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2036 else
2037 for (k = 0;k < 12;k++)
2038 bonepose[12*i+k] = m[k];
2039 }
2040 for (j = 0;j < pheader->numverts;j++)
2041 {
2042 // this format really should have had a per vertexweight weight value...
2043 // but since it does not, the weighting is completely ignored and
2044 // only one weight is allowed per vertex
2045 int boneindex = BigLong(vertdata[j].bonenum);
2046 const float *m = bonepose + 12 * boneindex;
2047 float relativeorigin[3];
2048 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
2049 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
2050 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
2051 // transform the vertex bone weight into the base mesh
2052 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
2053 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
2054 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
2055 // store the weight as the primary weight on this vertex
2056 loadmodel->surfmesh.blends[j] = boneindex;
2057 loadmodel->surfmesh.data_skeletalindex4ub[j*4 ] = boneindex;
2065 }
2066 Z_Free(bonepose);
2067 // normals and tangents are calculated after elements are loaded
2068
2069 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
2070 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
2071 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
2072 for (i = 0;i < pheader->numverts;i++)
2073 {
2074 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
2075 // flip T coordinate for OpenGL
2076 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2077 }
2078
2079 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2080 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2081 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2082
2083 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2084 //zymlump_t lump_render; // int renderlist[rendersize]; // sorted by shader with run lengths (int count), shaders are sequentially used, each run can be used with glDrawElements (each triangle is 3 int indices)
2085 // byteswap, validate, and swap winding order of tris
2086 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2087 if (pheader->lump_render.length != count)
2088 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2089 renderlist = (int *) (pheader->lump_render.start + pbase);
2090 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2091 meshtriangles = 0;
2092 for (i = 0;i < loadmodel->num_surfaces;i++)
2093 {
2094 int firstvertex, lastvertex;
2095 if (renderlist >= renderlistend)
2096 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2097 count = BigLong(*renderlist);renderlist++;
2098 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2099 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2100
2102 surface = loadmodel->data_surfaces + i;
2103 surface->texture = loadmodel->data_textures + i;
2104 surface->num_firsttriangle = meshtriangles;
2105 surface->num_triangles = count;
2106 meshtriangles += surface->num_triangles;
2107
2108 // load the elements
2109 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2110 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2111 {
2112 outelements[j*3+2] = BigLong(renderlist[0]);
2113 outelements[j*3+1] = BigLong(renderlist[1]);
2114 outelements[j*3+0] = BigLong(renderlist[2]);
2115 }
2116 // validate the elements and find the used vertex range
2117 firstvertex = meshvertices;
2118 lastvertex = 0;
2119 for (j = 0;j < surface->num_triangles * 3;j++)
2120 {
2121 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2122 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2123 firstvertex = min(firstvertex, outelements[j]);
2124 lastvertex = max(lastvertex, outelements[j]);
2125 }
2126 surface->num_firstvertex = firstvertex;
2127 surface->num_vertices = lastvertex + 1 - firstvertex;
2128
2129 // since zym models do not have named sections, reuse their shader
2130 // name as the section name
2131 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2132 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2133 }
2134 Mod_FreeSkinFiles(skinfiles);
2135 Mem_Free(vertbonecounts);
2136 Mem_Free(verts);
2138
2139 // compute all the mesh information that was not loaded from the file
2141 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2150
2151 // Always make a BIH for the first frame, we can use it where possible.
2154 {
2160 }
2161}
GLenum GLenum GLsizei count
Definition glquake.h:656
#define ZYMSCENEFLAG_NOLOOP
char name[32]
float framerate
zymlump_t lump_verts
zymlump_t lump_bones
zymlump_t lump_render
zymlump_t lump_poses
zymlump_t lump_trizone
zymlump_t lump_texcoords
zymlump_t lump_vertbonecounts
zymlump_t lump_scenes
zymlump_t lump_shaders

References model_t::AnimateVertices, model_t::animscenes, BigFloat, BigLong, surfmesh_t::blends, buffer, model_t::collision_bih, model_t::CompileShadowMap, Con_Printf(), count, data, model_t::data_baseboneposeinverse, surfmesh_t::data_blendweights, model_t::data_bones, surfmesh_t::data_element3i, surfmesh_t::data_element3s, surfmesh_t::data_normal3f, model_t::data_poses7s, surfmesh_t::data_skeletalindex4ub, surfmesh_t::data_skeletalweight4ub, model_t::data_surfaces, surfmesh_t::data_svector3f, surfmesh_t::data_texcoordtexture2f, model_t::data_textures, surfmesh_t::data_tvector3f, surfmesh_t::data_vertex3f, model_t::Draw, model_t::DrawDebug, model_t::DrawDepth, model_t::DrawLight, model_t::DrawPrepass, model_t::DrawShadowMap, f, fabs(), zymtype1header_t::filesize, animscene_t::firstframe, aliasbone_t::flags, flags, zymscene_t::flags, animscene_t::framecount, animscene_t::framerate, zymscene_t::framerate, Host_Error(), i, zymtype1header_t::id, int(), cvar_t::integer, surfmesh_t::isanimated, zymlump_t::length, zymscene_t::length, loadmodel, animscene_t::loop, zymtype1header_t::lump_bones, zymtype1header_t::lump_poses, zymtype1header_t::lump_render, zymtype1header_t::lump_scenes, zymtype1header_t::lump_shaders, zymtype1header_t::lump_texcoords, zymtype1header_t::lump_trizone, zymtype1header_t::lump_vertbonecounts, zymtype1header_t::lump_verts, Matrix4x4_FromArray12FloatD3D(), Matrix4x4_ToBonePose7s(), max, zymtype1header_t::maxs, Mem_Alloc, Mem_AllocType, Mem_Free, model_t::mempool, min, zymtype1header_t::mins, mod_alias, Mod_Alias_CalculateBoundingBox(), mod_alias_force_animated, Mod_BuildAliasSkinsFromSkinFiles(), Mod_BuildBaseBonePoses(), Mod_BuildNormals(), Mod_BuildTextureVectorsFromNormals(), Mod_CollisionBIH_PointSuperContents_Mesh(), Mod_CollisionBIH_TraceBox(), Mod_CollisionBIH_TraceBrush(), Mod_CollisionBIH_TraceLine(), Mod_CollisionBIH_TracePoint_Mesh(), Mod_FreeSkinFiles(), Mod_LoadSkinFiles(), Mod_MakeCollisionBIH(), Mod_MakeSortedSurfaces(), Mod_MDLMD2MD3_TraceBox(), Mod_MDLMD2MD3_TraceLine(), Mod_Skeletal_AnimateVertices(), Mod_ValidateElements(), model_t::modeldatatypestring, model_t::modelsurfaces_sorted, aliasbone_t::name, animscene_t::name, model_t::name, zymbone_t::name, zymscene_t::name, model_t::normalmaxs, model_t::normalmins, NULL, surfmesh_t::num_blends, model_t::num_bones, msurface_t::num_firsttriangle, msurface_t::num_firstvertex, model_t::num_poseinvscale, model_t::num_poses, model_t::num_posescale, model_t::num_surfaces, model_t::num_textures, model_t::num_texturesperskin, msurface_t::num_triangles, surfmesh_t::num_triangles, msurface_t::num_vertices, surfmesh_t::num_vertices, zymtype1header_t::numbones, model_t::numframes, zymtype1header_t::numscenes, zymtype1header_t::numshaders, model_t::numskins, zymtype1header_t::numtris, zymtype1header_t::numverts, origin, aliasbone_t::parent, model_t::PointSuperContents, R_ConcatTransforms(), R_Mod_CompileShadowMap(), R_Mod_Draw(), R_Mod_DrawDebug(), R_Mod_DrawDepth(), R_Mod_DrawLight(), R_Mod_DrawPrepass(), R_Mod_DrawShadowMap(), r_smoothnormals_areaweighting, model_t::radius, zymtype1header_t::radius, model_t::radius2, model_t::rotatedmaxs, model_t::rotatedmins, model_t::skinscenes, sqrt(), ST_RAND, zymlump_t::start, zymscene_t::start, cvar_t::string, model_t::submodelsurfaces_end, model_t::submodelsurfaces_start, model_t::surfmesh, model_t::synctype, msurface_t::texture, model_t::TraceBox, model_t::TraceBrush, model_t::TraceLine, model_t::TracePoint, model_t::type, zymtype1header_t::type, VectorLength, VectorNormalize, model_t::yawmaxs, model_t::yawmins, Z_Free, Z_Malloc, and ZYMSCENEFLAG_NOLOOP.

Variable Documentation

◆ mod_alias_force_animated

cvar_t mod_alias_force_animated = {CF_CLIENT | CF_SERVER, "mod_alias_force_animated", "", "if set to an non-empty string, overrides the is-animated flag of any alias models (for benchmarking)"}

Definition at line 40 of file model_alias.c.

40{CF_CLIENT | CF_SERVER, "mod_alias_force_animated", "", "if set to an non-empty string, overrides the is-animated flag of any alias models (for benchmarking)"};
#define CF_SERVER
cvar/command that only the server can change/execute
Definition cmd.h:49
#define CF_CLIENT
cvar/command that only the client can change/execute
Definition cmd.h:48

Referenced by Mod_AliasInit(), Mod_DARKPLACESMODEL_Load(), Mod_IDP0_Load(), Mod_IDP2_Load(), Mod_IDP3_Load(), Mod_INTERQUAKEMODEL_Load(), Mod_PSKMODEL_Load(), and Mod_ZYMOTICMODEL_Load().

◆ mod_alias_supporttagscale

cvar_t mod_alias_supporttagscale = {CF_CLIENT | CF_SERVER, "mod_alias_supporttagscale", "1", "support scaling factors in bone/tag attachment matrices as supported by MD3"}

Definition at line 39 of file model_alias.c.

39{CF_CLIENT | CF_SERVER, "mod_alias_supporttagscale", "1", "support scaling factors in bone/tag attachment matrices as supported by MD3"};

Referenced by Mod_Alias_GetTagMatrix(), and Mod_AliasInit().

◆ mod_md3_sin

float mod_md3_sin[320]

◆ Mod_Skeletal_AnimateVertices_bonepose

void* Mod_Skeletal_AnimateVertices_bonepose = NULL
static

◆ Mod_Skeletal_AnimateVertices_maxbonepose

size_t Mod_Skeletal_AnimateVertices_maxbonepose = 0
static

◆ r_nolerp_list

cvar_t r_nolerp_list
extern

Definition at line 204 of file gl_rmain.c.

204{CF_CLIENT | CF_ARCHIVE, "r_nolerp_list", "progs/v_nail.mdl,progs/v_nail2.mdl,progs/flame.mdl,progs/flame2.mdl,progs/braztall.mdl,progs/brazshrt.mdl,progs/longtrch.mdl,progs/flame_pyre.mdl,progs/v_saw.mdl,progs/v_xfist.mdl,progs/h2stuff/newfire.mdl", "comma separated list of models that will not have their animations smoothed"};
#define CF_ARCHIVE
cvar should have its set value saved to config.cfg and persist across sessions
Definition cmd.h:53

Referenced by GL_Main_Init(), and Mod_IDP0_Load().

◆ r_skeletal_debugbone

cvar_t r_skeletal_debugbone = {CF_CLIENT, "r_skeletal_debugbone", "-1", "development cvar for testing skeletal model code"}

Definition at line 33 of file model_alias.c.

33{CF_CLIENT, "r_skeletal_debugbone", "-1", "development cvar for testing skeletal model code"};

Referenced by Mod_AliasInit(), and Mod_Skeletal_BuildTransforms().

◆ r_skeletal_debugbonecomponent

cvar_t r_skeletal_debugbonecomponent = {CF_CLIENT, "r_skeletal_debugbonecomponent", "3", "development cvar for testing skeletal model code"}

Definition at line 34 of file model_alias.c.

34{CF_CLIENT, "r_skeletal_debugbonecomponent", "3", "development cvar for testing skeletal model code"};

Referenced by Mod_AliasInit(), and Mod_Skeletal_BuildTransforms().

◆ r_skeletal_debugbonevalue

cvar_t r_skeletal_debugbonevalue = {CF_CLIENT, "r_skeletal_debugbonevalue", "100", "development cvar for testing skeletal model code"}

Definition at line 35 of file model_alias.c.

35{CF_CLIENT, "r_skeletal_debugbonevalue", "100", "development cvar for testing skeletal model code"};

Referenced by Mod_AliasInit(), and Mod_Skeletal_BuildTransforms().

◆ r_skeletal_debugtranslatex

cvar_t r_skeletal_debugtranslatex = {CF_CLIENT, "r_skeletal_debugtranslatex", "1", "development cvar for testing skeletal model code"}

Definition at line 36 of file model_alias.c.

36{CF_CLIENT, "r_skeletal_debugtranslatex", "1", "development cvar for testing skeletal model code"};

Referenced by Mod_AliasInit(), and Mod_Skeletal_BuildTransforms().

◆ r_skeletal_debugtranslatey

cvar_t r_skeletal_debugtranslatey = {CF_CLIENT, "r_skeletal_debugtranslatey", "1", "development cvar for testing skeletal model code"}

Definition at line 37 of file model_alias.c.

37{CF_CLIENT, "r_skeletal_debugtranslatey", "1", "development cvar for testing skeletal model code"};

Referenced by Mod_AliasInit(), and Mod_Skeletal_BuildTransforms().

◆ r_skeletal_debugtranslatez

cvar_t r_skeletal_debugtranslatez = {CF_CLIENT, "r_skeletal_debugtranslatez", "1", "development cvar for testing skeletal model code"}

Definition at line 38 of file model_alias.c.

38{CF_CLIENT, "r_skeletal_debugtranslatez", "1", "development cvar for testing skeletal model code"};

Referenced by Mod_AliasInit(), and Mod_Skeletal_BuildTransforms().