Con_Printf("t(%f %f %f,%f %f %f,%i %f %f %f)", rhc.start[0], rhc.start[1], rhc.start[2], rhc.end[0], rhc.end[1], rhc.end[2], rhc.hull - model->brushq1.hulls, rhc.hull->clip_mins[0], rhc.hull->clip_mins[1], rhc.hull->clip_mins[2]);
Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end);
{
-
+
double test[3];
trace_t testtrace;
VectorLerp(rhc.start, rhc.trace->fraction, rhc.end, test);
cbox_planes[3].normal[0] = 0;cbox_planes[3].normal[1] = -1;cbox_planes[3].normal[2] = 0;cbox_planes[3].dist = maxs[1] - cmins[1];
cbox_planes[4].normal[0] = 0;cbox_planes[4].normal[1] = 0;cbox_planes[4].normal[2] = 1;cbox_planes[4].dist = cmaxs[2] - mins[2];
cbox_planes[5].normal[0] = 0;cbox_planes[5].normal[1] = 0;cbox_planes[5].normal[2] = -1;cbox_planes[5].dist = maxs[2] - cmins[2];
- cbox_planes[0].supercontents = boxsupercontents;cbox_planes[0].q3surfaceflags = boxq3surfaceflags;cbox_planes[0].texture = boxtexture;
- cbox_planes[1].supercontents = boxsupercontents;cbox_planes[1].q3surfaceflags = boxq3surfaceflags;cbox_planes[1].texture = boxtexture;
- cbox_planes[2].supercontents = boxsupercontents;cbox_planes[2].q3surfaceflags = boxq3surfaceflags;cbox_planes[2].texture = boxtexture;
- cbox_planes[3].supercontents = boxsupercontents;cbox_planes[3].q3surfaceflags = boxq3surfaceflags;cbox_planes[3].texture = boxtexture;
- cbox_planes[4].supercontents = boxsupercontents;cbox_planes[4].q3surfaceflags = boxq3surfaceflags;cbox_planes[4].texture = boxtexture;
- cbox_planes[5].supercontents = boxsupercontents;cbox_planes[5].q3surfaceflags = boxq3surfaceflags;cbox_planes[5].texture = boxtexture;
+ cbox_planes[0].q3surfaceflags = boxq3surfaceflags;cbox_planes[0].texture = boxtexture;
+ cbox_planes[1].q3surfaceflags = boxq3surfaceflags;cbox_planes[1].texture = boxtexture;
+ cbox_planes[2].q3surfaceflags = boxq3surfaceflags;cbox_planes[2].texture = boxtexture;
+ cbox_planes[3].q3surfaceflags = boxq3surfaceflags;cbox_planes[3].texture = boxtexture;
+ cbox_planes[4].q3surfaceflags = boxq3surfaceflags;cbox_planes[4].texture = boxtexture;
+ cbox_planes[5].q3surfaceflags = boxq3surfaceflags;cbox_planes[5].texture = boxtexture;
memset(trace, 0, sizeof(trace_t));
trace->hitsupercontentsmask = hitsupercontentsmask;
trace->fraction = 1;
void Mod_Q1BSP_LightPoint(model_t *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal)
{
- Mod_Q1BSP_LightPoint_RecursiveBSPNode(model, ambientcolor, diffusecolor, diffusenormal, model->brush.data_nodes + model->brushq1.hulls[0].firstclipnode, p[0], p[1], p[2], p[2] - 65536);
+ Mod_Q1BSP_LightPoint_RecursiveBSPNode(model, ambientcolor, diffusecolor, diffusenormal, model->brush.data_nodes + model->brushq1.hulls[0].firstclipnode, p[0], p[1], p[2] + 0.125, p[2] - 65536);
VectorSet(diffusenormal, 0, 0, -1);
}
texture_t *tx, *tx2, *anims[10], *altanims[10];
dmiptexlump_t *m;
unsigned char *data, *mtdata;
- char name[MAX_QPATH];
+ const char *s;
+ char mapname[MAX_QPATH], name[MAX_QPATH];
loadmodel->data_textures = NULL;
if (!m)
return;
+ s = loadmodel->name;
+ if (!strncasecmp(s, "maps/", 5))
+ s += 5;
+ FS_StripExtension(s, mapname, sizeof(mapname));
+
// just to work around bounds checking when debugging with it (array index out of bounds error thing)
dofs = m->dataofs;
// LordHavoc: mostly rewritten map texture loader
}
else
{
- if (!Mod_LoadSkinFrame(&tx->skin, gamemode == GAME_TENEBRAE ? tx->name : va("textures/%s", tx->name), TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, false, true))
+ if (!Mod_LoadSkinFrame(&tx->skin, gamemode == GAME_TENEBRAE ? tx->name : va("textures/%s/%s", mapname, tx->name), TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, false, true)
+ && !Mod_LoadSkinFrame(&tx->skin, gamemode == GAME_TENEBRAE ? tx->name : va("textures/%s", tx->name), TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, false, true))
{
// did not find external texture, load it from the bsp or wad3
if (loadmodel->brush.ishlbsp)
tx->basematerialflags |= MATERIALFLAG_WALL;
}
if (tx->skin.fog)
- tx->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
+ tx->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
// start out with no animation
tx->currentframe = tx;
int i, j, k;
if (!data)
return;
- if (!COM_ParseToken(&data, false))
+ if (!COM_ParseTokenConsole(&data))
return; // error
if (com_token[0] != '{')
return; // error
while (1)
{
- if (!COM_ParseToken(&data, false))
+ if (!COM_ParseTokenConsole(&data))
return; // error
if (com_token[0] == '}')
break; // end of worldspawn
strcpy(key, com_token);
while (key[strlen(key)-1] == ' ') // remove trailing spaces
key[strlen(key)-1] = 0;
- if (!COM_ParseToken(&data, false))
+ if (!COM_ParseTokenConsole(&data))
return; // error
dpsnprintf(value, sizeof(value), "%s", com_token);
if (!strcmp("wad", key)) // for HalfLife maps
}
// compile additional data about the surface geometry
- Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, (loadmodel->surfmesh.data_element3i + 3 * surface->num_firsttriangle), loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, loadmodel->surfmesh.data_normal3f, true);
+ Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, loadmodel->surfmesh.data_vertex3f, (loadmodel->surfmesh.data_element3i + 3 * surface->num_firsttriangle), loadmodel->surfmesh.data_normal3f, true);
+ Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, (loadmodel->surfmesh.data_element3i + 3 * surface->num_firsttriangle), loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, true);
BoxFromPoints(surface->mins, surface->maxs, surface->num_vertices, (loadmodel->surfmesh.data_vertex3f + 3 * surface->num_firstvertex));
// generate surface extents information
if (!maptext)
return;
text = maptext;
- if (!COM_ParseToken(&data, false))
+ if (!COM_ParseTokenConsole(&data))
return; // error
submodel = 0;
for (;;)
{
- if (!COM_ParseToken(&data, false))
+ if (!COM_ParseTokenConsole(&data))
break;
if (com_token[0] != '{')
return; // error
brushes = Mem_Alloc(loadmodel->mempool, maxbrushes * sizeof(mbrush_t));
for (;;)
{
- if (!COM_ParseToken(&data, false))
+ if (!COM_ParseTokenConsole(&data))
return; // error
if (com_token[0] == '}')
break; // end of entity
}
for (;;)
{
- if (!COM_ParseToken(&data, false))
+ if (!COM_ParseTokenConsole(&data))
return; // error
if (com_token[0] == '}')
break; // end of brush
// FIXME: support hl .map format
for (pointnum = 0;pointnum < 3;pointnum++)
{
- COM_ParseToken(&data, false);
+ COM_ParseTokenConsole(&data);
for (componentnum = 0;componentnum < 3;componentnum++)
{
- COM_ParseToken(&data, false);
+ COM_ParseTokenConsole(&data);
point[pointnum][componentnum] = atof(com_token);
}
- COM_ParseToken(&data, false);
+ COM_ParseTokenConsole(&data);
}
- COM_ParseToken(&data, false);
+ COM_ParseTokenConsole(&data);
strlcpy(facetexture, com_token, sizeof(facetexture));
- COM_ParseToken(&data, false);
+ COM_ParseTokenConsole(&data);
//scroll_s = atof(com_token);
- COM_ParseToken(&data, false);
+ COM_ParseTokenConsole(&data);
//scroll_t = atof(com_token);
- COM_ParseToken(&data, false);
+ COM_ParseTokenConsole(&data);
//rotate = atof(com_token);
- COM_ParseToken(&data, false);
+ COM_ParseTokenConsole(&data);
//scale_s = atof(com_token);
- COM_ParseToken(&data, false);
+ COM_ParseTokenConsole(&data);
//scale_t = atof(com_token);
TriangleNormal(point[0], point[1], point[2], planenormal);
VectorNormalizeDouble(planenormal);
memcpy(loadmodel->brush.entities, mod_base + l->fileofs, l->filelen);
data = loadmodel->brush.entities;
// some Q3 maps override the lightgrid_cellsize with a worldspawn key
- if (data && COM_ParseToken(&data, false) && com_token[0] == '{')
+ if (data && COM_ParseTokenConsole(&data) && com_token[0] == '{')
{
while (1)
{
- if (!COM_ParseToken(&data, false))
+ if (!COM_ParseTokenConsole(&data))
break; // error
if (com_token[0] == '}')
break; // end of worldspawn
strcpy(key, com_token);
while (key[strlen(key)-1] == ' ') // remove trailing spaces
key[strlen(key)-1] = 0;
- if (!COM_ParseToken(&data, false))
+ if (!COM_ParseTokenConsole(&data))
break; // error
strcpy(value, com_token);
if (!strcmp("gridsize", key))
}
}
-static void Mod_Q3BSP_LoadTextures(lump_t *l)
+// FIXME: make MAXSHADERS dynamic
+#define Q3SHADER_MAXSHADERS 4096
+#define Q3SHADER_MAXLAYERS 8
+
+typedef struct q3shaderinfo_layer_s
{
- q3dtexture_t *in;
- texture_t *out;
- int i, count;
- int j, c;
+ char texturename[Q3PATHLENGTH];
+ int blendfunc[2];
+ qboolean rgbgenvertex;
+ qboolean alphagenvertex;
+}
+q3shaderinfo_layer_t;
+
+typedef struct q3shaderinfo_s
+{
+ char name[Q3PATHLENGTH];
+ int surfaceparms;
+ int textureflags;
+ int numlayers;
+ qboolean lighting;
+ qboolean vertexalpha;
+ qboolean textureblendalpha;
+ q3shaderinfo_layer_t *primarylayer, *backgroundlayer;
+ q3shaderinfo_layer_t layers[Q3SHADER_MAXLAYERS];
+ char skyboxname[Q3PATHLENGTH];
+}
+q3shaderinfo_t;
+
+int q3shaders_numshaders;
+q3shaderinfo_t q3shaders_shaders[Q3SHADER_MAXSHADERS];
+
+static void Mod_Q3BSP_LoadShaders(void)
+{
+ int j;
+ int fileindex;
fssearch_t *search;
char *f;
const char *text;
- int flags, flags2, numparameters, passnumber;
- char shadername[Q3PATHLENGTH];
- char sky[Q3PATHLENGTH];
- char firstpasstexturename[Q3PATHLENGTH];
+ q3shaderinfo_t *shader;
+ q3shaderinfo_layer_t *layer;
+ int numparameters;
char parameter[4][Q3PATHLENGTH];
-
- in = (q3dtexture_t *)(mod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- Host_Error("Mod_Q3BSP_LoadTextures: funny lump size in %s",loadmodel->name);
- count = l->filelen / sizeof(*in);
- out = (texture_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
-
- loadmodel->data_textures = out;
- loadmodel->num_textures = count;
-
- for (i = 0;i < count;i++, in++, out++)
- {
- strlcpy (out->name, in->name, sizeof (out->name));
- out->surfaceflags = LittleLong(in->surfaceflags);
- out->supercontents = Mod_Q3BSP_SuperContentsFromNativeContents(loadmodel, LittleLong(in->contents));
- out->surfaceparms = -1;
- }
-
- // do a quick parse of shader files to get surfaceparms
- if ((search = FS_Search("scripts/*.shader", true, false)))
+ search = FS_Search("scripts/*.shader", true, false);
+ if (!search)
+ return;
+ q3shaders_numshaders = 0;
+ for (fileindex = 0;fileindex < search->numfilenames;fileindex++)
{
- for (i = 0;i < search->numfilenames;i++)
+ text = f = (char *)FS_LoadFile(search->filenames[fileindex], tempmempool, false, NULL);
+ if (!f)
+ continue;
+ while (COM_ParseToken(&text, false))
{
- if ((f = (char *)FS_LoadFile(search->filenames[i], tempmempool, false, NULL)))
+ if (q3shaders_numshaders >= Q3SHADER_MAXSHADERS)
+ {
+ Con_Printf("Mod_Q3BSP_LoadShaders: too many shaders!\n");
+ break;
+ }
+ shader = q3shaders_shaders + q3shaders_numshaders++;
+ memset(shader, 0, sizeof(*shader));
+ strlcpy(shader->name, com_token, sizeof(shader->name));
+ if (!COM_ParseToken(&text, false) || strcasecmp(com_token, "{"))
{
- text = f;
- while (COM_ParseToken(&text, false))
+ Con_Printf("%s parsing error - expected \"{\", found \"%s\"\n", search->filenames[fileindex], com_token);
+ break;
+ }
+ while (COM_ParseToken(&text, false))
+ {
+ if (!strcasecmp(com_token, "}"))
+ break;
+ if (!strcasecmp(com_token, "{"))
{
- strlcpy (shadername, com_token, sizeof (shadername));
- flags = 0;
- flags2 = 0;
- sky[0] = 0;
- passnumber = 0;
- firstpasstexturename[0] = 0;
- if (COM_ParseToken(&text, false) && !strcasecmp(com_token, "{"))
+ if (shader->numlayers < Q3SHADER_MAXLAYERS)
+ {
+ layer = shader->layers + shader->numlayers++;
+ layer->rgbgenvertex = false;
+ layer->alphagenvertex = false;
+ layer->blendfunc[0] = GL_ONE;
+ layer->blendfunc[1] = GL_ZERO;
+ }
+ else
+ layer = NULL;
+ while (COM_ParseToken(&text, false))
{
- while (COM_ParseToken(&text, false))
+ if (!strcasecmp(com_token, "}"))
+ break;
+ if (!strcasecmp(com_token, "\n"))
+ continue;
+ if (layer == NULL)
+ continue;
+ numparameters = 0;
+ for (j = 0;strcasecmp(com_token, "\n") && strcasecmp(com_token, "}");j++)
{
- if (!strcasecmp(com_token, "}"))
- break;
- else if (!strcasecmp(com_token, "{"))
+ if (j < 4)
{
- while (COM_ParseToken(&text, false))
- {
- if (!strcasecmp(com_token, "}"))
- break;
- if (!strcasecmp(com_token, "\n"))
- continue;
- numparameters = 0;
- for (j = 0;strcasecmp(com_token, "\n") && strcasecmp(com_token, "}");j++)
- {
- if (j < 4)
- {
- strlcpy(parameter[j], com_token, sizeof(parameter[j]));
- numparameters = j + 1;
- }
- if (!COM_ParseToken(&text, true))
- break;
- }
- if (developer.integer >= 100)
- {
- Con_Printf("%s %i: ", shadername, passnumber);
- for (j = 0;j < numparameters;j++)
- Con_Printf(" %s", parameter[j]);
- Con_Print("\n");
- }
- if (passnumber == 0 && numparameters >= 1)
- {
- if (!strcasecmp(parameter[0], "blendfunc") && (flags & Q3SURFACEPARM_TRANS))
- {
- if (numparameters == 2 && !strcasecmp(parameter[1], "add"))
- flags2 |= Q3TEXTUREFLAG_ADDITIVE;
- else if (numparameters == 3 && !strcasecmp(parameter[1], "gl_one") && !strcasecmp(parameter[2], "gl_one"))
- flags2 |= Q3TEXTUREFLAG_ADDITIVE;
- else if (numparameters == 3 && !strcasecmp(parameter[1], "gl_src_alpha") && !strcasecmp(parameter[2], "gl_one"))
- flags2 |= Q3TEXTUREFLAG_ADDITIVE;
- }
- else if (numparameters >= 2 && (!strcasecmp(parameter[0], "map") || !strcasecmp(parameter[0], "clampmap")))
- strlcpy(firstpasstexturename, parameter[1], sizeof(firstpasstexturename));
- else if (numparameters >= 3 && !strcasecmp(parameter[0], "animmap"))
- strlcpy(firstpasstexturename, parameter[2], sizeof(firstpasstexturename));
- else if (numparameters >= 2 && !strcasecmp(parameter[0], "alphafunc"))
- flags2 |= Q3TEXTUREFLAG_ALPHATEST;
- }
- // break out a level if it was }
- if (!strcasecmp(com_token, "}"))
- break;
- }
- passnumber++;
- continue;
+ strlcpy(parameter[j], com_token, sizeof(parameter[j]));
+ numparameters = j + 1;
}
- numparameters = 0;
- for (j = 0;strcasecmp(com_token, "\n") && strcasecmp(com_token, "}");j++)
- {
- if (j < 4)
- {
- strlcpy(parameter[j], com_token, sizeof(parameter[j]));
- numparameters = j + 1;
- }
- if (!COM_ParseToken(&text, true))
- break;
- }
- if (i == 0 && !strcasecmp(com_token, "}"))
+ if (!COM_ParseToken(&text, true))
break;
- if (developer.integer >= 100)
- {
- Con_Printf("%s: ", shadername);
- for (j = 0;j < numparameters;j++)
- Con_Printf(" %s", parameter[j]);
- Con_Print("\n");
- }
- if (numparameters < 1)
- continue;
- if (!strcasecmp(parameter[0], "surfaceparm") && numparameters >= 2)
- {
- if (!strcasecmp(parameter[1], "alphashadow"))
- flags |= Q3SURFACEPARM_ALPHASHADOW;
- else if (!strcasecmp(parameter[1], "areaportal"))
- flags |= Q3SURFACEPARM_AREAPORTAL;
- else if (!strcasecmp(parameter[1], "clusterportal"))
- flags |= Q3SURFACEPARM_CLUSTERPORTAL;
- else if (!strcasecmp(parameter[1], "detail"))
- flags |= Q3SURFACEPARM_DETAIL;
- else if (!strcasecmp(parameter[1], "donotenter"))
- flags |= Q3SURFACEPARM_DONOTENTER;
- else if (!strcasecmp(parameter[1], "fog"))
- flags |= Q3SURFACEPARM_FOG;
- else if (!strcasecmp(parameter[1], "lava"))
- flags |= Q3SURFACEPARM_LAVA;
- else if (!strcasecmp(parameter[1], "lightfilter"))
- flags |= Q3SURFACEPARM_LIGHTFILTER;
- else if (!strcasecmp(parameter[1], "metalsteps"))
- flags |= Q3SURFACEPARM_METALSTEPS;
- else if (!strcasecmp(parameter[1], "nodamage"))
- flags |= Q3SURFACEPARM_NODAMAGE;
- else if (!strcasecmp(parameter[1], "nodlight"))
- flags |= Q3SURFACEPARM_NODLIGHT;
- else if (!strcasecmp(parameter[1], "nodraw"))
- flags |= Q3SURFACEPARM_NODRAW;
- else if (!strcasecmp(parameter[1], "nodrop"))
- flags |= Q3SURFACEPARM_NODROP;
- else if (!strcasecmp(parameter[1], "noimpact"))
- flags |= Q3SURFACEPARM_NOIMPACT;
- else if (!strcasecmp(parameter[1], "nolightmap"))
- flags |= Q3SURFACEPARM_NOLIGHTMAP;
- else if (!strcasecmp(parameter[1], "nomarks"))
- flags |= Q3SURFACEPARM_NOMARKS;
- else if (!strcasecmp(parameter[1], "nomipmaps"))
- flags |= Q3SURFACEPARM_NOMIPMAPS;
- else if (!strcasecmp(parameter[1], "nonsolid"))
- flags |= Q3SURFACEPARM_NONSOLID;
- else if (!strcasecmp(parameter[1], "origin"))
- flags |= Q3SURFACEPARM_ORIGIN;
- else if (!strcasecmp(parameter[1], "playerclip"))
- flags |= Q3SURFACEPARM_PLAYERCLIP;
- else if (!strcasecmp(parameter[1], "sky"))
- flags |= Q3SURFACEPARM_SKY;
- else if (!strcasecmp(parameter[1], "slick"))
- flags |= Q3SURFACEPARM_SLICK;
- else if (!strcasecmp(parameter[1], "slime"))
- flags |= Q3SURFACEPARM_SLIME;
- else if (!strcasecmp(parameter[1], "structural"))
- flags |= Q3SURFACEPARM_STRUCTURAL;
- else if (!strcasecmp(parameter[1], "trans"))
- flags |= Q3SURFACEPARM_TRANS;
- else if (!strcasecmp(parameter[1], "water"))
- flags |= Q3SURFACEPARM_WATER;
- else if (!strcasecmp(parameter[1], "pointlight"))
- flags |= Q3SURFACEPARM_POINTLIGHT;
- else
- Con_Printf("%s parsing warning: unknown surfaceparm \"%s\"\n", search->filenames[i], parameter[1]);
- }
- else if (!strcasecmp(parameter[0], "sky") && numparameters >= 2)
- strlcpy(sky, parameter[1], sizeof(sky));
- else if (!strcasecmp(parameter[0], "skyparms") && numparameters >= 2)
- {
- if (!atoi(parameter[1]) && strcasecmp(parameter[1], "-"))
- strlcpy(sky, parameter[1], sizeof(sky));
- }
- else if (!strcasecmp(parameter[0], "cull") && numparameters >= 2)
- {
- if (!strcasecmp(parameter[1], "disable") || !strcasecmp(parameter[1], "none") || !strcasecmp(parameter[1], "twosided"))
- flags2 |= Q3TEXTUREFLAG_TWOSIDED;
- }
- else if (!strcasecmp(parameter[0], "nomipmaps"))
- flags2 |= Q3TEXTUREFLAG_NOMIPMAPS;
- else if (!strcasecmp(parameter[0], "nopicmip"))
- flags2 |= Q3TEXTUREFLAG_NOPICMIP;
- else if (!strcasecmp(parameter[0], "deformvertexes") && numparameters >= 2)
- {
- if (!strcasecmp(parameter[1], "autosprite") && numparameters == 2)
- flags2 |= Q3TEXTUREFLAG_AUTOSPRITE;
- if (!strcasecmp(parameter[1], "autosprite2") && numparameters == 2)
- flags2 |= Q3TEXTUREFLAG_AUTOSPRITE2;
- }
}
- // add shader to list (shadername and flags)
- // actually here we just poke into the texture settings
- for (j = 0, out = loadmodel->data_textures;j < loadmodel->num_textures;j++, out++)
+ if (developer.integer >= 100)
{
- if (!strcasecmp(out->name, shadername))
+ Con_Printf("%s %i: ", shader->name, shader->numlayers - 1);
+ for (j = 0;j < numparameters;j++)
+ Con_Printf(" %s", parameter[j]);
+ Con_Print("\n");
+ }
+ if (numparameters >= 2 && !strcasecmp(parameter[0], "blendfunc"))
+ {
+ if (numparameters == 2)
{
- out->surfaceparms = flags;
- out->textureflags = flags2;
- out->basematerialflags = 0;
- if (out->surfaceparms & Q3SURFACEPARM_NODRAW)
- out->basematerialflags |= MATERIALFLAG_NODRAW;
- else if (out->surfaceparms & Q3SURFACEPARM_SKY)
- out->basematerialflags |= MATERIALFLAG_SKY;
- else if (out->surfaceparms & Q3SURFACEPARM_LAVA)
- out->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_FULLBRIGHT;
- else if (out->surfaceparms & Q3SURFACEPARM_SLIME)
- out->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_WATERALPHA;
- else if (out->surfaceparms & Q3SURFACEPARM_WATER)
- out->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_WATERALPHA;
- else
- out->basematerialflags |= MATERIALFLAG_WALL;
- if (out->textureflags & Q3TEXTUREFLAG_ALPHATEST)
+ if (!strcasecmp(parameter[1], "add"))
{
- // FIXME: support alpha test?
- out->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
+ layer->blendfunc[0] = GL_ONE;
+ layer->blendfunc[1] = GL_ONE;
}
- else if (out->surfaceparms & Q3SURFACEPARM_TRANS)
+ else if (!strcasecmp(parameter[1], "filter"))
{
- if (out->textureflags & Q3TEXTUREFLAG_ADDITIVE)
- out->basematerialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
- else
- out->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
+ layer->blendfunc[0] = GL_DST_COLOR;
+ layer->blendfunc[1] = GL_ZERO;
+ }
+ else if (!strcasecmp(parameter[1], "blend"))
+ {
+ layer->blendfunc[0] = GL_SRC_ALPHA;
+ layer->blendfunc[1] = GL_ONE_MINUS_SRC_ALPHA;
}
- strlcpy(out->firstpasstexturename, firstpasstexturename, sizeof(out->firstpasstexturename));
- if ((flags & Q3SURFACEPARM_SKY) && sky[0])
+ }
+ else if (numparameters == 3)
+ {
+ int k;
+ for (k = 0;k < 2;k++)
{
- // quake3 seems to append a _ to the skybox name, so this must do so as well
- dpsnprintf(loadmodel->brush.skybox, sizeof(loadmodel->brush.skybox), "%s_", sky);
+ if (!strcasecmp(parameter[k+1], "GL_ONE"))
+ layer->blendfunc[k] = GL_ONE;
+ else if (!strcasecmp(parameter[k+1], "GL_ZERO"))
+ layer->blendfunc[k] = GL_ZERO;
+ else if (!strcasecmp(parameter[k+1], "GL_SRC_COLOR"))
+ layer->blendfunc[k] = GL_SRC_COLOR;
+ else if (!strcasecmp(parameter[k+1], "GL_SRC_ALPHA"))
+ layer->blendfunc[k] = GL_SRC_ALPHA;
+ else if (!strcasecmp(parameter[k+1], "GL_DST_COLOR"))
+ layer->blendfunc[k] = GL_DST_COLOR;
+ else if (!strcasecmp(parameter[k+1], "GL_DST_ALPHA"))
+ layer->blendfunc[k] = GL_ONE_MINUS_DST_ALPHA;
+ else if (!strcasecmp(parameter[k+1], "GL_ONE_MINUS_SRC_COLOR"))
+ layer->blendfunc[k] = GL_ONE_MINUS_SRC_COLOR;
+ else if (!strcasecmp(parameter[k+1], "GL_ONE_MINUS_SRC_ALPHA"))
+ layer->blendfunc[k] = GL_ONE_MINUS_SRC_ALPHA;
+ else if (!strcasecmp(parameter[k+1], "GL_ONE_MINUS_DST_COLOR"))
+ layer->blendfunc[k] = GL_ONE_MINUS_DST_COLOR;
+ else if (!strcasecmp(parameter[k+1], "GL_ONE_MINUS_DST_ALPHA"))
+ layer->blendfunc[k] = GL_ONE_MINUS_DST_ALPHA;
+ else
+ layer->blendfunc[k] = GL_ONE; // default in case of parsing error
}
}
}
+ if (layer == shader->layers + 0)
+ {
+ if (numparameters >= 2 && !strcasecmp(parameter[0], "alphafunc"))
+ shader->textureflags |= Q3TEXTUREFLAG_ALPHATEST;
+ }
+ if (numparameters >= 2 && (!strcasecmp(parameter[0], "map") || !strcasecmp(parameter[0], "clampmap")))
+ {
+ strlcpy(layer->texturename, parameter[1], sizeof(layer->texturename));
+ if (!strcasecmp(parameter[1], "$lightmap"))
+ shader->lighting = true;
+ }
+ else if (numparameters >= 3 && !strcasecmp(parameter[0], "animmap"))
+ strlcpy(layer->texturename, parameter[2], sizeof(layer->texturename));
+ else if (numparameters >= 2 && !strcasecmp(parameter[0], "rgbgen") && !strcasecmp(parameter[1], "vertex"))
+ layer->rgbgenvertex = true;
+ else if (numparameters >= 2 && !strcasecmp(parameter[0], "alphagen") && !strcasecmp(parameter[1], "vertex"))
+ layer->alphagenvertex = true;
+ // break out a level if it was }
+ if (!strcasecmp(com_token, "}"))
+ break;
}
- else
+ if (layer->rgbgenvertex)
+ shader->lighting = true;
+ if (layer->alphagenvertex)
+ {
+ if (layer == shader->layers + 0)
+ {
+ // vertex controlled transparency
+ shader->vertexalpha = true;
+ }
+ else
+ {
+ // multilayer terrain shader or similar
+ shader->textureblendalpha = true;
+ }
+ }
+ continue;
+ }
+ numparameters = 0;
+ for (j = 0;strcasecmp(com_token, "\n") && strcasecmp(com_token, "}");j++)
+ {
+ if (j < 4)
{
- Con_Printf("%s parsing error - expected \"{\", found \"%s\"\n", search->filenames[i], com_token);
- goto parseerror;
+ strlcpy(parameter[j], com_token, sizeof(parameter[j]));
+ numparameters = j + 1;
}
+ if (!COM_ParseToken(&text, true))
+ break;
+ }
+ if (fileindex == 0 && !strcasecmp(com_token, "}"))
+ break;
+ if (developer.integer >= 100)
+ {
+ Con_Printf("%s: ", shader->name);
+ for (j = 0;j < numparameters;j++)
+ Con_Printf(" %s", parameter[j]);
+ Con_Print("\n");
+ }
+ if (numparameters < 1)
+ continue;
+ if (!strcasecmp(parameter[0], "surfaceparm") && numparameters >= 2)
+ {
+ if (!strcasecmp(parameter[1], "alphashadow"))
+ shader->surfaceparms |= Q3SURFACEPARM_ALPHASHADOW;
+ else if (!strcasecmp(parameter[1], "areaportal"))
+ shader->surfaceparms |= Q3SURFACEPARM_AREAPORTAL;
+ else if (!strcasecmp(parameter[1], "botclip"))
+ shader->surfaceparms |= Q3SURFACEPARM_BOTCLIP;
+ else if (!strcasecmp(parameter[1], "clusterportal"))
+ shader->surfaceparms |= Q3SURFACEPARM_CLUSTERPORTAL;
+ else if (!strcasecmp(parameter[1], "detail"))
+ shader->surfaceparms |= Q3SURFACEPARM_DETAIL;
+ else if (!strcasecmp(parameter[1], "donotenter"))
+ shader->surfaceparms |= Q3SURFACEPARM_DONOTENTER;
+ else if (!strcasecmp(parameter[1], "dust"))
+ shader->surfaceparms |= Q3SURFACEPARM_DUST;
+ else if (!strcasecmp(parameter[1], "hint"))
+ shader->surfaceparms |= Q3SURFACEPARM_HINT;
+ else if (!strcasecmp(parameter[1], "fog"))
+ shader->surfaceparms |= Q3SURFACEPARM_FOG;
+ else if (!strcasecmp(parameter[1], "lava"))
+ shader->surfaceparms |= Q3SURFACEPARM_LAVA;
+ else if (!strcasecmp(parameter[1], "lightfilter"))
+ shader->surfaceparms |= Q3SURFACEPARM_LIGHTFILTER;
+ else if (!strcasecmp(parameter[1], "lightgrid"))
+ shader->surfaceparms |= Q3SURFACEPARM_LIGHTGRID;
+ else if (!strcasecmp(parameter[1], "metalsteps"))
+ shader->surfaceparms |= Q3SURFACEPARM_METALSTEPS;
+ else if (!strcasecmp(parameter[1], "nodamage"))
+ shader->surfaceparms |= Q3SURFACEPARM_NODAMAGE;
+ else if (!strcasecmp(parameter[1], "nodlight"))
+ shader->surfaceparms |= Q3SURFACEPARM_NODLIGHT;
+ else if (!strcasecmp(parameter[1], "nodraw"))
+ shader->surfaceparms |= Q3SURFACEPARM_NODRAW;
+ else if (!strcasecmp(parameter[1], "nodrop"))
+ shader->surfaceparms |= Q3SURFACEPARM_NODROP;
+ else if (!strcasecmp(parameter[1], "noimpact"))
+ shader->surfaceparms |= Q3SURFACEPARM_NOIMPACT;
+ else if (!strcasecmp(parameter[1], "nolightmap"))
+ shader->surfaceparms |= Q3SURFACEPARM_NOLIGHTMAP;
+ else if (!strcasecmp(parameter[1], "nomarks"))
+ shader->surfaceparms |= Q3SURFACEPARM_NOMARKS;
+ else if (!strcasecmp(parameter[1], "nomipmaps"))
+ shader->surfaceparms |= Q3SURFACEPARM_NOMIPMAPS;
+ else if (!strcasecmp(parameter[1], "nonsolid"))
+ shader->surfaceparms |= Q3SURFACEPARM_NONSOLID;
+ else if (!strcasecmp(parameter[1], "origin"))
+ shader->surfaceparms |= Q3SURFACEPARM_ORIGIN;
+ else if (!strcasecmp(parameter[1], "playerclip"))
+ shader->surfaceparms |= Q3SURFACEPARM_PLAYERCLIP;
+ else if (!strcasecmp(parameter[1], "sky"))
+ shader->surfaceparms |= Q3SURFACEPARM_SKY;
+ else if (!strcasecmp(parameter[1], "slick"))
+ shader->surfaceparms |= Q3SURFACEPARM_SLICK;
+ else if (!strcasecmp(parameter[1], "slime"))
+ shader->surfaceparms |= Q3SURFACEPARM_SLIME;
+ else if (!strcasecmp(parameter[1], "structural"))
+ shader->surfaceparms |= Q3SURFACEPARM_STRUCTURAL;
+ else if (!strcasecmp(parameter[1], "trans"))
+ shader->surfaceparms |= Q3SURFACEPARM_TRANS;
+ else if (!strcasecmp(parameter[1], "water"))
+ shader->surfaceparms |= Q3SURFACEPARM_WATER;
+ else if (!strcasecmp(parameter[1], "pointlight"))
+ shader->surfaceparms |= Q3SURFACEPARM_POINTLIGHT;
+ else
+ Con_Printf("%s parsing warning: unknown surfaceparm \"%s\"\n", search->filenames[fileindex], parameter[1]);
+ }
+ else if (!strcasecmp(parameter[0], "sky") && numparameters >= 2)
+ {
+ // some q3 skies don't have the sky parm set
+ shader->surfaceparms |= Q3SURFACEPARM_SKY;
+ strlcpy(shader->skyboxname, parameter[1], sizeof(shader->skyboxname));
+ }
+ else if (!strcasecmp(parameter[0], "skyparms") && numparameters >= 2)
+ {
+ // some q3 skies don't have the sky parm set
+ shader->surfaceparms |= Q3SURFACEPARM_SKY;
+ if (!atoi(parameter[1]) && strcasecmp(parameter[1], "-"))
+ strlcpy(shader->skyboxname, parameter[1], sizeof(shader->skyboxname));
}
-parseerror:
- Mem_Free(f);
+ else if (!strcasecmp(parameter[0], "cull") && numparameters >= 2)
+ {
+ if (!strcasecmp(parameter[1], "disable") || !strcasecmp(parameter[1], "none") || !strcasecmp(parameter[1], "twosided"))
+ shader->textureflags |= Q3TEXTUREFLAG_TWOSIDED;
+ }
+ else if (!strcasecmp(parameter[0], "nomipmaps"))
+ shader->surfaceparms |= Q3SURFACEPARM_NOMIPMAPS;
+ else if (!strcasecmp(parameter[0], "nopicmip"))
+ shader->textureflags |= Q3TEXTUREFLAG_NOPICMIP;
+ else if (!strcasecmp(parameter[0], "deformvertexes") && numparameters >= 2)
+ {
+ if (!strcasecmp(parameter[1], "autosprite") && numparameters == 2)
+ shader->textureflags |= Q3TEXTUREFLAG_AUTOSPRITE;
+ if (!strcasecmp(parameter[1], "autosprite2") && numparameters == 2)
+ shader->textureflags |= Q3TEXTUREFLAG_AUTOSPRITE2;
+ }
+ }
+ // identify if this is a blended terrain shader or similar
+ if (shader->numlayers)
+ {
+ shader->primarylayer = shader->layers + 0;
+ if (shader->layers[1].blendfunc[0] == GL_SRC_ALPHA && shader->layers[1].blendfunc[1] == GL_ONE_MINUS_SRC_ALPHA)
+ {
+ // terrain blending or other effects
+ shader->backgroundlayer = shader->layers + 0;
+ shader->primarylayer = shader->layers + 1;
+ }
+ // now see if the lightmap came first, and if so choose the second texture instead
+ if (!strcasecmp(shader->primarylayer->texturename, "$lightmap"))
+ shader->primarylayer = shader->layers + 1;
}
}
+ Mem_Free(f);
}
+}
+
+q3shaderinfo_t *Mod_Q3BSP_LookupShader(const char *name)
+{
+ int i;
+ for (i = 0;i < Q3SHADER_MAXSHADERS;i++)
+ if (!strcasecmp(q3shaders_shaders[i].name, name))
+ return q3shaders_shaders + i;
+ return NULL;
+}
+
+static void Mod_Q3BSP_LoadTextures(lump_t *l)
+{
+ q3dtexture_t *in;
+ texture_t *out;
+ int i, count, c;
+
+ in = (q3dtexture_t *)(mod_base + l->fileofs);
+ if (l->filelen % sizeof(*in))
+ Host_Error("Mod_Q3BSP_LoadTextures: funny lump size in %s",loadmodel->name);
+ count = l->filelen / sizeof(*in);
+ out = (texture_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
+
+ loadmodel->data_textures = out;
+ loadmodel->num_textures = count;
+
+ // parse the Q3 shader files
+ Mod_Q3BSP_LoadShaders();
c = 0;
- for (j = 0, out = loadmodel->data_textures;j < loadmodel->num_textures;j++, out++)
+ for (i = 0;i < count;i++, in++, out++)
{
- if (out->surfaceparms == -1)
+ q3shaderinfo_t *shader;
+ strlcpy (out->name, in->name, sizeof (out->name));
+ out->surfaceflags = LittleLong(in->surfaceflags);
+ out->supercontents = Mod_Q3BSP_SuperContentsFromNativeContents(loadmodel, LittleLong(in->contents));
+ shader = Mod_Q3BSP_LookupShader(out->name);
+ if (shader)
+ {
+ out->surfaceparms = shader->surfaceparms;
+ out->textureflags = shader->textureflags;
+ out->basematerialflags = 0;
+ if (shader->surfaceparms & Q3SURFACEPARM_SKY)
+ {
+ out->basematerialflags |= MATERIALFLAG_SKY;
+ if (shader->skyboxname[0])
+ {
+ // quake3 seems to append a _ to the skybox name, so this must do so as well
+ dpsnprintf(loadmodel->brush.skybox, sizeof(loadmodel->brush.skybox), "%s_", shader->skyboxname);
+ }
+ }
+ else if ((out->surfaceflags & Q3SURFACEFLAG_NODRAW) || shader->numlayers == 0)
+ out->basematerialflags |= MATERIALFLAG_NODRAW;
+ else if (shader->surfaceparms & Q3SURFACEPARM_LAVA)
+ out->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_FULLBRIGHT;
+ else if (shader->surfaceparms & Q3SURFACEPARM_SLIME)
+ out->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_WATERALPHA;
+ else if (shader->surfaceparms & Q3SURFACEPARM_WATER)
+ out->basematerialflags |= MATERIALFLAG_WATER | MATERIALFLAG_WATERALPHA;
+ else
+ out->basematerialflags |= MATERIALFLAG_WALL;
+ if (shader->textureflags & Q3TEXTUREFLAG_ALPHATEST)
+ out->basematerialflags |= MATERIALFLAG_ALPHATEST | MATERIALFLAG_TRANSPARENT;
+ out->customblendfunc[0] = GL_ONE;
+ out->customblendfunc[1] = GL_ZERO;
+ if (shader->numlayers > 0)
+ {
+ out->customblendfunc[0] = shader->layers[0].blendfunc[0];
+ out->customblendfunc[1] = shader->layers[0].blendfunc[1];
+/*
+Q3 shader blendfuncs actually used in the game (* = supported by DP)
+* additive GL_ONE GL_ONE
+ additive weird GL_ONE GL_SRC_ALPHA
+ additive weird 2 GL_ONE GL_ONE_MINUS_SRC_ALPHA
+* alpha GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
+ alpha inverse GL_ONE_MINUS_SRC_ALPHA GL_SRC_ALPHA
+ brighten GL_DST_COLOR GL_ONE
+ brighten GL_ONE GL_SRC_COLOR
+ brighten weird GL_DST_COLOR GL_ONE_MINUS_DST_ALPHA
+ brighten weird 2 GL_DST_COLOR GL_SRC_ALPHA
+* modulate GL_DST_COLOR GL_ZERO
+* modulate GL_ZERO GL_SRC_COLOR
+ modulate inverse GL_ZERO GL_ONE_MINUS_SRC_COLOR
+ modulate inverse alpha GL_ZERO GL_SRC_ALPHA
+ modulate weird inverse GL_ONE_MINUS_DST_COLOR GL_ZERO
+* modulate x2 GL_DST_COLOR GL_SRC_COLOR
+* no blend GL_ONE GL_ZERO
+ nothing GL_ZERO GL_ONE
+*/
+ // if not opaque, figure out what blendfunc to use
+ if (shader->layers[0].blendfunc[0] != GL_ONE || shader->layers[0].blendfunc[1] != GL_ZERO)
+ {
+ if (shader->layers[0].blendfunc[0] == GL_ONE && shader->layers[0].blendfunc[1] == GL_ONE)
+ out->basematerialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
+ else if (shader->layers[0].blendfunc[0] == GL_SRC_ALPHA && shader->layers[0].blendfunc[1] == GL_ONE)
+ out->basematerialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
+ else if (shader->layers[0].blendfunc[0] == GL_SRC_ALPHA && shader->layers[0].blendfunc[1] == GL_ONE_MINUS_SRC_ALPHA)
+ out->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
+ else
+ out->basematerialflags |= MATERIALFLAG_CUSTOMBLEND | MATERIALFLAG_FULLBRIGHT | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
+ }
+ }
+ if (!shader->lighting)
+ out->basematerialflags |= MATERIALFLAG_FULLBRIGHT;
+ if (cls.state != ca_dedicated)
+ if (shader->primarylayer && !Mod_LoadSkinFrame(&out->skin, shader->primarylayer->texturename, ((shader->surfaceparms & Q3SURFACEPARM_NOMIPMAPS) ? 0 : TEXF_MIPMAP) | TEXF_ALPHA | TEXF_PRECACHE | (shader->textureflags & Q3TEXTUREFLAG_NOPICMIP ? 0 : TEXF_PICMIP), false, true))
+ Con_Printf("%s: could not load texture \"%s\" for shader \"%s\"\n", loadmodel->name, shader->primarylayer->texturename, out->name);
+ }
+ else
{
c++;
Con_DPrintf("%s: No shader found for texture \"%s\"\n", loadmodel->name, out->name);
// out->surfaceparms |= Q3SURFACEPARM_NODRAW;
//if (R_TextureHasAlpha(out->skin.base))
// out->surfaceparms |= Q3SURFACEPARM_TRANS;
+ if (cls.state != ca_dedicated)
+ if (!Mod_LoadSkinFrame(&out->skin, out->name, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, false, true))
+ Con_Printf("%s: could not load texture for missing shader \"%s\"\n", loadmodel->name, out->name);
}
- if (cls.state != ca_dedicated)
- if (!Mod_LoadSkinFrame(&out->skin, out->name, (((out->textureflags & Q3TEXTUREFLAG_NOMIPMAPS) || (out->surfaceparms & Q3SURFACEPARM_NOMIPMAPS)) ? 0 : TEXF_MIPMAP) | TEXF_ALPHA | TEXF_PRECACHE | (out->textureflags & Q3TEXTUREFLAG_NOPICMIP ? 0 : TEXF_PICMIP), false, true))
- if (!Mod_LoadSkinFrame(&out->skin, out->firstpasstexturename, (((out->textureflags & Q3TEXTUREFLAG_NOMIPMAPS) || (out->surfaceparms & Q3SURFACEPARM_NOMIPMAPS)) ? 0 : TEXF_MIPMAP) | TEXF_ALPHA | TEXF_PRECACHE | (out->textureflags & Q3TEXTUREFLAG_NOPICMIP ? 0 : TEXF_PICMIP), false, true))
- Con_Printf("%s: texture loading for shader \"%s\" failed (first layer \"%s\" not found either)\n", loadmodel->name, out->name, out->firstpasstexturename);
// no animation
out->currentframe = out;
}
{
VectorCopy(out->firstbrushside[j].plane->normal, planes[j].normal);
planes[j].dist = out->firstbrushside[j].plane->dist;
- planes[j].supercontents = out->firstbrushside[j].texture->supercontents;
planes[j].q3surfaceflags = out->firstbrushside[j].texture->surfaceflags;
planes[j].texture = out->firstbrushside[j].texture;
}
// make the colbrush from the planes
- out->colbrushf = Collision_NewBrushFromPlanes(loadmodel->mempool, out->numbrushsides, planes);
+ out->colbrushf = Collision_NewBrushFromPlanes(loadmodel->mempool, out->numbrushsides, planes, out->texture->supercontents);
}
if (planes)
Mem_Free(planes);
if (l->filelen % sizeof(*in))
Host_Error("Mod_Q3BSP_LoadVertices: funny lump size in %s",loadmodel->name);
loadmodel->brushq3.num_vertices = count = l->filelen / sizeof(*in);
- loadmodel->brushq3.data_vertex3f = (float *)Mem_Alloc(loadmodel->mempool, count * (sizeof(float) * (3 + 2 + 2 + 4)));
- loadmodel->brushq3.data_texcoordtexture2f = loadmodel->brushq3.data_vertex3f + count * 3;
+ loadmodel->brushq3.data_vertex3f = (float *)Mem_Alloc(loadmodel->mempool, count * (sizeof(float) * (3 + 3 + 2 + 2 + 4)));
+ loadmodel->brushq3.data_normal3f = loadmodel->brushq3.data_vertex3f + count * 3;
+ loadmodel->brushq3.data_texcoordtexture2f = loadmodel->brushq3.data_normal3f + count * 3;
loadmodel->brushq3.data_texcoordlightmap2f = loadmodel->brushq3.data_texcoordtexture2f + count * 2;
loadmodel->brushq3.data_color4f = loadmodel->brushq3.data_texcoordlightmap2f + count * 2;
loadmodel->brushq3.data_vertex3f[i * 3 + 0] = LittleFloat(in->origin3f[0]);
loadmodel->brushq3.data_vertex3f[i * 3 + 1] = LittleFloat(in->origin3f[1]);
loadmodel->brushq3.data_vertex3f[i * 3 + 2] = LittleFloat(in->origin3f[2]);
+ loadmodel->brushq3.data_normal3f[i * 3 + 0] = LittleFloat(in->normal3f[0]);
+ loadmodel->brushq3.data_normal3f[i * 3 + 1] = LittleFloat(in->normal3f[1]);
+ loadmodel->brushq3.data_normal3f[i * 3 + 2] = LittleFloat(in->normal3f[2]);
loadmodel->brushq3.data_texcoordtexture2f[i * 2 + 0] = LittleFloat(in->texcoord2f[0]);
loadmodel->brushq3.data_texcoordtexture2f[i * 2 + 1] = LittleFloat(in->texcoord2f[1]);
loadmodel->brushq3.data_texcoordlightmap2f[i * 2 + 0] = LittleFloat(in->lightmap2f[0]);
loadmodel->brushq3.data_lightmaps = out;
loadmodel->brushq3.num_lightmaps = count;
- loadmodel->brushq3.deluxemapping_modelspace = false;
for (i = 0;i < count;i++, in++, out++)
- {
- // if this may be a deluxemap, check if it's in modelspace or not
- if ((i & 1) && !loadmodel->brushq3.deluxemapping_modelspace)
- {
- int j;
- unsigned char *b = in->rgb;
- for (j = 2;j < 128*128*3;j += 3)
- {
- // if this is definitely negative Z, it is not facing outward,
- // and thus must be in modelspace, as negative Z would never
- // occur in tangentspace
- if (b[j] < 120)
- {
- loadmodel->brushq3.deluxemapping_modelspace = true;
- break;
- }
- }
- }
*out = R_LoadTexture2D(loadmodel->texturepool, va("lightmap%04i", i), 128, 128, in->rgb, TEXTYPE_RGB, TEXF_FORCELINEAR | TEXF_PRECACHE, NULL);
- }
}
static void Mod_Q3BSP_LoadFaces(lump_t *l)
float *originalvertex3f;
//float *originalsvector3f;
//float *originaltvector3f;
- //float *originalnormal3f;
+ float *originalnormal3f;
float *originalcolor4f;
float *originaltexcoordtexture2f;
float *originaltexcoordlightmap2f;
// is also not a deluxemapped bsp if it has an odd number of lightmaps or
// less than 2
loadmodel->brushq3.deluxemapping = true;
+ loadmodel->brushq3.deluxemapping_modelspace = true;
if (loadmodel->brushq3.num_lightmaps >= 2 && !(loadmodel->brushq3.num_lightmaps & 1))
{
for (i = 0;i < count;i++)
(loadmodel->surfmesh.data_vertex3f + 3 * out->num_firstvertex)[j * 3 + 0] = loadmodel->brushq3.data_vertex3f[(firstvertex + j) * 3 + 0];
(loadmodel->surfmesh.data_vertex3f + 3 * out->num_firstvertex)[j * 3 + 1] = loadmodel->brushq3.data_vertex3f[(firstvertex + j) * 3 + 1];
(loadmodel->surfmesh.data_vertex3f + 3 * out->num_firstvertex)[j * 3 + 2] = loadmodel->brushq3.data_vertex3f[(firstvertex + j) * 3 + 2];
+ (loadmodel->surfmesh.data_normal3f + 3 * out->num_firstvertex)[j * 3 + 0] = loadmodel->brushq3.data_normal3f[(firstvertex + j) * 3 + 0];
+ (loadmodel->surfmesh.data_normal3f + 3 * out->num_firstvertex)[j * 3 + 1] = loadmodel->brushq3.data_normal3f[(firstvertex + j) * 3 + 1];
+ (loadmodel->surfmesh.data_normal3f + 3 * out->num_firstvertex)[j * 3 + 2] = loadmodel->brushq3.data_normal3f[(firstvertex + j) * 3 + 2];
(loadmodel->surfmesh.data_texcoordtexture2f + 2 * out->num_firstvertex)[j * 2 + 0] = loadmodel->brushq3.data_texcoordtexture2f[(firstvertex + j) * 2 + 0];
(loadmodel->surfmesh.data_texcoordtexture2f + 2 * out->num_firstvertex)[j * 2 + 1] = loadmodel->brushq3.data_texcoordtexture2f[(firstvertex + j) * 2 + 1];
(loadmodel->surfmesh.data_texcoordlightmap2f + 2 * out->num_firstvertex)[j * 2 + 0] = loadmodel->brushq3.data_texcoordlightmap2f[(firstvertex + j) * 2 + 0];
patchsize[0] = LittleLong(in->specific.patch.patchsize[0]);
patchsize[1] = LittleLong(in->specific.patch.patchsize[1]);
originalvertex3f = loadmodel->brushq3.data_vertex3f + firstvertex * 3;
+ originalnormal3f = loadmodel->brushq3.data_normal3f + firstvertex * 3;
originaltexcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f + firstvertex * 2;
originaltexcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f + firstvertex * 2;
originalcolor4f = loadmodel->brushq3.data_color4f + firstvertex * 4;
// generate geometry
// (note: normals are skipped because they get recalculated)
Q3PatchTesselateFloat(3, sizeof(float[3]), (loadmodel->surfmesh.data_vertex3f + 3 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[3]), originalvertex3f, xtess, ytess);
+ Q3PatchTesselateFloat(3, sizeof(float[3]), (loadmodel->surfmesh.data_normal3f + 3 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[3]), originalnormal3f, xtess, ytess);
Q3PatchTesselateFloat(2, sizeof(float[2]), (loadmodel->surfmesh.data_texcoordtexture2f + 2 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[2]), originaltexcoordtexture2f, xtess, ytess);
Q3PatchTesselateFloat(2, sizeof(float[2]), (loadmodel->surfmesh.data_texcoordlightmap2f + 2 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[2]), originaltexcoordlightmap2f, xtess, ytess);
Q3PatchTesselateFloat(4, sizeof(float[4]), (loadmodel->surfmesh.data_lightmapcolor4f + 4 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[4]), originalcolor4f, xtess, ytess);
}
Con_Print("\n");
}
- // for per pixel lighting
- Mod_BuildTextureVectorsAndNormals(out->num_firstvertex, out->num_vertices, out->num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, (loadmodel->surfmesh.data_element3i + 3 * out->num_firsttriangle), loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, loadmodel->surfmesh.data_normal3f, true);
// calculate a bounding box
VectorClear(out->mins);
VectorClear(out->maxs);
//out->lightmapinfo->styles[3] = 255;
}
+ // for per pixel lighting
+ Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, true);
+
// free the no longer needed vertex data
loadmodel->brushq3.num_vertices = 0;
Mem_Free(loadmodel->brushq3.data_vertex3f);
loadmodel->brushq3.data_vertex3f = NULL;
+ loadmodel->brushq3.data_normal3f = NULL;
loadmodel->brushq3.data_texcoordtexture2f = NULL;
loadmodel->brushq3.data_texcoordlightmap2f = NULL;
loadmodel->brushq3.data_color4f = NULL;