DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
model_shared.h File Reference
#include <stddef.h>
#include "qdefs.h"
#include "bspfile.h"
#include "r_qshader.h"
#include "matrixlib.h"
#include "bih.h"
#include "model_brush.h"
#include "model_q1bsp.h"
#include "model_q2bsp.h"
#include "model_q3bsp.h"
#include "model_vbsp.h"
#include "model_sprite.h"
#include "model_alias.h"
+ Include dependency graph for model_shared.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  animscene_t
 
struct  blendweights_t
 
struct  mod_alloclightmap_row_t
 
struct  mod_alloclightmap_state_t
 
struct  model_t
 
struct  modloader_t
 
struct  msurface_lightmapinfo_t
 
struct  msurface_t
 describes the textures to use on a range of triangles in the model, and mins/maxs (AABB) for culling. More...
 
struct  mtexinfo_t
 
struct  r_meshbuffer_t
 
struct  shadowmesh_t
 
struct  shadowmeshvertexhash_t
 
struct  skinfile_t
 
struct  skinfileitem_t
 
struct  surfmesh_t
 
struct  texture_t
 
struct  texvecvertex_t
 

Macros

#define SHADOWMESHVERTEXHASH   1024
 

Enumerations

enum  modtype_t {
  mod_invalid , mod_brushq1 , mod_sprite , mod_alias ,
  mod_brushq2 , mod_brushq3 , mod_brushhl2 , mod_obj ,
  mod_null
}
 
enum  synctype_t { ST_SYNC =0 , ST_RAND }
 

Functions

void Mod_2PSB_Load (model_t *mod, void *buffer, void *bufferend)
 
int Mod_Alias_GetExtendedTagInfoForIndex (const model_t *model, unsigned int skin, const struct frameblend_s *frameblend, const struct skeleton_s *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 struct frameblend_s *frameblend, const struct skeleton_s *skeleton, int tagindex, matrix4x4_t *outmatrix)
 
void Mod_AliasInit (void)
 
qbool Mod_AllocLightmap_Block (mod_alloclightmap_state_t *state, int blockwidth, int blockheight, int *outx, int *outy)
 
void Mod_AllocLightmap_Free (mod_alloclightmap_state_t *state)
 
void Mod_AllocLightmap_Init (mod_alloclightmap_state_t *state, struct mempool_s *mempool, int width, int height)
 
void Mod_AllocLightmap_Reset (mod_alloclightmap_state_t *state)
 
void Mod_AllocSurfMesh (struct mempool_s *mempool, int numvertices, int numtriangles, qbool lightmapoffsets, qbool vertexcolors)
 
void Mod_BrushInit (void)
 
void Mod_BSP2_Load (model_t *mod, void *buffer, void *bufferend)
 
void Mod_BuildAliasSkinsFromSkinFiles (texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
 
void Mod_BuildNormals (int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const int *elements, float *normal3f, qbool areaweighting)
 
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)
 
void Mod_BuildVBOs (void)
 
int Mod_BuildVertexRemapTableFromElements (int numelements, const int *elements, int numvertices, int *remapvertices)
 
void Mod_ClearUsed (void)
 
int Mod_CollisionBIH_PointSuperContents (struct model_s *model, int frame, const vec3_t point)
 
int Mod_CollisionBIH_PointSuperContents_Mesh (struct model_s *model, int frame, const vec3_t point)
 
void Mod_CollisionBIH_TraceBox (model_t *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 Mod_CollisionBIH_TraceBrush (model_t *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)
 
void Mod_CollisionBIH_TraceLine (model_t *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)
 
qbool Mod_CollisionBIH_TraceLineOfSight (struct model_s *model, const vec3_t start, const vec3_t end, const vec3_t acceptmins, const vec3_t acceptmaxs)
 
void Mod_CollisionBIH_TracePoint (model_t *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 Mod_CollisionBIH_TracePoint_Mesh (model_t *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)
 
int Mod_CountSkinFiles (skinfile_t *skinfile)
 
void Mod_CreateCollisionMesh (model_t *mod)
 
texture_shaderpass_tMod_CreateShaderPass (struct mempool_s *mempool, struct skinframe_s *skinframe)
 
texture_shaderpass_tMod_CreateShaderPassFromQ3ShaderLayer (struct mempool_s *mempool, const char *modelname, q3shaderinfo_layer_t *layer, int layerindex, int texflags, const char *texturename)
 
void Mod_DARKPLACESMODEL_Load (model_t *mod, void *buffer, void *bufferend)
 
model_tMod_FindName (const char *name, const char *parentname)
 
model_tMod_ForName (const char *name, qbool crash, qbool checkdisk, const char *parentname)
 
void Mod_FreeQ3Shaders (void)
 
void Mod_FreeSkinFiles (skinfile_t *skinfile)
 
void Mod_HLBSP_Load (model_t *mod, void *buffer, void *bufferend)
 
void Mod_IBSP_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_IDS2_Load (model_t *mod, void *buffer, void *bufferend)
 
void Mod_IDSP_Load (model_t *mod, void *buffer, void *bufferend)
 
void Mod_Init (void)
 
void Mod_INTERQUAKEMODEL_Load (model_t *mod, void *buffer, void *bufferend)
 
void Mod_LoadCustomMaterial (struct mempool_s *mempool, texture_t *texture, const char *name, int supercontents, int materialflags, struct skinframe_s *skinframe)
 Sets up a material to render the provided skinframe. See also R_SkinFrame_LoadInternalBGRA.
 
model_tMod_LoadModel (model_t *mod, qbool crash, qbool checkdisk)
 
void Mod_LoadQ3Shaders (void)
 
skinfile_tMod_LoadSkinFiles (void)
 
qbool Mod_LoadTextureFromQ3Shader (struct mempool_s *mempool, const char *modelname, texture_t *texture, const char *name, qbool warnmissing, qbool fallback, int defaulttexflags, int defaultmaterialflags)
 
shader_tMod_LookupQ3Shader (const char *name)
 
bih_tMod_MakeCollisionBIH (model_t *model, qbool userendersurfaces, bih_t *out)
 
void Mod_MakeSortedSurfaces (model_t *mod)
 
void Mod_MAP_Load (model_t *mod, void *buffer, void *bufferend)
 
msurface_tMod_Mesh_AddSurface (model_t *mod, texture_t *tex, qbool batchwithprevioussurface)
 
void Mod_Mesh_AddTriangle (model_t *mod, msurface_t *surf, int e0, int e1, int e2)
 
void Mod_Mesh_Create (model_t *mod, const char *name)
 
void Mod_Mesh_Destroy (model_t *mod)
 
void Mod_Mesh_Finalize (model_t *mod)
 
texture_tMod_Mesh_GetTexture (model_t *mod, const char *name, int defaultdrawflags, int defaulttexflags, int defaultmaterialflags)
 
int Mod_Mesh_IndexForVertex (model_t *mod, msurface_t *surf, float x, float y, float z, float nx, float ny, float nz, float s, float t, float u, float v, float r, float g, float b, float a)
 
void Mod_Mesh_Reset (model_t *mod)
 
void Mod_Mesh_Validate (model_t *mod)
 
void Mod_OBJ_Load (model_t *mod, void *buffer, void *bufferend)
 
void Mod_PSKMODEL_Load (model_t *mod, void *buffer, void *bufferend)
 
void Mod_PurgeUnused (void)
 
void Mod_Q1BSP_Load (model_t *mod, void *buffer, void *bufferend)
 
int Mod_Q1BSP_NativeContentsFromSuperContents (int supercontents)
 
int Mod_Q1BSP_SuperContentsFromNativeContents (int nativecontents)
 
int Mod_Q2BSP_NativeContentsFromSuperContents (int supercontents)
 
int Mod_Q2BSP_SuperContentsFromNativeContents (int nativecontents)
 
void Mod_Reload (void)
 
int Mod_RemoveDegenerateTriangles (int numtriangles, const int *inelement3i, int *outelement3i, const float *vertex3f)
 
void Mod_RemoveStaleWorldModels (model_t *skip)
 
void Mod_SetDrawSkyAndWater (model_t *mod)
 Sets the mod->DrawSky and mod->DrawAddWaterPlanes pointers conditionally based on whether surfaces in this submodel use these features called specifically by brush model loaders when generating submodels automatically called after model loader returns.
 
void Mod_ShadowMesh_AddMesh (shadowmesh_t *mesh, const float *vertex3f, int numtris, const int *element3i)
 
int Mod_ShadowMesh_AddVertex (shadowmesh_t *mesh, const float *vertex3f)
 
shadowmesh_tMod_ShadowMesh_Alloc (struct mempool_s *mempool, int maxverts, int maxtriangles)
 
shadowmesh_tMod_ShadowMesh_Begin (struct mempool_s *mempool, int maxverts, int maxtriangles)
 
void Mod_ShadowMesh_CalcBBox (shadowmesh_t *firstmesh, vec3_t mins, vec3_t maxs, vec3_t center, float *radius)
 
shadowmesh_tMod_ShadowMesh_Finish (shadowmesh_t *firstmesh, qbool createvbo)
 
void Mod_ShadowMesh_Free (shadowmesh_t *mesh)
 
void Mod_Skeletal_FreeBuffers (void)
 
void Mod_SnapVertices (int numcomponents, int numvertices, float *vertices, float snap)
 
void Mod_SpriteInit (void)
 
void Mod_UnloadCustomMaterial (texture_t *texture, qbool purgeskins)
 Removes all shaderpasses from material, and optionally deletes the textures in the skinframes.
 
void Mod_UnloadModel (model_t *mod)
 
qbool Mod_ValidateElements (int *element3i, unsigned short *element3s, int numtriangles, int firstvertex, int numvertices, const char *filename, int fileline)
 
void Mod_VBSP_Load (model_t *mod, void *buffer, void *bufferend)
 
void Mod_VertexRangeFromElements (int numelements, const int *elements, int *firstvertexpointer, int *lastvertexpointer)
 
void Mod_ZYMOTICMODEL_Load (model_t *mod, void *buffer, void *bufferend)
 
void R_Mod_CompileShadowMap (struct entity_render_s *ent, vec3_t relativelightorigin, vec3_t relativelightdirection, float lightradius, int numsurfaces, const int *surfacelist)
 
void R_Mod_Draw (struct entity_render_s *ent)
 
void R_Mod_DrawAddWaterPlanes (struct entity_render_s *ent)
 
void R_Mod_DrawDebug (struct entity_render_s *ent)
 
void R_Mod_DrawDepth (struct entity_render_s *ent)
 
void R_Mod_DrawLight (struct entity_render_s *ent, int numsurfaces, const int *surfacelist, const unsigned char *trispvs)
 
void R_Mod_DrawPrepass (struct entity_render_s *ent)
 
void R_Mod_DrawShadowMap (int side, struct entity_render_s *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)
 
void R_Mod_DrawSky (struct entity_render_s *ent)
 
void R_Mod_GetLightInfo (struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, unsigned char *outleafpvs, int *outnumleafspointer, int *outsurfacelist, unsigned char *outsurfacepvs, int *outnumsurfacespointer, unsigned char *outshadowtrispvs, unsigned char *outlighttrispvs, unsigned char *visitingleafpvs, int numfrustumplanes, const mplane_t *frustumplanes, qbool noocclusion)
 

Variables

model_tloadmodel
 
char loadname [32]
 
unsigned char * mod_base
 
struct cvar_s mod_noshader_default_offsetmapping
 
struct cvar_s mod_q3bsp_lightgrid_bsp_surfaces
 
struct cvar_s mod_q3bsp_lightgrid_texture
 
struct cvar_s mod_q3bsp_lightgrid_world_surfaces
 
struct cvar_s mod_q3shader_default_offsetmapping
 
struct cvar_s mod_q3shader_default_offsetmapping_bias
 
struct cvar_s mod_q3shader_default_offsetmapping_scale
 
struct cvar_s mod_q3shader_default_polygonfactor
 
struct cvar_s mod_q3shader_default_polygonoffset
 
struct cvar_s mod_q3shader_default_refractive_index
 
struct cvar_s mod_q3shader_force_addalpha
 
struct cvar_s mod_q3shader_force_terrain_alphaflag
 
struct cvar_s r_fullbrights
 
struct cvar_s r_mipnormalmaps
 
struct cvar_s r_mipskins
 

Macro Definition Documentation

◆ SHADOWMESHVERTEXHASH

#define SHADOWMESHVERTEXHASH   1024

Definition at line 152 of file model_shared.h.

Referenced by Mod_ShadowMesh_AddVertex(), and Mod_ShadowMesh_Alloc().

Enumeration Type Documentation

◆ modtype_t

enum modtype_t
Enumerator
mod_invalid 
mod_brushq1 
mod_sprite 
mod_alias 
mod_brushq2 
mod_brushq3 
mod_brushhl2 
mod_obj 
mod_null 

Definition at line 43 of file model_shared.h.

modtype_t
@ mod_invalid
@ mod_obj
@ mod_null
@ mod_brushq3
@ mod_brushq2
@ mod_brushq1
@ mod_alias
@ mod_brushhl2
@ mod_sprite

◆ synctype_t

enum synctype_t
Enumerator
ST_SYNC 
ST_RAND 

Definition at line 34 of file model_shared.h.

synctype_t
@ ST_RAND
@ ST_SYNC

Function Documentation

◆ Mod_2PSB_Load()

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

Definition at line 3881 of file model_brush.c.

3882{
3883 mod->brush.isbsp2 = true;
3884 mod->brush.isbsp2rmqe = true; // like bsp2 except leaf/node bounds are 16bit (unexpanded)
3885 mod->modeldatatypestring = "Q1BSP2rmqe";
3886 Mod_Q1BSP_Load(mod, buffer, bufferend);
3887}
float mod(float dividend, float divisor)
GLuint buffer
Definition glquake.h:630
void Mod_Q1BSP_Load(model_t *mod, void *buffer, void *bufferend)

References buffer, mod(), and Mod_Q1BSP_Load().

◆ Mod_Alias_GetExtendedTagInfoForIndex()

int Mod_Alias_GetExtendedTagInfoForIndex ( const model_t * model,
unsigned int skin,
const struct frameblend_s * frameblend,
const struct skeleton_s * skeleton,
int tagindex,
int * parentindex,
const char ** tagname,
matrix4x4_t * tag_localmatrix )

◆ 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
string model
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 struct frameblend_s * frameblend,
const struct skeleton_s * skeleton,
int tagindex,
matrix4x4_t * outmatrix )

◆ 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 mod_alias_supporttagscale
Definition model_alias.c:39
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_AllocLightmap_Block()

qbool Mod_AllocLightmap_Block ( mod_alloclightmap_state_t * state,
int blockwidth,
int blockheight,
int * outx,
int * outy )

Definition at line 3482 of file model_shared.c.

3483{
3485 int y;
3486
3487 row = state->rows + blockheight;
3488 if ((row->rowY < 0) || (row->currentX + blockwidth > state->width))
3489 {
3490 if (state->currentY + blockheight <= state->height)
3491 {
3492 // use the current allocation position
3493 row->rowY = state->currentY;
3494 row->currentX = 0;
3495 state->currentY += blockheight;
3496 }
3497 else
3498 {
3499 // find another position
3500 for (y = blockheight;y < state->height;y++)
3501 {
3502 if ((state->rows[y].rowY >= 0) && (state->rows[y].currentX + blockwidth <= state->width))
3503 {
3504 row = state->rows + y;
3505 break;
3506 }
3507 }
3508 if (y == state->height)
3509 return false;
3510 }
3511 }
3512 *outy = row->rowY;
3513 *outx = row->currentX;
3514 row->currentX += blockwidth;
3515
3516 return true;
3517}
GLenum GLsizei width
Definition glquake.h:622
GLenum GLsizei GLsizei height
Definition glquake.h:622
GLint GLenum GLint GLint y
Definition glquake.h:651
mod_alloclightmap_row_t * rows

References mod_alloclightmap_row_t::currentX, mod_alloclightmap_state_t::currentY, height, mod_alloclightmap_state_t::height, mod_alloclightmap_state_t::rows, mod_alloclightmap_row_t::rowY, mod_alloclightmap_state_t::width, width, and y.

Referenced by Mod_GenerateLightmaps_CreateLightmaps(), Mod_Q1BSP_LoadFaces(), Mod_VBSP_LoadFaces(), and R_Shadow_PrepareLights().

◆ Mod_AllocLightmap_Free()

void Mod_AllocLightmap_Free ( mod_alloclightmap_state_t * state)

Definition at line 3475 of file model_shared.c.

3476{
3477 if (state->rows)
3478 Mem_Free(state->rows);
3479 memset(state, 0, sizeof(*state));
3480}
#define Mem_Free(mem)
Definition zone.h:96

References Mem_Free, and mod_alloclightmap_state_t::rows.

Referenced by Mod_GenerateLightmaps_CreateLightmaps(), and R_Shadow_FreeShadowMaps().

◆ Mod_AllocLightmap_Init()

void Mod_AllocLightmap_Init ( mod_alloclightmap_state_t * state,
struct mempool_s * mempool,
int width,
int height )

◆ Mod_AllocLightmap_Reset()

void Mod_AllocLightmap_Reset ( mod_alloclightmap_state_t * state)

◆ Mod_AllocSurfMesh()

void Mod_AllocSurfMesh ( struct mempool_s * mempool,
int numvertices,
int numtriangles,
qbool lightmapoffsets,
qbool vertexcolors )

◆ Mod_BrushInit()

void Mod_BrushInit ( void )

Definition at line 80 of file model_brush.c.

81{
82// Cvar_RegisterVariable(&r_subdivide_size);
119
120 // these games were made for older DP engines and are no longer
121 // maintained; use this hack to show their textures properly
122 if(gamemode == GAME_NEXUIZ)
124
129
134
139
144
149}
#define SUPERCONTENTS_SKY
Definition bspfile.h:200
#define SUPERCONTENTS_LAVA
Definition bspfile.h:199
#define SUPERCONTENTS_SLIME
Definition bspfile.h:198
#define SUPERCONTENTS_SOLID
Definition bspfile.h:196
#define SUPERCONTENTS_NODROP
Definition bspfile.h:203
#define SUPERCONTENTS_WATER
Definition bspfile.h:197
gamemode_t gamemode
Definition com_game.c:26
@ GAME_NEXUIZ
Definition com_game.h:33
#define dp_strlcpy(dst, src, dsize)
Definition common.h:303
void Cvar_SetQuick(cvar_t *var, const char *value)
Definition cvar.c:436
cvar_t mod_q3bsp_curves_subdivisions_maxtess
Definition model_brush.c:40
static texture_t mod_q1bsp_texture_sky
Definition model_brush.c:73
cvar_t mod_q3bsp_curves_subdivisions_maxvertices
Definition model_brush.c:41
cvar_t mod_q3shader_force_addalpha
Definition model_brush.c:58
cvar_t mod_bsp_portalize
Definition model_brush.c:67
static texture_t mod_q1bsp_texture_solid
Definition model_brush.c:72
cvar_t mod_q2bsp_littransparentsurfaces
Definition model_brush.c:61
cvar_t mod_q3bsp_lightgrid_world_surfaces
Definition model_brush.c:49
cvar_t mod_q3shader_default_polygonfactor
Definition model_brush.c:55
cvar_t mod_q3bsp_lightmapmergepower
Definition model_brush.c:44
cvar_t mod_noshader_default_offsetmapping
Definition model_brush.c:51
cvar_t mod_q3bsp_curves_subdivisions_mintess
Definition model_brush.c:39
cvar_t mod_q3bsp_nolightmaps
Definition model_brush.c:45
static texture_t mod_q1bsp_texture_lava
Definition model_brush.c:74
cvar_t mod_q3bsp_lightgrid_texture
Definition model_brush.c:48
cvar_t mod_q3bsp_curves_subdivisions_tolerance
Definition model_brush.c:38
cvar_t mod_q3shader_default_offsetmapping_scale
Definition model_brush.c:53
cvar_t mod_recalculatenodeboxes
Definition model_brush.c:68
cvar_t mod_q3bsp_sRGBlightmaps
Definition model_brush.c:47
cvar_t mod_q3bsp_tracelineofsight_brushes
Definition model_brush.c:46
static texture_t mod_q1bsp_texture_slime
Definition model_brush.c:75
cvar_t mod_q3shader_default_polygonoffset
Definition model_brush.c:56
cvar_t mod_q3shader_default_offsetmapping_bias
Definition model_brush.c:54
cvar_t mod_q3bsp_lightgrid_bsp_surfaces
Definition model_brush.c:50
cvar_t mod_q3shader_default_offsetmapping
Definition model_brush.c:52
cvar_t r_nosurftextures
Definition model_brush.c:32
cvar_t mod_q3bsp_curves_collisions
Definition model_brush.c:42
cvar_t r_novis
Definition model_brush.c:31
cvar_t mod_q1bsp_zero_hullsize_cutoff
Definition model_brush.c:65
cvar_t mod_q3bsp_optimizedtraceline
Definition model_brush.c:43
cvar_t r_trippy
Definition model_brush.c:29
cvar_t r_subdivisions_mintess
Definition model_brush.c:35
cvar_t mod_q1bsp_polygoncollisions
Definition model_brush.c:63
static texture_t mod_q1bsp_texture_water
Definition model_brush.c:76
cvar_t r_subdivisions_tolerance
Definition model_brush.c:34
cvar_t mod_q1bsp_traceoutofsolid
Definition model_brush.c:64
cvar_t mod_q3shader_force_terrain_alphaflag
Definition model_brush.c:59
cvar_t r_subdivisions_maxvertices
Definition model_brush.c:37
cvar_t r_subdivisions_maxtess
Definition model_brush.c:36
cvar_t mod_obj_orientation
Definition model_brush.c:70
cvar_t mod_q3shader_default_refractive_index
Definition model_brush.c:57
#define Q3SURFACEFLAG_SKY
#define Q3SURFACEFLAG_NOMARKS
#define Q3SURFACEFLAG_NOIMPACT
#define Q3SURFACEFLAG_NOLIGHTMAP
#define Q3SURFACEFLAG_NODLIGHT
char name[64]
int supercontents

References Cvar_RegisterVariable(), Cvar_SetQuick(), dp_strlcpy, GAME_NEXUIZ, gamemode, mod_bsp_portalize, mod_noshader_default_offsetmapping, mod_obj_orientation, mod_q1bsp_polygoncollisions, mod_q1bsp_texture_lava, mod_q1bsp_texture_sky, mod_q1bsp_texture_slime, mod_q1bsp_texture_solid, mod_q1bsp_texture_water, mod_q1bsp_traceoutofsolid, mod_q1bsp_zero_hullsize_cutoff, mod_q2bsp_littransparentsurfaces, mod_q3bsp_curves_collisions, mod_q3bsp_curves_subdivisions_maxtess, mod_q3bsp_curves_subdivisions_maxvertices, mod_q3bsp_curves_subdivisions_mintess, mod_q3bsp_curves_subdivisions_tolerance, mod_q3bsp_lightgrid_bsp_surfaces, mod_q3bsp_lightgrid_texture, mod_q3bsp_lightgrid_world_surfaces, mod_q3bsp_lightmapmergepower, mod_q3bsp_nolightmaps, mod_q3bsp_optimizedtraceline, mod_q3bsp_sRGBlightmaps, mod_q3bsp_tracelineofsight_brushes, mod_q3shader_default_offsetmapping, mod_q3shader_default_offsetmapping_bias, mod_q3shader_default_offsetmapping_scale, mod_q3shader_default_polygonfactor, mod_q3shader_default_polygonoffset, mod_q3shader_default_refractive_index, mod_q3shader_force_addalpha, mod_q3shader_force_terrain_alphaflag, mod_recalculatenodeboxes, texture_t::name, Q3SURFACEFLAG_NODLIGHT, Q3SURFACEFLAG_NOIMPACT, Q3SURFACEFLAG_NOLIGHTMAP, Q3SURFACEFLAG_NOMARKS, Q3SURFACEFLAG_SKY, r_nosurftextures, r_novis, r_subdivisions_maxtess, r_subdivisions_maxvertices, r_subdivisions_mintess, r_subdivisions_tolerance, r_trippy, texture_t::supercontents, SUPERCONTENTS_LAVA, SUPERCONTENTS_NODROP, SUPERCONTENTS_SKY, SUPERCONTENTS_SLIME, SUPERCONTENTS_SOLID, SUPERCONTENTS_WATER, and texture_t::surfaceflags.

Referenced by Mod_Init().

◆ Mod_BSP2_Load()

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

Definition at line 3889 of file model_brush.c.

3890{
3891 mod->brush.isbsp2 = true;
3892 mod->modeldatatypestring = "Q1BSP2";
3893 Mod_Q1BSP_Load(mod, buffer, bufferend);
3894}

References buffer, mod(), and Mod_Q1BSP_Load().

◆ 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}
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)
model_t * loadmodel
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 integer
Definition cvar.h:73
struct mempool_s * mempool
char name[MAX_QPATH]
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_BuildNormals()

void Mod_BuildNormals ( int firstvertex,
int numvertices,
int numtriangles,
const float * vertex3f,
const int * elements,
float * normal3f,
qbool areaweighting )

Definition at line 806 of file model_shared.c.

807{
808 int i, j;
809 const int *element;
810 float *vectorNormal;
811 float areaNormal[3];
812 // clear the vectors
813 memset(normal3f + 3 * firstvertex, 0, numvertices * sizeof(float[3]));
814 // process each vertex of each triangle and accumulate the results
815 // use area-averaging, to make triangles with a big area have a bigger
816 // weighting on the vertex normal than triangles with a small area
817 // to do so, just add the 'normals' together (the bigger the area
818 // the greater the length of the normal is
819 element = elements;
820 for (i = 0; i < numtriangles; i++, element += 3)
821 {
823 vertex3f + element[0] * 3,
824 vertex3f + element[1] * 3,
825 vertex3f + element[2] * 3,
826 areaNormal
827 );
828
829 if (!areaweighting)
830 VectorNormalize(areaNormal);
831
832 for (j = 0;j < 3;j++)
833 {
834 vectorNormal = normal3f + element[j] * 3;
835 vectorNormal[0] += areaNormal[0];
836 vectorNormal[1] += areaNormal[1];
837 vectorNormal[2] += areaNormal[2];
838 }
839 }
840 // and just normalize the accumulated vertex normal in the end
841 vectorNormal = normal3f + 3 * firstvertex;
842 for (i = 0; i < numvertices; i++, vectorNormal += 3)
843 VectorNormalize(vectorNormal);
844}
#define VectorNormalize(v)
Definition mathlib.h:104
#define TriangleNormal(a, b, c, n)
Definition mathlib.h:126

References i, TriangleNormal, and VectorNormalize.

Referenced by Mod_INTERQUAKEMODEL_Load(), Mod_OBJ_Load(), Mod_PSKMODEL_Load(), Mod_Q1BSP_LoadFaces(), Mod_VBSP_LoadFaces(), Mod_ZYMOTICMODEL_Load(), RSurf_ActiveCustomEntity(), RSurf_PrepareVerticesForBatch(), and VM_CL_R_PolygonEnd().

◆ Mod_BuildTextureVectorsFromNormals()

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 )

Definition at line 893 of file model_shared.c.

894{
895 int i, tnum;
896 float sdir[3], tdir[3], normal[3], *svec, *tvec;
897 const float *v0, *v1, *v2, *tc0, *tc1, *tc2, *n;
898 float f, tangentcross[3], v10[3], v20[3], tc10[2], tc20[2];
899 const int *e;
900 // clear the vectors
901 memset(svector3f + 3 * firstvertex, 0, numvertices * sizeof(float[3]));
902 memset(tvector3f + 3 * firstvertex, 0, numvertices * sizeof(float[3]));
903 // process each vertex of each triangle and accumulate the results
904 for (tnum = 0, e = elements;tnum < numtriangles;tnum++, e += 3)
905 {
906 v0 = vertex3f + e[0] * 3;
907 v1 = vertex3f + e[1] * 3;
908 v2 = vertex3f + e[2] * 3;
909 tc0 = texcoord2f + e[0] * 2;
910 tc1 = texcoord2f + e[1] * 2;
911 tc2 = texcoord2f + e[2] * 2;
912
913 // 79 add/sub/negate/multiply (1 cycle), 1 compare (3 cycle?), total cycles not counting load/store/exchange roughly 82 cycles
914 // 6 add, 28 subtract, 39 multiply, 1 compare, 50% chance of 6 negates
915
916 // calculate the edge directions and surface normal
917 // 6 multiply, 9 subtract
918 VectorSubtract(v1, v0, v10);
919 VectorSubtract(v2, v0, v20);
920 normal[0] = v20[1] * v10[2] - v20[2] * v10[1];
921 normal[1] = v20[2] * v10[0] - v20[0] * v10[2];
922 normal[2] = v20[0] * v10[1] - v20[1] * v10[0];
923
924 // calculate the tangents
925 // 12 multiply, 10 subtract
926 tc10[1] = tc1[1] - tc0[1];
927 tc20[1] = tc2[1] - tc0[1];
928 sdir[0] = tc10[1] * v20[0] - tc20[1] * v10[0];
929 sdir[1] = tc10[1] * v20[1] - tc20[1] * v10[1];
930 sdir[2] = tc10[1] * v20[2] - tc20[1] * v10[2];
931 tc10[0] = tc1[0] - tc0[0];
932 tc20[0] = tc2[0] - tc0[0];
933 tdir[0] = tc10[0] * v20[0] - tc20[0] * v10[0];
934 tdir[1] = tc10[0] * v20[1] - tc20[0] * v10[1];
935 tdir[2] = tc10[0] * v20[2] - tc20[0] * v10[2];
936
937 // if texture is mapped the wrong way (counterclockwise), the tangents
938 // have to be flipped, this is detected by calculating a normal from the
939 // two tangents, and seeing if it is opposite the surface normal
940 // 9 multiply, 2 add, 3 subtract, 1 compare, 50% chance of: 6 negates
941 CrossProduct(tdir, sdir, tangentcross);
942 if (DotProduct(tangentcross, normal) < 0)
943 {
944 VectorNegate(sdir, sdir);
945 VectorNegate(tdir, tdir);
946 }
947
948 if (!areaweighting)
949 {
950 VectorNormalize(sdir);
951 VectorNormalize(tdir);
952 }
953 for (i = 0;i < 3;i++)
954 {
955 VectorAdd(svector3f + e[i]*3, sdir, svector3f + e[i]*3);
956 VectorAdd(tvector3f + e[i]*3, tdir, tvector3f + e[i]*3);
957 }
958 }
959 // make the tangents completely perpendicular to the surface normal, and
960 // then normalize them
961 // 16 assignments, 2 divide, 2 sqrt, 2 negates, 14 adds, 24 multiplies
962 for (i = 0, svec = svector3f + 3 * firstvertex, tvec = tvector3f + 3 * firstvertex, n = normal3f + 3 * firstvertex;i < numvertices;i++, svec += 3, tvec += 3, n += 3)
963 {
964 f = -DotProduct(svec, n);
965 VectorMA(svec, f, n, svec);
966 VectorNormalize(svec);
967 f = -DotProduct(tvec, n);
968 VectorMA(tvec, f, n, tvec);
969 VectorNormalize(tvec);
970 }
971}
#define n(x, y)
GLfloat GLfloat GLfloat v2
Definition glquake.h:747
GLfloat v0
Definition glquake.h:739
GLfloat GLfloat v1
Definition glquake.h:743
#define VectorNegate(a, b)
Definition mathlib.h:95
#define VectorSubtract(a, b, out)
Definition mathlib.h:99
#define CrossProduct(a, b, out)
Definition mathlib.h:103
#define DotProduct(a, b)
Definition mathlib.h:98
#define VectorAdd(a, b, out)
Definition mathlib.h:100
#define VectorMA(a, scale, b, out)
Definition mathlib.h:114
float f
vec3 normal

References CrossProduct, DotProduct, f, i, n, normal, v0, v1, v2, VectorAdd, VectorMA, VectorNegate, VectorNormalize, and VectorSubtract.

Referenced by Mod_Alias_MorphMesh_CompileFrames(), Mod_DARKPLACESMODEL_Load(), Mod_INTERQUAKEMODEL_Load(), Mod_Mesh_Finalize(), Mod_OBJ_Load(), Mod_PSKMODEL_Load(), Mod_Q1BSP_LoadFaces(), Mod_Q3BSP_LoadFaces(), Mod_VBSP_LoadFaces(), Mod_ZYMOTICMODEL_Load(), RSurf_ActiveCustomEntity(), and RSurf_PrepareVerticesForBatch().

◆ Mod_BuildVBOs()

void Mod_BuildVBOs ( void )

Definition at line 2964 of file model_shared.c.

2965{
2966 if(cls.state == ca_dedicated)
2967 return;
2968
2970 return;
2971
2973 {
2974 int i;
2975 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2976 {
2978 {
2979 Con_Printf(CON_WARN "Mod_BuildVBOs: element %u is incorrect (%u should be %u)\n", i, loadmodel->surfmesh.data_element3s[i], loadmodel->surfmesh.data_element3i[i]);
2981 }
2982 }
2983 }
2984
2985 // upload short indices as a buffer
2988
2989 // upload int indices as a buffer
2992
2993 // only build a vbo if one has not already been created (this is important for brush models which load specially)
2994 // we put several vertex data streams in the same buffer
2996 {
2997 int size;
2998 unsigned char *mem;
2999 size = 0;
3009 mem = (unsigned char *)Mem_Alloc(tempmempool, size);
3028 Mem_Free(mem);
3029 }
3030}
client_static_t cls
Definition cl_main.c:116
@ ca_dedicated
Definition client.h:530
#define CON_WARN
Definition console.h:101
vector size
r_meshbuffer_t * R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qbool isindexbuffer, qbool isuniformbuffer, qbool isdynamic, qbool isindex16)
cvar_t gl_paranoid
Definition gl_backend.c:8
#define NULL
Definition qtypes.h:12
cactive_t state
Definition client.h:568
surfmesh_t surfmesh
r_meshbuffer_t * data_svector3f_vertexbuffer
int data_normal3f_bufferoffset
int data_skeletalweight4ub_bufferoffset
r_meshbuffer_t * data_lightmapcolor4f_vertexbuffer
r_meshbuffer_t * data_normal3f_vertexbuffer
int data_texcoordlightmap2f_bufferoffset
int data_skeletalindex4ub_bufferoffset
int data_svector3f_bufferoffset
float * data_lightmapcolor4f
unsigned char * data_skeletalweight4ub
float * data_svector3f
unsigned char * data_skeletalindex4ub
int * data_element3i
unsigned short * data_element3s
r_meshbuffer_t * data_texcoordtexture2f_vertexbuffer
r_meshbuffer_t * data_skeletalindex4ub_vertexbuffer
float * data_vertex3f
r_meshbuffer_t * data_tvector3f_vertexbuffer
r_meshbuffer_t * data_element3i_indexbuffer
float * data_tvector3f
int data_texcoordtexture2f_bufferoffset
int num_triangles
int data_tvector3f_bufferoffset
r_meshbuffer_t * data_texcoordlightmap2f_vertexbuffer
r_meshbuffer_t * data_skeletalweight4ub_vertexbuffer
int data_vertex3f_bufferoffset
int data_lightmapcolor4f_bufferoffset
float * data_texcoordtexture2f
r_meshbuffer_t * data_element3s_indexbuffer
float * data_normal3f
float * data_texcoordlightmap2f
r_meshbuffer_t * data_vertex3f_vertexbuffer
mempool_t * tempmempool
Definition zone.c:794
#define Mem_Alloc(pool, size)
Definition zone.h:92

References ca_dedicated, cls, Con_Printf(), CON_WARN, surfmesh_t::data_element3i, surfmesh_t::data_element3i_indexbuffer, surfmesh_t::data_element3s, surfmesh_t::data_element3s_indexbuffer, surfmesh_t::data_lightmapcolor4f, surfmesh_t::data_lightmapcolor4f_bufferoffset, surfmesh_t::data_lightmapcolor4f_vertexbuffer, surfmesh_t::data_normal3f, surfmesh_t::data_normal3f_bufferoffset, surfmesh_t::data_normal3f_vertexbuffer, surfmesh_t::data_skeletalindex4ub, surfmesh_t::data_skeletalindex4ub_bufferoffset, surfmesh_t::data_skeletalindex4ub_vertexbuffer, surfmesh_t::data_skeletalweight4ub, surfmesh_t::data_skeletalweight4ub_bufferoffset, surfmesh_t::data_skeletalweight4ub_vertexbuffer, surfmesh_t::data_svector3f, surfmesh_t::data_svector3f_bufferoffset, surfmesh_t::data_svector3f_vertexbuffer, surfmesh_t::data_texcoordlightmap2f, surfmesh_t::data_texcoordlightmap2f_bufferoffset, surfmesh_t::data_texcoordlightmap2f_vertexbuffer, surfmesh_t::data_texcoordtexture2f, surfmesh_t::data_texcoordtexture2f_bufferoffset, surfmesh_t::data_texcoordtexture2f_vertexbuffer, surfmesh_t::data_tvector3f, surfmesh_t::data_tvector3f_bufferoffset, surfmesh_t::data_tvector3f_vertexbuffer, surfmesh_t::data_vertex3f, surfmesh_t::data_vertex3f_bufferoffset, surfmesh_t::data_vertex3f_vertexbuffer, gl_paranoid, i, cvar_t::integer, loadmodel, Mem_Alloc, Mem_Free, model_t::name, NULL, surfmesh_t::num_triangles, surfmesh_t::num_vertices, R_Mesh_CreateMeshBuffer(), size, client_static_t::state, model_t::surfmesh, and tempmempool.

Referenced by Mod_LoadModel(), Mod_OBJ_Load(), Mod_Q1BSP_Load(), Mod_Q2BSP_Load(), and Mod_Q3BSP_Load().

◆ Mod_BuildVertexRemapTableFromElements()

int Mod_BuildVertexRemapTableFromElements ( int numelements,
const int * elements,
int numvertices,
int * remapvertices )

Definition at line 724 of file model_shared.c.

725{
726 int i, count;
727 unsigned char *used;
728 used = (unsigned char *)Mem_Alloc(tempmempool, numvertices);
729 memset(used, 0, numvertices);
730 for (i = 0;i < numelements;i++)
731 used[elements[i]] = 1;
732 for (i = 0, count = 0;i < numvertices;i++)
733 remapvertices[i] = used[i] ? count++ : -1;
734 Mem_Free(used);
735 return count;
736}
GLenum GLenum GLsizei count
Definition glquake.h:656

References count, i, Mem_Alloc, Mem_Free, and tempmempool.

◆ Mod_ClearUsed()

void Mod_ClearUsed ( void )

Definition at line 564 of file model_shared.c.

565{
566 int i;
567 int nummodels = (int)Mem_ExpandableArray_IndexRange(&models);
568 model_t *mod;
569 for (i = 0;i < nummodels;i++)
570 if ((mod = (model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0])
571 mod->used = false;
572}
static int(ZEXPORT *qz_inflate)(z_stream *strm
static memexpandablearray_t models
size_t Mem_ExpandableArray_IndexRange(const memexpandablearray_t *l)
Definition zone.c:763
void * Mem_ExpandableArray_RecordAtIndex(const memexpandablearray_t *l, size_t index)
Definition zone.c:780

References i, int(), Mem_ExpandableArray_IndexRange(), Mem_ExpandableArray_RecordAtIndex(), mod(), and models.

Referenced by CL_ParseServerInfo(), QW_CL_RequestNextDownload(), and SV_SpawnServer().

◆ Mod_CollisionBIH_PointSuperContents()

int Mod_CollisionBIH_PointSuperContents ( struct model_s * model,
int frame,
const vec3_t point )

Definition at line 7348 of file model_brush.c.

7349{
7350 trace_t trace;
7351 Mod_CollisionBIH_TracePoint(model, NULL, NULL, &trace, point, 0, 0, 0);
7352 return trace.startsupercontents;
7353}
void Mod_CollisionBIH_TracePoint(model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
int startsupercontents
Definition collision.h:56

References Mod_CollisionBIH_TracePoint(), model, NULL, and trace_t::startsupercontents.

Referenced by Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), and Mod_VBSP_Load().

◆ Mod_CollisionBIH_PointSuperContents_Mesh()

int Mod_CollisionBIH_PointSuperContents_Mesh ( struct model_s * model,
int frame,
const vec3_t point )

Definition at line 7387 of file model_brush.c.

7388{
7389#if 0
7390 // broken - needs to be modified to count front faces and backfaces to figure out if it is in solid
7391 trace_t trace;
7392 vec3_t end;
7393 VectorSet(end, start[0], start[1], model->normalmins[2]);
7394 memset(&trace, 0, sizeof(trace));
7395 trace.fraction = 1;
7396 trace.hitsupercontentsmask = hitsupercontentsmask;
7397 trace.skipsupercontentsmask = skipsupercontentsmask;
7398 trace.skipmaterialflagsmask = skipmaterialflagsmask;
7399 Mod_CollisionBIH_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
7400 return trace.hitsupercontents;
7401#else
7402 return 0;
7403#endif
7404}
#define VectorSet(vec, x, y, z)
Definition mathlib.h:96
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)
vec_t vec3_t[3]
Definition qtypes.h:71
int hitsupercontentsmask
Definition collision.h:50
double fraction
Definition collision.h:40
int skipsupercontentsmask
Definition collision.h:52
int hitsupercontents
Definition collision.h:58
int skipmaterialflagsmask
Definition collision.h:54

References trace_t::fraction, trace_t::hitsupercontents, trace_t::hitsupercontentsmask, Mod_CollisionBIH_TraceLine(), model, trace_t::skipmaterialflagsmask, trace_t::skipsupercontentsmask, and VectorSet.

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_CollisionBIH_TraceBox()

void Mod_CollisionBIH_TraceBox ( model_t * 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 )

◆ Mod_CollisionBIH_TraceBrush()

void Mod_CollisionBIH_TraceBrush ( model_t * 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 )

◆ Mod_CollisionBIH_TraceLine()

void Mod_CollisionBIH_TraceLine ( model_t * 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 )

◆ Mod_CollisionBIH_TraceLineOfSight()

qbool Mod_CollisionBIH_TraceLineOfSight ( struct model_s * model,
const vec3_t start,
const vec3_t end,
const vec3_t acceptmins,
const vec3_t acceptmaxs )

Definition at line 7355 of file model_brush.c.

7356{
7357 trace_t trace;
7359 return trace.fraction == 1 || BoxesOverlap(trace.endpos, trace.endpos, acceptmins, acceptmaxs);
7360}
#define SUPERCONTENTS_VISBLOCKERMASK
Definition bspfile.h:219
#define BoxesOverlap(a, b, c, d)
Definition mathlib.h:122
#define MATERIALFLAGMASK_TRANSLUCENT
double endpos[3]
Definition collision.h:42

References BoxesOverlap, trace_t::endpos, trace_t::fraction, MATERIALFLAGMASK_TRANSLUCENT, Mod_CollisionBIH_TraceLine(), model, NULL, and SUPERCONTENTS_VISBLOCKERMASK.

◆ Mod_CollisionBIH_TracePoint()

void Mod_CollisionBIH_TracePoint ( model_t * 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 )

◆ Mod_CollisionBIH_TracePoint_Mesh()

void Mod_CollisionBIH_TracePoint_Mesh ( model_t * 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 )

◆ Mod_CountSkinFiles()

int Mod_CountSkinFiles ( skinfile_t * skinfile)

Definition at line 2826 of file model_shared.c.

2827{
2828 int i;
2829 for (i = 0;skinfile;skinfile = skinfile->next, i++);
2830 return i;
2831}

References i, and skinfile_t::next.

◆ Mod_CreateCollisionMesh()

void Mod_CreateCollisionMesh ( model_t * mod)

Definition at line 1196 of file model_shared.c.

1197{
1198 int k, numcollisionmeshtriangles;
1199 qbool usesinglecollisionmesh = false;
1200 const msurface_t *surface = NULL;
1201
1202 mempool_t *mempool = mod->mempool;
1203 if (!mempool && mod->brush.parentmodel)
1204 mempool = mod->brush.parentmodel->mempool;
1205 // make a single combined collision mesh for physics engine use
1206 // TODO rewrite this to use the collision brushes as source, to fix issues with e.g. common/caulk which creates no drawsurface
1207 numcollisionmeshtriangles = 0;
1208 for (k = mod->submodelsurfaces_start;k < mod->submodelsurfaces_end;k++)
1209 {
1210 surface = mod->data_surfaces + k;
1211 if (!strcmp(surface->texture->name, "collision") || !strcmp(surface->texture->name, "collisionconvex")) // found collision mesh
1212 {
1213 usesinglecollisionmesh = true;
1214 numcollisionmeshtriangles = surface->num_triangles;
1215 break;
1216 }
1217 if (!(surface->texture->supercontents & SUPERCONTENTS_SOLID))
1218 continue;
1219 numcollisionmeshtriangles += surface->num_triangles;
1220 }
1221 mod->brush.collisionmesh = Mod_ShadowMesh_Begin(mempool, numcollisionmeshtriangles * 3, numcollisionmeshtriangles);
1222 if (usesinglecollisionmesh)
1223 Mod_ShadowMesh_AddMesh(mod->brush.collisionmesh, mod->surfmesh.data_vertex3f, surface->num_triangles, (mod->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
1224 else
1225 {
1226 for (k = mod->submodelsurfaces_start; k < mod->submodelsurfaces_end; k++)
1227 {
1228 surface = mod->data_surfaces + k;
1229 if (!(surface->texture->supercontents & SUPERCONTENTS_SOLID))
1230 continue;
1231 Mod_ShadowMesh_AddMesh(mod->brush.collisionmesh, mod->surfmesh.data_vertex3f, surface->num_triangles, (mod->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
1232 }
1233 }
1234 mod->brush.collisionmesh = Mod_ShadowMesh_Finish(mod->brush.collisionmesh, false);
1235}
shadowmesh_t * Mod_ShadowMesh_Finish(shadowmesh_t *mesh, qbool createvbo)
void Mod_ShadowMesh_AddMesh(shadowmesh_t *mesh, const float *vertex3f, int numtris, const int *element3i)
shadowmesh_t * Mod_ShadowMesh_Begin(mempool_t *mempool, int maxverts, int maxtriangles)
bool qbool
Definition qtypes.h:9
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

References mod(), Mod_ShadowMesh_AddMesh(), Mod_ShadowMesh_Begin(), Mod_ShadowMesh_Finish(), texture_t::name, NULL, msurface_t::num_firsttriangle, msurface_t::num_triangles, texture_t::supercontents, SUPERCONTENTS_SOLID, and msurface_t::texture.

◆ Mod_CreateShaderPass()

texture_shaderpass_t * Mod_CreateShaderPass ( struct mempool_s * mempool,
struct skinframe_s * skinframe )

◆ Mod_CreateShaderPassFromQ3ShaderLayer()

texture_shaderpass_t * Mod_CreateShaderPassFromQ3ShaderLayer ( struct mempool_s * mempool,
const char * modelname,
q3shaderinfo_layer_t * layer,
int layerindex,
int texflags,
const char * texturename )

◆ 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
cvar_t r_smoothnormals_areaweighting
Definition gl_rmain.c:229
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
GLsizeiptr const GLvoid * data
Definition glquake.h:639
void Host_Error(const char *error,...)
Definition host.c:85
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 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)
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_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)
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)
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]
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)
void(* DrawDepth)(struct entity_render_s *ent)
modtype_t type
float * data_baseboneposeinverse
int(* PointSuperContents)(struct model_s *model, int frame, const vec3_t point)
vec3_t rotatedmins
vec3_t yawmaxs
int * modelsurfaces_sorted
surface indices of model in an optimal draw order (submodelindex -> texture -> lightmap -> index)
bih_t collision_bih
int submodelsurfaces_end
vec3_t rotatedmaxs
msurface_t * data_surfaces
float num_posescale
void(* Draw)(struct entity_render_s *ent)
float radius
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)
vec3_t normalmaxs
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)
int num_poses
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)
vec3_t yawmins
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)
vec3_t normalmins
int num_textures
const char * modeldatatypestring
texture_t * data_textures
aliasbone_t * data_bones
animscene_t * skinscenes
short * data_poses7s
void(* DrawLight)(struct entity_render_s *ent, int numsurfaces, const int *surfacelist, const unsigned char *trispvs)
int num_texturesperskin
int num_bones
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)
int num_firstvertex
qbool isanimated
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_FindName()

model_t * Mod_FindName ( const char * name,
const char * parentname )

Definition at line 595 of file model_shared.c.

596{
597 int i;
598 int nummodels;
599 model_t *mod;
600
601 if (!parentname)
602 parentname = "";
603
605
606 if (!name[0])
607 Host_Error ("Mod_ForName: empty name");
608
609 // search the currently loaded models
610 for (i = 0;i < nummodels;i++)
611 {
612 if ((mod = (model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && !strcmp(mod->name, name) && ((!mod->brush.parentmodel && !parentname[0]) || (mod->brush.parentmodel && parentname[0] && !strcmp(mod->brush.parentmodel->name, parentname))))
613 {
614 mod->used = true;
615 return mod;
616 }
617 }
618
619 // no match found, create a new one
621 dp_strlcpy(mod->name, name, sizeof(mod->name));
622 if (parentname[0])
623 mod->brush.parentmodel = Mod_FindName(parentname, NULL);
624 else
625 mod->brush.parentmodel = NULL;
626 mod->loaded = false;
627 mod->used = true;
628 return mod;
629}
const GLchar * name
Definition glquake.h:601
model_t * Mod_FindName(const char *name, const char *parentname)
void * Mem_ExpandableArray_AllocRecord(memexpandablearray_t *l)
Definition zone.c:695

References dp_strlcpy, Host_Error(), i, int(), Mem_ExpandableArray_AllocRecord(), Mem_ExpandableArray_IndexRange(), Mem_ExpandableArray_RecordAtIndex(), mod(), Mod_FindName(), models, name, and NULL.

Referenced by CL_ParseServerInfo(), Mod_FindName(), Mod_ForName(), Mod_OBJ_Load(), Mod_Q1BSP_Load(), Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), QW_CL_RequestNextDownload(), SV_ModelIndex(), and VM_CL_effect().

◆ Mod_ForName()

model_t * Mod_ForName ( const char * name,
qbool crash,
qbool checkdisk,
const char * parentname )

Definition at line 640 of file model_shared.c.

641{
642 model_t *model;
643
644 // FIXME: So we don't crash if a server is started early.
645 if(!vid_opened)
647
648 model = Mod_FindName(name, parentname);
649 if (!model->loaded || checkdisk)
650 Mod_LoadModel(model, crash, checkdisk);
651 return model;
652}
void CL_StartVideo(void)
Definition cl_main.c:2786
void crash(void)
qbool vid_opened
Definition cl_main.c:2785
model_t * Mod_LoadModel(model_t *mod, qbool crash, qbool checkdisk)

References CL_StartVideo(), crash(), Mod_FindName(), Mod_LoadModel(), model, name, and vid_opened.

Referenced by CL_BeginDownloads(), CL_ParseServerInfo(), CL_ParseServerMessage(), CL_ParseTempEntity(), Mod_Decompile_f(), Mod_Precache_f(), QW_CL_RequestNextDownload(), SV_Loadgame_f(), SV_ModelIndex(), SV_SpawnServer(), SV_Viewmodel_f(), and VM_CL_precache_model().

◆ Mod_FreeQ3Shaders()

void Mod_FreeQ3Shaders ( void )

Definition at line 1403 of file model_shared.c.

1404{
1406}
static mempool_t * q3shaders_mem
#define Mem_FreePool(pool)
Definition zone.h:105

References Mem_FreePool, and q3shaders_mem.

Referenced by CL_BeginDownloads(), CL_SignonReply(), Mod_LoadQ3Shaders(), mod_shutdown(), and SV_SpawnServer().

◆ Mod_FreeSkinFiles()

void Mod_FreeSkinFiles ( skinfile_t * skinfile)

Definition at line 2810 of file model_shared.c.

2811{
2812 skinfile_t *next;
2813 skinfileitem_t *skinfileitem, *nextitem;
2814 for (;skinfile;skinfile = next)
2815 {
2816 next = skinfile->next;
2817 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = nextitem)
2818 {
2819 nextitem = skinfileitem->next;
2820 Mem_Free(skinfileitem);
2821 }
2822 Mem_Free(skinfile);
2823 }
2824}

References skinfile_t::items, Mem_Free, skinfile_t::next, and skinfileitem_t::next.

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_HLBSP_Load()

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

Definition at line 3896 of file model_brush.c.

3897{
3898 mod->brush.ishlbsp = true;
3899 mod->modeldatatypestring = "HLBSP";
3900 Mod_Q1BSP_Load(mod, buffer, bufferend);
3901}

References buffer, mod(), and Mod_Q1BSP_Load().

◆ Mod_IBSP_Load()

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

Definition at line 7876 of file model_brush.c.

7877{
7878 int i = LittleLong(((int *)buffer)[1]);
7880 Mod_Q3BSP_Load(mod,buffer, bufferend);
7881 else if (i == Q2BSPVERSION)
7882 Mod_Q2BSP_Load(mod,buffer, bufferend);
7883 else
7884 Host_Error("Mod_IBSP_Load: unknown/unsupported version %i", i);
7885}
#define LittleLong(l)
Definition common.h:92
static void Mod_Q2BSP_Load(model_t *mod, void *buffer, void *bufferend)
static void Mod_Q3BSP_Load(model_t *mod, void *buffer, void *bufferend)
#define Q2BSPVERSION
Definition model_q2bsp.h:7
#define Q3BSPVERSION_IG
Definition model_q3bsp.h:13
#define Q3BSPVERSION_LIVE
Definition model_q3bsp.h:12
#define Q3BSPVERSION
Definition model_q3bsp.h:11

References buffer, Host_Error(), i, LittleLong, mod(), Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), Q2BSPVERSION, Q3BSPVERSION, Q3BSPVERSION_IG, and Q3BSPVERSION_LIVE.

◆ 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 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
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)
@ 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
int num_morphframes
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
const GLdouble * v
Definition glquake.h:762
#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_IDS2_Load()

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

Definition at line 378 of file model_sprite.c.

379{
380 int i, version;
381 qbool fullbright;
382 const dsprite2_t *pinqsprite;
383 skinframe_t *skinframe;
384 float modelradius;
386
388
390
394
395 pinqsprite = (dsprite2_t *)buffer;
396
397 version = LittleLong(pinqsprite->version);
399 Host_Error("Mod_IDS2_Load: %s has wrong version number (%i should be 2 (quake 2)", loadmodel->name, version);
400
401 loadmodel->numframes = LittleLong (pinqsprite->numframes);
402 if (loadmodel->numframes < 1)
403 Host_Error ("Mod_IDS2_Load: Invalid # of frames: %d", loadmodel->numframes);
406
407 // LadyHavoc: hack to allow sprites to be non-fullbright
408 fullbright = true;
409 for (i = 0;i < MAX_QPATH && loadmodel->name[i];i++)
410 if (loadmodel->name[i] == '!')
411 fullbright = false;
412
418
419 modelradius = 0;
420 for (i = 0;i < loadmodel->numframes;i++)
421 {
422 int origin[2], x, y, width, height;
423 const dsprite2frame_t *pinframe;
424 mspriteframe_t *sprframe;
425
426 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "frame %i", i);
430 loadmodel->animscenes[i].loop = true;
431
432 pinframe = &pinqsprite->frames[i];
433
434 origin[0] = LittleLong (pinframe->origin_x);
435 origin[1] = LittleLong (pinframe->origin_y);
436 width = LittleLong (pinframe->width);
437 height = LittleLong (pinframe->height);
438
439 sprframe = &loadmodel->sprite.sprdata_frames[i];
440
441 // note that sp2 origin[0] is positive, where as it is negative in
442 // spr/spr32/hlspr
443 sprframe->left = -origin[0];
444 sprframe->right = -origin[0] + width;
445 sprframe->up = origin[1];
446 sprframe->down = origin[1] - height;
447
448 x = (int)max(sprframe->left * sprframe->left, sprframe->right * sprframe->right);
449 y = (int)max(sprframe->up * sprframe->up, sprframe->down * sprframe->down);
450 if (modelradius < x + y)
451 modelradius = x + y;
452 }
453
454 if (cls.state != ca_dedicated)
455 {
456 for (i = 0;i < loadmodel->numframes;i++)
457 {
458 const dsprite2frame_t *pinframe;
459 pinframe = &pinqsprite->frames[i];
460 if (!(skinframe = R_SkinFrame_LoadExternal(pinframe->name, texflags, false, false)))
461 {
462 Con_Printf(CON_ERROR "Mod_IDS2_Load: failed to load %s", pinframe->name);
463 skinframe = R_SkinFrame_LoadMissing();
464 }
465 Mod_SpriteSetupTexture(&loadmodel->data_textures[i], skinframe, fullbright, false);
466 }
467 }
468
469 modelradius = sqrt(modelradius);
470 for (i = 0;i < 3;i++)
471 {
472 loadmodel->normalmins[i] = loadmodel->yawmins[i] = loadmodel->rotatedmins[i] = -modelradius;
474 }
475 loadmodel->radius = modelradius;
476 loadmodel->radius2 = modelradius * modelradius;
477
478 // TODO: Note that isanimated only means whether vertices change due to
479 // the animation. This may happen due to sprframe parameters changing.
480 // Mere texture chanegs OTOH shouldn't require isanimated to be 1.
482}
#define CON_ERROR
Definition console.h:102
vector origin
GLint GLenum GLint x
Definition glquake.h:651
float sqrt(float f)
cvar_t r_mipsprites
static void Mod_SpriteSetupTexture(texture_t *texture, skinframe_t *skinframe, qbool fullbright, qbool additive)
void R_Model_Sprite_Draw(entity_render_t *ent)
Definition r_sprites.c:430
#define TEXF_ISSPRITE
Definition r_textures.h:35
#define TEXF_CLAMP
Definition r_textures.h:15
#define SPR_VP_PARALLEL
Definition spritegn.h:98
#define SPRITE2_VERSION
Definition spritegn.h:52
dsprite2frame_t frames[1]
Definition spritegn.h:93
int version
Definition spritegn.h:91
int numframes
Definition spritegn.h:92
char name[64]
Definition spritegn.h:85
mspriteframe_t * sprdata_frames
model_sprite_t sprite

References model_t::animscenes, buffer, ca_dedicated, cls, CON_ERROR, Con_Printf(), model_t::data_textures, mspriteframe_t::down, dpsnprintf(), model_t::Draw, model_t::DrawDepth, model_t::DrawLight, animscene_t::firstframe, animscene_t::framecount, animscene_t::framerate, dsprite2_t::frames, dsprite2frame_t::height, height, Host_Error(), i, int(), cvar_t::integer, surfmesh_t::isanimated, mspriteframe_t::left, LittleLong, loadmodel, animscene_t::loop, max, MAX_QPATH, Mem_Alloc, model_t::mempool, mod_sprite, Mod_SpriteSetupTexture(), model_t::modeldatatypestring, animscene_t::name, dsprite2frame_t::name, model_t::name, model_t::normalmaxs, model_t::normalmins, NULL, model_t::num_textures, model_t::num_texturesperskin, dsprite2_t::numframes, model_t::numframes, origin, dsprite2frame_t::origin_x, dsprite2frame_t::origin_y, r_mipsprites, R_Model_Sprite_Draw(), R_SkinFrame_LoadExternal(), R_SkinFrame_LoadMissing(), model_t::radius, model_t::radius2, mspriteframe_t::right, model_t::rotatedmaxs, model_t::rotatedmins, SPR_VP_PARALLEL, model_sprite_t::sprdata_frames, model_t::sprite, SPRITE2_VERSION, model_sprite_t::sprnum_type, sqrt(), ST_SYNC, client_static_t::state, model_t::surfmesh, model_t::synctype, TEXF_ALPHA, TEXF_CLAMP, TEXF_COMPRESS, TEXF_ISSPRITE, TEXF_MIPMAP, TEXF_PICMIP, model_t::type, mspriteframe_t::up, dsprite2_t::version, version, dsprite2frame_t::width, width, x, y, model_t::yawmaxs, and model_t::yawmins.

◆ Mod_IDSP_Load()

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

Definition at line 267 of file model_sprite.c.

268{
269 int version;
270 const unsigned char *datapointer;
271
272 datapointer = (unsigned char *)buffer;
273
275
277
281
284 {
285 dsprite_t *pinqsprite;
286
287 pinqsprite = (dsprite_t *)datapointer;
288 datapointer += sizeof(dsprite_t);
289
290 loadmodel->numframes = LittleLong (pinqsprite->numframes);
291 loadmodel->sprite.sprnum_type = LittleLong (pinqsprite->type);
293
294 Mod_Sprite_SharedSetup(datapointer, LittleLong (pinqsprite->version), NULL, false);
295 }
296 else if (version == SPRITEHL_VERSION)
297 {
298 int i, rendermode;
299 unsigned char palette[256][4];
300 const unsigned char *in;
301 dspritehl_t *pinhlsprite;
302
303 pinhlsprite = (dspritehl_t *)datapointer;
304 datapointer += sizeof(dspritehl_t);
305
306 loadmodel->numframes = LittleLong (pinhlsprite->numframes);
307 loadmodel->sprite.sprnum_type = LittleLong (pinhlsprite->type);
309 rendermode = pinhlsprite->rendermode;
310
311 in = datapointer;
312 datapointer += 2;
313 i = in[0] + in[1] * 256;
314 if (i != 256)
315 Host_Error ("Mod_IDSP_Load: unexpected number of palette colors %i (should be 256)", i);
316 in = datapointer;
317 datapointer += 768;
318 switch(rendermode)
319 {
320 case SPRHL_OPAQUE:
321 for (i = 0;i < 256;i++)
322 {
323 palette[i][2] = in[i*3+0];
324 palette[i][1] = in[i*3+1];
325 palette[i][0] = in[i*3+2];
326 palette[i][3] = 255;
327 }
328 break;
329 case SPRHL_ADDITIVE:
330 for (i = 0;i < 256;i++)
331 {
332 palette[i][2] = in[i*3+0];
333 palette[i][1] = in[i*3+1];
334 palette[i][0] = in[i*3+2];
335 palette[i][3] = 255;
336 }
337 // also passes additive == true to Mod_Sprite_SharedSetup
338 break;
339 case SPRHL_INDEXALPHA:
340 for (i = 0;i < 256;i++)
341 {
342 palette[i][2] = in[765];
343 palette[i][1] = in[766];
344 palette[i][0] = in[767];
345 palette[i][3] = i;
346 in += 3;
347 }
348 break;
349 case SPRHL_ALPHATEST:
350 for (i = 0;i < 256;i++)
351 {
352 palette[i][2] = in[i*3+0];
353 palette[i][1] = in[i*3+1];
354 palette[i][0] = in[i*3+2];
355 palette[i][3] = 255;
356 }
357 palette[255][0] = palette[255][1] = palette[255][2] = palette[255][3] = 0;
358 // should this use alpha test or alpha blend? (currently blend)
359 break;
360 default:
361 Host_Error("Mod_IDSP_Load: unknown texFormat (%i, should be 0, 1, 2, or 3)", i);
362 return;
363 }
364
365 Mod_Sprite_SharedSetup(datapointer, LittleLong (pinhlsprite->version), (unsigned int *)(&palette[0][0]), rendermode == SPRHL_ADDITIVE);
366 }
367 else
368 Host_Error("Mod_IDSP_Load: %s has wrong version number (%i). Only %i (quake), %i (HalfLife), and %i (sprite32) supported",
370
371 // TODO: Note that isanimated only means whether vertices change due to
372 // the animation. This may happen due to sprframe parameters changing.
373 // Mere texture chanegs OTOH shouldn't require isanimated to be 1.
375}
static void Mod_Sprite_SharedSetup(const unsigned char *datapointer, int version, const unsigned int *palette, qbool additive)
#define SPRITEHL_VERSION
Definition spritegn.h:49
#define SPRITE32_VERSION
Definition spritegn.h:50
#define SPRHL_ADDITIVE
Definition spritegn.h:106
#define SPRHL_OPAQUE
Definition spritegn.h:105
#define SPRITE_VERSION
Definition spritegn.h:48
#define SPRHL_INDEXALPHA
Definition spritegn.h:107
#define SPRHL_ALPHATEST
Definition spritegn.h:108
int version
Definition spritegn.h:57
int numframes
Definition spritegn.h:62
int synctype
Definition spritegn.h:64
int type
Definition spritegn.h:58
int numframes
Definition spritegn.h:76
int version
Definition spritegn.h:70
int synctype
Definition spritegn.h:78
int rendermode
Definition spritegn.h:72

References model_t::animscenes, buffer, model_t::Draw, model_t::DrawDepth, model_t::DrawLight, animscene_t::framecount, Host_Error(), i, surfmesh_t::isanimated, LittleLong, loadmodel, mod_sprite, Mod_Sprite_SharedSetup(), model_t::modeldatatypestring, model_t::name, NULL, dsprite_t::numframes, dspritehl_t::numframes, model_t::numframes, R_Model_Sprite_Draw(), dspritehl_t::rendermode, SPRHL_ADDITIVE, SPRHL_ALPHATEST, SPRHL_INDEXALPHA, SPRHL_OPAQUE, model_t::sprite, SPRITE32_VERSION, SPRITE_VERSION, SPRITEHL_VERSION, model_sprite_t::sprnum_type, model_t::surfmesh, dsprite_t::synctype, dspritehl_t::synctype, model_t::synctype, dsprite_t::type, dspritehl_t::type, model_t::type, dsprite_t::version, dspritehl_t::version, and version.

◆ Mod_Init()

void Mod_Init ( void )

Definition at line 178 of file model_shared.c.

179{
180 mod_mempool = Mem_AllocPool("modelinfo", 0, NULL);
182
186
192
199
200 Cmd_AddCommand(CF_CLIENT, "modellist", Mod_Print_f, "prints a list of loaded models");
201 Cmd_AddCommand(CF_CLIENT, "modelprecache", Mod_Precache_f, "load a model");
202 Cmd_AddCommand(CF_CLIENT, "modeldecompile", Mod_Decompile_f, "exports a model in several formats for editing purposes");
203 Cmd_AddCommand(CF_CLIENT, "mod_generatelightmaps", Mod_GenerateLightmaps_f, "rebuilds lighting on current worldmodel");
204}
void Cmd_AddCommand(unsigned flags, const char *cmd_name, xcommand_t function, const char *description)
called by the init functions of other parts of the program to register commands and functions to call...
Definition cmd.c:1661
#define CF_CLIENT
cvar/command that only the client can change/execute
Definition cmd.h:48
void Mod_AliasInit(void)
void Mod_BrushInit(void)
Definition model_brush.c:80
static void Mod_Print_f(cmd_state_t *cmd)
cvar_t mod_generatelightmaps_borderpixels
cvar_t mod_generatelightmaps_gridsamples
cvar_t r_mipnormalmaps
cvar_t mod_generatelightmaps_texturesize
static void Mod_GenerateLightmaps_f(cmd_state_t *cmd)
cvar_t mod_generatelightmaps_lightmapradius
static void Mod_Decompile_f(cmd_state_t *cmd)
cvar_t mod_generatelightmaps_vertexsamples
static mempool_t * mod_mempool
cvar_t mod_generatelightmaps_lightmapsamples
cvar_t mod_generatelightmaps_unitspersample
static void Mod_Precache_f(cmd_state_t *cmd)
cvar_t mod_generatelightmaps_vertexradius
cvar_t mod_generatelightmaps_gridradius
void Mod_SpriteInit(void)
void Mem_ExpandableArray_NewArray(memexpandablearray_t *l, mempool_t *mempool, size_t recordsize, int numrecordsperarray)
Definition zone.c:675
#define Mem_AllocPool(name, flags, parent)
Definition zone.h:104

References CF_CLIENT, Cmd_AddCommand(), Cvar_RegisterVariable(), Mem_AllocPool, Mem_ExpandableArray_NewArray(), Mod_AliasInit(), Mod_BrushInit(), Mod_Decompile_f(), mod_generatelightmaps_borderpixels, Mod_GenerateLightmaps_f(), mod_generatelightmaps_gridradius, mod_generatelightmaps_gridsamples, mod_generatelightmaps_lightmapradius, mod_generatelightmaps_lightmapsamples, mod_generatelightmaps_texturesize, mod_generatelightmaps_unitspersample, mod_generatelightmaps_vertexradius, mod_generatelightmaps_vertexsamples, mod_mempool, Mod_Precache_f(), Mod_Print_f(), Mod_SpriteInit(), models, NULL, r_mipnormalmaps, and r_mipskins.

Referenced by Host_Init().

◆ 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
#define Vector4Normalize2(v, dest)
Definition mathlib.h:87
#define VectorClear(a)
Definition mathlib.h:97
#define bound(min, num, max)
Definition mathlib.h:34
#define Vector4Negate(in, out)
Definition mathlib.h:85
#define VectorCopy(in, out)
Definition mathlib.h:101
void Matrix4x4_Concat(matrix4x4_t *out, const matrix4x4_t *in1, const matrix4x4_t *in2)
Definition matrixlib.c:83
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
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

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_LoadCustomMaterial()

void Mod_LoadCustomMaterial ( struct mempool_s * mempool,
texture_t * texture,
const char * name,
int supercontents,
int materialflags,
struct skinframe_s * skinframe )

Sets up a material to render the provided skinframe. See also R_SkinFrame_LoadInternalBGRA.

◆ Mod_LoadModel()

model_t * Mod_LoadModel ( model_t * mod,
qbool crash,
qbool checkdisk )

Definition at line 406 of file model_shared.c.

407{
408 unsigned int crc;
409 void *buf;
410 fs_offset_t filesize = 0;
411 char vabuf[1024];
412
413 mod->used = true;
414
415 if (mod->name[0] == '*') // submodel
416 return mod;
417
418 if (!strcmp(mod->name, "null"))
419 {
420 if(mod->loaded)
421 return mod;
422
423 if (mod->loaded || mod->mempool)
425
427 Con_Printf("loading model %s\n", mod->name);
428
429 mod->used = true;
430 mod->crc = (unsigned int)-1;
431 mod->loaded = false;
432
433 VectorClear(mod->normalmins);
434 VectorClear(mod->normalmaxs);
435 VectorClear(mod->yawmins);
436 VectorClear(mod->yawmaxs);
437 VectorClear(mod->rotatedmins);
438 VectorClear(mod->rotatedmaxs);
439
440 mod->modeldatatypestring = "null";
441 mod->type = mod_null;
442 mod->Draw = R_Model_Null_Draw;
443 mod->numframes = 2;
444 mod->numskins = 1;
445
446 // no fatal errors occurred, so this model is ready to use.
447 mod->loaded = true;
448
449 return mod;
450 }
451
452 crc = 0;
453 buf = NULL;
454
455 // even if the model is loaded it still may need reloading...
456
457 // if it is not loaded or checkdisk is true we need to calculate the crc
458 if (!mod->loaded || checkdisk)
459 {
460 if (checkdisk && mod->loaded)
461 Con_DPrintf("checking model %s\n", mod->name);
462 buf = FS_LoadFile (mod->name, tempmempool, false, &filesize);
463 if (buf)
464 {
465 crc = CRC_Block((unsigned char *)buf, filesize);
466 // we need to reload the model if the crc does not match
467 if (mod->crc != crc)
468 mod->loaded = false;
469 }
470 }
471
472 // if the model is already loaded and checks passed, just return
473 if (mod->loaded)
474 {
475 if (buf)
476 Mem_Free(buf);
477 return mod;
478 }
479
481 Con_Printf("loading model %s\n", mod->name);
482
483 SCR_PushLoadingScreen(mod->name, 1);
484
485 // LadyHavoc: unload the existing model in this slot (if there is one)
486 if (mod->loaded || mod->mempool)
488
489 // load the model
490 mod->used = true;
491 mod->crc = crc;
492 // errors can prevent the corresponding mod->loaded = true;
493 mod->loaded = false;
494
495 // default lightmap scale
496 mod->lightmapscale = 1;
497
498 // default model radius and bounding box (mainly for missing models)
499 mod->radius = 16;
500 VectorSet(mod->normalmins, -mod->radius, -mod->radius, -mod->radius);
501 VectorSet(mod->normalmaxs, mod->radius, mod->radius, mod->radius);
502 VectorSet(mod->yawmins, -mod->radius, -mod->radius, -mod->radius);
503 VectorSet(mod->yawmaxs, mod->radius, mod->radius, mod->radius);
504 VectorSet(mod->rotatedmins, -mod->radius, -mod->radius, -mod->radius);
505 VectorSet(mod->rotatedmaxs, mod->radius, mod->radius, mod->radius);
506
507 if (!q3shaders_mem)
508 {
509 // load q3 shaders for the first time, or after a level change
511 }
512
513 if (buf)
514 {
515 int i;
516 const char *ext = FS_FileExtension(mod->name);
517 char *bufend = (char *)buf + filesize;
518 // all models use memory, so allocate a memory pool
519 mod->mempool = Mem_AllocPool(mod->name, 0, NULL);
520
521 // We need to have a reference to the base model in case we're parsing submodels
522 loadmodel = mod;
523
524 // Call the appropriate loader. Try matching magic bytes.
525 for (i = 0; loader[i].Load; i++)
526 {
527 // Headerless formats can just load based on extension. Otherwise match the magic string.
528 if((loader[i].extension && !strcasecmp(ext, loader[i].extension) && !loader[i].header) ||
529 (loader[i].header && !memcmp(buf, loader[i].header, loader[i].headersize)))
530 {
531 // Matched. Load it.
532 loader[i].Load(mod, buf, bufend);
533 Mem_Free(buf);
534
536
537 buf = FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.framegroups", mod->name), tempmempool, false, &filesize);
538 if(buf)
539 {
540 Mod_FrameGroupify(mod, (const char *)buf);
541 Mem_Free(buf);
542 }
543
546 break;
547 }
548 }
549 if(!loader[i].Load)
550 Con_Printf(CON_ERROR "Mod_LoadModel: model \"%s\" is of unknown/unsupported type\n", mod->name);
551 }
552 else if (crash)
553 // LadyHavoc: Sys_Error was *ANNOYING*
554 Con_Printf (CON_ERROR "Mod_LoadModel: %s not found\n", mod->name);
555
556 // no fatal errors occurred, so this model is ready to use.
557 mod->loaded = true;
558
560
561 return mod;
562}
void SCR_PopLoadingScreen(qbool redraw)
Definition cl_screen.c:1899
void SCR_PushLoadingScreen(const char *msg, float len_in_parent)
Definition cl_screen.c:1873
unsigned short CRC_Block(const unsigned char *data, size_t size)
Definition com_crc16.c:75
const char * FS_FileExtension(const char *in)
Definition fs.c:1403
unsigned char * FS_LoadFile(const char *path, mempool_t *pool, qbool quiet, fs_offset_t *filesizepointer)
Definition fs.c:3540
int64_t fs_offset_t
Definition fs.h:37
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glquake.h:657
cvar_t developer_loading
Definition host.c:52
static void R_Model_Null_Draw(entity_render_t *ent)
static void Mod_FindPotentialDeforms(model_t *mod)
static modloader_t loader[]
void Mod_BuildVBOs(void)
void Mod_UnloadModel(model_t *mod)
void Mod_LoadQ3Shaders(void)
static void Mod_FrameGroupify(model_t *mod, const char *buf)
void Mod_SetDrawSkyAndWater(model_t *mod)
Sets the mod->DrawSky and mod->DrawAddWaterPlanes pointers conditionally based on whether surfaces in...
void(* Load)(model_t *, void *, void *)

References buf, Con_DPrintf(), CON_ERROR, Con_Printf(), crash(), CRC_Block(), developer_loading, FS_FileExtension(), FS_LoadFile(), i, int(), cvar_t::integer, modloader_t::Load, loader, loadmodel, Mem_AllocPool, Mem_Free, mod(), Mod_BuildVBOs(), Mod_FindPotentialDeforms(), Mod_FrameGroupify(), Mod_LoadQ3Shaders(), mod_null, Mod_SetDrawSkyAndWater(), Mod_UnloadModel(), NULL, q3shaders_mem, R_Model_Null_Draw(), SCR_PopLoadingScreen(), SCR_PushLoadingScreen(), tempmempool, va(), VectorClear, and VectorSet.

Referenced by Mod_ForName(), Mod_Reload(), and mod_start().

◆ Mod_LoadQ3Shaders()

void Mod_LoadQ3Shaders ( void )

Definition at line 1466 of file model_shared.c.

1467{
1468 int j;
1469 int fileindex;
1470 fssearch_t *search;
1471 char *f;
1472 const char *text;
1473 shader_t shader;
1475 int numparameters;
1476 char parameter[TEXTURE_MAXFRAMES + 4][Q3PATHLENGTH];
1477 char *custsurfaceparmnames[256]; // VorteX: q3map2 has 64 but well, someone will need more
1478 unsigned long custsurfaceflags[256];
1479 int numcustsurfaceflags;
1480 qbool dpshaderkill;
1481
1483
1484 q3shaders_mem = Mem_AllocPool("q3shaders", 0, NULL);
1486 sizeof (q3shader_data_t));
1488 q3shaders_mem, sizeof (q3shader_hash_entry_t), 256);
1490 q3shaders_mem, sizeof (char**), 256);
1491
1492 // parse custinfoparms.txt
1493 numcustsurfaceflags = 0;
1494 if ((text = f = (char *)FS_LoadFile("scripts/custinfoparms.txt", tempmempool, false, NULL)) != NULL)
1495 {
1496 if (!COM_ParseToken_QuakeC(&text, false) || strcasecmp(com_token, "{"))
1497 Con_DPrintf("scripts/custinfoparms.txt: contentflags section parsing error - expected \"{\", found \"%s\"\n", com_token);
1498 else
1499 {
1500 while (COM_ParseToken_QuakeC(&text, false))
1501 if (!strcasecmp(com_token, "}"))
1502 break;
1503 // custom surfaceflags section
1504 if (!COM_ParseToken_QuakeC(&text, false) || strcasecmp(com_token, "{"))
1505 Con_DPrintf("scripts/custinfoparms.txt: surfaceflags section parsing error - expected \"{\", found \"%s\"\n", com_token);
1506 else
1507 {
1508 while(COM_ParseToken_QuakeC(&text, false))
1509 {
1510 if (!strcasecmp(com_token, "}"))
1511 break;
1512 // register surfaceflag
1513 if (numcustsurfaceflags >= 256)
1514 {
1515 Con_Printf("scripts/custinfoparms.txt: surfaceflags section parsing error - max 256 surfaceflags exceeded\n");
1516 break;
1517 }
1518 // name
1519 j = (int)strlen(com_token)+1;
1520 custsurfaceparmnames[numcustsurfaceflags] = (char *)Mem_Alloc(tempmempool, j);
1521 dp_strlcpy(custsurfaceparmnames[numcustsurfaceflags], com_token, j+1);
1522 // value
1523 if (COM_ParseToken_QuakeC(&text, false))
1524 custsurfaceflags[numcustsurfaceflags] = strtol(com_token, NULL, 0);
1525 else
1526 custsurfaceflags[numcustsurfaceflags] = 0;
1527 numcustsurfaceflags++;
1528 }
1529 }
1530 }
1531 Mem_Free(f);
1532 }
1533
1534 // parse shaders
1535 search = FS_Search("scripts/*.shader", true, false, NULL);
1536 if (!search)
1537 return;
1538 for (fileindex = 0;fileindex < search->numfilenames;fileindex++)
1539 {
1540 text = f = (char *)FS_LoadFile(search->filenames[fileindex], tempmempool, false, NULL);
1541 if (!f)
1542 continue;
1543 while (COM_ParseToken_QuakeC(&text, false))
1544 {
1545 memset (&shader, 0, sizeof(shader));
1546 shader.name[0] = 0;
1547 shader.surfaceparms = 0;
1548 shader.surfaceflags = 0;
1549 shader.textureflags = 0;
1550 shader.numlayers = 0;
1551 shader.lighting = false;
1552 shader.vertexalpha = false;
1553 shader.textureblendalpha = false;
1554 shader.skyboxname[0] = 0;
1555 shader.deforms[0].deform = Q3DEFORM_NONE;
1556 shader.dpnortlight = false;
1557 shader.dpshadow = false;
1558 shader.dpnoshadow = false;
1559 shader.dpmeshcollisions = false;
1560 shader.dpshaderkill = false;
1561 shader.dpreflectcube[0] = 0;
1562 shader.reflectmin = 0;
1563 shader.reflectmax = 1;
1564 shader.refractfactor = 1;
1565 Vector4Set(shader.refractcolor4f, 1, 1, 1, 1);
1566 shader.reflectfactor = 1;
1567 Vector4Set(shader.reflectcolor4f, 1, 1, 1, 1);
1568 shader.r_water_wateralpha = 1;
1569 shader.r_water_waterscroll[0] = 0;
1570 shader.r_water_waterscroll[1] = 0;
1577 shader.specularscalemod = 1;
1578 shader.specularpowermod = 1;
1579 shader.rtlightambient = 0;
1580 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
1581 // JUST GREP FOR "specularscalemod = 1".
1582
1583 dp_strlcpy(shader.name, com_token, sizeof(shader.name));
1584 if (!COM_ParseToken_QuakeC(&text, false) || strcasecmp(com_token, "{"))
1585 {
1586 Con_DPrintf("%s parsing error - expected \"{\", found \"%s\"\n", search->filenames[fileindex], com_token);
1587 break;
1588 }
1589 while (COM_ParseToken_QuakeC(&text, false))
1590 {
1591 if (!strcasecmp(com_token, "}"))
1592 break;
1593 if (!strcasecmp(com_token, "{"))
1594 {
1595 static q3shaderinfo_layer_t dummy;
1596 if (shader.numlayers < Q3SHADER_MAXLAYERS)
1597 {
1598 layer = shader.layers + shader.numlayers++;
1599 }
1600 else
1601 {
1602 // parse and process it anyway, just don't store it (so a map $lightmap or such stuff still is found)
1603 memset(&dummy, 0, sizeof(dummy));
1604 layer = &dummy;
1605 }
1606 layer->rgbgen.rgbgen = Q3RGBGEN_IDENTITY;
1607 layer->alphagen.alphagen = Q3ALPHAGEN_IDENTITY;
1608 layer->tcgen.tcgen = Q3TCGEN_TEXTURE;
1609 layer->blendfunc[0] = GL_ONE;
1610 layer->blendfunc[1] = GL_ZERO;
1611 while (COM_ParseToken_QuakeC(&text, false))
1612 {
1613 if (!strcasecmp(com_token, "}"))
1614 break;
1615 if (!strcasecmp(com_token, "\n"))
1616 continue;
1617 numparameters = 0;
1618 for (j = 0;strcasecmp(com_token, "\n") && strcasecmp(com_token, "}");j++)
1619 {
1620 if (j < TEXTURE_MAXFRAMES + 4)
1621 {
1622 // remap dp_water to dpwater, dp_reflect to dpreflect, etc.
1623 if(j == 0 && !strncasecmp(com_token, "dp_", 3))
1624 dpsnprintf(parameter[j], sizeof(parameter[j]), "dp%s", &com_token[3]);
1625 else
1626 dp_strlcpy(parameter[j], com_token, sizeof(parameter[j]));
1627 numparameters = j + 1;
1628 }
1629 if (!COM_ParseToken_QuakeC(&text, true))
1630 break;
1631 }
1632 //for (j = numparameters;j < TEXTURE_MAXFRAMES + 4;j++)
1633 // parameter[j][0] = 0;
1635 {
1636 Con_DPrintf("%s %i: ", shader.name, shader.numlayers - 1);
1637 for (j = 0;j < numparameters;j++)
1638 Con_DPrintf(" %s", parameter[j]);
1639 Con_DPrint("\n");
1640 }
1641 if (numparameters >= 2 && !strcasecmp(parameter[0], "blendfunc"))
1642 {
1643 if (numparameters == 2)
1644 {
1645 if (!strcasecmp(parameter[1], "add"))
1646 {
1647 layer->blendfunc[0] = GL_ONE;
1648 layer->blendfunc[1] = GL_ONE;
1649 }
1650 else if (!strcasecmp(parameter[1], "addalpha"))
1651 {
1652 layer->blendfunc[0] = GL_SRC_ALPHA;
1653 layer->blendfunc[1] = GL_ONE;
1654 }
1655 else if (!strcasecmp(parameter[1], "filter"))
1656 {
1657 layer->blendfunc[0] = GL_DST_COLOR;
1658 layer->blendfunc[1] = GL_ZERO;
1659 }
1660 else if (!strcasecmp(parameter[1], "blend"))
1661 {
1662 layer->blendfunc[0] = GL_SRC_ALPHA;
1663 layer->blendfunc[1] = GL_ONE_MINUS_SRC_ALPHA;
1664 }
1665 }
1666 else if (numparameters == 3)
1667 {
1668 int k;
1669 for (k = 0;k < 2;k++)
1670 {
1671 if (!strcasecmp(parameter[k+1], "GL_ONE"))
1672 layer->blendfunc[k] = GL_ONE;
1673 else if (!strcasecmp(parameter[k+1], "GL_ZERO"))
1674 layer->blendfunc[k] = GL_ZERO;
1675 else if (!strcasecmp(parameter[k+1], "GL_SRC_COLOR"))
1676 layer->blendfunc[k] = GL_SRC_COLOR;
1677 else if (!strcasecmp(parameter[k+1], "GL_SRC_ALPHA"))
1678 layer->blendfunc[k] = GL_SRC_ALPHA;
1679 else if (!strcasecmp(parameter[k+1], "GL_DST_COLOR"))
1680 layer->blendfunc[k] = GL_DST_COLOR;
1681 else if (!strcasecmp(parameter[k+1], "GL_DST_ALPHA"))
1682 layer->blendfunc[k] = GL_DST_ALPHA;
1683 else if (!strcasecmp(parameter[k+1], "GL_ONE_MINUS_SRC_COLOR"))
1684 layer->blendfunc[k] = GL_ONE_MINUS_SRC_COLOR;
1685 else if (!strcasecmp(parameter[k+1], "GL_ONE_MINUS_SRC_ALPHA"))
1686 layer->blendfunc[k] = GL_ONE_MINUS_SRC_ALPHA;
1687 else if (!strcasecmp(parameter[k+1], "GL_ONE_MINUS_DST_COLOR"))
1688 layer->blendfunc[k] = GL_ONE_MINUS_DST_COLOR;
1689 else if (!strcasecmp(parameter[k+1], "GL_ONE_MINUS_DST_ALPHA"))
1690 layer->blendfunc[k] = GL_ONE_MINUS_DST_ALPHA;
1691 else
1692 layer->blendfunc[k] = GL_ONE; // default in case of parsing error
1693 }
1694 }
1695 }
1696 if (numparameters >= 2 && !strcasecmp(parameter[0], "alphafunc"))
1697 layer->alphatest = true;
1698 if (numparameters >= 2 && (!strcasecmp(parameter[0], "map") || !strcasecmp(parameter[0], "clampmap")))
1699 {
1700 if (!strcasecmp(parameter[0], "clampmap"))
1701 layer->clampmap = true;
1702 layer->numframes = 1;
1703 layer->framerate = 1;
1704 layer->texturename = (char**)Mem_ExpandableArray_AllocRecord (
1706 layer->texturename[0] = Mem_strdup (q3shaders_mem, parameter[1]);
1707 if (!strcasecmp(parameter[1], "$lightmap"))
1708 shader.lighting = true;
1709 }
1710 else if (numparameters >= 3 && (!strcasecmp(parameter[0], "animmap") || !strcasecmp(parameter[0], "animclampmap")))
1711 {
1712 int i;
1713 layer->numframes = min(numparameters - 2, TEXTURE_MAXFRAMES);
1714 layer->framerate = atof(parameter[1]);
1715 layer->texturename = (char **) Mem_Alloc (q3shaders_mem, sizeof (char*) * layer->numframes);
1716 for (i = 0;i < layer->numframes;i++)
1717 layer->texturename[i] = Mem_strdup (q3shaders_mem, parameter[i + 2]);
1718 }
1719 else if (numparameters >= 2 && !strcasecmp(parameter[0], "rgbgen"))
1720 {
1721 int i;
1722 for (i = 0;i < numparameters - 2 && i < Q3RGBGEN_MAXPARMS;i++)
1723 layer->rgbgen.parms[i] = atof(parameter[i+2]);
1724 if (!strcasecmp(parameter[1], "identity")) layer->rgbgen.rgbgen = Q3RGBGEN_IDENTITY;
1725 else if (!strcasecmp(parameter[1], "const")) layer->rgbgen.rgbgen = Q3RGBGEN_CONST;
1726 else if (!strcasecmp(parameter[1], "entity")) layer->rgbgen.rgbgen = Q3RGBGEN_ENTITY;
1727 else if (!strcasecmp(parameter[1], "exactvertex")) layer->rgbgen.rgbgen = Q3RGBGEN_EXACTVERTEX;
1728 else if (!strcasecmp(parameter[1], "identitylighting")) layer->rgbgen.rgbgen = Q3RGBGEN_IDENTITYLIGHTING;
1729 else if (!strcasecmp(parameter[1], "lightingdiffuse")) layer->rgbgen.rgbgen = Q3RGBGEN_LIGHTINGDIFFUSE;
1730 else if (!strcasecmp(parameter[1], "oneminusentity")) layer->rgbgen.rgbgen = Q3RGBGEN_ONEMINUSENTITY;
1731 else if (!strcasecmp(parameter[1], "oneminusvertex")) layer->rgbgen.rgbgen = Q3RGBGEN_ONEMINUSVERTEX;
1732 else if (!strcasecmp(parameter[1], "vertex")) layer->rgbgen.rgbgen = Q3RGBGEN_VERTEX;
1733 else if (!strcasecmp(parameter[1], "wave"))
1734 {
1735 layer->rgbgen.rgbgen = Q3RGBGEN_WAVE;
1736 layer->rgbgen.wavefunc = Mod_LoadQ3Shaders_EnumerateWaveFunc(parameter[2]);
1737 for (i = 0;i < numparameters - 3 && i < Q3WAVEPARMS;i++)
1738 layer->rgbgen.waveparms[i] = atof(parameter[i+3]);
1739 }
1740 else Con_DPrintf("%s parsing warning: unknown rgbgen %s\n", search->filenames[fileindex], parameter[1]);
1741 }
1742 else if (numparameters >= 2 && !strcasecmp(parameter[0], "alphagen"))
1743 {
1744 int i;
1745 for (i = 0;i < numparameters - 2 && i < Q3ALPHAGEN_MAXPARMS;i++)
1746 layer->alphagen.parms[i] = atof(parameter[i+2]);
1747 if (!strcasecmp(parameter[1], "identity")) layer->alphagen.alphagen = Q3ALPHAGEN_IDENTITY;
1748 else if (!strcasecmp(parameter[1], "const")) layer->alphagen.alphagen = Q3ALPHAGEN_CONST;
1749 else if (!strcasecmp(parameter[1], "entity")) layer->alphagen.alphagen = Q3ALPHAGEN_ENTITY;
1750 else if (!strcasecmp(parameter[1], "lightingspecular")) layer->alphagen.alphagen = Q3ALPHAGEN_LIGHTINGSPECULAR;
1751 else if (!strcasecmp(parameter[1], "oneminusentity")) layer->alphagen.alphagen = Q3ALPHAGEN_ONEMINUSENTITY;
1752 else if (!strcasecmp(parameter[1], "oneminusvertex")) layer->alphagen.alphagen = Q3ALPHAGEN_ONEMINUSVERTEX;
1753 else if (!strcasecmp(parameter[1], "portal")) layer->alphagen.alphagen = Q3ALPHAGEN_PORTAL;
1754 else if (!strcasecmp(parameter[1], "vertex")) layer->alphagen.alphagen = Q3ALPHAGEN_VERTEX;
1755 else if (!strcasecmp(parameter[1], "wave"))
1756 {
1757 layer->alphagen.alphagen = Q3ALPHAGEN_WAVE;
1758 layer->alphagen.wavefunc = Mod_LoadQ3Shaders_EnumerateWaveFunc(parameter[2]);
1759 for (i = 0;i < numparameters - 3 && i < Q3WAVEPARMS;i++)
1760 layer->alphagen.waveparms[i] = atof(parameter[i+3]);
1761 }
1762 else Con_DPrintf("%s parsing warning: unknown alphagen %s\n", search->filenames[fileindex], parameter[1]);
1763 }
1764 else if (numparameters >= 2 && (!strcasecmp(parameter[0], "texgen") || !strcasecmp(parameter[0], "tcgen")))
1765 {
1766 int i;
1767 // observed values: tcgen environment
1768 // no other values have been observed in real shaders
1769 for (i = 0;i < numparameters - 2 && i < Q3TCGEN_MAXPARMS;i++)
1770 layer->tcgen.parms[i] = atof(parameter[i+2]);
1771 if (!strcasecmp(parameter[1], "base")) layer->tcgen.tcgen = Q3TCGEN_TEXTURE;
1772 else if (!strcasecmp(parameter[1], "texture")) layer->tcgen.tcgen = Q3TCGEN_TEXTURE;
1773 else if (!strcasecmp(parameter[1], "environment")) layer->tcgen.tcgen = Q3TCGEN_ENVIRONMENT;
1774 else if (!strcasecmp(parameter[1], "lightmap")) layer->tcgen.tcgen = Q3TCGEN_LIGHTMAP;
1775 else if (!strcasecmp(parameter[1], "vector")) layer->tcgen.tcgen = Q3TCGEN_VECTOR;
1776 else Con_DPrintf("%s parsing warning: unknown tcgen mode %s\n", search->filenames[fileindex], parameter[1]);
1777 }
1778 else if (numparameters >= 2 && !strcasecmp(parameter[0], "tcmod"))
1779 {
1780 int i, tcmodindex;
1781 // observed values:
1782 // tcmod rotate #
1783 // tcmod scale # #
1784 // tcmod scroll # #
1785 // tcmod stretch sin # # # #
1786 // tcmod stretch triangle # # # #
1787 // tcmod transform # # # # # #
1788 // tcmod turb # # # #
1789 // tcmod turb sin # # # # (this is bogus)
1790 // no other values have been observed in real shaders
1791 for (tcmodindex = 0;tcmodindex < Q3MAXTCMODS;tcmodindex++)
1792 if (!layer->tcmods[tcmodindex].tcmod)
1793 break;
1794 if (tcmodindex < Q3MAXTCMODS)
1795 {
1796 for (i = 0;i < numparameters - 2 && i < Q3TCMOD_MAXPARMS;i++)
1797 layer->tcmods[tcmodindex].parms[i] = atof(parameter[i+2]);
1798 if (!strcasecmp(parameter[1], "entitytranslate")) layer->tcmods[tcmodindex].tcmod = Q3TCMOD_ENTITYTRANSLATE;
1799 else if (!strcasecmp(parameter[1], "rotate")) layer->tcmods[tcmodindex].tcmod = Q3TCMOD_ROTATE;
1800 else if (!strcasecmp(parameter[1], "scale")) layer->tcmods[tcmodindex].tcmod = Q3TCMOD_SCALE;
1801 else if (!strcasecmp(parameter[1], "scroll")) layer->tcmods[tcmodindex].tcmod = Q3TCMOD_SCROLL;
1802 else if (!strcasecmp(parameter[1], "page")) layer->tcmods[tcmodindex].tcmod = Q3TCMOD_PAGE;
1803 else if (!strcasecmp(parameter[1], "stretch"))
1804 {
1805 layer->tcmods[tcmodindex].tcmod = Q3TCMOD_STRETCH;
1806 layer->tcmods[tcmodindex].wavefunc = Mod_LoadQ3Shaders_EnumerateWaveFunc(parameter[2]);
1807 for (i = 0;i < numparameters - 3 && i < Q3WAVEPARMS;i++)
1808 layer->tcmods[tcmodindex].waveparms[i] = atof(parameter[i+3]);
1809 }
1810 else if (!strcasecmp(parameter[1], "transform")) layer->tcmods[tcmodindex].tcmod = Q3TCMOD_TRANSFORM;
1811 else if (!strcasecmp(parameter[1], "turb")) layer->tcmods[tcmodindex].tcmod = Q3TCMOD_TURBULENT;
1812 else Con_DPrintf("%s parsing warning: unknown tcmod mode %s\n", search->filenames[fileindex], parameter[1]);
1813 }
1814 else
1815 Con_DPrintf("%s parsing warning: too many tcmods on one layer\n", search->filenames[fileindex]);
1816 }
1817 // break out a level if it was a closing brace (not using the character here to not confuse vim)
1818 if (!strcasecmp(com_token, "}"))
1819 break;
1820 }
1821 if (layer->rgbgen.rgbgen == Q3RGBGEN_LIGHTINGDIFFUSE || layer->rgbgen.rgbgen == Q3RGBGEN_VERTEX)
1822 shader.lighting = true;
1823 if (layer->alphagen.alphagen == Q3ALPHAGEN_VERTEX)
1824 {
1825 if (layer == shader.layers + 0)
1826 {
1827 // vertex controlled transparency
1828 shader.vertexalpha = true;
1829 }
1830 else
1831 {
1832 // multilayer terrain shader or similar
1833 shader.textureblendalpha = true;
1835 shader.layers[0].dptexflags |= TEXF_ALPHA;
1836 }
1837 }
1838
1840 {
1841 // for a long while, DP treated GL_ONE GL_ONE as GL_SRC_ALPHA GL_ONE
1842 // this cvar brings back this behaviour
1843 if(layer->blendfunc[0] == GL_ONE && layer->blendfunc[1] == GL_ONE)
1844 layer->blendfunc[0] = GL_SRC_ALPHA;
1845 }
1846
1847 layer->dptexflags = 0;
1848 if (layer->alphatest)
1849 layer->dptexflags |= TEXF_ALPHA;
1850 switch(layer->blendfunc[0])
1851 {
1852 case GL_SRC_ALPHA:
1854 layer->dptexflags |= TEXF_ALPHA;
1855 break;
1856 }
1857 switch(layer->blendfunc[1])
1858 {
1859 case GL_SRC_ALPHA:
1861 layer->dptexflags |= TEXF_ALPHA;
1862 break;
1863 }
1864 if (!(shader.surfaceparms & Q3SURFACEPARM_NOMIPMAPS))
1865 layer->dptexflags |= TEXF_MIPMAP;
1866 if (!(shader.textureflags & Q3TEXTUREFLAG_NOPICMIP))
1867 layer->dptexflags |= TEXF_PICMIP | TEXF_COMPRESS;
1868 if (layer->clampmap)
1869 layer->dptexflags |= TEXF_CLAMP;
1870 continue;
1871 }
1872 numparameters = 0;
1873 for (j = 0;strcasecmp(com_token, "\n") && strcasecmp(com_token, "}");j++)
1874 {
1875 if (j < TEXTURE_MAXFRAMES + 4)
1876 {
1877 // remap dp_water to dpwater, dp_reflect to dpreflect, etc.
1878 if(j == 0 && !strncasecmp(com_token, "dp_", 3))
1879 dpsnprintf(parameter[j], sizeof(parameter[j]), "dp%s", &com_token[3]);
1880 else
1881 dp_strlcpy(parameter[j], com_token, sizeof(parameter[j]));
1882 numparameters = j + 1;
1883 }
1884 if (!COM_ParseToken_QuakeC(&text, true))
1885 break;
1886 }
1887 //for (j = numparameters;j < TEXTURE_MAXFRAMES + 4;j++)
1888 // parameter[j][0] = 0;
1889 if (fileindex == 0 && !strcasecmp(com_token, "}"))
1890 break;
1892 {
1893 Con_DPrintf("%s: ", shader.name);
1894 for (j = 0;j < numparameters;j++)
1895 Con_DPrintf(" %s", parameter[j]);
1896 Con_DPrint("\n");
1897 }
1898 if (numparameters < 1)
1899 continue;
1900 if (!strcasecmp(parameter[0], "surfaceparm") && numparameters >= 2)
1901 {
1902 if (!strcasecmp(parameter[1], "alphashadow"))
1904 else if (!strcasecmp(parameter[1], "areaportal"))
1906 else if (!strcasecmp(parameter[1], "botclip"))
1908 else if (!strcasecmp(parameter[1], "clusterportal"))
1910 else if (!strcasecmp(parameter[1], "detail"))
1912 else if (!strcasecmp(parameter[1], "donotenter"))
1914 else if (!strcasecmp(parameter[1], "dust"))
1916 else if (!strcasecmp(parameter[1], "hint"))
1918 else if (!strcasecmp(parameter[1], "fog"))
1920 else if (!strcasecmp(parameter[1], "lava"))
1922 else if (!strcasecmp(parameter[1], "lightfilter"))
1924 else if (!strcasecmp(parameter[1], "lightgrid"))
1926 else if (!strcasecmp(parameter[1], "metalsteps"))
1928 else if (!strcasecmp(parameter[1], "nodamage"))
1930 else if (!strcasecmp(parameter[1], "nodlight"))
1932 else if (!strcasecmp(parameter[1], "nodraw"))
1934 else if (!strcasecmp(parameter[1], "nodrop"))
1936 else if (!strcasecmp(parameter[1], "noimpact"))
1938 else if (!strcasecmp(parameter[1], "nolightmap"))
1940 else if (!strcasecmp(parameter[1], "nomarks"))
1942 else if (!strcasecmp(parameter[1], "nomipmaps"))
1944 else if (!strcasecmp(parameter[1], "nonsolid"))
1946 else if (!strcasecmp(parameter[1], "origin"))
1948 else if (!strcasecmp(parameter[1], "playerclip"))
1950 else if (!strcasecmp(parameter[1], "sky"))
1952 else if (!strcasecmp(parameter[1], "slick"))
1954 else if (!strcasecmp(parameter[1], "slime"))
1956 else if (!strcasecmp(parameter[1], "structural"))
1958 else if (!strcasecmp(parameter[1], "trans"))
1960 else if (!strcasecmp(parameter[1], "water"))
1962 else if (!strcasecmp(parameter[1], "pointlight"))
1964 else if (!strcasecmp(parameter[1], "antiportal"))
1966 else if (!strcasecmp(parameter[1], "skip"))
1967 ; // shader.surfaceparms |= Q3SURFACEPARM_SKIP; FIXME we don't have enough #defines for this any more, and the engine doesn't need this one anyway
1968 else
1969 {
1970 // try custom surfaceparms
1971 for (j = 0; j < numcustsurfaceflags; j++)
1972 {
1973 if (!strcasecmp(custsurfaceparmnames[j], parameter[1]))
1974 {
1975 shader.surfaceflags |= custsurfaceflags[j];
1976 break;
1977 }
1978 }
1979 // failed all
1980 if (j == numcustsurfaceflags)
1981 Con_DPrintf("%s parsing warning: unknown surfaceparm \"%s\"\n", search->filenames[fileindex], parameter[1]);
1982 }
1983 }
1984 else if (!strcasecmp(parameter[0], "dpshadow"))
1985 shader.dpshadow = true;
1986 else if (!strcasecmp(parameter[0], "dpnoshadow"))
1987 shader.dpnoshadow = true;
1988 else if (!strcasecmp(parameter[0], "dpnortlight"))
1989 shader.dpnortlight = true;
1990 else if (!strcasecmp(parameter[0], "dpreflectcube"))
1991 dp_strlcpy(shader.dpreflectcube, parameter[1], sizeof(shader.dpreflectcube));
1992 else if (!strcasecmp(parameter[0], "dpmeshcollisions"))
1993 shader.dpmeshcollisions = true;
1994 // this sets dpshaderkill to true if dpshaderkillifcvarzero was used, and to false if dpnoshaderkillifcvarzero was used
1995 else if (((dpshaderkill = !strcasecmp(parameter[0], "dpshaderkillifcvarzero")) || !strcasecmp(parameter[0], "dpnoshaderkillifcvarzero")) && numparameters >= 2)
1996 {
1997 if (Cvar_VariableValue(&cvars_all, parameter[1], ~0) == 0.0f)
1998 shader.dpshaderkill = dpshaderkill;
1999 }
2000 // this sets dpshaderkill to true if dpshaderkillifcvar was used, and to false if dpnoshaderkillifcvar was used
2001 else if (((dpshaderkill = !strcasecmp(parameter[0], "dpshaderkillifcvar")) || !strcasecmp(parameter[0], "dpnoshaderkillifcvar")) && numparameters >= 2)
2002 {
2003 const char *op = NULL;
2004 if (numparameters >= 3)
2005 op = parameter[2];
2006 if(!op)
2007 {
2008 if (Cvar_VariableValue(&cvars_all, parameter[1], ~0) != 0.0f)
2009 shader.dpshaderkill = dpshaderkill;
2010 }
2011 else if (numparameters >= 4 && !strcmp(op, "=="))
2012 {
2013 if (Cvar_VariableValue(&cvars_all, parameter[1], ~0) == atof(parameter[3]))
2014 shader.dpshaderkill = dpshaderkill;
2015 }
2016 else if (numparameters >= 4 && !strcmp(op, "!="))
2017 {
2018 if (Cvar_VariableValue(&cvars_all, parameter[1], ~0) != atof(parameter[3]))
2019 shader.dpshaderkill = dpshaderkill;
2020 }
2021 else if (numparameters >= 4 && !strcmp(op, ">"))
2022 {
2023 if (Cvar_VariableValue(&cvars_all, parameter[1], ~0) > atof(parameter[3]))
2024 shader.dpshaderkill = dpshaderkill;
2025 }
2026 else if (numparameters >= 4 && !strcmp(op, "<"))
2027 {
2028 if (Cvar_VariableValue(&cvars_all, parameter[1], ~0) < atof(parameter[3]))
2029 shader.dpshaderkill = dpshaderkill;
2030 }
2031 else if (numparameters >= 4 && !strcmp(op, ">="))
2032 {
2033 if (Cvar_VariableValue(&cvars_all, parameter[1], ~0) >= atof(parameter[3]))
2034 shader.dpshaderkill = dpshaderkill;
2035 }
2036 else if (numparameters >= 4 && !strcmp(op, "<="))
2037 {
2038 if (Cvar_VariableValue(&cvars_all, parameter[1], ~0) <= atof(parameter[3]))
2039 shader.dpshaderkill = dpshaderkill;
2040 }
2041 else
2042 {
2043 Con_DPrintf("%s parsing warning: unknown dpshaderkillifcvar op \"%s\", or not enough arguments\n", search->filenames[fileindex], op);
2044 }
2045 }
2046 else if (!strcasecmp(parameter[0], "sky") && numparameters >= 2)
2047 {
2048 // some q3 skies don't have the sky parm set
2050 dp_strlcpy(shader.skyboxname, parameter[1], sizeof(shader.skyboxname));
2051 }
2052 else if (!strcasecmp(parameter[0], "skyparms") && numparameters >= 2)
2053 {
2054 // some q3 skies don't have the sky parm set
2056 if (!atoi(parameter[1]) && strcasecmp(parameter[1], "-"))
2057 dp_strlcpy(shader.skyboxname, parameter[1], sizeof(shader.skyboxname));
2058 }
2059 else if (!strcasecmp(parameter[0], "cull") && numparameters >= 2)
2060 {
2061 if (!strcasecmp(parameter[1], "disable") || !strcasecmp(parameter[1], "none") || !strcasecmp(parameter[1], "twosided"))
2063 }
2064 else if (!strcasecmp(parameter[0], "nomipmaps"))
2066 else if (!strcasecmp(parameter[0], "nopicmip"))
2068 else if (!strcasecmp(parameter[0], "polygonoffset"))
2070 else if (!strcasecmp(parameter[0], "dppolygonoffset"))
2071 {
2073 if(numparameters >= 2)
2074 {
2075 shader.biaspolygonfactor = atof(parameter[1]);
2076 if(numparameters >= 3)
2077 shader.biaspolygonoffset = atof(parameter[2]);
2078 else
2079 shader.biaspolygonoffset = 0;
2080 }
2081 }
2082 else if (!strcasecmp(parameter[0], "dptransparentsort") && numparameters >= 2)
2083 {
2085 if (!strcasecmp(parameter[1], "sky"))
2087 else if (!strcasecmp(parameter[1], "distance"))
2089 else if (!strcasecmp(parameter[1], "hud"))
2091 else
2092 Con_DPrintf("%s parsing warning: unknown dptransparentsort category \"%s\", or not enough arguments\n", search->filenames[fileindex], parameter[1]);
2093 }
2094 else if (!strcasecmp(parameter[0], "dprefract") && numparameters >= 5)
2095 {
2097 shader.refractfactor = atof(parameter[1]);
2098 Vector4Set(shader.refractcolor4f, atof(parameter[2]), atof(parameter[3]), atof(parameter[4]), 1);
2099 }
2100 else if (!strcasecmp(parameter[0], "dpreflect") && numparameters >= 6)
2101 {
2103 shader.reflectfactor = atof(parameter[1]);
2104 Vector4Set(shader.reflectcolor4f, atof(parameter[2]), atof(parameter[3]), atof(parameter[4]), atof(parameter[5]));
2105 }
2106 else if (!strcasecmp(parameter[0], "dpcamera"))
2107 {
2109 }
2110 else if (!strcasecmp(parameter[0], "dpwater") && numparameters >= 12)
2111 {
2113 shader.reflectmin = atof(parameter[1]);
2114 shader.reflectmax = atof(parameter[2]);
2115 shader.refractfactor = atof(parameter[3]);
2116 shader.reflectfactor = atof(parameter[4]);
2117 Vector4Set(shader.refractcolor4f, atof(parameter[5]), atof(parameter[6]), atof(parameter[7]), 1);
2118 Vector4Set(shader.reflectcolor4f, atof(parameter[8]), atof(parameter[9]), atof(parameter[10]), 1);
2119 shader.r_water_wateralpha = atof(parameter[11]);
2120 }
2121 else if (!strcasecmp(parameter[0], "dpwaterscroll") && numparameters >= 3)
2122 {
2123 shader.r_water_waterscroll[0] = 1/atof(parameter[1]);
2124 shader.r_water_waterscroll[1] = 1/atof(parameter[2]);
2125 }
2126 else if (!strcasecmp(parameter[0], "dpglossintensitymod") && numparameters >= 2)
2127 {
2128 shader.specularscalemod = atof(parameter[1]);
2129 }
2130 else if (!strcasecmp(parameter[0], "dpglossexponentmod") && numparameters >= 2)
2131 {
2132 shader.specularpowermod = atof(parameter[1]);
2133 }
2134 else if (!strcasecmp(parameter[0], "dprtlightambient") && numparameters >= 2)
2135 {
2136 shader.rtlightambient = atof(parameter[1]);
2137 }
2138 else if (!strcasecmp(parameter[0], "dpoffsetmapping") && numparameters >= 2)
2139 {
2140 if (!strcasecmp(parameter[1], "disable") || !strcasecmp(parameter[1], "none") || !strcasecmp(parameter[1], "off"))
2142 else if (!strcasecmp(parameter[1], "default") || !strcasecmp(parameter[1], "normal"))
2144 else if (!strcasecmp(parameter[1], "linear"))
2146 else if (!strcasecmp(parameter[1], "relief"))
2148 if (numparameters >= 3)
2149 shader.offsetscale = atof(parameter[2]);
2150 if (numparameters >= 5)
2151 {
2152 if(!strcasecmp(parameter[3], "bias"))
2153 shader.offsetbias = atof(parameter[4]);
2154 else if(!strcasecmp(parameter[3], "match"))
2155 shader.offsetbias = 1.0f - atof(parameter[4]);
2156 else if(!strcasecmp(parameter[3], "match8"))
2157 shader.offsetbias = 1.0f - atof(parameter[4]) / 255.0f;
2158 else if(!strcasecmp(parameter[3], "match16"))
2159 shader.offsetbias = 1.0f - atof(parameter[4]) / 65535.0f;
2160 }
2161 }
2162 else if (!strcasecmp(parameter[0], "deformvertexes") && numparameters >= 2)
2163 {
2164 int i, deformindex;
2165 for (deformindex = 0;deformindex < Q3MAXDEFORMS;deformindex++)
2166 if (!shader.deforms[deformindex].deform)
2167 break;
2168 if (deformindex < Q3MAXDEFORMS)
2169 {
2170 for (i = 0;i < numparameters - 2 && i < Q3DEFORM_MAXPARMS;i++)
2171 shader.deforms[deformindex].parms[i] = atof(parameter[i+2]);
2172 if (!strcasecmp(parameter[1], "projectionshadow")) shader.deforms[deformindex].deform = Q3DEFORM_PROJECTIONSHADOW;
2173 else if (!strcasecmp(parameter[1], "autosprite" )) shader.deforms[deformindex].deform = Q3DEFORM_AUTOSPRITE;
2174 else if (!strcasecmp(parameter[1], "autosprite2" )) shader.deforms[deformindex].deform = Q3DEFORM_AUTOSPRITE2;
2175 else if (!strcasecmp(parameter[1], "text0" )) shader.deforms[deformindex].deform = Q3DEFORM_TEXT0;
2176 else if (!strcasecmp(parameter[1], "text1" )) shader.deforms[deformindex].deform = Q3DEFORM_TEXT1;
2177 else if (!strcasecmp(parameter[1], "text2" )) shader.deforms[deformindex].deform = Q3DEFORM_TEXT2;
2178 else if (!strcasecmp(parameter[1], "text3" )) shader.deforms[deformindex].deform = Q3DEFORM_TEXT3;
2179 else if (!strcasecmp(parameter[1], "text4" )) shader.deforms[deformindex].deform = Q3DEFORM_TEXT4;
2180 else if (!strcasecmp(parameter[1], "text5" )) shader.deforms[deformindex].deform = Q3DEFORM_TEXT5;
2181 else if (!strcasecmp(parameter[1], "text6" )) shader.deforms[deformindex].deform = Q3DEFORM_TEXT6;
2182 else if (!strcasecmp(parameter[1], "text7" )) shader.deforms[deformindex].deform = Q3DEFORM_TEXT7;
2183 else if (!strcasecmp(parameter[1], "bulge" )) shader.deforms[deformindex].deform = Q3DEFORM_BULGE;
2184 else if (!strcasecmp(parameter[1], "normal" )) shader.deforms[deformindex].deform = Q3DEFORM_NORMAL;
2185 else if (!strcasecmp(parameter[1], "wave" ))
2186 {
2187 shader.deforms[deformindex].deform = Q3DEFORM_WAVE;
2188 shader.deforms[deformindex].wavefunc = Mod_LoadQ3Shaders_EnumerateWaveFunc(parameter[3]);
2189 for (i = 0;i < numparameters - 4 && i < Q3WAVEPARMS;i++)
2190 shader.deforms[deformindex].waveparms[i] = atof(parameter[i+4]);
2191 }
2192 else if (!strcasecmp(parameter[1], "move" ))
2193 {
2194 shader.deforms[deformindex].deform = Q3DEFORM_MOVE;
2195 shader.deforms[deformindex].wavefunc = Mod_LoadQ3Shaders_EnumerateWaveFunc(parameter[5]);
2196 for (i = 0;i < numparameters - 6 && i < Q3WAVEPARMS;i++)
2197 shader.deforms[deformindex].waveparms[i] = atof(parameter[i+6]);
2198 }
2199 }
2200 }
2201 }
2202 // hide this shader if a cvar said it should be killed
2203 if (shader.dpshaderkill)
2204 shader.numlayers = 0;
2205 // fix up multiple reflection types
2208
2209 Q3Shader_AddToHash (&shader);
2210 }
2211 Mem_Free(f);
2212 }
2213 FS_FreeSearch(search);
2214 // free custinfoparm values
2215 for (j = 0; j < numcustsurfaceflags; j++)
2216 Mem_Free(custsurfaceparmnames[j]);
2217}
char com_token[MAX_INPUTLINE]
Definition common.c:39
qbool COM_ParseToken_QuakeC(const char **datapointer, qbool returnnewline)
Definition common.c:581
void Con_DPrint(const char *msg)
A Con_Print that only shows up if the "developer" cvar is set.
Definition console.c:1531
float Cvar_VariableValue(cvar_state_t *cvars, const char *var_name, unsigned neededflags)
Definition cvar.c:129
cvar_state_t cvars_all
Definition cvar.c:28
void FS_FreeSearch(fssearch_t *search)
Definition fs.c:3963
fssearch_t * FS_Search(const char *pattern, int caseinsensitive, int quiet, const char *packfile)
Definition fs.c:3756
GLenum GLenum GLuint GLint GLint layer
Definition glquake.h:615
#define GL_ONE_MINUS_DST_ALPHA
Definition glquake.h:82
#define GL_ONE_MINUS_DST_COLOR
Definition glquake.h:78
#define GL_SRC_ALPHA
Definition glquake.h:79
#define GL_SRC_COLOR
Definition glquake.h:75
#define GL_ZERO
Definition glquake.h:73
#define GL_ONE_MINUS_SRC_ALPHA
Definition glquake.h:80
#define GL_ONE
Definition glquake.h:74
#define GL_DST_ALPHA
Definition glquake.h:81
#define GL_DST_COLOR
Definition glquake.h:77
#define GL_ONE_MINUS_SRC_COLOR
Definition glquake.h:76
cvar_t developer_insane
Definition host.c:50
#define min(A, B)
Definition mathlib.h:37
#define Vector4Set(vec, r, g, b, a)
Definition mathlib.h:86
float strlen(string s)
#define Q3SURFACEPARM_PLAYERCLIP
#define Q3SURFACEPARM_NOIMPACT
#define Q3SURFACEPARM_STRUCTURAL
#define Q3SURFACEPARM_NONSOLID
#define Q3SURFACEPARM_TRANS
#define Q3SURFACEPARM_FOG
#define Q3SURFACEPARM_NODROP
#define Q3SURFACEPARM_NOMIPMAPS
#define Q3SURFACEPARM_CLUSTERPORTAL
#define Q3SURFACEPARM_NODAMAGE
#define Q3SURFACEPARM_SLICK
#define Q3SURFACEPARM_METALSTEPS
#define Q3SURFACEPARM_NODRAW
#define Q3SURFACEPARM_NOLIGHTMAP
#define Q3SURFACEPARM_LAVA
#define Q3SURFACEPARM_SLIME
#define Q3SURFACEPARM_SKY
#define Q3SURFACEPARM_LIGHTFILTER
#define Q3SURFACEPARM_ANTIPORTAL
#define Q3SURFACEPARM_NOMARKS
#define Q3SURFACEPARM_ORIGIN
#define Q3SURFACEPARM_ALPHASHADOW
#define Q3SURFACEPARM_BOTCLIP
#define Q3SURFACEPARM_DUST
#define Q3SURFACEPARM_WATER
#define Q3SURFACEPARM_DETAIL
#define Q3SURFACEPARM_POINTLIGHT
#define Q3SURFACEPARM_DONOTENTER
#define Q3SURFACEPARM_AREAPORTAL
#define Q3SURFACEPARM_NODLIGHT
#define Q3SURFACEPARM_LIGHTGRID
#define Q3SURFACEPARM_HINT
static void Q3Shader_AddToHash(shader_t *shader)
static q3shader_data_t * q3shader_data
static int Mod_LoadQ3Shaders_EnumerateWaveFunc(const char *s)
void Mod_FreeQ3Shaders(void)
#define Q3TEXTUREFLAG_WATERSHADER
Definition r_qshader.h:13
#define Q3PATHLENGTH
Definition r_qshader.h:17
#define Q3TCMOD_MAXPARMS
Definition r_qshader.h:25
#define Q3TEXTUREFLAG_NOPICMIP
Definition r_qshader.h:9
#define TEXTURE_MAXFRAMES
Definition r_qshader.h:18
#define Q3WAVEPARMS
Definition r_qshader.h:19
#define Q3ALPHAGEN_MAXPARMS
Definition r_qshader.h:23
#define Q3MAXTCMODS
Definition r_qshader.h:26
#define Q3MAXDEFORMS
Definition r_qshader.h:27
#define Q3RGBGEN_MAXPARMS
Definition r_qshader.h:22
@ Q3RGBGEN_VERTEX
Definition r_qshader.h:77
@ Q3RGBGEN_LIGHTINGDIFFUSE
Definition r_qshader.h:74
@ Q3RGBGEN_CONST
Definition r_qshader.h:70
@ Q3RGBGEN_WAVE
Definition r_qshader.h:78
@ Q3RGBGEN_IDENTITYLIGHTING
Definition r_qshader.h:73
@ Q3RGBGEN_ONEMINUSENTITY
Definition r_qshader.h:75
@ Q3RGBGEN_IDENTITY
Definition r_qshader.h:69
@ Q3RGBGEN_ONEMINUSVERTEX
Definition r_qshader.h:76
@ Q3RGBGEN_ENTITY
Definition r_qshader.h:71
@ Q3RGBGEN_EXACTVERTEX
Definition r_qshader.h:72
#define Q3TEXTUREFLAG_POLYGONOFFSET
Definition r_qshader.h:10
@ Q3DEFORM_NORMAL
Definition r_qshader.h:61
@ Q3DEFORM_TEXT3
Definition r_qshader.h:54
@ Q3DEFORM_TEXT5
Definition r_qshader.h:56
@ Q3DEFORM_TEXT0
Definition r_qshader.h:51
@ Q3DEFORM_AUTOSPRITE
Definition r_qshader.h:49
@ Q3DEFORM_PROJECTIONSHADOW
Definition r_qshader.h:48
@ Q3DEFORM_WAVE
Definition r_qshader.h:60
@ Q3DEFORM_TEXT1
Definition r_qshader.h:52
@ Q3DEFORM_TEXT2
Definition r_qshader.h:53
@ Q3DEFORM_NONE
Definition r_qshader.h:47
@ Q3DEFORM_AUTOSPRITE2
Definition r_qshader.h:50
@ Q3DEFORM_TEXT7
Definition r_qshader.h:58
@ Q3DEFORM_MOVE
Definition r_qshader.h:62
@ Q3DEFORM_TEXT6
Definition r_qshader.h:57
@ Q3DEFORM_TEXT4
Definition r_qshader.h:55
@ Q3DEFORM_BULGE
Definition r_qshader.h:59
#define Q3SHADER_MAXLAYERS
Definition r_qshader.h:21
@ TRANSPARENTSORT_DISTANCE
Definition r_qshader.h:194
@ TRANSPARENTSORT_SKY
Definition r_qshader.h:193
@ TRANSPARENTSORT_HUD
Definition r_qshader.h:195
#define Q3TEXTUREFLAG_TRANSPARENTSORT
Definition r_qshader.h:15
@ Q3TCMOD_SCALE
Definition r_qshader.h:114
@ Q3TCMOD_ROTATE
Definition r_qshader.h:113
@ Q3TCMOD_ENTITYTRANSLATE
Definition r_qshader.h:112
@ Q3TCMOD_TRANSFORM
Definition r_qshader.h:117
@ Q3TCMOD_SCROLL
Definition r_qshader.h:115
@ Q3TCMOD_PAGE
Definition r_qshader.h:119
@ Q3TCMOD_TURBULENT
Definition r_qshader.h:118
@ Q3TCMOD_STRETCH
Definition r_qshader.h:116
@ OFFSETMAPPING_DEFAULT
Definition r_qshader.h:186
@ OFFSETMAPPING_OFF
Definition r_qshader.h:185
@ OFFSETMAPPING_LINEAR
Definition r_qshader.h:187
@ OFFSETMAPPING_RELIEF
Definition r_qshader.h:188
@ Q3TCGEN_VECTOR
Definition r_qshader.h:104
@ Q3TCGEN_ENVIRONMENT
Definition r_qshader.h:102
@ Q3TCGEN_LIGHTMAP
Definition r_qshader.h:103
@ Q3TCGEN_TEXTURE
Definition r_qshader.h:101
#define Q3TEXTUREFLAG_CAMERA
Definition r_qshader.h:14
#define Q3TCGEN_MAXPARMS
Definition r_qshader.h:24
@ Q3ALPHAGEN_LIGHTINGSPECULAR
Definition r_qshader.h:88
@ Q3ALPHAGEN_ONEMINUSENTITY
Definition r_qshader.h:89
@ Q3ALPHAGEN_WAVE
Definition r_qshader.h:93
@ Q3ALPHAGEN_ONEMINUSVERTEX
Definition r_qshader.h:90
@ Q3ALPHAGEN_IDENTITY
Definition r_qshader.h:85
@ Q3ALPHAGEN_VERTEX
Definition r_qshader.h:92
@ Q3ALPHAGEN_PORTAL
Definition r_qshader.h:91
@ Q3ALPHAGEN_CONST
Definition r_qshader.h:86
@ Q3ALPHAGEN_ENTITY
Definition r_qshader.h:87
#define Q3DEFORM_MAXPARMS
Definition r_qshader.h:20
#define Q3TEXTUREFLAG_REFLECTION
Definition r_qshader.h:12
#define Q3TEXTUREFLAG_TWOSIDED
Definition r_qshader.h:8
#define Q3TEXTUREFLAG_REFRACTION
Definition r_qshader.h:11
float value
Definition cvar.h:74
char ** filenames
Definition fs.h:117
int numfilenames
Definition fs.h:116
memexpandablearray_t char_ptrs
memexpandablearray_t hash_entries
q3wavefunc_t wavefunc
Definition r_qshader.h:178
float parms[Q3DEFORM_MAXPARMS]
Definition r_qshader.h:177
float waveparms[Q3WAVEPARMS]
Definition r_qshader.h:179
qbool dpnortlight
Definition r_qshader.h:216
char name[Q3PATHLENGTH]
Definition r_qshader.h:200
float r_water_waterscroll[2]
Definition r_qshader.h:237
float biaspolygonfactor
Definition r_qshader.h:245
qbool dpnoshadow
Definition r_qshader.h:218
qbool vertexalpha
Definition r_qshader.h:207
q3shaderinfo_layer_t layers[Q3SHADER_MAXLAYERS]
Definition r_qshader.h:209
float offsetscale
Definition r_qshader.h:241
dptransparentsortcategory_t transparentsort
Definition r_qshader.h:248
vec4_t refractcolor4f
Definition r_qshader.h:233
q3shaderinfo_deform_t deforms[Q3MAXDEFORMS]
Definition r_qshader.h:211
float r_water_wateralpha
Definition r_qshader.h:236
char skyboxname[Q3PATHLENGTH]
Definition r_qshader.h:210
qbool dpshadow
Definition r_qshader.h:217
qbool lighting
Definition r_qshader.h:206
float reflectmin
Definition r_qshader.h:230
float reflectfactor
Definition r_qshader.h:234
dpoffsetmapping_technique_t offsetmapping
Definition r_qshader.h:240
char dpreflectcube[Q3PATHLENGTH]
Definition r_qshader.h:227
float specularscalemod
Definition r_qshader.h:251
qbool dpmeshcollisions
Definition r_qshader.h:221
float offsetbias
Definition r_qshader.h:242
vec4_t reflectcolor4f
Definition r_qshader.h:235
int textureflags
Definition r_qshader.h:204
qbool dpshaderkill
Definition r_qshader.h:224
int numlayers
Definition r_qshader.h:205
float specularpowermod
Definition r_qshader.h:252
int surfaceflags
Definition r_qshader.h:203
qbool textureblendalpha
Definition r_qshader.h:208
float refractfactor
Definition r_qshader.h:232
int surfaceparms
Definition r_qshader.h:202
float biaspolygonoffset
Definition r_qshader.h:245
float reflectmax
Definition r_qshader.h:231
float rtlightambient
Definition r_qshader.h:255
#define Mem_strdup(pool, s)
Definition zone.h:97

References shader_t::biaspolygonfactor, shader_t::biaspolygonoffset, q3shader_data_t::char_ptrs, COM_ParseToken_QuakeC(), com_token, Con_DPrint(), Con_DPrintf(), Con_Printf(), Cvar_VariableValue(), cvars_all, q3shaderinfo_deform_t::deform, shader_t::deforms, developer_insane, dp_strlcpy, shader_t::dpmeshcollisions, shader_t::dpnortlight, shader_t::dpnoshadow, shader_t::dpreflectcube, shader_t::dpshaderkill, shader_t::dpshadow, dpsnprintf(), q3shaderinfo_layer_t::dptexflags, f, fssearch_t::filenames, FS_FreeSearch(), FS_LoadFile(), FS_Search(), GL_DST_ALPHA, GL_DST_COLOR, GL_ONE, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_SRC_COLOR, GL_ZERO, q3shader_data_t::hash_entries, i, int(), cvar_t::integer, layer, shader_t::layers, shader_t::lighting, Mem_Alloc, Mem_AllocPool, Mem_ExpandableArray_AllocRecord(), Mem_ExpandableArray_NewArray(), Mem_Free, Mem_strdup, min, Mod_FreeQ3Shaders(), Mod_LoadQ3Shaders_EnumerateWaveFunc(), mod_q3shader_default_offsetmapping, mod_q3shader_default_offsetmapping_bias, mod_q3shader_default_offsetmapping_scale, mod_q3shader_default_polygonfactor, mod_q3shader_default_polygonoffset, mod_q3shader_force_addalpha, mod_q3shader_force_terrain_alphaflag, shader_t::name, NULL, fssearch_t::numfilenames, shader_t::numlayers, shader_t::offsetbias, shader_t::offsetmapping, OFFSETMAPPING_DEFAULT, OFFSETMAPPING_LINEAR, OFFSETMAPPING_OFF, OFFSETMAPPING_RELIEF, shader_t::offsetscale, q3shaderinfo_deform_t::parms, Q3ALPHAGEN_CONST, Q3ALPHAGEN_ENTITY, Q3ALPHAGEN_IDENTITY, Q3ALPHAGEN_LIGHTINGSPECULAR, Q3ALPHAGEN_MAXPARMS, Q3ALPHAGEN_ONEMINUSENTITY, Q3ALPHAGEN_ONEMINUSVERTEX, Q3ALPHAGEN_PORTAL, Q3ALPHAGEN_VERTEX, Q3ALPHAGEN_WAVE, Q3DEFORM_AUTOSPRITE, Q3DEFORM_AUTOSPRITE2, Q3DEFORM_BULGE, Q3DEFORM_MAXPARMS, Q3DEFORM_MOVE, Q3DEFORM_NONE, Q3DEFORM_NORMAL, Q3DEFORM_PROJECTIONSHADOW, Q3DEFORM_TEXT0, Q3DEFORM_TEXT1, Q3DEFORM_TEXT2, Q3DEFORM_TEXT3, Q3DEFORM_TEXT4, Q3DEFORM_TEXT5, Q3DEFORM_TEXT6, Q3DEFORM_TEXT7, Q3DEFORM_WAVE, Q3MAXDEFORMS, Q3MAXTCMODS, Q3PATHLENGTH, Q3RGBGEN_CONST, Q3RGBGEN_ENTITY, Q3RGBGEN_EXACTVERTEX, Q3RGBGEN_IDENTITY, Q3RGBGEN_IDENTITYLIGHTING, Q3RGBGEN_LIGHTINGDIFFUSE, Q3RGBGEN_MAXPARMS, Q3RGBGEN_ONEMINUSENTITY, Q3RGBGEN_ONEMINUSVERTEX, Q3RGBGEN_VERTEX, Q3RGBGEN_WAVE, Q3Shader_AddToHash(), q3shader_data, Q3SHADER_MAXLAYERS, q3shaders_mem, Q3SURFACEPARM_ALPHASHADOW, Q3SURFACEPARM_ANTIPORTAL, Q3SURFACEPARM_AREAPORTAL, Q3SURFACEPARM_BOTCLIP, Q3SURFACEPARM_CLUSTERPORTAL, Q3SURFACEPARM_DETAIL, Q3SURFACEPARM_DONOTENTER, Q3SURFACEPARM_DUST, Q3SURFACEPARM_FOG, Q3SURFACEPARM_HINT, Q3SURFACEPARM_LAVA, Q3SURFACEPARM_LIGHTFILTER, Q3SURFACEPARM_LIGHTGRID, Q3SURFACEPARM_METALSTEPS, Q3SURFACEPARM_NODAMAGE, Q3SURFACEPARM_NODLIGHT, Q3SURFACEPARM_NODRAW, Q3SURFACEPARM_NODROP, Q3SURFACEPARM_NOIMPACT, Q3SURFACEPARM_NOLIGHTMAP, Q3SURFACEPARM_NOMARKS, Q3SURFACEPARM_NOMIPMAPS, Q3SURFACEPARM_NONSOLID, Q3SURFACEPARM_ORIGIN, Q3SURFACEPARM_PLAYERCLIP, Q3SURFACEPARM_POINTLIGHT, Q3SURFACEPARM_SKY, Q3SURFACEPARM_SLICK, Q3SURFACEPARM_SLIME, Q3SURFACEPARM_STRUCTURAL, Q3SURFACEPARM_TRANS, Q3SURFACEPARM_WATER, Q3TCGEN_ENVIRONMENT, Q3TCGEN_LIGHTMAP, Q3TCGEN_MAXPARMS, Q3TCGEN_TEXTURE, Q3TCGEN_VECTOR, Q3TCMOD_ENTITYTRANSLATE, Q3TCMOD_MAXPARMS, Q3TCMOD_PAGE, Q3TCMOD_ROTATE, Q3TCMOD_SCALE, Q3TCMOD_SCROLL, Q3TCMOD_STRETCH, Q3TCMOD_TRANSFORM, Q3TCMOD_TURBULENT, Q3TEXTUREFLAG_CAMERA, Q3TEXTUREFLAG_NOPICMIP, Q3TEXTUREFLAG_POLYGONOFFSET, Q3TEXTUREFLAG_REFLECTION, Q3TEXTUREFLAG_REFRACTION, Q3TEXTUREFLAG_TRANSPARENTSORT, Q3TEXTUREFLAG_TWOSIDED, Q3TEXTUREFLAG_WATERSHADER, Q3WAVEPARMS, shader_t::r_water_wateralpha, shader_t::r_water_waterscroll, shader_t::reflectcolor4f, shader_t::reflectfactor, shader_t::reflectmax, shader_t::reflectmin, shader_t::refractcolor4f, shader_t::refractfactor, shader_t::rtlightambient, shader_t::skyboxname, shader_t::specularpowermod, shader_t::specularscalemod, strlen(), shader_t::surfaceflags, shader_t::surfaceparms, tempmempool, TEXF_ALPHA, TEXF_CLAMP, TEXF_COMPRESS, TEXF_MIPMAP, TEXF_PICMIP, TEXTURE_MAXFRAMES, shader_t::textureblendalpha, shader_t::textureflags, shader_t::transparentsort, TRANSPARENTSORT_DISTANCE, TRANSPARENTSORT_HUD, TRANSPARENTSORT_SKY, cvar_t::value, Vector4Set, shader_t::vertexalpha, q3shaderinfo_deform_t::wavefunc, and q3shaderinfo_deform_t::waveparms.

Referenced by Mod_LoadModel(), and Mod_LookupQ3Shader().

◆ Mod_LoadSkinFiles()

skinfile_t * Mod_LoadSkinFiles ( void )

Definition at line 2705 of file model_shared.c.

2706{
2707 int i, words, line, wordsoverflow;
2708 char *text;
2709 const char *data;
2710 skinfile_t *skinfile = NULL, *first = NULL;
2711 skinfileitem_t *skinfileitem;
2712 char word[10][MAX_QPATH];
2713 char vabuf[1024];
2714
2715/*
2716sample file:
2717U_bodyBox,models/players/Legoman/BikerA2.tga
2718U_RArm,models/players/Legoman/BikerA1.tga
2719U_LArm,models/players/Legoman/BikerA1.tga
2720U_armor,common/nodraw
2721U_sword,common/nodraw
2722U_shield,common/nodraw
2723U_homb,common/nodraw
2724U_backpack,common/nodraw
2725U_colcha,common/nodraw
2726tag_head,
2727tag_weapon,
2728tag_torso,
2729*/
2730 memset(word, 0, sizeof(word));
2731 for (i = 0;i < 256 && (data = text = (char *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s_%i.skin", loadmodel->name, i), tempmempool, true, NULL));i++)
2732 {
2733 // If it's the first file we parse
2734 if (skinfile == NULL)
2735 {
2736 skinfile = (skinfile_t *)Mem_Alloc(loadmodel->mempool, sizeof(skinfile_t));
2737 first = skinfile;
2738 }
2739 else
2740 {
2741 skinfile->next = (skinfile_t *)Mem_Alloc(loadmodel->mempool, sizeof(skinfile_t));
2742 skinfile = skinfile->next;
2743 }
2744 skinfile->next = NULL;
2745
2746 for(line = 0;;line++)
2747 {
2748 // parse line
2749 if (!COM_ParseToken_QuakeC(&data, true))
2750 break;
2751 if (!strcmp(com_token, "\n"))
2752 continue;
2753 words = 0;
2754 wordsoverflow = false;
2755 do
2756 {
2757 if (words < 10)
2758 dp_strlcpy(word[words++], com_token, sizeof (word[0]));
2759 else
2760 wordsoverflow = true;
2761 }
2762 while (COM_ParseToken_QuakeC(&data, true) && strcmp(com_token, "\n"));
2763 if (wordsoverflow)
2764 {
2765 Con_Printf("Mod_LoadSkinFiles: parsing error in file \"%s_%i.skin\" on line #%i: line with too many statements, skipping\n", loadmodel->name, i, line);
2766 continue;
2767 }
2768 // words is always >= 1
2769 if (!strcmp(word[0], "replace"))
2770 {
2771 if (words == 3)
2772 {
2774 Con_Printf("Mod_LoadSkinFiles: parsed mesh \"%s\" shader replacement \"%s\"\n", word[1], word[2]);
2775 skinfileitem = (skinfileitem_t *)Mem_Alloc(loadmodel->mempool, sizeof(skinfileitem_t));
2776 skinfileitem->next = skinfile->items;
2777 skinfile->items = skinfileitem;
2778 dp_strlcpy (skinfileitem->name, word[1], sizeof (skinfileitem->name));
2779 dp_strlcpy (skinfileitem->replacement, word[2], sizeof (skinfileitem->replacement));
2780 }
2781 else
2782 Con_Printf("Mod_LoadSkinFiles: parsing error in file \"%s_%i.skin\" on line #%i: wrong number of parameters to command \"%s\", see documentation in DP_GFX_SKINFILES extension in dpextensions.qc\n", loadmodel->name, i, line, word[0]);
2783 }
2784 else if (words >= 2 && !strncmp(word[0], "tag_", 4))
2785 {
2786 // tag name, like "tag_weapon,"
2787 // not used for anything (not even in Quake3)
2788 }
2789 else if (words >= 2 && !strcmp(word[1], ","))
2790 {
2791 // mesh shader name, like "U_RArm,models/players/Legoman/BikerA1.tga"
2793 Con_Printf("Mod_LoadSkinFiles: parsed mesh \"%s\" shader replacement \"%s\"\n", word[0], word[2]);
2794 skinfileitem = (skinfileitem_t *)Mem_Alloc(loadmodel->mempool, sizeof(skinfileitem_t));
2795 skinfileitem->next = skinfile->items;
2796 skinfile->items = skinfileitem;
2797 dp_strlcpy (skinfileitem->name, word[0], sizeof (skinfileitem->name));
2798 dp_strlcpy (skinfileitem->replacement, word[2], sizeof (skinfileitem->replacement));
2799 }
2800 else
2801 Con_Printf("Mod_LoadSkinFiles: parsing error in file \"%s_%i.skin\" on line #%i: does not look like tag or mesh specification, or replace command, see documentation in DP_GFX_SKINFILES extension in dpextensions.qc\n", loadmodel->name, i, line);
2802 }
2803 Mem_Free(text);
2804 }
2805 if (i)
2806 loadmodel->numskins = i;
2807 return first;
2808}
GLint first
Definition glquake.h:671

References COM_ParseToken_QuakeC(), com_token, Con_Printf(), data, developer_loading, dp_strlcpy, first, FS_LoadFile(), i, cvar_t::integer, skinfile_t::items, loadmodel, MAX_QPATH, Mem_Alloc, Mem_Free, model_t::mempool, model_t::name, skinfileitem_t::name, skinfile_t::next, skinfileitem_t::next, NULL, model_t::numskins, skinfileitem_t::replacement, tempmempool, and va().

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_LoadTextureFromQ3Shader()

qbool Mod_LoadTextureFromQ3Shader ( struct mempool_s * mempool,
const char * modelname,
texture_t * texture,
const char * name,
qbool warnmissing,
qbool fallback,
int defaulttexflags,
int defaultmaterialflags )

◆ Mod_LookupQ3Shader()

shader_t * Mod_LookupQ3Shader ( const char * name)

Definition at line 2219 of file model_shared.c.

2220{
2221 unsigned short hash;
2222 q3shader_hash_entry_t* entry;
2223 if (!q3shaders_mem)
2225 hash = CRC_Block_CaseInsensitive ((const unsigned char *)name, strlen (name));
2226 entry = q3shader_data->hash + (hash % Q3SHADER_HASH_SIZE);
2227 while (entry != NULL)
2228 {
2229 if (strcasecmp (entry->shader.name, name) == 0)
2230 return &entry->shader;
2231 entry = entry->chain;
2232 }
2233 return NULL;
2234}
unsigned short CRC_Block_CaseInsensitive(const unsigned char *data, size_t size)
Definition com_crc16.c:83
#define Q3SHADER_HASH_SIZE
q3shader_hash_entry_t hash[Q3SHADER_HASH_SIZE]
struct q3shader_hash_entry_s * chain
shader_t shader

References q3shader_hash_entry_t::chain, CRC_Block_CaseInsensitive(), q3shader_data_t::hash, Mod_LoadQ3Shaders(), name, shader_t::name, NULL, q3shader_data, Q3SHADER_HASH_SIZE, q3shaders_mem, q3shader_hash_entry_t::shader, and strlen().

Referenced by Mod_LoadTextureFromQ3Shader().

◆ Mod_MakeCollisionBIH()

bih_t * Mod_MakeCollisionBIH ( model_t * model,
qbool userendersurfaces,
bih_t * out )

Definition at line 7412 of file model_brush.c.

7413{
7414 int j;
7415 int bihnumleafs;
7416 int bihmaxnodes;
7417 int brushindex;
7418 int triangleindex;
7419 int bihleafindex;
7420 int nummodelbrushes = model->nummodelbrushes;
7421 const int *e;
7422 const int *collisionelement3i;
7423 const float *collisionvertex3f;
7424 const int *renderelement3i;
7425 const float *rendervertex3f;
7426 bih_leaf_t *bihleafs;
7427 bih_node_t *bihnodes;
7428 int *temp_leafsort;
7429 int *temp_leafsortscratch;
7430 const msurface_t *surface;
7431 const q3mbrush_t *brush;
7432
7433 // find out how many BIH leaf nodes we need
7434 bihnumleafs = 0;
7435 if (userendersurfaces)
7436 {
7437 for (j = model->submodelsurfaces_start;j < model->submodelsurfaces_end;j++)
7438 bihnumleafs += model->data_surfaces[j].num_triangles;
7439 }
7440 else
7441 {
7442 for (brushindex = 0, brush = model->brush.data_brushes + brushindex+model->firstmodelbrush;brushindex < nummodelbrushes;brushindex++, brush++)
7443 if (brush->colbrushf)
7444 bihnumleafs++;
7445 for (j = model->submodelsurfaces_start;j < model->submodelsurfaces_end;j++)
7446 {
7447 if (model->data_surfaces[j].texture->basematerialflags & MATERIALFLAG_MESHCOLLISIONS)
7448 bihnumleafs += model->data_surfaces[j].num_triangles + model->data_surfaces[j].num_collisiontriangles;
7449 else
7450 bihnumleafs += model->data_surfaces[j].num_collisiontriangles;
7451 }
7452 }
7453
7454 if (!bihnumleafs)
7455 return NULL;
7456
7457 // allocate the memory for the BIH leaf nodes
7458 bihleafs = (bih_leaf_t *)Mem_Alloc(loadmodel->mempool, sizeof(bih_leaf_t) * bihnumleafs);
7459
7460 // now populate the BIH leaf nodes
7461 bihleafindex = 0;
7462
7463 // add render surfaces
7464 renderelement3i = model->surfmesh.data_element3i;
7465 rendervertex3f = model->surfmesh.data_vertex3f;
7466 for (j = model->submodelsurfaces_start; j < model->submodelsurfaces_end; j++)
7467 {
7468 surface = model->data_surfaces + j;
7469 for (triangleindex = 0, e = renderelement3i + 3*surface->num_firsttriangle;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7470 {
7471 if (!userendersurfaces && !(surface->texture->basematerialflags & MATERIALFLAG_MESHCOLLISIONS))
7472 continue;
7473 bihleafs[bihleafindex].type = BIH_RENDERTRIANGLE;
7474 bihleafs[bihleafindex].textureindex = surface->texture - model->data_textures;
7475 bihleafs[bihleafindex].surfaceindex = surface - model->data_surfaces;
7476 bihleafs[bihleafindex].itemindex = triangleindex+surface->num_firsttriangle;
7477 bihleafs[bihleafindex].mins[0] = min(rendervertex3f[3*e[0]+0], min(rendervertex3f[3*e[1]+0], rendervertex3f[3*e[2]+0])) - 1;
7478 bihleafs[bihleafindex].mins[1] = min(rendervertex3f[3*e[0]+1], min(rendervertex3f[3*e[1]+1], rendervertex3f[3*e[2]+1])) - 1;
7479 bihleafs[bihleafindex].mins[2] = min(rendervertex3f[3*e[0]+2], min(rendervertex3f[3*e[1]+2], rendervertex3f[3*e[2]+2])) - 1;
7480 bihleafs[bihleafindex].maxs[0] = max(rendervertex3f[3*e[0]+0], max(rendervertex3f[3*e[1]+0], rendervertex3f[3*e[2]+0])) + 1;
7481 bihleafs[bihleafindex].maxs[1] = max(rendervertex3f[3*e[0]+1], max(rendervertex3f[3*e[1]+1], rendervertex3f[3*e[2]+1])) + 1;
7482 bihleafs[bihleafindex].maxs[2] = max(rendervertex3f[3*e[0]+2], max(rendervertex3f[3*e[1]+2], rendervertex3f[3*e[2]+2])) + 1;
7483 bihleafindex++;
7484 }
7485 }
7486
7487 if (!userendersurfaces)
7488 {
7489 // add collision brushes
7490 for (brushindex = 0, brush = model->brush.data_brushes + brushindex+model->firstmodelbrush;brushindex < nummodelbrushes;brushindex++, brush++)
7491 {
7492 if (!brush->colbrushf)
7493 continue;
7494 bihleafs[bihleafindex].type = BIH_BRUSH;
7495 bihleafs[bihleafindex].textureindex = brush->texture - model->data_textures;
7496 bihleafs[bihleafindex].surfaceindex = -1;
7497 bihleafs[bihleafindex].itemindex = brushindex+model->firstmodelbrush;
7498 VectorCopy(brush->colbrushf->mins, bihleafs[bihleafindex].mins);
7499 VectorCopy(brush->colbrushf->maxs, bihleafs[bihleafindex].maxs);
7500 bihleafindex++;
7501 }
7502
7503 // add collision surfaces
7504 collisionelement3i = model->brush.data_collisionelement3i;
7505 collisionvertex3f = model->brush.data_collisionvertex3f;
7506 for (j = model->submodelsurfaces_start; j < model->submodelsurfaces_end; j++)
7507 {
7508 surface = model->data_surfaces + j;
7509 for (triangleindex = 0, e = collisionelement3i + 3*surface->num_firstcollisiontriangle;triangleindex < surface->num_collisiontriangles;triangleindex++, e += 3)
7510 {
7511 bihleafs[bihleafindex].type = BIH_COLLISIONTRIANGLE;
7512 bihleafs[bihleafindex].textureindex = surface->texture - model->data_textures;
7513 bihleafs[bihleafindex].surfaceindex = surface - model->data_surfaces;
7514 bihleafs[bihleafindex].itemindex = triangleindex+surface->num_firstcollisiontriangle;
7515 bihleafs[bihleafindex].mins[0] = min(collisionvertex3f[3*e[0]+0], min(collisionvertex3f[3*e[1]+0], collisionvertex3f[3*e[2]+0])) - 1;
7516 bihleafs[bihleafindex].mins[1] = min(collisionvertex3f[3*e[0]+1], min(collisionvertex3f[3*e[1]+1], collisionvertex3f[3*e[2]+1])) - 1;
7517 bihleafs[bihleafindex].mins[2] = min(collisionvertex3f[3*e[0]+2], min(collisionvertex3f[3*e[1]+2], collisionvertex3f[3*e[2]+2])) - 1;
7518 bihleafs[bihleafindex].maxs[0] = max(collisionvertex3f[3*e[0]+0], max(collisionvertex3f[3*e[1]+0], collisionvertex3f[3*e[2]+0])) + 1;
7519 bihleafs[bihleafindex].maxs[1] = max(collisionvertex3f[3*e[0]+1], max(collisionvertex3f[3*e[1]+1], collisionvertex3f[3*e[2]+1])) + 1;
7520 bihleafs[bihleafindex].maxs[2] = max(collisionvertex3f[3*e[0]+2], max(collisionvertex3f[3*e[1]+2], collisionvertex3f[3*e[2]+2])) + 1;
7521 bihleafindex++;
7522 }
7523 }
7524 }
7525
7526 // allocate buffers for the produced and temporary data
7527 bihmaxnodes = bihnumleafs + 1;
7528 bihnodes = (bih_node_t *)Mem_Alloc(loadmodel->mempool, sizeof(bih_node_t) * bihmaxnodes);
7529 temp_leafsort = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int) * bihnumleafs * 2);
7530 temp_leafsortscratch = temp_leafsort + bihnumleafs;
7531
7532 // now build it
7533 BIH_Build(out, bihnumleafs, bihleafs, bihmaxnodes, bihnodes, temp_leafsort, temp_leafsortscratch);
7534
7535 // we're done with the temporary data
7536 Mem_Free(temp_leafsort);
7537
7538 // resize the BIH nodes array if it over-allocated
7539 if (out->maxnodes > out->numnodes)
7540 {
7541 out->maxnodes = out->numnodes;
7542 out->nodes = (bih_node_t *)Mem_Realloc(loadmodel->mempool, out->nodes, out->numnodes * sizeof(bih_node_t));
7543 }
7544
7545 return out;
7546}
int BIH_Build(bih_t *bih, int numleafs, bih_leaf_t *leafs, int maxnodes, bih_node_t *nodes, int *temp_leafsort, int *temp_leafsortscratch)
Definition bih.c:133
@ BIH_COLLISIONTRIANGLE
Definition bih.h:30
@ BIH_RENDERTRIANGLE
Definition bih.h:31
@ BIH_BRUSH
Definition bih.h:29
#define MATERIALFLAG_MESHCOLLISIONS
Definition model_brush.h:77
int textureindex
Definition bih.h:63
float maxs[3]
Definition bih.h:61
bih_leaftype_t type
Definition bih.h:59
int surfaceindex
Definition bih.h:64
int itemindex
Definition bih.h:65
float mins[3]
Definition bih.h:60
bih_node_t * nodes
Definition bih.h:77
int maxnodes
Definition bih.h:84
int numnodes
Definition bih.h:76
int num_firstcollisiontriangle
mesh information for collisions (only used by q3bsp curves)
struct colbrushf_s * colbrushf
struct texture_s * texture
int basematerialflags
#define Mem_Realloc(pool, data, size)
Definition zone.h:94

References texture_t::basematerialflags, BIH_BRUSH, BIH_Build(), BIH_COLLISIONTRIANGLE, BIH_RENDERTRIANGLE, q3mbrush_t::colbrushf, bih_leaf_t::itemindex, loadmodel, MATERIALFLAG_MESHCOLLISIONS, max, bih_t::maxnodes, bih_leaf_t::maxs, Mem_Alloc, Mem_Free, Mem_Realloc, model_t::mempool, min, bih_leaf_t::mins, model, bih_t::nodes, NULL, msurface_t::num_firstcollisiontriangle, msurface_t::num_firsttriangle, bih_t::numnodes, bih_leaf_t::surfaceindex, msurface_t::texture, q3mbrush_t::texture, bih_leaf_t::textureindex, bih_leaf_t::type, and VectorCopy.

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

◆ Mod_MakeSortedSurfaces()

void Mod_MakeSortedSurfaces ( model_t * mod)

Definition at line 2936 of file model_shared.c.

2937{
2938 // make an optimal set of texture-sorted batches to draw...
2939 int j, k;
2941
2942 if(cls.state == ca_dedicated)
2943 return;
2944
2945 info = (Mod_MakeSortedSurfaces_qsortsurface_t*)Mem_Alloc(loadmodel->mempool, mod->num_surfaces * sizeof(*info));
2946 if (!mod->modelsurfaces_sorted)
2947 mod->modelsurfaces_sorted = (int *) Mem_Alloc(loadmodel->mempool, mod->num_surfaces * sizeof(*mod->modelsurfaces_sorted));
2948 // the goal is to sort by submodel (can't change which submodel a surface belongs to), and then by effects and textures
2949 for (j = 0; j < mod->num_surfaces; j++)
2950 {
2951 info[j].surfaceindex = j;
2952 info[j].effect = mod->data_surfaces[j].effect;
2953 info[j].texture = mod->data_surfaces[j].texture;
2954 info[j].lightmaptexture = mod->data_surfaces[j].lightmaptexture;
2955 }
2956 for (k = 0; k < mod->brush.numsubmodels; k++)
2957 if (mod->brush.submodels[k]->submodelsurfaces_end > mod->brush.submodels[k]->submodelsurfaces_start + 1)
2958 qsort(info + mod->brush.submodels[k]->submodelsurfaces_start, (size_t)mod->brush.submodels[k]->submodelsurfaces_end - mod->brush.submodels[k]->submodelsurfaces_start, sizeof(*info), Mod_MakeSortedSurfaces_qsortfunc);
2959 for (j = 0; j < mod->num_surfaces; j++)
2960 mod->modelsurfaces_sorted[j] = info[j].surfaceindex;
2961 Mem_Free(info);
2962}
static int Mod_MakeSortedSurfaces_qsortfunc(const void *a, const void *b)

References ca_dedicated, cls, Mod_MakeSortedSurfaces_qsortsurface_t::effect, Mod_MakeSortedSurfaces_qsortsurface_t::lightmaptexture, loadmodel, Mem_Alloc, Mem_Free, model_t::mempool, mod(), Mod_MakeSortedSurfaces_qsortfunc(), client_static_t::state, Mod_MakeSortedSurfaces_qsortsurface_t::surfaceindex, and Mod_MakeSortedSurfaces_qsortsurface_t::texture.

Referenced by Mod_DARKPLACESMODEL_Load(), Mod_IDP3_Load(), Mod_INTERQUAKEMODEL_Load(), Mod_OBJ_Load(), Mod_PSKMODEL_Load(), Mod_Q1BSP_Load(), Mod_Q2BSP_Load(), Mod_Q3BSP_Load(), and Mod_ZYMOTICMODEL_Load().

◆ Mod_MAP_Load()

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

Definition at line 8399 of file model_brush.c.

8400{
8401 Host_Error("Mod_MAP_Load: not yet implemented");
8402}

References Host_Error().

◆ Mod_Mesh_AddSurface()

msurface_t * Mod_Mesh_AddSurface ( model_t * mod,
texture_t * tex,
qbool batchwithprevioussurface )

Definition at line 4528 of file model_shared.c.

4529{
4530 msurface_t *surf;
4531 // batch if possible; primarily useful for UI rendering where bounding boxes don't matter
4532 if (batchwithprevioussurface && mod->num_surfaces > 0 && mod->data_surfaces[mod->num_surfaces - 1].texture == tex)
4533 return mod->data_surfaces + mod->num_surfaces - 1;
4534 // create new surface
4535 if (mod->max_surfaces == mod->num_surfaces)
4536 {
4537 mod->max_surfaces = 2 * max(mod->num_surfaces, 64);
4538 mod->data_surfaces = (msurface_t *)Mem_Realloc(mod->mempool, mod->data_surfaces, mod->max_surfaces * sizeof(*mod->data_surfaces));
4539 mod->modelsurfaces_sorted = (int *)Mem_Realloc(mod->mempool, mod->modelsurfaces_sorted, mod->max_surfaces * sizeof(*mod->modelsurfaces_sorted));
4540 }
4541 surf = mod->data_surfaces + mod->num_surfaces;
4542 mod->num_surfaces++;
4543 memset(surf, 0, sizeof(*surf));
4544 surf->texture = tex;
4545 surf->num_firsttriangle = mod->surfmesh.num_triangles;
4546 surf->num_firstvertex = mod->surfmesh.num_vertices;
4548 mod->DrawSky = R_Mod_DrawSky;
4550 mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
4551 return surf;
4552}
void R_Mod_DrawSky(entity_render_t *ent)
Definition gl_rsurf.c:596
void R_Mod_DrawAddWaterPlanes(entity_render_t *ent)
Definition gl_rsurf.c:603
#define MATERIALFLAG_SKY
Definition model_brush.h:92
#define MATERIALFLAG_REFRACTION
#define MATERIALFLAG_WATERSHADER
#define MATERIALFLAG_CAMERA
#define MATERIALFLAG_REFLECTION

References texture_t::basematerialflags, MATERIALFLAG_CAMERA, MATERIALFLAG_REFLECTION, MATERIALFLAG_REFRACTION, MATERIALFLAG_SKY, MATERIALFLAG_WATERSHADER, max, Mem_Realloc, mod(), msurface_t::num_firsttriangle, msurface_t::num_firstvertex, R_Mod_DrawAddWaterPlanes(), R_Mod_DrawSky(), and msurface_t::texture.

Referenced by CL_Beam_AddPolygons(), DrawQ_Line(), DrawQ_Pic(), DrawQ_RotPic(), DrawQ_String_Scale(), DrawQ_SuperPic(), R_DebugLine(), and VM_CL_R_PolygonEnd().

◆ Mod_Mesh_AddTriangle()

void Mod_Mesh_AddTriangle ( model_t * mod,
msurface_t * surf,
int e0,
int e1,
int e2 )

Definition at line 4633 of file model_shared.c.

4634{
4635 surfmesh_t *mesh = &mod->surfmesh;
4636 if (mesh->max_triangles == mesh->num_triangles)
4637 {
4638 mesh->max_triangles = 2 * max(mesh->num_triangles, 128);
4639 mesh->data_element3s = (unsigned short *)Mem_Realloc(mod->mempool, mesh->data_element3s, mesh->max_triangles * sizeof(unsigned short[3]));
4640 mesh->data_element3i = (int *)Mem_Realloc(mod->mempool, mesh->data_element3i, mesh->max_triangles * sizeof(int[3]));
4641 }
4642 mesh->data_element3s[mesh->num_triangles * 3 + 0] = e0;
4643 mesh->data_element3s[mesh->num_triangles * 3 + 1] = e1;
4644 mesh->data_element3s[mesh->num_triangles * 3 + 2] = e2;
4645 mesh->data_element3i[mesh->num_triangles * 3 + 0] = e0;
4646 mesh->data_element3i[mesh->num_triangles * 3 + 1] = e1;
4647 mesh->data_element3i[mesh->num_triangles * 3 + 2] = e2;
4648 mesh->num_triangles++;
4649 surf->num_triangles++;
4650}

References surfmesh_t::data_element3i, surfmesh_t::data_element3s, max, surfmesh_t::max_triangles, Mem_Realloc, mod(), msurface_t::num_triangles, and surfmesh_t::num_triangles.

Referenced by CL_Beam_AddQuad(), DrawQ_Line(), DrawQ_Pic(), DrawQ_RotPic(), DrawQ_String_Scale(), DrawQ_SuperPic(), R_DebugLine(), and VM_CL_R_PolygonEnd().

◆ Mod_Mesh_Create()

void Mod_Mesh_Create ( model_t * mod,
const char * name )

Definition at line 4443 of file model_shared.c.

4444{
4445 memset(mod, 0, sizeof(*mod));
4446 dp_strlcpy(mod->name, name, sizeof(mod->name));
4447 mod->mempool = Mem_AllocPool(name, 0, NULL);
4448 mod->texturepool = R_AllocTexturePool();
4449 mod->Draw = R_Mod_Draw;
4450 mod->DrawDepth = R_Mod_DrawDepth;
4451 mod->DrawDebug = R_Mod_DrawDebug;
4452 mod->DrawPrepass = R_Mod_DrawPrepass;
4453 mod->GetLightInfo = R_Mod_GetLightInfo;
4454 mod->DrawShadowMap = R_Mod_DrawShadowMap;
4455 mod->DrawLight = R_Mod_DrawLight;
4456}
void R_Mod_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, unsigned char *outleafpvs, int *outnumleafspointer, int *outsurfacelist, unsigned char *outsurfacepvs, int *outnumsurfacespointer, unsigned char *outshadowtrispvs, unsigned char *outlighttrispvs, unsigned char *visitingleafpvs, int numfrustumplanes, const mplane_t *frustumplanes, qbool noocclusion)
Definition gl_rsurf.c:1202
rtexturepool_t * R_AllocTexturePool(void)

References dp_strlcpy, Mem_AllocPool, mod(), name, NULL, R_AllocTexturePool(), R_Mod_Draw(), R_Mod_DrawDebug(), R_Mod_DrawDepth(), R_Mod_DrawLight(), R_Mod_DrawPrepass(), R_Mod_DrawShadowMap(), and R_Mod_GetLightInfo().

Referenced by CL_MeshEntities_Init(), CL_MeshEntities_Restart(), and CL_MeshEntities_Start().

◆ Mod_Mesh_Destroy()

void Mod_Mesh_Destroy ( model_t * mod)

Definition at line 4458 of file model_shared.c.

4459{
4461}

References mod(), and Mod_UnloadModel().

Referenced by CL_MeshEntities_Restart(), and CL_MeshEntities_Shutdown().

◆ Mod_Mesh_Finalize()

void Mod_Mesh_Finalize ( model_t * mod)

Definition at line 4775 of file model_shared.c.

4776{
4777 if (gl_paranoid.integer)
4782 Mod_BuildTextureVectorsFromNormals(0, mod->surfmesh.num_vertices, mod->surfmesh.num_triangles, mod->surfmesh.data_vertex3f, mod->surfmesh.data_texcoordtexture2f, mod->surfmesh.data_normal3f, mod->surfmesh.data_element3i, mod->surfmesh.data_svector3f, mod->surfmesh.data_tvector3f, true);
4784}
r_refdef_t r_refdef
Definition gl_rmain.c:57
static void Mod_Mesh_ComputeBounds(model_t *mod)
void Mod_Mesh_Validate(model_t *mod)
static void Mod_Mesh_UploadDynamicBuffers(model_t *mod)
static void Mod_Mesh_MakeSortedSurfaces(model_t *mod)
int draw2dstage
Definition render.h:452

References r_refdef_t::draw2dstage, gl_paranoid, cvar_t::integer, mod(), Mod_BuildTextureVectorsFromNormals(), Mod_Mesh_ComputeBounds(), Mod_Mesh_MakeSortedSurfaces(), Mod_Mesh_UploadDynamicBuffers(), Mod_Mesh_Validate(), and r_refdef.

Referenced by CL_MeshEntities_Scene_FinalizeRenderEntity(), and DrawQ_FlushUI().

◆ Mod_Mesh_GetTexture()

texture_t * Mod_Mesh_GetTexture ( model_t * mod,
const char * name,
int defaultdrawflags,
int defaulttexflags,
int defaultmaterialflags )

Definition at line 4476 of file model_shared.c.

4477{
4478 int i;
4479 texture_t *t;
4480 int drawflag = defaultdrawflags & DRAWFLAG_MASK;
4481 for (i = 0, t = mod->data_textures; i < mod->num_textures; i++, t++)
4482 if (!strcmp(t->name, name) && t->mesh_drawflag == drawflag && t->mesh_defaulttexflags == defaulttexflags && t->mesh_defaultmaterialflags == defaultmaterialflags)
4483 return t;
4484 if (mod->max_textures <= mod->num_textures)
4485 {
4486 texture_t *oldtextures = mod->data_textures;
4487 mod->max_textures = max(mod->max_textures * 2, 1024);
4488 mod->data_textures = (texture_t *)Mem_Realloc(mod->mempool, mod->data_textures, mod->max_textures * sizeof(*mod->data_textures));
4489 // update the pointers
4490 for (i = 0; i < mod->num_surfaces; i++)
4491 mod->data_surfaces[i].texture = mod->data_textures + (mod->data_surfaces[i].texture - oldtextures);
4492 }
4493 t = &mod->data_textures[mod->num_textures++];
4494 Mod_LoadTextureFromQ3Shader(mod->mempool, mod->name, t, name, true, true, defaulttexflags, defaultmaterialflags);
4495 t->mesh_drawflag = drawflag;
4496 t->mesh_defaulttexflags = defaulttexflags;
4497 t->mesh_defaultmaterialflags = defaultmaterialflags;
4498 switch (defaultdrawflags & DRAWFLAG_MASK)
4499 {
4500 case DRAWFLAG_ADDITIVE:
4503 break;
4504 case DRAWFLAG_MODULATE:
4508 t->customblendfunc[1] = GL_ZERO;
4509 break;
4515 break;
4516 case DRAWFLAG_SCREEN:
4520 t->customblendfunc[1] = GL_ONE;
4521 break;
4522 default:
4523 break;
4524 }
4525 return t;
4526}
const float DRAWFLAG_ADDITIVE
const float DRAWFLAG_2XMODULATE
const float DRAWFLAG_SCREEN
const float DRAWFLAG_MODULATE
@ DRAWFLAG_MASK
Definition draw.h:80
#define MATERIALFLAG_ADD
Definition model_brush.h:81
#define MATERIALFLAG_BLENDED
#define MATERIALFLAG_CUSTOMBLEND
int currentmaterialflags
int mesh_drawflag
int mesh_defaulttexflags
int mesh_defaultmaterialflags
int customblendfunc[2]

References texture_t::basematerialflags, texture_t::currentmaterialflags, texture_t::customblendfunc, DRAWFLAG_2XMODULATE, DRAWFLAG_ADDITIVE, DRAWFLAG_MASK, DRAWFLAG_MODULATE, DRAWFLAG_SCREEN, GL_DST_COLOR, GL_ONE, GL_ONE_MINUS_DST_COLOR, GL_SRC_COLOR, GL_ZERO, i, MATERIALFLAG_ADD, MATERIALFLAG_BLENDED, MATERIALFLAG_CUSTOMBLEND, max, Mem_Realloc, texture_t::mesh_defaultmaterialflags, texture_t::mesh_defaulttexflags, texture_t::mesh_drawflag, mod(), Mod_LoadTextureFromQ3Shader(), name, and texture_t::name.

Referenced by DrawQ_Line(), DrawQ_Pic(), DrawQ_RotPic(), DrawQ_String_Scale(), DrawQ_SuperPic(), R_DebugLine(), and VM_CL_R_PolygonEnd().

◆ Mod_Mesh_IndexForVertex()

int Mod_Mesh_IndexForVertex ( model_t * mod,
msurface_t * surf,
float x,
float y,
float z,
float nx,
float ny,
float nz,
float s,
float t,
float u,
float v,
float r,
float g,
float b,
float a )

Definition at line 4554 of file model_shared.c.

4555{
4556 int hashindex, h, vnum, mask;
4557 surfmesh_t *mesh = &mod->surfmesh;
4558 if (mesh->max_vertices == mesh->num_vertices)
4559 {
4560 mesh->max_vertices = max(mesh->num_vertices * 2, 256);
4561 mesh->data_vertex3f = (float *)Mem_Realloc(mod->mempool, mesh->data_vertex3f, mesh->max_vertices * sizeof(float[3]));
4562 mesh->data_svector3f = (float *)Mem_Realloc(mod->mempool, mesh->data_svector3f, mesh->max_vertices * sizeof(float[3]));
4563 mesh->data_tvector3f = (float *)Mem_Realloc(mod->mempool, mesh->data_tvector3f, mesh->max_vertices * sizeof(float[3]));
4564 mesh->data_normal3f = (float *)Mem_Realloc(mod->mempool, mesh->data_normal3f, mesh->max_vertices * sizeof(float[3]));
4565 mesh->data_texcoordtexture2f = (float *)Mem_Realloc(mod->mempool, mesh->data_texcoordtexture2f, mesh->max_vertices * sizeof(float[2]));
4566 mesh->data_texcoordlightmap2f = (float *)Mem_Realloc(mod->mempool, mesh->data_texcoordlightmap2f, mesh->max_vertices * sizeof(float[2]));
4567 mesh->data_lightmapcolor4f = (float *)Mem_Realloc(mod->mempool, mesh->data_lightmapcolor4f, mesh->max_vertices * sizeof(float[4]));
4568 // rebuild the hash table
4569 mesh->num_vertexhashsize = 4 * mesh->max_vertices;
4570 mesh->num_vertexhashsize &= ~(mesh->num_vertexhashsize - 1); // round down to pow2
4571 mesh->data_vertexhash = (int *)Mem_Realloc(mod->mempool, mesh->data_vertexhash, mesh->num_vertexhashsize * sizeof(*mesh->data_vertexhash));
4572 memset(mesh->data_vertexhash, -1, mesh->num_vertexhashsize * sizeof(*mesh->data_vertexhash));
4573 mask = mod->surfmesh.num_vertexhashsize - 1;
4574 // no need to hash the vertices for the entire model, the latest surface will suffice.
4575 for (vnum = surf ? surf->num_firstvertex : 0; vnum < mesh->num_vertices; vnum++)
4576 {
4577 // this uses prime numbers intentionally for computing the hash
4578 hashindex = (unsigned int)(mesh->data_vertex3f[vnum * 3 + 0] * 2003 + mesh->data_vertex3f[vnum * 3 + 1] * 4001 + mesh->data_vertex3f[vnum * 3 + 2] * 7919 + mesh->data_normal3f[vnum * 3 + 0] * 4097 + mesh->data_normal3f[vnum * 3 + 1] * 257 + mesh->data_normal3f[vnum * 3 + 2] * 17) & mask;
4579 for (h = hashindex; mesh->data_vertexhash[h] >= 0; h = (h + 1) & mask)
4580 ; // just iterate until we find the terminator
4581 mesh->data_vertexhash[h] = vnum;
4582 }
4583 }
4584 mask = mod->surfmesh.num_vertexhashsize - 1;
4585 // this uses prime numbers intentionally for computing the hash
4586 hashindex = (unsigned int)(x * 2003 + y * 4001 + z * 7919 + nx * 4097 + ny * 257 + nz * 17) & mask;
4587 // when possible find an identical vertex within the same surface and return it
4588 for(h = hashindex;(vnum = mesh->data_vertexhash[h]) >= 0;h = (h + 1) & mask)
4589 {
4590 if (vnum >= surf->num_firstvertex
4591 && mesh->data_vertex3f[vnum * 3 + 0] == x && mesh->data_vertex3f[vnum * 3 + 1] == y && mesh->data_vertex3f[vnum * 3 + 2] == z
4592 && mesh->data_normal3f[vnum * 3 + 0] == nx && mesh->data_normal3f[vnum * 3 + 1] == ny && mesh->data_normal3f[vnum * 3 + 2] == nz
4593 && mesh->data_texcoordtexture2f[vnum * 2 + 0] == s && mesh->data_texcoordtexture2f[vnum * 2 + 1] == t
4594 && mesh->data_texcoordlightmap2f[vnum * 2 + 0] == u && mesh->data_texcoordlightmap2f[vnum * 2 + 1] == v
4595 && mesh->data_lightmapcolor4f[vnum * 4 + 0] == r && mesh->data_lightmapcolor4f[vnum * 4 + 1] == g && mesh->data_lightmapcolor4f[vnum * 4 + 2] == b && mesh->data_lightmapcolor4f[vnum * 4 + 3] == a)
4596 return vnum;
4597 }
4598 // add the new vertex
4599 vnum = mesh->num_vertices++;
4600 if (surf->num_vertices > 0)
4601 {
4602 if (surf->mins[0] > x) surf->mins[0] = x;
4603 if (surf->mins[1] > y) surf->mins[1] = y;
4604 if (surf->mins[2] > z) surf->mins[2] = z;
4605 if (surf->maxs[0] < x) surf->maxs[0] = x;
4606 if (surf->maxs[1] < y) surf->maxs[1] = y;
4607 if (surf->maxs[2] < z) surf->maxs[2] = z;
4608 }
4609 else
4610 {
4611 VectorSet(surf->mins, x, y, z);
4612 VectorSet(surf->maxs, x, y, z);
4613 }
4614 surf->num_vertices = mesh->num_vertices - surf->num_firstvertex;
4615 mesh->data_vertexhash[h] = vnum;
4616 mesh->data_vertex3f[vnum * 3 + 0] = x;
4617 mesh->data_vertex3f[vnum * 3 + 1] = y;
4618 mesh->data_vertex3f[vnum * 3 + 2] = z;
4619 mesh->data_normal3f[vnum * 3 + 0] = nx;
4620 mesh->data_normal3f[vnum * 3 + 1] = ny;
4621 mesh->data_normal3f[vnum * 3 + 2] = nz;
4622 mesh->data_texcoordtexture2f[vnum * 2 + 0] = s;
4623 mesh->data_texcoordtexture2f[vnum * 2 + 1] = t;
4624 mesh->data_texcoordlightmap2f[vnum * 2 + 0] = u;
4625 mesh->data_texcoordlightmap2f[vnum * 2 + 1] = v;
4626 mesh->data_lightmapcolor4f[vnum * 4 + 0] = r;
4627 mesh->data_lightmapcolor4f[vnum * 4 + 1] = g;
4628 mesh->data_lightmapcolor4f[vnum * 4 + 2] = b;
4629 mesh->data_lightmapcolor4f[vnum * 4 + 3] = a;
4630 return vnum;
4631}
GLubyte GLubyte GLubyte z
Definition glquake.h:782
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
Definition glquake.h:609
dp_FragColor r
dp_FragColor g
dp_FragColor b
ret a
vec3_t mins
bounding box for onscreen checks
int * data_vertexhash
int num_vertexhashsize

References a, b, surfmesh_t::data_lightmapcolor4f, surfmesh_t::data_normal3f, surfmesh_t::data_svector3f, surfmesh_t::data_texcoordlightmap2f, surfmesh_t::data_texcoordtexture2f, surfmesh_t::data_tvector3f, surfmesh_t::data_vertex3f, surfmesh_t::data_vertexhash, g, int(), mask, max, surfmesh_t::max_vertices, msurface_t::maxs, Mem_Realloc, msurface_t::mins, mod(), msurface_t::num_firstvertex, surfmesh_t::num_vertexhashsize, msurface_t::num_vertices, surfmesh_t::num_vertices, r, v, VectorSet, x, y, and z.

Referenced by CL_Beam_AddQuad(), DrawQ_Line(), DrawQ_Pic(), DrawQ_RotPic(), DrawQ_String_Scale(), DrawQ_SuperPic(), R_DebugLine(), and VM_CL_R_PolygonEnd().

◆ Mod_Mesh_Reset()

void Mod_Mesh_Reset ( model_t * mod)

Definition at line 4465 of file model_shared.c.

4466{
4467 mod->num_surfaces = 0;
4468 mod->surfmesh.num_vertices = 0;
4469 mod->surfmesh.num_triangles = 0;
4470 if (mod->surfmesh.data_vertexhash) // UBSan: memset arg 1 isn't allowed to be null, but sometimes this is NULL.
4471 memset(mod->surfmesh.data_vertexhash, -1, mod->surfmesh.num_vertexhashsize * sizeof(*mod->surfmesh.data_vertexhash));
4472 mod->DrawSky = NULL; // will be set if a texture needs it
4473 mod->DrawAddWaterPlanes = NULL; // will be set if a texture needs it
4474}

References mod(), and NULL.

Referenced by CL_MeshEntities_Scene_Clear(), and DrawQ_FlushUI().

◆ Mod_Mesh_Validate()

void Mod_Mesh_Validate ( model_t * mod)

Definition at line 4736 of file model_shared.c.

4737{
4738 int i;
4739 qbool warned = false;
4740 for (i = 0; i < mod->num_surfaces; i++)
4741 {
4742 msurface_t *surf = mod->data_surfaces + i;
4743 int *e = mod->surfmesh.data_element3i + surf->num_firsttriangle * 3;
4744 int first = surf->num_firstvertex;
4745 int end = surf->num_firstvertex + surf->num_vertices;
4746 int j;
4747 for (j = 0;j < surf->num_triangles * 3;j++)
4748 {
4749 if (e[j] < first || e[j] >= end)
4750 {
4751 if (!warned)
4752 Con_DPrintf(CON_WARN "Mod_Mesh_Validate: detected corrupt surface - debug me!\n");
4753 warned = true;
4754 e[j] = first;
4755 }
4756 }
4757 }
4758}

References Con_DPrintf(), CON_WARN, first, i, mod(), msurface_t::num_firsttriangle, msurface_t::num_firstvertex, msurface_t::num_triangles, and msurface_t::num_vertices.

Referenced by Mod_Mesh_Finalize().

◆ Mod_OBJ_Load()

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

Definition at line 8417 of file model_brush.c.

8418{
8419 const char *textbase = (char *)buffer, *text = textbase;
8420 char *s;
8421 char *argv[512];
8422 char line[1024];
8423 char materialname[MAX_QPATH];
8424 int i, j, l, numvertices, firstvertex, firsttriangle, elementindex, vertexindex, surfacevertices, surfacetriangles, surfaceelements, submodelindex = 0;
8425 int index1, index2, index3;
8426 objvertex_t vfirst, vprev, vcurrent;
8427 int argc;
8428 int linelen;
8429 int numtriangles = 0;
8430 int maxtriangles = 0;
8431 objvertex_t *vertices = NULL;
8432 int linenumber = 0;
8433 int maxtextures = 0, numtextures = 0, textureindex = 0;
8434 int maxv = 0, numv = 1;
8435 int maxvt = 0, numvt = 1;
8436 int maxvn = 0, numvn = 1;
8437 char *texturenames = NULL;
8438 float dist, modelradius, modelyawradius, yawradius;
8439 float *obj_v = NULL;
8440 float *obj_vt = NULL;
8441 float *obj_vn = NULL;
8442 float mins[3];
8443 float maxs[3];
8444 float corner[3];
8445 objvertex_t *thisvertex = NULL;
8446 int vertexhashindex;
8447 int *vertexhashtable = NULL;
8448 objvertex_t *vertexhashdata = NULL;
8449 objvertex_t *vdata = NULL;
8450 int vertexhashsize = 0;
8451 int vertexhashcount = 0;
8452 skinfile_t *skinfiles = NULL;
8453 unsigned char *data = NULL;
8454 int *submodelfirstsurface;
8455 msurface_t *tempsurface;
8456 msurface_t *tempsurfaces;
8457
8458 memset(&vfirst, 0, sizeof(vfirst));
8459 memset(&vprev, 0, sizeof(vprev));
8460 memset(&vcurrent, 0, sizeof(vcurrent));
8461
8462 dpsnprintf(materialname, sizeof(materialname), "%s", loadmodel->name);
8463
8465
8467 loadmodel->soundfromcenter = true;
8496
8497 skinfiles = Mod_LoadSkinFiles();
8498 if (loadmodel->numskins < 1)
8499 loadmodel->numskins = 1;
8500
8501 // make skinscenes for the skins (no groups)
8503 for (i = 0;i < loadmodel->numskins;i++)
8504 {
8507 loadmodel->skinscenes[i].loop = true;
8509 }
8510
8513
8514 // we always have model 0, i.e. the first "submodel"
8516
8517 // parse the OBJ text now
8518 for(;;)
8519 {
8520 static char emptyarg[1] = "";
8521 if (!*text)
8522 break;
8523 linenumber++;
8524 linelen = 0;
8525 for (linelen = 0;text[linelen] && text[linelen] != '\r' && text[linelen] != '\n';linelen++)
8526 line[linelen] = text[linelen];
8527 line[linelen] = 0;
8528 for (argc = 0;argc < 4;argc++)
8529 argv[argc] = emptyarg;
8530 argc = 0;
8531 s = line;
8532 while (*s == ' ' || *s == '\t')
8533 s++;
8534 while (*s)
8535 {
8536 argv[argc++] = s;
8537 while (*s > ' ')
8538 s++;
8539 if (!*s)
8540 break;
8541 *s++ = 0;
8542 while (*s == ' ' || *s == '\t')
8543 s++;
8544 }
8545 text += linelen;
8546 if (*text == '\r')
8547 text++;
8548 if (*text == '\n')
8549 text++;
8550 if (!argc)
8551 continue;
8552 if (argv[0][0] == '#')
8553 continue;
8554 if (!strcmp(argv[0], "v"))
8555 {
8556 if (maxv <= numv)
8557 {
8558 maxv = max(maxv * 2, 1024);
8559 obj_v = (float *)Mem_Realloc(tempmempool, obj_v, maxv * sizeof(float[3]));
8560 }
8562 {
8563 obj_v[numv*3+0] = atof(argv[1]);
8564 obj_v[numv*3+2] = atof(argv[2]);
8565 obj_v[numv*3+1] = atof(argv[3]);
8566 }
8567 else
8568 {
8569 obj_v[numv*3+0] = atof(argv[1]);
8570 obj_v[numv*3+1] = atof(argv[2]);
8571 obj_v[numv*3+2] = atof(argv[3]);
8572 }
8573 numv++;
8574 }
8575 else if (!strcmp(argv[0], "vt"))
8576 {
8577 if (maxvt <= numvt)
8578 {
8579 maxvt = max(maxvt * 2, 1024);
8580 obj_vt = (float *)Mem_Realloc(tempmempool, obj_vt, maxvt * sizeof(float[2]));
8581 }
8582 obj_vt[numvt*2+0] = atof(argv[1]);
8583 obj_vt[numvt*2+1] = 1-atof(argv[2]);
8584 numvt++;
8585 }
8586 else if (!strcmp(argv[0], "vn"))
8587 {
8588 if (maxvn <= numvn)
8589 {
8590 maxvn = max(maxvn * 2, 1024);
8591 obj_vn = (float *)Mem_Realloc(tempmempool, obj_vn, maxvn * sizeof(float[3]));
8592 }
8594 {
8595 obj_vn[numvn*3+0] = atof(argv[1]);
8596 obj_vn[numvn*3+2] = atof(argv[2]);
8597 obj_vn[numvn*3+1] = atof(argv[3]);
8598 }
8599 else
8600 {
8601 obj_vn[numvn*3+0] = atof(argv[1]);
8602 obj_vn[numvn*3+1] = atof(argv[2]);
8603 obj_vn[numvn*3+2] = atof(argv[3]);
8604 }
8605 numvn++;
8606 }
8607 else if (!strcmp(argv[0], "f"))
8608 {
8609 if (!numtextures)
8610 {
8611 if (maxtextures <= numtextures)
8612 {
8613 maxtextures = max(maxtextures * 2, 256);
8614 texturenames = (char *)Mem_Realloc(loadmodel->mempool, texturenames, maxtextures * MAX_QPATH);
8615 }
8616 textureindex = numtextures++;
8617 dp_strlcpy(texturenames + textureindex*MAX_QPATH, loadmodel->name, MAX_QPATH);
8618 }
8619 for (j = 1;j < argc;j++)
8620 {
8621 index1 = atoi(argv[j]);
8622 while(argv[j][0] && argv[j][0] != '/')
8623 argv[j]++;
8624 if (argv[j][0])
8625 argv[j]++;
8626 index2 = atoi(argv[j]);
8627 while(argv[j][0] && argv[j][0] != '/')
8628 argv[j]++;
8629 if (argv[j][0])
8630 argv[j]++;
8631 index3 = atoi(argv[j]);
8632 // negative refers to a recent vertex
8633 // zero means not specified
8634 // positive means an absolute vertex index
8635 if (index1 < 0)
8636 index1 = numv - index1;
8637 if (index2 < 0)
8638 index2 = numvt - index2;
8639 if (index3 < 0)
8640 index3 = numvn - index3;
8641 vcurrent.nextindex = -1;
8642 vcurrent.textureindex = textureindex;
8643 vcurrent.submodelindex = submodelindex;
8644 if (obj_v && index1 >= 0 && index1 < numv)
8645 VectorCopy(obj_v + 3*index1, vcurrent.v);
8646 if (obj_vt && index2 >= 0 && index2 < numvt)
8647 Vector2Copy(obj_vt + 2*index2, vcurrent.vt);
8648 if (obj_vn && index3 >= 0 && index3 < numvn)
8649 VectorCopy(obj_vn + 3*index3, vcurrent.vn);
8650 if (numtriangles == 0)
8651 {
8652 VectorCopy(vcurrent.v, mins);
8653 VectorCopy(vcurrent.v, maxs);
8654 }
8655 else
8656 {
8657 mins[0] = min(mins[0], vcurrent.v[0]);
8658 mins[1] = min(mins[1], vcurrent.v[1]);
8659 mins[2] = min(mins[2], vcurrent.v[2]);
8660 maxs[0] = max(maxs[0], vcurrent.v[0]);
8661 maxs[1] = max(maxs[1], vcurrent.v[1]);
8662 maxs[2] = max(maxs[2], vcurrent.v[2]);
8663 }
8664 if (j == 1)
8665 vfirst = vcurrent;
8666 else if (j >= 3)
8667 {
8668 if (maxtriangles <= numtriangles)
8669 {
8670 maxtriangles = max(maxtriangles * 2, 32768);
8671 vertices = (objvertex_t*)Mem_Realloc(loadmodel->mempool, vertices, maxtriangles * sizeof(objvertex_t[3]));
8672 }
8674 {
8675 vertices[numtriangles*3+0] = vfirst;
8676 vertices[numtriangles*3+1] = vprev;
8677 vertices[numtriangles*3+2] = vcurrent;
8678 }
8679 else
8680 {
8681 vertices[numtriangles*3+0] = vfirst;
8682 vertices[numtriangles*3+2] = vprev;
8683 vertices[numtriangles*3+1] = vcurrent;
8684 }
8685 numtriangles++;
8686 }
8687 vprev = vcurrent;
8688 }
8689 }
8690 else if (!strcmp(argv[0], "o") || !strcmp(argv[0], "g"))
8691 {
8692 submodelindex = atof(argv[1]);
8693 loadmodel->brush.numsubmodels = max(submodelindex + 1, loadmodel->brush.numsubmodels);
8694 }
8695 else if (!strcmp(argv[0], "usemtl"))
8696 {
8697 for (i = 0;i < numtextures;i++)
8698 if (!strcmp(texturenames+i*MAX_QPATH, argv[1]))
8699 break;
8700 if (i < numtextures)
8701 textureindex = i;
8702 else
8703 {
8704 if (maxtextures <= numtextures)
8705 {
8706 maxtextures = max(maxtextures * 2, 256);
8707 texturenames = (char *)Mem_Realloc(loadmodel->mempool, texturenames, maxtextures * MAX_QPATH);
8708 }
8709 textureindex = numtextures++;
8710 dp_strlcpy(texturenames + textureindex*MAX_QPATH, argv[1], MAX_QPATH);
8711 }
8712 }
8713 }
8714
8715 // now that we have the OBJ data loaded as-is, we can convert it
8716
8717 // copy the model bounds, then enlarge the yaw and rotated bounds according to radius
8721 modelyawradius = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
8722 modelyawradius = dist*dist+modelyawradius*modelyawradius;
8723 modelradius = max(fabs(loadmodel->normalmins[2]), fabs(loadmodel->normalmaxs[2]));
8724 modelradius = modelyawradius + modelradius * modelradius;
8725 modelyawradius = sqrt(modelyawradius);
8726 modelradius = sqrt(modelradius);
8727 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -modelyawradius;
8729 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelyawradius;
8731 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -modelradius;
8732 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = modelradius;
8733 loadmodel->radius = modelradius;
8734 loadmodel->radius2 = modelradius * modelradius;
8735
8736 // allocate storage for triangles
8737 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, numtriangles * sizeof(int[3]));
8738 // allocate vertex hash structures to build an optimal vertex subset
8739 vertexhashsize = numtriangles*2;
8740 vertexhashtable = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int) * vertexhashsize);
8741 memset(vertexhashtable, 0xFF, sizeof(int) * vertexhashsize);
8742 vertexhashdata = (objvertex_t *)Mem_Alloc(loadmodel->mempool, sizeof(*vertexhashdata) * numtriangles*3);
8743 vertexhashcount = 0;
8744
8745 // gather surface stats for assigning vertex/triangle ranges
8746 firstvertex = 0;
8747 firsttriangle = 0;
8748 elementindex = 0;
8750 // allocate storage for the worst case number of surfaces, later we resize
8751 tempsurfaces = (msurface_t *)Mem_Alloc(loadmodel->mempool, numtextures * loadmodel->brush.numsubmodels * sizeof(msurface_t));
8752 submodelfirstsurface = (int *)Mem_Alloc(loadmodel->mempool, (loadmodel->brush.numsubmodels+1) * sizeof(int));
8753 tempsurface = tempsurfaces;
8754 for (submodelindex = 0;submodelindex < loadmodel->brush.numsubmodels;submodelindex++)
8755 {
8756 submodelfirstsurface[submodelindex] = loadmodel->num_surfaces;
8757 for (textureindex = 0;textureindex < numtextures;textureindex++)
8758 {
8759 for (vertexindex = 0;vertexindex < numtriangles*3;vertexindex++)
8760 {
8761 thisvertex = vertices + vertexindex;
8762 if (thisvertex->submodelindex == submodelindex && thisvertex->textureindex == textureindex)
8763 break;
8764 }
8765 // skip the surface creation if there are no triangles for it
8766 if (vertexindex == numtriangles*3)
8767 continue;
8768 // create a surface for these vertices
8769 surfacevertices = 0;
8770 surfaceelements = 0;
8771 // we hack in a texture index in the surface to be fixed up later...
8772 tempsurface->texture = (texture_t *)((size_t)textureindex);
8773 // calculate bounds as we go
8774 VectorCopy(thisvertex->v, tempsurface->mins);
8775 VectorCopy(thisvertex->v, tempsurface->maxs);
8776 for (;vertexindex < numtriangles*3;vertexindex++)
8777 {
8778 thisvertex = vertices + vertexindex;
8779 if (thisvertex->submodelindex != submodelindex)
8780 continue;
8781 if (thisvertex->textureindex != textureindex)
8782 continue;
8783 // add vertex to surface bounds
8784 tempsurface->mins[0] = min(tempsurface->mins[0], thisvertex->v[0]);
8785 tempsurface->mins[1] = min(tempsurface->mins[1], thisvertex->v[1]);
8786 tempsurface->mins[2] = min(tempsurface->mins[2], thisvertex->v[2]);
8787 tempsurface->maxs[0] = max(tempsurface->maxs[0], thisvertex->v[0]);
8788 tempsurface->maxs[1] = max(tempsurface->maxs[1], thisvertex->v[1]);
8789 tempsurface->maxs[2] = max(tempsurface->maxs[2], thisvertex->v[2]);
8790 // add the vertex if it is not found in the merged set, and
8791 // get its index (triangle element) for the surface
8792 vertexhashindex = (unsigned int)(thisvertex->v[0] * 3571 + thisvertex->v[0] * 1777 + thisvertex->v[0] * 457) % (unsigned int)vertexhashsize;
8793 for (i = vertexhashtable[vertexhashindex];i >= 0;i = vertexhashdata[i].nextindex)
8794 {
8795 vdata = vertexhashdata + i;
8796 if (vdata->submodelindex == thisvertex->submodelindex && vdata->textureindex == thisvertex->textureindex && VectorCompare(thisvertex->v, vdata->v) && VectorCompare(thisvertex->vn, vdata->vn) && Vector2Compare(thisvertex->vt, vdata->vt))
8797 break;
8798 }
8799 if (i < 0)
8800 {
8801 i = vertexhashcount++;
8802 vdata = vertexhashdata + i;
8803 *vdata = *thisvertex;
8804 vdata->nextindex = vertexhashtable[vertexhashindex];
8805 vertexhashtable[vertexhashindex] = i;
8806 surfacevertices++;
8807 }
8808 loadmodel->surfmesh.data_element3i[elementindex++] = i;
8809 surfaceelements++;
8810 }
8811 surfacetriangles = surfaceelements / 3;
8812 tempsurface->num_vertices = surfacevertices;
8813 tempsurface->num_triangles = surfacetriangles;
8814 tempsurface->num_firstvertex = firstvertex;
8815 tempsurface->num_firsttriangle = firsttriangle;
8816 firstvertex += tempsurface->num_vertices;
8817 firsttriangle += tempsurface->num_triangles;
8818 tempsurface++;
8820 }
8821 }
8822 submodelfirstsurface[submodelindex] = loadmodel->num_surfaces;
8823 numvertices = firstvertex;
8825 tempsurfaces = NULL;
8826
8827 // allocate storage for final mesh data
8828 loadmodel->num_textures = numtextures * loadmodel->numskins;
8829 loadmodel->num_texturesperskin = numtextures;
8830 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + numtriangles * sizeof(int[3]) + (numvertices <= 65536 ? numtriangles * sizeof(unsigned short[3]) : 0) + numvertices * sizeof(float[14]) + loadmodel->brush.numsubmodels * sizeof(model_t *));
8834 loadmodel->surfmesh.num_vertices = numvertices;
8835 loadmodel->surfmesh.num_triangles = numtriangles;
8836 loadmodel->surfmesh.data_vertex3f = (float *)data;data += numvertices * sizeof(float[3]);
8837 loadmodel->surfmesh.data_svector3f = (float *)data;data += numvertices * sizeof(float[3]);
8838 loadmodel->surfmesh.data_tvector3f = (float *)data;data += numvertices * sizeof(float[3]);
8839 loadmodel->surfmesh.data_normal3f = (float *)data;data += numvertices * sizeof(float[3]);
8840 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += numvertices * sizeof(float[2]);
8841
8842 if (loadmodel->surfmesh.num_vertices <= 65536) {
8843 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
8844 }
8845
8846 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
8847 {
8848 VectorCopy(vertexhashdata[j].v, loadmodel->surfmesh.data_vertex3f + 3*j);
8849 VectorCopy(vertexhashdata[j].vn, loadmodel->surfmesh.data_normal3f + 3*j);
8850 Vector2Copy(vertexhashdata[j].vt, loadmodel->surfmesh.data_texcoordtexture2f + 2*j);
8851 }
8852
8853 // load the textures
8854 for (textureindex = 0;textureindex < numtextures;textureindex++)
8855 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + textureindex, skinfiles, texturenames + textureindex*MAX_QPATH, texturenames + textureindex*MAX_QPATH);
8856 Mod_FreeSkinFiles(skinfiles);
8857
8858 // set the surface textures to their real values now that we loaded them...
8859 for (i = 0;i < loadmodel->num_surfaces;i++)
8861
8862 // free data
8863 Mem_Free(vertices);
8864 Mem_Free(texturenames);
8865 Mem_Free(obj_v);
8866 Mem_Free(obj_vt);
8867 Mem_Free(obj_vn);
8868 Mem_Free(vertexhashtable);
8869 Mem_Free(vertexhashdata);
8870
8871 // compute all the mesh information that was not loaded from the file
8873 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
8876 // generate normals if the file did not have them
8880
8881 // if this is a worldmodel and has no BSP tree, create a fake one for the purpose
8891 //if (loadmodel->num_nodes) loadmodel->data_nodes = (mnode_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_nodes * sizeof(mnode_t));
8892 //loadmodel->data_leafsurfaces = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->num_leafsurfaces * sizeof(int));
8904
8907
8908 mod = loadmodel;
8909 for (i = 0;i < loadmodel->brush.numsubmodels;i++)
8910 {
8911 if (i > 0)
8912 {
8913 char name[10];
8914 // duplicate the basic information
8915 dpsnprintf(name, sizeof(name), "*%i", i);
8917 // copy the base model to this one
8918 *mod = *loadmodel;
8919 // rename the clone back to its proper name
8920 dp_strlcpy(mod->name, name, sizeof(mod->name));
8921 mod->brush.parentmodel = loadmodel;
8922 // textures and memory belong to the main model
8923 mod->texturepool = NULL;
8924 mod->mempool = NULL;
8925 mod->brush.GetPVS = NULL;
8926 mod->brush.FatPVS = NULL;
8927 mod->brush.BoxTouchingPVS = NULL;
8928 mod->brush.BoxTouchingLeafPVS = NULL;
8929 mod->brush.BoxTouchingVisibleLeafs = NULL;
8930 mod->brush.FindBoxClusters = NULL;
8931 mod->brush.LightPoint = NULL;
8932 mod->brush.AmbientSoundLevelsForPoint = NULL;
8933 }
8934 mod->brush.submodel = i;
8937
8938 // make the model surface list (used by shadowing/lighting)
8939 mod->submodelsurfaces_start = submodelfirstsurface[i];
8940 mod->submodelsurfaces_end = submodelfirstsurface[i+1];
8941 mod->firstmodelbrush = 0;
8942 mod->nummodelbrushes = 0;
8943
8944 VectorClear(mod->normalmins);
8945 VectorClear(mod->normalmaxs);
8946 l = false;
8947 for (j = mod->submodelsurfaces_start;j < mod->submodelsurfaces_end;j++)
8948 {
8949 const msurface_t *surface = mod->data_surfaces + j;
8950 const float *v3f = mod->surfmesh.data_vertex3f + 3 * surface->num_firstvertex;
8951 int k;
8952 if (!surface->num_vertices)
8953 continue;
8954 if (!l)
8955 {
8956 l = true;
8957 VectorCopy(v3f, mod->normalmins);
8958 VectorCopy(v3f, mod->normalmaxs);
8959 }
8960 for (k = 0;k < surface->num_vertices;k++, v3f += 3)
8961 {
8962 mod->normalmins[0] = min(mod->normalmins[0], v3f[0]);
8963 mod->normalmins[1] = min(mod->normalmins[1], v3f[1]);
8964 mod->normalmins[2] = min(mod->normalmins[2], v3f[2]);
8965 mod->normalmaxs[0] = max(mod->normalmaxs[0], v3f[0]);
8966 mod->normalmaxs[1] = max(mod->normalmaxs[1], v3f[1]);
8967 mod->normalmaxs[2] = max(mod->normalmaxs[2], v3f[2]);
8968 }
8969 }
8970 corner[0] = max(fabs(mod->normalmins[0]), fabs(mod->normalmaxs[0]));
8971 corner[1] = max(fabs(mod->normalmins[1]), fabs(mod->normalmaxs[1]));
8972 corner[2] = max(fabs(mod->normalmins[2]), fabs(mod->normalmaxs[2]));
8973 modelradius = sqrt(corner[0]*corner[0]+corner[1]*corner[1]+corner[2]*corner[2]);
8974 yawradius = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
8975 mod->rotatedmins[0] = mod->rotatedmins[1] = mod->rotatedmins[2] = -modelradius;
8976 mod->rotatedmaxs[0] = mod->rotatedmaxs[1] = mod->rotatedmaxs[2] = modelradius;
8977 mod->yawmaxs[0] = mod->yawmaxs[1] = yawradius;
8978 mod->yawmins[0] = mod->yawmins[1] = -yawradius;
8979 mod->yawmins[2] = mod->normalmins[2];
8980 mod->yawmaxs[2] = mod->normalmaxs[2];
8981 mod->radius = modelradius;
8982 mod->radius2 = modelradius * modelradius;
8983
8985
8986 Mod_MakeCollisionBIH(mod, true, &mod->collision_bih);
8987 mod->render_bih = mod->collision_bih;
8988
8989 // generate VBOs and other shared data before cloning submodels
8990 if (i == 0)
8991 Mod_BuildVBOs();
8992 }
8993 mod = loadmodel;
8994 Mem_Free(submodelfirstsurface);
8995
8996 // make the model surface list (used by shadowing/lighting)
8998
8999 Con_DPrintf("Stats for obj model \"%s\": %i faces, %i nodes, %i leafs, %i clusters, %i clusterportals, mesh: %i vertices, %i triangles, %i surfaces\n", loadmodel->name, loadmodel->num_surfaces, loadmodel->brush.num_nodes, loadmodel->brush.num_leafs, mod->brush.num_pvsclusters, loadmodel->brush.num_portals, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->num_surfaces);
9000}
#define Vector2Copy(in, out)
Definition mathlib.h:74
#define VectorLength2(a)
Definition mathlib.h:110
#define VectorCompare(a, b)
Definition mathlib.h:113
#define Vector2Compare(a, b)
Definition mathlib.h:73
string argv(float n)
static unsigned char nobsp_pvs[1]
int numleafbrushes
int * firstleafbrush
vec3_t mins
int * firstleafsurface
int areaindex
vec3_t maxs
int clusterindex
int numleafsurfaces
int combinedsupercontents
int(* BoxTouchingVisibleLeafs)(struct model_s *model, const unsigned char *visibleleafs, const vec3_t mins, const vec3_t maxs)
unsigned char * data_pvsclusters
int(* NativeContentsFromSuperContents)(int supercontents)
qbool(* TraceLineOfSight)(struct model_s *model, const vec3_t start, const vec3_t end, const vec3_t acceptmins, const vec3_t acceptmaxs)
qbool supportwateralpha
void(* RoundUpToHullSize)(struct model_s *cmodel, const vec3_t inmins, const vec3_t inmaxs, vec3_t outmins, vec3_t outmaxs)
size_t(* FatPVS)(struct model_s *model, const vec3_t org, vec_t radius, unsigned char **pvsbuffer, mempool_t *pool, qbool merge)
int(* SuperContentsFromNativeContents)(int nativecontents)
struct model_s ** submodels
unsigned char *(* GetPVS)(struct model_s *model, const vec3_t p)
int(* FindBoxClusters)(struct model_s *model, const vec3_t mins, const vec3_t maxs, int maxclusters, int *clusterlist)
mleaf_t *(* PointInLeaf)(struct model_s *model, const vec3_t p)
int num_pvsclusterbytes
void(* LightPoint)(struct model_s *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal)
void(* FindNonSolidLocation)(struct model_s *model, const vec3_t in, vec3_t out, vec_t radius)
void(* AmbientSoundLevelsForPoint)(struct model_s *model, const vec3_t p, unsigned char *out, int outsize)
int * data_leafsurfaces
int(* BoxTouchingPVS)(struct model_s *model, const unsigned char *pvs, const vec3_t mins, const vec3_t maxs)
int(* BoxTouchingLeafPVS)(struct model_s *model, const unsigned char *pvs, const vec3_t mins, const vec3_t maxs)
mleaf_t * data_leafs
mnode_t * data_nodes
model_brush_t brush
void(* GetLightInfo)(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, unsigned char *outleafpvs, int *outnumleafspointer, int *outsurfacelist, unsigned char *outsurfacepvs, int *outnumsurfacespointer, unsigned char *outshadowtrispvs, unsigned char *outlighttrispvs, unsigned char *visitingleafpvs, int numfrustumplanes, const mplane_t *frustumplanes, qbool noocclusion)
void(* TraceLineAgainstSurfaces)(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)
int soundfromcenter
float vn[3]
float vt[2]

References model_brush_t::AmbientSoundLevelsForPoint, mleaf_t::areaindex, argv(), model_brush_t::BoxTouchingLeafPVS, model_brush_t::BoxTouchingPVS, model_brush_t::BoxTouchingVisibleLeafs, model_t::brush, buffer, mleaf_t::clusterindex, mleaf_t::combinedsupercontents, model_t::CompileShadowMap, Con_DPrintf(), data, surfmesh_t::data_element3i, surfmesh_t::data_element3s, model_brush_t::data_leafs, model_brush_t::data_leafsurfaces, model_brush_t::data_nodes, surfmesh_t::data_normal3f, model_brush_t::data_pvsclusters, 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, dpsnprintf(), model_t::Draw, model_t::DrawDebug, model_t::DrawDepth, model_t::DrawLight, model_t::DrawPrepass, model_t::DrawShadowMap, fabs(), model_brush_t::FatPVS, model_brush_t::FindBoxClusters, model_brush_t::FindNonSolidLocation, animscene_t::firstframe, mleaf_t::firstleafbrush, mleaf_t::firstleafsurface, animscene_t::framecount, animscene_t::framerate, model_t::GetLightInfo, model_brush_t::GetPVS, i, int(), cvar_t::integer, model_brush_t::LightPoint, loadmodel, animscene_t::loop, max, MAX_QPATH, maxs, mleaf_t::maxs, msurface_t::maxs, Mem_Alloc, Mem_Free, Mem_Realloc, model_t::mempool, min, mins, mleaf_t::mins, msurface_t::mins, mod(), Mod_BuildAliasSkinsFromSkinFiles(), Mod_BuildNormals(), Mod_BuildTextureVectorsFromNormals(), Mod_BuildVBOs(), Mod_CollisionBIH_PointSuperContents_Mesh(), Mod_CollisionBIH_TraceBox(), Mod_CollisionBIH_TraceBrush(), Mod_CollisionBIH_TraceLine(), Mod_CollisionBIH_TracePoint_Mesh(), Mod_FindName(), Mod_FreeSkinFiles(), Mod_LoadSkinFiles(), Mod_MakeCollisionBIH(), Mod_MakeSortedSurfaces(), mod_obj, mod_obj_orientation, Mod_SetDrawSkyAndWater(), Mod_ValidateElements(), model_t::modeldatatypestring, model_t::modelsurfaces_sorted, model_t::name, name, model_brush_t::NativeContentsFromSuperContents, objvertex_t::nextindex, nobsp_pvs, model_t::normalmaxs, model_t::normalmins, NULL, msurface_t::num_firsttriangle, msurface_t::num_firstvertex, model_brush_t::num_leafs, model_brush_t::num_leafsurfaces, model_brush_t::num_nodes, model_brush_t::num_portals, model_brush_t::num_pvsclusterbytes, model_brush_t::num_pvsclusters, 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, model_brush_t::num_visleafs, mleaf_t::numleafbrushes, mleaf_t::numleafsurfaces, model_t::numskins, model_brush_t::numsubmodels, model_brush_t::PointInLeaf, 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_Mod_GetLightInfo(), r_smoothnormals_areaweighting, model_t::radius, model_t::radius2, model_t::rotatedmaxs, model_t::rotatedmins, model_brush_t::RoundUpToHullSize, model_t::skinscenes, model_t::soundfromcenter, sqrt(), objvertex_t::submodelindex, model_brush_t::submodels, model_brush_t::SuperContentsFromNativeContents, model_brush_t::supportwateralpha, model_t::surfmesh, tempmempool, msurface_t::texture, objvertex_t::textureindex, model_t::TraceBox, model_t::TraceBrush, model_t::TraceLine, model_t::TraceLineAgainstSurfaces, model_brush_t::TraceLineOfSight, model_t::TracePoint, model_t::type, objvertex_t::v, v, Vector2Compare, Vector2Copy, VectorClear, VectorCompare, VectorCopy, VectorLength2, objvertex_t::vn, objvertex_t::vt, model_t::yawmaxs, and model_t::yawmins.

◆ 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
void FS_StripExtension(const char *in, char *out, size_t size_out)
Definition fs.c:3611
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_PurgeUnused()

void Mod_PurgeUnused ( void )

Definition at line 574 of file model_shared.c.

575{
576 int i;
577 int nummodels = (int)Mem_ExpandableArray_IndexRange(&models);
578 model_t *mod;
579 for (i = 0;i < nummodels;i++)
580 {
581 if ((mod = (model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && !mod->used)
582 {
585 }
586 }
587}
void Mem_ExpandableArray_FreeRecord(memexpandablearray_t *l, void *record)
Definition zone.c:743

References i, int(), Mem_ExpandableArray_FreeRecord(), Mem_ExpandableArray_IndexRange(), Mem_ExpandableArray_RecordAtIndex(), mod(), Mod_UnloadModel(), and models.

Referenced by CL_SignonReply(), and SV_SpawnServer().

◆ Mod_Q1BSP_Load()

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

Definition at line 3903 of file model_brush.c.

3904{
3905 int i, j, k;
3906 sizebuf_t lumpsb[HEADER_LUMPS];
3907 mmodel_t *bm;
3908 float dist, modelyawradius, modelradius;
3909 msurface_t *surface;
3910 hullinfo_t hullinfo;
3911 int totalstylesurfaces, totalstyles, stylecounts[256], remapstyles[256];
3912 model_brush_lightstyleinfo_t styleinfo[256];
3913 int *datapointer;
3914 model_brush_lightstyleinfo_t *lsidatapointer;
3915 sizebuf_t sb;
3916
3917 MSG_InitReadBuffer(&sb, (unsigned char *)buffer, (unsigned char *)bufferend - (unsigned char *)buffer);
3918
3919 mod->type = mod_brushq1;
3920
3921 mod->brush.skymasking = true;
3922 i = MSG_ReadLittleLong(&sb);
3923
3924 if(!mod->modeldatatypestring)
3925 mod->modeldatatypestring = "Q1BSP";
3926
3927// fill in hull info
3928 VectorClear (hullinfo.hullsizes[0][0]);
3929 VectorClear (hullinfo.hullsizes[0][1]);
3930 if (mod->brush.ishlbsp)
3931 {
3932 hullinfo.filehulls = 4;
3933 VectorSet (hullinfo.hullsizes[1][0], -16, -16, -36);
3934 VectorSet (hullinfo.hullsizes[1][1], 16, 16, 36);
3935 VectorSet (hullinfo.hullsizes[2][0], -32, -32, -32);
3936 VectorSet (hullinfo.hullsizes[2][1], 32, 32, 32);
3937 VectorSet (hullinfo.hullsizes[3][0], -16, -16, -18);
3938 VectorSet (hullinfo.hullsizes[3][1], 16, 16, 18);
3939 }
3940 else
3941 {
3942 hullinfo.filehulls = 4;
3943 VectorSet (hullinfo.hullsizes[1][0], -16, -16, -24);
3944 VectorSet (hullinfo.hullsizes[1][1], 16, 16, 32);
3945 VectorSet (hullinfo.hullsizes[2][0], -32, -32, -24);
3946 VectorSet (hullinfo.hullsizes[2][1], 32, 32, 64);
3947 }
3948
3949// read lumps
3950 for (i = 0; i < HEADER_LUMPS; i++)
3951 {
3952 int offset = MSG_ReadLittleLong(&sb);
3953 int size = MSG_ReadLittleLong(&sb);
3955 Host_Error("Mod_Q1BSP_Load: %s has invalid lump %i (offset %i, size %i, file size %i)\n", mod->name, i, offset, size, (int)sb.cursize);
3956 MSG_InitReadBuffer(&lumpsb[i], sb.data + offset, size);
3957 }
3958
3959 mod->soundfromcenter = true;
3960 mod->TraceBox = Mod_Q1BSP_TraceBox;
3961 mod->TraceLine = Mod_Q1BSP_TraceLine;
3962 mod->TracePoint = Mod_Q1BSP_TracePoint;
3963 mod->PointSuperContents = Mod_Q1BSP_PointSuperContents;
3964 mod->TraceLineAgainstSurfaces = Mod_Q1BSP_TraceLineAgainstSurfaces;
3965 mod->brush.TraceLineOfSight = Mod_Q1BSP_TraceLineOfSight;
3966 mod->brush.SuperContentsFromNativeContents = Mod_Q1BSP_SuperContentsFromNativeContents;
3967 mod->brush.NativeContentsFromSuperContents = Mod_Q1BSP_NativeContentsFromSuperContents;
3968 mod->brush.GetPVS = Mod_BSP_GetPVS;
3969 mod->brush.FatPVS = Mod_BSP_FatPVS;
3970 mod->brush.BoxTouchingPVS = Mod_BSP_BoxTouchingPVS;
3971 mod->brush.BoxTouchingLeafPVS = Mod_BSP_BoxTouchingLeafPVS;
3972 mod->brush.BoxTouchingVisibleLeafs = Mod_BSP_BoxTouchingVisibleLeafs;
3973 mod->brush.FindBoxClusters = Mod_BSP_FindBoxClusters;
3974 mod->brush.LightPoint = Mod_BSP_LightPoint;
3975 mod->brush.FindNonSolidLocation = Mod_BSP_FindNonSolidLocation;
3976 mod->brush.AmbientSoundLevelsForPoint = Mod_Q1BSP_AmbientSoundLevelsForPoint;
3977 mod->brush.RoundUpToHullSize = Mod_Q1BSP_RoundUpToHullSize;
3978 mod->brush.PointInLeaf = Mod_BSP_PointInLeaf;
3979 mod->Draw = R_Mod_Draw;
3980 mod->DrawDepth = R_Mod_DrawDepth;
3981 mod->DrawDebug = R_Mod_DrawDebug;
3982 mod->DrawPrepass = R_Mod_DrawPrepass;
3983 mod->GetLightInfo = R_Mod_GetLightInfo;
3984 mod->CompileShadowMap = R_Mod_CompileShadowMap;
3985 mod->DrawShadowMap = R_Mod_DrawShadowMap;
3986 mod->DrawLight = R_Mod_DrawLight;
3987
3988// load into heap
3989
3990 mod->brush.qw_md4sum = 0;
3991 mod->brush.qw_md4sum2 = 0;
3992 for (i = 0;i < HEADER_LUMPS;i++)
3993 {
3994 int temp;
3995 if (i == LUMP_ENTITIES)
3996 continue;
3997 temp = Com_BlockChecksum(lumpsb[i].data, lumpsb[i].cursize);
3998 mod->brush.qw_md4sum ^= LittleLong(temp);
3999 if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES)
4000 continue;
4001 mod->brush.qw_md4sum2 ^= LittleLong(temp);
4002 }
4003
4015 // load submodels before leafs because they contain the number of vis leafs
4016 Mod_BSP_LoadSubmodels(&lumpsb[LUMP_MODELS], &hullinfo);
4019 Mod_Q1BSP_LoadClipnodes(&lumpsb[LUMP_CLIPNODES], &hullinfo);
4020
4021 for (i = 0; i < HEADER_LUMPS; i++)
4022 if (lumpsb[i].readcount != lumpsb[i].cursize && i != LUMP_TEXTURES && i != LUMP_LIGHTING)
4023 Host_Error("Lump %i incorrectly loaded (readcount %i, size %i)\n", i, lumpsb[i].readcount, lumpsb[i].cursize);
4024
4025 // check if the map supports transparent water rendering
4027
4028 // we don't need the compressed pvs data anymore
4029 if (mod->brushq1.data_compressedpvs)
4030 Mem_Free(mod->brushq1.data_compressedpvs);
4031 mod->brushq1.data_compressedpvs = NULL;
4032 mod->brushq1.num_compressedpvs = 0;
4033
4037
4038 mod->numframes = 2; // regular and alternate animation
4039 mod->numskins = 1;
4040
4043
4044 // LadyHavoc: to clear the fog around the original quake submodel code, I
4045 // will explain:
4046 // first of all, some background info on the submodels:
4047 // model 0 is the map model (the world, named maps/e1m1.bsp for example)
4048 // model 1 and higher are submodels (doors and the like, named *1, *2, etc)
4049 // now the weird for loop itself:
4050 // the loop functions in an odd way, on each iteration it sets up the
4051 // current 'mod' model (which despite the confusing code IS the model of
4052 // the number i), at the end of the loop it duplicates the model to become
4053 // the next submodel, and loops back to set up the new submodel.
4054
4055 // LadyHavoc: now the explanation of my sane way (which works identically):
4056 // set up the world model, then on each submodel copy from the world model
4057 // and set up the submodel with the respective model info.
4058 totalstylesurfaces = 0;
4059 totalstyles = 0;
4060 for (i = 0;i < mod->brush.numsubmodels;i++)
4061 {
4062 memset(stylecounts, 0, sizeof(stylecounts));
4063 for (k = 0;k < mod->brushq1.submodels[i].numfaces;k++)
4064 {
4065 surface = mod->data_surfaces + mod->brushq1.submodels[i].firstface + k;
4066 for (j = 0;j < MAXLIGHTMAPS;j++)
4067 stylecounts[surface->lightmapinfo->styles[j]]++;
4068 }
4069 for (k = 0;k < 255;k++)
4070 {
4071 totalstyles++;
4072 if (stylecounts[k])
4073 totalstylesurfaces += stylecounts[k];
4074 }
4075 }
4076 // bones_was_here: using a separate allocation for model_brush_lightstyleinfo_t
4077 // because on a 64-bit machine it no longer has the same alignment requirement as int.
4078 lsidatapointer = Mem_AllocType(mod->mempool, model_brush_lightstyleinfo_t, totalstyles * sizeof(model_brush_lightstyleinfo_t));
4079 datapointer = Mem_AllocType(mod->mempool, int, mod->num_surfaces * sizeof(int) + totalstylesurfaces * sizeof(int));
4080 mod->modelsurfaces_sorted = datapointer;datapointer += mod->num_surfaces;
4081 for (i = 0;i < mod->brush.numsubmodels;i++)
4082 {
4083 // LadyHavoc: this code was originally at the end of this loop, but
4084 // has been transformed to something more readable at the start here.
4085
4086 if (i > 0)
4087 {
4088 char name[10];
4089 // duplicate the basic information
4090 dpsnprintf(name, sizeof(name), "*%i", i);
4092 // copy the base model to this one
4093 *mod = *loadmodel;
4094 // rename the clone back to its proper name
4095 dp_strlcpy(mod->name, name, sizeof(mod->name));
4096 mod->brush.parentmodel = loadmodel;
4097 // textures and memory belong to the main model
4098 mod->texturepool = NULL;
4099 mod->mempool = NULL;
4100 mod->brush.GetPVS = NULL;
4101 mod->brush.FatPVS = NULL;
4102 mod->brush.BoxTouchingPVS = NULL;
4103 mod->brush.BoxTouchingLeafPVS = NULL;
4104 mod->brush.BoxTouchingVisibleLeafs = NULL;
4105 mod->brush.FindBoxClusters = NULL;
4106 mod->brush.LightPoint = NULL;
4107 mod->brush.AmbientSoundLevelsForPoint = NULL;
4108 }
4109
4110 mod->brush.submodel = i;
4111
4114
4115 bm = &mod->brushq1.submodels[i];
4116
4117 mod->brushq1.hulls[0].firstclipnode = bm->headnode[0];
4118 for (j=1 ; j<MAX_MAP_HULLS ; j++)
4119 {
4120 mod->brushq1.hulls[j].firstclipnode = bm->headnode[j];
4121 mod->brushq1.hulls[j].lastclipnode = mod->brushq1.numclipnodes - 1;
4122 }
4123
4124 mod->submodelsurfaces_start = bm->firstface;
4125 mod->submodelsurfaces_end = bm->firstface + bm->numfaces;
4126
4127 // set node/leaf parents for this submodel
4128 Mod_BSP_LoadNodes_RecursiveSetParent(mod->brush.data_nodes + mod->brushq1.hulls[0].firstclipnode, NULL);
4129
4130 // this has to occur after hull info has been set, as it uses Mod_Q1BSP_PointSuperContents
4132
4133 // copy the submodel bounds, then enlarge the yaw and rotated bounds according to radius
4134 // (previously this code measured the radius of the vertices of surfaces in the submodel, but that broke submodels that contain only CLIP brushes, which do not produce surfaces)
4135 VectorCopy(bm->mins, mod->normalmins);
4136 VectorCopy(bm->maxs, mod->normalmaxs);
4137 dist = max(fabs(mod->normalmins[0]), fabs(mod->normalmaxs[0]));
4138 modelyawradius = max(fabs(mod->normalmins[1]), fabs(mod->normalmaxs[1]));
4139 modelyawradius = dist*dist+modelyawradius*modelyawradius;
4140 modelradius = max(fabs(mod->normalmins[2]), fabs(mod->normalmaxs[2]));
4141 modelradius = modelyawradius + modelradius * modelradius;
4142 modelyawradius = sqrt(modelyawradius);
4143 modelradius = sqrt(modelradius);
4144 mod->yawmins[0] = mod->yawmins[1] = -modelyawradius;
4145 mod->yawmins[2] = mod->normalmins[2];
4146 mod->yawmaxs[0] = mod->yawmaxs[1] = modelyawradius;
4147 mod->yawmaxs[2] = mod->normalmaxs[2];
4148 mod->rotatedmins[0] = mod->rotatedmins[1] = mod->rotatedmins[2] = -modelradius;
4149 mod->rotatedmaxs[0] = mod->rotatedmaxs[1] = mod->rotatedmaxs[2] = modelradius;
4150 mod->radius = modelradius;
4151 mod->radius2 = modelradius * modelradius;
4152
4154
4155 if (mod->submodelsurfaces_start < mod->submodelsurfaces_end)
4156 {
4157 // build lightstyle update chains
4158 // (used to rapidly mark lightmapupdateflags on many surfaces
4159 // when d_lightstylevalue changes)
4160 memset(stylecounts, 0, sizeof(stylecounts));
4161 for (k = mod->submodelsurfaces_start;k < mod->submodelsurfaces_end;k++)
4162 for (j = 0;j < MAXLIGHTMAPS;j++)
4163 stylecounts[mod->data_surfaces[k].lightmapinfo->styles[j]]++;
4164 mod->brushq1.num_lightstyles = 0;
4165 for (k = 0;k < 255;k++)
4166 {
4167 if (stylecounts[k])
4168 {
4169 styleinfo[mod->brushq1.num_lightstyles].style = k;
4170 styleinfo[mod->brushq1.num_lightstyles].value = 0;
4171 styleinfo[mod->brushq1.num_lightstyles].numsurfaces = 0;
4172 styleinfo[mod->brushq1.num_lightstyles].surfacelist = datapointer;datapointer += stylecounts[k];
4173 remapstyles[k] = mod->brushq1.num_lightstyles;
4174 mod->brushq1.num_lightstyles++;
4175 }
4176 }
4177 for (k = mod->submodelsurfaces_start;k < mod->submodelsurfaces_end;k++)
4178 {
4179 surface = mod->data_surfaces + k;
4180 for (j = 0;j < MAXLIGHTMAPS;j++)
4181 {
4182 if (surface->lightmapinfo->styles[j] != 255)
4183 {
4184 int r = remapstyles[surface->lightmapinfo->styles[j]];
4185 styleinfo[r].surfacelist[styleinfo[r].numsurfaces++] = k;
4186 }
4187 }
4188 }
4189 mod->brushq1.data_lightstyleinfo = lsidatapointer;lsidatapointer += mod->brushq1.num_lightstyles;
4190 memcpy(mod->brushq1.data_lightstyleinfo, styleinfo, mod->brushq1.num_lightstyles * sizeof(model_brush_lightstyleinfo_t));
4191 }
4192 else
4193 {
4194 // LadyHavoc: empty submodel(lacrima.bsp has such a glitch)
4195 Con_Printf(CON_WARN "warning: empty submodel *%i in %s\n", i+1, loadmodel->name);
4196 }
4197 //mod->brushq1.num_visleafs = bm->visleafs;
4198
4199 // build a Bounding Interval Hierarchy for culling triangles in light rendering
4200 Mod_MakeCollisionBIH(mod, true, &mod->render_bih);
4201
4203 {
4204 mod->collision_bih = mod->render_bih;
4205 // point traces and contents checks still use the bsp tree
4206 mod->TraceLine = Mod_CollisionBIH_TraceLine;
4207 mod->TraceBox = Mod_CollisionBIH_TraceBox;
4208 mod->TraceBrush = Mod_CollisionBIH_TraceBrush;
4209 mod->TraceLineAgainstSurfaces = Mod_CollisionBIH_TraceLineAgainstSurfaces;
4210 }
4211
4212 // generate VBOs and other shared data before cloning submodels
4213 if (i == 0)
4214 {
4215 Mod_BuildVBOs();
4217 //Mod_Q1BSP_ProcessLightList();
4218 }
4219 }
4220 mod = loadmodel;
4221
4222 // make the model surface list (used by shadowing/lighting)
4224
4225 Con_DPrintf("Stats for q1bsp model \"%s\": %i faces, %i nodes, %i leafs, %i visleafs, %i visleafportals, mesh: %i vertices, %i triangles, %i surfaces\n", loadmodel->name, loadmodel->num_surfaces, loadmodel->brush.num_nodes, loadmodel->brush.num_leafs, mod->brush.num_pvsclusters, loadmodel->brush.num_portals, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->num_surfaces);
4226}
#define LUMP_LIGHTING
Definition bspfile.h:47
#define LUMP_EDGES
Definition bspfile.h:51
#define LUMP_SURFEDGES
Definition bspfile.h:52
#define MAXLIGHTMAPS
Definition bspfile.h:282
#define LUMP_LEAFS
Definition bspfile.h:49
#define LUMP_VERTEXES
Definition bspfile.h:42
#define LUMP_CLIPNODES
Definition bspfile.h:48
#define HEADER_LUMPS
Definition bspfile.h:54
#define MAX_MAP_HULLS
Definition bspfile.h:24
#define LUMP_PLANES
Definition bspfile.h:40
#define LUMP_TEXINFO
Definition bspfile.h:45
#define LUMP_MODELS
Definition bspfile.h:53
#define LUMP_MARKSURFACES
Definition bspfile.h:50
#define LUMP_TEXTURES
Definition bspfile.h:41
#define LUMP_VISIBILITY
Definition bspfile.h:43
#define LUMP_FACES
Definition bspfile.h:46
#define LUMP_NODES
Definition bspfile.h:44
#define LUMP_ENTITIES
Definition bspfile.h:39
void MSG_InitReadBuffer(sizebuf_t *buf, unsigned char *data, int size)
Definition com_msg.c:249
int MSG_ReadLittleLong(sizebuf_t *sb)
Definition com_msg.c:285
unsigned Com_BlockChecksum(void *buffer, int length)
Definition mdfour.c:198
GLuint GLuint GLintptr offset
Definition glquake.h:632
static int Mod_Q1BSP_PointSuperContents(struct model_s *model, int frame, const vec3_t point)
static void Mod_Q1BSP_LoadVertexes(sizebuf_t *sb)
static void Mod_BSP_LightPoint(model_t *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal)
static void Mod_Q1BSP_LoadTextures(sizebuf_t *sb)
int Mod_Q1BSP_SuperContentsFromNativeContents(int nativecontents)
static void Mod_Q1BSP_LoadLeafs(sizebuf_t *sb)
static unsigned char * Mod_BSP_GetPVS(model_t *model, const vec3_t p)
static void Mod_Q1BSP_LoadClipnodes(sizebuf_t *sb, hullinfo_t *hullinfo)
static void Mod_Q1BSP_LoadPlanes(sizebuf_t *sb)
int Mod_Q1BSP_NativeContentsFromSuperContents(int supercontents)
static qbool Mod_Q1BSP_CheckWaterAlphaSupport(void)
static void Mod_Q1BSP_LoadTexinfo(sizebuf_t *sb)
static int Mod_BSP_BoxTouchingLeafPVS(model_t *model, const unsigned char *pvs, const vec3_t mins, const vec3_t maxs)
static void Mod_Q1BSP_LoadLighting(sizebuf_t *sb)
void Mod_CollisionBIH_TraceLineAgainstSurfaces(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_Q1BSP_TraceLineAgainstSurfaces(struct model_s *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 size_t Mod_BSP_FatPVS(model_t *model, const vec3_t org, vec_t radius, unsigned char **pvsbuffer, mempool_t *pool, qbool merge)
static void Mod_Q1BSP_LoadEntities(sizebuf_t *sb)
static void Mod_BSP_LoadNodes_RecursiveSetParent(mnode_t *node, mnode_t *parent)
static void Mod_Q1BSP_RoundUpToHullSize(model_t *cmodel, const vec3_t inmins, const vec3_t inmaxs, vec3_t outmins, vec3_t outmaxs)
static int Mod_BSP_FindBoxClusters(model_t *model, const vec3_t mins, const vec3_t maxs, int maxclusters, int *clusterlist)
static void Mod_Q1BSP_TraceLine(struct model_s *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_Q1BSP_LoadFaces(sizebuf_t *sb)
static void Mod_Q1BSP_TracePoint(struct model_s *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask)
static void Mod_BSP_FindNonSolidLocation(model_t *model, const vec3_t in, vec3_t out, float radius)
static void Mod_Q1BSP_AssignNoShadowSkySurfaces(model_t *mod)
static int Mod_BSP_BoxTouchingPVS(model_t *model, const unsigned char *pvs, const vec3_t mins, const vec3_t maxs)
static void Mod_Q1BSP_LoadSurfedges(sizebuf_t *sb)
static void Mod_Q1BSP_LoadLeaffaces(sizebuf_t *sb)
static mleaf_t * Mod_BSP_PointInLeaf(model_t *model, const vec3_t p)
static void Mod_Q1BSP_LoadEdges(sizebuf_t *sb)
static void Mod_Q1BSP_LoadNodes(sizebuf_t *sb)
static void Mod_Q1BSP_AmbientSoundLevelsForPoint(model_t *model, const vec3_t p, unsigned char *out, int outsize)
static int Mod_BSP_BoxTouchingVisibleLeafs(model_t *model, const unsigned char *visibleleafs, const vec3_t mins, const vec3_t maxs)
static void Mod_Q1BSP_MakeHull0(void)
static void Mod_Q1BSP_LoadVisibility(sizebuf_t *sb)
static qbool Mod_Q1BSP_TraceLineOfSight(struct model_s *model, const vec3_t start, const vec3_t end, const vec3_t acceptmins, const vec3_t acceptmaxs)
static void Mod_Q1BSP_LoadMapBrushes(void)
static void Mod_BSP_MakePortals(void)
static void Mod_BSP_LoadSubmodels(sizebuf_t *sb, hullinfo_t *hullinfo)
static void Mod_Q1BSP_TraceBox(struct model_s *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)
int filehulls
Definition bspfile.h:58
float hullsizes[MAX_MAP_HULLS][2][3]
Definition bspfile.h:59
float mins[3]
Definition bspfile.h:64
int headnode[MAX_MAP_HULLS]
Definition bspfile.h:66
int firstface
Definition bspfile.h:68
int numfaces
Definition bspfile.h:68
float maxs[3]
Definition bspfile.h:64
unsigned char styles[MAXLIGHTMAPS]
msurface_lightmapinfo_t * lightmapinfo
lightmaptexture rebuild information not used in q3bsp
unsigned char * data
Definition common.h:52
int cursize
Definition common.h:54

References model_t::brush, buffer, ca_dedicated, cls, Com_BlockChecksum(), Con_DPrintf(), Con_Printf(), CON_WARN, sizebuf_t::cursize, data, sizebuf_t::data, dp_strlcpy, dpsnprintf(), fabs(), hullinfo_t::filehulls, mmodel_t::firstface, HEADER_LUMPS, mmodel_t::headnode, Host_Error(), hullinfo_t::hullsizes, i, cvar_t::integer, msurface_t::lightmapinfo, LittleLong, loadmodel, LUMP_CLIPNODES, LUMP_EDGES, LUMP_ENTITIES, LUMP_FACES, LUMP_LEAFS, LUMP_LIGHTING, LUMP_MARKSURFACES, LUMP_MODELS, LUMP_NODES, LUMP_PLANES, LUMP_SURFEDGES, LUMP_TEXINFO, LUMP_TEXTURES, LUMP_VERTEXES, LUMP_VISIBILITY, max, MAX_MAP_HULLS, MAXLIGHTMAPS, mmodel_t::maxs, Mem_Alloc, Mem_AllocType, Mem_Free, model_t::mempool, mmodel_t::mins, mod(), mod_brushq1, Mod_BSP_BoxTouchingLeafPVS(), Mod_BSP_BoxTouchingPVS(), Mod_BSP_BoxTouchingVisibleLeafs(), Mod_BSP_FatPVS(), Mod_BSP_FindBoxClusters(), Mod_BSP_FindNonSolidLocation(), Mod_BSP_GetPVS(), Mod_BSP_LightPoint(), Mod_BSP_LoadNodes_RecursiveSetParent(), Mod_BSP_LoadSubmodels(), Mod_BSP_MakePortals(), Mod_BSP_PointInLeaf(), mod_bsp_portalize, Mod_BuildVBOs(), Mod_CollisionBIH_TraceBox(), Mod_CollisionBIH_TraceBrush(), Mod_CollisionBIH_TraceLine(), Mod_CollisionBIH_TraceLineAgainstSurfaces(), Mod_FindName(), Mod_MakeCollisionBIH(), Mod_MakeSortedSurfaces(), Mod_Q1BSP_AmbientSoundLevelsForPoint(), Mod_Q1BSP_AssignNoShadowSkySurfaces(), Mod_Q1BSP_CheckWaterAlphaSupport(), Mod_Q1BSP_LoadClipnodes(), Mod_Q1BSP_LoadEdges(), Mod_Q1BSP_LoadEntities(), Mod_Q1BSP_LoadFaces(), Mod_Q1BSP_LoadLeaffaces(), Mod_Q1BSP_LoadLeafs(), Mod_Q1BSP_LoadLighting(), Mod_Q1BSP_LoadMapBrushes(), Mod_Q1BSP_LoadNodes(), Mod_Q1BSP_LoadPlanes(), Mod_Q1BSP_LoadSurfedges(), Mod_Q1BSP_LoadTexinfo(), Mod_Q1BSP_LoadTextures(), Mod_Q1BSP_LoadVertexes(), Mod_Q1BSP_LoadVisibility(), Mod_Q1BSP_MakeHull0(), Mod_Q1BSP_NativeContentsFromSuperContents(), Mod_Q1BSP_PointSuperContents(), mod_q1bsp_polygoncollisions, Mod_Q1BSP_RoundUpToHullSize(), Mod_Q1BSP_SuperContentsFromNativeContents(), Mod_Q1BSP_TraceBox(), Mod_Q1BSP_TraceLine(), Mod_Q1BSP_TraceLineAgainstSurfaces(), Mod_Q1BSP_TraceLineOfSight(), Mod_Q1BSP_TracePoint(), Mod_SetDrawSkyAndWater(), MSG_InitReadBuffer(), MSG_ReadLittleLong(), model_t::name, name, NULL, model_brush_t::num_leafs, model_brush_t::num_nodes, model_brush_t::num_portals, model_t::num_surfaces, surfmesh_t::num_triangles, surfmesh_t::num_vertices, mmodel_t::numfaces, model_brush_t::numsubmodels, model_brush_lightstyleinfo_t::numsurfaces, offset, r, R_Mod_CompileShadowMap(), R_Mod_Draw(), R_Mod_DrawDebug(), R_Mod_DrawDepth(), R_Mod_DrawLight(), R_Mod_DrawPrepass(), R_Mod_DrawShadowMap(), R_Mod_GetLightInfo(), size, sqrt(), client_static_t::state, model_brush_lightstyleinfo_t::style, msurface_lightmapinfo_t::styles, model_brush_t::submodels, model_brush_t::supportwateralpha, model_brush_lightstyleinfo_t::surfacelist, model_t::surfmesh, model_brush_lightstyleinfo_t::value, VectorClear, VectorCopy, and VectorSet.

Referenced by Mod_2PSB_Load(), Mod_BSP2_Load(), and Mod_HLBSP_Load().

◆ Mod_Q1BSP_NativeContentsFromSuperContents()

int Mod_Q1BSP_NativeContentsFromSuperContents ( int supercontents)

Definition at line 650 of file model_brush.c.

651{
652 if (supercontents & (SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY))
653 return CONTENTS_SOLID;
654 if (supercontents & SUPERCONTENTS_SKY)
655 return CONTENTS_SKY;
656 if (supercontents & SUPERCONTENTS_LAVA)
657 return CONTENTS_LAVA;
658 if (supercontents & SUPERCONTENTS_SLIME)
659 return CONTENTS_SLIME;
660 if (supercontents & SUPERCONTENTS_WATER)
661 return CONTENTS_WATER;
662 return CONTENTS_EMPTY;
663}
#define SUPERCONTENTS_BODY
Definition bspfile.h:201
#define CONTENTS_LAVA
Definition bspfile.h:137
#define CONTENTS_SOLID
Definition bspfile.h:134
#define CONTENTS_SKY
Definition bspfile.h:138
#define CONTENTS_SLIME
Definition bspfile.h:136
#define CONTENTS_WATER
Definition bspfile.h:135
#define CONTENTS_EMPTY
Definition bspfile.h:133

References CONTENTS_EMPTY, CONTENTS_LAVA, CONTENTS_SKY, CONTENTS_SLIME, CONTENTS_SOLID, CONTENTS_WATER, SUPERCONTENTS_BODY, SUPERCONTENTS_LAVA, SUPERCONTENTS_SKY, SUPERCONTENTS_SLIME, SUPERCONTENTS_SOLID, and SUPERCONTENTS_WATER.

Referenced by Mod_Q1BSP_Load(), SV_CheckWater(), SV_CheckWaterTransition(), VM_CL_pointcontents(), and VM_SV_pointcontents().

◆ Mod_Q1BSP_SuperContentsFromNativeContents()

int Mod_Q1BSP_SuperContentsFromNativeContents ( int nativecontents)

◆ Mod_Q2BSP_NativeContentsFromSuperContents()

int Mod_Q2BSP_NativeContentsFromSuperContents ( int supercontents)

Definition at line 4252 of file model_brush.c.

4253{
4254 int nativecontents = 0;
4255 if (supercontents & SUPERCONTENTS_SOLID)
4256 nativecontents |= CONTENTSQ2_SOLID;
4257 if (supercontents & SUPERCONTENTS_WATER)
4258 nativecontents |= CONTENTSQ2_WATER;
4259 if (supercontents & SUPERCONTENTS_SLIME)
4260 nativecontents |= CONTENTSQ2_SLIME;
4261 if (supercontents & SUPERCONTENTS_LAVA)
4262 nativecontents |= CONTENTSQ2_LAVA;
4263 if (supercontents & SUPERCONTENTS_BODY)
4264 nativecontents |= CONTENTSQ2_MONSTER;
4265 if (supercontents & SUPERCONTENTS_CORPSE)
4266 nativecontents |= CONTENTSQ2_DEADMONSTER;
4267 if (supercontents & SUPERCONTENTS_PLAYERCLIP)
4268 nativecontents |= CONTENTSQ2_PLAYERCLIP;
4269 if (supercontents & SUPERCONTENTS_MONSTERCLIP)
4270 nativecontents |= CONTENTSQ2_MONSTERCLIP;
4271 if (!(supercontents & SUPERCONTENTS_OPAQUE))
4272 nativecontents |= CONTENTSQ2_TRANSLUCENT;
4273 return nativecontents;
4274}
#define CONTENTSQ2_MONSTERCLIP
Definition bspfile.h:159
#define CONTENTSQ2_LAVA
Definition bspfile.h:153
#define SUPERCONTENTS_MONSTERCLIP
Definition bspfile.h:205
#define CONTENTSQ2_DEADMONSTER
Definition bspfile.h:168
#define CONTENTSQ2_MONSTER
Definition bspfile.h:167
#define CONTENTSQ2_TRANSLUCENT
Definition bspfile.h:170
#define CONTENTSQ2_WATER
Definition bspfile.h:155
#define SUPERCONTENTS_CORPSE
Definition bspfile.h:202
#define CONTENTSQ2_PLAYERCLIP
Definition bspfile.h:158
#define SUPERCONTENTS_PLAYERCLIP
Definition bspfile.h:204
#define CONTENTSQ2_SOLID
Definition bspfile.h:150
#define CONTENTSQ2_SLIME
Definition bspfile.h:154

References CONTENTSQ2_DEADMONSTER, CONTENTSQ2_LAVA, CONTENTSQ2_MONSTER, CONTENTSQ2_MONSTERCLIP, CONTENTSQ2_PLAYERCLIP, CONTENTSQ2_SLIME, CONTENTSQ2_SOLID, CONTENTSQ2_TRANSLUCENT, CONTENTSQ2_WATER, SUPERCONTENTS_BODY, SUPERCONTENTS_CORPSE, SUPERCONTENTS_LAVA, SUPERCONTENTS_MONSTERCLIP, SUPERCONTENTS_OPAQUE, SUPERCONTENTS_PLAYERCLIP, SUPERCONTENTS_SLIME, SUPERCONTENTS_SOLID, and SUPERCONTENTS_WATER.

Referenced by Mod_Q2BSP_Load().

◆ Mod_Q2BSP_SuperContentsFromNativeContents()

int Mod_Q2BSP_SuperContentsFromNativeContents ( int nativecontents)

Definition at line 4228 of file model_brush.c.

4229{
4230 int supercontents = 0;
4231 if (nativecontents & CONTENTSQ2_SOLID)
4232 supercontents |= SUPERCONTENTS_SOLID;
4233 if (nativecontents & CONTENTSQ2_WATER)
4234 supercontents |= SUPERCONTENTS_WATER;
4235 if (nativecontents & CONTENTSQ2_SLIME)
4236 supercontents |= SUPERCONTENTS_SLIME;
4237 if (nativecontents & CONTENTSQ2_LAVA)
4238 supercontents |= SUPERCONTENTS_LAVA;
4239 if (nativecontents & CONTENTSQ2_MONSTER)
4240 supercontents |= SUPERCONTENTS_BODY;
4241 if (nativecontents & CONTENTSQ2_DEADMONSTER)
4242 supercontents |= SUPERCONTENTS_CORPSE;
4243 if (nativecontents & CONTENTSQ2_PLAYERCLIP)
4244 supercontents |= SUPERCONTENTS_PLAYERCLIP;
4245 if (nativecontents & CONTENTSQ2_MONSTERCLIP)
4246 supercontents |= SUPERCONTENTS_MONSTERCLIP;
4247 if (!(nativecontents & CONTENTSQ2_TRANSLUCENT))
4248 supercontents |= SUPERCONTENTS_OPAQUE;
4249 return supercontents;
4250}

References CONTENTSQ2_DEADMONSTER, CONTENTSQ2_LAVA, CONTENTSQ2_MONSTER, CONTENTSQ2_MONSTERCLIP, CONTENTSQ2_PLAYERCLIP, CONTENTSQ2_SLIME, CONTENTSQ2_SOLID, CONTENTSQ2_TRANSLUCENT, CONTENTSQ2_WATER, SUPERCONTENTS_BODY, SUPERCONTENTS_CORPSE, SUPERCONTENTS_LAVA, SUPERCONTENTS_MONSTERCLIP, SUPERCONTENTS_OPAQUE, SUPERCONTENTS_PLAYERCLIP, SUPERCONTENTS_SLIME, SUPERCONTENTS_SOLID, and SUPERCONTENTS_WATER.

Referenced by Mod_LoadTextureFromQ3Shader(), Mod_Q2BSP_Load(), Mod_Q2BSP_LoadBrushes(), and Mod_Q2BSP_LoadTexinfo().

◆ Mod_Reload()

void Mod_Reload ( void )

Definition at line 661 of file model_shared.c.

662{
663 int i, count;
664 int nummodels = (int)Mem_ExpandableArray_IndexRange(&models);
665 model_t *mod;
666
667 SCR_PushLoadingScreen("Reloading models", 1.0);
668 count = 0;
669 for (i = 0;i < nummodels;i++)
670 if ((mod = (model_t *) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && mod->name[0] != '*' && mod->used)
671 ++count;
672 for (i = 0;i < nummodels;i++)
673 if ((mod = (model_t *) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && mod->name[0] != '*' && mod->used)
674 {
675 SCR_PushLoadingScreen(mod->name, 1.0 / count);
676 Mod_LoadModel(mod, true, true);
678 }
680}

References count, i, int(), Mem_ExpandableArray_IndexRange(), Mem_ExpandableArray_RecordAtIndex(), mod(), Mod_LoadModel(), models, SCR_PopLoadingScreen(), and SCR_PushLoadingScreen().

◆ Mod_RemoveDegenerateTriangles()

int Mod_RemoveDegenerateTriangles ( int numtriangles,
const int * inelement3i,
int * outelement3i,
const float * vertex3f )

Definition at line 2841 of file model_shared.c.

2842{
2843 int i, outtriangles;
2844 float edgedir1[3], edgedir2[3], temp[3];
2845 // a degenerate triangle is one with no width (thickness, surface area)
2846 // these are characterized by having all 3 points colinear (along a line)
2847 // or having two points identical
2848 // the simplest check is to calculate the triangle's area
2849 for (i = 0, outtriangles = 0;i < numtriangles;i++, inelement3i += 3)
2850 {
2851 // calculate first edge
2852 VectorSubtract(vertex3f + inelement3i[1] * 3, vertex3f + inelement3i[0] * 3, edgedir1);
2853 VectorSubtract(vertex3f + inelement3i[2] * 3, vertex3f + inelement3i[0] * 3, edgedir2);
2854 CrossProduct(edgedir1, edgedir2, temp);
2855 if (VectorLength2(temp) < 0.001f)
2856 continue; // degenerate triangle (no area)
2857 // valid triangle (has area)
2858 VectorCopy(inelement3i, outelement3i);
2859 outelement3i += 3;
2860 outtriangles++;
2861 }
2862 return outtriangles;
2863}

References CrossProduct, i, VectorCopy, VectorLength2, and VectorSubtract.

Referenced by Mod_Q3BSP_LoadFaces().

◆ Mod_RemoveStaleWorldModels()

void Mod_RemoveStaleWorldModels ( model_t * skip)

◆ Mod_SetDrawSkyAndWater()

void Mod_SetDrawSkyAndWater ( model_t * mod)

Sets the mod->DrawSky and mod->DrawAddWaterPlanes pointers conditionally based on whether surfaces in this submodel use these features called specifically by brush model loaders when generating submodels automatically called after model loader returns.

Definition at line 2887 of file model_shared.c.

2888{
2889 int j;
2890 uint64_t basematerialflags = 0;
2891 // by default assume there is no sky or water used in this model
2892 mod->DrawSky = NULL;
2893 mod->DrawAddWaterPlanes = NULL;
2894 // combine all basematerialflags observed in the submodelsurfaces range, then check for special flags
2895 for (j = mod->submodelsurfaces_start; j < mod->submodelsurfaces_end; j++)
2896 if (mod->data_surfaces[j].texture)
2897 basematerialflags |= mod->data_surfaces[j].texture->basematerialflags;
2898 if (basematerialflags & MATERIALFLAG_SKY)
2899 mod->DrawSky = R_Mod_DrawSky;
2901 mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
2902}

References MATERIALFLAG_CAMERA, MATERIALFLAG_REFLECTION, MATERIALFLAG_REFRACTION, MATERIALFLAG_SKY, MATERIALFLAG_WATERSHADER, mod(), NULL, R_Mod_DrawAddWaterPlanes(), and R_Mod_DrawSky().

Referenced by Mod_LoadModel(), Mod_OBJ_Load(), Mod_Q1BSP_Load(), Mod_Q2BSP_Load(), and Mod_Q3BSP_Load().

◆ Mod_ShadowMesh_AddMesh()

void Mod_ShadowMesh_AddMesh ( shadowmesh_t * mesh,
const float * vertex3f,
int numtris,
const int * element3i )

Definition at line 1041 of file model_shared.c.

1042{
1043 int i;
1044
1045 for (i = 0;i < numtris;i++)
1046 {
1047 if ((mesh->numtriangles * 3 + 2) * sizeof(int) + 1 >= Mem_Size(mesh->element3i))
1048 {
1049 // FIXME: we didn't allocate enough space for all the tris, see R_Mod_CompileShadowMap
1050 Con_Print(CON_WARN "Mod_ShadowMesh_AddMesh: insufficient memory allocated!\n");
1051 return;
1052 }
1053 mesh->element3i[mesh->numtriangles * 3 + 0] = Mod_ShadowMesh_AddVertex(mesh, vertex3f + 3 * element3i[i * 3 + 0]);
1054 mesh->element3i[mesh->numtriangles * 3 + 1] = Mod_ShadowMesh_AddVertex(mesh, vertex3f + 3 * element3i[i * 3 + 1]);
1055 mesh->element3i[mesh->numtriangles * 3 + 2] = Mod_ShadowMesh_AddVertex(mesh, vertex3f + 3 * element3i[i * 3 + 2]);
1056 mesh->numtriangles++;
1057 }
1058
1059 // the triangle calculation can take a while, so let's do a keepalive here
1060 CL_KeepaliveMessage(false);
1061}
void CL_KeepaliveMessage(qbool readmessages)
Definition cl_parse.c:314
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
Definition console.c:1504
int Mod_ShadowMesh_AddVertex(shadowmesh_t *mesh, const float *vertex3f)
static size_t Mem_Size(void *data)
Returns the current size of an allocation.
Definition zone.h:122

References CL_KeepaliveMessage(), Con_Print(), CON_WARN, shadowmesh_t::element3i, i, Mem_Size(), Mod_ShadowMesh_AddVertex(), and shadowmesh_t::numtriangles.

Referenced by Mod_CreateCollisionMesh(), and R_Shadow_ShadowMapFromList().

◆ Mod_ShadowMesh_AddVertex()

int Mod_ShadowMesh_AddVertex ( shadowmesh_t * mesh,
const float * vertex3f )

Definition at line 1019 of file model_shared.c.

1020{
1021 int hashindex, vnum;
1023 // this uses prime numbers intentionally
1024 hashindex = (unsigned int) (vertex3f[0] * 2003 + vertex3f[1] * 4001 + vertex3f[2] * 7919) % SHADOWMESHVERTEXHASH;
1025 for (hash = mesh->vertexhashtable[hashindex];hash;hash = hash->next)
1026 {
1027 vnum = (hash - mesh->vertexhashentries);
1028 if (mesh->vertex3f[vnum * 3 + 0] == vertex3f[0] && mesh->vertex3f[vnum * 3 + 1] == vertex3f[1] && mesh->vertex3f[vnum * 3 + 2] == vertex3f[2])
1029 return hash - mesh->vertexhashentries;
1030 }
1031 vnum = mesh->numverts++;
1032 hash = mesh->vertexhashentries + vnum;
1033 hash->next = mesh->vertexhashtable[hashindex];
1034 mesh->vertexhashtable[hashindex] = hash;
1035 mesh->vertex3f[vnum * 3 + 0] = vertex3f[0];
1036 mesh->vertex3f[vnum * 3 + 1] = vertex3f[1];
1037 mesh->vertex3f[vnum * 3 + 2] = vertex3f[2];
1038 return vnum;
1039}
#define SHADOWMESHVERTEXHASH
shadowmeshvertexhash_t ** vertexhashtable
float * vertex3f
shadowmeshvertexhash_t * vertexhashentries
struct shadowmeshvertexhash_s * next

References int(), shadowmeshvertexhash_t::next, shadowmesh_t::numverts, SHADOWMESHVERTEXHASH, shadowmesh_t::vertex3f, shadowmesh_t::vertexhashentries, and shadowmesh_t::vertexhashtable.

Referenced by Mod_ShadowMesh_AddMesh().

◆ Mod_ShadowMesh_Alloc()

shadowmesh_t * Mod_ShadowMesh_Alloc ( struct mempool_s * mempool,
int maxverts,
int maxtriangles )

◆ Mod_ShadowMesh_Begin()

shadowmesh_t * Mod_ShadowMesh_Begin ( struct mempool_s * mempool,
int maxverts,
int maxtriangles )

◆ Mod_ShadowMesh_CalcBBox()

void Mod_ShadowMesh_CalcBBox ( shadowmesh_t * firstmesh,
vec3_t mins,
vec3_t maxs,
vec3_t center,
float * radius )

Definition at line 1136 of file model_shared.c.

1137{
1138 int i;
1139 vec3_t nmins, nmaxs, ncenter, temp;
1140 float nradius2, dist2, *v;
1141 VectorClear(nmins);
1142 VectorClear(nmaxs);
1143 // calculate bbox
1144 VectorCopy(mesh->vertex3f, nmins);
1145 VectorCopy(mesh->vertex3f, nmaxs);
1146 for (i = 0, v = mesh->vertex3f;i < mesh->numverts;i++, v += 3)
1147 {
1148 if (nmins[0] > v[0]) { nmins[0] = v[0]; } if (nmaxs[0] < v[0]) { nmaxs[0] = v[0]; }
1149 if (nmins[1] > v[1]) { nmins[1] = v[1]; } if (nmaxs[1] < v[1]) { nmaxs[1] = v[1]; }
1150 if (nmins[2] > v[2]) { nmins[2] = v[2]; } if (nmaxs[2] < v[2]) { nmaxs[2] = v[2]; }
1151 }
1152 // calculate center and radius
1153 ncenter[0] = (nmins[0] + nmaxs[0]) * 0.5f;
1154 ncenter[1] = (nmins[1] + nmaxs[1]) * 0.5f;
1155 ncenter[2] = (nmins[2] + nmaxs[2]) * 0.5f;
1156 nradius2 = 0;
1157 for (i = 0, v = mesh->vertex3f;i < mesh->numverts;i++, v += 3)
1158 {
1159 VectorSubtract(v, ncenter, temp);
1160 dist2 = DotProduct(temp, temp);
1161 if (nradius2 < dist2)
1162 nradius2 = dist2;
1163 }
1164 // return data
1165 if (mins)
1166 VectorCopy(nmins, mins);
1167 if (maxs)
1168 VectorCopy(nmaxs, maxs);
1169 if (center)
1170 VectorCopy(ncenter, center);
1171 if (radius)
1172 *radius = sqrt(nradius2);
1173}

References DotProduct, i, maxs, mins, sqrt(), v, VectorClear, VectorCopy, VectorSubtract, and shadowmesh_t::vertex3f.

◆ Mod_ShadowMesh_Finish()

shadowmesh_t * Mod_ShadowMesh_Finish ( shadowmesh_t * firstmesh,
qbool createvbo )

Definition at line 1099 of file model_shared.c.

1100{
1101 if (mesh->numverts >= 3 && mesh->numtriangles >= 1)
1102 {
1103 if (mesh->vertexhashentries)
1104 Mem_Free(mesh->vertexhashentries);
1105 mesh->vertexhashentries = NULL;
1106 if (mesh->vertexhashtable)
1107 Mem_Free(mesh->vertexhashtable);
1108 mesh->vertexhashtable = NULL;
1109 if (mesh->maxverts > mesh->numverts)
1110 {
1111 mesh->vertex3f = (float *)Mem_Realloc(mesh->mempool, mesh->vertex3f, mesh->numverts * sizeof(float[3]));
1112 mesh->maxverts = mesh->numverts;
1113 }
1114 if (mesh->maxtriangles > mesh->numtriangles)
1115 {
1116 mesh->element3i = (int *)Mem_Realloc(mesh->mempool, mesh->element3i, mesh->numtriangles * sizeof(int[3]));
1117 mesh->maxtriangles = mesh->numtriangles;
1118 }
1119 if (mesh->numverts <= 65536)
1120 {
1121 int i;
1122 mesh->element3s = (unsigned short *)Mem_Alloc(mesh->mempool, mesh->numtriangles * sizeof(unsigned short[3]));
1123 for (i = 0;i < mesh->numtriangles*3;i++)
1124 mesh->element3s[i] = mesh->element3i[i];
1125 }
1126 if (createvbo)
1128 }
1129
1130 // this can take a while, so let's do a keepalive here
1131 CL_KeepaliveMessage(false);
1132
1133 return mesh;
1134}
static void Mod_ShadowMesh_CreateVBOs(shadowmesh_t *mesh)

References CL_KeepaliveMessage(), shadowmesh_t::element3i, shadowmesh_t::element3s, i, shadowmesh_t::maxtriangles, shadowmesh_t::maxverts, Mem_Alloc, Mem_Free, Mem_Realloc, shadowmesh_t::mempool, Mod_ShadowMesh_CreateVBOs(), NULL, shadowmesh_t::numtriangles, shadowmesh_t::numverts, shadowmesh_t::vertex3f, shadowmesh_t::vertexhashentries, and shadowmesh_t::vertexhashtable.

Referenced by Mod_CreateCollisionMesh(), and R_Mod_CompileShadowMap().

◆ Mod_ShadowMesh_Free()

void Mod_ShadowMesh_Free ( shadowmesh_t * mesh)

Definition at line 1175 of file model_shared.c.

1176{
1177 if (mesh->element3i_indexbuffer)
1179 if (mesh->element3s_indexbuffer)
1181 if (mesh->vbo_vertexbuffer)
1183 if (mesh->vertex3f)
1184 Mem_Free(mesh->vertex3f);
1185 if (mesh->element3i)
1186 Mem_Free(mesh->element3i);
1187 if (mesh->element3s)
1188 Mem_Free(mesh->element3s);
1189 if (mesh->vertexhashentries)
1191 if (mesh->vertexhashtable)
1193 Mem_Free(mesh);
1194}
void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
r_meshbuffer_t * element3s_indexbuffer
r_meshbuffer_t * vbo_vertexbuffer
r_meshbuffer_t * element3i_indexbuffer
unsigned short * element3s

References shadowmesh_t::element3i, shadowmesh_t::element3i_indexbuffer, shadowmesh_t::element3s, shadowmesh_t::element3s_indexbuffer, Mem_Free, R_Mesh_DestroyMeshBuffer(), shadowmesh_t::vbo_vertexbuffer, shadowmesh_t::vertex3f, shadowmesh_t::vertexhashentries, and shadowmesh_t::vertexhashtable.

Referenced by R_RTLight_Uncompile().

◆ Mod_Skeletal_FreeBuffers()

void Mod_Skeletal_FreeBuffers ( void )

◆ Mod_SnapVertices()

void Mod_SnapVertices ( int numcomponents,
int numvertices,
float * vertices,
float snap )

Definition at line 2833 of file model_shared.c.

2834{
2835 int i;
2836 double isnap = 1.0 / snap;
2837 for (i = 0;i < numvertices*numcomponents;i++)
2838 vertices[i] = floor(vertices[i]*isnap)*snap;
2839}
float floor(float f)

References floor(), and i.

Referenced by Mod_Q3BSP_LoadFaces().

◆ Mod_SpriteInit()

void Mod_SpriteInit ( void )

Definition at line 45 of file model_sprite.c.

References Cvar_RegisterVariable(), r_labelsprites_roundtopixels, r_labelsprites_scale, r_mipsprites, r_overheadsprites_perspective, r_overheadsprites_pushback, r_overheadsprites_scalex, r_overheadsprites_scaley, r_track_sprites, r_track_sprites_flags, r_track_sprites_scaleh, and r_track_sprites_scalew.

Referenced by Mod_Init().

◆ Mod_UnloadCustomMaterial()

void Mod_UnloadCustomMaterial ( texture_t * texture,
qbool purgeskins )

Removes all shaderpasses from material, and optionally deletes the textures in the skinframes.

Definition at line 2685 of file model_shared.c.

2686{
2687 long unsigned int i, j;
2688 for (i = 0; i < sizeof(texture->shaderpasses) / sizeof(texture->shaderpasses[0]); i++)
2689 {
2690 if (texture->shaderpasses[i])
2691 {
2692 if (purgeskins)
2693 for (j = 0; j < sizeof(texture->shaderpasses[i]->skinframes) / sizeof(skinframe_t *);j++)
2694 if (texture->shaderpasses[i]->skinframes[j] && texture->shaderpasses[i]->skinframes[j]->base)
2695 R_SkinFrame_PurgeSkinFrame(texture->shaderpasses[i]->skinframes[j]);
2696 Mem_Free(texture->shaderpasses[i]);
2697 texture->shaderpasses[i] = NULL;
2698 }
2699 }
2700 texture->materialshaderpass = NULL;
2701 texture->currentskinframe = NULL;
2702 texture->backgroundcurrentskinframe = NULL;
2703}
void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
Definition gl_rmain.c:2184
GLenum GLenum GLuint texture
Definition glquake.h:613

References i, Mem_Free, NULL, R_SkinFrame_PurgeSkinFrame(), and texture.

◆ Mod_UnloadModel()

void Mod_UnloadModel ( model_t * mod)

Definition at line 211 of file model_shared.c.

212{
213 char name[MAX_QPATH];
214 qbool used;
215 model_t *parentmodel;
216
218 Con_Printf("unloading model %s\n", mod->name);
219
220 dp_strlcpy(name, mod->name, sizeof(name));
221 parentmodel = mod->brush.parentmodel;
222 used = mod->used;
223 if (mod->mempool)
224 {
225 if (mod->surfmesh.data_element3i_indexbuffer && !mod->surfmesh.data_element3i_indexbuffer->isdynamic)
226 R_Mesh_DestroyMeshBuffer(mod->surfmesh.data_element3i_indexbuffer);
227 mod->surfmesh.data_element3i_indexbuffer = NULL;
228 if (mod->surfmesh.data_element3s_indexbuffer && !mod->surfmesh.data_element3s_indexbuffer->isdynamic)
229 R_Mesh_DestroyMeshBuffer(mod->surfmesh.data_element3s_indexbuffer);
230 mod->surfmesh.data_element3s_indexbuffer = NULL;
231 if (mod->surfmesh.data_vertex3f_vertexbuffer && !mod->surfmesh.data_vertex3f_vertexbuffer->isdynamic)
232 R_Mesh_DestroyMeshBuffer(mod->surfmesh.data_vertex3f_vertexbuffer);
233 mod->surfmesh.data_vertex3f_vertexbuffer = NULL;
234 mod->surfmesh.data_svector3f_vertexbuffer = NULL;
235 mod->surfmesh.data_tvector3f_vertexbuffer = NULL;
236 mod->surfmesh.data_normal3f_vertexbuffer = NULL;
237 mod->surfmesh.data_texcoordtexture2f_vertexbuffer = NULL;
238 mod->surfmesh.data_texcoordlightmap2f_vertexbuffer = NULL;
239 mod->surfmesh.data_lightmapcolor4f_vertexbuffer = NULL;
240 mod->surfmesh.data_skeletalindex4ub_vertexbuffer = NULL;
241 mod->surfmesh.data_skeletalweight4ub_vertexbuffer = NULL;
242 }
243 // free textures/memory attached to the model
244 R_FreeTexturePool(&mod->texturepool);
245 Mem_FreePool(&mod->mempool);
246 // clear the struct to make it available
247 memset(mod, 0, sizeof(model_t));
248 // restore the fields we want to preserve
249 dp_strlcpy(mod->name, name, sizeof(mod->name));
250 mod->brush.parentmodel = parentmodel;
251 mod->used = used;
252 mod->loaded = false;
253}
void R_FreeTexturePool(rtexturepool_t **rtexturepool)

References Con_Printf(), developer_loading, dp_strlcpy, cvar_t::integer, MAX_QPATH, Mem_FreePool, mod(), name, NULL, R_FreeTexturePool(), and R_Mesh_DestroyMeshBuffer().

Referenced by Mod_LoadModel(), Mod_Mesh_Destroy(), Mod_PurgeUnused(), and mod_shutdown().

◆ Mod_ValidateElements()

qbool Mod_ValidateElements ( int * element3i,
unsigned short * element3s,
int numtriangles,
int firstvertex,
int numvertices,
const char * filename,
int fileline )

Definition at line 738 of file model_shared.c.

739{
740 int first = firstvertex, last = first + numvertices - 1, numelements = numtriangles * 3;
741 int i;
742 int invalidintcount = 0, invalidintexample = 0;
743 int invalidshortcount = 0, invalidshortexample = 0;
744 int invalidmismatchcount = 0, invalidmismatchexample = 0;
745 if (element3i)
746 {
747 for (i = 0; i < numelements; i++)
748 {
749 if (element3i[i] < first || element3i[i] > last)
750 {
751 invalidintcount++;
752 invalidintexample = i;
753 }
754 }
755 }
756 if (element3s)
757 {
758 for (i = 0; i < numelements; i++)
759 {
760 if (element3s[i] < first || element3s[i] > last)
761 {
762 invalidintcount++;
763 invalidintexample = i;
764 }
765 }
766 }
767 if (element3i && element3s)
768 {
769 for (i = 0; i < numelements; i++)
770 {
771 if (element3s[i] != element3i[i])
772 {
773 invalidmismatchcount++;
774 invalidmismatchexample = i;
775 }
776 }
777 }
778 if (invalidintcount || invalidshortcount || invalidmismatchcount)
779 {
780 Con_Printf("Mod_ValidateElements(%i, %i, %i, %p, %p) called at %s:%d", numelements, first, last, (void *)element3i, (void *)element3s, filename, fileline);
781 Con_Printf(", %i elements are invalid in element3i (example: element3i[%i] == %i)", invalidintcount, invalidintexample, element3i ? element3i[invalidintexample] : 0);
782 Con_Printf(", %i elements are invalid in element3s (example: element3s[%i] == %i)", invalidshortcount, invalidshortexample, element3s ? element3s[invalidshortexample] : 0);
783 Con_Printf(", %i elements mismatch between element3i and element3s (example: element3s[%i] is %i and element3i[%i] is %i)", invalidmismatchcount, invalidmismatchexample, element3s ? element3s[invalidmismatchexample] : 0, invalidmismatchexample, element3i ? element3i[invalidmismatchexample] : 0);
784 Con_Print(". Please debug the engine code - these elements have been modified to not crash, but nothing more.\n");
785
786 // edit the elements to make them safer, as the driver will crash otherwise
787 if (element3i)
788 for (i = 0; i < numelements; i++)
789 if (element3i[i] < first || element3i[i] > last)
790 element3i[i] = first;
791 if (element3s)
792 for (i = 0; i < numelements; i++)
793 if (element3s[i] < first || element3s[i] > last)
794 element3s[i] = first;
795 if (element3i && element3s)
796 for (i = 0; i < numelements; i++)
797 if (element3s[i] != element3i[i])
798 element3s[i] = element3i[i];
799
800 return false;
801 }
802 return true;
803}

References Con_Print(), Con_Printf(), first, and i.

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

◆ Mod_VBSP_Load()

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

Definition at line 8312 of file model_brush.c.

8313{
8314 static cvar_t *testing = NULL; // TEMPORARY
8315 int i;
8316 sizebuf_t sb;
8317 sizebuf_t lumpsb[HL2HEADER_LUMPS];
8318
8319 if(!testing || !testing->integer)
8320 {
8321 if(!testing)
8322 testing = Cvar_Get(&cvars_all, "mod_bsp_vbsptest", "0", CF_CLIENT | CF_SERVER, "uhhh");
8323 Host_Error("Mod_VBSP_Load: not yet fully implemented. Change the now-generated \"mod_bsp_vbsptest\" to 1 if you wish to test this");
8324 }
8325 else
8326 {
8327
8328 MSG_InitReadBuffer(&sb, (unsigned char *)buffer, (unsigned char *)bufferend - (unsigned char *)buffer);
8329
8330 mod->type = mod_brushhl2;
8331
8332 MSG_ReadLittleLong(&sb);
8333 MSG_ReadLittleLong(&sb); // TODO version check
8334
8335 mod->modeldatatypestring = "VBSP";
8336
8337 // read lumps
8338 for (i = 0; i < HL2HEADER_LUMPS; i++)
8339 {
8340 int offset = MSG_ReadLittleLong(&sb);
8341 int size = MSG_ReadLittleLong(&sb);
8342 MSG_ReadLittleLong(&sb); // TODO support version
8343 MSG_ReadLittleLong(&sb); // TODO support ident
8345 Host_Error("Mod_VBSP_Load: %s has invalid lump %i (offset %i, size %i, file size %i)\n", mod->name, i, offset, size, (int)sb.cursize);
8346 MSG_InitReadBuffer(&lumpsb[i], sb.data + offset, size);
8347 }
8348
8349 MSG_ReadLittleLong(&sb); // TODO support revision field
8350
8351 mod->soundfromcenter = true;
8352 mod->TraceBox = Mod_CollisionBIH_TraceBox;
8353 mod->TraceBrush = Mod_CollisionBIH_TraceBrush;
8354 mod->TraceLine = Mod_CollisionBIH_TraceLine;
8355 mod->TracePoint = Mod_CollisionBIH_TracePoint;
8356 mod->PointSuperContents = Mod_CollisionBIH_PointSuperContents;
8357 mod->TraceLineAgainstSurfaces = Mod_CollisionBIH_TraceLine;
8358 mod->brush.TraceLineOfSight = Mod_Q3BSP_TraceLineOfSight; // probably not correct
8359 mod->brush.SuperContentsFromNativeContents = Mod_Q3BSP_SuperContentsFromNativeContents; // probably not correct
8360 mod->brush.NativeContentsFromSuperContents = Mod_Q3BSP_NativeContentsFromSuperContents; // probably not correct
8361 mod->brush.GetPVS = Mod_BSP_GetPVS;
8362 mod->brush.FatPVS = Mod_BSP_FatPVS;
8363 mod->brush.BoxTouchingPVS = Mod_BSP_BoxTouchingPVS;
8364 mod->brush.BoxTouchingLeafPVS = Mod_BSP_BoxTouchingLeafPVS;
8365 mod->brush.BoxTouchingVisibleLeafs = Mod_BSP_BoxTouchingVisibleLeafs;
8366 mod->brush.FindBoxClusters = Mod_BSP_FindBoxClusters;
8367 mod->brush.LightPoint = Mod_Q3BSP_LightPoint; // probably not correct
8368 mod->brush.FindNonSolidLocation = Mod_BSP_FindNonSolidLocation;
8369 mod->brush.AmbientSoundLevelsForPoint = NULL;
8370 mod->brush.RoundUpToHullSize = NULL;
8371 mod->brush.PointInLeaf = Mod_BSP_PointInLeaf;
8372 mod->Draw = R_Mod_Draw;
8373 mod->DrawDepth = R_Mod_DrawDepth;
8374 mod->DrawDebug = R_Mod_DrawDebug;
8375 mod->DrawPrepass = R_Mod_DrawPrepass;
8376 mod->GetLightInfo = R_Mod_GetLightInfo;
8377 mod->CompileShadowMap = R_Mod_CompileShadowMap;
8378 mod->DrawShadowMap = R_Mod_DrawShadowMap;
8379 mod->DrawLight = R_Mod_DrawLight;
8380
8381 // allocate a texture pool if we need it
8382 if (mod->texturepool == NULL)
8383 mod->texturepool = R_AllocTexturePool();
8384
8390 //Mod_VBSP_LoadLighting(&lumpsb[HL2LUMP_LIGHTING]);
8393
8394 // AHHHHHHH
8396 }
8397}
#define CF_SERVER
cvar/command that only the server can change/execute
Definition cmd.h:49
cvar_t * Cvar_Get(cvar_state_t *cvars, const char *name, const char *value, unsigned flags, const char *newdescription)
allocates a cvar by name and returns its address, or merely sets its value if it already exists.
Definition cvar.c:695
static void Mod_VBSP_LoadEdges(sizebuf_t *sb)
static int Mod_Q3BSP_SuperContentsFromNativeContents(int nativecontents)
static qbool Mod_Q3BSP_TraceLineOfSight(struct model_s *model, const vec3_t start, const vec3_t end, const vec3_t acceptmins, const vec3_t acceptmaxs)
static int Mod_Q3BSP_NativeContentsFromSuperContents(int supercontents)
static void Mod_VBSP_LoadPlanes(sizebuf_t *sb)
static void Mod_VBSP_LoadEntities(sizebuf_t *sb)
static void Mod_VBSP_LoadVertexes(sizebuf_t *sb)
static void Mod_VBSP_LoadSurfedges(sizebuf_t *sb)
static void Mod_Q3BSP_LightPoint(model_t *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal)
int Mod_CollisionBIH_PointSuperContents(struct model_s *model, int frame, const vec3_t point)
static void Mod_VBSP_LoadTexinfo(sizebuf_t *sb)
static void Mod_VBSP_LoadFaces(sizebuf_t *sb)
static void Mod_VBSP_LoadTextures(sizebuf_t *sb)
#define HL2HEADER_LUMPS
Definition model_vbsp.h:72
#define HL2LUMP_EDGES
Definition model_vbsp.h:86
#define HL2LUMP_TEXINFO
Definition model_vbsp.h:80
#define HL2LUMP_VERTEXES
Definition model_vbsp.h:77
#define HL2LUMP_FACES
Definition model_vbsp.h:81
#define HL2LUMP_PLANES
Definition model_vbsp.h:75
#define HL2LUMP_TEXDATA
Definition model_vbsp.h:76
#define HL2LUMP_ENTITIES
Definition model_vbsp.h:74
#define HL2LUMP_SURFEDGES
Definition model_vbsp.h:87
Definition cvar.h:66

References buffer, CF_CLIENT, CF_SERVER, sizebuf_t::cursize, Cvar_Get(), cvars_all, sizebuf_t::data, HL2HEADER_LUMPS, HL2LUMP_EDGES, HL2LUMP_ENTITIES, HL2LUMP_FACES, HL2LUMP_PLANES, HL2LUMP_SURFEDGES, HL2LUMP_TEXDATA, HL2LUMP_TEXINFO, HL2LUMP_VERTEXES, Host_Error(), i, cvar_t::integer, mod(), mod_brushhl2, Mod_BSP_BoxTouchingLeafPVS(), Mod_BSP_BoxTouchingPVS(), Mod_BSP_BoxTouchingVisibleLeafs(), Mod_BSP_FatPVS(), Mod_BSP_FindBoxClusters(), Mod_BSP_FindNonSolidLocation(), Mod_BSP_GetPVS(), Mod_BSP_PointInLeaf(), Mod_CollisionBIH_PointSuperContents(), Mod_CollisionBIH_TraceBox(), Mod_CollisionBIH_TraceBrush(), Mod_CollisionBIH_TraceLine(), Mod_CollisionBIH_TracePoint(), Mod_Q3BSP_LightPoint(), Mod_Q3BSP_NativeContentsFromSuperContents(), Mod_Q3BSP_SuperContentsFromNativeContents(), Mod_Q3BSP_TraceLineOfSight(), Mod_VBSP_LoadEdges(), Mod_VBSP_LoadEntities(), Mod_VBSP_LoadFaces(), Mod_VBSP_LoadPlanes(), Mod_VBSP_LoadSurfedges(), Mod_VBSP_LoadTexinfo(), Mod_VBSP_LoadTextures(), Mod_VBSP_LoadVertexes(), MSG_InitReadBuffer(), MSG_ReadLittleLong(), NULL, offset, R_AllocTexturePool(), R_Mod_CompileShadowMap(), R_Mod_Draw(), R_Mod_DrawDebug(), R_Mod_DrawDepth(), R_Mod_DrawLight(), R_Mod_DrawPrepass(), R_Mod_DrawShadowMap(), R_Mod_GetLightInfo(), and size.

◆ Mod_VertexRangeFromElements()

void Mod_VertexRangeFromElements ( int numelements,
const int * elements,
int * firstvertexpointer,
int * lastvertexpointer )

Definition at line 2865 of file model_shared.c.

2866{
2867 int i, e;
2868 int firstvertex, lastvertex;
2869 if (numelements > 0 && elements)
2870 {
2871 firstvertex = lastvertex = elements[0];
2872 for (i = 1;i < numelements;i++)
2873 {
2874 e = elements[i];
2875 firstvertex = min(firstvertex, e);
2876 lastvertex = max(lastvertex, e);
2877 }
2878 }
2879 else
2880 firstvertex = lastvertex = 0;
2881 if (firstvertexpointer)
2882 *firstvertexpointer = firstvertex;
2883 if (lastvertexpointer)
2884 *lastvertexpointer = lastvertex;
2885}

References i, max, and min.

◆ 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}
#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.

◆ R_Mod_CompileShadowMap()

void R_Mod_CompileShadowMap ( struct entity_render_s * ent,
vec3_t relativelightorigin,
vec3_t relativelightdirection,
float lightradius,
int numsurfaces,
const int * surfacelist )

◆ R_Mod_Draw()

void R_Mod_Draw ( struct entity_render_s * ent)

◆ R_Mod_DrawAddWaterPlanes()

void R_Mod_DrawAddWaterPlanes ( struct entity_render_s * ent)

◆ R_Mod_DrawDebug()

void R_Mod_DrawDebug ( struct entity_render_s * ent)

◆ R_Mod_DrawDepth()

void R_Mod_DrawDepth ( struct entity_render_s * ent)

◆ R_Mod_DrawLight()

void R_Mod_DrawLight ( struct entity_render_s * ent,
int numsurfaces,
const int * surfacelist,
const unsigned char * trispvs )

◆ R_Mod_DrawPrepass()

void R_Mod_DrawPrepass ( struct entity_render_s * ent)

◆ R_Mod_DrawShadowMap()

void R_Mod_DrawShadowMap ( int side,
struct entity_render_s * 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 )

◆ R_Mod_DrawSky()

void R_Mod_DrawSky ( struct entity_render_s * ent)

◆ R_Mod_GetLightInfo()

void R_Mod_GetLightInfo ( struct entity_render_s * ent,
vec3_t relativelightorigin,
float lightradius,
vec3_t outmins,
vec3_t outmaxs,
int * outleaflist,
unsigned char * outleafpvs,
int * outnumleafspointer,
int * outsurfacelist,
unsigned char * outsurfacepvs,
int * outnumsurfacespointer,
unsigned char * outshadowtrispvs,
unsigned char * outlighttrispvs,
unsigned char * visitingleafpvs,
int numfrustumplanes,
const mplane_t * frustumplanes,
qbool noocclusion )

Variable Documentation

◆ loadmodel

model_t* loadmodel
extern

Definition at line 598 of file model_shared.h.

Referenced by Mod_Alias_CalculateBoundingBox(), Mod_Alias_MorphMesh_CompileFrames(), Mod_AllocSurfMesh(), Mod_BSP_DecompressVis(), Mod_BSP_FinalizePortals(), Mod_BSP_LoadNodes_RecursiveSetParent(), Mod_BSP_LoadSubmodels(), Mod_BSP_MakePortals(), Mod_BSP_RecursiveNodePortals(), Mod_BuildAliasSkinsFromSkinFiles(), Mod_BuildBaseBonePoses(), Mod_BuildVBOs(), Mod_DARKPLACESMODEL_Load(), Mod_GenerateLightmaps(), Mod_GenerateLightmaps_CreateLightmaps(), Mod_IDP0_Load(), Mod_IDP2_Load(), Mod_IDP3_Load(), Mod_IDS2_Load(), Mod_IDSP_Load(), Mod_INTERQUAKEMODEL_Load(), Mod_LoadModel(), Mod_LoadSkinFiles(), Mod_LoadTextureFromQ3Shader(), Mod_MakeCollisionBIH(), Mod_MakeSortedSurfaces(), Mod_MDL_LoadFrames(), Mod_OBJ_Load(), Mod_PSKMODEL_Load(), Mod_Q1BSP_CheckWaterAlphaSupport(), Mod_Q1BSP_Load(), Mod_Q1BSP_LoadClipnodes(), Mod_Q1BSP_LoadEdges(), Mod_Q1BSP_LoadEntities(), Mod_Q1BSP_LoadFaces(), Mod_Q1BSP_LoadLeaffaces(), Mod_Q1BSP_LoadLeafs(), Mod_Q1BSP_LoadLighting(), Mod_Q1BSP_LoadMapBrushes(), Mod_Q1BSP_LoadNodes(), Mod_Q1BSP_LoadPlanes(), Mod_Q1BSP_LoadSplitSky(), Mod_Q1BSP_LoadSurfedges(), Mod_Q1BSP_LoadTexinfo(), Mod_Q1BSP_LoadTextures(), Mod_Q1BSP_LoadVertexes(), Mod_Q1BSP_LoadVisibility(), Mod_Q1BSP_MakeHull0(), Mod_Q1BSP_ParseWadsFromEntityLump(), Mod_Q2BSP_Load(), Mod_Q2BSP_LoadBrushes(), Mod_Q2BSP_LoadBrushSides(), Mod_Q2BSP_LoadLeafBrushes(), Mod_Q2BSP_LoadLeafs(), Mod_Q2BSP_LoadLighting(), Mod_Q2BSP_LoadNodes(), Mod_Q2BSP_LoadTexinfo(), Mod_Q2BSP_LoadVisibility(), Mod_Q3BSP_Load(), Mod_Q3BSP_LoadBrushes(), Mod_Q3BSP_LoadBrushSides(), Mod_Q3BSP_LoadBrushSides_IG(), Mod_Q3BSP_LoadEffects(), Mod_Q3BSP_LoadEntities(), Mod_Q3BSP_LoadFaces(), Mod_Q3BSP_LoadLeafBrushes(), Mod_Q3BSP_LoadLeafFaces(), Mod_Q3BSP_LoadLeafs(), Mod_Q3BSP_LoadLightGrid(), Mod_Q3BSP_LoadLightmaps(), Mod_Q3BSP_LoadModels(), Mod_Q3BSP_LoadNodes(), Mod_Q3BSP_LoadPlanes(), Mod_Q3BSP_LoadPVS(), Mod_Q3BSP_LoadTextures(), Mod_Q3BSP_LoadTriangles(), Mod_Q3BSP_LoadVertices(), Mod_Q3BSP_RecursiveFindNumLeafs(), Mod_Sprite_SharedSetup(), Mod_SpriteSetupTexture(), Mod_VBSP_LoadEdges(), Mod_VBSP_LoadEntities(), Mod_VBSP_LoadFaces(), Mod_VBSP_LoadPlanes(), Mod_VBSP_LoadSurfedges(), Mod_VBSP_LoadTexinfo(), Mod_VBSP_LoadVertexes(), and Mod_ZYMOTICMODEL_Load().

◆ loadname

char loadname[32]
extern

◆ mod_base

◆ mod_noshader_default_offsetmapping

struct cvar_s mod_noshader_default_offsetmapping
extern

Definition at line 51 of file model_brush.c.

51{CF_CLIENT | CF_ARCHIVE, "mod_noshader_default_offsetmapping", "1", "use offsetmapping by default on all surfaces that are not using q3 shader files"};
#define CF_ARCHIVE
cvar should have its set value saved to config.cfg and persist across sessions
Definition cmd.h:53

Referenced by Mod_BrushInit(), Mod_LoadCustomMaterial(), and Mod_LoadTextureFromQ3Shader().

◆ mod_q3bsp_lightgrid_bsp_surfaces

struct cvar_s mod_q3bsp_lightgrid_bsp_surfaces
extern

Definition at line 50 of file model_brush.c.

50{CF_CLIENT, "mod_q3bsp_lightgrid_bsp_surfaces", "0", "apply lightgrid lighting to bsp models other than the world rather than using their lightmaps (experimental/debug tool)"};

Referenced by CL_UpdateEntityShading_Entity(), and Mod_BrushInit().

◆ mod_q3bsp_lightgrid_texture

struct cvar_s mod_q3bsp_lightgrid_texture
extern

Definition at line 48 of file model_brush.c.

48{CF_CLIENT, "mod_q3bsp_lightgrid_texture", "1", "directly apply the lightgrid as a global texture rather than only reading it at the entity origin"};

Referenced by CL_UpdateEntityShading_Entity(), Mod_BrushInit(), and Mod_Q3BSP_LoadLightGrid().

◆ mod_q3bsp_lightgrid_world_surfaces

struct cvar_s mod_q3bsp_lightgrid_world_surfaces
extern

Definition at line 49 of file model_brush.c.

49{CF_CLIENT, "mod_q3bsp_lightgrid_world_surfaces", "0", "apply lightgrid lighting to the world bsp geometry rather than using lightmaps (experimental/debug tool)"};

Referenced by CL_UpdateEntityShading_Entity(), and Mod_BrushInit().

◆ mod_q3shader_default_offsetmapping

struct cvar_s mod_q3shader_default_offsetmapping
extern

Definition at line 52 of file model_brush.c.

52{CF_CLIENT | CF_ARCHIVE, "mod_q3shader_default_offsetmapping", "1", "use offsetmapping by default on all surfaces that are using q3 shader files"};

Referenced by Mod_BrushInit(), and Mod_LoadQ3Shaders().

◆ mod_q3shader_default_offsetmapping_bias

struct cvar_s mod_q3shader_default_offsetmapping_bias
extern

Definition at line 54 of file model_brush.c.

54{CF_CLIENT | CF_ARCHIVE, "mod_q3shader_default_offsetmapping_bias", "0", "default bias used for offsetmapping"};

Referenced by Mod_BrushInit(), and Mod_LoadQ3Shaders().

◆ mod_q3shader_default_offsetmapping_scale

struct cvar_s mod_q3shader_default_offsetmapping_scale
extern

Definition at line 53 of file model_brush.c.

53{CF_CLIENT | CF_ARCHIVE, "mod_q3shader_default_offsetmapping_scale", "1", "default scale used for offsetmapping"};

Referenced by Mod_BrushInit(), and Mod_LoadQ3Shaders().

◆ mod_q3shader_default_polygonfactor

struct cvar_s mod_q3shader_default_polygonfactor
extern

Definition at line 55 of file model_brush.c.

55{CF_CLIENT, "mod_q3shader_default_polygonfactor", "0", "biases depth values of 'polygonoffset' shaders to prevent z-fighting artifacts"};

Referenced by Mod_BrushInit(), and Mod_LoadQ3Shaders().

◆ mod_q3shader_default_polygonoffset

struct cvar_s mod_q3shader_default_polygonoffset
extern

Definition at line 56 of file model_brush.c.

56{CF_CLIENT, "mod_q3shader_default_polygonoffset", "-2", "biases depth values of 'polygonoffset' shaders to prevent z-fighting artifacts"};

Referenced by Mod_BrushInit(), and Mod_LoadQ3Shaders().

◆ mod_q3shader_default_refractive_index

struct cvar_s mod_q3shader_default_refractive_index
extern

Definition at line 57 of file model_brush.c.

57{CF_CLIENT, "mod_q3shader_default_refractive_index", "1.33", "angle of refraction specified as n to apply when a photon is refracted, example values are: 1.0003 = air, water = 1.333, crown glass = 1.517, flint glass = 1.655, diamond = 2.417"};

Referenced by Mod_BrushInit(), Mod_LoadTextureFromQ3Shader(), and Mod_Q1BSP_LoadTextures().

◆ mod_q3shader_force_addalpha

struct cvar_s mod_q3shader_force_addalpha
extern

Definition at line 58 of file model_brush.c.

58{CF_CLIENT, "mod_q3shader_force_addalpha", "0", "treat GL_ONE GL_ONE (or add) blendfunc as GL_SRC_ALPHA GL_ONE for compatibility with older DarkPlaces releases"};

Referenced by Mod_BrushInit(), and Mod_LoadQ3Shaders().

◆ mod_q3shader_force_terrain_alphaflag

struct cvar_s mod_q3shader_force_terrain_alphaflag
extern

Definition at line 59 of file model_brush.c.

59{CF_CLIENT, "mod_q3shader_force_terrain_alphaflag", "0", "for multilayered terrain shaders force TEXF_ALPHA flag on both layers"};

Referenced by Mod_BrushInit(), and Mod_LoadQ3Shaders().

◆ r_fullbrights

struct cvar_s r_fullbrights
extern

Definition at line 122 of file gl_rmain.c.

122{CF_CLIENT | CF_ARCHIVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};

Referenced by GL_Main_Init(), Mod_IDP0_Load(), Mod_Q1BSP_LoadTextures(), and R_LoadQWSkin().

◆ r_mipnormalmaps

struct cvar_s r_mipnormalmaps
extern

Definition at line 31 of file model_shared.c.

31{CF_CLIENT | CF_ARCHIVE, "r_mipnormalmaps", "1", "mipmaps normalmaps (turning it off looks sharper but may have aliasing)"};

Referenced by Mod_Init(), R_SkinFrame_GenerateTexturesFromQPixels(), R_SkinFrame_LoadExternal_SkinFrame(), and R_SkinFrame_LoadInternalBGRA().

◆ r_mipskins

struct cvar_s r_mipskins
extern

Definition at line 30 of file model_shared.c.

30{CF_CLIENT | CF_ARCHIVE, "r_mipskins", "0", "mipmaps model skins so they render faster in the distance and do not display noise artifacts, can cause discoloration of skins if they contain undesirable border colors"};

Referenced by Mod_BuildAliasSkinsFromSkinFiles(), Mod_IDP0_Load(), Mod_IDP2_Load(), Mod_Init(), and R_LoadQWSkin().