#include "r_shadow.h"
#include "polygon.h"
#include "curves.h"
+#include "wad.h"
+
// note: model_shared.c sets up r_notexture, and r_surf_notexture
int i, ds, dt;
msurface_t *surf;
- surf = cl.worldmodel->brushq1.surfaces + node->firstsurface;
+ surf = r_refdef.worldmodel->brushq1.surfaces + node->firstsurface;
for (i = 0;i < node->numsurfaces;i++, surf++)
{
if (!(surf->flags & SURF_LIGHTMAP) || !surf->samples)
void Mod_Q1BSP_LightPoint(model_t *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal)
{
- Mod_Q1BSP_LightPoint_RecursiveBSPNode(ambientcolor, diffusecolor, diffusenormal, cl.worldmodel->brushq1.nodes + cl.worldmodel->brushq1.hulls[0].firstclipnode, p[0], p[1], p[2], p[2] - 65536);
+ Mod_Q1BSP_LightPoint_RecursiveBSPNode(ambientcolor, diffusecolor, diffusenormal, model->brushq1.nodes + model->brushq1.hulls[0].firstclipnode, p[0], p[1], p[2], p[2] - 65536);
}
static void Mod_Q1BSP_DecompressVis(const qbyte *in, const qbyte *inend, qbyte *out, qbyte *outend)
{
if (in == inend)
{
- Con_DPrintf("Mod_Q1BSP_DecompressVis: input underrun on model \"%s\" (decompressed %i of %i output bytes)\n", loadmodel->name, out - outstart, outend - outstart);
+ Con_Printf("Mod_Q1BSP_DecompressVis: input underrun on model \"%s\" (decompressed %i of %i output bytes)\n", loadmodel->name, out - outstart, outend - outstart);
return;
}
c = *in++;
{
if (in == inend)
{
- Con_DPrintf("Mod_Q1BSP_DecompressVis: input underrun (during zero-run) on model \"%s\" (decompressed %i of %i output bytes)\n", loadmodel->name, out - outstart, outend - outstart);
+ Con_Printf("Mod_Q1BSP_DecompressVis: input underrun (during zero-run) on model \"%s\" (decompressed %i of %i output bytes)\n", loadmodel->name, out - outstart, outend - outstart);
return;
}
for (c = *in++;c > 0;c--)
{
if (out == outend)
{
- Con_DPrintf("Mod_Q1BSP_DecompressVis: output overrun on model \"%s\" (decompressed %i of %i output bytes)\n", loadmodel->name, out - outstart, outend - outstart);
+ Con_Printf("Mod_Q1BSP_DecompressVis: output overrun on model \"%s\" (decompressed %i of %i output bytes)\n", loadmodel->name, out - outstart, outend - outstart);
return;
}
*out++ = 0;
static void Mod_Q1BSP_LoadLightList(void)
{
int a, n, numlights;
- char lightsfilename[1024], *s, *t, *lightsstring;
+ char tempchar, *s, *t, *lightsstring, lightsfilename[1024];
mlight_t *e;
strlcpy (lightsfilename, loadmodel->name, sizeof (lightsfilename));
numlights = 0;
while (*s)
{
- while (*s && *s != '\n')
+ while (*s && *s != '\n' && *s != '\r')
s++;
if (!*s)
{
Mem_Free(lightsstring);
- Host_Error("lights file must end with a newline\n");
+ Con_Printf("lights file must end with a newline\n");
+ return;
}
s++;
numlights++;
while (*s && n < numlights)
{
t = s;
- while (*s && *s != '\n')
+ while (*s && *s != '\n' && *s != '\r')
s++;
if (!*s)
{
- Mem_Free(lightsstring);
- Host_Error("misparsed lights file!\n");
+ Con_Printf("misparsed lights file!\n");
+ break;
}
e = loadmodel->brushq1.lights + n;
+ tempchar = *s;
*s = 0;
a = sscanf(t, "%f %f %f %f %f %f %f %f %f %f %f %f %f %d", &e->origin[0], &e->origin[1], &e->origin[2], &e->falloff, &e->light[0], &e->light[1], &e->light[2], &e->subtract, &e->spotdir[0], &e->spotdir[1], &e->spotdir[2], &e->spotcone, &e->distbias, &e->style);
- *s = '\n';
+ *s = tempchar;
if (a != 14)
{
- Mem_Free(lightsstring);
- Host_Error("invalid lights file, found %d parameters on line %i, should be 14 parameters (origin[0] origin[1] origin[2] falloff light[0] light[1] light[2] subtract spotdir[0] spotdir[1] spotdir[2] spotcone distancebias style)\n", a, n + 1);
+ Con_Printf("invalid lights file, found %d parameters on line %i, should be 14 parameters (origin[0] origin[1] origin[2] falloff light[0] light[1] light[2] subtract spotdir[0] spotdir[1] spotdir[2] spotcone distancebias style)\n", a, n + 1);
+ break;
}
- s++;
+ if (*s == '\r')
+ s++;
+ if (*s == '\n')
+ s++;
n++;
}
if (*s)
- {
- Mem_Free(lightsstring);
- Host_Error("misparsed lights file!\n");
- }
+ Con_Printf("misparsed lights file!\n");
loadmodel->brushq1.numlights = numlights;
Mem_Free(lightsstring);
}
}
}
+static void Mod_Q1BSP_LoadMapBrushes(void)
+{
+#if 0
+// unfinished
+ int submodel, numbrushes;
+ qboolean firstbrush;
+ char *text, *maptext;
+ char mapfilename[MAX_QPATH];
+ FS_StripExtension (loadmodel->name, mapfilename, sizeof (mapfilename));
+ strlcat (mapfilename, ".map", sizeof (mapfilename));
+ maptext = (qbyte*) FS_LoadFile(mapfilename, tempmempool, false);
+ if (!maptext)
+ return;
+ text = maptext;
+ if (!COM_ParseToken(&data, false))
+ return; // error
+ submodel = 0;
+ for (;;)
+ {
+ if (!COM_ParseToken(&data, false))
+ break;
+ if (com_token[0] != '{')
+ return; // error
+ // entity
+ firstbrush = true;
+ numbrushes = 0;
+ maxbrushes = 256;
+ brushes = Mem_Alloc(loadmodel->mempool, maxbrushes * sizeof(mbrush_t));
+ for (;;)
+ {
+ if (!COM_ParseToken(&data, false))
+ return; // error
+ if (com_token[0] == '}')
+ break; // end of entity
+ if (com_token[0] == '{')
+ {
+ // brush
+ if (firstbrush)
+ {
+ if (submodel)
+ {
+ if (submodel > loadmodel->brush.numsubmodels)
+ {
+ Con_Printf("Mod_Q1BSP_LoadMapBrushes: .map has more submodels than .bsp!\n");
+ model = NULL;
+ }
+ else
+ model = loadmodel->brush.submodels[submodel];
+ }
+ else
+ model = loadmodel;
+ }
+ for (;;)
+ {
+ if (!COM_ParseToken(&data, false))
+ return; // error
+ if (com_token[0] == '}')
+ break; // end of brush
+ // each brush face should be this format:
+ // ( x y z ) ( x y z ) ( x y z ) texture scroll_s scroll_t rotateangle scale_s scale_t
+ // FIXME: support hl .map format
+ for (pointnum = 0;pointnum < 3;pointnum++)
+ {
+ COM_ParseToken(&data, false);
+ for (componentnum = 0;componentnum < 3;componentnum++)
+ {
+ COM_ParseToken(&data, false);
+ point[pointnum][componentnum] = atof(com_token);
+ }
+ COM_ParseToken(&data, false);
+ }
+ COM_ParseToken(&data, false);
+ strlcpy(facetexture, com_token, sizeof(facetexture));
+ COM_ParseToken(&data, false);
+ //scroll_s = atof(com_token);
+ COM_ParseToken(&data, false);
+ //scroll_t = atof(com_token);
+ COM_ParseToken(&data, false);
+ //rotate = atof(com_token);
+ COM_ParseToken(&data, false);
+ //scale_s = atof(com_token);
+ COM_ParseToken(&data, false);
+ //scale_t = atof(com_token);
+ TriangleNormal(point[0], point[1], point[2], planenormal);
+ VectorNormalizeDouble(planenormal);
+ planedist = DotProduct(point[0], planenormal);
+ //ChooseTexturePlane(planenormal, texturevector[0], texturevector[1]);
+ }
+ continue;
+ }
+ }
+ }
+#endif
+}
+
+
#define MAX_PORTALPOINTS 64
typedef struct portal_s
RemovePortalFromNodes(portal);
// cut the portal into two portals, one on each side of the node plane
- PolygonD_Divide(portal->numpoints, portal->points, plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, 1.0/32.0, MAX_PORTALPOINTS, frontpoints, &numfrontpoints, MAX_PORTALPOINTS, backpoints, &numbackpoints);
+ PolygonD_Divide(portal->numpoints, portal->points, plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, 1.0/32.0, MAX_PORTALPOINTS, frontpoints, &numfrontpoints, MAX_PORTALPOINTS, backpoints, &numbackpoints);
if (!numfrontpoints)
{
extern void R_Q1BSP_Draw(entity_render_t *ent);
extern void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outclusterlist, qbyte *outclusterpvs, int *outnumclusterspointer, int *outsurfacelist, qbyte *outsurfacepvs, int *outnumsurfacespointer);
extern void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist);
-extern void R_Q1BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap, int numsurfaces, const int *surfacelist);
+extern void R_Q1BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int numsurfaces, const int *surfacelist);
void Mod_Q1BSP_Load(model_t *mod, void *buffer)
{
int i, j, k;
Mod_Q1BSP_MakePortals();
mod->numframes = 2; // regular and alternate animation
+ mod->numskins = 1;
mainmempool = mod->mempool;
Mod_Q1BSP_LoadLightList();
- loadmodel = loadmodel;
// make a single combined shadow mesh to allow optimized shadow volume creation
numshadowmeshtriangles = 0;
Mod_ShadowMesh_AddMesh(loadmodel->mempool, loadmodel->brush.shadowmesh, NULL, NULL, NULL, surf->mesh.data_vertex3f, NULL, NULL, NULL, NULL, surf->mesh.num_triangles, surf->mesh.data_element3i);
loadmodel->brush.shadowmesh = Mod_ShadowMesh_Finish(loadmodel->mempool, loadmodel->brush.shadowmesh, false, true);
Mod_BuildTriangleNeighbors(loadmodel->brush.shadowmesh->neighbor3i, loadmodel->brush.shadowmesh->element3i, loadmodel->brush.shadowmesh->numtriangles);
-
+
+ if (loadmodel->brush.numsubmodels)
+ loadmodel->brush.submodels = Mem_Alloc(loadmodel->mempool, loadmodel->brush.numsubmodels * sizeof(model_t *));
+
// LordHavoc: to clear the fog around the original quake submodel code, I
// will explain:
// first of all, some background info on the submodels:
mod->mempool = NULL;
}
+ if (loadmodel->brush.submodels)
+ loadmodel->brush.submodels[i] = mod;
+
bm = &mod->brushq1.submodels[i];
mod->brushq1.hulls[0].firstclipnode = bm->headnode[0];
mod->brushq1.num_visleafs = bm->visleafs;
}
+ Mod_Q1BSP_LoadMapBrushes();
+
//Mod_Q1BSP_ProcessLightList();
if (developer.integer)
else if (numparameters >= 3 && !strcasecmp(parameter[0], "animmap"))
strlcpy(firstpasstexturename, parameter[2], sizeof(firstpasstexturename));
}
+ if (!strcasecmp(parameter[0], "alphafunc"))
+ flags2 |= Q3TEXTUREFLAG_ALPHATEST;
// break out a level if it was }
if (!strcasecmp(com_token, "}"))
break;
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]);
}
// force transparent render path for a number of odd
// shader effects to avoid bogging down the normal
// render path unnecessarily
- if (flags2 & (Q3TEXTUREFLAG_ADDITIVE | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
+ if (flags2 & (Q3TEXTUREFLAG_ADDITIVE | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2 | Q3TEXTUREFLAG_ALPHATEST))
flags |= Q3SURFACEPARM_TRANS;
// add shader to list (shadername and flags)
// actually here we just poke into the texture settings
if ((flags & Q3SURFACEPARM_SKY) && sky[0])
{
// quake3 seems to append a _ to the skybox name, so this must do so as well
- snprintf(loadmodel->brush.skybox, sizeof(loadmodel->brush.skybox), "%s_", sky);
+ dpsnprintf(loadmodel->brush.skybox, sizeof(loadmodel->brush.skybox), "%s_", sky);
}
}
}
Con_DPrintf("%s: No shader found for texture \"%s\"\n", loadmodel->name, out->name);
out->surfaceparms = 0;
// these are defaults
- if (!strncmp(out->name, "textures/skies/", 15))
- out->surfaceparms |= Q3SURFACEPARM_SKY;
+ //if (!strncmp(out->name, "textures/skies/", 15))
+ // out->surfaceparms |= Q3SURFACEPARM_SKY;
//if (!strcmp(out->name, "caulk") || !strcmp(out->name, "common/caulk") || !strcmp(out->name, "textures/common/caulk")
// || !strcmp(out->name, "nodraw") || !strcmp(out->name, "common/nodraw") || !strcmp(out->name, "textures/common/nodraw"))
// out->surfaceparms |= Q3SURFACEPARM_NODRAW;
// out->surfaceparms |= Q3SURFACEPARM_TRANS;
}
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, true))
- 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, 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, true))
+ Con_Printf("%s: texture loading for shader \"%s\" failed (first layer \"%s\" not found either)\n", loadmodel->name, out->name, out->firstpasstexturename);
}
- Con_DPrintf("%s: %i textures missing shaders\n", loadmodel->name, c);
+ if (c)
+ Con_DPrintf("%s: %i textures missing shaders\n", loadmodel->name, c);
}
static void Mod_Q3BSP_LoadPlanes(lump_t *l)
else
out->effect = loadmodel->brushq3.data_effects + n;
n = LittleLong(in->lightmapindex);
- if (n < -1 || n >= loadmodel->brushq3.num_lightmaps)
+ if (n >= loadmodel->brushq3.num_lightmaps)
{
- Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid lightmapindex %i (%i lightmaps)\n", i, out->texture->name, n, loadmodel->brushq3.num_lightmaps);
+ Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid lightmapindex %i (%i lightmaps)\n", i, out->texture->name, n, loadmodel->brushq3.num_lightmaps);
n = -1;
}
+ else if (n < 0)
+ n = -1;
if (n == -1)
out->lightmaptexture = NULL;
else
Q3PatchTesselateFloat(3, sizeof(float[3]), out->data_collisionvertex3f, patchsize[0], patchsize[1], sizeof(float[3]), originalvertex3f, xtess, ytess);
Q3PatchTriangleElements(out->data_collisionelement3i, finalwidth, finalheight);
- Mod_SnapVertices(3, out->num_vertices, out->data_vertex3f, 0.25);
+ //Mod_SnapVertices(3, out->num_vertices, out->data_vertex3f, 0.25);
Mod_SnapVertices(3, out->num_collisionvertices, out->data_collisionvertex3f, 1);
oldnumtriangles = out->num_triangles;
// leafs to find real number of clusters
loadmodel->brush.num_pvsclusters = 1;
for (i = 0;i < loadmodel->brushq3.num_leafs;i++)
- loadmodel->brush.num_pvsclusters = min(loadmodel->brush.num_pvsclusters, loadmodel->brushq3.data_leafs[i].clusterindex + 1);
+ loadmodel->brush.num_pvsclusters = max(loadmodel->brush.num_pvsclusters, loadmodel->brushq3.data_leafs[i].clusterindex + 1);
// create clusters
loadmodel->brush.num_pvsclusterbytes = (loadmodel->brush.num_pvsclusters + 7) / 8;
if (dist1near >= 0 && dist2near >= 0 && dist1far < 0 && dist2far >= 0){node = node->children[0];continue;}
if (dist1near >= 0 && dist2near >= 0 && dist1far >= 0 && dist2far < 0){node = node->children[0];continue;}
if (dist1near >= 0 && dist2near >= 0 && dist1far >= 0 && dist2far >= 0){node = node->children[0];continue;}
- {
+ {
if (dist2near < 0) // d1n<0 && d2n<0
{
if (dist2near < 0) // d1n<0 && d2n<0
extern void R_Q3BSP_Draw(struct entity_render_s *ent);
extern void R_Q3BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outclusterlist, qbyte *outclusterpvs, int *outnumclusterspointer, int *outsurfacelist, qbyte *outsurfacepvs, int *outnumsurfacespointer);
extern void R_Q3BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist);
-extern void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap, int numsurfaces, const int *surfacelist);
+extern void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int numsurfaces, const int *surfacelist);
void Mod_Q3BSP_Load(model_t *mod, void *buffer)
{
int i, j, numshadowmeshtriangles;
q3msurface_t *face;
mod->type = mod_brushq3;
- mod->numframes = 1;
+ mod->numframes = 2; // although alternate textures are not supported it is annoying to complain about no such frame 1
mod->numskins = 1;
header = (q3dheader_t *)buffer;