@@ -3031,6 +3031,8 @@ Mod_LoadAliasGroup
30313031*/
30323032void * Mod_LoadAliasGroup (void * pin , aliashdr_t * pheader , const int index )
30333033{
3034+ assert (pheader -> poseverttype == PV_QUAKE1 );
3035+
30343036 maliasframedesc_t * frame = & pheader -> frames [index ];
30353037 daliasgroup_t * pingroup ;
30363038 int i , numframes ;
@@ -3378,6 +3380,8 @@ Mod_LoadAllSkins
33783380*/
33793381void * Mod_LoadAllSkins (aliashdr_t * pheader , qmodel_t * mod , byte * mod_base , int numskins , byte * pskintype )
33803382{
3383+ assert (pheader -> poseverttype == PV_QUAKE1 );
3384+
33813385 if (numskins < 1 || numskins > MAX_SKINS )
33823386 Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d" , numskins );
33833387
@@ -4482,17 +4486,13 @@ Mod_LoadMD5MeshModel
44824486*/
44834487static void Mod_LoadMD5MeshModel (qmodel_t * mod , const void * buffer )
44844488{
4485- const char * fname = mod -> name ;
4486- unsigned short * poutindexes = NULL ;
4487- md5vert_t * poutvertexes = NULL ;
4488- aliashdr_t * outhdr , * surf ;
4489- size_t hdrsize ;
4490- size_t numjoints , j ;
4491- size_t nummeshes , m ;
4492- char texname [MAX_QPATH ];
4493- md5vertinfo_t * vinfo = NULL ;
4494- md5weightinfo_t * weight = NULL ;
4495- size_t numweights ;
4489+ const char * fname = mod -> name ;
4490+
4491+ aliashdr_t * outhdr , * surf ;
4492+ size_t hdrsize ;
4493+ size_t numjoints , j ;
4494+ size_t nummeshes , m ;
4495+ char texname [MAX_QPATH ];
44964496
44974497 md5animctx_t anim = {NULL };
44984498
@@ -4519,10 +4519,14 @@ static void Mod_LoadMD5MeshModel (qmodel_t *mod, const void *buffer)
45194519
45204520 hdrsize = sizeof (* outhdr ) - sizeof (outhdr -> frames );
45214521 hdrsize += sizeof (outhdr -> frames ) * anim .numposes ;
4522- outhdr = (aliashdr_t * )Mem_Alloc (hdrsize * numjoints );
4522+
4523+ // alloc all aliashdr_t and their chained nextsurface, a.k.a nummeshes, in one array
4524+ outhdr = (aliashdr_t * )Mem_Alloc (hdrsize * nummeshes );
4525+
45234526 TEMP_ALLOC_ZEROED (jointinfo_t , joint_infos , numjoints );
45244527 TEMP_ALLOC_ZEROED (jointpose_t , joint_poses , numjoints );
45254528
4529+ // 1. Load joints
45264530 MD5EXPECT ("{" );
45274531 for (j = 0 ; j < numjoints ; j ++ )
45284532 {
@@ -4558,18 +4562,40 @@ static void Mod_LoadMD5MeshModel (qmodel_t *mod, const void *buffer)
45584562 MD5Anim_Load (& anim , joint_infos , numjoints );
45594563 buffer = COM_Parse (buffer );
45604564
4561- int index_offset = 0 ;
4562- int vertex_offset = 0 ;
4563- int weight_offset = 0 ;
4565+ // 2. Compute inverted joints:
4566+ TEMP_ALLOC_ZEROED (jointpose_t , inverted_joints , anim .numjoints * anim .numposes );
4567+ TEMP_ALLOC_ZEROED (jointpose_t , concat_joints , anim .numjoints );
4568+ for (size_t pose_index = 0 ; pose_index < anim .numposes ; ++ pose_index )
4569+ {
4570+ const jointpose_t * in_pose = anim .posedata + (pose_index * anim .numjoints );
4571+ const jointpose_t * out_pose = inverted_joints + (pose_index * anim .numjoints );
4572+ for (size_t joint_index = 0 ; joint_index < anim .numjoints ; ++ joint_index )
4573+ {
4574+ // concat it onto the parent (relative->abs)
4575+ if (joint_infos [joint_index ].parent < 0 )
4576+ memcpy (concat_joints [joint_index ].mat , in_pose [joint_index ].mat , sizeof (jointpose_t ));
4577+ else
4578+ R_ConcatTransforms (
4579+ (void * )concat_joints [joint_infos [joint_index ].parent ].mat , (void * )in_pose [joint_index ].mat , (void * )concat_joints [joint_index ].mat );
4580+ // and finally invert it
4581+ R_ConcatTransforms ((void * )concat_joints [joint_index ].mat , (void * )joint_infos [joint_index ].inverse .mat , (void * )out_pose [joint_index ].mat );
4582+ }
4583+ }
4584+ Mem_Free (anim .posedata );
45644585
4565- size_t total_numverts = 0 ;
4566- size_t total_numweights = 0 ;
4586+ // 3. each mesh has its own aliashdr_t : load vertices, triangles, textures...etc. and upload to GPU each surface:
4587+
4588+ // total_numverts and total_vertexes accumulate all vertices of the ssurface,
4589+ // just to be able to Mod_CalcAliasBounds at the end.
4590+ size_t total_numverts = 0 ;
4591+ md5vert_t * total_vertexes = NULL ;
45674592
45684593 for (m = 0 ; m < nummeshes ; m ++ )
45694594 {
45704595 MD5EXPECT ("mesh" );
45714596 MD5EXPECT ("{" );
45724597
4598+ // go to the surf, a.k.a mesh, chaining the next nextsurface
45734599 surf = (aliashdr_t * )((byte * )outhdr + m * hdrsize );
45744600 if (m + 1 < nummeshes )
45754601 surf -> nextsurface = (aliashdr_t * )((byte * )outhdr + (m + 1 ) * hdrsize );
@@ -4596,6 +4622,7 @@ static void Mod_LoadMD5MeshModel (qmodel_t *mod, const void *buffer)
45964622 surf -> numframes = j ;
45974623 }
45984624
4625+ //"shader" is the texture of the surf
45994626 MD5EXPECT ("shader" );
46004627 // MD5 violation: the skin is a single material. adding prefixes/postfixes here is the wrong thing to do.
46014628 // but we do so anyway, because rerelease compat.
@@ -4700,34 +4727,35 @@ static void Mod_LoadMD5MeshModel (qmodel_t *mod, const void *buffer)
47004727 surf -> fbtextures [surf -> numskins ][2 ] = surf -> fbtextures [surf -> numskins ][0 ];
47014728 }
47024729 }
4703-
4730+ // MD5 have only 1 pose, a.k.a frame in MDL / MD3
4731+ // because it uses skeletal animation instead of displaying/interpolating different frames/poses of vertices
47044732 surf -> numposes = 1 ;
47054733
47064734 buffer = COM_Parse (buffer );
47074735 MD5EXPECT ("numverts" );
47084736 surf -> numverts_vbo = surf -> numverts = MD5UINT ();
47094737
4710- vinfo = (md5vertinfo_t * )Mem_Realloc ( vinfo , sizeof (* vinfo ) * ( vertex_offset + surf -> numverts ) );
4711- poutvertexes = (md5vert_t * )Mem_Realloc ( poutvertexes , sizeof (* poutvertexes ) * ( vertex_offset + surf -> numverts ) );
4712- total_numverts += surf -> numverts ;
4738+ md5vertinfo_t * vinfo = (md5vertinfo_t * )Mem_Alloc ( sizeof (* vinfo ) * surf -> numverts );
4739+ md5vert_t * poutvertexes = (md5vert_t * )Mem_Alloc ( sizeof (* poutvertexes ) * surf -> numverts );
4740+
47134741 while (MD5CHECK ("vert" ))
47144742 {
47154743 size_t idx = MD5UINT ();
47164744 if (idx >= (size_t )surf -> numverts )
47174745 Sys_Error ("vertex index out of bounds" );
47184746 MD5EXPECT ("(" );
4719- poutvertexes [vertex_offset + idx ].st [0 ] = MD5FLOAT ();
4720- poutvertexes [vertex_offset + idx ].st [1 ] = MD5FLOAT ();
4747+ poutvertexes [idx ].st [0 ] = MD5FLOAT ();
4748+ poutvertexes [idx ].st [1 ] = MD5FLOAT ();
47214749 MD5EXPECT (")" );
4722- vinfo [vertex_offset + idx ].firstweight = MD5UINT () + weight_offset ; // shift firstwieight by numwieigts of previous meshes
4723- vinfo [vertex_offset + idx ].count = MD5UINT ();
4750+ vinfo [idx ].firstweight = MD5UINT ();
4751+ vinfo [idx ].count = MD5UINT ();
47244752 }
47254753
47264754 MD5EXPECT ("numtris" );
47274755 surf -> numtris = MD5UINT ();
47284756 surf -> numindexes = surf -> numtris * 3 ;
4729- poutindexes = (unsigned short * )Mem_Realloc ( poutindexes , sizeof (* poutindexes ) * (index_offset + surf -> numindexes ));
4730- outhdr -> total_numindexes += surf -> numindexes ;
4757+ unsigned short * poutindexes = (unsigned short * )Mem_Alloc ( sizeof (unsigned short ) * (surf -> numindexes ));
4758+
47314759 while (MD5CHECK ("tri" ))
47324760 {
47334761 size_t idx = MD5UINT ();
@@ -4739,92 +4767,72 @@ static void Mod_LoadMD5MeshModel (qmodel_t *mod, const void *buffer)
47394767 size_t t = MD5UINT ();
47404768 if (t > (size_t )surf -> numverts )
47414769 Sys_Error ("vertex index out of bounds" );
4742- poutindexes [index_offset + idx + j ] = t + vertex_offset ; // shift indices by numvertindexes of previous meshes
4770+ poutindexes [idx + j ] = t ;
47434771 }
47444772 }
47454773
47464774 // md5 is a gpu-unfriendly interchange format. :(
47474775 MD5EXPECT ("numweights" );
4748- numweights = MD5UINT ();
4749- weight = (md5weightinfo_t * )Mem_Realloc (weight , sizeof (* weight ) * (weight_offset + numweights ));
4750- total_numweights += numweights ;
4776+ size_t numweights = MD5UINT ();
4777+ md5weightinfo_t * weight = (md5weightinfo_t * )Mem_Alloc (sizeof (* weight ) * numweights );
47514778
47524779 while (MD5CHECK ("weight" ))
47534780 {
47544781 size_t idx = MD5UINT ();
47554782 if (idx >= numweights )
47564783 Sys_Error ("weight index out of bounds" );
47574784
4758- weight [weight_offset + idx ].joint_index = MD5UINT ();
4759- if (weight [weight_offset + idx ].joint_index >= numjoints )
4785+ weight [idx ].joint_index = MD5UINT ();
4786+ if (weight [idx ].joint_index >= numjoints )
47604787 Sys_Error ("joint index out of bounds" );
4761- weight [weight_offset + idx ].pos [3 ] = MD5FLOAT ();
4788+ weight [idx ].pos [3 ] = MD5FLOAT ();
47624789 MD5EXPECT ("(" );
4763- weight [weight_offset + idx ].pos [0 ] = MD5FLOAT () * weight [weight_offset + idx ].pos [3 ];
4764- weight [weight_offset + idx ].pos [1 ] = MD5FLOAT () * weight [weight_offset + idx ].pos [3 ];
4765- weight [weight_offset + idx ].pos [2 ] = MD5FLOAT () * weight [weight_offset + idx ].pos [3 ];
4790+ weight [idx ].pos [0 ] = MD5FLOAT () * weight [idx ].pos [3 ];
4791+ weight [idx ].pos [1 ] = MD5FLOAT () * weight [idx ].pos [3 ];
4792+ weight [idx ].pos [2 ] = MD5FLOAT () * weight [idx ].pos [3 ];
47664793 MD5EXPECT (")" );
47674794 }
47684795
47694796 MD5EXPECT ("}" );
47704797
4771- // increment offsets for the next meshes
4772- vertex_offset += surf -> numverts ;
4773- index_offset += surf -> numindexes ;
4774- weight_offset += numweights ;
4798+ // so make it gpu-friendly.
4799+ MD5_BakeInfluences (fname , joint_poses , poutvertexes , vinfo , weight , surf -> numverts , numweights );
4800+ // and now make up the normals that the format lacks. we'll still probably have issues from seams, but then so did qme, so at least its faithful...
4801+ // :P
4802+ MD5_ComputeNormals (poutvertexes , surf -> numverts , poutindexes , surf -> numindexes );
47754803
4776- } // end foreach mesh
4804+ Mem_Free (weight );
4805+ Mem_Free (vinfo );
47774806
4778- // vertex indices are 16 bit (VK_INDEX_TYPE_UINT16) so we cannot address more than MAXALIASVERTS vertexes.
4779- if (total_numverts > MAXALIASVERTS )
4780- Sys_Error ("MD5 model %s has too many vertices (%d; max = %d)" , mod -> name , (int )total_numverts , MAXALIASVERTS );
4807+ // Upload to GPU that surface/mesh m:
4808+ GLMesh_UploadBuffers (mod , surf , poutindexes , (byte * )poutvertexes , NULL , inverted_joints );
47814809
4782- // so make it gpu-friendly.
4783- MD5_BakeInfluences (fname , joint_poses , poutvertexes , vinfo , weight , total_numverts , total_numweights );
4784- // and now make up the normals that the format lacks. we'll still probably have issues from seams, but then so did qme, so at least its faithful...
4785- // :P
4786- MD5_ComputeNormals (poutvertexes , total_numverts , poutindexes , outhdr -> total_numindexes );
4810+ // concat surface vertices to total_vertexes
4811+ total_vertexes = (md5vert_t * )Mem_Realloc (total_vertexes , sizeof (* poutvertexes ) * (total_numverts + surf -> numverts ));
4812+ memcpy ((void * )(total_vertexes + total_numverts ), (const void * )poutvertexes , sizeof (* poutvertexes ) * surf -> numverts );
4813+ total_numverts += surf -> numverts ;
47874814
4788- Mem_Free (weight );
4789- Mem_Free (vinfo );
4815+ Mem_Free (poutvertexes );
4816+ Mem_Free (poutindexes );
47904817
4791- TEMP_ALLOC_ZEROED (jointpose_t , inverted_joints , anim .numjoints * anim .numposes );
4792- TEMP_ALLOC_ZEROED (jointpose_t , concat_joints , anim .numjoints );
4793- for (size_t pose_index = 0 ; pose_index < anim .numposes ; ++ pose_index )
4794- {
4795- const jointpose_t * in_pose = anim .posedata + (pose_index * anim .numjoints );
4796- const jointpose_t * out_pose = inverted_joints + (pose_index * anim .numjoints );
4797- for (size_t joint_index = 0 ; joint_index < anim .numjoints ; ++ joint_index )
4798- {
4799- // concat it onto the parent (relative->abs)
4800- if (joint_infos [joint_index ].parent < 0 )
4801- memcpy (concat_joints [joint_index ].mat , in_pose [joint_index ].mat , sizeof (jointpose_t ));
4802- else
4803- R_ConcatTransforms (
4804- (void * )concat_joints [joint_infos [joint_index ].parent ].mat , (void * )in_pose [joint_index ].mat , (void * )concat_joints [joint_index ].mat );
4805- // and finally invert it
4806- R_ConcatTransforms ((void * )concat_joints [joint_index ].mat , (void * )joint_infos [joint_index ].inverse .mat , (void * )out_pose [joint_index ].mat );
4807- }
4808- }
4809- Mem_Free (anim .posedata );
4810-
4811- GLMesh_UploadBuffers (mod , outhdr , poutindexes , (byte * )poutvertexes , NULL , inverted_joints );
4812- TEMP_FREE (concat_joints );
4813- TEMP_FREE (inverted_joints );
4818+ } // end foreach mesh
48144819
4815- // the md5 format does not have its own modelflags, yet we still need to know about trails and rotating etc
4820+ // the MD5 format does not have its own modelflags, yet we still need to know about trails and rotating etc
48164821 mod -> flags = MD5_HackyModelFlags (mod -> name );
48174822
48184823 mod -> synctype = ST_FRAMETIME ; // keep MD5 animations synced to when .frame is changed. framegroups are otherwise not very useful.
48194824 mod -> type = mod_alias ;
48204825 mod -> extradata [PV_MD5 ] = (byte * )outhdr ;
48214826
4822- Mod_CalcAliasBounds (mod , outhdr , total_numverts , (byte * )poutvertexes ); // johnfitz
4827+ Mod_CalcAliasBounds (mod , outhdr , total_numverts , (byte * )total_vertexes ); // johnfitz
4828+
4829+ Mem_Free (total_vertexes );
4830+
4831+ TEMP_FREE (concat_joints );
4832+ TEMP_FREE (inverted_joints );
48234833
48244834 TEMP_FREE (joint_poses );
48254835 TEMP_FREE (joint_infos )
4826- Mem_Free (poutvertexes );
4827- Mem_Free (poutindexes );
48284836}
48294837
48304838//=============================================================================
0 commit comments