if (e->render.model)
{
Mod_CheckLoaded(e->render.model);
- if (e->render.model->type != mod_brush)
+ if (e->render.model->type == mod_alias || e->render.model->type == mod_sprite)
angles[0] = -angles[0];
if (e->render.model->flags & EF_ROTATE)
{
// as soon as player is known we can call V_CalcRefDef
if ((e - cl_entities) == cl.viewentity)
V_CalcRefdef();
- if (e->render.model && e->render.model->name[0] == '*' && e->render.model->type == mod_brush)
+ if (e->render.model && e->render.model->name[0] == '*' && e->render.model->brush.TraceBox)
cl_brushmodel_entities[cl_num_brushmodel_entities++] = &e->render;
// don't show entities with no modelindex (note: this still shows
// entities which have a modelindex that resolved to a NULL model)
entity_render_t *ent;
model_t *model;
vec3_t org;
- if (cl.worldmodel == NULL)
+ if (cl.worldmodel == NULL || !cl.worldmodel->brushq1.nodes)
return;
fcolor[0] = cr1;
fcolor[1] = cg1;
if (model && model->name[0] == '*')
{
Mod_CheckLoaded(model);
- if (model->type == mod_brush)
+ if (model->brushq1.nodes)
{
Matrix4x4_Transform(&ent->inversematrix, origin, org);
R_StainNode(model->brushq1.nodes + model->brushq1.hulls[0].firstclipnode, model, org, radius, fcolor);
}
}
-void R_WorldVisibility (entity_render_t *ent)
+void R_WorldVisibility(entity_render_t *ent)
{
vec3_t modelorg;
mleaf_t *viewleaf;
Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
- viewleaf = ent->model ? ent->model->brushq1.PointInLeaf(ent->model, modelorg) : NULL;
+ viewleaf = (ent->model && ent->model->brushq1.PointInLeaf) ? ent->model->brushq1.PointInLeaf(ent->model, modelorg) : NULL;
R_PVSUpdate(ent, viewleaf);
if (!viewleaf)
R_PortalWorldNode (ent, viewleaf);
}
-void R_DrawWorld (entity_render_t *ent)
+void R_DrawWorld(entity_render_t *ent)
{
if (ent->model == NULL)
return;
- R_PrepareSurfaces(ent);
- R_DrawSurfaces(ent, SHADERSTAGE_SKY, ent->model->brushq1.pvstexturechains);
- R_DrawSurfaces(ent, SHADERSTAGE_NORMAL, ent->model->brushq1.pvstexturechains);
- if (r_drawportals.integer)
- R_DrawPortals(ent);
+ if (!ent->model->brushq1.numleafs && ent->model->Draw)
+ ent->model->Draw(ent);
+ else
+ {
+ R_PrepareSurfaces(ent);
+ R_DrawSurfaces(ent, SHADERSTAGE_SKY, ent->model->brushq1.pvstexturechains);
+ R_DrawSurfaces(ent, SHADERSTAGE_NORMAL, ent->model->brushq1.pvstexturechains);
+ if (r_drawportals.integer)
+ R_DrawPortals(ent);
+ }
}
-void R_Model_Brush_DrawSky (entity_render_t *ent)
+void R_Model_Brush_DrawSky(entity_render_t *ent)
{
if (ent->model == NULL)
return;
R_DrawSurfaces(ent, SHADERSTAGE_SKY, ent->model->brushq1.pvstexturechains);
}
-void R_Model_Brush_Draw (entity_render_t *ent)
+void R_Model_Brush_Draw(entity_render_t *ent)
{
if (ent->model == NULL)
return;
}
}
+void R_Q3BSP_DrawFace_Mesh(entity_render_t *ent, q3mface_t *face)
+{
+ const surfmesh_t *mesh;
+ rmeshstate_t m;
+ memset(&m, 0, sizeof(m));
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_DepthMask(true);
+ GL_DepthTest(true);
+ m.tex[0] = R_GetTexture(face->texture->skin.base);
+ m.pointer_texcoord[0] = face->data_texcoordtexture2f;
+ if (face->lightmaptexture)
+ {
+ m.tex[1] = R_GetTexture(face->lightmaptexture);
+ m.pointer_texcoord[1] = face->data_texcoordlightmap2f;
+ m.texrgbscale[1] = 2;
+ GL_Color(r_colorscale, r_colorscale, r_colorscale, 1);
+ }
+ else
+ {
+ m.texrgbscale[0] = 2;
+ GL_ColorPointer(face->data_color4f);
+ }
+ R_Mesh_State_Texture(&m);
+ GL_VertexPointer(face->data_vertex3f);
+ R_Mesh_Draw(mesh->numverts, mesh->numtriangles, mesh->element3i);
+}
+
+void R_Q3BSP_DrawFace_Patch(entity_render_t *ent, q3mface_t *face)
+{
+}
+
+void R_Q3BSP_DrawFace(entity_render_t *ent, q3mface_t *face)
+{
+ switch(face->type)
+ {
+ case Q3FACETYPE_POLYGON:
+ case Q3FACETYPE_MESH:
+ R_Q3BSP_DrawFace_Mesh(ent, face);
+ break;
+ case Q3FACETYPE_PATCH:
+ R_Q3BSP_DrawFace_Patch(ent, face);
+ break;
+ case Q3FACETYPE_FLARE:
+ break;
+ }
+}
+
/*
void R_Q3BSP_DrawSky(entity_render_t *ent)
{
void R_Q3BSP_Draw(entity_render_t *ent)
{
+ int i;
+ q3mface_t *face;
+ model_t *model;
+ model = ent->model;
+ for (i = 0, face = model->brushq3.data_thismodel->firstface;i < model->brushq3.data_thismodel->numfaces;i++, face++)
+ R_Q3BSP_DrawFace(ent, face);
}
/*
char sv_spawnmap[MAX_QPATH];
char sv_loadgame[MAX_OSPATH];
+cvar_t sv_cheats = {0, "sv_cheats", "0"};
+qboolean allowcheats = false;
+
mfunction_t *ED_FindFunction (char *name);
/*
return;
}
- if (pr_global_struct->deathmatch || !sv_player)
+ if (!sv_player)
+ return;
+
+ if (!allowcheats)
+ {
+ SV_ClientPrintf("No cheats allowed, use sv_cheats 1 and restart level to enable.\n");
return;
+ }
sv_player->v->flags = (int)sv_player->v->flags ^ FL_GODMODE;
if (!((int)sv_player->v->flags & FL_GODMODE) )
return;
}
- if (pr_global_struct->deathmatch || !sv_player)
+ if (!sv_player)
return;
+ if (!allowcheats)
+ {
+ SV_ClientPrintf("No cheats allowed, use sv_cheats 1 and restart level to enable.\n");
+ return;
+ }
+
sv_player->v->flags = (int)sv_player->v->flags ^ FL_NOTARGET;
if (!((int)sv_player->v->flags & FL_NOTARGET) )
SV_ClientPrintf ("notarget OFF\n");
return;
}
- if (pr_global_struct->deathmatch || !sv_player)
+ if (!sv_player)
return;
+ if (!allowcheats)
+ {
+ SV_ClientPrintf("No cheats allowed, use sv_cheats 1 and restart level to enable.\n");
+ return;
+ }
+
if (sv_player->v->movetype != MOVETYPE_NOCLIP)
{
noclip_anglehack = true;
return;
}
- if (pr_global_struct->deathmatch || !sv_player)
+ if (!sv_player)
return;
+ if (!allowcheats)
+ {
+ SV_ClientPrintf("No cheats allowed, use sv_cheats 1 and restart level to enable.\n");
+ return;
+ }
+
if (sv_player->v->movetype != MOVETYPE_FLY)
{
sv_player->v->movetype = MOVETYPE_FLY;
str = FS_Getline (f);
sscanf (str, "%f\n",&time);
+ allowcheats = sv_cheats.integer != 0;
SV_SpawnServer (mapname);
if (!sv.active)
{
int i;
qboolean byNumber = false;
- if (cmd_source == src_command)
- {
- if (!sv.active)
- {
- Cmd_ForwardToServer ();
- return;
- }
- }
- else if (pr_global_struct->deathmatch)
+ if (cmd_source != src_command || !sv.active)
return;
save = host_client;
return;
}
- if (pr_global_struct->deathmatch || !sv_player)
+ if (!sv_player)
return;
+ if (!allowcheats)
+ {
+ SV_ClientPrintf("No cheats allowed, use sv_cheats 1 and restart level to enable.\n");
+ return;
+ }
+
t = Cmd_Argv(1);
v = atoi (Cmd_Argv(2));
if (sv_loadgame[0])
Host_PerformLoadGame(sv_loadgame);
else if (sv_spawnmap[0])
+ {
+ allowcheats = sv_cheats.integer != 0;
SV_SpawnServer(sv_spawnmap);
+ }
sv_loadgame[0] = 0;
sv_spawnmap[0] = 0;
if (sv.active && cls.state == ca_disconnected)
Cmd_AddCommand ("prespawn", Host_PreSpawn_f);
Cmd_AddCommand ("spawn", Host_Spawn_f);
Cmd_AddCommand ("begin", Host_Begin_f);
+
+ Cvar_RegisterVariable(&sv_cheats);
}
q3mbrush_t *out;
int i, j, k, m, n, c, count, numpoints, numplanes;
winding_t *w;
+ mplane_t plane;
colpointf_t pointsbuf[256*3];
colplanef_t planesbuf[256], colplanef;
numplanes = 0;
for (j = 0;j < out->numbrushsides;j++)
{
+ // for some reason the planes are all flipped compared to what I
+ // would expect, so this has to negate them...
+
// create a huge polygon for the plane
- w = BaseWindingForPlane(out->firstbrushside[j].plane);
+ VectorNegate(out->firstbrushside[j].plane->normal, plane.normal);
+ plane.dist = -out->firstbrushside[j].plane->dist;
+ w = BaseWindingForPlane(&plane);
// clip it by all other planes
for (k = 0;k < out->numbrushsides && w;k++)
+ {
if (k != j)
- w = ClipWinding(w, out->firstbrushside[k].plane, true);
+ {
+ VectorNegate(out->firstbrushside[k].plane->normal, plane.normal);
+ plane.dist = -out->firstbrushside[k].plane->dist;
+ w = ClipWinding(w, &plane, true);
+ }
+ }
// if nothing is left, skip it
// FIXME: should keep count of how many were skipped and report
// it, just for sake of statistics
for (k = 0;k < w->numpoints;k++)
{
for (m = 0;m < numpoints;m++)
- if (VectorDistance2(w->points[k * 3], pointsbuf[m * 3].v) < DIST_EPSILON)
+ if (VectorDistance2(w->points[k], pointsbuf[m].v) < DIST_EPSILON)
break;
if (m == numpoints)
{
goto failedtomakecolbrush;
}
// add the new one
- VectorCopy(w->points[k * 3], pointsbuf[numpoints * 3].v);
+ VectorCopy(w->points[k], pointsbuf[numpoints].v);
numpoints++;
}
}
if (numplanes && numpoints)
{
out->colbrushf = Collision_AllocBrushFloat(loadmodel->mempool, numpoints, numplanes);
- memcpy(out->colbrushf->points, pointsbuf, numpoints * sizeof(float[3]));
- memcpy(out->colbrushf->planes, planesbuf, numplanes * sizeof(mplane_t));
+ memcpy(out->colbrushf->points, pointsbuf, numpoints * sizeof(colpointf_t));
+ memcpy(out->colbrushf->planes, planesbuf, numplanes * sizeof(colplanef_t));
}
// return from errors to here
failedtomakecolbrush:;
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 = Mem_Alloc(loadmodel->mempool, count * sizeof(float[3]));
- loadmodel->brushq3.data_texturetexcoord2f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[2]));
- loadmodel->brushq3.data_lightmaptexcoord2f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[2]));
+ loadmodel->brushq3.data_texcoordtexture2f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[2]));
+ loadmodel->brushq3.data_texcoordlightmap2f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[2]));
loadmodel->brushq3.data_svector3f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[3]));
loadmodel->brushq3.data_tvector3f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[3]));
loadmodel->brushq3.data_normal3f = Mem_Alloc(loadmodel->mempool, count * sizeof(float[3]));
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_texturetexcoord2f[i * 2 + 0] = LittleFloat(in->texcoord2f[0]);
- loadmodel->brushq3.data_texturetexcoord2f[i * 2 + 1] = LittleFloat(in->texcoord2f[1]);
- loadmodel->brushq3.data_lightmaptexcoord2f[i * 2 + 0] = LittleFloat(in->lightmap2f[0]);
- loadmodel->brushq3.data_lightmaptexcoord2f[i * 2 + 1] = LittleFloat(in->lightmap2f[1]);
+ 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_texcoordlightmap2f[i * 2 + 1] = LittleFloat(in->lightmap2f[1]);
// svector/tvector are calculated later in face loading
loadmodel->brushq3.data_svector3f[i * 3 + 0] = 0;
loadmodel->brushq3.data_svector3f[i * 3 + 1] = 0;
case Q3FACETYPE_POLYGON:
case Q3FACETYPE_MESH:
out->data_vertex3f = loadmodel->brushq3.data_vertex3f + out->firstvertex * 3;
- out->data_texturetexcoord2f = loadmodel->brushq3.data_texturetexcoord2f + out->firstvertex * 2;
- out->data_lightmaptexcoord2f = loadmodel->brushq3.data_lightmaptexcoord2f + out->firstvertex * 2;
+ out->data_texcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f + out->firstvertex * 2;
+ out->data_texcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f + out->firstvertex * 2;
out->data_svector3f = loadmodel->brushq3.data_svector3f + out->firstvertex * 3;
out->data_tvector3f = loadmodel->brushq3.data_tvector3f + out->firstvertex * 3;
out->data_normal3f = loadmodel->brushq3.data_normal3f + out->firstvertex * 3;
q3mleaf_t *leaf;
leaf = (q3mleaf_t *)node;
for (i = 0;i < leaf->numleafbrushes;i++)
- Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, leaf->firstleafbrush[i]->colbrushf, leaf->firstleafbrush[i]->colbrushf);
+ if (leaf->firstleafbrush[i]->colbrushf)
+ Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, leaf->firstleafbrush[i]->colbrushf, leaf->firstleafbrush[i]->colbrushf);
}
}
Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace, model->brushq3.data_nodes, thisbrush_start, thisbrush_end);
else
for (i = 0;i < model->brushq3.num_brushes;i++)
- Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, model->brushq3.data_brushes[i].colbrushf, model->brushq3.data_brushes[i].colbrushf);
+ if (model->brushq3.data_brushes[i].colbrushf)
+ Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, model->brushq3.data_brushes[i].colbrushf, model->brushq3.data_brushes[i].colbrushf);
}
int i;
q3dheader_t *header;
- mod->type = mod_brushq2;
+ mod->type = mod_brushq3;
header = (q3dheader_t *)buffer;
Mod_Q3BSP_LoadNodes(&header->lumps[Q3LUMP_NODES]);
Mod_Q3BSP_LoadLightGrid(&header->lumps[Q3LUMP_LIGHTGRID]);
Mod_Q3BSP_LoadPVS(&header->lumps[Q3LUMP_PVS]);
+ loadmodel->brush.numsubmodels = loadmodel->brushq3.num_models;
+
+ for (i = 0;i < loadmodel->brushq3.num_models;i++)
+ {
+ if (i == 0)
+ mod = loadmodel;
+ else
+ {
+ char name[10];
+ // LordHavoc: only register submodels if it is the world
+ // (prevents bsp models from replacing world submodels)
+ if (!loadmodel->isworldmodel)
+ continue;
+ // duplicate the basic information
+ sprintf(name, "*%i", i);
+ mod = Mod_FindName(name);
+ *mod = *loadmodel;
+ strcpy(mod->name, name);
+ // textures and memory belong to the main model
+ mod->texturepool = NULL;
+ mod->mempool = NULL;
+ }
+ mod->brushq3.data_thismodel = loadmodel->brushq3.data_models + i;
+ }
}
void Mod_IBSP_Load(model_t *mod, void *buffer)
int patchsize[2];
float *data_vertex3f;
- float *data_texturetexcoord2f;
- float *data_lightmaptexcoord2f;
+ float *data_texcoordtexture2f;
+ float *data_texcoordlightmap2f;
float *data_svector3f;
float *data_tvector3f;
float *data_normal3f;
int num_models;
q3mmodel_t *data_models;
// each submodel gets its own model struct so this is different for each.
- q3mmodel_t data_thismodel;
+ q3mmodel_t *data_thismodel;
int num_brushes;
q3mbrush_t *data_brushes;
int num_vertices;
float *data_vertex3f;
- float *data_texturetexcoord2f;
- float *data_lightmaptexcoord2f;
+ float *data_texcoordtexture2f;
+ float *data_texcoordlightmap2f;
float *data_svector3f;
float *data_tvector3f;
float *data_normal3f;
// if there is no model, it can not block visibility
if (model == NULL)
- Host_Error("Portal_Visibility: NULL model\n");
+ {
+ Con_Printf("Portal_Visibility: NULL model\n");
+ return;
+ }
Mod_CheckLoaded(model);
- if (model->type != mod_brush)
- Host_Error("Portal_Visibility: not a brush model\n");
+ if (!model->brushq1.numportals)
+ {
+ Con_Printf("Portal_Visibility: not a brush model\n");
+ return;
+ }
// put frustum planes (if any) into tinyplane format at start of buffer
for (i = 0;i < numfrustumplanes;i++)
if (modelindex < 1 || modelindex >= MAX_MODELS)
return NULL;
model = sv.models[modelindex];
- if (model->type != mod_brush)
- return NULL;
if (surfnum < 0 || surfnum >= model->brushq1.nummodelsurfaces)
return NULL;
return model->brushq1.surfaces + surfnum + model->brushq1.firstmodelsurface;
if (modelindex < 1 || modelindex >= MAX_MODELS)
return;
model = sv.models[modelindex];
- if (model->type != mod_brush)
+ if (!model->brushq1.numsurfaces)
return;
// FIXME: implement rotation/scaling
int i, bit, bitindex;
rdlight_t *rd;
vec3_t lightorigin;
- if (!gl_flashblend.integer && r_dynamic.integer && ent->model)
+ if (!gl_flashblend.integer && r_dynamic.integer && ent->model && ent->model->brushq1.numleafs)
{
for (i = 0, rd = r_dlight;i < r_numdlights;i++, rd++)
{
{
//Con_Printf("-- entnum %i origin %f %f %f neworigin %f %f %f\n", ch->entnum, ch->origin[0], ch->origin[1], ch->origin[2], cl_entities[ch->entnum].state_current.origin[0], cl_entities[ch->entnum].state_current.origin[1], cl_entities[ch->entnum].state_current.origin[2]);
VectorCopy(cl_entities[ch->entnum].state_current.origin, ch->origin);
- if (cl_entities[ch->entnum].state_current.modelindex && cl.model_precache[cl_entities[ch->entnum].state_current.modelindex]->type == mod_brush)
+ if (cl_entities[ch->entnum].state_current.modelindex && cl.model_precache[cl_entities[ch->entnum].state_current.modelindex]->brush.TraceBox)
VectorMAMAM(1.0f, ch->origin, 0.5f, cl.model_precache[cl_entities[ch->entnum].state_current.modelindex]->normalmins, 0.5f, cl.model_precache[cl_entities[ch->entnum].state_current.modelindex]->normalmaxs, ch->origin);
}
}
// don't try to cull embedded brush models with this, they're sometimes huge (spanning several rooms)
- if (sv_cullentities_trace.integer && (model == NULL || model->type != mod_brush || model->name[0] != '*'))
+ if (sv_cullentities_trace.integer && (model == NULL || model->brush.TraceBox == NULL || model->name[0] != '*'))
{
// LordHavoc: test random offsets, to maximize chance of detection
testorigin[0] = lhrandom(entmins[0], entmaxs[0]);
if (model != NULL)
{
Mod_CheckLoaded(model);
- if (model->type != mod_brush)
+ if (!model->brush.TraceBox)
Host_Error("SOLID_BSP with non-BSP model\n");
if (ent->v->angles[0] || ent->v->angles[2] || ent->v->avelocity[0] || ent->v->avelocity[2])
Host_Error("SV_ClipMoveToEntity: invalid modelindex\n");
Mod_CheckLoaded(model);
- if (model->type != mod_brush)
+ if (!model->brush.TraceBox)
{
Con_Printf ("SV_ClipMoveToEntity: SOLID_BSP with a non bsp model, entity dump:\n");
ED_Print (ent);