#include "r_shadow.h"
#include "polygon.h"
-cvar_t r_mipskins = {CVAR_SAVE, "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"};
-cvar_t r_mipnormalmaps = {CVAR_SAVE, "r_mipnormalmaps", "1", "mipmaps normalmaps (turning it off looks sharper but may have aliasing)"};
-cvar_t mod_generatelightmaps_unitspersample = {CVAR_SAVE, "mod_generatelightmaps_unitspersample", "8", "lightmap resolution"};
-cvar_t mod_generatelightmaps_borderpixels = {CVAR_SAVE, "mod_generatelightmaps_borderpixels", "2", "extra space around polygons to prevent sampling artifacts"};
-cvar_t mod_generatelightmaps_texturesize = {CVAR_SAVE, "mod_generatelightmaps_texturesize", "1024", "size of lightmap textures"};
-cvar_t mod_generatelightmaps_lightmapsamples = {CVAR_SAVE, "mod_generatelightmaps_lightmapsamples", "16", "number of shadow tests done per lightmap pixel"};
-cvar_t mod_generatelightmaps_vertexsamples = {CVAR_SAVE, "mod_generatelightmaps_vertexsamples", "16", "number of shadow tests done per vertex"};
-cvar_t mod_generatelightmaps_gridsamples = {CVAR_SAVE, "mod_generatelightmaps_gridsamples", "64", "number of shadow tests done per lightgrid cell"};
-cvar_t mod_generatelightmaps_lightmapradius = {CVAR_SAVE, "mod_generatelightmaps_lightmapradius", "16", "sampling area around each lightmap pixel"};
-cvar_t mod_generatelightmaps_vertexradius = {CVAR_SAVE, "mod_generatelightmaps_vertexradius", "16", "sampling area around each vertex"};
-cvar_t mod_generatelightmaps_gridradius = {CVAR_SAVE, "mod_generatelightmaps_gridradius", "64", "sampling area around each lightgrid cell center"};
-
-dp_model_t *loadmodel;
+cvar_t r_mipskins = {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"};
+cvar_t r_mipnormalmaps = {CF_CLIENT | CF_ARCHIVE, "r_mipnormalmaps", "1", "mipmaps normalmaps (turning it off looks sharper but may have aliasing)"};
+cvar_t mod_generatelightmaps_unitspersample = {CF_CLIENT | CF_ARCHIVE, "mod_generatelightmaps_unitspersample", "8", "lightmap resolution"};
+cvar_t mod_generatelightmaps_borderpixels = {CF_CLIENT | CF_ARCHIVE, "mod_generatelightmaps_borderpixels", "2", "extra space around polygons to prevent sampling artifacts"};
+cvar_t mod_generatelightmaps_texturesize = {CF_CLIENT | CF_ARCHIVE, "mod_generatelightmaps_texturesize", "1024", "size of lightmap textures"};
+cvar_t mod_generatelightmaps_lightmapsamples = {CF_CLIENT | CF_ARCHIVE, "mod_generatelightmaps_lightmapsamples", "16", "number of shadow tests done per lightmap pixel"};
+cvar_t mod_generatelightmaps_vertexsamples = {CF_CLIENT | CF_ARCHIVE, "mod_generatelightmaps_vertexsamples", "16", "number of shadow tests done per vertex"};
+cvar_t mod_generatelightmaps_gridsamples = {CF_CLIENT | CF_ARCHIVE, "mod_generatelightmaps_gridsamples", "64", "number of shadow tests done per lightgrid cell"};
+cvar_t mod_generatelightmaps_lightmapradius = {CF_CLIENT | CF_ARCHIVE, "mod_generatelightmaps_lightmapradius", "16", "sampling area around each lightmap pixel"};
+cvar_t mod_generatelightmaps_vertexradius = {CF_CLIENT | CF_ARCHIVE, "mod_generatelightmaps_vertexradius", "16", "sampling area around each vertex"};
+cvar_t mod_generatelightmaps_gridradius = {CF_CLIENT | CF_ARCHIVE, "mod_generatelightmaps_gridradius", "64", "sampling area around each lightgrid cell center"};
+
+model_t *loadmodel;
+
+// Supported model formats
+static modloader_t loader[] =
+{
+ {"obj", NULL, 0, Mod_OBJ_Load},
+ {NULL, "IDPO", 4, Mod_IDP0_Load},
+ {NULL, "IDP2", 4, Mod_IDP2_Load},
+ {NULL, "IDP3", 4, Mod_IDP3_Load},
+ {NULL, "IDSP", 4, Mod_IDSP_Load},
+ {NULL, "IDS2", 4, Mod_IDS2_Load},
+ {NULL, "\035", 1, Mod_Q1BSP_Load},
+ {NULL, "\036", 1, Mod_HLBSP_Load},
+ {NULL, "BSP2", 4, Mod_BSP2_Load},
+ {NULL, "2PSB", 4, Mod_2PSB_Load},
+ {NULL, "IBSP", 4, Mod_IBSP_Load},
+ {NULL, "VBSP", 4, Mod_VBSP_Load},
+ {NULL, "ZYMOTICMODEL", 13, Mod_ZYMOTICMODEL_Load},
+ {NULL, "DARKPLACESMODEL", 16, Mod_DARKPLACESMODEL_Load},
+ {NULL, "PSKMODEL", 9, Mod_PSKMODEL_Load},
+ {NULL, "INTERQUAKEMODEL", 16, Mod_INTERQUAKEMODEL_Load},
+ {"map", NULL, 0, Mod_MAP_Load},
+ {NULL, NULL, 0, NULL}
+};
static mempool_t *mod_mempool;
static memexpandablearray_t models;
static mempool_t* q3shaders_mem;
typedef struct q3shader_hash_entry_s
{
- q3shaderinfo_t shader;
+ shader_t shader;
struct q3shader_hash_entry_s* chain;
} q3shader_hash_entry_t;
#define Q3SHADER_HASH_SIZE 1021
{
int i, count;
int nummodels = (int)Mem_ExpandableArray_IndexRange(&models);
- dp_model_t *mod;
+ model_t *mod;
- SCR_PushLoadingScreen(false, "Loading models", 1.0);
+ SCR_PushLoadingScreen("Loading models", 1.0);
count = 0;
for (i = 0;i < nummodels;i++)
- if ((mod = (dp_model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && mod->name[0] != '*')
+ if ((mod = (model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && mod->name[0] != '*')
if (mod->used)
++count;
for (i = 0;i < nummodels;i++)
- if ((mod = (dp_model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && mod->name[0] != '*')
+ if ((mod = (model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && mod->name[0] != '*')
if (mod->used)
{
- SCR_PushLoadingScreen(true, mod->name, 1.0 / count);
+ SCR_PushLoadingScreen(mod->name, 1.0 / count);
Mod_LoadModel(mod, true, false);
SCR_PopLoadingScreen(false);
}
{
int i;
int nummodels = (int)Mem_ExpandableArray_IndexRange(&models);
- dp_model_t *mod;
+ model_t *mod;
for (i = 0;i < nummodels;i++)
- if ((mod = (dp_model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && (mod->loaded || mod->mempool))
+ if ((mod = (model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && (mod->loaded || mod->mempool))
Mod_UnloadModel(mod);
Mod_FreeQ3Shaders();
msurface_t *surface;
int i, j, k, l, surfacenum, ssize, tsize;
int nummodels = (int)Mem_ExpandableArray_IndexRange(&models);
- dp_model_t *mod;
+ model_t *mod;
for (i = 0;i < nummodels;i++)
{
- if ((mod = (dp_model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->mempool)
+ if ((mod = (model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->mempool)
{
for (j = 0;j < mod->num_textures && mod->data_textures;j++)
{
for (i = 0;i < nummodels;i++)
{
- if ((mod = (dp_model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->mempool && mod->data_surfaces)
+ if ((mod = (model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->mempool && mod->data_surfaces)
{
for (surfacenum = 0, surface = mod->data_surfaces;surfacenum < mod->num_surfaces;surfacenum++, surface++)
{
Mod_Init
===============
*/
-static void Mod_Print(void);
-static void Mod_Precache (void);
-static void Mod_Decompile_f(void);
-static void Mod_GenerateLightmaps_f(void);
+static void Mod_Print_f(cmd_state_t *cmd);
+static void Mod_Precache_f(cmd_state_t *cmd);
+static void Mod_Decompile_f(cmd_state_t *cmd);
+static void Mod_GenerateLightmaps_f(cmd_state_t *cmd);
void Mod_Init (void)
{
mod_mempool = Mem_AllocPool("modelinfo", 0, NULL);
- Mem_ExpandableArray_NewArray(&models, mod_mempool, sizeof(dp_model_t), 16);
+ Mem_ExpandableArray_NewArray(&models, mod_mempool, sizeof(model_t), 16);
Mod_BrushInit();
Mod_AliasInit();
Cvar_RegisterVariable(&mod_generatelightmaps_vertexradius);
Cvar_RegisterVariable(&mod_generatelightmaps_gridradius);
- Cmd_AddCommand ("modellist", Mod_Print, "prints a list of loaded models");
- Cmd_AddCommand ("modelprecache", Mod_Precache, "load a model");
- Cmd_AddCommand ("modeldecompile", Mod_Decompile_f, "exports a model in several formats for editing purposes");
- Cmd_AddCommand ("mod_generatelightmaps", Mod_GenerateLightmaps_f, "rebuilds lighting on current worldmodel");
+ Cmd_AddCommand(CF_CLIENT, "modellist", Mod_Print_f, "prints a list of loaded models");
+ Cmd_AddCommand(CF_CLIENT, "modelprecache", Mod_Precache_f, "load a model");
+ Cmd_AddCommand(CF_CLIENT, "modeldecompile", Mod_Decompile_f, "exports a model in several formats for editing purposes");
+ Cmd_AddCommand(CF_CLIENT, "mod_generatelightmaps", Mod_GenerateLightmaps_f, "rebuilds lighting on current worldmodel");
}
void Mod_RenderInit(void)
R_RegisterModule("Models", mod_start, mod_shutdown, mod_newmap, NULL, NULL);
}
-void Mod_UnloadModel (dp_model_t *mod)
+void Mod_UnloadModel (model_t *mod)
{
char name[MAX_QPATH];
- qboolean used;
- dp_model_t *parentmodel;
+ qbool used;
+ model_t *parentmodel;
if (developer_loading.integer)
Con_Printf("unloading model %s\n", mod->name);
R_FreeTexturePool(&mod->texturepool);
Mem_FreePool(&mod->mempool);
// clear the struct to make it available
- memset(mod, 0, sizeof(dp_model_t));
+ memset(mod, 0, sizeof(model_t));
// restore the fields we want to preserve
strlcpy(mod->name, name, sizeof(mod->name));
mod->brush.parentmodel = parentmodel;
}
-typedef void (*mod_framegroupify_parsegroups_t) (unsigned int i, int start, int len, float fps, qboolean loop, const char *name, void *pass);
+typedef void (*mod_framegroupify_parsegroups_t) (unsigned int i, int start, int len, float fps, qbool loop, const char *name, void *pass);
static int Mod_FrameGroupify_ParseGroups(const char *buf, mod_framegroupify_parsegroups_t cb, void *pass)
{
int start, len;
float fps;
unsigned int i;
- qboolean loop;
+ qbool loop;
char name[64];
bufptr = buf;
return i;
}
-static void Mod_FrameGroupify_ParseGroups_Store (unsigned int i, int start, int len, float fps, qboolean loop, const char *name, void *pass)
+static void Mod_FrameGroupify_ParseGroups_Store (unsigned int i, int start, int len, float fps, qbool loop, const char *name, void *pass)
{
- dp_model_t *mod = (dp_model_t *) pass;
+ model_t *mod = (model_t *) pass;
animscene_t *anim = &mod->animscenes[i];
if(name)
strlcpy(anim->name, name, sizeof(anim[i].name));
//Con_Printf("frame group %d is %d %d %f %d\n", i, start, len, fps, loop);
}
-static void Mod_FrameGroupify(dp_model_t *mod, const char *buf)
+static void Mod_FrameGroupify(model_t *mod, const char *buf)
{
unsigned int cnt;
Mod_FrameGroupify_ParseGroups(buf, Mod_FrameGroupify_ParseGroups_Store, mod);
}
-static void Mod_FindPotentialDeforms(dp_model_t *mod)
+static void Mod_FindPotentialDeforms(model_t *mod)
{
int i, j;
texture_t *texture;
Loads a model
==================
*/
-dp_model_t *Mod_LoadModel(dp_model_t *mod, qboolean crash, qboolean checkdisk)
+model_t *Mod_LoadModel(model_t *mod, qbool crash, qbool checkdisk)
{
- int num;
unsigned int crc;
void *buf;
fs_offset_t filesize = 0;
if (developer_loading.integer)
Con_Printf("loading model %s\n", mod->name);
- SCR_PushLoadingScreen(true, mod->name, 1);
+ SCR_PushLoadingScreen(mod->name, 1);
- // LordHavoc: unload the existing model in this slot (if there is one)
+ // LadyHavoc: unload the existing model in this slot (if there is one)
if (mod->loaded || mod->mempool)
Mod_UnloadModel(mod);
if (buf)
{
+ int i;
+ const char *ext = FS_FileExtension(mod->name);
char *bufend = (char *)buf + filesize;
-
// all models use memory, so allocate a memory pool
mod->mempool = Mem_AllocPool(mod->name, 0, NULL);
- num = LittleLong(*((int *)buf));
- // call the apropriate loader
+ // We need to have a reference to the base model in case we're parsing submodels
loadmodel = mod;
- if (!strcasecmp(FS_FileExtension(mod->name), "obj")) Mod_OBJ_Load(mod, buf, bufend);
- else if (!memcmp(buf, "IDPO", 4)) Mod_IDP0_Load(mod, buf, bufend);
- else if (!memcmp(buf, "IDP2", 4)) Mod_IDP2_Load(mod, buf, bufend);
- else if (!memcmp(buf, "IDP3", 4)) Mod_IDP3_Load(mod, buf, bufend);
- else if (!memcmp(buf, "IDSP", 4)) Mod_IDSP_Load(mod, buf, bufend);
- else if (!memcmp(buf, "IDS2", 4)) Mod_IDS2_Load(mod, buf, bufend);
- else if (!memcmp(buf, "IBSP", 4)) Mod_IBSP_Load(mod, buf, bufend);
- else if (!memcmp(buf, "ZYMOTICMODEL", 12)) Mod_ZYMOTICMODEL_Load(mod, buf, bufend);
- else if (!memcmp(buf, "DARKPLACESMODEL", 16)) Mod_DARKPLACESMODEL_Load(mod, buf, bufend);
- else if (!memcmp(buf, "ACTRHEAD", 8)) Mod_PSKMODEL_Load(mod, buf, bufend);
- else if (!memcmp(buf, "INTERQUAKEMODEL", 16)) Mod_INTERQUAKEMODEL_Load(mod, buf, bufend);
- else if (strlen(mod->name) >= 4 && !strcmp(mod->name + strlen(mod->name) - 4, ".map")) Mod_MAP_Load(mod, buf, bufend);
- else if (num == BSPVERSION || num == 30 || !memcmp(buf, "BSP2", 4) || !memcmp(buf, "2PSB", 4)) Mod_Q1BSP_Load(mod, buf, bufend);
- else Con_Printf("Mod_LoadModel: model \"%s\" is of unknown/unsupported type\n", mod->name);
- Mem_Free(buf);
-
- Mod_FindPotentialDeforms(mod);
-
- buf = FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.framegroups", mod->name), tempmempool, false, &filesize);
- if(buf)
+
+ // Call the appropriate loader. Try matching magic bytes.
+ for (i = 0; loader[i].Load; i++)
{
- Mod_FrameGroupify(mod, (const char *)buf);
- Mem_Free(buf);
- }
+ // Headerless formats can just load based on extension. Otherwise match the magic string.
+ if((loader[i].extension && !strcasecmp(ext, loader[i].extension) && !loader[i].header) ||
+ (loader[i].header && !memcmp(buf, loader[i].header, loader[i].headersize)))
+ {
+ // Matched. Load it.
+ loader[i].Load(mod, buf, bufend);
+ Mem_Free(buf);
+
+ Mod_FindPotentialDeforms(mod);
+
+ buf = FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.framegroups", mod->name), tempmempool, false, &filesize);
+ if(buf)
+ {
+ Mod_FrameGroupify(mod, (const char *)buf);
+ Mem_Free(buf);
+ }
- Mod_BuildVBOs();
+ Mod_SetDrawSkyAndWater(mod);
+ Mod_BuildVBOs();
+ break;
+ }
+ }
+ if(!loader[i].Load)
+ Con_Printf(CON_ERROR "Mod_LoadModel: model \"%s\" is of unknown/unsupported type\n", mod->name);
}
else if (crash)
- {
- // LordHavoc: Sys_Error was *ANNOYING*
- Con_Printf ("Mod_LoadModel: %s not found\n", mod->name);
- }
+ // LadyHavoc: Sys_Error was *ANNOYING*
+ Con_Printf (CON_ERROR "Mod_LoadModel: %s not found\n", mod->name);
// no fatal errors occurred, so this model is ready to use.
mod->loaded = true;
{
int i;
int nummodels = (int)Mem_ExpandableArray_IndexRange(&models);
- dp_model_t *mod;
+ model_t *mod;
for (i = 0;i < nummodels;i++)
- if ((mod = (dp_model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0])
+ if ((mod = (model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0])
mod->used = false;
}
{
int i;
int nummodels = (int)Mem_ExpandableArray_IndexRange(&models);
- dp_model_t *mod;
+ model_t *mod;
for (i = 0;i < nummodels;i++)
{
- if ((mod = (dp_model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && !mod->used)
+ if ((mod = (model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && !mod->used)
{
Mod_UnloadModel(mod);
Mem_ExpandableArray_FreeRecord(&models, mod);
==================
*/
-dp_model_t *Mod_FindName(const char *name, const char *parentname)
+model_t *Mod_FindName(const char *name, const char *parentname)
{
int i;
int nummodels;
- dp_model_t *mod;
+ model_t *mod;
if (!parentname)
parentname = "";
- // if we're not dedicatd, the renderer calls will crash without video
- Host_StartVideo();
-
nummodels = (int)Mem_ExpandableArray_IndexRange(&models);
if (!name[0])
// search the currently loaded models
for (i = 0;i < nummodels;i++)
{
- if ((mod = (dp_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))))
+ 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))))
{
mod->used = true;
return mod;
}
// no match found, create a new one
- mod = (dp_model_t *) Mem_ExpandableArray_AllocRecord(&models);
+ mod = (model_t *) Mem_ExpandableArray_AllocRecord(&models);
strlcpy(mod->name, name, sizeof(mod->name));
if (parentname[0])
mod->brush.parentmodel = Mod_FindName(parentname, NULL);
return mod;
}
+extern qbool vid_opened;
+
/*
==================
Mod_ForName
Loads in a model for the given name
==================
*/
-dp_model_t *Mod_ForName(const char *name, qboolean crash, qboolean checkdisk, const char *parentname)
+model_t *Mod_ForName(const char *name, qbool crash, qbool checkdisk, const char *parentname)
{
- dp_model_t *model;
+ model_t *model;
+
+ // FIXME: So we don't crash if a server is started early.
+ if(!vid_opened)
+ CL_StartVideo();
+
model = Mod_FindName(name, parentname);
if (!model->loaded || checkdisk)
Mod_LoadModel(model, crash, checkdisk);
{
int i, count;
int nummodels = (int)Mem_ExpandableArray_IndexRange(&models);
- dp_model_t *mod;
+ model_t *mod;
- SCR_PushLoadingScreen(false, "Reloading models", 1.0);
+ SCR_PushLoadingScreen("Reloading models", 1.0);
count = 0;
for (i = 0;i < nummodels;i++)
- if ((mod = (dp_model_t *) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && mod->name[0] != '*' && mod->used)
+ if ((mod = (model_t *) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && mod->name[0] != '*' && mod->used)
++count;
for (i = 0;i < nummodels;i++)
- if ((mod = (dp_model_t *) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && mod->name[0] != '*' && mod->used)
+ if ((mod = (model_t *) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && mod->name[0] != '*' && mod->used)
{
- SCR_PushLoadingScreen(true, mod->name, 1.0 / count);
+ SCR_PushLoadingScreen(mod->name, 1.0 / count);
Mod_LoadModel(mod, true, true);
SCR_PopLoadingScreen(false);
}
Mod_Print
================
*/
-static void Mod_Print(void)
+static void Mod_Print_f(cmd_state_t *cmd)
{
int i;
int nummodels = (int)Mem_ExpandableArray_IndexRange(&models);
- dp_model_t *mod;
+ model_t *mod;
Con_Print("Loaded models:\n");
for (i = 0;i < nummodels;i++)
{
- if ((mod = (dp_model_t *) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && mod->name[0] != '*')
+ if ((mod = (model_t *) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->name[0] && mod->name[0] != '*')
{
if (mod->brush.numsubmodels)
Con_Printf("%4iK %s (%i submodels)\n", mod->mempool ? (int)((mod->mempool->totalsize + 1023) / 1024) : 0, mod->name, mod->brush.numsubmodels);
Mod_Precache
================
*/
-static void Mod_Precache(void)
+static void Mod_Precache_f(cmd_state_t *cmd)
{
- if (Cmd_Argc() == 2)
- Mod_ForName(Cmd_Argv(1), false, true, Cmd_Argv(1)[0] == '*' ? cl.model_name[1] : NULL);
+ if (Cmd_Argc(cmd) == 2)
+ Mod_ForName(Cmd_Argv(cmd, 1), false, true, Cmd_Argv(cmd, 1)[0] == '*' ? cl.model_name[1] : NULL);
else
Con_Print("usage: modelprecache <filename>\n");
}
return count;
}
-qboolean Mod_ValidateElements(int *element3i, unsigned short *element3s, int numtriangles, int firstvertex, int numvertices, const char *filename, int fileline)
+qbool Mod_ValidateElements(int *element3i, unsigned short *element3s, int numtriangles, int firstvertex, int numvertices, const char *filename, int fileline)
{
int first = firstvertex, last = first + numvertices - 1, numelements = numtriangles * 3;
int i;
}
if (invalidintcount || invalidshortcount || invalidmismatchcount)
{
- Con_Printf("Mod_ValidateElements(%i, %i, %i, %p, %p) called at %s:%d", numelements, first, last, element3i, element3s, filename, fileline);
+ Con_Printf("Mod_ValidateElements(%i, %i, %i, %p, %p) called at %s:%d", numelements, first, last, (void *)element3i, (void *)element3s, filename, fileline);
Con_Printf(", %i elements are invalid in element3i (example: element3i[%i] == %i)", invalidintcount, invalidintexample, element3i ? element3i[invalidintexample] : 0);
Con_Printf(", %i elements are invalid in element3s (example: element3s[%i] == %i)", invalidshortcount, invalidshortexample, element3s ? element3s[invalidshortexample] : 0);
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);
}
// warning: this is an expensive function!
-void Mod_BuildNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const int *elements, float *normal3f, qboolean areaweighting)
+void Mod_BuildNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const int *elements, float *normal3f, qbool areaweighting)
{
int i, j;
const int *element;
#endif
// warning: this is a very expensive function!
-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, qboolean 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)
{
int i, tnum;
float sdir[3], tdir[3], normal[3], *svec, *tvec;
}
}
-void Mod_AllocSurfMesh(mempool_t *mempool, int numvertices, int numtriangles, qboolean lightmapoffsets, qboolean vertexcolors)
+void Mod_AllocSurfMesh(mempool_t *mempool, int numvertices, int numtriangles, qbool lightmapoffsets, qbool vertexcolors)
{
unsigned char *data;
data = (unsigned char *)Mem_Alloc(mempool, numvertices * (3 + 3 + 3 + 3 + 2 + 2 + (vertexcolors ? 4 : 0)) * sizeof(float) + numvertices * (lightmapoffsets ? 1 : 0) * sizeof(int) + numtriangles * sizeof(int[3]) + (numvertices <= 65536 ? numtriangles * sizeof(unsigned short[3]) : 0));
}
}
-shadowmesh_t *Mod_ShadowMesh_Finish(shadowmesh_t *mesh, qboolean createvbo)
+shadowmesh_t *Mod_ShadowMesh_Finish(shadowmesh_t *mesh, qbool createvbo)
{
if (mesh->numverts >= 3 && mesh->numtriangles >= 1)
{
Mem_Free(mesh);
}
-void Mod_CreateCollisionMesh(dp_model_t *mod)
+void Mod_CreateCollisionMesh(model_t *mod)
{
int k, numcollisionmeshtriangles;
- qboolean usesinglecollisionmesh = false;
+ qbool usesinglecollisionmesh = false;
const msurface_t *surface = NULL;
mempool_t *mempool = mod->mempool;
// make a single combined collision mesh for physics engine use
// TODO rewrite this to use the collision brushes as source, to fix issues with e.g. common/caulk which creates no drawsurface
numcollisionmeshtriangles = 0;
- for (k = 0;k < mod->nummodelsurfaces;k++)
+ for (k = mod->submodelsurfaces_start;k < mod->submodelsurfaces_end;k++)
{
- surface = mod->data_surfaces + mod->firstmodelsurface + k;
+ surface = mod->data_surfaces + k;
if (!strcmp(surface->texture->name, "collision") || !strcmp(surface->texture->name, "collisionconvex")) // found collision mesh
{
usesinglecollisionmesh = true;
Mod_ShadowMesh_AddMesh(mod->brush.collisionmesh, mod->surfmesh.data_vertex3f, surface->num_triangles, (mod->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
else
{
- for (k = 0;k < mod->nummodelsurfaces;k++)
+ for (k = mod->submodelsurfaces_start; k < mod->submodelsurfaces_end; k++)
{
- surface = mod->data_surfaces + mod->firstmodelsurface + k;
+ surface = mod->data_surfaces + k;
if (!(surface->texture->supercontents & SUPERCONTENTS_SOLID))
continue;
Mod_ShadowMesh_AddMesh(mod->brush.collisionmesh, mod->surfmesh.data_vertex3f, surface->num_triangles, (mod->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
#endif
#if 0
-void Mod_Terrain_SurfaceRecurseChunk(dp_model_t *model, int stepsize, int x, int y)
+void Mod_Terrain_SurfaceRecurseChunk(model_t *model, int stepsize, int x, int y)
{
float mins[3];
float maxs[3];
// TODO: emit skirt vertices
}
-void Mod_Terrain_UpdateSurfacesForViewOrigin(dp_model_t *model)
+void Mod_Terrain_UpdateSurfacesForViewOrigin(model_t *model)
{
for (y = 0;y < model->terrain.size[1];y += model->terrain.
Mod_Terrain_SurfaceRecurseChunk(model, model->terrain.maxstepsize, x, y);
Mem_FreePool(&q3shaders_mem);
}
-static void Q3Shader_AddToHash (q3shaderinfo_t* shader)
+static void Q3Shader_AddToHash (shader_t* shader)
{
unsigned short hash = CRC_Block_CaseInsensitive ((const unsigned char *)shader->name, strlen (shader->name));
q3shader_hash_entry_t* entry = q3shader_data->hash + (hash % Q3SHADER_HASH_SIZE);
/* else: head of chain, in hash entry array */
entry = lastEntry;
}
- memcpy (&entry->shader, shader, sizeof (q3shaderinfo_t));
+ memcpy (&entry->shader, shader, sizeof (shader_t));
}
-extern cvar_t mod_noshader_default_offsetmapping;
-extern cvar_t mod_q3shader_default_offsetmapping;
-extern cvar_t mod_q3shader_default_offsetmapping_scale;
-extern cvar_t mod_q3shader_default_offsetmapping_bias;
-extern cvar_t mod_q3shader_default_polygonoffset;
-extern cvar_t mod_q3shader_default_polygonfactor;
-extern cvar_t mod_q3shader_force_addalpha;
-extern cvar_t mod_q3shader_force_terrain_alphaflag;
void Mod_LoadQ3Shaders(void)
{
int j;
fssearch_t *search;
char *f;
const char *text;
- q3shaderinfo_t shader;
+ shader_t shader;
q3shaderinfo_layer_t *layer;
int numparameters;
char parameter[TEXTURE_MAXFRAMES + 4][Q3PATHLENGTH];
char *custsurfaceparmnames[256]; // VorteX: q3map2 has 64 but well, someone will need more
unsigned long custsurfaceflags[256];
int numcustsurfaceflags;
- qboolean dpshaderkill;
+ qbool dpshaderkill;
Mod_FreeQ3Shaders();
}
// parse shaders
- search = FS_Search("scripts/*.shader", true, false);
+ search = FS_Search("scripts/*.shader", true, false, NULL);
if (!search)
return;
for (fileindex = 0;fileindex < search->numfilenames;fileindex++)
// this sets dpshaderkill to true if dpshaderkillifcvarzero was used, and to false if dpnoshaderkillifcvarzero was used
else if (((dpshaderkill = !strcasecmp(parameter[0], "dpshaderkillifcvarzero")) || !strcasecmp(parameter[0], "dpnoshaderkillifcvarzero")) && numparameters >= 2)
{
- if (Cvar_VariableValue(parameter[1]) == 0.0f)
+ if (Cvar_VariableValue(&cvars_all, parameter[1], ~0) == 0.0f)
shader.dpshaderkill = dpshaderkill;
}
// this sets dpshaderkill to true if dpshaderkillifcvar was used, and to false if dpnoshaderkillifcvar was used
op = parameter[2];
if(!op)
{
- if (Cvar_VariableValue(parameter[1]) != 0.0f)
+ if (Cvar_VariableValue(&cvars_all, parameter[1], ~0) != 0.0f)
shader.dpshaderkill = dpshaderkill;
}
else if (numparameters >= 4 && !strcmp(op, "=="))
{
- if (Cvar_VariableValue(parameter[1]) == atof(parameter[3]))
+ if (Cvar_VariableValue(&cvars_all, parameter[1], ~0) == atof(parameter[3]))
shader.dpshaderkill = dpshaderkill;
}
else if (numparameters >= 4 && !strcmp(op, "!="))
{
- if (Cvar_VariableValue(parameter[1]) != atof(parameter[3]))
+ if (Cvar_VariableValue(&cvars_all, parameter[1], ~0) != atof(parameter[3]))
shader.dpshaderkill = dpshaderkill;
}
else if (numparameters >= 4 && !strcmp(op, ">"))
{
- if (Cvar_VariableValue(parameter[1]) > atof(parameter[3]))
+ if (Cvar_VariableValue(&cvars_all, parameter[1], ~0) > atof(parameter[3]))
shader.dpshaderkill = dpshaderkill;
}
else if (numparameters >= 4 && !strcmp(op, "<"))
{
- if (Cvar_VariableValue(parameter[1]) < atof(parameter[3]))
+ if (Cvar_VariableValue(&cvars_all, parameter[1], ~0) < atof(parameter[3]))
shader.dpshaderkill = dpshaderkill;
}
else if (numparameters >= 4 && !strcmp(op, ">="))
{
- if (Cvar_VariableValue(parameter[1]) >= atof(parameter[3]))
+ if (Cvar_VariableValue(&cvars_all, parameter[1], ~0) >= atof(parameter[3]))
shader.dpshaderkill = dpshaderkill;
}
else if (numparameters >= 4 && !strcmp(op, "<="))
{
- if (Cvar_VariableValue(parameter[1]) <= atof(parameter[3]))
+ if (Cvar_VariableValue(&cvars_all, parameter[1], ~0) <= atof(parameter[3]))
shader.dpshaderkill = dpshaderkill;
}
else
Mem_Free(custsurfaceparmnames[j]);
}
-q3shaderinfo_t *Mod_LookupQ3Shader(const char *name)
+shader_t *Mod_LookupQ3Shader(const char *name)
{
unsigned short hash;
q3shader_hash_entry_t* entry;
return shaderpass;
}
-qboolean Mod_LoadTextureFromQ3Shader(mempool_t *mempool, const char *modelname, texture_t *texture, const char *name, qboolean warnmissing, qboolean fallback, int defaulttexflags, int defaultmaterialflags)
+qbool Mod_LoadTextureFromQ3Shader(mempool_t *mempool, const char *modelname, texture_t *texture, const char *name, qbool warnmissing, qbool fallback, int defaulttexflags, int defaultmaterialflags)
{
int texflagsmask, texflagsor;
- qboolean success = true;
- q3shaderinfo_t *shader;
+ qbool success = true;
+ shader_t *shader;
if (!name)
name = "";
strlcpy(texture->name, name, sizeof(texture->name));
texture->specularscalemod = shader->specularscalemod;
texture->specularpowermod = shader->specularpowermod;
texture->rtlightambient = shader->rtlightambient;
+ texture->refractive_index = mod_q3shader_default_refractive_index.value;
if (shader->dpreflectcube[0])
texture->reflectcubetexture = R_GetCubemap(shader->dpreflectcube);
{
if (developer_extra.integer)
Con_DPrintf("^1%s:^7 using fallback noshader material for ^3\"%s\"\n", modelname, name);
+ texture->basematerialflags = defaultmaterialflags;
texture->supercontents = SUPERCONTENTS_SOLID | SUPERCONTENTS_OPAQUE;
}
else if (!strcmp(texture->name, "common/nodraw") || !strcmp(texture->name, "textures/common/nodraw"))
texture->backgroundcurrentskinframe = NULL;
}
-void Mod_UnloadCustomMaterial(texture_t *texture, qboolean purgeskins)
+void Mod_UnloadCustomMaterial(texture_t *texture, qbool purgeskins)
{
- int i, j;
+ long unsigned int i, j;
for (i = 0; i < sizeof(texture->shaderpasses) / sizeof(texture->shaderpasses[0]); i++)
{
if (texture->shaderpasses[i])
*lastvertexpointer = lastvertex;
}
-void Mod_MakeSortedSurfaces(dp_model_t *mod)
+void Mod_SetDrawSkyAndWater(model_t* mod)
+{
+ int j;
+ uint64_t basematerialflags = 0;
+ // by default assume there is no sky or water used in this model
+ mod->DrawSky = NULL;
+ mod->DrawAddWaterPlanes = NULL;
+ // combine all basematerialflags observed in the submodelsurfaces range, then check for special flags
+ for (j = mod->submodelsurfaces_start; j < mod->submodelsurfaces_end; j++)
+ if (mod->data_surfaces[j].texture)
+ basematerialflags |= mod->data_surfaces[j].texture->basematerialflags;
+ if (basematerialflags & MATERIALFLAG_SKY)
+ mod->DrawSky = R_Mod_DrawSky;
+ if (basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
+ mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
+}
+
+typedef struct Mod_MakeSortedSurfaces_qsortsurface_s
+{
+ int surfaceindex;
+ q3deffect_t* effect;
+ texture_t* texture;
+ rtexture_t* lightmaptexture;
+}
+Mod_MakeSortedSurfaces_qsortsurface_t;
+
+static int Mod_MakeSortedSurfaces_qsortfunc(const void *a, const void *b)
+{
+ const Mod_MakeSortedSurfaces_qsortsurface_t* l = (Mod_MakeSortedSurfaces_qsortsurface_t*)a;
+ const Mod_MakeSortedSurfaces_qsortsurface_t* r = (Mod_MakeSortedSurfaces_qsortsurface_t*)b;
+ if (l->effect < r->effect)
+ return -1;
+ if (l->effect > r->effect)
+ return 1;
+ if (l->texture < r->texture)
+ return -1;
+ if (l->texture > r->texture)
+ return 1;
+ if (l->lightmaptexture < r->lightmaptexture)
+ return -1;
+ if (l->lightmaptexture > r->lightmaptexture)
+ return 1;
+ if (l->surfaceindex < r->surfaceindex)
+ return -1;
+ if (l->surfaceindex > r->surfaceindex)
+ return 1;
+ return 0;
+}
+
+void Mod_MakeSortedSurfaces(model_t *mod)
{
// make an optimal set of texture-sorted batches to draw...
- int j, t;
- int *firstsurfacefortexture;
- int *numsurfacesfortexture;
- if (!mod->sortedmodelsurfaces)
- mod->sortedmodelsurfaces = (int *) Mem_Alloc(loadmodel->mempool, mod->nummodelsurfaces * sizeof(*mod->sortedmodelsurfaces));
- firstsurfacefortexture = (int *) Mem_Alloc(tempmempool, mod->num_textures * sizeof(*firstsurfacefortexture));
- numsurfacesfortexture = (int *) Mem_Alloc(tempmempool, mod->num_textures * sizeof(*numsurfacesfortexture));
- memset(numsurfacesfortexture, 0, mod->num_textures * sizeof(*numsurfacesfortexture));
- for (j = 0;j < mod->nummodelsurfaces;j++)
- {
- const msurface_t *surface = mod->data_surfaces + j + mod->firstmodelsurface;
- t = (int)(surface->texture - mod->data_textures);
- numsurfacesfortexture[t]++;
- }
- j = 0;
- for (t = 0;t < mod->num_textures;t++)
- {
- firstsurfacefortexture[t] = j;
- j += numsurfacesfortexture[t];
- }
- for (j = 0;j < mod->nummodelsurfaces;j++)
+ int j, k;
+ Mod_MakeSortedSurfaces_qsortsurface_t *info;
+
+ if(cls.state == ca_dedicated)
+ return;
+
+ info = (Mod_MakeSortedSurfaces_qsortsurface_t*)Mem_Alloc(loadmodel->mempool, mod->num_surfaces * sizeof(*info));
+ if (!mod->modelsurfaces_sorted)
+ mod->modelsurfaces_sorted = (int *) Mem_Alloc(loadmodel->mempool, mod->num_surfaces * sizeof(*mod->modelsurfaces_sorted));
+ // the goal is to sort by submodel (can't change which submodel a surface belongs to), and then by effects and textures
+ for (j = 0; j < mod->num_surfaces; j++)
{
- const msurface_t *surface = mod->data_surfaces + j + mod->firstmodelsurface;
- t = (int)(surface->texture - mod->data_textures);
- mod->sortedmodelsurfaces[firstsurfacefortexture[t]++] = j + mod->firstmodelsurface;
+ info[j].surfaceindex = j;
+ info[j].effect = mod->data_surfaces[j].effect;
+ info[j].texture = mod->data_surfaces[j].texture;
+ info[j].lightmaptexture = mod->data_surfaces[j].lightmaptexture;
}
- Mem_Free(firstsurfacefortexture);
- Mem_Free(numsurfacesfortexture);
+ for (k = 0; k < mod->brush.numsubmodels; k++)
+ if (mod->brush.submodels[k]->submodelsurfaces_end > mod->brush.submodels[k]->submodelsurfaces_start + 1)
+ 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);
+ for (j = 0; j < mod->num_surfaces; j++)
+ mod->modelsurfaces_sorted[j] = info[j].surfaceindex;
+ Mem_Free(info);
}
void Mod_BuildVBOs(void)
}
extern cvar_t mod_obj_orientation;
-static void Mod_Decompile_OBJ(dp_model_t *model, const char *filename, const char *mtlfilename, const char *originalfilename)
+static void Mod_Decompile_OBJ(model_t *model, const char *filename, const char *mtlfilename, const char *originalfilename)
{
int submodelindex, vertexindex, surfaceindex, triangleindex, textureindex, countvertices = 0, countsurfaces = 0, countfaces = 0, counttextures = 0;
int a, b, c;
const msurface_t *surface;
const int maxtextures = 256;
char *texturenames = (char *) Z_Malloc(maxtextures * MAX_QPATH);
- dp_model_t *submodel;
+ model_t *submodel;
// construct the mtllib file
l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "# mtllib for %s exported by darkplaces engine\n", originalfilename);
if (l > 0)
outbufferpos += l;
submodel = model->brush.numsubmodels ? model->brush.submodels[submodelindex] : model;
- for (surfaceindex = 0;surfaceindex < submodel->nummodelsurfaces;surfaceindex++)
+ for (surfaceindex = submodel->submodelsurfaces_start;surfaceindex < submodel->submodelsurfaces_end;surfaceindex++)
{
- surface = model->data_surfaces + submodel->sortedmodelsurfaces[surfaceindex];
+ surface = model->data_surfaces + surfaceindex;
l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "usemtl %s\n", (surface->texture && surface->texture->name[0]) ? surface->texture->name : "default");
if (l > 0)
outbufferpos += l;
Con_Printf("Wrote %s (%i bytes, %i vertices, %i faces, %i surfaces with %i distinct textures)\n", filename, (int)outbufferpos, countvertices, countfaces, countsurfaces, counttextures);
}
-static void Mod_Decompile_SMD(dp_model_t *model, const char *filename, int firstpose, int numposes, qboolean writetriangles)
+static void Mod_Decompile_SMD(model_t *model, const char *filename, int firstpose, int numposes, qbool writetriangles)
{
int countnodes = 0, counttriangles = 0, countframes = 0;
int surfaceindex;
// strangely the smd angles are for a transposed matrix, so we
// have to generate a transposed matrix, then convert that...
Matrix4x4_FromBonePose7s(&posematrix, model->num_posescale, model->data_poses7s + 7*(model->num_bones * poseindex + transformindex));
- Matrix4x4_ToArray12FloatGL(&posematrix, mtest[0]);
+ Matrix4x4_ToArray12FloatGL(&posematrix, mtest);
AnglesFromVectors(angles, mtest[0], mtest[2], false);
if (angles[0] >= 180) angles[0] -= 360;
if (angles[1] >= 180) angles[1] -= 360;
decompiles a model to editable files
================
*/
-static void Mod_Decompile_f(void)
+static void Mod_Decompile_f(cmd_state_t *cmd)
{
int i, j, k, l, first, count;
- dp_model_t *mod;
+ model_t *mod;
char inname[MAX_QPATH];
char outname[MAX_QPATH];
char mtlname[MAX_QPATH];
int framegroupstextsize = 0;
char vabuf[1024];
- if (Cmd_Argc() != 2)
+ if (Cmd_Argc(cmd) != 2)
{
Con_Print("usage: modeldecompile <filename>\n");
return;
}
- strlcpy(inname, Cmd_Argv(1), sizeof(inname));
+ strlcpy(inname, Cmd_Argv(cmd, 1), sizeof(inname));
FS_StripExtension(inname, basename, sizeof(basename));
mod = Mod_ForName(inname, false, true, inname[0] == '*' ? cl.model_name[1] : NULL);
memset(state, 0, sizeof(*state));
}
-qboolean Mod_AllocLightmap_Block(mod_alloclightmap_state_t *state, int blockwidth, int blockheight, int *outx, int *outy)
+qbool Mod_AllocLightmap_Block(mod_alloclightmap_state_t *state, int blockwidth, int blockheight, int *outx, int *outy)
{
mod_alloclightmap_row_t *row;
int y;
extern cvar_t r_shadow_lightattenuationdividebias;
extern cvar_t r_shadow_lightattenuationlinearscale;
-static void Mod_GenerateLightmaps_LightPoint(dp_model_t *model, const vec3_t pos, vec3_t ambient, vec3_t diffuse, vec3_t lightdir)
+static void Mod_GenerateLightmaps_LightPoint(model_t *model, const vec3_t pos, vec3_t ambient, vec3_t diffuse, vec3_t lightdir)
{
int i;
int index;
VectorCopy(dir, lightdir);
}
-static void Mod_GenerateLightmaps_CreateLights_ComputeSVBSP_InsertSurfaces(const dp_model_t *model, svbsp_t *svbsp, const float *mins, const float *maxs)
+static void Mod_GenerateLightmaps_CreateLights_ComputeSVBSP_InsertSurfaces(const model_t *model, svbsp_t *svbsp, const float *mins, const float *maxs)
{
int surfaceindex;
int triangleindex;
const int *element3i = model->surfmesh.data_element3i;
const int *e;
float v2[3][3];
- for (surfaceindex = 0, surface = model->data_surfaces;surfaceindex < model->nummodelsurfaces;surfaceindex++, surface++)
+ for (surfaceindex = model->submodelsurfaces_start;surfaceindex < model->submodelsurfaces_end;surfaceindex++)
{
+ surface = model->data_surfaces + surfaceindex;
if (!BoxesOverlap(surface->mins, surface->maxs, mins, maxs))
continue;
if (surface->texture->basematerialflags & MATERIALFLAG_NOSHADOW)
}
}
-static void Mod_GenerateLightmaps_CreateLights_ComputeSVBSP(dp_model_t *model, lightmaplight_t *lightinfo)
+static void Mod_GenerateLightmaps_CreateLights_ComputeSVBSP(model_t *model, lightmaplight_t *lightinfo)
{
int maxnodes = 1<<14;
svbsp_node_t *nodes;
Mem_Free(nodes);
}
-static void Mod_GenerateLightmaps_CreateLights(dp_model_t *model)
+static void Mod_GenerateLightmaps_CreateLights(model_t *model)
{
int index;
int result;
}
}
-static void Mod_GenerateLightmaps_DestroyLights(dp_model_t *model)
+static void Mod_GenerateLightmaps_DestroyLights(model_t *model)
{
int i;
if (mod_generatelightmaps_lightinfo)
mod_generatelightmaps_numlights = 0;
}
-static qboolean Mod_GenerateLightmaps_SamplePoint_SVBSP(const svbsp_t *svbsp, const float *pos)
+static qbool Mod_GenerateLightmaps_SamplePoint_SVBSP(const svbsp_t *svbsp, const float *pos)
{
const svbsp_node_t *node;
const svbsp_node_t *nodes = svbsp->nodes;
else {s->diffusepitch = (unsigned char)(acos(dir[2]) * (127.5f/M_PI));s->diffuseyaw = (unsigned char)(atan2(dir[1], dir[0]) * (127.5f/M_PI));}
}
-static void Mod_GenerateLightmaps_InitSampleOffsets(dp_model_t *model)
+static void Mod_GenerateLightmaps_InitSampleOffsets(model_t *model)
{
float radius[3];
float temp[3];
}
}
-static void Mod_GenerateLightmaps_DestroyLightmaps(dp_model_t *model)
+static void Mod_GenerateLightmaps_DestroyLightmaps(model_t *model)
{
msurface_t *surface;
int surfaceindex;
}
}
-static void Mod_GenerateLightmaps_UnweldTriangles(dp_model_t *model)
+static void Mod_GenerateLightmaps_UnweldTriangles(model_t *model)
{
msurface_t *surface;
int surfaceindex;
model->brush.submodels[i]->surfmesh = model->surfmesh;
}
-static void Mod_GenerateLightmaps_CreateTriangleInformation(dp_model_t *model)
+static void Mod_GenerateLightmaps_CreateTriangleInformation(model_t *model)
{
msurface_t *surface;
int surfaceindex;
}
}
-static void Mod_GenerateLightmaps_DestroyTriangleInformation(dp_model_t *model)
+static void Mod_GenerateLightmaps_DestroyTriangleInformation(model_t *model)
{
if (mod_generatelightmaps_lightmaptriangles)
Mem_Free(mod_generatelightmaps_lightmaptriangles);
float lmaxis[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
-static void Mod_GenerateLightmaps_CreateLightmaps(dp_model_t *model)
+static void Mod_GenerateLightmaps_CreateLightmaps(model_t *model)
{
msurface_t *surface;
int surfaceindex;
}
}
-static void Mod_GenerateLightmaps_UpdateVertexColors(dp_model_t *model)
+static void Mod_GenerateLightmaps_UpdateVertexColors(model_t *model)
{
int i;
for (i = 0;i < model->surfmesh.num_vertices;i++)
Mod_GenerateLightmaps_VertexSample(model->surfmesh.data_vertex3f + 3*i, model->surfmesh.data_normal3f + 3*i, model->surfmesh.data_lightmapcolor4f + 4*i);
}
-static void Mod_GenerateLightmaps_UpdateLightGrid(dp_model_t *model)
+static void Mod_GenerateLightmaps_UpdateLightGrid(model_t *model)
{
int x;
int y;
}
extern cvar_t mod_q3bsp_nolightmaps;
-static void Mod_GenerateLightmaps(dp_model_t *model)
+static void Mod_GenerateLightmaps(model_t *model)
{
//lightmaptriangle_t *lightmaptriangles = Mem_Alloc(model->mempool, model->surfmesh.num_triangles * sizeof(lightmaptriangle_t));
- dp_model_t *oldloadmodel = loadmodel;
+ model_t *oldloadmodel = loadmodel;
loadmodel = model;
Mod_GenerateLightmaps_InitSampleOffsets(model);
loadmodel = oldloadmodel;
}
-static void Mod_GenerateLightmaps_f(void)
+static void Mod_GenerateLightmaps_f(cmd_state_t *cmd)
{
- if (Cmd_Argc() != 1)
+ if (Cmd_Argc(cmd) != 1)
{
Con_Printf("usage: mod_generatelightmaps\n");
return;
Mod_GenerateLightmaps(cl.worldmodel);
}
-void Mod_Mesh_Create(dp_model_t *mod, const char *name)
+void Mod_Mesh_Create(model_t *mod, const char *name)
{
memset(mod, 0, sizeof(*mod));
strlcpy(mod->name, name, sizeof(mod->name));
mod->mempool = Mem_AllocPool(name, 0, NULL);
mod->texturepool = R_AllocTexturePool();
- mod->Draw = R_Q1BSP_Draw;
- mod->DrawDepth = R_Q1BSP_DrawDepth;
- mod->DrawDebug = R_Q1BSP_DrawDebug;
- mod->DrawPrepass = R_Q1BSP_DrawPrepass;
- mod->GetLightInfo = R_Q1BSP_GetLightInfo;
- mod->DrawShadowMap = R_Q1BSP_DrawShadowMap;
- mod->DrawLight = R_Q1BSP_DrawLight;
+ mod->Draw = R_Mod_Draw;
+ mod->DrawDepth = R_Mod_DrawDepth;
+ mod->DrawDebug = R_Mod_DrawDebug;
+ mod->DrawPrepass = R_Mod_DrawPrepass;
+ mod->GetLightInfo = R_Mod_GetLightInfo;
+ mod->DrawShadowMap = R_Mod_DrawShadowMap;
+ mod->DrawLight = R_Mod_DrawLight;
}
-void Mod_Mesh_Destroy(dp_model_t *mod)
+void Mod_Mesh_Destroy(model_t *mod)
{
Mod_UnloadModel(mod);
}
// resets the mesh model to have no geometry to render, ready for a new frame -
// the mesh will be prepared for rendering later using Mod_Mesh_Finalize
-void Mod_Mesh_Reset(dp_model_t *mod)
+void Mod_Mesh_Reset(model_t *mod)
{
mod->num_surfaces = 0;
mod->surfmesh.num_vertices = 0;
mod->DrawAddWaterPlanes = NULL; // will be set if a texture needs it
}
-texture_t *Mod_Mesh_GetTexture(dp_model_t *mod, const char *name, int defaultdrawflags, int defaulttexflags, int defaultmaterialflags)
+texture_t *Mod_Mesh_GetTexture(model_t *mod, const char *name, int defaultdrawflags, int defaulttexflags, int defaultmaterialflags)
{
int i;
texture_t *t;
- for (i = 0; i < mod->num_textures; i++)
- if (!strcmp(mod->data_textures[i].name, name))
- return mod->data_textures + i;
+ int drawflag = defaultdrawflags & DRAWFLAG_MASK;
+ for (i = 0, t = mod->data_textures; i < mod->num_textures; i++, t++)
+ if (!strcmp(t->name, name) && t->mesh_drawflag == drawflag && t->mesh_defaulttexflags == defaulttexflags && t->mesh_defaultmaterialflags == defaultmaterialflags)
+ return t;
if (mod->max_textures <= mod->num_textures)
{
texture_t *oldtextures = mod->data_textures;
mod->data_surfaces[i].texture = mod->data_textures + (mod->data_surfaces[i].texture - oldtextures);
}
t = &mod->data_textures[mod->num_textures++];
- Mod_LoadTextureFromQ3Shader(mod->mempool, mod->name, t, name, false, true, defaulttexflags, defaultmaterialflags);
+ Mod_LoadTextureFromQ3Shader(mod->mempool, mod->name, t, name, true, true, defaulttexflags, defaultmaterialflags);
+ t->mesh_drawflag = drawflag;
+ t->mesh_defaulttexflags = defaulttexflags;
+ t->mesh_defaultmaterialflags = defaultmaterialflags;
switch (defaultdrawflags & DRAWFLAG_MASK)
{
case DRAWFLAG_ADDITIVE:
return t;
}
-msurface_t *Mod_Mesh_AddSurface(dp_model_t *mod, texture_t *tex, qboolean batchwithprevioussurface)
+msurface_t *Mod_Mesh_AddSurface(model_t *mod, texture_t *tex, qbool batchwithprevioussurface)
{
msurface_t *surf;
// batch if possible; primarily useful for UI rendering where bounding boxes don't matter
{
mod->max_surfaces = 2 * max(mod->num_surfaces, 64);
mod->data_surfaces = (msurface_t *)Mem_Realloc(mod->mempool, mod->data_surfaces, mod->max_surfaces * sizeof(*mod->data_surfaces));
- mod->sortedmodelsurfaces = (int *)Mem_Realloc(mod->mempool, mod->sortedmodelsurfaces, mod->max_surfaces * sizeof(*mod->sortedmodelsurfaces));
+ mod->modelsurfaces_sorted = (int *)Mem_Realloc(mod->mempool, mod->modelsurfaces_sorted, mod->max_surfaces * sizeof(*mod->modelsurfaces_sorted));
}
surf = mod->data_surfaces + mod->num_surfaces;
mod->num_surfaces++;
surf->num_firsttriangle = mod->surfmesh.num_triangles;
surf->num_firstvertex = mod->surfmesh.num_vertices;
if (tex->basematerialflags & (MATERIALFLAG_SKY))
- mod->DrawSky = R_Q1BSP_DrawSky;
+ mod->DrawSky = R_Mod_DrawSky;
if (tex->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
- mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
+ mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
return surf;
}
-int Mod_Mesh_IndexForVertex(dp_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)
+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)
{
int hashindex, h, vnum, mask;
surfmesh_t *mesh = &mod->surfmesh;
return vnum;
}
-void Mod_Mesh_AddTriangle(dp_model_t *mod, msurface_t *surf, int e0, int e1, int e2)
+void Mod_Mesh_AddTriangle(model_t *mod, msurface_t *surf, int e0, int e1, int e2)
{
surfmesh_t *mesh = &mod->surfmesh;
if (mesh->max_triangles == mesh->num_triangles)
surf->num_triangles++;
}
-static void Mod_Mesh_MakeSortedSurfaces(dp_model_t *mod)
+static void Mod_Mesh_MakeSortedSurfaces(model_t *mod)
{
int i, j;
texture_t *tex;
- msurface_t *surf, *surf2;
// build the sorted surfaces list properly to reduce material setup
// this is easy because we're just sorting on texture and don't care about the order of textures
- mod->nummodelsurfaces = 0;
+ mod->submodelsurfaces_start = 0;
+ mod->submodelsurfaces_end = 0;
for (i = 0; i < mod->num_surfaces; i++)
mod->data_surfaces[i].included = false;
for (i = 0; i < mod->num_surfaces; i++)
{
- surf = mod->data_surfaces + i;
- if (surf->included)
+ if (mod->data_surfaces[i].included)
continue;
- tex = surf->texture;
+ tex = mod->data_surfaces[i].texture;
// j = i is intentional
for (j = i; j < mod->num_surfaces; j++)
{
- surf2 = mod->data_surfaces + j;
- if (surf2->included)
- continue;
- if (surf2->texture == tex)
+ if (!mod->data_surfaces[j].included && mod->data_surfaces[j].texture == tex)
{
- surf2->included = true;
- mod->sortedmodelsurfaces[mod->nummodelsurfaces++] = j;
+ mod->data_surfaces[j].included = 1;
+ mod->modelsurfaces_sorted[mod->submodelsurfaces_end++] = j;
}
}
}
}
-void Mod_Mesh_ComputeBounds(dp_model_t *mod)
+static void Mod_Mesh_ComputeBounds(model_t *mod)
{
int i;
vec_t x2a, x2b, y2a, y2b, z2a, z2b, x2, y2, z2, yawradius, rotatedradius;
}
}
-void Mod_Mesh_Validate(dp_model_t *mod)
+void Mod_Mesh_Validate(model_t *mod)
{
int i;
- qboolean warned = false;
+ qbool warned = false;
for (i = 0; i < mod->num_surfaces; i++)
{
msurface_t *surf = mod->data_surfaces + i;
}
}
-void Mod_Mesh_UploadDynamicBuffers(dp_model_t *mod)
+static void Mod_Mesh_UploadDynamicBuffers(model_t *mod)
{
mod->surfmesh.data_element3s_indexbuffer = mod->surfmesh.data_element3s ? R_BufferData_Store(mod->surfmesh.num_triangles * sizeof(short[3]), mod->surfmesh.data_element3s, R_BUFFERDATA_INDEX16, &mod->surfmesh.data_element3s_bufferoffset) : NULL;
mod->surfmesh.data_element3i_indexbuffer = mod->surfmesh.data_element3i ? R_BufferData_Store(mod->surfmesh.num_triangles * sizeof(int[3]), mod->surfmesh.data_element3i, R_BUFFERDATA_INDEX32, &mod->surfmesh.data_element3i_bufferoffset) : NULL;
mod->surfmesh.data_skeletalweight4ub_vertexbuffer = mod->surfmesh.data_skeletalweight4ub ? R_BufferData_Store(mod->surfmesh.num_vertices * sizeof(unsigned char[4]), mod->surfmesh.data_skeletalweight4ub, R_BUFFERDATA_VERTEX, &mod->surfmesh.data_skeletalweight4ub_bufferoffset) : NULL;
}
-void Mod_Mesh_Finalize(dp_model_t *mod)
+void Mod_Mesh_Finalize(model_t *mod)
{
if (gl_paranoid.integer)
Mod_Mesh_Validate(mod);
Mod_Mesh_ComputeBounds(mod);
Mod_Mesh_MakeSortedSurfaces(mod);
- 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);
+ if(!r_refdef.draw2dstage)
+ 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);
Mod_Mesh_UploadDynamicBuffers(mod);
}