-#define BUILDNUMBER 105
+#define BUILDNUMBER 253
int buildnumber = BUILDNUMBER;
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
// start position 12 units behind head
}
-float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal)
+int traceline_endcontents;
+
+float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal, int contents)
{
- trace_t trace;
+ trace_t trace;
memset (&trace, 0, sizeof(trace));
VectorCopy (end, trace.endpos);
trace.fraction = 1;
- SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace);
- VectorCopy (trace.endpos, impact);
- VectorCopy (trace.plane.normal, normal);
+ trace.startcontents = contents;
+ VectorCopy(start, RecursiveHullCheckInfo.start);
+ VectorSubtract(end, start, RecursiveHullCheckInfo.dist);
+ RecursiveHullCheckInfo.hull = cl.worldmodel->hulls;
+ RecursiveHullCheckInfo.trace = &trace;
+ SV_RecursiveHullCheck (0, 0, 1, start, end);
+ if (impact)
+ VectorCopy (trace.endpos, impact);
+ if (normal)
+ VectorCopy (trace.plane.normal, normal);
+ traceline_endcontents = trace.endcontents;
return trace.fraction;
}
chase_dest[1] = r_refdef.vieworg[1] + forward[1] * dist;
chase_dest[2] = r_refdef.vieworg[2] + forward[2] * dist + chase_up.value;
- TraceLine (r_refdef.vieworg, chase_dest, stop, normal);
+ TraceLine (r_refdef.vieworg, chase_dest, stop, normal, 0);
chase_dest[0] = stop[0] + forward[0] * 8 + normal[0] * 4;
chase_dest[1] = stop[1] + forward[1] * 8 + normal[1] * 4;
chase_dest[2] = stop[2] + forward[2] * 8 + normal[2] * 4;
}
CL_PlayDemo_f ();
-
+
// cls.td_starttime will be grabbed at the second frame of the demo, so
// all the loading time doesn't get counted
-
+
+ // instantly hide console and deactivate it
+ key_dest = key_game;
+ scr_conlines = 0;
+ scr_con_current = 0;
+
cls.timedemo = true;
cls.td_startframe = host_framecount;
cls.td_lastframe = -1; // get a new message this frame
int endframe;
// these are for interpolation
int frame;
- double frame1start;
- double frame2start;
+ double frame1time;
+ double frame2time;
}
effect_t;
-effect_t effect[MAX_EFFECTS];
+static effect_t effect[MAX_EFFECTS];
-cvar_t r_draweffects = {0, "r_draweffects", "1"};
+static cvar_t r_draweffects = {0, "r_draweffects", "1"};
-void r_effects_start(void)
+static void r_effects_start(void)
{
memset(effect, 0, sizeof(effect));
}
-void r_effects_shutdown(void)
+static void r_effects_shutdown(void)
{
}
-void r_effects_newmap(void)
+static void r_effects_newmap(void)
{
memset(effect, 0, sizeof(effect));
}
e->framerate = framerate;
e->frame = 0;
- e->frame1start = cl.time;
- e->frame2start = cl.time;
+ e->frame1time = cl.time;
+ e->frame2time = cl.time;
break;
}
}
+extern void CL_LerpAnimation(entity_t *e);
+
void CL_DoEffects()
{
int i, intframe;
if (intframe != e->frame)
{
e->frame = intframe;
- e->frame1start = e->frame2start;
- e->frame2start = cl.time;
+ e->frame1time = e->frame2time;
+ e->frame2time = cl.time;
}
- vis = CL_NewTempEntity();
- if (!vis)
- continue;
- VectorCopy(e->origin, vis->render.origin);
- vis->render.lerp_model = vis->render.model = cl.model_precache[e->modelindex];
- vis->render.frame1 = e->frame;
- vis->render.frame2 = e->frame + 1;
- if (vis->render.frame2 >= e->endframe)
- vis->render.frame2 = -1; // disappear
- vis->render.frame = vis->render.frame2;
- vis->render.framelerp = frame - vis->render.frame1;
- vis->render.frame1start = e->frame1start;
- vis->render.frame2start = e->frame2start;
- vis->render.lerp_starttime = -1;
- vis->render.colormap = -1; // no special coloring
- vis->render.scale = 1;
- vis->render.alpha = 1;
- vis->render.colormod[0] = vis->render.colormod[1] = vis->render.colormod[2] = 1;
+ if ((vis = CL_NewTempEntity()))
+ {
+ // interpolation stuff
+ vis->render.frame1 = intframe;
+ vis->render.frame2 = intframe + 1;
+ if (vis->render.frame2 >= e->endframe)
+ vis->render.frame2 = -1; // disappear
+ vis->render.framelerp = frame - intframe;
+ vis->render.frame1time = e->frame1time;
+ vis->render.frame2time = e->frame2time;
+
+ // normal stuff
+ VectorCopy(e->origin, vis->render.origin);
+ vis->render.model = cl.model_precache[e->modelindex];
+ vis->render.frame = vis->render.frame2;
+ vis->render.colormap = -1; // no special coloring
+ vis->render.scale = 1;
+ vis->render.alpha = 1;
+ vis->render.colormod[0] = vis->render.colormod[1] = vis->render.colormod[2] = 1;
+ }
}
}
}
--- /dev/null
+#include "quakedef.h"
+
+dlight_t cl_dlights[MAX_DLIGHTS];
+
+void cl_light_start(void)
+{
+}
+
+void cl_light_shutdown(void)
+{
+}
+
+void cl_light_newmap(void)
+{
+ memset (cl_dlights, 0, sizeof(cl_dlights));
+}
+
+void CL_Light_Init(void)
+{
+ R_RegisterModule("CL_Light", cl_light_start, cl_light_shutdown, cl_light_newmap);
+}
+
+/*
+===============
+CL_AllocDlight
+
+===============
+*/
+void CL_AllocDlight (entity_render_t *ent, vec3_t org, float radius, float red, float green, float blue, float decay, float lifetime)
+{
+ int i;
+ dlight_t *dl;
+
+// first look for an exact key match
+ if (ent)
+ {
+ dl = cl_dlights;
+ for (i = 0;i < MAX_DLIGHTS;i++, dl++)
+ if (dl->ent == ent)
+ goto dlightsetup;
+ }
+
+// then look for anything else
+ dl = cl_dlights;
+ for (i = 0;i < MAX_DLIGHTS;i++, dl++)
+ if (!dl->radius)
+ goto dlightsetup;
+
+ // unable to find one
+ return;
+
+dlightsetup:
+ memset (dl, 0, sizeof(*dl));
+ dl->ent = ent;
+ VectorCopy(org, dl->origin);
+ dl->radius = radius;
+ dl->color[0] = red;
+ dl->color[1] = green;
+ dl->color[2] = blue;
+ dl->decay = decay;
+ dl->die = cl.time + lifetime;
+}
+
+
+/*
+===============
+CL_DecayLights
+
+===============
+*/
+void CL_DecayLights (void)
+{
+ int i;
+ dlight_t *dl;
+ float time;
+
+ time = cl.time - cl.oldtime;
+
+ c_dlights = 0;
+ dl = cl_dlights;
+ for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
+ {
+ if (!dl->radius)
+ continue;
+ if (dl->die < cl.time)
+ {
+ dl->radius = 0;
+ continue;
+ }
+
+ c_dlights++; // count every dlight in use
+
+ dl->radius -= time*dl->decay;
+ if (dl->radius < 0)
+ dl->radius = 0;
+ }
+}
+
+
--- /dev/null
+
+// LordHavoc: 256 dynamic lights
+#define MAX_DLIGHTS 256
+typedef struct
+{
+ vec3_t origin;
+ float radius;
+ float die; // stop lighting after this time
+ float decay; // drop this each second
+ entity_render_t *ent; // the entity that spawned this light (can be NULL if it will never be replaced)
+ vec3_t color; // LordHavoc: colored lighting
+} dlight_t;
+
+// LordHavoc: this affects the lighting scale of the whole game
+#define LIGHTOFFSET 4096.0f
+
+extern dlight_t cl_dlights[MAX_DLIGHTS];
+
+extern void CL_AllocDlight (entity_render_t *ent, vec3_t org, float radius, float red, float green, float blue, float decay, float lifetime);
+extern void CL_DecayLights (void);
+
entity_t cl_entities[MAX_EDICTS];
entity_t cl_static_entities[MAX_STATIC_ENTITIES];
lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES];
-dlight_t cl_dlights[MAX_DLIGHTS];
int cl_numvisedicts;
entity_t *cl_visedicts[MAX_VISEDICTS];
SZ_Clear (&cls.message);
-// clear other arrays
+// clear other arrays
memset (cl_entities, 0, sizeof(cl_entities));
- memset (cl_dlights, 0, sizeof(cl_dlights));
memset (cl_lightstyle, 0, sizeof(cl_lightstyle));
memset (cl_temp_entities, 0, sizeof(cl_temp_entities));
memset (cl_beams, 0, sizeof(cl_beams));
}
}
+void CL_LerpUpdate(entity_t *e, int frame, int modelindex)
+{
+ entity_persistent_t *p;
+ entity_render_t *r;
+ p = &e->persistent;
+ r = &e->render;
+
+ if (p->modelindex != modelindex)
+ {
+ // reset all interpolation information
+ p->modelindex = modelindex;
+ p->frame1 = p->frame2 = frame;
+ p->frame1time = p->frame2time = cl.time;
+ p->framelerp = 1;
+ }
+ else if (p->frame2 != frame)
+ {
+ // transition to new frame
+ p->frame1 = p->frame2;
+ p->frame1time = p->frame2time;
+ p->frame2 = frame;
+ p->frame2time = cl.time;
+ p->framelerp = 0;
+ }
+ else
+ {
+ // update transition
+ p->framelerp = (cl.time - p->frame2time) * 10;
+ p->framelerp = bound(0, p->framelerp, 1);
+ }
+
+ r->frame1 = p->frame1;
+ r->frame2 = p->frame2;
+ r->framelerp = p->framelerp;
+ r->frame1time = p->frame1time;
+ r->frame2time = p->frame2time;
+}
+
/*
=====================
CL_Disconnect
MSG_WriteByte (&cls.message, clc_stringcmd);
MSG_WriteString (&cls.message, "prespawn");
break;
-
+
case 2:
MSG_WriteByte (&cls.message, clc_stringcmd);
MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
}
-/*
-===============
-CL_AllocDlight
-
-===============
-*/
-void CL_AllocDlight (entity_t *ent, vec3_t org, float radius, float red, float green, float blue, float decay, float lifetime)
-{
- int i;
- dlight_t *dl;
-
-// first look for an exact key match
- if (ent)
- {
- dl = cl_dlights;
- for (i = 0;i < MAX_DLIGHTS;i++, dl++)
- if (dl->ent == ent)
- goto dlightsetup;
- }
-
-// then look for anything else
- dl = cl_dlights;
- for (i = 0;i < MAX_DLIGHTS;i++, dl++)
- if (!dl->radius)
- goto dlightsetup;
-
- // unable to find one
- return;
-
-dlightsetup:
- memset (dl, 0, sizeof(*dl));
- dl->ent = ent;
- VectorCopy(org, dl->origin);
- dl->radius = radius;
- dl->color[0] = red;
- dl->color[1] = green;
- dl->color[2] = blue;
- dl->decay = decay;
- dl->die = cl.time + lifetime;
-}
-
-
-/*
-===============
-CL_DecayLights
-
-===============
-*/
-void CL_DecayLights (void)
-{
- int i;
- dlight_t *dl;
- float time;
-
- time = cl.time - cl.oldtime;
-
- c_dlights = 0;
- dl = cl_dlights;
- for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
- {
- if (!dl->radius)
- continue;
- if (dl->die < cl.time)
- {
- dl->radius = 0;
- continue;
- }
-
- c_dlights++; // count every dlight in use
-
- dl->radius -= time*dl->decay;
- if (dl->radius < 0)
- dl->radius = 0;
- }
-}
-
-
/*
===============
CL_LerpPoint
void CL_RelinkStaticEntities(void)
{
- entity_t *ent, *endent;
- if (cl.num_statics > MAX_VISEDICTS)
- Host_Error("CL_RelinkStaticEntities: cl.num_statics > MAX_VISEDICTS??\n");
-
- ent = cl_static_entities;
- endent = ent + cl.num_statics;
- for (;ent < endent;ent++)
- cl_visedicts[cl_numvisedicts++] = ent;
+ int i;
+ for (i = 0;i < cl.num_statics && cl_numvisedicts < MAX_VISEDICTS;i++)
+ cl_visedicts[cl_numvisedicts++] = &cl_static_entities[i];
}
/*
===============
*/
void R_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent);
-void CL_RelinkEntities (void)
+void CL_RelinkNetworkEntities()
{
entity_t *ent;
int i, j, glowcolor, effects;
- float frac, f, d, bobjrotate/*, bobjoffset*/, dlightradius, glowsize;
- vec3_t oldorg, delta, dlightcolor;
-
-// determine partial update time
- frac = CL_LerpPoint ();
+ float f, d, bobjrotate/*, bobjoffset*/, dlightradius, glowsize;
+ vec3_t oldorg, neworg, delta, dlightcolor;
- cl_numvisedicts = 0;
+ bobjrotate = ANGLEMOD(100*cl.time);
+// bobjoffset = cos(180 * cl.time * M_PI / 180) * 4.0f + 4.0f;
CL_RelinkStaticEntities();
-//
-// interpolate player info
-//
- for (i = 0;i < 3;i++)
- cl.velocity[i] = cl.mvelocity[1][i] + frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]);
-
- if (cls.demoplayback)
- {
- // interpolate the angles
- for (j = 0;j < 3;j++)
- {
- d = cl.mviewangles[0][j] - cl.mviewangles[1][j];
- if (d > 180)
- d -= 360;
- else if (d < -180)
- d += 360;
- cl.viewangles[j] = cl.mviewangles[1][j] + frac*d;
- }
- }
-
- bobjrotate = ANGLEMOD(100*cl.time);
-// bobjoffset = cos(180 * cl.time * M_PI / 180) * 4.0f + 4.0f;
-
// start on the entity after the world
for (i = 1, ent = cl_entities + 1;i < MAX_EDICTS /*cl.num_entities*/;i++, ent++)
{
if (!ent->state_current.active)
continue;
- VectorCopy (ent->render.origin, oldorg);
+ VectorCopy(ent->persistent.trail_origin, oldorg);
if (!ent->state_previous.active)
{
// only one state available
- VectorCopy (ent->state_current.origin, ent->render.origin);
+ VectorCopy (ent->state_current.origin, neworg);
VectorCopy (ent->state_current.angles, ent->render.angles);
-// Con_Printf(" %i", i);
}
else
{
// if the delta is large, assume a teleport and don't lerp
- f = CL_EntityLerpPoint(ent);
- if (f < 1)
- {
- for (j = 0;j < 3;j++)
- {
- delta[j] = ent->state_current.origin[j] - ent->state_previous.origin[j];
- // LordHavoc: increased lerp tolerance from 100 to 200
- if (delta[j] > 200 || delta[j] < -200)
- f = 1;
- }
- }
+ VectorSubtract(ent->state_current.origin, ent->state_previous.origin, delta);
+ // LordHavoc: increased tolerance from 100 to 200
+ if (DotProduct(delta, delta) > 200*200)
+ f = 1;
+ else
+ f = CL_EntityLerpPoint(ent);
if (f >= 1)
{
// no interpolation
- VectorCopy (ent->state_current.origin, ent->render.origin);
+ VectorCopy (ent->state_current.origin, neworg);
VectorCopy (ent->state_current.angles, ent->render.angles);
}
else
// interpolate the origin and angles
for (j = 0;j < 3;j++)
{
- ent->render.origin[j] = ent->state_previous.origin[j] + f*delta[j];
+ neworg[j] = ent->state_previous.origin[j] + f*delta[j];
d = ent->state_current.angles[j] - ent->state_previous.angles[j];
if (d > 180)
}
}
+ VectorCopy (neworg, ent->persistent.trail_origin);
+ // persistent.modelindex will be updated by CL_LerpUpdate
+ if (ent->state_current.modelindex != ent->persistent.modelindex)
+ VectorCopy(neworg, oldorg);
+
+ VectorCopy (neworg, ent->render.origin);
ent->render.flags = ent->state_current.flags;
ent->render.effects = effects = ent->state_current.effects;
ent->render.model = cl.model_precache[ent->state_current.modelindex];
ent->render.colormod[1] = (float) ((ent->state_current.colormod >> 2) & 7) * (1.0f / 7.0f);
ent->render.colormod[2] = (float) (ent->state_current.colormod & 3) * (1.0f / 3.0f);
+ // update interpolation info
+ CL_LerpUpdate(ent, ent->state_current.frame, ent->state_current.modelindex);
+
+ // handle effects now...
dlightradius = 0;
dlightcolor[0] = 0;
dlightcolor[1] = 0;
R_EntityParticles (ent);
if (effects & EF_MUZZLEFLASH)
{
- vec3_t v;
+ vec3_t v, v2;
AngleVectors (ent->render.angles, v, NULL, NULL);
- v[0] = v[0] * 18 + ent->render.origin[0];
- v[1] = v[1] * 18 + ent->render.origin[1];
- v[2] = v[2] * 18 + ent->render.origin[2] + 16;
+ v2[0] = v[0] * 18 + neworg[0];
+ v2[1] = v[1] * 18 + neworg[1];
+ v2[2] = v[2] * 18 + neworg[2] + 16;
+ TraceLine(neworg, v2, v, NULL, 0);
CL_AllocDlight (NULL, v, 100, 1, 1, 1, 0, 0.1);
}
dlightcolor[1] += 20.0f;
dlightcolor[2] += 200.0f;
}
- else if (effects & EF_FLAME)
+ if (effects & EF_FLAME)
{
if (ent->render.model)
{
vec3_t mins, maxs;
int temp;
- VectorAdd(ent->render.origin, ent->render.model->mins, mins);
- VectorAdd(ent->render.origin, ent->render.model->maxs, maxs);
+ if (ent->render.angles[0] || ent->render.angles[2])
+ {
+ VectorAdd(neworg, ent->render.model->rotatedmins, mins);
+ VectorAdd(neworg, ent->render.model->rotatedmaxs, maxs);
+ }
+ else if (ent->render.angles[1])
+ {
+ VectorAdd(neworg, ent->render.model->yawmins, mins);
+ VectorAdd(neworg, ent->render.model->yawmaxs, maxs);
+ }
+ else
+ {
+ VectorAdd(neworg, ent->render.model->normalmins, mins);
+ VectorAdd(neworg, ent->render.model->normalmaxs, maxs);
+ }
// how many flames to make
temp = (int) (cl.time * 300) - (int) (cl.oldtime * 300);
R_FlameCube(mins, maxs, temp);
if (ent->state_previous.active)
{
if (ent->render.model->flags & EF_GIB)
- R_RocketTrail (oldorg, ent->render.origin, 2, ent);
+ R_RocketTrail (oldorg, neworg, 2, ent);
else if (ent->render.model->flags & EF_ZOMGIB)
- R_RocketTrail (oldorg, ent->render.origin, 4, ent);
+ R_RocketTrail (oldorg, neworg, 4, ent);
else if (ent->render.model->flags & EF_TRACER)
- R_RocketTrail (oldorg, ent->render.origin, 3, ent);
+ R_RocketTrail (oldorg, neworg, 3, ent);
else if (ent->render.model->flags & EF_TRACER2)
- R_RocketTrail (oldorg, ent->render.origin, 5, ent);
+ R_RocketTrail (oldorg, neworg, 5, ent);
else if (ent->render.model->flags & EF_ROCKET)
{
R_RocketTrail (oldorg, ent->render.origin, 0, ent);
else if (ent->render.model->flags & EF_GRENADE)
{
if (ent->render.alpha == -1) // LordHavoc: Nehahra dem compatibility
- R_RocketTrail (oldorg, ent->render.origin, 7, ent);
+ R_RocketTrail (oldorg, neworg, 7, ent);
else
- R_RocketTrail (oldorg, ent->render.origin, 1, ent);
+ R_RocketTrail (oldorg, neworg, 1, ent);
}
else if (ent->render.model->flags & EF_TRACER3)
- R_RocketTrail (oldorg, ent->render.origin, 6, ent);
+ R_RocketTrail (oldorg, neworg, 6, ent);
}
}
// LordHavoc: customizable glow
}
// LordHavoc: customizable trail
if (ent->render.flags & RENDER_GLOWTRAIL)
- R_RocketTrail2 (oldorg, ent->render.origin, glowcolor, ent);
+ R_RocketTrail2 (oldorg, neworg, glowcolor, ent);
if (dlightcolor[0] || dlightcolor[1] || dlightcolor[2])
{
vec3_t vec;
dlightradius = VectorLength(dlightcolor);
d = 1.0f / dlightradius;
- VectorCopy(ent->render.origin, vec);
+ VectorCopy(neworg, vec);
+ // hack to make glowing player light shine on their gun
if (i == cl.viewentity && !chase_active.value)
vec[2] += 30;
- CL_AllocDlight (ent, vec, dlightradius, dlightcolor[0] * d, dlightcolor[1] * d, dlightcolor[2] * d, 0, 0);
+ CL_AllocDlight (&ent->render, vec, dlightradius, dlightcolor[0] * d, dlightcolor[1] * d, dlightcolor[2] * d, 0, 0);
}
if (chase_active.value)
if (cl_numvisedicts < MAX_VISEDICTS)
cl_visedicts[cl_numvisedicts++] = ent;
}
-// Con_Printf("\n");
+}
+
+void CL_LerpPlayerVelocity (void)
+{
+ int i;
+ float frac, d;
+
+ // fraction from previous network update to current
+ frac = CL_LerpPoint ();
+
+ for (i = 0;i < 3;i++)
+ cl.velocity[i] = cl.mvelocity[1][i] + frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]);
+
+ if (cls.demoplayback)
+ {
+ // interpolate the angles
+ for (i = 0;i < 3;i++)
+ {
+ d = cl.mviewangles[0][i] - cl.mviewangles[1][i];
+ if (d > 180)
+ d -= 360;
+ else if (d < -180)
+ d += 360;
+ cl.viewangles[i] = cl.mviewangles[1][i] + frac*d;
+ }
+ }
+}
+
+void CL_RelinkEntities (void)
+{
+ cl_numvisedicts = 0;
+
+ CL_LerpPlayerVelocity();
+ CL_RelinkNetworkEntities();
}
"svc_stufftext", // [string] stuffed into client's console buffer
// the string should be \n terminated
"svc_setangle", // [vec3] set the view angle to this absolute value
-
+
"svc_serverinfo", // [long] version
// [string] signon string
// [string]..[0]model cache [string]...[0]sounds cache
{
// LordHavoc: added demo_nehahra cvar
Cvar_RegisterVariable (&demo_nehahra);
- if (nehahra)
+ if (gamemode == GAME_NEHAHRA)
Cvar_SetValue("demo_nehahra", 1);
}
for (i=0 ; i<3 ; i++)
pos[i] = MSG_ReadCoord ();
-
+
S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
}
SZ_Clear (&cls.message);
}
+//FIXME finish this code!
+#define MAX_STATICLIGHTS 2048
+// tyrlite types
+#define LIGHTFADE_LMINUSX 0 // light, arghlite, others?
+#define LIGHTFADE_LDIVX 1
+#define LIGHTFADE_LDIVX2 2 // hlight
+#define LIGHTFADE_L 3
+#define LIGHTFADE_DEFAULT 999999 // light util not yet identified, switched later
+
+typedef struct
+{
+ int fadetype; // one of the LIGHTFADE_ values
+ int style;
+ vec3_t origin;
+ vec_t radius; // the point at which lighting stops
+ vec3_t direction;
+ vec_t cone; // if non-zero, it is a spot light
+ vec3_t color;
+ vec_t distancescale; // attenuation
+ vec_t lightsubtract; // biasing lighting toward black (hlight feature)
+}
+staticlight_t;
+
+staticlight_t staticlight[MAX_STATICLIGHTS];
+int staticlights;
+
+int r_sunlightenabled;
+vec3_t r_sunlightdirection, r_sunlightcolor;
+vec3_t r_light_ambientcolor;
+
void CL_ParseEntityLump(char *entdata)
{
char *data;
char key[128], value[4096];
char wadname[128];
- int i, j, k;
+ char targetnamebuffer[65536];
+ char *targetname[8192], *target[MAX_STATICLIGHTS], light_target[256];
+ vec3_t targetnameorigin[8192], targetnametemporigin, v;
+ int targets, targetnames, targetnamebufferpos, targetnameorigintofillin;
+ int i, j, k, n;
+ float f1, f2, f3, f4;
+ float ambientlight, ambientcolor[3], sunlight, sunlightdirection[3], sunlightcolor[3];
+ int light_fadetype, light_style, hlight, tyrlite, light_enable;
+ float light_origin[3], light_light, light_distancescale, light_lightcolor[3], light_color[3], light_direction[3], light_cone, light_lightradius;
FOG_clear(); // LordHavoc: no fog until set
R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
r_farclip.value = 6144; // LordHavoc: default farclip distance
+ r_sunlightenabled = false;
+ staticlights = 0;
data = entdata;
if (!data)
return;
data = COM_Parse(data);
if (!data)
- return; // valid exit
+ return; // error
if (com_token[0] != '{')
return; // error
+ hlight = false;
+ tyrlite = false;
+ ambientlight = 0;
+ ambientcolor[0] = ambientcolor[1] = ambientcolor[2] = 1;
+ sunlight = 0;
+ sunlightcolor[0] = sunlightcolor[1] = sunlightcolor[2] = 1;
+ sunlightdirection[0] = 0;
+ sunlightdirection[1] = 0;
+ sunlightdirection[2] = -1;
+ targets = 0;
+ targetnames = 0;
+ targetnamebufferpos = 0;
+ targetnameorigintofillin = -1;
+ targetnametemporigin[0] = 0;
+ targetnametemporigin[1] = 0;
+ targetnametemporigin[2] = 0;
while (1)
{
data = COM_Parse(data);
if (!data)
return; // error
if (com_token[0] == '}')
- return; // since we're just parsing the first ent (worldspawn), exit
- strcpy(key, com_token);
+ break; // end of worldspawn
+ if (com_token[0] == '_')
+ strcpy(key, com_token + 1);
+ else
+ strcpy(key, com_token);
while (key[strlen(key)-1] == ' ') // remove trailing spaces
key[strlen(key)-1] = 0;
data = COM_Parse(data);
r_farclip.value = 64;
}
else if (!strcmp("fog", key))
- {
scanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
- j = 0;
- }
else if (!strcmp("fog_density", key))
fog_density = atof(value);
else if (!strcmp("fog_red", key))
}
}
}
+ else if (!strcmp("light", key))
+ ambientlight = atof(value);
+ else if (!strcmp("sunlight", key))
+ {
+ sunlight = atof(value);
+ tyrlite = true;
+ }
+ else if (!strcmp("sun_color", key))
+ {
+ if (scanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3)
+ VectorCopy(v, sunlightcolor);
+ tyrlite = true;
+ }
+ else if (!strcmp("sun_mangle", key))
+ {
+ if (scanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3)
+ AngleVectors(v, sunlightdirection, NULL, NULL);
+ tyrlite = true;
+ }
+ else if (!strcmp("origin", key))
+ {
+ if (scanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3)
+ {
+ VectorCopy(v, targetnametemporigin);
+ VectorCopy(v, light_origin);
+ }
+ }
+ else if (!strcmp("targetname", key))
+ {
+ if ((targetnames < 8192) && (strlen(value) + 1 + targetnamebufferpos <= 65536))
+ {
+ targetname[targetnames] = targetnamebuffer + targetnamebufferpos;
+ strcpy(targetnamebuffer + targetnamebufferpos, value);
+ targetnamebufferpos += strlen(value) + 1;
+ targetnameorigintofillin = targetnames++;
+ }
+ }
+ }
+ if (targetnameorigintofillin >= 0)
+ VectorCopy(targetnametemporigin, targetnameorigin[targetnameorigintofillin]);
+
+ if (sunlight)
+ {
+ r_sunlightenabled = true;
+ VectorScale(sunlightcolor, sunlight, r_sunlightcolor);
+ VectorCopy(sunlightdirection, r_sunlightdirection);
+ }
+ VectorScale(ambientcolor, ambientlight, r_light_ambientcolor);
+
+ while(1)
+ {
+ data = COM_Parse(data);
+ if (!data)
+ break; // done
+ if (com_token[0] != '{')
+ break; // error
+ light_light = 0;
+ light_lightcolor[0] = light_lightcolor[1] = light_lightcolor[2] = 1.0f;
+ light_color[0] = light_color[1] = light_color[2] = 1.0f;
+ light_direction[0] = light_direction[1] = light_direction[2] = 0.0f;
+ light_cone = -cos(20*M_PI/180);
+ light_distancescale = 1.0f;
+ light_fadetype = LIGHTFADE_DEFAULT; // replaced later when light util is identified
+ light_style = 0;
+ light_lightradius = 0;
+ light_enable = false;
+ targetnameorigintofillin = -1;
+ targetnametemporigin[0] = 0;
+ targetnametemporigin[1] = 0;
+ targetnametemporigin[2] = 0;
+ while (1)
+ {
+ data = COM_Parse(data);
+ if (!data)
+ return; // error
+ if (com_token[0] == '}')
+ break;
+ if (com_token[0] == '_')
+ strcpy(key, com_token + 1);
+ else
+ strcpy(key, com_token);
+ while (key[strlen(key)-1] == ' ') // remove trailing spaces
+ key[strlen(key)-1] = 0;
+ data = COM_Parse(data);
+ if (!data)
+ return; // error
+ strcpy(value, com_token);
+ if (!strcmp("light", key))
+ {
+ n = scanf(value, "%f %f %f %f", &f1, &f2, &f3, &f4);
+ switch(n)
+ {
+ case 1:
+ // id light, arghlite, tyrlite, others
+ light_light = f1;
+ light_lightcolor[0] = light_lightcolor[1] = light_lightcolor[2] = 1.0f;
+ break;
+ case 3:
+ // hlight specific (supports all 3 light formats, but this one is unique to it)
+ hlight = true;
+ light_light = max(f1, max(f2, f3));
+ light_lightcolor[0] = f1 / light_light;
+ light_lightcolor[1] = f2 / light_light;
+ light_lightcolor[2] = f3 / light_light;
+ break;
+ case 4:
+ // halflife
+ hlight = true; // unless this is a halflife map, probably hlight
+ light_light = f4;
+ light_lightcolor[0] = f1 * (1.0f / 255.0f);
+ light_lightcolor[1] = f1 * (1.0f / 255.0f);
+ light_lightcolor[2] = f1 * (1.0f / 255.0f);
+ break;
+ default:
+ // error
+ break;
+ }
+ }
+ else if (!strcmp("color", key))
+ {
+ n = scanf(value, "%f %f %f", &f1, &f2, &f3);
+ if (n == 3)
+ {
+ light_color[0] = f1;
+ light_color[1] = f2;
+ light_color[2] = f3;
+ }
+ // n != 3 is an error
+ }
+ else if (!strcmp("wait", key))
+ light_distancescale = atof(value);
+ else if (!strcmp("delay", key))
+ {
+ light_fadetype = atoi(value);
+ tyrlite = true;
+ }
+ else if (!strcmp("angle", key))
+ light_cone = -cos(atof(value) * M_PI / 360);
+ else if (!strcmp("mangle", key))
+ {
+ n = scanf(value, "%f %f %f", &v[0], &v[1], &v[2]);
+ if (n == 3)
+ AngleVectors(v, light_direction, NULL, NULL);
+ // n != 3 is an error
+ tyrlite = true;
+ }
+ else if (!strcmp("style", key))
+ {
+ n = atoi(value);
+ if (n >= 0 && n < MAX_LIGHTSTYLES)
+ light_style = n;
+ }
+ else if (!strcmp("lightradius", key))
+ {
+ hlight = true;
+ light_lightradius = atof(value);
+ }
+ else if (!strcmp("classname", key))
+ if (!strncmp(value, "light", 5))
+ light_enable = true;
+ else if (!strcmp("origin", key))
+ {
+ if (scanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3)
+ VectorCopy(v, targetnametemporigin);
+ }
+ else if (!strcmp("targetname", key))
+ {
+ if ((targetnames < 8192) && (strlen(value) + 1 + targetnamebufferpos <= 65536))
+ {
+ targetname[targetnames] = targetnamebuffer + targetnamebufferpos;
+ strcpy(targetnamebuffer + targetnamebufferpos, value);
+ targetnamebufferpos += strlen(value) + 1;
+ targetnameorigintofillin = targetnames++;
+ }
+ }
+ else if (!strcmp("target", key))
+ if (strlen(value) < sizeof(light_target))
+ strcpy(light_target, value);
+ }
+ if (targetnameorigintofillin >= 0)
+ VectorCopy(targetnametemporigin, targetnameorigin[targetnameorigintofillin]);
+ if (light_enable && staticlights < MAX_STATICLIGHTS && light_light != 0)
+ {
+ VectorCopy(light_origin, staticlight[staticlights].origin);
+ staticlight[staticlights].color[0] = light_light * light_lightcolor[0] * light_color[0];
+ staticlight[staticlights].color[1] = light_light * light_lightcolor[1] * light_color[1];
+ staticlight[staticlights].color[2] = light_light * light_lightcolor[2] * light_color[2];
+ VectorCopy(light_direction, staticlight[staticlights].direction);
+ staticlight[staticlights].cone = light_cone;
+ staticlight[staticlights].distancescale = light_distancescale;
+ staticlight[staticlights].fadetype = light_fadetype;
+ staticlight[staticlights].style = light_style;
+ if (light_target && (targets < 8192) && (strlen(value) + 1 + targetnamebufferpos <= 65536))
+ {
+ target[staticlights] = targetnamebuffer + targetnamebufferpos;
+ strcpy(targetnamebuffer + targetnamebufferpos, value);
+ targetnamebufferpos += strlen(value) + 1;
+ }
+ else
+ target[staticlights] = NULL;
+ staticlight[staticlights].lightsubtract = 0;
+ if (light_lightradius)
+ {
+ staticlight[staticlights].fadetype = LIGHTFADE_LDIVX2;
+ staticlight[staticlights].lightsubtract = max(staticlight[staticlights].color[0], max(staticlight[staticlights].color[1], staticlight[staticlights].color[2])) * 0.5f / (light_lightradius * light_distancescale * light_lightradius * light_distancescale * (1.0f / 65536.0f) + 1.0f);
+ }
+ staticlights++;
+ }
+ }
+ if (hlbsp)
+ n = LIGHTFADE_LDIVX2;
+ else if (tyrlite)
+ n = LIGHTFADE_LMINUSX;
+ else if (hlight)
+ n = LIGHTFADE_LDIVX2;
+ else
+ n = LIGHTFADE_LMINUSX;
+ for (i = 0;i < staticlights;i++)
+ {
+ if (staticlight[i].fadetype == LIGHTFADE_DEFAULT)
+ staticlight[i].fadetype = n;
+ if (target[i])
+ {
+ for (j = 0;j < targetnames;j++)
+ {
+ if (!strcmp(target[i], targetname[j]))
+ {
+ VectorSubtract(targetnameorigin[j], staticlight[i].origin, v);
+ VectorNormalize(v);
+ VectorCopy(v, staticlight[i].direction);
+ break;
+ }
+ }
+ }
+ if (staticlight[i].direction[0] == 0 && staticlight[i].direction[1] == 0 && staticlight[i].direction[2] == 0)
+ staticlight[i].cone = 0;
}
}
int nummodels, numsounds;
char model_precache[MAX_MODELS][MAX_QPATH];
char sound_precache[MAX_SOUNDS][MAX_QPATH];
-
+
Con_DPrintf ("Serverinfo packet received.\n");
//
// wipe the client_state_t struct
Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
s->frame = 0;
}
+ if (model && s->skin >= model->numskins)
+ {
+ Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
+ s->skin = 0;
+ }
}
/*
i = MSG_ReadByte ();
- if (standard_quake)
- cl.stats[STAT_ACTIVEWEAPON] = i;
- else
+ if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
+ else
+ cl.stats[STAT_ACTIVEWEAPON] = i;
}
/*
void CL_ParseStatic (int large)
{
entity_t *ent;
-
+
if (cl.num_statics >= MAX_STATIC_ENTITIES)
Host_Error ("Too many static entities");
ent = &cl_static_entities[cl.num_statics++];
ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
ent->render.framelerp = 0;
- ent->render.lerp_starttime = -1;
// make torchs play out of sync
- ent->render.frame1start = ent->render.frame2start = -(rand() & 32767);
+ ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
ent->render.colormap = -1; // no special coloring
ent->render.skinnum = ent->state_baseline.skin;
ent->render.effects = ent->state_baseline.effects;
case svc_serverinfo:
CL_ParseServerInfo ();
- vid.recalc_refdef = true; // leave intermission full screen
+// vid.recalc_refdef = true; // leave intermission full screen
break;
case svc_setangle:
case svc_intermission:
cl.intermission = 1;
cl.completed_time = cl.time;
- vid.recalc_refdef = true; // go to full screen
+// vid.recalc_refdef = true; // go to full screen
break;
case svc_finale:
cl.intermission = 2;
cl.completed_time = cl.time;
- vid.recalc_refdef = true; // go to full screen
+// vid.recalc_refdef = true; // go to full screen
SCR_CenterPrint (MSG_ReadString ());
break;
case svc_cutscene:
cl.intermission = 3;
cl.completed_time = cl.time;
- vid.recalc_refdef = true; // go to full screen
+// vid.recalc_refdef = true; // go to full screen
SCR_CenterPrint (MSG_ReadString ());
break;
ent->render.angles[2] = rand()%360;
if (r_glowinglightning.value > 0)
- CL_AllocDlight(ent, ent->render.origin, lhrandom(100, 120), r_glowinglightning.value * 0.25f, r_glowinglightning.value * 0.25f, r_glowinglightning.value * 0.25f, 0, 0);
+ CL_AllocDlight(&ent->render, ent->render.origin, lhrandom(100, 120), r_glowinglightning.value * 0.25f, r_glowinglightning.value * 0.25f, r_glowinglightning.value * 0.25f, 0, 0);
VectorMA(org, 30, dist, org);
d -= 30;
extern entity_t cl_entities[MAX_EDICTS];
extern entity_t cl_static_entities[MAX_STATIC_ENTITIES];
extern lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES];
-extern dlight_t cl_dlights[MAX_DLIGHTS];
extern entity_t cl_temp_entities[MAX_TEMP_ENTITIES];
extern beam_t cl_beams[MAX_BEAMS];
//=============================================================================
+#include "cl_light.h"
+
//
// cl_main
//
-extern void CL_AllocDlight (entity_t *ent, vec3_t org, float radius, float red, float green, float blue, float decay, float lifetime);
-extern void CL_DecayLights (void);
extern void CL_Init (void);
#define CMDLINE_LENGTH 1024
char com_cmdline[CMDLINE_LENGTH];
-qboolean standard_quake = true, rogue = false, hipnotic = false, nehahra = false;
+int gamemode;
+char *gamename;
/*
largv[com_argc] = argvdummy;
com_argv = largv;
-#ifdef NEHAHRA
- nehahra = true;
- standard_quake = false;
+#if ZYMOTIC
+ gamemode = GAME_ZYMOTIC;
+#elif FIENDARENA
+ gamemode = GAME_FIENDARENA;
+#elif NEHAHRA
+ gamemode = GAME_NEHAHRA;
#else
- if (COM_CheckParm ("-rogue"))
- {
- rogue = true;
- standard_quake = false;
- }
-
- if (COM_CheckParm ("-hipnotic"))
- {
- hipnotic = true;
- standard_quake = false;
- }
-
- if (COM_CheckParm ("-nehahra"))
+ if (COM_CheckParm ("-zymotic"))
+ gamemode = GAME_ZYMOTIC;
+ else if (COM_CheckParm ("-fiendarena"))
+ gamemode = GAME_FIENDARENA;
+ else if (COM_CheckParm ("-nehahra"))
+ gamemode = GAME_NEHAHRA;
+ else if (COM_CheckParm ("-hipnotic"))
+ gamemode = GAME_HIPNOTIC;
+ else if (COM_CheckParm ("-rogue"))
+ gamemode = GAME_ROGUE;
+#endif
+ switch(gamemode)
{
- nehahra = true;
- standard_quake = false;
+ case GAME_NORMAL:
+ gamename = "DarkPlaces";
+ break;
+ case GAME_HIPNOTIC:
+ gamename = "Darkplaces-Hipnotic";
+ break;
+ case GAME_ROGUE:
+ gamename = "Darkplaces-Rogue";
+ break;
+ case GAME_NEHAHRA:
+ gamename = "DarkPlaces-Nehahra";
+ break;
+ case GAME_FIENDARENA:
+ gamename = "FiendArena";
+ break;
+ case GAME_ZYMOTIC:
+ gamename = "Zymotic";
+ break;
+ default:
+ Sys_Error("COM_InitArgv: unknown gamemode %i\n", gamemode);
+ break;
}
-#endif
}
{
int handle;
char name[MAX_OSPATH];
-
+
sprintf (name, "%s/%s", com_gamedir, filename);
// LordHavoc: added this
Sys_Printf ("COM_WriteFile: failed on %s\n", name);
return;
}
-
- Sys_Printf ("COM_WriteFile: %s\n", name);
+
+ Con_Printf ("COM_WriteFile: %s\n", name);
Sys_FileWrite (handle, data, len);
Sys_FileClose (handle);
}
com_cachedir[0] = 0;
#endif
-//
// start up with GAMENAME by default (id1)
-//
COM_AddGameDirectory (va("%s/"GAMENAME, basedir) );
-#ifdef NEHAHRA
- COM_AddGameDirectory (va("%s/nehahra", basedir) );
-#else
- if (COM_CheckParm ("-rogue"))
- COM_AddGameDirectory (va("%s/rogue", basedir) );
- if (COM_CheckParm ("-hipnotic"))
+ switch(gamemode)
+ {
+ case GAME_NORMAL:
+ break;
+ case GAME_HIPNOTIC:
COM_AddGameDirectory (va("%s/hipnotic", basedir) );
- if (COM_CheckParm ("-nehahra"))
+ break;
+ case GAME_ROGUE:
+ COM_AddGameDirectory (va("%s/rogue", basedir) );
+ break;
+ case GAME_NEHAHRA:
COM_AddGameDirectory (va("%s/nehahra", basedir) );
-#endif
+ break;
+ case GAME_FIENDARENA:
+ COM_AddGameDirectory (va("%s/fiendarena", basedir) );
+ break;
+ case GAME_ZYMOTIC:
+ COM_AddGameDirectory (va("%s/zymotic", basedir) );
+ break;
+ default:
+ Sys_Error("COM_InitFilesystem: unknown gamemode %i\n", gamemode);
+ break;
+ }
//
// -game <gamedir>
{
if (!com_argv[i] || com_argv[i][0] == '+' || com_argv[i][0] == '-')
break;
-
+
search = Hunk_AllocName (sizeof(searchpath_t), "pack info");
if ( !strcmp(COM_FileExtension(com_argv[i]), "pak") )
{
}
else
{
- sprintf (netpath, "%s/%s",search->filename, filename);
+ sprintf (netpath, "%s/%s",search->filename, filename);
findtime = Sys_FileTime (netpath);
if (findtime != -1)
return true;
extern struct cvar_s registered;
-extern qboolean standard_quake, rogue, hipnotic, nehahra;
+#define GAME_NORMAL 0
+#define GAME_HIPNOTIC 1
+#define GAME_ROGUE 2
+#define GAME_NEHAHRA 3
+#define GAME_FIENDARENA 4
+#define GAME_ZYMOTIC 5
+
+extern int gamemode;
+extern char *gamename;
// LordHavoc: useful...
extern void COM_ToLowerString(char *in, char *out);
int i, j, width, oldwidth, oldtotallines, numlines, numchars;
char tbuf[CON_TEXTSIZE];
- width = (vid.width >> 3) - 2;
+ width = (vid.conwidth >> 3) - 2;
if (width == con_linewidth)
return;
void Draw_ConsoleBackground (int lines);
void Draw_Fill (int x, int y, int w, int h, int c);
void Draw_String (int x, int y, char *str, int maxlen); // LordHavoc: added maxlen
+void Draw_AdditiveString (int x, int y, char *str, int maxlen);
qpic_t *Draw_PicFromWad (char *name);
qpic_t *Draw_CachePic (char *path);
{
}
-char engineversion[40];
+extern char engineversion[40];
int engineversionx, engineversiony;
extern void R_Textures_Init();
int i;
Cvar_RegisterVariable (&scr_conalpha);
-#if defined(__linux__)
- sprintf (engineversion, "DarkPlaces Linux GL %.2f build %3i", (float) VERSION, buildnumber);
-#elif defined(WIN32)
- sprintf (engineversion, "DarkPlaces Windows GL %.2f build %3i", (float) VERSION, buildnumber);
-#else
- sprintf (engineversion, "DarkPlaces Unknown GL %.2f build %3i", (float) VERSION, buildnumber);
-#endif
for (i = 0;i < 40 && engineversion[i];i++)
engineversion[i] += 0x80; // shift to orange
- engineversionx = vid.width - strlen(engineversion) * 8 - 8;
- engineversiony = vid.height - 8;
+ engineversionx = vid.conwidth - strlen(engineversion) * 8 - 8;
+ engineversiony = vid.conheight - 8;
R_Textures_Init();
R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap);
return;
glBindTexture(GL_TEXTURE_2D, R_GetTexture(char_texture));
// LordHavoc: NEAREST mode on text if not scaling up
- if (glwidth <= (int) vid.width)
+ if (vid.realwidth <= (int) vid.conwidth)
{
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glEnd ();
// LordHavoc: revert to LINEAR mode
-// if (glwidth < (int) vid.width)
+// if (vid.realwidth <= (int) vid.conwidth)
// {
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
float frow, fcol;
if (!r_render.value)
return;
- if (y <= -8 || y >= (int) vid.height || x >= (int) vid.width || *str == 0) // completely offscreen or no text to print
+ if (y <= -8 || y >= (int) vid.conheight || x >= (int) vid.conwidth || *str == 0) // completely offscreen or no text to print
return;
if (maxlen < 1)
maxlen = strlen(str);
glBindTexture(GL_TEXTURE_2D, R_GetTexture(char_texture));
// LordHavoc: NEAREST mode on text if not scaling up
- if (glwidth <= (int) vid.width)
+ if (vid.realwidth <= (int) vid.conwidth)
{
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else
glColor3f(1.0f,1.0f,1.0f);
glBegin (GL_QUADS);
- while (maxlen-- && x < (int) vid.width) // stop rendering when out of characters or room
+ while (maxlen-- && x < (int) vid.conwidth) // stop rendering when out of characters or room
{
if ((num = *str++) != 32) // skip spaces
{
glEnd ();
// LordHavoc: revert to LINEAR mode
-// if (glwidth < (int) vid.width)
+// if (vid.realwidth < (int) vid.conwidth)
// {
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// }
}
+void Draw_AdditiveString (int x, int y, char *str, int maxlen)
+{
+ if (!r_render.value)
+ return;
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ Draw_String(x, y, str, maxlen);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+}
+
void Draw_GenericPic (rtexture_t *tex, float red, float green, float blue, float alpha, int x, int y, int width, int height)
{
if (!r_render.value)
*/
void Draw_ConsoleBackground (int lines)
{
- Draw_GenericPic (conbacktex, 1,1,1,scr_conalpha.value*lines/vid.height, 0, lines - vid.height, vid.width, vid.height);
+ Draw_GenericPic (conbacktex, 1,1,1,scr_conalpha.value * lines / vid.conheight, 0, lines - vid.conheight, vid.conwidth, vid.conheight);
// LordHavoc: draw version
- Draw_String(engineversionx, lines - vid.height + engineversiony, engineversion, 9999);
+ Draw_String(engineversionx, lines - vid.conheight + engineversiony, engineversion, 9999);
}
/*
{
if (!r_render.value)
return;
- glViewport (glx, gly, glwidth, glheight);
+ glViewport (vid.realx, vid.realy, vid.realwidth, vid.realheight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity ();
- glOrtho (0, vid.width, vid.height, 0, -99999, 99999);
+ glOrtho (0, vid.conwidth, vid.conheight, 0, -99999, 99999);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity ();
float x, y;
strcpy(lmplabel,MSG_ReadString());
strcpy(picname, MSG_ReadString());
- if (nehahra) // LordHavoc: nasty old legacy junk
+ if (gamemode == GAME_NEHAHRA) // LordHavoc: nasty old legacy junk
{
x = MSG_ReadByte();
y = MSG_ReadByte();
}
}
-void GL_DrawModelMesh(rtexture_t *skin, byte *colors, maliashdr_t *maliashdr)
+void GL_DrawModelMesh(rtexture_t *skin, byte *colors, maliashdr_t *m)
{
if (!r_render.value)
return;
glEnableClientState(GL_COLOR_ARRAY);
}
- glDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata));
+ glDrawElements(GL_TRIANGLES, m->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) m + m->tridata));
if (colors)
glDisableClientState(GL_COLOR_ARRAY);
=================
*/
-void R_LightModel(entity_t *ent, int numverts, vec3_t center, vec3_t basecolor);
-void R_DrawAliasFrame (model_t *model, maliashdr_t *maliashdr, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, vec_t scale, frameblend_t *blend, rtexture_t **skin, int colormap, int effects, int flags)
+void R_DrawAliasFrame (void)
{
+ maliashdr_t *m = Mod_Extradata(currentrenderentity->model);
+// int *skinanimrange = (int *) (currentrenderentity->model->skinanimrange + (int) modelheader) + skin * 2;
+// int *skinanim = (int *) (currentrenderentity->model->skinanim + (int) modelheader);
+ int *skinanimrange = currentrenderentity->model->skinanimrange;
+ int skin;
+ rtexture_t **skinanim = currentrenderentity->model->skinanim;
+ rtexture_t **skinset;
+
+ skinanimrange += currentrenderentity->skinnum * 2;
+ skin = skinanimrange[0];
+ if (skinanimrange[1] > 1) // animated
+ skin += (int) (cl.time * 10) % skinanimrange[1];
+ skinset = skinanim + skin * 5;
+
if (gl_transform.value)
{
if (r_render.value)
{
glPushMatrix();
- GL_SetupModelTransform(org, angles, scale);
+ GL_SetupModelTransform(currentrenderentity->origin, currentrenderentity->angles, currentrenderentity->scale);
}
}
// always needed, for model lighting
- softwaretransformforentity(ent);
+ softwaretransformforentity(currentrenderentity);
+
+ R_AliasLerpVerts(m->numverts,
+ currentrenderentity->frameblend[0].lerp, ((trivertx_t *)((int) m + m->posedata)) + currentrenderentity->frameblend[0].frame * m->numverts, m->scale, m->scale_origin,
+ currentrenderentity->frameblend[1].lerp, ((trivertx_t *)((int) m + m->posedata)) + currentrenderentity->frameblend[1].frame * m->numverts, m->scale, m->scale_origin,
+ currentrenderentity->frameblend[2].lerp, ((trivertx_t *)((int) m + m->posedata)) + currentrenderentity->frameblend[2].frame * m->numverts, m->scale, m->scale_origin,
+ currentrenderentity->frameblend[3].lerp, ((trivertx_t *)((int) m + m->posedata)) + currentrenderentity->frameblend[3].frame * m->numverts, m->scale, m->scale_origin);
- R_AliasLerpVerts(maliashdr->numverts,
- blend[0].lerp, ((trivertx_t *)((int) maliashdr + maliashdr->posedata)) + blend[0].frame * maliashdr->numverts, maliashdr->scale, maliashdr->scale_origin,
- blend[1].lerp, ((trivertx_t *)((int) maliashdr + maliashdr->posedata)) + blend[1].frame * maliashdr->numverts, maliashdr->scale, maliashdr->scale_origin,
- blend[2].lerp, ((trivertx_t *)((int) maliashdr + maliashdr->posedata)) + blend[2].frame * maliashdr->numverts, maliashdr->scale, maliashdr->scale_origin,
- blend[3].lerp, ((trivertx_t *)((int) maliashdr + maliashdr->posedata)) + blend[3].frame * maliashdr->numverts, maliashdr->scale, maliashdr->scale_origin);
if (!gl_transform.value)
- R_AliasTransformVerts(maliashdr->numverts);
+ R_AliasTransformVerts(m->numverts);
// prep the vertex array as early as possible
if (r_render.value)
{
glVertexPointer(3, GL_FLOAT, sizeof(float[3]), aliasvert);
glEnableClientState(GL_VERTEX_ARRAY);
- glTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), (void *)((int) maliashdr->texdata + (int) maliashdr));
+ glTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), (void *)((int) m->texdata + (int) m));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- GL_LockArray(0, maliashdr->numverts);
+ GL_LockArray(0, m->numverts);
}
- R_LightModel(ent, maliashdr->numverts, org, color);
+ R_LightModel(m->numverts);
if (!r_render.value)
return;
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glShadeModel(GL_SMOOTH);
- if (effects & EF_ADDITIVE)
+// glShadeModel(GL_SMOOTH);
+ if (currentrenderentity->effects & EF_ADDITIVE)
{
glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering
glEnable(GL_BLEND);
glDepthMask(0);
}
- else if (alpha != 1.0 || (model->flags2 & MODF_TRANSPARENT))
+ else if (currentrenderentity->alpha != 1.0 || (currentrenderentity->model->flags2 & MODF_TRANSPARENT))
{
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glDepthMask(1);
}
- if (skin[0] || skin[1] || skin[2] || skin[3] || skin[4])
+ if (skinset[0] || skinset[1] || skinset[2] || skinset[3] || skinset[4])
{
- if (colormap >= 0 && (skin[0] || skin[1] || skin[2]))
+ if (currentrenderentity->colormap >= 0 && (skinset[0] || skinset[1] || skinset[2]))
{
int c;
- if (skin[0])
- GL_DrawModelMesh(skin[0], aliasvertcolor, maliashdr);
- if (skin[1])
+ if (skinset[0])
+ GL_DrawModelMesh(skinset[0], aliasvertcolor, m);
+ if (skinset[1])
{
- c = (colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
- R_TintModel(aliasvertcolor, aliasvertcolor2, maliashdr->numverts, (byte *) (&d_8to24table[c]));
- GL_DrawModelMesh(skin[1], aliasvertcolor2, maliashdr);
+ c = (currentrenderentity->colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
+ R_TintModel(aliasvertcolor, aliasvertcolor2, m->numverts, (byte *) (&d_8to24table[c]));
+ GL_DrawModelMesh(skinset[1], aliasvertcolor2, m);
}
- if (skin[2])
+ if (skinset[2])
{
- c = colormap & 0xF0 ;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
- R_TintModel(aliasvertcolor, aliasvertcolor2, maliashdr->numverts, (byte *) (&d_8to24table[c]));
- GL_DrawModelMesh(skin[2], aliasvertcolor2, maliashdr);
+ c = currentrenderentity->colormap & 0xF0 ;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
+ R_TintModel(aliasvertcolor, aliasvertcolor2, m->numverts, (byte *) (&d_8to24table[c]));
+ GL_DrawModelMesh(skinset[2], aliasvertcolor2, m);
}
}
else
{
- if (skin[4]) GL_DrawModelMesh(skin[4], aliasvertcolor, maliashdr);
+ if (skinset[4])
+ GL_DrawModelMesh(skinset[4], aliasvertcolor, m);
else
{
- if (skin[0]) GL_DrawModelMesh(skin[0], aliasvertcolor, maliashdr);
- if (skin[1]) GL_DrawModelMesh(skin[1], aliasvertcolor, maliashdr);
- if (skin[2]) GL_DrawModelMesh(skin[2], aliasvertcolor, maliashdr);
+ if (skinset[0]) GL_DrawModelMesh(skinset[0], aliasvertcolor, m);
+ if (skinset[1]) GL_DrawModelMesh(skinset[1], aliasvertcolor, m);
+ if (skinset[2]) GL_DrawModelMesh(skinset[2], aliasvertcolor, m);
}
}
- if (skin[3]) GL_DrawModelMesh(skin[3], NULL, maliashdr);
+ if (skinset[3]) GL_DrawModelMesh(skinset[3], NULL, m);
}
else
- GL_DrawModelMesh(0, NULL, maliashdr);
+ GL_DrawModelMesh(0, NULL, m);
if (fogenabled)
{
glEnable (GL_BLEND);
glDepthMask(0); // disable zbuffer updates
- VectorSubtract(org, r_origin, diff);
+ VectorSubtract(currentrenderentity->origin, r_origin, diff);
glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
- glDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata));
+ glDrawElements(GL_TRIANGLES, m->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) m + m->tridata));
glEnable (GL_TEXTURE_2D);
glColor3f (1,1,1);
}
+
GL_UnlockArray();
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
=================
*/
-void R_DrawQ2AliasFrame (model_t *model, md2mem_t *pheader, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, vec_t scale, frameblend_t *blend, rtexture_t *skin, int effects, int flags)
+void R_DrawQ2AliasFrame (void)
{
int *order, count;
md2frame_t *frame1, *frame2, *frame3, *frame4;
+ vec3_t diff;
+ md2mem_t *m = Mod_Extradata(currentrenderentity->model);
+// int *skinanimrange = (int *) (currentrenderentity->model->skinanimrange + (int) modelheader) + skin * 2;
+// int *skinanim = (int *) (currentrenderentity->model->skinanim + (int) modelheader);
+ int *skinanimrange = currentrenderentity->model->skinanimrange;
+ int skin;
+ rtexture_t **skinanim = currentrenderentity->model->skinanim;
+ rtexture_t **skinset;
+
+ skinanimrange += currentrenderentity->skinnum * 2;
+ skin = skinanimrange[0];
+ if (skinanimrange[1] > 1) // animated
+ skin += (int) (cl.time * 10) % skinanimrange[1];
+ skinset = skinanim + skin * 5;
if (r_render.value)
- glBindTexture(GL_TEXTURE_2D, R_GetTexture(skin));
+ glBindTexture(GL_TEXTURE_2D, R_GetTexture(skinset[0]));
if (gl_transform.value)
{
if (r_render.value)
{
glPushMatrix();
- GL_SetupModelTransform(org, angles, scale);
+ GL_SetupModelTransform(currentrenderentity->origin, currentrenderentity->angles, currentrenderentity->scale);
}
}
// always needed, for model lighting
- softwaretransformforentity(ent);
-
- frame1 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * blend[0].frame));
- frame2 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * blend[1].frame));
- frame3 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * blend[2].frame));
- frame4 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * blend[3].frame));
- R_AliasLerpVerts(pheader->num_xyz,
- blend[0].lerp, frame1->verts, frame1->scale, frame1->translate,
- blend[1].lerp, frame2->verts, frame2->scale, frame2->translate,
- blend[2].lerp, frame3->verts, frame3->scale, frame3->translate,
- blend[3].lerp, frame4->verts, frame4->scale, frame4->translate);
+ softwaretransformforentity(currentrenderentity);
+
+ frame1 = (void *)((int) m + m->ofs_frames + (m->framesize * currentrenderentity->frameblend[0].frame));
+ frame2 = (void *)((int) m + m->ofs_frames + (m->framesize * currentrenderentity->frameblend[1].frame));
+ frame3 = (void *)((int) m + m->ofs_frames + (m->framesize * currentrenderentity->frameblend[2].frame));
+ frame4 = (void *)((int) m + m->ofs_frames + (m->framesize * currentrenderentity->frameblend[3].frame));
+ R_AliasLerpVerts(m->num_xyz,
+ currentrenderentity->frameblend[0].lerp, frame1->verts, frame1->scale, frame1->translate,
+ currentrenderentity->frameblend[1].lerp, frame2->verts, frame2->scale, frame2->translate,
+ currentrenderentity->frameblend[2].lerp, frame3->verts, frame3->scale, frame3->translate,
+ currentrenderentity->frameblend[3].lerp, frame4->verts, frame4->scale, frame4->translate);
if (!gl_transform.value)
- R_AliasTransformVerts(pheader->num_xyz);
+ R_AliasTransformVerts(m->num_xyz);
- R_LightModel(ent, pheader->num_xyz, org, color);
+ R_LightModel(m->num_xyz);
if (!r_render.value)
return;
+
+ if (currentrenderentity->effects & EF_ADDITIVE)
+ {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering
+ glEnable(GL_BLEND);
+ glDepthMask(0);
+ }
+ else if (currentrenderentity->alpha != 1.0 || (currentrenderentity->model->flags2 & MODF_TRANSPARENT))
+ {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glDepthMask(0);
+ }
+ else
+ {
+ glDisable(GL_BLEND);
+ glDepthMask(1);
+ }
+
// LordHavoc: big mess...
// using vertex arrays only slightly, although it is enough to prevent duplicates
// (saving half the transforms)
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
- order = (int *)((int)pheader + pheader->ofs_glcmds);
+ order = (int *)((int)m + m->ofs_glcmds);
while(1)
{
if (!(count = *order++))
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable (GL_BLEND);
glDepthMask(0); // disable zbuffer updates
- {
- vec3_t diff;
- VectorSubtract(org, r_origin, diff);
- glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
- }
+
+ VectorSubtract(currentrenderentity->origin, r_origin, diff);
+ glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
// LordHavoc: big mess...
// using vertex arrays only slightly, although it is enough to prevent duplicates
glVertexPointer(3, GL_FLOAT, sizeof(float[3]), aliasvert);
glEnableClientState(GL_VERTEX_ARRAY);
- order = (int *)((int)pheader + pheader->ofs_glcmds);
+ order = (int *)((int)m + m->ofs_glcmds);
while(1)
{
if (!(count = *order++))
R_DrawZymoticFrame
=================
*/
-void R_DrawZymoticFrame (model_t *model, zymtype1header_t *m, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, vec_t scale, frameblend_t *blend, int skinblah, int effects, int flags)
+void R_DrawZymoticFrame (void)
{
- ZymoticLerpBones(m->numbones, (zymbonematrix *)(m->lump_poses.start + (int) m), blend, (zymbone_t *)(m->lump_bones.start + (int) m), org, angles, scale);
+ zymtype1header_t *m = Mod_Extradata(currentrenderentity->model);
+ ZymoticLerpBones(m->numbones, (zymbonematrix *)(m->lump_poses.start + (int) m), currentrenderentity->frameblend, (zymbone_t *)(m->lump_bones.start + (int) m), currentrenderentity->origin, currentrenderentity->angles, currentrenderentity->scale);
ZymoticTransformVerts(m->numverts, (int *)(m->lump_vertbonecounts.start + (int) m), (zymvertex_t *)(m->lump_verts.start + (int) m));
ZymoticCalcNormals(m->numverts, m->numshaders, (int *)(m->lump_render.start + (int) m));
- R_LightModel(ent, m->numverts, org, color);
+ R_LightModel(m->numverts);
if (!r_render.value)
return;
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glShadeModel(GL_SMOOTH);
- if (effects & EF_ADDITIVE)
+// glShadeModel(GL_SMOOTH);
+ if (currentrenderentity->effects & EF_ADDITIVE)
{
glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering
glEnable(GL_BLEND);
glDepthMask(0);
}
- else if (alpha != 1.0)
+ else if (currentrenderentity->alpha != 1.0)
{
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
GL_DrawZymoticModelMesh(aliasvertcolor, m);
if (fogenabled)
- GL_DrawZymoticModelMeshFog(org, m);
+ GL_DrawZymoticModelMeshFog(currentrenderentity->origin, m);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable (GL_BLEND);
=================
*/
-void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, frameblend_t *blend, int skin, vec3_t org, vec3_t angles, vec_t scale, int effects, int flags, int colormap)
+void R_DrawAliasModel (void)
{
- int i;
- vec3_t mins, maxs, color;
- void *modelheader;
- rtexture_t **skinset;
-
- if (alpha < (1.0 / 64.0))
+ if (currentrenderentity->alpha < (1.0 / 64.0))
return; // basically completely transparent
- VectorAdd (org, clmodel->mins, mins);
- VectorAdd (org, clmodel->maxs, maxs);
-
-// if (cull && R_CullBox (mins, maxs))
-// return;
-
c_models++;
- if (skin < 0 || skin >= clmodel->numskins)
- {
- skin = 0;
- Con_DPrintf("invalid skin number %d for model %s\n", skin, clmodel->name);
- }
-
- modelheader = Mod_Extradata (clmodel);
-
- {
-// int *skinanimrange = (int *) (clmodel->skinanimrange + (int) modelheader) + skin * 2;
-// int *skinanim = (int *) (clmodel->skinanim + (int) modelheader);
- int *skinanimrange = clmodel->skinanimrange + skin * 2;
- rtexture_t **skinanim = clmodel->skinanim;
- i = skinanimrange[0];
- if (skinanimrange[1] > 1) // animated
- i += ((int) (cl.time * 10) % skinanimrange[1]);
- skinset = skinanim + i*5;
- }
-
if (r_render.value)
glEnable (GL_TEXTURE_2D);
- c_alias_polys += clmodel->numtris;
- if (clmodel->aliastype == ALIASTYPE_ZYM)
- R_DrawZymoticFrame (clmodel, modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, scale, blend, 0 , effects, flags);
- else if (clmodel->aliastype == ALIASTYPE_MD2)
- R_DrawQ2AliasFrame (clmodel, modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, scale, blend, skinset[0] , effects, flags);
+ c_alias_polys += currentrenderentity->model->numtris;
+ if (currentrenderentity->model->aliastype == ALIASTYPE_ZYM)
+ R_DrawZymoticFrame ();
+ else if (currentrenderentity->model->aliastype == ALIASTYPE_MD2)
+ R_DrawQ2AliasFrame ();
else
- R_DrawAliasFrame (clmodel, modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, scale, blend, skinset , colormap, effects, flags);
+ R_DrawAliasFrame ();
}
#include "quakedef.h"
+typedef struct
+{
+ unsigned short tex;
+ unsigned short type;
+ int indices;
+}
+rendertranspoly_t;
+
transvert_t *transvert;
transpoly_t *transpoly;
-unsigned short *transpolyindex;
+rendertranspoly_t *rendertranspoly;
+int *transpolyindex;
+int *transvertindex;
wallvert_t *wallvert;
wallvertcolor_t *wallvertcolor;
wallpoly_t *wallpoly;
int currentskypoly;
int currentskyvert;
+
void LoadSky_f(void);
cvar_t r_multitexture = {0, "r_multitexture", "1"};
cvar_t r_skyquality = {CVAR_SAVE, "r_skyquality", "2"};
cvar_t r_mergesky = {CVAR_SAVE, "r_mergesky", "0"};
+cvar_t gl_transpolytris = {0, "gl_transpolytris", "0"};
static char skyworldname[1024];
static rtexture_t *mergeskytexture;
static qboolean skyavailable_quake;
static qboolean skyavailable_box;
-void R_BuildSky (int scrollupper, int scrolllower);
+static void R_BuildSky (int scrollupper, int scrolllower);
typedef struct translistitem_s
{
float transreciptable[256];
-void gl_poly_start(void)
+static void gl_poly_start(void)
{
int i;
transvert = qmalloc(MAX_TRANSVERTS * sizeof(transvert_t));
transpoly = qmalloc(MAX_TRANSPOLYS * sizeof(transpoly_t));
- transpolyindex = qmalloc(MAX_TRANSPOLYS * sizeof(unsigned short));
+ rendertranspoly = qmalloc(MAX_TRANSPOLYS * sizeof(rendertranspoly_t));
+ transpolyindex = qmalloc(MAX_TRANSPOLYS * sizeof(int));
+ transvertindex = qmalloc(MAX_TRANSVERTS * sizeof(int));
wallvert = qmalloc(MAX_WALLVERTS * sizeof(wallvert_t));
wallvertcolor = qmalloc(MAX_WALLVERTS * sizeof(wallvertcolor_t));
wallpoly = qmalloc(MAX_WALLPOLYS * sizeof(wallpoly_t));
transreciptable[i] = 1.0f / i;
}
-void gl_poly_shutdown(void)
+static void gl_poly_shutdown(void)
{
qfree(transvert);
qfree(transpoly);
+ qfree(rendertranspoly);
qfree(transpolyindex);
+ qfree(transvertindex);
qfree(wallvert);
qfree(wallvertcolor);
qfree(wallpoly);
qfree(skypoly);
}
-void gl_poly_newmap(void)
+static void gl_poly_newmap(void)
{
skyavailable_box = false;
skyavailable_quake = false;
Cvar_RegisterVariable (&r_multitexture);
Cvar_RegisterVariable (&r_skyquality);
Cvar_RegisterVariable (&r_mergesky);
+ Cvar_RegisterVariable (&gl_transpolytris);
R_RegisterModule("GL_Poly", gl_poly_start, gl_poly_shutdown, gl_poly_newmap);
}
transviewdist = DotProduct(r_origin, vpn);
}
-// turned into a #define
-/*
-void transpolybegin(int texnum, int glowtexnum, int fogtexnum, int transpolytype)
-{
- if (currenttranspoly >= MAX_TRANSPOLYS || currenttransvert >= MAX_TRANSVERTS)
- return;
- transpoly[currenttranspoly].texnum = (unsigned short) texnum;
- transpoly[currenttranspoly].glowtexnum = (unsigned short) glowtexnum;
- transpoly[currenttranspoly].fogtexnum = (unsigned short) fogtexnum;
- transpoly[currenttranspoly].transpolytype = (unsigned short) transpolytype;
- transpoly[currenttranspoly].firstvert = currenttransvert;
- transpoly[currenttranspoly].verts = 0;
-// transpoly[currenttranspoly].ndist = 0; // clear the normal
-}
-*/
-
-// turned into a #define
-/*
-void transpolyvert(float x, float y, float z, float s, float t, int r, int g, int b, int a)
-{
- int i;
- if (currenttranspoly >= MAX_TRANSPOLYS || currenttransvert >= MAX_TRANSVERTS)
- return;
- transvert[currenttransvert].s = s;
- transvert[currenttransvert].t = t;
- transvert[currenttransvert].r = bound(0, r, 255);
- transvert[currenttransvert].g = bound(0, g, 255);
- transvert[currenttransvert].b = bound(0, b, 255);
- transvert[currenttransvert].a = bound(0, a, 255);
- transvert[currenttransvert].v[0] = x;
- transvert[currenttransvert].v[1] = y;
- transvert[currenttransvert].v[2] = z;
- currenttransvert++;
- transpoly[currenttranspoly].verts++;
-}
-*/
+// transpolybegin and transpolyvert are #define macros
void transpolyend(void)
{
currenttranspoly++;
}
-int transpolyindices;
+void transpolyparticle(vec3_t org, vec3_t right, vec3_t up, vec_t scale, unsigned short texnum, unsigned short transpolytype, int ir, int ig, int ib, float alphaf, float s1, float t1, float s2, float t2)
+{
+ float center, scale2;
+ int i;
+ vec3_t corner;
+ byte br, bg, bb, ba;
+ transpoly_t *p;
+ transvert_t *v;
+ center = DotProduct(org, vpn) - transviewdist;
+ if (center < 4.0f || currenttranspoly >= MAX_TRANSPOLYS || (currenttransvert + 4) > MAX_TRANSVERTS)
+ return;
+
+ p = transpoly + (currenttranspoly++);
+ v = transvert + currenttransvert;
+
+ if (lighthalf)
+ {
+ ir >>= 1;
+ ig >>= 1;
+ ib >>= 1;
+ }
+ ir = bound(0, ir, 255);
+ ig = bound(0, ig, 255);
+ ib = bound(0, ib, 255);
+ br = (byte) ir;
+ bg = (byte) ig;
+ bb = (byte) ib;
+
+#if SLOWMATH
+ i = (int) alphaf;
+ if (i > 255)
+ i = 255;
+ ba = (byte) i;
+
+ i = (int) center;
+#else
+ alphaf += 8388608.0f;
+ i = *((long *)&alphaf) & 0x007FFFFF;
+ if (i > 255)
+ i = 255;
+ ba = (byte) i;
+
+ center += 8388608.0f;
+ i = *((long *)¢er) & 0x007FFFFF;
+#endif
+ i = bound(0, i, 4095);
+ currenttranslist->next = translisthash[i];
+ currenttranslist->poly = p;
+ translisthash[i] = currenttranslist++;
+
+ p->texnum = p->fogtexnum = texnum;
+ p->glowtexnum = 0;
+ p->transpolytype = transpolytype;
+ p->firstvert = currenttransvert;
+ p->verts = 4;
+ currenttransvert += 4;
+
+ scale2 = scale * -0.5f;
+ corner[0] = org[0] + (up[0] + right[0]) * scale2;
+ corner[1] = org[1] + (up[1] + right[1]) * scale2;
+ corner[2] = org[2] + (up[2] + right[2]) * scale2;
+ v->s = s1;
+ v->t = t1;
+ v->r = br;
+ v->g = bg;
+ v->b = bb;
+ v->a = ba;
+ v->v[0] = corner[0];
+ v->v[1] = corner[1];
+ v->v[2] = corner[2];
+ v++;
+ v->s = s1;
+ v->t = t2;
+ v->r = br;
+ v->g = bg;
+ v->b = bb;
+ v->a = ba;
+ v->v[0] = corner[0] + up[0] * scale;
+ v->v[1] = corner[1] + up[1] * scale;
+ v->v[2] = corner[2] + up[2] * scale;
+ v++;
+ v->s = s2;
+ v->t = t2;
+ v->r = br;
+ v->g = bg;
+ v->b = bb;
+ v->a = ba;
+ v->v[0] = corner[0] + (up[0] + right[0]) * scale;
+ v->v[1] = corner[1] + (up[1] + right[1]) * scale;
+ v->v[2] = corner[2] + (up[2] + right[2]) * scale;
+ v++;
+ v->s = s2;
+ v->t = t1;
+ v->r = br;
+ v->g = bg;
+ v->b = bb;
+ v->a = ba;
+ v->v[0] = corner[0] + right[0] * scale;
+ v->v[1] = corner[1] + right[1] * scale;
+ v->v[2] = corner[2] + right[2] * scale;
+ v++;
+}
void transpolyrender(void)
{
- int i, j, tpolytype, texnum;
- transpoly_t *p;
+ int i, j, k, l, tpolytype, texnum, transvertindices, alpha, currentrendertranspoly;
+ byte fogr, fogg, fogb;
+ vec3_t diff;
+ transpoly_t *p;
+ rendertranspoly_t *r, *rend;
+ translistitem *item;
+
if (!r_render.value)
return;
if (currenttranspoly < 1)
return;
-// transpolyrenderminmax();
-// if (transpolyindices < 1)
-// return;
- // testing
-// Con_DPrintf("transpolyrender: %i polys %i infront %i vertices\n", currenttranspoly, transpolyindices, currenttransvert);
-// if (transpolyindices >= 2)
-// transpolysort();
+
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_BLEND);
- glShadeModel(GL_SMOOTH);
+// glShadeModel(GL_SMOOTH);
glDepthMask(0); // disable zbuffer updates
- glDisable(GL_ALPHA_TEST);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- tpolytype = TPOLYTYPE_ALPHA;
- texnum = -1;
- /*
- if (gl_vertexarrays.value)
+
+ // set up the vertex array
+ glInterleavedArrays(GL_T2F_C4UB_V3F, sizeof(transvert[0]), transvert);
+
+ currentrendertranspoly = 0;
+ transvertindices = 0;
+ fogr = (byte) bound(0, (int) (fogcolor[0] * 255.0f), 255);
+ fogg = (byte) bound(0, (int) (fogcolor[1] * 255.0f), 255);
+ fogb = (byte) bound(0, (int) (fogcolor[2] * 255.0f), 255);
+ if (gl_transpolytris.value)
{
- // set up the vertex array
- glInterleavedArrays(GL_T2F_C4UB_V3F, 0, transvert);
- for (i = 0;i < transpolyindices;i++)
+ int glowtexnum, fogtexnum;
+ for (i = 4095;i >= 0;i--)
{
- p = &transpoly[transpolyindex[i]];
- if (p->texnum != texnum || p->transpolytype != tpolytype)
+ item = translisthash[i];
+ while(item)
{
- if (p->texnum != texnum)
+ p = item->poly;
+ item = item->next;
+ glowtexnum = p->glowtexnum;
+ fogtexnum = p->fogtexnum;
+
+#define POLYTOTRI(pfirstvert, ptexnum, ptranspolytype) \
+ l = pfirstvert;\
+ r = &rendertranspoly[currentrendertranspoly++];\
+ r->tex = ptexnum;\
+ r->type = ptranspolytype;\
+ if (p->verts == 4)\
+ {\
+ transvertindex[transvertindices] = l;\
+ transvertindex[transvertindices + 1] = l + 1;\
+ transvertindex[transvertindices + 2] = l + 2;\
+ transvertindex[transvertindices + 3] = l;\
+ transvertindex[transvertindices + 4] = l + 2;\
+ transvertindex[transvertindices + 5] = l + 3;\
+ transvertindices += 6;\
+ r->indices = 6;\
+ }\
+ else if (p->verts == 3)\
+ {\
+ transvertindex[transvertindices] = l;\
+ transvertindex[transvertindices + 1] = l + 1;\
+ transvertindex[transvertindices + 2] = l + 2;\
+ transvertindices += 3;\
+ r->indices = 3;\
+ }\
+ else\
+ {\
+ for (j = l + p->verts, k = l + 2;k < j;k++)\
+ {\
+ transvertindex[transvertindices] = l;\
+ transvertindex[transvertindices + 1] = k - 1;\
+ transvertindex[transvertindices + 2] = k;\
+ transvertindices += 3;\
+ }\
+ r->indices = (p->verts - 2) * 3;\
+ }
+
+ POLYTOTRI(p->firstvert, p->texnum, p->transpolytype)
+
+ if (p->glowtexnum)
{
- texnum = p->texnum;
- glBindTexture(GL_TEXTURE_2D, texnum);
+ // make another poly for glow effect
+ if (currenttranspoly < MAX_TRANSPOLYS && currenttransvert + p->verts <= MAX_TRANSVERTS)
+ {
+ memcpy(&transvert[currenttransvert], &transvert[p->firstvert], sizeof(transvert_t) * p->verts);
+ POLYTOTRI(currenttransvert, p->glowtexnum, TPOLYTYPE_ADD)
+ for (j = 0;j < p->verts;j++)
+ {
+ transvert[currenttransvert].r = transvert[currenttransvert].g = transvert[currenttransvert].b = 255;
+ currenttransvert++;
+ }
+ }
}
- if (p->transpolytype != tpolytype)
+
+ if (fogenabled)
{
- tpolytype = p->transpolytype;
- if (tpolytype == TPOLYTYPE_ADD) // additive
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- else // alpha
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ // make another poly for fog
+ if (currenttranspoly < MAX_TRANSPOLYS && currenttransvert + p->verts <= MAX_TRANSVERTS)
+ {
+ memcpy(&transvert[currenttransvert], &transvert[p->firstvert], sizeof(transvert_t) * p->verts);
+ POLYTOTRI(currenttransvert, p->fogtexnum, TPOLYTYPE_ALPHA)
+ for (j = 0, k = p->firstvert;j < p->verts;j++, k++)
+ {
+ transvert[currenttransvert].r = fogr;
+ transvert[currenttransvert].g = fogg;
+ transvert[currenttransvert].b = fogb;
+ VectorSubtract(transvert[currenttransvert].v, r_origin, diff);
+ alpha = transvert[currenttransvert].a * exp(fogdensity / DotProduct(diff, diff));
+ transvert[currenttransvert].a = (byte) bound(0, alpha, 255);
+ currenttransvert++;
+ }
+ }
}
}
- glDrawArrays(GL_POLYGON, p->firstvert, p->verts);
- if (p->glowtexnum)
- {
- texnum = p->glowtexnum; // highly unlikely to match next poly, but...
- glBindTexture(GL_TEXTURE_2D, texnum);
- tpolytype = TPOLYTYPE_ADD; // might match next poly
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- glDrawArrays(GL_POLYGON, p->firstvert, p->verts);
- }
}
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
}
else
- */
{
- int points = -1;
- translistitem *item;
- transvert_t *vert;
for (i = 4095;i >= 0;i--)
{
item = translisthash[i];
- while (item)
+ while(item)
{
p = item->poly;
item = item->next;
- if (p->texnum != texnum || p->verts != points || p->transpolytype != tpolytype)
- {
- glEnd();
- if (isG200)
- {
- // LordHavoc: Matrox G200 cards can't handle per pixel alpha
- if (p->fogtexnum)
- glEnable(GL_ALPHA_TEST);
- else
- glDisable(GL_ALPHA_TEST);
- }
- if (p->texnum != texnum)
- {
- texnum = p->texnum;
- glBindTexture(GL_TEXTURE_2D, texnum);
- }
- if (p->transpolytype != tpolytype)
- {
- tpolytype = p->transpolytype;
- if (tpolytype == TPOLYTYPE_ADD) // additive
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- else // alpha
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- points = p->verts;
- switch (points)
- {
- case 3:
- glBegin(GL_TRIANGLES);
- break;
- case 4:
- glBegin(GL_QUADS);
- break;
- default:
- glBegin(GL_POLYGON);
- points = -1; // to force a reinit on the next poly
- break;
- }
- }
- for (j = 0,vert = &transvert[p->firstvert];j < p->verts;j++, vert++)
- {
- // would be 2fv, but windoze Matrox G200 and probably G400 drivers don't support that (dumb...)
- glTexCoord2f(vert->s, vert->t);
- // again, vector version isn't supported I think
- glColor4ub(vert->r, vert->g, vert->b, vert->a);
- glVertex3fv(vert->v);
- }
+
+ l = p->firstvert;
+ r = &rendertranspoly[currentrendertranspoly++];
+ r->tex = p->texnum;
+ r->type = p->transpolytype;
+ r->indices = p->verts;
+
+ for (j = l + p->verts, k = l;k < j;k++)
+ transvertindex[transvertindices++] = k;
+
if (p->glowtexnum)
{
- glEnd();
- texnum = p->glowtexnum; // highly unlikely to match next poly, but...
- glBindTexture(GL_TEXTURE_2D, texnum);
- if (tpolytype != TPOLYTYPE_ADD)
- {
- tpolytype = TPOLYTYPE_ADD; // might match next poly
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- }
- points = -1;
- glBegin(GL_POLYGON);
- for (j = 0,vert = &transvert[p->firstvert];j < p->verts;j++, vert++)
- {
- glColor4ub(255,255,255,vert->a);
- // would be 2fv, but windoze Matrox G200 and probably G400 drivers don't support that (dumb...)
- glTexCoord2f(vert->s, vert->t);
- glVertex3fv(vert->v);
- }
- glEnd();
- }
- if (fogenabled && p->transpolytype == TPOLYTYPE_ALPHA)
- {
- vec3_t diff;
- glEnd();
- points = -1; // to force a reinit on the next poly
- if (tpolytype != TPOLYTYPE_ALPHA)
+ // make another poly for glow effect
+ if (currentrendertranspoly < MAX_TRANSPOLYS && currenttransvert + p->verts <= MAX_TRANSVERTS)
{
- tpolytype = TPOLYTYPE_ALPHA; // probably matchs next poly
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- if (p->fogtexnum)
- {
- if (texnum != p->fogtexnum) // highly unlikely to match next poly, but...
- {
- texnum = p->fogtexnum;
- glBindTexture(GL_TEXTURE_2D, texnum);
- }
- glBegin(GL_POLYGON);
- for (j = 0,vert = &transvert[p->firstvert];j < p->verts;j++, vert++)
+ l = currenttransvert;
+ r = &rendertranspoly[currentrendertranspoly++];
+ r->tex = p->glowtexnum;
+ r->type = TPOLYTYPE_ADD;
+ r->indices = p->verts;
+
+ memcpy(&transvert[currenttransvert], &transvert[p->firstvert], sizeof(transvert_t) * p->verts);
+ for (j = 0;j < p->verts;j++)
{
- VectorSubtract(vert->v, r_origin, diff);
- glTexCoord2f(vert->s, vert->t);
- glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], vert->a*(1.0f/255.0f)*exp(fogdensity/DotProduct(diff,diff)));
- glVertex3fv(vert->v);
+ transvert[currenttransvert].r = transvert[currenttransvert].g = transvert[currenttransvert].b = 255;
+ transvertindex[transvertindices++] = currenttransvert++;
}
- glEnd ();
}
- else
+ }
+ if (fogenabled)
+ {
+ // make another poly for fog
+ if (currentrendertranspoly < MAX_TRANSPOLYS && currenttransvert + p->verts <= MAX_TRANSVERTS)
{
- glDisable(GL_TEXTURE_2D);
- glBegin(GL_POLYGON);
- for (j = 0,vert = &transvert[p->firstvert];j < p->verts;j++, vert++)
+ l = currenttransvert;
+ r = &rendertranspoly[currentrendertranspoly++];
+ r->tex = p->fogtexnum;
+ r->type = TPOLYTYPE_ALPHA;
+ r->indices = p->verts;
+
+ memcpy(&transvert[currenttransvert], &transvert[p->firstvert], sizeof(transvert_t) * p->verts);
+ for (j = 0;j < p->verts;j++)
{
- VectorSubtract(vert->v, r_origin, diff);
- glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], vert->a*(1.0f/255.0f)*exp(fogdensity/DotProduct(diff,diff)));
- glVertex3fv(vert->v);
+ transvert[currenttransvert].r = fogr;
+ transvert[currenttransvert].g = fogg;
+ transvert[currenttransvert].b = fogb;
+ VectorSubtract(transvert[currenttransvert].v, r_origin, diff);
+ alpha = transvert[currenttransvert].a * exp(fogdensity / DotProduct(diff, diff));
+ transvert[currenttransvert].a = (byte) bound(0, alpha, 255);
+ transvertindex[transvertindices++] = currenttransvert++;
}
- glEnd ();
- glEnable(GL_TEXTURE_2D);
}
}
}
}
- glEnd();
}
+ GL_LockArray(0, currenttransvert);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ tpolytype = TPOLYTYPE_ALPHA;
+ texnum = -1;
+ transvertindices = 0;
+ r = rendertranspoly;
+ rend = r + currentrendertranspoly;
+ while(r < rend)
+ {
+ if (texnum != r->tex)
+ {
+ texnum = r->tex;
+ glBindTexture(GL_TEXTURE_2D, texnum);
+ }
+ if (tpolytype != r->type)
+ {
+ tpolytype = r->type;
+ if (tpolytype == TPOLYTYPE_ADD) // additive
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ else // alpha
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ k = transvertindices;
+ if (gl_transpolytris.value)
+ {
+ do
+ transvertindices += r->indices, r++;
+ while (r < rend && r->tex == texnum && r->type == tpolytype);
+ glDrawElements(GL_TRIANGLES, transvertindices - k, GL_UNSIGNED_INT, &transvertindex[k]);
+ }
+ else
+ {
+ if (r->indices == 4)
+ {
+ do
+ transvertindices += 4, r++;
+ while (r < rend && r->indices == 4 && r->tex == texnum && r->type == tpolytype);
+ glDrawElements(GL_QUADS, transvertindices - k, GL_UNSIGNED_INT, &transvertindex[k]);
+ }
+ else if (r->indices == 3)
+ {
+ do
+ transvertindices += 3, r++;
+ while (r < rend && r->indices == 3 && r->tex == texnum && r->type == tpolytype);
+ glDrawElements(GL_TRIANGLES, transvertindices - k, GL_UNSIGNED_INT, &transvertindex[k]);
+ }
+ else
+ {
+ transvertindices += r->indices, r++;
+ glDrawElements(GL_POLYGON, transvertindices - k, GL_UNSIGNED_INT, &transvertindex[k]);
+ }
+ }
+ }
+
+ GL_UnlockArray();
+
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(1); // enable zbuffer updates
- glDisable(GL_ALPHA_TEST);
+ glDisable(GL_BLEND);
+ glColor3f(1,1,1);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
}
void wallpolyclear(void)
{
+ if (!gl_mtexable)
+ r_multitexture.value = 0;
currentwallpoly = currentwallvert = 0;
}
-void wallpolyrender(void)
+// render walls and fullbrights, but not fog
+void wallpolyrender1(void)
{
int i, j, texnum, lighttexnum;
wallpoly_t *p;
c_brush_polys += currentwallpoly;
// testing
//Con_DPrintf("wallpolyrender: %i polys %i vertices\n", currentwallpoly, currentwallvert);
- if (!gl_mtexable)
- r_multitexture.value = 0;
glDisable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glShadeModel(GL_FLAT);
+// glShadeModel(GL_FLAT);
// make sure zbuffer is enabled
glEnable(GL_DEPTH_TEST);
// glDisable(GL_ALPHA_TEST);
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
texnum = -1;
- for (i = 0,p = wallpoly;i < currentwallpoly;i++, p++)
+ for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++)
{
if (p->texnum != texnum)
{
}
texnum = -1;
lighttexnum = -1;
- for (i = 0,p = wallpoly;i < currentwallpoly;i++, p++)
+ for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++)
{
if (p->texnum != texnum)
{
// first do the textures
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
texnum = -1;
- for (i = 0,p = wallpoly;i < currentwallpoly;i++, p++)
+ for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++)
{
if (p->texnum != texnum)
{
// switch to additive mode settings
glDepthMask(0);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ glBlendFunc(GL_ONE, GL_ONE);
glEnable(GL_BLEND);
// glDisable(GL_ALPHA_TEST);
- glShadeModel(GL_SMOOTH);
+// glShadeModel(GL_SMOOTH);
// render vertex lit overlays ontop
texnum = -1;
for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++)
glEnd();
}
// render glow textures
- glShadeModel(GL_FLAT);
- glBlendFunc(GL_ONE, GL_ONE);
+// glShadeModel(GL_FLAT);
if (lighthalf)
glColor3f(0.5,0.5,0.5);
else
glColor3f(1,1,1);
texnum = -1;
- for (i = 0,p = wallpoly;i < currentwallpoly;i++, p++)
+ for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++)
{
if (!p->glowtexnum)
continue;
}
glColor3f(1,1,1);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glShadeModel(GL_SMOOTH);
+// glDisable(GL_ALPHA_TEST);
+// glShadeModel(GL_SMOOTH);
+ glDisable(GL_BLEND);
+ glDepthMask(1);
+}
+
+// render fog
+void wallpolyrender2(void)
+{
+ if (!r_render.value)
+ return;
+ if (currentwallpoly < 1)
+ return;
if (fogenabled)
{
+ int i, j, alpha, fogr, fogg, fogb;
+ wallpoly_t *p;
+ wallvert_t *vert;
vec3_t diff;
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(0);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+// glShadeModel(GL_SMOOTH);
glDisable(GL_TEXTURE_2D);
- for (i = 0,p = &wallpoly[0];i < currentwallpoly;i++, p++)
+ fogr = (byte) bound(0, (int) (fogcolor[0] * 255.0f), 255);
+ fogg = (byte) bound(0, (int) (fogcolor[1] * 255.0f), 255);
+ fogb = (byte) bound(0, (int) (fogcolor[2] * 255.0f), 255);
+ for (i = 0, p = wallpoly;i < currentwallpoly;i++, p++)
{
vert = &wallvert[p->firstvert];
glBegin(GL_POLYGON);
for (j=0 ; j<p->numverts ; j++, vert++)
{
VectorSubtract(vert->vert, r_origin, diff);
- glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
+ alpha = 255.0f * exp(fogdensity/DotProduct(diff,diff));
+ alpha = bound(0, alpha, 255);
+ glColor4ub(fogr, fogg, fogb, (byte) alpha);
glVertex3fv (vert->vert);
}
glEnd ();
}
glEnable(GL_TEXTURE_2D);
+ glColor3f(1,1,1);
+ glDisable(GL_BLEND);
+ glDepthMask(1);
}
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-// glDisable(GL_ALPHA_TEST);
- glShadeModel(GL_SMOOTH);
- glDisable(GL_BLEND);
- glDepthMask(1);
}
static int skyrendersphere;
}
+static void R_Sky(void);
+
void skypolyrender(void)
{
int i, j;
}
GL_UnlockArray();
glDisableClientState(GL_VERTEX_ARRAY);
+
+ R_Sky();
}
static char skyname[256];
R_SetSkyBox
==================
*/
-char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
-rtexture_t *skyboxside[6];
+static char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
+static rtexture_t *skyboxside[6];
int R_SetSkyBox(char *sky)
{
int i;
sprintf (name, "gfx/env/%s%s", sky, suf[i]);
if (!(image_rgba = loadimagepixels(name, false, 0, 0)))
{
- Con_Printf ("Couldn't load %s\n", name);
+ Con_Printf ("Couldn't load env/%s%s or gfx/env/%s%s\n", sky, suf[i], sky, suf[i]);
continue;
}
}
glTexCoord2f((s) * (254.0f/256.0f) + (1.0f/256.0f), (t) * (254.0f/256.0f) + (1.0f/256.0f));\
glVertex3f((x) * 1024.0 + r_origin[0], (y) * 1024.0 + r_origin[1], (z) * 1024.0 + r_origin[2]);
-void R_SkyBox(void)
+static void R_SkyBox(void)
{
glDisable(GL_DEPTH_TEST);
glDepthMask(0);
glColor3f (1,1,1);
}
-float skysphere[33*33*5];
-int skysphereindices[32*32*6];
-void skyspherecalc(float *sphere, float dx, float dy, float dz)
+static float skysphere[33*33*5];
+static int skysphereindices[32*32*6];
+static void skyspherecalc(float *sphere, float dx, float dy, float dz)
{
float a, b, x, ax, ay, v[3], length;
int i, j, *index;
}
}
-void skyspherearrays(float *vert, float *tex, float *tex2, float *source, float s, float s2)
+static void skyspherearrays(float *vert, float *tex, float *tex2, float *source, float s, float s2)
{
float *v, *t, *t2;
int i;
}
}
-void R_SkySphere(void)
+static void R_SkySphere(void)
{
float speedscale, speedscale2;
float vert[33*33*4], tex[33*33*2], tex2[33*33*2];
glColor3f (1,1,1);
}
-void R_Sky(void)
+static void R_Sky(void)
{
if (!r_render.value)
return;
//===============================================================
-byte skyupperlayerpixels[128*128*4];
-byte skylowerlayerpixels[128*128*4];
-byte skymergedpixels[128*128*4];
+static byte skyupperlayerpixels[128*128*4];
+static byte skylowerlayerpixels[128*128*4];
+static byte skymergedpixels[128*128*4];
-void R_BuildSky (int scrollupper, int scrolllower)
+static void R_BuildSky (int scrollupper, int scrolllower)
{
int x, y, ux, uy, lx, ly;
byte *m, *u, *l;
extern void transpolyrender(void);
extern void transpolybegin(int texnum, int glowtexnum, int fogtexnum, int transpolytype);
extern void transpolyend(void);
+extern void transpolyparticle(vec3_t org, vec3_t right, vec3_t up, vec_t scale, unsigned short texnum, unsigned short transpolytype, int ir, int ig, int ib, float alphaf, float s1, float t1, float s2, float t2);
extern void wallpolyclear(void);
-extern void wallpolyrender(void);
+extern void wallpolyrender1(void);
+extern void wallpolyrender2(void);
extern void skypolyclear(void);
extern void skypolyrender(void);
extern transvert_t *transvert;
extern transpoly_t *transpoly;
-extern unsigned short *transpolyindex;
+extern int *transpolyindex;
+extern int *transvertindex;
+extern transpoly_t **transpolylist;
extern wallvert_t *wallvert;
extern wallvertcolor_t *wallvertcolor;
extern wallpoly_t *wallpoly;
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
#include "quakedef.h"
-qboolean r_cache_thrash; // compatability
+//static qboolean r_cache_thrash; // compatability
-vec3_t modelorg, r_entorigin;
-entity_t *currententity;
+vec3_t modelorg;
+entity_render_t *currentrenderentity;
int r_framecount; // used for dlight push checking
vec3_t vright;
vec3_t r_origin;
-float r_world_matrix[16];
-float r_base_world_matrix[16];
+//float r_world_matrix[16];
+//float r_base_world_matrix[16];
//
// screen size info
unsigned short d_lightstylevalue[256]; // 8.8 fraction of base light value
-void R_MarkLeaves (void);
-
//cvar_t r_norefresh = {0, "r_norefresh","0"};
cvar_t r_drawentities = {0, "r_drawentities","1"};
cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
cvar_t glfog = {0, "glfog", "0"};
cvar_t r_ser = {CVAR_SAVE, "r_ser", "1"};
+cvar_t gl_viewmodeldepthhack = {0, "gl_viewmodeldepthhack", "1"};
-/*
int R_VisibleCullBox (vec3_t mins, vec3_t maxs)
{
int sides;
mnode_t *nodestack[8192], *node;
int stack = 0;
+ if (R_CullBox(mins, maxs))
+ return true;
+
node = cl.worldmodel->nodes;
loc0:
if (node->contents < 0)
{
if (((mleaf_t *)node)->visframe == r_framecount)
- {
- if (R_CullBox(mins, maxs))
- return true;
return false;
- }
if (!stack)
return true;
node = nodestack[--stack];
node = node->children[1];
goto loc0;
}
-*/
qboolean lighthalf;
qboolean oldgl_fogenable;
void FOG_framebegin(void)
{
- if (nehahra)
+ if (gamemode == GAME_NEHAHRA)
{
-// if (!Nehahrademcompatibility)
-// gl_fogenable.value = 0;
if (gl_fogenable.value)
{
oldgl_fogenable = true;
return;
if(fog_density)
{
- // LordHavoc: Borland C++ 5.0 was choking on this line, stupid compiler...
+ // LordHavoc: Borland C++ 5.0 was choking on this line...
//GLfloat colors[4] = {(GLfloat) gl_fogred.value, (GLfloat) gl_foggreen.value, (GLfloat) gl_fogblue.value, (GLfloat) 1};
GLfloat colors[4];
colors[0] = fog_red;
}
glFogi (GL_FOG_MODE, GL_EXP2);
- glFogf (GL_FOG_DENSITY, (GLfloat) fog_density / 100);
+ glFogf (GL_FOG_DENSITY, (GLfloat) fog_density / 100);
glFogfv (GL_FOG_COLOR, colors);
glEnable (GL_FOG);
}
void FOG_clear(void)
{
- if (nehahra)
+ if (gamemode == GAME_NEHAHRA)
{
Cvar_Set("gl_fogenable", "0");
Cvar_Set("gl_fogdensity", "0.2");
void FOG_registercvars(void)
{
Cvar_RegisterVariable (&glfog);
- if (nehahra)
+ if (gamemode == GAME_NEHAHRA)
{
Cvar_RegisterVariable (&gl_fogenable);
Cvar_RegisterVariable (&gl_fogdensity);
Cvar_RegisterVariable (&r_dynamic);
Cvar_RegisterVariable (&r_waterripple);
Cvar_RegisterVariable (&r_farclip);
- if (nehahra)
- Cvar_SetValue("r_fullbrights", 0);
-// if (gl_vendor && strstr(gl_vendor, "3Dfx"))
-// gl_lightmode.value = 0;
Cvar_RegisterVariable (&r_fullbright);
Cvar_RegisterVariable (&r_ser);
+ Cvar_RegisterVariable (&gl_viewmodeldepthhack);
+ if (gamemode == GAME_NEHAHRA)
+ Cvar_SetValue("r_fullbrights", 0);
R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
}
}
-/*
-void R_RotateForEntity (entity_t *e)
-{
- glTranslatef (e->origin[0], e->origin[1], e->origin[2]);
-
- glRotatef (e->angles[1], 0, 0, 1);
- glRotatef (-e->angles[0], 0, 1, 0);
- glRotatef (e->angles[2], 1, 0, 0);
-
- glScalef (e->scale, e->scale, e->scale); // LordHavoc: model scale
-}
-*/
-
-// LordHavoc: shading stuff
-vec3_t shadevector;
-vec3_t shadecolor;
-
-float modelalpha;
-
//==================================================================================
-void R_LerpUpdate(entity_t *ent)
+void R_Entity_Callback(void *data, void *junk)
{
- int frame;
- frame = ent->render.frame;
- if (ent->render.model && ent->render.frame >= ent->render.model->numframes)
- {
- Con_Printf("R_LerpUpdate: no such frame%6i in \"%s\"\n", ent->render.frame, ent->render.model->name);
- frame = 0;
- }
-
- if (ent->render.lerp_model != ent->render.model)
- {
- // reset all interpolation information
- ent->render.lerp_model = ent->render.model;
- ent->render.frame1 = ent->render.frame2 = frame;
- ent->render.frame1start = ent->render.frame2start = cl.time;
- ent->render.framelerp = 1;
- ent->render.lerp_starttime = 0;
- }
- else if (ent->render.frame2 != frame)
- {
- // transition to new frame
- ent->render.frame1 = ent->render.frame2;
- ent->render.frame1start = ent->render.frame2start;
- ent->render.frame2 = frame;
- ent->render.frame2start = cl.time;
- ent->render.framelerp = 0;
- ent->render.lerp_starttime = cl.time;
- }
- else
- {
- // lerp_starttime < 0 is used to prevent changing of framelerp
- if (ent->render.lerp_starttime >= 0)
- {
- // update transition
- ent->render.framelerp = (cl.time - ent->render.lerp_starttime) * 10;
- ent->render.framelerp = bound(0, ent->render.framelerp, 1);
- }
- }
+ ((entity_render_t *)data)->visframe = r_framecount;
}
-
-void R_PrepareEntities (void)
+static void R_AddModelEntities (void)
{
- int i;
- entity_t *ent;
- vec3_t v;
- // this updates entities that are supposed to be view relative
+ int i;
+ vec3_t v;
+
+ if (!r_drawentities.value)
+ return;
+
for (i = 0;i < cl_numvisedicts;i++)
{
- ent = cl_visedicts[i];
+ currentrenderentity = &cl_visedicts[i]->render;
- if (ent->render.flags & RENDER_VIEWMODEL)
+ // move view-relative models to where they should be
+ if (currentrenderentity->flags & RENDER_VIEWMODEL)
{
// remove flag so it will not be repeated incase RelinkEntities is not called again for a while
- ent->render.flags -= RENDER_VIEWMODEL;
+ currentrenderentity->flags -= RENDER_VIEWMODEL;
// transform origin
- VectorCopy(ent->render.origin, v);
- ent->render.origin[0] = v[0] * vpn[0] + v[1] * vright[0] + v[2] * vup[0] + r_origin[0];
- ent->render.origin[1] = v[0] * vpn[1] + v[1] * vright[1] + v[2] * vup[1] + r_origin[1];
- ent->render.origin[2] = v[0] * vpn[2] + v[1] * vright[2] + v[2] * vup[2] + r_origin[2];
+ VectorCopy(currentrenderentity->origin, v);
+ currentrenderentity->origin[0] = v[0] * vpn[0] + v[1] * vright[0] + v[2] * vup[0] + r_origin[0];
+ currentrenderentity->origin[1] = v[0] * vpn[1] + v[1] * vright[1] + v[2] * vup[1] + r_origin[1];
+ currentrenderentity->origin[2] = v[0] * vpn[2] + v[1] * vright[2] + v[2] * vup[2] + r_origin[2];
// adjust angles
- VectorAdd(ent->render.angles, r_refdef.viewangles, ent->render.angles);
+ VectorAdd(currentrenderentity->angles, r_refdef.viewangles, currentrenderentity->angles);
}
- }
-}
-
-void R_Entity_Callback(void *data, void *junk)
-{
- ((entity_t *)data)->render.visframe = r_framecount;
-}
-
-void R_AddModelEntities (void)
-{
- int i;
- vec3_t mins, maxs;
- frameblend_t blend[4];
-
- if (!r_drawentities.value)
- return;
- for (i = 0;i < cl_numvisedicts;i++)
- {
- currententity = cl_visedicts[i];
- if (currententity->render.model->type == mod_brush)
+ if (currentrenderentity->angles[0] || currentrenderentity->angles[2])
{
- modelalpha = currententity->render.alpha;
- R_DrawBrushModel (currententity);
+ VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->rotatedmins, currentrenderentity->mins);
+ VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->rotatedmaxs, currentrenderentity->maxs);
}
- else if (currententity->render.model->type == mod_alias)
+ else if (currentrenderentity->angles[1])
{
- VectorAdd(currententity->render.origin, currententity->render.model->mins, mins);
- VectorAdd(currententity->render.origin, currententity->render.model->maxs, maxs);
- if (r_ser.value)
- R_Clip_AddBox(mins, maxs, R_Entity_Callback, currententity, NULL);
- else if (R_NotCulledBox(mins, maxs))
- currententity->render.visframe = r_framecount;
+ VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->yawmins, currentrenderentity->mins);
+ VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->yawmaxs, currentrenderentity->maxs);
}
- else if (currententity->render.model->type == mod_sprite)
+ else
{
- R_LerpUpdate(currententity);
- if (r_ser.value)
- {
- R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend);
- R_ClipSprite(currententity, blend);
- }
- else
- {
- VectorAdd(currententity->render.origin, currententity->render.model->mins, mins);
- VectorAdd(currententity->render.origin, currententity->render.model->maxs, maxs);
- if (R_NotCulledBox(mins, maxs))
- currententity->render.visframe = r_framecount;
- }
+ VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->normalmins, currentrenderentity->mins);
+ VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->normalmaxs, currentrenderentity->maxs);
}
+ if (R_VisibleCullBox(currentrenderentity->mins, currentrenderentity->maxs))
+ continue;
+
+ R_LerpAnimation(currentrenderentity);
+ if (r_ser.value)
+ currentrenderentity->model->SERAddEntity();
+ else
+ currentrenderentity->visframe = r_framecount;
}
}
-/*
-=============
-R_DrawEntitiesOnList
-=============
-*/
-/*
-void R_DrawEntitiesOnList1 (void)
+void R_DrawModels1 (void)
{
int i;
for (i = 0;i < cl_numvisedicts;i++)
{
- if (cl_visedicts[i]->render.visframe != r_framecount)
- continue;
- if (cl_visedicts[i]->render.model->type != mod_brush)
- continue;
- currententity = cl_visedicts[i];
- modelalpha = currententity->render.alpha;
-
- R_DrawBrushModel (currententity);
+ currentrenderentity = &cl_visedicts[i]->render;
+ if (currentrenderentity->visframe == r_framecount && currentrenderentity->model->DrawEarly)
+ currentrenderentity->model->DrawEarly();
}
}
-*/
-void R_DrawModels (void)
+void R_DrawModels2 (void)
{
int i;
- frameblend_t blend[4];
-// vec3_t mins, maxs;
if (!r_drawentities.value)
return;
for (i = 0;i < cl_numvisedicts;i++)
{
- if (cl_visedicts[i]->render.visframe != r_framecount)
- continue;
- currententity = cl_visedicts[i];
- if (currententity->render.model->type != mod_alias && currententity->render.model->type != mod_sprite)
- continue;
-
- modelalpha = currententity->render.alpha;
-
- if (currententity->render.model->type == mod_alias)
- {
- // only lerp models here because sprites were already lerped for their clip polygon
- R_LerpUpdate(currententity);
- R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend);
- R_DrawAliasModel (currententity, true, modelalpha, currententity->render.model, blend, currententity->render.skinnum, currententity->render.origin, currententity->render.angles, currententity->render.scale, currententity->render.effects, currententity->render.model->flags, currententity->render.colormap);
- }
- else //if (currententity->render.model->type == mod_sprite)
- {
- // build blend array
- R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend);
- R_DrawSpriteModel (currententity, blend);
- }
-
- /*
- VectorAdd(cl_visedicts[i]->render.origin, cl_visedicts[i]->render.model->mins, mins);
- VectorAdd(cl_visedicts[i]->render.origin, cl_visedicts[i]->render.model->maxs, maxs);
-
- switch (cl_visedicts[i]->render.model->type)
- {
- case mod_alias:
- R_Clip_AddBox(mins, maxs, R_DrawModelCallback, cl_visedicts[i], NULL);
- break;
- case mod_sprite:
- R_Clip_AddBox(mins, maxs, R_DrawSpriteCallback, cl_visedicts[i], NULL);
- break;
- }
- */
+ currentrenderentity = &cl_visedicts[i]->render;
+ if (currentrenderentity->visframe == r_framecount && currentrenderentity->model->DrawLate)
+ currentrenderentity->model->DrawLate();
}
}
*/
void R_DrawViewModel (void)
{
- frameblend_t blend[4];
-
if (!r_drawviewmodel.value || chase_active.value || envmap || !r_drawentities.value || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.render.model)
return;
- currententity = &cl.viewent;
- currententity->render.alpha = modelalpha = cl_entities[cl.viewentity].render.alpha; // LordHavoc: if the player is transparent, so is the gun
- currententity->render.effects = cl_entities[cl.viewentity].render.effects;
- currententity->render.scale = 1;
- VectorCopy(cl_entities[cl.viewentity].render.colormod, currententity->render.colormod);
+ currentrenderentity = &cl.viewent.render;
- R_LerpUpdate(currententity);
- R_LerpAnimation(currententity->render.model, currententity->render.frame1, currententity->render.frame2, currententity->render.frame1start, currententity->render.frame2start, currententity->render.framelerp, blend);
+ R_LerpAnimation(currentrenderentity);
// hack the depth range to prevent view model from poking into walls
- glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
- R_DrawAliasModel (currententity, false, modelalpha, currententity->render.model, blend, currententity->render.skinnum, currententity->render.origin, currententity->render.angles, currententity->render.scale, currententity->render.effects, currententity->render.model->flags, currententity->render.colormap);
- glDepthRange (gldepthmin, gldepthmax);
+ if (gl_viewmodeldepthhack.value)
+ glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
+ currentrenderentity->model->DrawLate();
+ if (gl_viewmodeldepthhack.value)
+ glDepthRange (gldepthmin, gldepthmax);
}
-void R_DrawBrushModel (entity_t *e);
-
-void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees );
-
-void R_SetFrustum (void)
+static void R_SetFrustum (void)
{
int i;
}
}
-void R_AnimateLight (void);
-void V_CalcBlend (void);
-
/*
===============
R_SetupFrame
===============
*/
-void R_SetupFrame (void)
+static void R_SetupFrame (void)
{
// don't allow cheats in multiplayer
if (cl.maxclients > 1)
{
- Cvar_Set ("r_fullbright", "0");
- Cvar_Set ("r_ambient", "0");
+ if (r_fullbright.value != 0)
+ Cvar_Set ("r_fullbright", "0");
+ if (r_ambient.value != 0)
+ Cvar_Set ("r_ambient", "0");
}
r_framecount++;
V_SetContentsColor (r_viewleaf->contents);
V_CalcBlend ();
- r_cache_thrash = false;
+// r_cache_thrash = false;
c_brush_polys = 0;
c_alias_polys = 0;
}
-void MYgluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar )
+static void MYgluPerspective(GLdouble fovx, GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar )
{
- GLdouble xmin, xmax, ymin, ymax;
+ GLdouble xmax, ymax;
- ymax = zNear * tan( fovy * M_PI / 360.0 );
- ymin = -ymax;
+ xmax = zNear * tan( fovx * M_PI / 360.0 ) * aspect;
+ ymax = zNear * tan( fovy * M_PI / 360.0 );
- xmin = ymin * aspect;
- xmax = ymax * aspect;
+ if (r_viewleaf->contents != CONTENTS_EMPTY && r_viewleaf->contents != CONTENTS_SOLID)
+ {
+ xmax *= (sin(cl.time * 4.7) * 0.03 + 0.97);
+ ymax *= (sin(cl.time * 3) * 0.03 + 0.97);
+ }
- glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
+ glFrustum(-xmax, xmax, -ymax, ymax, zNear, zFar );
}
R_SetupGL
=============
*/
-void R_SetupGL (void)
+static void R_SetupGL (void)
{
- float screenaspect;
- int x, x2, y2, y, w, h;
-
if (!r_render.value)
return;
- //
+
// set up viewpoint
- //
glMatrixMode(GL_PROJECTION);
- glLoadIdentity ();
- x = r_refdef.vrect.x * glwidth/vid.width;
- x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width;
- y = (vid.height-r_refdef.vrect.y) * glheight/vid.height;
- y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height;
-
- // fudge around because of frac screen scale
- if (x > 0)
- x--;
- if (x2 < glwidth)
- x2++;
- if (y2 < 0)
- y2--;
- if (y < glheight)
- y++;
-
- w = x2 - x;
- h = y - y2;
-
- if (envmap)
- {
- x = y2 = 0;
- w = h = 256;
- }
+ glLoadIdentity ();
- glViewport (glx + x, gly + y2, w, h);
- screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
-// yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
- MYgluPerspective (r_refdef.fov_y, screenaspect, 4, r_farclip.value);
+ // y is weird beause OpenGL is bottom to top, we use top to bottom
+ glViewport(r_refdef.x, vid.realheight - (r_refdef.y + r_refdef.height), r_refdef.width, r_refdef.height);
+// yfov = 2*atan((float)r_refdef.height/r_refdef.width)*180/M_PI;
+ MYgluPerspective (r_refdef.fov_x, r_refdef.fov_y, r_refdef.width/r_refdef.height, 4, r_farclip.value);
glCullFace(GL_FRONT);
glMatrixMode(GL_MODELVIEW);
- glLoadIdentity ();
+ glLoadIdentity ();
- glRotatef (-90, 1, 0, 0); // put Z going up
- glRotatef (90, 0, 0, 1); // put Z going up
- glRotatef (-r_refdef.viewangles[2], 1, 0, 0);
- glRotatef (-r_refdef.viewangles[0], 0, 1, 0);
- glRotatef (-r_refdef.viewangles[1], 0, 0, 1);
- glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]);
+ glRotatef (-90, 1, 0, 0); // put Z going up
+ glRotatef (90, 0, 0, 1); // put Z going up
+ glRotatef (-r_refdef.viewangles[2], 1, 0, 0);
+ glRotatef (-r_refdef.viewangles[0], 0, 1, 0);
+ glRotatef (-r_refdef.viewangles[1], 0, 0, 1);
+ glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]);
- glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
+// glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
//
// set drawing parms
R_Clear
=============
*/
-void R_Clear (void)
+static void R_Clear (void)
{
if (!r_render.value)
return;
glDepthRange (gldepthmin, gldepthmax);
}
-// LordHavoc: my trick to *FIX* GLQuake lighting once and for all :)
-void GL_Brighten(void)
-{
- if (!r_render.value)
- return;
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity ();
- glOrtho (0, vid.width, vid.height, 0, -99999, 99999);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity ();
- glDisable (GL_DEPTH_TEST);
- glDisable (GL_CULL_FACE);
- glDisable(GL_TEXTURE_2D);
- glEnable(GL_BLEND);
- glBlendFunc (GL_DST_COLOR, GL_ONE);
- glBegin (GL_TRIANGLES);
- glColor3f (1, 1, 1);
- glVertex2f (-5000, -5000);
- glVertex2f (10000, -5000);
- glVertex2f (-5000, 10000);
- glEnd ();
- glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glDisable(GL_BLEND);
- glEnable(GL_TEXTURE_2D);
- glEnable (GL_DEPTH_TEST);
- glEnable (GL_CULL_FACE);
-}
-
-void GL_BlendView(void)
+static void GL_BlendView(void)
{
if (!r_render.value)
return;
glMatrixMode(GL_PROJECTION);
glLoadIdentity ();
- glOrtho (0, vid.width, vid.height, 0, -99999, 99999);
+ glOrtho (0, 256, 256, 0, -99999, 99999);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity ();
glDisable (GL_DEPTH_TEST);
r_refdef must be set before the first call
================
*/
-extern void R_Sky(void);
extern void UploadLightmaps(void);
extern void R_DrawSurfaces(void);
extern void R_DrawPortals(void);
void R_RenderView (void)
{
double starttime, currtime, temptime;
-// if (r_norefresh.value)
-// return;
if (!cl.worldmodel)
Host_Error ("R_RenderView: NULL worldmodel");
if (r_speeds2.value)
{
- starttime = currtime = Sys_DoubleTime();
-
speedstringcount = 0;
sprintf(r_speeds2_string, "org:'%c%6.2f %c%6.2f %c%6.2f' ang:'%c%3.0f %c%3.0f %c%3.0f' dir:'%c%2.3f %c%2.3f %c%2.3f'\n%6i walls %6i dlitwalls %7i modeltris %7i transpoly\nBSP: %6i faces %6i nodes %6i leafs\n%4i models %4i bmodels %4i sprites %5i particles %3i dlights\n",
r_origin[0] < 0 ? '-' : ' ', fabs(r_origin[0]), r_origin[1] < 0 ? '-' : ' ', fabs(r_origin[1]), r_origin[2] < 0 ? '-' : ' ', fabs(r_origin[2]), r_refdef.viewangles[0] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[0]), r_refdef.viewangles[1] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[1]), r_refdef.viewangles[2] < 0 ? '-' : ' ', fabs(r_refdef.viewangles[2]), vpn[0] < 0 ? '-' : ' ', fabs(vpn[0]), vpn[1] < 0 ? '-' : ' ', fabs(vpn[1]), vpn[2] < 0 ? '-' : ' ', fabs(vpn[2]),
c_brush_polys, c_light_polys, c_alias_polys, currenttranspoly,
c_faces, c_nodes, c_leafs,
c_models, c_bmodels, c_sprites, c_particles, c_dlights);
+
+ starttime = currtime = Sys_DoubleTime();
}
else
starttime = currtime = 0;
R_MoveParticles ();
+ TIMEREPORT("mparticles")
R_MoveExplosions();
+ TIMEREPORT("mexplosion")
FOG_framebegin();
R_SetupGL ();
R_Clip_StartFrame();
- R_PrepareEntities();
-
skypolyclear();
wallpolyclear();
transpolyclear();
TIMEREPORT("setup ")
R_DrawWorld ();
- TIMEREPORT("world ")
+ TIMEREPORT("addworld ")
R_AddModelEntities();
- TIMEREPORT("addmodels")
+ TIMEREPORT("addmodels ")
R_Clip_EndFrame();
TIMEREPORT("scanedge ")
// now mark the lit surfaces
R_PushDlights ();
- // yes this does add the world surfaces after the brush models
+ TIMEREPORT("marklights")
+
+ R_DrawModels1 ();
+
+ // yes this does add the world after the brush models when using the SER
R_DrawSurfaces ();
R_DrawPortals ();
TIMEREPORT("surfaces ");
UploadLightmaps();
TIMEREPORT("uploadlmap")
- // fogged sky polys, affects depth
skypolyrender();
-
- // does not affect depth, draws over the sky polys
- if (currentskypoly)
- R_Sky();
TIMEREPORT("skypoly ")
- wallpolyrender();
- TIMEREPORT("wallpoly ")
+ wallpolyrender1();
+ TIMEREPORT("wallpoly1 ")
GL_DrawDecals();
TIMEREPORT("ddecal ")
+ wallpolyrender2();
+ TIMEREPORT("wallpoly2 ")
+
// don't let sound skip if going slow
if (!intimerefresh && !r_speeds2.value)
S_ExtraUpdate ();
R_DrawViewModel ();
- R_DrawModels ();
+ R_DrawModels2 ();
TIMEREPORT("models ")
R_DrawParticles ();
TIMEREPORT("dparticles")
+
R_DrawExplosions();
TIMEREPORT("dexplosion")
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
Grab six views for environment mapping tests
===============
*/
+float CalcFov (float fov_x, float width, float height);
+struct
+{
+ float angles[3];
+ char *name;
+}
+envmapinfo[6] =
+{
+ {{ 0, 0, 0}, "ft"},
+ {{ 0, 90, 0}, "rt"},
+ {{ 0, 180, 0}, "bk"},
+ {{ 0, 270, 0}, "lf"},
+ {{-90, 90, 0}, "up"},
+ {{ 90, 90, 0}, "dn"}
+};
void R_Envmap_f (void)
{
- byte buffer[256*256*4];
+ int i, size;
+ char filename[256];
+ char basename[256];
+ byte *buffer, gamma[256];
+
+ if (Cmd_Argc() != 3)
+ {
+ Con_Printf ("envmap <basename> <size>: save out 6 cubic environment map images, usable with loadsky, note that size must one of 128, 256, 512, or 1024 and can't be bigger than your current resolution\n");
+ return;
+ }
if (!r_render.value)
return;
- glDrawBuffer (GL_FRONT);
- glReadBuffer (GL_FRONT);
+ strcpy(basename, Cmd_Argv(1));
+ size = atoi(Cmd_Argv(2));
+ if (size != 128 && size != 256 && size != 512 && size != 1024)
+ {
+ Con_Printf("envmap: size must be one of 128, 256, 512, or 1024\n");
+ return;
+ }
+ if (size > vid.realwidth || size > vid.realheight)
+ {
+ Con_Printf("envmap: your resolution is not big enough to render that size\n");
+ return;
+ }
+
+ buffer = malloc(size*size*3);
+ if (buffer == NULL)
+ {
+ Con_Printf("envmap: unable to allocate memory for image\n");
+ return;
+ }
+
+ BuildGammaTable8((lighthalf && hardwaregammasupported) ? 2.0f : 1.0f, 1, 1, 0, gamma);
+
+// glDrawBuffer (GL_FRONT);
+// glReadBuffer (GL_FRONT);
+ glDrawBuffer (GL_BACK);
+ glReadBuffer (GL_BACK);
envmap = true;
- r_refdef.vrect.x = 0;
- r_refdef.vrect.y = 0;
- r_refdef.vrect.width = 256;
- r_refdef.vrect.height = 256;
-
- r_refdef.viewangles[0] = 0;
- r_refdef.viewangles[1] = 0;
- r_refdef.viewangles[2] = 0;
- R_RenderView ();
- glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
- COM_WriteFile ("env0.rgb", buffer, sizeof(buffer));
-
- r_refdef.viewangles[1] = 90;
- R_RenderView ();
- glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
- COM_WriteFile ("env1.rgb", buffer, sizeof(buffer));
-
- r_refdef.viewangles[1] = 180;
- R_RenderView ();
- glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
- COM_WriteFile ("env2.rgb", buffer, sizeof(buffer));
-
- r_refdef.viewangles[1] = 270;
- GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
- R_RenderView ();
- glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
- COM_WriteFile ("env3.rgb", buffer, sizeof(buffer));
-
- r_refdef.viewangles[0] = -90;
- r_refdef.viewangles[1] = 0;
- R_RenderView ();
- glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
- COM_WriteFile ("env4.rgb", buffer, sizeof(buffer));
-
- r_refdef.viewangles[0] = 90;
- r_refdef.viewangles[1] = 0;
- R_RenderView ();
- glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
- COM_WriteFile ("env5.rgb", buffer, sizeof(buffer));
+ r_refdef.x = 0;
+ r_refdef.y = 0;
+ r_refdef.width = size;
+ r_refdef.height = size;
+
+ r_refdef.fov_x = 90;
+ r_refdef.fov_y = 90;
+
+ for (i = 0;i < 6;i++)
+ {
+ VectorCopy(envmapinfo[i].angles, r_refdef.viewangles);
+ glClearColor(0,0,0,0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: clear the screen (around the view as well)
+ R_RenderView ();
+ glReadPixels (0, 0, size, size, GL_RGB, GL_UNSIGNED_BYTE, buffer);
+ sprintf(filename, "env/%s%s.tga", basename, envmapinfo[i].name);
+ Image_GammaRemapRGB(buffer, buffer, size * size, gamma, gamma, gamma);
+ Image_WriteTGARGB_preflipped(filename, size, size, buffer);
+ }
envmap = false;
glDrawBuffer (GL_BACK);
glReadBuffer (GL_BACK);
- GL_EndRendering ();
-}
-void R_InitParticles (void);
+ free(buffer);
+
+ // cause refdef to be fixed
+// vid.recalc_refdef = 1;
+}
-void gl_misc_start(void)
+static void gl_misc_start(void)
{
}
-void gl_misc_shutdown(void)
+static void gl_misc_shutdown(void)
{
}
-void gl_misc_newmap(void)
+static void gl_misc_newmap(void)
{
}
R_Init
===============
*/
+static void R_TimeRefresh_f (void);
void GL_Misc_Init (void)
-{
- Cmd_AddCommand ("envmap", R_Envmap_f);
- Cmd_AddCommand ("timerefresh", R_TimeRefresh_f);
+{
+ Cmd_AddCommand ("envmap", R_Envmap_f);
+ Cmd_AddCommand ("timerefresh", R_TimeRefresh_f);
R_RegisterModule("GL_Misc", gl_misc_start, gl_misc_shutdown, gl_misc_newmap);
}
-extern void R_ClearParticles (void);
extern void GL_BuildLightmaps (void);
/*
void R_NewMap (void)
{
int i;
-
+
for (i=0 ; i<256 ; i++)
d_lightstylevalue[i] = 264; // normal light value
====================
*/
qboolean intimerefresh = 0;
-void R_TimeRefresh_f (void)
+static void R_TimeRefresh_f (void)
{
int i;
float start, stop, time;
intimerefresh = 1;
start = Sys_DoubleTime ();
+ glDrawBuffer (GL_FRONT);
for (i = 0;i < 128;i++)
{
r_refdef.viewangles[0] = 0;
r_refdef.viewangles[1] = i/128.0*360.0;
r_refdef.viewangles[2] = 0;
- SCR_UpdateScreen();
+ R_RenderView();
}
+ glDrawBuffer (GL_BACK);
stop = Sys_DoubleTime ();
intimerefresh = 0;
signed int blocklights[BLOCK_WIDTH*BLOCK_HEIGHT*3]; // LordHavoc: *3 for colored lighting
-int lightmapalign, lightmapalignmask; // LordHavoc: NVIDIA's broken subimage fix, see BuildLightmaps for notes
-cvar_t gl_lightmapalign = {0, "gl_lightmapalign", "4"};
+byte templight[BLOCK_WIDTH*BLOCK_HEIGHT*4];
+
+int lightmapalign, lightmapalignmask; // LordHavoc: align texsubimage updates on 4 byte boundaries
+cvar_t gl_lightmapalign = {0, "gl_lightmapalign", "4"}; // align texsubimage updates on 4 byte boundaries
cvar_t gl_lightmaprgba = {0, "gl_lightmaprgba", "1"};
cvar_t gl_nosubimagefragments = {0, "gl_nosubimagefragments", "0"};
cvar_t gl_nosubimage = {0, "gl_nosubimage", "0"};
cvar_t r_dlightmap = {CVAR_SAVE, "r_dlightmap", "1"};
cvar_t r_drawportals = {0, "r_drawportals", "0"};
cvar_t r_testvis = {0, "r_testvis", "0"};
-cvar_t r_solidworldnode = {0, "r_solidworldnode", "3"};
-cvar_t r_pvsworldnode = {0, "r_pvsworldnode", "1"};
qboolean lightmaprgba, nosubimagefragments, nosubimage;
int lightmapbytes;
Cvar_RegisterVariable(&r_dlightmap);
Cvar_RegisterVariable(&r_drawportals);
Cvar_RegisterVariable(&r_testvis);
- Cvar_RegisterVariable(&r_solidworldnode);
- Cvar_RegisterVariable(&r_pvsworldnode);
R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap);
}
if (!(surf->dlightbits[lnum >> 5] & (1 << (lnum & 31))))
continue; // not lit by this light
- VectorSubtract (cl_dlights[lnum].origin, currententity->render.origin, local);
+ VectorSubtract (cl_dlights[lnum].origin, currentrenderentity->origin, local);
dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
// for comparisons to minimum acceptable light
Combine and scale multiple lightmaps into the 8.8 format in blocklights
===============
*/
-void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
+void R_BuildLightMap (msurface_t *surf, byte *dest, int stride, int dlightchanged)
{
int smax, tmax;
int i, j, size, size3;
int maps;
int *bl;
+ // update cached lighting info
surf->cached_dlight = 0;
surf->cached_lightscalebit = lightscalebit;
surf->cached_ambient = r_ambient.value;
+ surf->cached_light[0] = d_lightstylevalue[surf->styles[0]];
+ surf->cached_light[1] = d_lightstylevalue[surf->styles[1]];
+ surf->cached_light[2] = d_lightstylevalue[surf->styles[2]];
+ surf->cached_light[3] = d_lightstylevalue[surf->styles[3]];
smax = (surf->extents[0]>>4)+1;
tmax = (surf->extents[1]>>4)+1;
lightmap = surf->samples;
// set to full bright if no light data
- if ((currententity && (currententity->render.effects & EF_FULLBRIGHT)) || !cl.worldmodel->lightdata)
+ if ((currentrenderentity->effects & EF_FULLBRIGHT) || !cl.worldmodel->lightdata)
{
bl = blocklights;
- for (i=0 ; i<size ; i++)
+ for (i = 0;i < size;i++)
{
*bl++ = 255*256;
*bl++ = 255*256;
else
memset(&blocklights[0], 0, size*3*sizeof(int));
+ if (r_dlightmap.value && surf->dlightframe == r_framecount)
+ {
+ if ((surf->cached_dlight = R_AddDynamicLights(surf)))
+ c_light_polys++;
+ else if (dlightchanged)
+ return; // don't upload if only updating dlights and none mattered
+ }
+
// add all the lightmaps
if (lightmap)
- {
for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++)
- {
- scale = d_lightstylevalue[surf->styles[maps]];
- surf->cached_light[maps] = scale; // 8.8 fraction
- bl = blocklights;
- for (i = 0;i < size3;i++)
+ for (scale = d_lightstylevalue[surf->styles[maps]], bl = blocklights, i = 0;i < size3;i++)
*bl++ += *lightmap++ * scale;
- }
- }
- if (r_dlightmap.value && surf->dlightframe == r_framecount)
- if ((surf->cached_dlight = R_AddDynamicLights(surf)))
- c_light_polys++;
}
+
R_ConvertLightmap(blocklights, dest, smax, tmax, stride);
}
-byte templight[BLOCK_WIDTH*BLOCK_HEIGHT*4];
-
-void R_UpdateLightmap(msurface_t *s, int lnum)
+void R_UpdateLightmap(msurface_t *s, int lnum, int dlightschanged)
{
int smax, tmax;
// upload the new lightmap texture fragment
if (lightmapupdate[lnum][1] < (s->light_t + ((s->extents[1]>>4)+1)))
lightmapupdate[lnum][1] = (s->light_t + ((s->extents[1]>>4)+1));
if (lightmaprgba)
- R_BuildLightMap (s, lightmaps[s->lightmaptexturenum] + (s->light_t * BLOCK_WIDTH + s->light_s) * 4, BLOCK_WIDTH * 4);
+ R_BuildLightMap (s, lightmaps[s->lightmaptexturenum] + (s->light_t * BLOCK_WIDTH + s->light_s) * 4, BLOCK_WIDTH * 4, false);
else
- R_BuildLightMap (s, lightmaps[s->lightmaptexturenum] + (s->light_t * BLOCK_WIDTH + s->light_s) * 3, BLOCK_WIDTH * 3);
+ R_BuildLightMap (s, lightmaps[s->lightmaptexturenum] + (s->light_t * BLOCK_WIDTH + s->light_s) * 3, BLOCK_WIDTH * 3, false);
}
else
{
tmax = (s->extents[1]>>4)+1;
if (lightmaprgba)
{
- R_BuildLightMap (s, templight, smax * 4);
+ R_BuildLightMap (s, templight, smax * 4, false);
if(r_upload.value)
glTexSubImage2D(GL_TEXTURE_2D, 0, s->light_s, s->light_t, smax, tmax, GL_RGBA, GL_UNSIGNED_BYTE, templight);
}
else
{
- R_BuildLightMap (s, templight, smax * 3);
+ R_BuildLightMap (s, templight, smax * 3, false);
if(r_upload.value)
glTexSubImage2D(GL_TEXTURE_2D, 0, s->light_s, s->light_t, smax, tmax, GL_RGB , GL_UNSIGNED_BYTE, templight);
}
*/
texture_t *R_TextureAnimation (texture_t *base)
{
-// texture_t *original;
-// int relative;
-// int count;
+ if (currentrenderentity->frame && base->alternate_anims != NULL)
+ base = base->alternate_anims;
- if (currententity->render.frame)
- {
- if (base->alternate_anims)
- base = base->alternate_anims;
- }
-
- if (!base->anim_total)
+ if (base->anim_total < 2)
return base;
- return base->anim_frames[(int)(cl.time*5) % base->anim_total];
-
- /*
- original = base;
-
- relative = (int)(cl.time*5) % base->anim_total;
-
- count = 0;
- while (base->anim_min > relative || base->anim_max <= relative)
- {
- base = base->anim_next;
- if (!base)
- {
- Con_Printf("R_TextureAnimation: broken cycle");
- return original;
- }
- if (++count > 100)
- {
- Con_Printf("R_TextureAnimation: infinite cycle");
- return original;
- }
- }
-
- return base;
- */
+ return base->anim_frames[(int)(cl.time * 5.0f) % base->anim_total];
}
wallvertcolor_t *outcolor;
// check for lightmap modification
if (s->cached_dlight
- || (r_dynamic.value && r_dlightmap.value && s->dlightframe == r_framecount)
|| r_ambient.value != s->cached_ambient
|| lightscalebit != s->cached_lightscalebit
|| (r_dynamic.value
- && ((s->styles[0] != 255 && d_lightstylevalue[s->styles[0]] != s->cached_light[0])
- || (s->styles[1] != 255 && d_lightstylevalue[s->styles[1]] != s->cached_light[1])
- || (s->styles[2] != 255 && d_lightstylevalue[s->styles[2]] != s->cached_light[2])
- || (s->styles[3] != 255 && d_lightstylevalue[s->styles[3]] != s->cached_light[3]))))
- R_UpdateLightmap(s, s->lightmaptexturenum);
+ && (d_lightstylevalue[s->styles[0]] != s->cached_light[0]
+ || d_lightstylevalue[s->styles[1]] != s->cached_light[1]
+ || d_lightstylevalue[s->styles[2]] != s->cached_light[2]
+ || d_lightstylevalue[s->styles[3]] != s->cached_light[3])))
+ R_UpdateLightmap(s, s->lightmaptexturenum, false); // base lighting changed
+ else if (r_dynamic.value && r_dlightmap.value && s->dlightframe == r_framecount)
+ R_UpdateLightmap(s, s->lightmaptexturenum, true); // only dlights
+
if (s->dlightframe != r_framecount || r_dlightmap.value)
{
// LordHavoc: fast path version for no vertex lighting cases
- wp = &wallpoly[currentwallpoly];
out = &wallvert[currentwallvert];
for (p = s->polys;p;p = p->next)
{
if ((currentwallpoly >= MAX_WALLPOLYS) || (currentwallvert+p->numverts > MAX_WALLVERTS))
return;
+ wp = &wallpoly[currentwallpoly++];
wp->texnum = (unsigned short) R_GetTexture(t->texture);
wp->lighttexnum = (unsigned short) (lightmap_textures + s->lightmaptexturenum);
wp->glowtexnum = (unsigned short) R_GetTexture(t->glowtexture);
wp->numverts = p->numverts;
wp->lit = false;
wp++;
- currentwallpoly++;
currentwallvert += p->numverts;
v = p->verts[0];
if (transform)
float *v, *wv, scale;
glpoly_t *p;
byte *lm;
- alpha = (int) (modelalpha * 255.0f);
+ alpha = (int) (currentrenderentity->alpha * 255.0f);
size3 = ((s->extents[0]>>4)+1)*((s->extents[1]>>4)+1)*3; // *3 for colored lighting
wv = wvert;
for (p = s->polys;p;p = p->next)
if (s->dlightframe == r_framecount)
RSurf_Light(s->dlightbits, s->polys);
wv = wvert;
- if (isbmodel && (currententity->render.colormod[0] != 1 || currententity->render.colormod[1] != 1 || currententity->render.colormod[2] != 1))
+ if (alpha != 255 || currentrenderentity->colormod[0] != 1 || currentrenderentity->colormod[1] != 1 || currentrenderentity->colormod[2] != 1)
{
for (p = s->polys;p;p = p->next)
{
v = p->verts[0];
- transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currententity->render.effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
+ transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currentrenderentity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE, wv += 6)
- transpolyvert(wv[0], wv[1], wv[2], v[3], v[4], wv[3] * currententity->render.colormod[0], wv[4] * currententity->render.colormod[1], wv[5] * currententity->render.colormod[2], alpha);
+ transpolyvert(wv[0], wv[1], wv[2], v[3], v[4], wv[3] * currentrenderentity->colormod[0], wv[4] * currentrenderentity->colormod[1], wv[5] * currentrenderentity->colormod[2], alpha);
transpolyend();
}
}
for (p = s->polys;p;p = p->next)
{
v = p->verts[0];
- transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currententity->render.effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
+ transpolybegin(R_GetTexture(t->texture), R_GetTexture(t->glowtexture), 0, currentrenderentity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE, wv += 6)
transpolyvert(wv[0], wv[1], wv[2], v[3], v[4], wv[3], wv[4], wv[5], alpha);
transpolyend();
int vertexworld;
+// LordHavoc: disabled clipping on bmodels because they tend to intersect things sometimes
/*
void RBrushModelSurf_DoVisible(msurface_t *surf)
{
}
*/
+/*
void RBrushModelSurf_Callback(void *data, void *data2)
{
- entity_t *ent = data2;
msurface_t *surf = data;
texture_t *t;
+ currentrenderentity = data2;
+*/
/*
// FIXME: implement better dupe prevention in AddPolygon callback code
if (ent->render.model->firstmodelsurface != 0)
return;
}
*/
+/*
surf->visframe = r_framecount;
c_faces++;
- currententity = ent;
- modelalpha = ent->render.alpha;
-
- softwaretransformforbrushentity (ent);
+ softwaretransformforbrushentity (currentrenderentity);
if (surf->flags & (SURF_DRAWSKY | SURF_DRAWTURB))
{
else
{
t = R_TextureAnimation(surf->texinfo->texture);
- if (surf->texinfo->texture->transparent || vertexworld || ent->render.alpha != 1 || ent->render.model->firstmodelsurface == 0 || (ent->render.effects & EF_FULLBRIGHT) || ent->render.colormod[0] != 1 || ent->render.colormod[2] != 1 || ent->render.colormod[2] != 1)
+ if (t->transparent || vertexworld || ent->render.alpha != 1 || ent->render.model->firstmodelsurface == 0 || (ent->render.effects & EF_FULLBRIGHT) || ent->render.colormod[0] != 1 || ent->render.colormod[2] != 1 || ent->render.colormod[2] != 1)
RSurf_DrawWallVertex(surf, t, true, true);
else
RSurf_DrawWall(surf, t, true);
}
}
+*/
/*
=================
R_DrawBrushModel
=================
*/
-void R_DrawBrushModel (entity_t *e)
+void R_DrawBrushModel (void)
{
- int i, j, vertexlit;
- vec3_t mins, maxs;
+ int i/*, j*/, vertexlit, rotated, transform;
msurface_t *s;
- model_t *clmodel;
- int rotated;
- vec3_t org;
- glpoly_t *p;
-
- currententity = e;
-
- clmodel = e->render.model;
-
- if (e->render.angles[0] || e->render.angles[1] || e->render.angles[2])
- {
- rotated = true;
- for (i=0 ; i<3 ; i++)
- {
- mins[i] = e->render.origin[i] - clmodel->radius;
- maxs[i] = e->render.origin[i] + clmodel->radius;
- }
- }
- else
- {
- rotated = false;
- VectorAdd (e->render.origin, clmodel->mins, mins);
- VectorAdd (e->render.origin, clmodel->maxs, maxs);
- }
+ model_t *model;
+ vec3_t org, temp, forward, right, up;
+// glpoly_t *p;
+ texture_t *t;
- if (R_CullBox (mins, maxs))
- return;
+ model = currentrenderentity->model;
c_bmodels++;
- VectorSubtract (r_origin, e->render.origin, modelorg);
- if (rotated)
+ VectorSubtract (r_origin, currentrenderentity->origin, modelorg);
+ rotated = false;
+ transform = false;
+ if (currentrenderentity->angles[0] || currentrenderentity->angles[1] || currentrenderentity->angles[2])
{
- vec3_t temp;
- vec3_t forward, right, up;
-
+ transform = true;
+ rotated = true;
VectorCopy (modelorg, temp);
- AngleVectors (e->render.angles, forward, right, up);
+ AngleVectors (currentrenderentity->angles, forward, right, up);
modelorg[0] = DotProduct (temp, forward);
modelorg[1] = -DotProduct (temp, right);
modelorg[2] = DotProduct (temp, up);
}
+ else if (currentrenderentity->origin[0] || currentrenderentity->origin[1] || currentrenderentity->origin[2] || currentrenderentity->scale)
+ transform = true;
- softwaretransformforbrushentity (e);
+ if (transform)
+ softwaretransformforbrushentity (currentrenderentity);
- for (i = 0, s = &clmodel->surfaces[clmodel->firstmodelsurface];i < clmodel->nummodelsurfaces;i++, s++)
+ for (i = 0, s = &model->surfaces[model->firstmodelsurface];i < model->nummodelsurfaces;i++, s++)
{
s->visframe = -1;
if (((s->flags & SURF_PLANEBACK) == 0) == (PlaneDiff(modelorg, s->plane) >= 0))
if (!cl_dlights[i].radius)
continue;
- VectorSubtract(cl_dlights[i].origin, currententity->render.origin, org);
- R_NoVisMarkLights (org, &cl_dlights[i], 1<<(i&31), i >> 5, clmodel);
+ if (rotated)
+ {
+ VectorSubtract(cl_dlights[i].origin, currentrenderentity->origin, temp);
+ org[0] = DotProduct (temp, forward);
+ org[1] = -DotProduct (temp, right);
+ org[2] = DotProduct (temp, up);
+ }
+ else
+ VectorSubtract(cl_dlights[i].origin, currentrenderentity->origin, org);
+ R_NoVisMarkLights (org, &cl_dlights[i], 1<<(i&31), i >> 5, model);
}
- vertexlit = modelalpha != 1 || clmodel->firstmodelsurface == 0 || (currententity->render.effects & EF_FULLBRIGHT) || currententity->render.colormod[0] != 1 || currententity->render.colormod[2] != 1 || currententity->render.colormod[2] != 1;
+ vertexlit = vertexworld || currentrenderentity->alpha != 1 || model->firstmodelsurface == 0 || (currentrenderentity->effects & EF_FULLBRIGHT) || currentrenderentity->colormod[0] != 1 || currentrenderentity->colormod[2] != 1 || currentrenderentity->colormod[2] != 1;
// draw texture
- for (i = 0, s = &clmodel->surfaces[clmodel->firstmodelsurface];i < clmodel->nummodelsurfaces;i++, s++)
+ for (i = 0, s = &model->surfaces[model->firstmodelsurface];i < model->nummodelsurfaces;i++, s++)
{
if (s->visframe == r_framecount)
{
// R_DrawSurf(s, true, vertexlit || s->texinfo->texture->transparent);
+ /*
if (r_ser.value)
{
for (p = s->polys;p;p = p->next)
{
for (j = 0;j < p->numverts;j++)
softwaretransform(&p->verts[j][0], bmverts + j * 3);
- R_Clip_AddPolygon(bmverts, p->numverts, 3 * sizeof(float), (s->flags & SURF_CLIPSOLID) != 0 && modelalpha == 1, RBrushModelSurf_Callback, s, e, NULL);
+ R_Clip_AddPolygon(bmverts, p->numverts, 3 * sizeof(float), (s->flags & SURF_CLIPSOLID) != 0 && currentrenderentity->alpha == 1, RBrushModelSurf_Callback, s, e, NULL);
}
}
else
{
+ */
+ c_faces++;
+ t = R_TextureAnimation(s->texinfo->texture);
if (s->flags & (SURF_DRAWSKY | SURF_DRAWTURB))
{
// sky and liquid don't need sorting (skypoly/transpoly)
if (s->flags & SURF_DRAWSKY)
- RSurf_DrawSky(s, true);
+ RSurf_DrawSky(s, transform);
else
- RSurf_DrawWater(s, R_TextureAnimation(s->texinfo->texture), true, s->flags & SURF_DRAWNOALPHA ? 255 : wateralpha);
+ RSurf_DrawWater(s, t, transform, s->flags & SURF_DRAWNOALPHA ? 255 : wateralpha);
}
else
{
- texture_t *t = R_TextureAnimation(s->texinfo->texture);
- if (vertexlit || s->texinfo->texture->transparent)
- RSurf_DrawWallVertex(s, t, true, true);
+ if (t->transparent || vertexlit)
+ RSurf_DrawWallVertex(s, t, transform, true);
else
- RSurf_DrawWall(s, t, true);
+ RSurf_DrawWall(s, t, transform);
}
- }
+ //}
}
}
UploadLightmaps();
void R_SolidWorldNode (void)
{
- if ((int) r_solidworldnode.value == 3)
+ if (r_viewleaf->contents != CONTENTS_SOLID)
{
int portalstack;
mportal_t *p, *pstack[8192];
mleaf_t *leaf;
glpoly_t *poly;
tinyplane_t plane;
+ // LordHavoc: portal-passage worldnode; follows portals leading
+ // outward from viewleaf, if a portal leads offscreen it is not
+ // followed, in indoor maps this can often cull a great deal of
+ // geometry away when pvs data is not present (useful with pvs as well)
leaf = r_viewleaf;
leaf->worldnodeframe = r_framecount;
if (portalstack)
goto loc1;
}
- else if ((int) r_solidworldnode.value == 2)
+ else
{
mnode_t *nodestack[8192], *node = cl.worldmodel->nodes;
int nodestackpos = 0;
glpoly_t *poly;
+ // LordHavoc: recursive descending worldnode; if portals are not
+ // available, this is a good last resort, can cull large amounts of
+ // geometry, but is more time consuming than portal-passage and renders
+ // things behind walls
loc2:
if (R_NotCulledBox(node->mins, node->maxs))
{
- if (r_ser.value)
+ if (node->numsurfaces)
{
- if (node->numsurfaces)
+ if (r_ser.value)
{
msurface_t *surf = cl.worldmodel->surfaces + node->firstsurface, *surfend = surf + node->numsurfaces;
tinyplane_t plane;
}
}
}
- }
- else
- {
- if (node->numsurfaces)
+ else
{
msurface_t *surf = cl.worldmodel->surfaces + node->firstsurface, *surfend = surf + node->numsurfaces;
if (PlaneDiff (r_origin, node->plane) < 0)
goto loc2;
}
}
- else if ((int) r_solidworldnode.value == 1 && r_ser.value)
- {
- glpoly_t *poly;
- msurface_t *surf, *endsurf;
- tinyplane_t plane;
-
- surf = &cl.worldmodel->surfaces[cl.worldmodel->firstmodelsurface];
- endsurf = surf + cl.worldmodel->nummodelsurfaces;
- for (;surf < endsurf;surf++)
- {
- if (PlaneDiff(r_origin, surf->plane) < 0)
- {
- if (surf->flags & SURF_PLANEBACK)
- {
- VectorNegate(surf->plane->normal, plane.normal);
- plane.dist = -surf->plane->dist;
- for (poly = surf->polys;poly;poly = poly->next)
- R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane);
- }
- }
- else
- {
- if (!(surf->flags & SURF_PLANEBACK))
- for (poly = surf->polys;poly;poly = poly->next)
- R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)&surf->plane);
- }
- }
- }
- else
- {
- int l;
- mleaf_t *leaf;
- msurface_t *surf, **mark, **endmark;
- glpoly_t *poly;
- tinyplane_t plane;
-
- for (l = 0, leaf = cl.worldmodel->leafs;l < cl.worldmodel->numleafs;l++, leaf++)
- {
- if (R_CullBox(leaf->mins, leaf->maxs))
- continue;
- leaf->visframe = r_framecount;
- c_leafs++;
- if (leaf->nummarksurfaces)
- {
-// if (R_CullBox(leaf->mins, leaf->maxs))
-// continue;
-
- if (leaf->nummarksurfaces)
- {
- mark = leaf->firstmarksurface;
- endmark = mark + leaf->nummarksurfaces;
- if (r_ser.value)
- {
- do
- {
- surf = *mark++;
- // make sure surfaces are only processed once
- if (surf->worldnodeframe == r_framecount)
- continue;
- surf->worldnodeframe = r_framecount;
- if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
- {
- if (surf->flags & SURF_PLANEBACK)
- {
- VectorNegate(surf->plane->normal, plane.normal);
- plane.dist = -surf->plane->dist;
- for (poly = surf->polys;poly;poly = poly->next)
- R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane);
- }
- }
- else
- {
- if (!(surf->flags & SURF_PLANEBACK))
- for (poly = surf->polys;poly;poly = poly->next)
- R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane);
- }
- }
- while (mark < endmark);
- }
- else
- {
- do
- {
- surf = *mark++;
- // make sure surfaces are only processed once
- if (surf->worldnodeframe == r_framecount)
- continue;
- surf->worldnodeframe = r_framecount;
- if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
- {
- if (surf->flags & SURF_PLANEBACK)
- surf->visframe = r_framecount;
- }
- else
- {
- if (!(surf->flags & SURF_PLANEBACK))
- surf->visframe = r_framecount;
- }
- }
- while (mark < endmark);
- }
- }
- }
- }
- }
}
/*
void R_PVSWorldNode()
{
- if (r_pvsworldnode.value == 1)
- {
- int portalstack, i;
- mportal_t *p, *pstack[8192];
- msurface_t *surf, **mark, **endmark;
- mleaf_t *leaf;
- tinyplane_t plane;
- glpoly_t *poly;
- byte *worldvis;
+ int portalstack, i;
+ mportal_t *p, *pstack[8192];
+ msurface_t *surf, **mark, **endmark;
+ mleaf_t *leaf;
+ tinyplane_t plane;
+ glpoly_t *poly;
+ byte *worldvis;
- worldvis = Mod_LeafPVS (r_viewleaf, cl.worldmodel);
+ worldvis = Mod_LeafPVS (r_viewleaf, cl.worldmodel);
- leaf = r_viewleaf;
- leaf->worldnodeframe = r_framecount;
- portalstack = 0;
- loc0:
- c_leafs++;
+ leaf = r_viewleaf;
+ leaf->worldnodeframe = r_framecount;
+ portalstack = 0;
+loc0:
+ c_leafs++;
- leaf->visframe = r_framecount;
+ leaf->visframe = r_framecount;
- if (leaf->nummarksurfaces)
+ if (leaf->nummarksurfaces)
+ {
+ mark = leaf->firstmarksurface;
+ endmark = mark + leaf->nummarksurfaces;
+ if (r_ser.value)
{
- mark = leaf->firstmarksurface;
- endmark = mark + leaf->nummarksurfaces;
- if (r_ser.value)
+ do
{
- do
+ surf = *mark++;
+ // make sure surfaces are only processed once
+ if (surf->worldnodeframe == r_framecount)
+ continue;
+ surf->worldnodeframe = r_framecount;
+ if (PlaneDist(modelorg, surf->plane) < surf->plane->dist)
{
- surf = *mark++;
- // make sure surfaces are only processed once
- if (surf->worldnodeframe == r_framecount)
- continue;
- surf->worldnodeframe = r_framecount;
- if (PlaneDist(modelorg, surf->plane) < surf->plane->dist)
- {
- if (surf->flags & SURF_PLANEBACK)
- {
- VectorNegate(surf->plane->normal, plane.normal);
- plane.dist = -surf->plane->dist;
- for (poly = surf->polys;poly;poly = poly->next)
- R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane);
- }
- }
- else
+ if (surf->flags & SURF_PLANEBACK)
{
- if (!(surf->flags & SURF_PLANEBACK))
- for (poly = surf->polys;poly;poly = poly->next)
- R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane);
+ VectorNegate(surf->plane->normal, plane.normal);
+ plane.dist = -surf->plane->dist;
+ for (poly = surf->polys;poly;poly = poly->next)
+ R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane);
}
}
- while (mark < endmark);
- }
- else
- {
- do
+ else
{
- surf = *mark++;
- // make sure surfaces are only processed once
- if (surf->worldnodeframe == r_framecount)
- continue;
- surf->worldnodeframe = r_framecount;
- if (PlaneDist(modelorg, surf->plane) < surf->plane->dist)
- {
- if (surf->flags & SURF_PLANEBACK)
- surf->visframe = r_framecount;
- }
- else
- {
- if (!(surf->flags & SURF_PLANEBACK))
- surf->visframe = r_framecount;
- }
+ if (!(surf->flags & SURF_PLANEBACK))
+ for (poly = surf->polys;poly;poly = poly->next)
+ R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane);
}
- while (mark < endmark);
}
+ while (mark < endmark);
}
-
- // follow portals into other leafs
- p = leaf->portals;
- for (;p;p = p->next)
+ else
{
- if (DotProduct(r_origin, p->plane.normal) < p->plane.dist)
+ do
{
- leaf = p->past;
- if (leaf->worldnodeframe != r_framecount)
+ surf = *mark++;
+ // make sure surfaces are only processed once
+ if (surf->worldnodeframe == r_framecount)
+ continue;
+ surf->worldnodeframe = r_framecount;
+ if (PlaneDist(modelorg, surf->plane) < surf->plane->dist)
{
- leaf->worldnodeframe = r_framecount;
- if (leaf->contents != CONTENTS_SOLID)
- {
- i = (leaf - cl.worldmodel->leafs) - 1;
- if (worldvis[i>>3] & (1<<(i&7)))
- {
- if (R_NotCulledBox(leaf->mins, leaf->maxs))
- {
- pstack[portalstack++] = p;
- goto loc0;
-
- loc1:
- p = pstack[--portalstack];
- }
- }
- }
+ if (surf->flags & SURF_PLANEBACK)
+ surf->visframe = r_framecount;
+ }
+ else
+ {
+ if (!(surf->flags & SURF_PLANEBACK))
+ surf->visframe = r_framecount;
}
}
+ while (mark < endmark);
}
-
- if (portalstack)
- goto loc1;
}
- else
- {
- int i/*, l*/, k, c, row, numbits, bit, leafnum, numleafs;
- mleaf_t *leaf;
- msurface_t *surf, **mark, **endmark;
- model_t *model = cl.worldmodel;
- byte *in;
- // mportal_t *portal;
- glpoly_t *poly;
- tinyplane_t plane;
-
- // c_leafs++;
- // r_viewleaf->visframe = r_framecount;
- if (!r_testvis.value)
- r_portalframecount++;
- numleafs = model->numleafs;
- numbits = numleafs;
- k = 0;
- in = r_viewleaf->compressed_vis;
- row = (numbits + 7) >> 3;
- while (k < row)
+ // follow portals into other leafs
+ p = leaf->portals;
+ for (;p;p = p->next)
+ {
+ if (DotProduct(r_origin, p->plane.normal) < p->plane.dist)
{
- c = *in++;
- if (c)
+ leaf = p->past;
+ if (leaf->worldnodeframe != r_framecount)
{
- for (i = 0, bit = 1;c;i++, bit <<= 1)
+ leaf->worldnodeframe = r_framecount;
+ if (leaf->contents != CONTENTS_SOLID)
{
- if (c & bit)
+ i = (leaf - cl.worldmodel->leafs) - 1;
+ if (worldvis[i>>3] & (1<<(i&7)))
{
- leafnum = (k << 3)+i+1;
- if (leafnum > numleafs)
- return;
- c -= bit;
- leaf = &model->leafs[leafnum];
if (R_NotCulledBox(leaf->mins, leaf->maxs))
{
- //for (portal = leaf->portals;portal;portal = portal->next)
- // if (DotProduct(r_origin, portal->plane.normal) > portal->plane.dist)
- // R_Clip_AddPolygon((float *)portal->points, portal->numpoints, sizeof(mvertex_t), false, R_Portal_Callback, leaf, portal, portal->plane);
- //leaf->visframe = r_framecount;
- c_leafs++;
- if (leaf->nummarksurfaces)
- {
- mark = leaf->firstmarksurface;
- endmark = mark + leaf->nummarksurfaces;
- if (r_ser.value)
- {
- do
- {
- surf = *mark++;
- // make sure surfaces are only processed once
- if (surf->worldnodeframe == r_framecount)
- continue;
- surf->worldnodeframe = r_framecount;
- if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
- {
- if (surf->flags & SURF_PLANEBACK)
- {
- VectorNegate(surf->plane->normal, plane.normal);
- plane.dist = -surf->plane->dist;
- for (poly = surf->polys;poly;poly = poly->next)
- R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane);
- }
- }
- else
- {
- if (!(surf->flags & SURF_PLANEBACK))
- for (poly = surf->polys;poly;poly = poly->next)
- R_Clip_AddPolygon((float *)poly->verts, poly->numverts, VERTEXSIZE * sizeof(float), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane);
- }
- }
- while (mark < endmark);
- }
- else
- {
- do
- {
- surf = *mark++;
- // make sure surfaces are only processed once
- if (surf->worldnodeframe == r_framecount)
- continue;
- surf->worldnodeframe = r_framecount;
- if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
- {
- if (surf->flags & SURF_PLANEBACK)
- surf->visframe = r_framecount;
- }
- else
- {
- if (!(surf->flags & SURF_PLANEBACK))
- surf->visframe = r_framecount;
- }
- }
- while (mark < endmark);
- }
- }
+ pstack[portalstack++] = p;
+ goto loc0;
+
+loc1:
+ p = pstack[--portalstack];
}
}
}
- k++;
}
- else
- k += *in++;
}
}
+
+ if (portalstack)
+ goto loc1;
}
entity_t clworldent;
texture_t *t, *currentt;
int vertex = gl_vertex.value;
- currententity = &clworldent;
- modelalpha = 1;
+ currentrenderentity = &clworldent.render;
softwaretransformidentity();
surf = &cl.worldmodel->surfaces[cl.worldmodel->firstmodelsurface];
endsurf = surf + cl.worldmodel->nummodelsurfaces;
}
}
+void R_SetupWorldEnt(void)
+{
+ memset (&clworldent, 0, sizeof(clworldent));
+ clworldent.render.model = cl.worldmodel;
+ clworldent.render.colormod[0] = clworldent.render.colormod[1] = clworldent.render.colormod[2] = 1;
+ clworldent.render.alpha = 1;
+ clworldent.render.scale = 1;
+
+ VectorCopy (r_origin, modelorg);
+
+ currentrenderentity = &clworldent.render;
+}
+
/*
=============
R_DrawWorld
wateralpha = bound(0, r_wateralpha.value*255.0f, 255);
vertexworld = gl_vertex.value;
- memset (&clworldent, 0, sizeof(clworldent));
- clworldent.render.model = cl.worldmodel;
- clworldent.render.colormod[0] = clworldent.render.colormod[1] = clworldent.render.colormod[2] = 1;
- modelalpha = clworldent.render.alpha = 1;
- clworldent.render.scale = 1;
-
- VectorCopy (r_origin, modelorg);
-
- currententity = &clworldent;
+ R_SetupWorldEnt();
softwaretransformidentity(); // LordHavoc: clear transform
- if (cl.worldmodel)
- {
- if (r_novis.value || r_viewleaf->compressed_vis == NULL)
- R_SolidWorldNode ();
- else
- {
-// R_MarkLeaves ();
- R_PVSWorldNode ();
- }
- }
+ if (r_viewleaf->contents == CONTENTS_SOLID || r_novis.value || r_viewleaf->compressed_vis == NULL)
+ R_SolidWorldNode ();
+ else
+ R_PVSWorldNode ();
}
/*
{
best = BLOCK_HEIGHT;
- for (i = 0;i < BLOCK_WIDTH - w;i += lightmapalign) // LordHavoc: NVIDIA has broken subimage, so align the lightmaps
+ for (i = 0;i < BLOCK_WIDTH - w;i += lightmapalign) // LordHavoc: align updates on 4 byte boundaries
{
best2 = 0;
// LordHavoc: clear texture to blank image, fragments are uploaded using subimage
else if (!allocated[texnum][0])
{
- byte blank[BLOCK_WIDTH*BLOCK_HEIGHT*4];
- memset(blank, 0, sizeof(blank));
+ memset(templight, 0, sizeof(templight));
if(r_upload.value)
{
glBindTexture(GL_TEXTURE_2D, lightmap_textures + texnum);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (lightmaprgba)
- glTexImage2D (GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, blank);
+ glTexImage2D (GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, templight);
else
- glTexImage2D (GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, blank);
+ glTexImage2D (GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, templight);
}
}
smax = ((surf->extents[0]>>4)+lightmapalign) & lightmapalignmask;
if (lightmaprgba)
{
- R_BuildLightMap (surf, templight, smax * 4);
+ R_BuildLightMap (surf, templight, smax * 4, false);
if(r_upload.value)
glTexSubImage2D(GL_TEXTURE_2D, 0, surf->light_s, surf->light_t, smax, tmax, GL_RGBA, GL_UNSIGNED_BYTE, templight);
}
else
{
- R_BuildLightMap (surf, templight, smax * 3);
+ R_BuildLightMap (surf, templight, smax * 3, false);
if(r_upload.value)
glTexSubImage2D(GL_TEXTURE_2D, 0, surf->light_s, surf->light_t, smax, tmax, GL_RGB , GL_UNSIGNED_BYTE, templight);
}
lightmapbytes = 3;
}
- // LordHavoc: NVIDIA seems to have a broken glTexSubImage2D,
- // it needs to be aligned on 4 pixel boundaries...
- // so I implemented an adjustable lightmap alignment
- if (gl_lightmapalign.value < 1)
- gl_lightmapalign.value = 1;
- if (gl_lightmapalign.value > 16)
- gl_lightmapalign.value = 16;
+ // LordHavoc: TexSubImage2D needs data aligned on 4 byte boundaries unless
+ // I specify glPixelStorei(GL_UNPACK_ALIGNMENT, 1), I suspect 4 byte may be
+ // faster anyway, so I implemented an adjustable lightmap alignment...
+
+ // validate the lightmap alignment
+ i = 1;
+ while (i < 16 && i < gl_lightmapalign.value)
+ i <<= 1;
+ Cvar_SetValue("gl_lightmapalign", i);
+
+ // find the lowest pixel count which satisfies the byte alignment
lightmapalign = 1;
- while (lightmapalign < gl_lightmapalign.value)
+ j = lightmaprgba ? 4 : 3; // bytes per pixel
+ while ((lightmapalign * j) & (i - 1))
lightmapalign <<= 1;
- gl_lightmapalign.value = lightmapalign;
lightmapalignmask = ~(lightmapalign - 1);
+
+ // alignment is irrelevant if using fallback modes
if (nosubimagefragments || nosubimage)
{
lightmapalign = 1;
if (!lightmap_textures)
lightmap_textures = R_GetTextureSlots(MAX_LIGHTMAPS);
+ // need a world entity for lightmap code
+ R_SetupWorldEnt();
+
for (j=1 ; j<MAX_MODELS ; j++)
{
m = cl.model_precache[j];
*/
-int glx, gly, glwidth, glheight;
-
float scr_con_current;
float scr_conlines; // lines of console to display
start = scr_centerstring;
if (scr_center_lines <= 4)
- y = vid.height*0.35;
+ y = vid.conheight*0.35;
else
y = 48;
for (l=0 ; l<40 ; l++)
if (start[l] == '\n' || !start[l])
break;
- x = (vid.width - l*8)/2;
+ x = (vid.conwidth - l*8)/2;
// LordHavoc: speedup
if (l > 0)
{
*/
float CalcFov (float fov_x, float width, float height)
{
- float a;
- float x;
-
- if (fov_x < 1 || fov_x > 179)
- Sys_Error ("Bad fov: %f", fov_x);
-
- x = width/tan(fov_x/360*M_PI);
-
- a = atan (height/x);
-
- a = a*360/M_PI;
-
- return a;
+ // calculate vision size and alter by aspect, then convert back to angle
+ return atan (height / (width / tan(fov_x/360*M_PI))) * 360 / M_PI;
}
/*
*/
static void SCR_CalcRefdef (void)
{
- float size;
- int h;
- qboolean full = false;
-
+ float size;
- vid.recalc_refdef = 0;
+// vid.recalc_refdef = 0;
//========================================
-
+
// bound viewsize
if (scr_viewsize.value < 30)
Cvar_Set ("viewsize","30");
// intermission is always full screen
if (cl.intermission)
{
- full = true;
size = 1;
sb_lines = 0;
}
sb_lines = 24; // no inventory
else
sb_lines = 24+16+8;
-
- if (scr_viewsize.value >= 100.0)
- {
- full = true;
- size = 1.0f;
- }
- else
- size = scr_viewsize.value * (1.0f / 100.0f);
+ size = scr_viewsize.value * (1.0 / 100.0);
}
- // LordHavoc: always fullscreen rendering
- h = vid.height/* - sb_lines*/;
-
- r_refdef.vrect.width = vid.width * size;
- if (r_refdef.vrect.width < 96)
+ if (size >= 1)
{
- size = 96.0 / r_refdef.vrect.width;
- r_refdef.vrect.width = 96; // min for icons
+ r_refdef.width = vid.realwidth;
+ r_refdef.height = vid.realheight;
+ r_refdef.x = 0;
+ r_refdef.y = 0;
}
-
- r_refdef.vrect.height = vid.height * size;
- //if (r_refdef.vrect.height > vid.height - sb_lines)
- // r_refdef.vrect.height = vid.height - sb_lines;
- if (r_refdef.vrect.height > (int) vid.height)
- r_refdef.vrect.height = vid.height;
- r_refdef.vrect.x = (vid.width - r_refdef.vrect.width)/2;
- if (full)
- r_refdef.vrect.y = 0;
else
- r_refdef.vrect.y = (h - r_refdef.vrect.height)/2;
+ {
+ r_refdef.width = vid.realwidth * size;
+ r_refdef.height = vid.realheight * size;
+ r_refdef.x = (vid.realwidth - r_refdef.width)/2;
+ r_refdef.y = (vid.realheight - r_refdef.height)/2;
+ }
r_refdef.fov_x = scr_fov.value;
- r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height);
+ r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.width, r_refdef.height);
+
+ r_refdef.width = bound(0, r_refdef.width, vid.realwidth);
+ r_refdef.height = bound(0, r_refdef.height, vid.realheight);
+ r_refdef.x = bound(0, r_refdef.x, vid.realwidth) + vid.realx;
+ r_refdef.y = bound(0, r_refdef.y, vid.realheight) + vid.realy;
}
void SCR_SizeUp_f (void)
{
Cvar_SetValue ("viewsize",scr_viewsize.value+10);
- vid.recalc_refdef = 1;
+// vid.recalc_refdef = 1;
}
void SCR_SizeDown_f (void)
{
Cvar_SetValue ("viewsize",scr_viewsize.value-10);
- vid.recalc_refdef = 1;
+// vid.recalc_refdef = 1;
}
//============================================================================
*/
void SCR_DrawRam (void)
{
- if (!scr_showram.value)
- return;
-
- if (!r_cache_thrash)
- return;
-
- Draw_Pic (32, 0, scr_ram);
+// if (!scr_showram.value)
+// return;
+// Draw_Pic (32, 0, scr_ram);
}
/*
return;
pic = Draw_CachePic ("gfx/pause.lmp");
- Draw_Pic ( (vid.width - pic->width)/2,
- (vid.height - 48 - pic->height)/2, pic);
+ Draw_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, pic);
}
return;
pic = Draw_CachePic ("gfx/loading.lmp");
- Draw_Pic ( (vid.width - pic->width)/2,
- (vid.height - 48 - pic->height)/2, pic);
+ Draw_Pic ((vid.conwidth - pic->width)/2, (vid.conheight - pic->height)/2, pic);
}
*/
if (con_forcedup)
{
- scr_conlines = vid.height; // full screen
+ scr_conlines = vid.conheight; // full screen
scr_con_current = scr_conlines;
}
else if (key_dest == key_console)
- scr_conlines = vid.height/2; // half screen
+ scr_conlines = vid.conheight/2; // half screen
else
scr_conlines = 0; // none visible
-
+
if (scr_conlines < scr_con_current)
{
scr_con_current -= scr_conspeed.value*host_realframetime;
scr_con_current = scr_conlines;
}
}
-
+
/*
==================
SCR_DrawConsole
/*
==============================================================================
-
+
SCREEN SHOTS
==============================================================================
*/
/*
-==================
+==================
SCR_ScreenShot_f
-==================
+==================
*/
-void SCR_ScreenShot_f (void)
+void SCR_ScreenShot_f (void)
{
- byte *buffer;
- char filename[80];
+ byte *buffer, gamma[256];
+ char filename[80];
char checkname[MAX_OSPATH];
int i;
//
-// find a file name to save it to
-//
+// find a file name to save it to
+//
strcpy(filename,"dp0000.tga");
-
- for (i=0 ; i<=9999 ; i++)
- {
- filename[2] = (i/1000)%10 + '0';
- filename[3] = (i/ 100)%10 + '0';
- filename[4] = (i/ 10)%10 + '0';
+
+ for (i=0 ; i<=9999 ; i++)
+ {
+ filename[2] = (i/1000)%10 + '0';
+ filename[3] = (i/ 100)%10 + '0';
+ filename[4] = (i/ 10)%10 + '0';
filename[5] = (i/ 1)%10 + '0';
sprintf (checkname, "%s/%s", com_gamedir, filename);
if (Sys_FileTime(checkname) == -1)
}
if (i==10000)
{
- Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n");
+ Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n");
return;
}
- buffer = qmalloc(glwidth*glheight*3);
- glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, buffer);
- Image_WriteTGARGB_preflipped(filename, glwidth, glheight, buffer);
+ buffer = qmalloc(vid.realwidth*vid.realheight*3);
+ glReadPixels (vid.realx, vid.realy, vid.realwidth, vid.realheight, GL_RGB, GL_UNSIGNED_BYTE, buffer);
+
+ // apply hardware gamma to the image
+ BuildGammaTable8((lighthalf && hardwaregammasupported) ? 2.0f : 1.0f, 1, 1, 0, gamma);
+ Image_GammaRemapRGB(buffer, buffer, vid.realwidth*vid.realheight, gamma, gamma, gamma);
+
+ Image_WriteTGARGB_preflipped(filename, vid.realwidth, vid.realheight, buffer);
qfree(buffer);
Con_Printf ("Wrote %s\n", filename);
// return;
// if (cls.signon != SIGNONS)
// return;
-
+
// redraw with no console and the loading plaque
// Con_ClearNotify ();
// scr_centertime_off = 0;
start = scr_notifystring;
- y = vid.height*0.35;
+ y = vid.conheight*0.35;
do
{
for (l=0 ; l<40 ; l++)
if (start[l] == '\n' || !start[l])
break;
- x = (vid.width - l*8)/2;
+ x = (vid.conwidth - l*8)/2;
// LordHavoc: speedup
// for (j=0 ; j<l ; j++, x+=8)
// Draw_Character (x, y, start[j]);
return; // not initialized yet
- GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
+ GL_BeginRendering (&vid.realx, &vid.realy, &vid.realwidth, &vid.realheight);
if (gl_combine.value && !gl_combine_extension)
Cvar_SetValue("gl_combine", false);
if (oldfov != scr_fov.value)
{
oldfov = scr_fov.value;
- vid.recalc_refdef = true;
+// vid.recalc_refdef = true;
}
if (oldscreensize != scr_viewsize.value)
{
oldscreensize = scr_viewsize.value;
- vid.recalc_refdef = true;
+// vid.recalc_refdef = true;
}
- if (vid.recalc_refdef)
+// if (vid.recalc_refdef)
SCR_CalcRefdef();
if (r_render.value)
calc = (int) ((1.0 / (newtime - currtime)) + 0.5);
sprintf(temp, "%4i fps", calc);
currtime = newtime;
- Draw_String(vid.width - (8*8), vid.height - sb_lines - 8, temp, 9999);
+ Draw_String(vid.conwidth - (8*8), vid.conheight - sb_lines - 8, temp, 9999);
}
- // LordHavoc: only print info if renderer is being used
- if (r_speeds2.value && !con_forcedup)
+ if (r_speeds2.value && r_speeds2_string[0])
{
int i, j, lines, y;
lines = 1;
for (i = 0;r_speeds2_string[i];i++)
if (r_speeds2_string[i] == '\n')
lines++;
- y = vid.height - sb_lines - lines * 8 - 8;
+ y = vid.conheight - sb_lines - lines * 8 - 8;
i = j = 0;
while (r_speeds2_string[i])
{
i++;
y += 8;
}
+ // clear so it won't reprint without renderer being called again
+ r_speeds2_string[0] = 0;
}
V_UpdateBlends();
extern glvert_t glv;
-extern int glx, gly, glwidth, glheight;
-
-// r_local.h -- private refresh defs
-
-#define ALIAS_BASE_SIZE_RATIO (1.0 / 11.0)
- // normalizing factor so player model works out to about
- // 1 pixel per triangle
-#define MAX_LBM_HEIGHT 480
-
-#define BACKFACE_EPSILON 0.01
-
-
-extern void R_TimeRefresh_f (void);
-
//====================================================
-
-extern qboolean r_cache_thrash; // compatability
-extern vec3_t modelorg, r_entorigin;
-extern entity_t *currententity;
-extern int r_framecount;
-extern mplane_t frustum[4];
-extern int c_brush_polys, c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights;
-
-
-//
-// view origin
-//
-extern vec3_t vup;
-extern vec3_t vpn;
-extern vec3_t vright;
-extern vec3_t r_origin;
-
-//
-// screen size info
-//
-extern refdef_t r_refdef;
-extern mleaf_t *r_viewleaf, *r_oldviewleaf;
-extern unsigned short d_lightstylevalue[256]; // 8.8 fraction of base light value
-
-extern qboolean envmap;
-
-extern cvar_t r_drawentities;
-extern cvar_t r_drawviewmodel;
-extern cvar_t r_speeds;
-extern cvar_t r_fullbright;
-extern cvar_t r_wateralpha;
-extern cvar_t r_dynamic;
-extern cvar_t r_waterripple;
-
-extern float r_world_matrix[16];
-
extern const char *gl_vendor;
extern const char *gl_renderer;
extern const char *gl_version;
void Host_Init (void)
{
int i;
- /*
- if (standard_quake)
- minimum_memory = MINIMUM_MEMORY;
- else
- minimum_memory = MINIMUM_MEMORY_LEVELPAK;
-
- if (COM_CheckParm ("-minmemory"))
- host_parms.memsize = minimum_memory;
-
- if (host_parms.memsize < minimum_memory)
- Sys_Error ("Only %4.1f megs of memory available, can't execute game", host_parms.memsize / (float)0x100000);
- */
host_parms.memsize = DEFAULTMEM * 1024 * 1024;
}
*/
CL_Disconnect ();
- Host_ShutdownServer(false);
+ Host_ShutdownServer(false);
Sys_Quit ();
}
int hours = 0;
int j;
void (*print) (char *fmt, ...);
-
+
if (cmd_source == src_command)
{
if (!sv.active)
print = SV_ClientPrintf;
print ("host: %s\n", Cvar_VariableString ("hostname"));
- print ("version: %4.2f (build %i)\n", VERSION, buildnumber);
+ print ("version: %s build %i\n", gamename, buildnumber);
if (tcpipAvailable)
print ("tcp/ip: %s\n", my_tcpip_address);
if (ipxAvailable)
void Host_Version_f (void)
{
- Con_Printf ("Version %4.2f (build %i)\n", VERSION, buildnumber);
+ Con_Printf ("Version: %s build %i\n", gamename, buildnumber);
Con_Printf ("Exe: "__TIME__" "__DATE__"\n");
}
t = Cmd_Argv(1);
v = atoi (Cmd_Argv(2));
-
+
switch (t[0])
{
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- // MED 01/04/97 added hipnotic give stuff
- if (hipnotic)
- {
- if (t[0] == '6')
- {
- if (t[1] == 'a')
- sv_player->v.items = (int)sv_player->v.items | HIT_PROXIMITY_GUN;
- else
- sv_player->v.items = (int)sv_player->v.items | IT_GRENADE_LAUNCHER;
- }
- else if (t[0] == '9')
- sv_player->v.items = (int)sv_player->v.items | HIT_LASER_CANNON;
- else if (t[0] == '0')
- sv_player->v.items = (int)sv_player->v.items | HIT_MJOLNIR;
- else if (t[0] >= '2')
- sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2'));
- }
- else
- {
- if (t[0] >= '2')
- sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2'));
- }
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ // MED 01/04/97 added hipnotic give stuff
+ if (gamemode == GAME_HIPNOTIC)
+ {
+ if (t[0] == '6')
+ {
+ if (t[1] == 'a')
+ sv_player->v.items = (int)sv_player->v.items | HIT_PROXIMITY_GUN;
+ else
+ sv_player->v.items = (int)sv_player->v.items | IT_GRENADE_LAUNCHER;
+ }
+ else if (t[0] == '9')
+ sv_player->v.items = (int)sv_player->v.items | HIT_LASER_CANNON;
+ else if (t[0] == '0')
+ sv_player->v.items = (int)sv_player->v.items | HIT_MJOLNIR;
+ else if (t[0] >= '2')
+ sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2'));
+ }
+ else
+ {
+ if (t[0] >= '2')
+ sv_player->v.items = (int)sv_player->v.items | (IT_SHOTGUN << (t[0] - '2'));
+ }
break;
-
- case 's':
- if (rogue)
+
+ case 's':
+ if (gamemode == GAME_ROGUE)
{
- if ((val = GETEDICTFIELDVALUE(sv_player, eval_ammo_shells1)))
- val->_float = v;
+ if ((val = GETEDICTFIELDVALUE(sv_player, eval_ammo_shells1)))
+ val->_float = v;
}
- sv_player->v.ammo_shells = v;
- break;
- case 'n':
- if (rogue)
+ sv_player->v.ammo_shells = v;
+ break;
+ case 'n':
+ if (gamemode == GAME_ROGUE)
{
- if ((val = GETEDICTFIELDVALUE(sv_player, eval_ammo_nails1)))
+ if ((val = GETEDICTFIELDVALUE(sv_player, eval_ammo_nails1)))
{
- val->_float = v;
+ val->_float = v;
if (sv_player->v.weapon <= IT_LIGHTNING)
sv_player->v.ammo_nails = v;
}
{
sv_player->v.ammo_nails = v;
}
- break;
- case 'l':
- if (rogue)
+ break;
+ case 'l':
+ if (gamemode == GAME_ROGUE)
{
val = GETEDICTFIELDVALUE(sv_player, eval_ammo_lava_nails);
if (val)
sv_player->v.ammo_nails = v;
}
}
- break;
- case 'r':
- if (rogue)
+ break;
+ case 'r':
+ if (gamemode == GAME_ROGUE)
{
val = GETEDICTFIELDVALUE(sv_player, eval_ammo_rockets1);
if (val)
{
sv_player->v.ammo_rockets = v;
}
- break;
- case 'm':
- if (rogue)
+ break;
+ case 'm':
+ if (gamemode == GAME_ROGUE)
{
val = GETEDICTFIELDVALUE(sv_player, eval_ammo_multi_rockets);
if (val)
sv_player->v.ammo_rockets = v;
}
}
- break;
- case 'h':
- sv_player->v.health = v;
- break;
- case 'c':
- if (rogue)
+ break;
+ case 'h':
+ sv_player->v.health = v;
+ break;
+ case 'c':
+ if (gamemode == GAME_ROGUE)
{
val = GETEDICTFIELDVALUE(sv_player, eval_ammo_cells1);
if (val)
{
sv_player->v.ammo_cells = v;
}
- break;
- case 'p':
- if (rogue)
+ break;
+ case 'p':
+ if (gamemode == GAME_ROGUE)
{
val = GETEDICTFIELDVALUE(sv_player, eval_ammo_plasma);
if (val)
sv_player->v.ammo_cells = v;
}
}
- break;
- }
+ break;
+ }
}
edict_t *FindViewthing (void)
{
int i;
edict_t *e;
-
+
for (i=0 ; i<sv.num_edicts ; i++)
{
e = EDICT_NUM(i);
void PrintFrameName (model_t *m, int frame)
{
int data;
- data = (int) Mod_Extradata(m);
- if (m->ofs_scenes && data)
+ if (m->ofs_scenes && (data = (int) Mod_Extradata(m)))
Con_Printf("frame %i: %s\n", frame, ((animscene_t *) (m->ofs_scenes + data))[frame].name);
else
Con_Printf("frame %i\n", frame);
{
Cmd_AddCommand ("status", Host_Status_f);
Cmd_AddCommand ("quit", Host_Quit_f);
- if (nehahra)
+ if (gamemode == GAME_NEHAHRA)
{
Cmd_AddCommand ("max", Host_God_f);
Cmd_AddCommand ("monster", Host_Notarget_f);
int image_width;
int image_height;
+void Image_GammaRemapRGB(byte *in, byte *out, int pixels, byte *gammar, byte *gammag, byte *gammab)
+{
+ while (pixels--)
+ {
+ out[0] = gammar[in[0]];
+ out[1] = gammag[in[1]];
+ out[2] = gammab[in[2]];
+ in += 3;
+ out += 3;
+ }
+}
+
// note: pal must be 32bit color
void Image_Copy8bitRGBA(byte *in, byte *out, int pixels, int *pal)
{
+void Image_GammaRemapRGB(byte *in, byte *out, int pixels, byte *gammar, byte *gammag, byte *gammab);
void Image_Copy8bitRGBA(byte *in, byte *out, int pixels, int *pal);
void Image_CopyRGBAGamma(byte *in, byte *out, int pixels);
int image_makemask (byte *in, byte *out, int size);
if (key == K_PGUP || key==K_MWHEELUP)
{
con_backscroll += 2;
- if (con_backscroll > con_totallines - (vid.height>>3) - 1)
- con_backscroll = con_totallines - (vid.height>>3) - 1;
+ if (con_backscroll > con_totallines - (vid.conheight>>3) - 1)
+ con_backscroll = con_totallines - (vid.conheight>>3) - 1;
return;
}
if (key == K_HOME)
{
- con_backscroll = con_totallines - (vid.height>>3) - 1;
+ con_backscroll = con_totallines - (vid.conheight>>3) - 1;
return;
}
#SND=snd_oss.o
#SOUNDLIB=
-OBJECTS= buildnumber.o cd_linux.o chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_tent.o cmd.o common.o console.o crc.o cvar.o fractalnoise.o gl_draw.o gl_poly.o gl_rmain.o gl_rmisc.o gl_rsurf.o gl_screen.o gl_warp.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_udp.o net_dgrm.o net_loop.o net_main.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_part.o r_explosion.o sbar.o snd_dma.o snd_mem.o snd_mix.o $(SND) sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o sys_linux.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o r_explosion.o r_lerpanim.o cl_effects.o r_decals.o protocol.o quakeio.o r_clip.o ui.o portals.o sys_shared.o
+OBJECTS= buildnumber.o cd_linux.o chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_tent.o cmd.o common.o console.o crc.o cvar.o fractalnoise.o gl_draw.o gl_poly.o gl_rmain.o gl_rmisc.o gl_rsurf.o gl_screen.o gl_warp.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_udp.o net_dgrm.o net_loop.o net_main.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_part.o r_explosion.o sbar.o snd_dma.o snd_mem.o snd_mix.o $(SND) sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o sys_linux.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o r_explosion.o r_lerpanim.o cl_effects.o r_decals.o protocol.o quakeio.o r_clip.o ui.o portals.o sys_shared.o cl_light.o
#K6/athlon optimizations
CPUOPTIMIZATIONS=-march=k6
LDFLAGS= -L/usr/X11R6/lib -lm -lX11 -lXext -lXIE -lXxf86dga -lXxf86vm -lGL -ldl $(SOUNDLIB) -lz $(PROFILEOPTION)
#most people can't build the -3dfx version (-3dfx version needs some updates for new mesa)
-all: darkplaces-glx
+all: buildnum darkplaces-glx
#all: darkplaces-glx darkplaces-3dfx
+buildnum/buildnum:
+ cd buildnum
+ make
+ cd ..
+
+buildnum: buildnum/buildnum
+ buildnum/buildnum buildnumber.c
+
.c.o:
gcc $(CFLAGS) -c $*.c
-rm -f darkplaces-glx darkplaces-3dfx
-rm -f vid_glx.o in_svgalib.o vid_3dfxsvga.o $(OBJECTS) *.d
-.PHONY: clean
+.PHONY: clean buildnum
-include *.d
return 1;
}
-void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
+void VectorMASlow (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
{
vecc[0] = veca[0] + scale*vecb[0];
vecc[1] = veca[1] + scale*vecb[1];
#define VectorDistance(a, b) (sqrt(VectorDistance2(a,b)))
#define VectorLength(a) sqrt(DotProduct(a, a))
#define VectorScale(in, scale, out) {(out)[0] = (in)[0] * (scale);(out)[1] = (in)[1] * (scale);(out)[2] = (in)[2] * (scale);}
-#define VectorMAQuick(a, scale, b, c) {(c)[0] = (a)[0] + (scale) * (b)[0];(c)[1] = (a)[1] + (scale) * (b)[1];(c)[2] = (a)[2] + (scale) * (b)[2];}
+#define VectorMA(a, scale, b, c) {(c)[0] = (a)[0] + (scale) * (b)[0];(c)[1] = (a)[1] + (scale) * (b)[1];(c)[2] = (a)[2] + (scale) * (b)[2];}
#define VectorNormalizeFast(_v)\
{\
float _y, _number;\
_y = _y * (1.5f - (_number * 0.5f * _y * _y));\
VectorScale(_v, _y, _v);\
}\
-}\
+}
+#define VectorRandom(v) {do{(v)[0] = lhrandom(-1, 1);(v)[1] = lhrandom(-1, 1);(v)[2] = lhrandom(-1, 1);}while(DotProduct(v, v) > 1);}
-void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc);
+void VectorMASlow (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc);
vec_t _DotProduct (vec3_t v1, vec3_t v2);
void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out);
{
double normal[3], dist;
} tinydoubleplane_t;
+
+void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees );
*/
void M_DrawCharacter (int cx, int line, int num)
{
- Draw_Character ( cx + ((vid.width - 320)>>1), line, num);
+ Draw_Character ( cx + ((vid.conwidth - 320)>>1), line, num);
}
void M_Print (int cx, int cy, char *str)
void M_DrawPic (int x, int y, qpic_t *pic)
{
- Draw_Pic (x + ((vid.width - 320)>>1), y, pic);
+ Draw_Pic (x + ((vid.conwidth - 320)>>1), y, pic);
}
byte identityTable[256];
void M_DrawPicTranslate (int x, int y, qpic_t *pic)
{
- Draw_PicTranslate (x + ((vid.width - 320)>>1), y, pic, translationTable);
+ Draw_PicTranslate (x + ((vid.conwidth - 320)>>1), y, pic, translationTable);
}
void M_Menu_Main_f (void)
{
- if (nehahra)
+ if (gamemode == GAME_NEHAHRA)
{
if (NehGameType == TYPE_DEMO)
MAIN_ITEMS = 4;
p = Draw_CachePic ("gfx/ttl_main.lmp");
M_DrawPic ( (320-p->width)/2, 4, p);
// Nehahra
- if (nehahra)
+ if (gamemode == GAME_NEHAHRA)
{
if (NehGameType == TYPE_BOTH)
M_DrawPic (72, 32, Draw_CachePic ("gfx/mainmenu.lmp"));
case K_ENTER:
m_entersound = true;
- if (nehahra)
+ if (gamemode == GAME_NEHAHRA)
{
switch (NehGameType)
{
if (sv.active)
Cbuf_AddText ("disconnect\n");
Cbuf_AddText ("maxplayers 1\n");
- if (nehahra)
+ if (gamemode == GAME_NEHAHRA)
Cbuf_AddText ("map nehstart\n");
else
Cbuf_AddText ("map start\n");
" this game just like ",
" everything else? ",
" ",
-
+
" Milord, methinks that ",
" thou art a lowly ",
" quitter. Is this true? ",
M_Print (160, 64, "Deathmatch");
M_Print (0, 72, " Teamplay");
- if (rogue)
+ if (gamemode == GAME_ROGUE)
{
char *msg;
M_Print (160, 96, va("%i minutes", (int)timelimit.value));
M_Print (0, 112, " Episode");
- //MED 01/06/97 added hipnotic episodes
- if (hipnotic)
- M_Print (160, 112, hipnoticepisodes[startepisode].description);
- //PGM 01/07/97 added rogue episodes
- else if (rogue)
- M_Print (160, 112, rogueepisodes[startepisode].description);
- else if (nehahra)
- M_Print (160, 112, nehahraepisodes[startepisode].description);
- else
- M_Print (160, 112, episodes[startepisode].description);
+ //MED 01/06/97 added hipnotic episodes
+ if (gamemode == GAME_HIPNOTIC)
+ M_Print (160, 112, hipnoticepisodes[startepisode].description);
+ //PGM 01/07/97 added rogue episodes
+ else if (gamemode == GAME_ROGUE)
+ M_Print (160, 112, rogueepisodes[startepisode].description);
+ else if (gamemode == GAME_NEHAHRA)
+ M_Print (160, 112, nehahraepisodes[startepisode].description);
+ else
+ M_Print (160, 112, episodes[startepisode].description);
M_Print (0, 120, " Level");
- //MED 01/06/97 added hipnotic episodes
- if (hipnotic)
- {
- M_Print (160, 120, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].description);
- M_Print (160, 128, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].name);
- }
- //PGM 01/07/97 added rogue episodes
- else if (rogue)
- {
- M_Print (160, 120, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].description);
- M_Print (160, 128, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].name);
- }
- else if (nehahra)
- {
- M_Print (160, 120, nehahralevels[nehahraepisodes[startepisode].firstLevel + startlevel].description);
- M_Print (160, 128, nehahralevels[nehahraepisodes[startepisode].firstLevel + startlevel].name);
- }
- else
- {
- M_Print (160, 120, levels[episodes[startepisode].firstLevel + startlevel].description);
- M_Print (160, 128, levels[episodes[startepisode].firstLevel + startlevel].name);
- }
+ //MED 01/06/97 added hipnotic episodes
+ if (gamemode == GAME_HIPNOTIC)
+ {
+ M_Print (160, 120, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].description);
+ M_Print (160, 128, hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].name);
+ }
+ //PGM 01/07/97 added rogue episodes
+ else if (gamemode == GAME_ROGUE)
+ {
+ M_Print (160, 120, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].description);
+ M_Print (160, 128, roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].name);
+ }
+ else if (gamemode == GAME_NEHAHRA)
+ {
+ M_Print (160, 120, nehahralevels[nehahraepisodes[startepisode].firstLevel + startlevel].description);
+ M_Print (160, 128, nehahralevels[nehahraepisodes[startepisode].firstLevel + startlevel].name);
+ }
+ else
+ {
+ M_Print (160, 120, levels[episodes[startepisode].firstLevel + startlevel].description);
+ M_Print (160, 128, levels[episodes[startepisode].firstLevel + startlevel].name);
+ }
// line cursor
M_DrawCharacter (144, gameoptions_cursor_table[gameoptions_cursor], 12+((int)(realtime*4)&1));
break;
case 3:
- if (rogue)
+ if (gamemode == GAME_ROGUE)
count = 6;
else
count = 2;
case 7:
startepisode += dir;
//MED 01/06/97 added hipnotic count
- if (hipnotic)
+ if (gamemode == GAME_HIPNOTIC)
count = 6;
//PGM 01/07/97 added rogue count
//PGM 03/02/97 added 1 for dmatch episode
- else if (rogue)
+ else if (gamemode == GAME_ROGUE)
count = 4;
- else if (nehahra)
+ else if (gamemode == GAME_NEHAHRA)
count = 4;
else if (registered.value)
count = 7;
case 8:
startlevel += dir;
//MED 01/06/97 added hipnotic episodes
- if (hipnotic)
+ if (gamemode == GAME_HIPNOTIC)
count = hipnoticepisodes[startepisode].levels;
//PGM 01/06/97 added hipnotic episodes
- else if (rogue)
+ else if (gamemode == GAME_ROGUE)
count = rogueepisodes[startepisode].levels;
- else if (nehahra)
+ else if (gamemode == GAME_NEHAHRA)
count = nehahraepisodes[startepisode].levels;
else
count = episodes[startepisode].levels;
Cbuf_AddText ( va ("maxplayers %u\n", maxplayers) );
// SCR_BeginLoadingPlaque ();
- if (hipnotic)
+ if (gamemode == GAME_HIPNOTIC)
Cbuf_AddText ( va ("map %s\n", hipnoticlevels[hipnoticepisodes[startepisode].firstLevel + startlevel].name) );
- else if (rogue)
+ else if (gamemode == GAME_ROGUE)
Cbuf_AddText ( va ("map %s\n", roguelevels[rogueepisodes[startepisode].firstLevel + startlevel].name) );
- else if (nehahra)
+ else if (gamemode == GAME_NEHAHRA)
Cbuf_AddText ( va ("map %s\n", nehahralevels[nehahraepisodes[startepisode].firstLevel + startlevel].name) );
else
Cbuf_AddText ( va ("map %s\n", levels[episodes[startepisode].firstLevel + startlevel].name) );
Cmd_AddCommand ("help", M_Menu_Help_f);
Cmd_AddCommand ("menu_quit", M_Menu_Quit_f);
- if (nehahra)
+ if (gamemode == GAME_NEHAHRA)
{
if (COM_FileExists("maps/neh1m4.bsp"))
{
{
if (scr_con_current)
{
- Draw_ConsoleBackground (vid.height);
+ Draw_ConsoleBackground (vid.conheight);
S_ExtraUpdate ();
}
}
#include "quakedef.h"
-cvar_t r_mipskins = {CVAR_SAVE, "r_mipskins", "1"};
+static cvar_t r_mipskins = {CVAR_SAVE, "r_mipskins", "0"};
/*
===============
Cvar_RegisterVariable(&r_mipskins);
}
-int posenum;
+static void Mod_Alias_SERAddEntity(void)
+{
+ R_Clip_AddBox(currentrenderentity->mins, currentrenderentity->maxs, R_Entity_Callback, currentrenderentity, NULL);
+}
+
+static int posenum;
-float aliasbboxmin[3], aliasbboxmax[3]; // LordHavoc: proper bounding box considerations
+// LordHavoc: proper bounding box considerations
+static float aliasbboxmin[3], aliasbboxmax[3], modelyawradius, modelradius;
-float vertst[MAXALIASVERTS][2];
-int vertusage[MAXALIASVERTS];
-int vertonseam[MAXALIASVERTS];
-int vertremap[MAXALIASVERTS];
-unsigned short temptris[MAXALIASTRIS][3];
+static float vertst[MAXALIASVERTS][2];
+static int vertusage[MAXALIASVERTS];
+static int vertonseam[MAXALIASVERTS];
+static int vertremap[MAXALIASVERTS];
+static unsigned short temptris[MAXALIASTRIS][3];
-void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out)
+static void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out)
{
int i, j, invalidnormals = 0;
+ float dist;
vec3_t temp;
for (i = 0;i < inverts;i++)
{
if (temp[0] > aliasbboxmax[0]) aliasbboxmax[0] = temp[0];
if (temp[1] > aliasbboxmax[1]) aliasbboxmax[1] = temp[1];
if (temp[2] > aliasbboxmax[2]) aliasbboxmax[2] = temp[2];
+ dist = temp[0]*temp[0]+temp[1]*temp[1];
+ if (modelyawradius < dist)
+ modelyawradius = dist;
+ dist += temp[2]*temp[2];
+ if (modelradius < dist)
+ modelradius = dist;
j = vertremap[i]; // not onseam
if (j >= 0)
{
Mod_LoadAliasFrame
=================
*/
-void * Mod_LoadAliasFrame (void *pin, maliashdr_t *mheader, int inverts, int outverts, trivertx_t **posevert, animscene_t *scene)
+static void * Mod_LoadAliasFrame (void *pin, maliashdr_t *mheader, int inverts, int outverts, trivertx_t **posevert, animscene_t *scene)
{
trivertx_t *pinframe;
daliasframe_t *pdaliasframe;
-
+
pdaliasframe = (daliasframe_t *)pin;
strcpy(scene->name, pdaliasframe->name);
Mod_LoadAliasGroup
=================
*/
-void *Mod_LoadAliasGroup (void *pin, maliashdr_t *mheader, int inverts, int outverts, trivertx_t **posevert, animscene_t *scene)
+static void *Mod_LoadAliasGroup (void *pin, maliashdr_t *mheader, int inverts, int outverts, trivertx_t **posevert, animscene_t *scene)
{
int i, numframes;
void *ptemp;
float interval;
-
+
numframes = LittleLong (((daliasgroup_t *)pin)->numframes);
strcpy(scene->name, ((daliasframe_t *) (sizeof(daliasinterval_t) * numframes + sizeof(daliasgroup_t) + (int) pin))->name);
//=========================================================
-/*
-=================
-Mod_FloodFillSkin
-
-Fill background pixels so mipmapping doesn't have haloes - Ed
-=================
-*/
-
-typedef struct
-{
- short x, y;
-} floodfill_t;
-
-// must be a power of 2
-#define FLOODFILL_FIFO_SIZE 0x1000
-#define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1)
-
-#define FLOODFILL_STEP( off, dx, dy ) \
-{ \
- if (pos[off] == fillcolor) \
- { \
- pos[off] = 255; \
- fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \
- inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \
- } \
- else if (pos[off] != 255) fdc = pos[off]; \
-}
-
-void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
-{
- byte fillcolor = *skin; // assume this is the pixel to fill
- floodfill_t fifo[FLOODFILL_FIFO_SIZE];
- int inpt = 0, outpt = 0;
- int filledcolor = -1;
- int i;
-
- if (filledcolor == -1)
- {
- filledcolor = 0;
- // attempt to find opaque black
- for (i = 0; i < 256; ++i)
- if (d_8to24table[i] == (255 << 0)) // alpha 1.0
- {
- filledcolor = i;
- break;
- }
- }
-
- // can't fill to filled color or to transparent color (used as visited marker)
- if ((fillcolor == filledcolor) || (fillcolor == 255))
- {
- //printf( "not filling skin from %d to %d\n", fillcolor, filledcolor );
- return;
- }
-
- fifo[inpt].x = 0, fifo[inpt].y = 0;
- inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;
-
- while (outpt != inpt)
- {
- int x = fifo[outpt].x, y = fifo[outpt].y;
- int fdc = filledcolor;
- byte *pos = &skin[x + skinwidth * y];
-
- outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;
-
- if (x > 0) FLOODFILL_STEP( -1, -1, 0 );
- if (x < skinwidth - 1) FLOODFILL_STEP( 1, 1, 0 );
- if (y > 0) FLOODFILL_STEP( -skinwidth, 0, -1 );
- if (y < skinheight - 1) FLOODFILL_STEP( skinwidth, 0, 1 );
- skin[x + skinwidth * y] = fdc;
- }
-}
-
-rtexture_t *GL_SkinSplitShirt(byte *in, byte *out, int width, int height, unsigned short bits, char *name, int precache)
+static rtexture_t *GL_SkinSplitShirt(byte *in, byte *out, int width, int height, unsigned short bits, char *name, int precache)
{
int i, pixels, passed;
byte pixeltest[16];
return NULL;
}
-rtexture_t *GL_SkinSplit(byte *in, byte *out, int width, int height, unsigned short bits, char *name, int precache)
+static rtexture_t *GL_SkinSplit(byte *in, byte *out, int width, int height, unsigned short bits, char *name, int precache)
{
int i, pixels, passed;
byte pixeltest[16];
return NULL;
}
-int GL_SkinCheck(byte *in, int width, int height, unsigned short bits)
+static int GL_SkinCheck(byte *in, int width, int height, unsigned short bits)
{
int i, pixels, passed;
byte pixeltest[16];
return false;
}
-void Mod_LoadSkin (maliashdr_t *mheader, char *basename, byte *skindata, byte *skintemp, int width, int height, rtexture_t **skintex)
+static void Mod_LoadSkin (maliashdr_t *mheader, char *basename, byte *skindata, byte *skintemp, int width, int height, rtexture_t **skintex)
{
skintex[0] = loadtextureimage(va("%s_normal", basename), 0, 0, false, r_mipskins.value, true);
skintex[1] = NULL;
Mod_LoadAllSkins
===============
*/
-void *Mod_LoadAllSkins (maliashdr_t *mheader, int numskins, daliasskintype_t *pskintype, int width, int height)
+static void *Mod_LoadAllSkins (maliashdr_t *mheader, int numskins, daliasskintype_t *pskintype, int width, int height)
{
int i, j;
char name[32];
rtexture_t **skintex;
void *temp;
byte *skintemp = NULL;
-
+
skin = (byte *)(pskintype + 1);
if (numskins < 1 || numskins > MAX_SKINS)
return (void *)pskintype;
}
-void *Mod_SkipAllSkins (int numskins, daliasskintype_t *pskintype, int skinsize)
+static void *Mod_SkipAllSkins (int numskins, daliasskintype_t *pskintype, int skinsize)
{
int i;
for (i = 0;i < numskins;i++)
trivertx_t *posevert;
animscene_t *animscenes;
+ modelyawradius = 0;
+ modelradius = 0;
+
start = Hunk_LowMark ();
pinmodel = (mdl_t *)buffer;
// LordHavoc: fixed model bbox - was //FIXME: do this right
//mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
//mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
+ modelyawradius = sqrt(modelyawradius);
+ modelradius = sqrt(modelradius);
+// mod->modelradius = modelradius;
for (j = 0;j < 3;j++)
{
- mod->mins[j] = aliasbboxmin[j];
- mod->maxs[j] = aliasbboxmax[j];
+ mod->normalmins[j] = aliasbboxmin[j];
+ mod->normalmaxs[j] = aliasbboxmax[j];
+ mod->rotatedmins[j] = -modelradius;
+ mod->rotatedmaxs[j] = modelradius;
}
+ mod->yawmins[0] = mod->yawmins[1] = -(mod->yawmaxs[0] = mod->yawmaxs[1] = modelyawradius);
+ mod->yawmins[2] = mod->normalmins[2];
+ mod->yawmaxs[2] = mod->normalmaxs[2];
+
+ mod->SERAddEntity = Mod_Alias_SERAddEntity;
+ mod->DrawEarly = NULL;
+ mod->DrawLate = R_DrawAliasModel;
+ mod->DrawShadow = NULL;
// move the complete, relocatable alias model to the cache
end = Hunk_LowMark ();
Hunk_FreeToLowMark (start);
}
-void Mod_ConvertQ2AliasVerts (int numverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out)
+static void Mod_ConvertQ2AliasVerts (int numverts, vec3_t scale, vec3_t translate, trivertx_t *v, trivertx_t *out)
{
int i, invalidnormals = 0;
+ float dist;
vec3_t temp;
for (i = 0;i < numverts;i++)
{
if (temp[0] > aliasbboxmax[0]) aliasbboxmax[0] = temp[0];
if (temp[1] > aliasbboxmax[1]) aliasbboxmax[1] = temp[1];
if (temp[2] > aliasbboxmax[2]) aliasbboxmax[2] = temp[2];
+ dist = temp[0]*temp[0]+temp[1]*temp[1];
+ if (modelyawradius < dist)
+ modelyawradius = dist;
+ dist += temp[2]*temp[2];
+ if (modelradius < dist)
+ modelradius = dist;
out[i].lightnormalindex = v[i].lightnormalindex;
if (out[i].lightnormalindex >= NUMVERTEXNORMALS)
{
// temptris_t *tris;
animscene_t *animscenes;
+ modelyawradius = 0;
+ modelradius = 0;
+
start = Hunk_LowMark ();
// if (!temptris)
version = LittleLong (pinmodel->version);
if (version != MD2ALIAS_VERSION)
Host_Error ("%s has wrong version number (%i should be %i)",
- mod->name, version, MD2ALIAS_VERSION);
+ mod->name, version, MD2ALIAS_VERSION);
mod->type = mod_alias;
mod->aliastype = ALIASTYPE_MD2;
if (size <= 0 || size >= MD2MAX_SIZE)
Host_Error ("%s is not a valid model", mod->name);
pheader = Hunk_AllocName (size, va("%s Quake2 model", loadname));
-
+
mod->flags = 0; // there are no MD2 flags
mod->numframes = LittleLong(pinmodel->num_frames);
mod->synctype = ST_RAND;
int *skinrange;
skinrange = loadmodel->skinanimrange;
skin = loadmodel->skinanim;
-// skinrange = Hunk_AllocName (sizeof(int) * (pheader->num_skins * 2), loadname);
+// skinrange = Hunk_AllocName (sizeof(int) * (pheader->num_skins * 2), loadname);
// skin = skinrange + pheader->num_skins * 2;
// loadmodel->skinanimrange = (int) skinrange - (int) pheader;
// loadmodel->skinanim = (int) skin - (int) pheader;
mod->ofs_scenes = (int) animscenes - (int) pheader;
// LordHavoc: model bbox
+ modelyawradius = sqrt(modelyawradius);
+ modelradius = sqrt(modelradius);
+// mod->modelradius = modelradius;
for (j = 0;j < 3;j++)
{
- mod->mins[j] = aliasbboxmin[j];
- mod->maxs[j] = aliasbboxmax[j];
+ mod->normalmins[j] = aliasbboxmin[j];
+ mod->normalmaxs[j] = aliasbboxmax[j];
+ mod->rotatedmins[j] = -modelradius;
+ mod->rotatedmaxs[j] = modelradius;
}
+ mod->yawmins[0] = mod->yawmins[1] = -(mod->yawmaxs[0] = mod->yawmaxs[1] = modelyawradius);
+ mod->yawmins[2] = mod->normalmins[2];
+ mod->yawmaxs[2] = mod->normalmaxs[2];
// load the draw list
pinglcmd = (void*) ((int) pinmodel + LittleLong(pinmodel->ofs_glcmds));
for (i = 0;i < pheader->num_glcmds;i++)
*poutglcmd++ = LittleLong(*pinglcmd++);
+ mod->SERAddEntity = Mod_Alias_SERAddEntity;
+ mod->DrawEarly = NULL;
+ mod->DrawLate = R_DrawAliasModel;
+ mod->DrawShadow = NULL;
+
// move the complete, relocatable alias model to the cache
end = Hunk_LowMark ();
mod->cachesize = total = end - start;
Hunk_FreeToLowMark (start);
}
-void swapintblock(int *m, int size)
+static void swapintblock(int *m, int size)
{
size /= 4;
while(size--)
zymscene_t *scene;
zymbone_t *bone;
animscene_t *animscenes;
+ float corner[2], modelradius;
start = Hunk_LowMark ();
// load the skins
skinrange = loadmodel->skinanimrange;
skin = loadmodel->skinanim;
-// skinrange = Hunk_AllocName (sizeof(int) * (pheader->num_skins * 2), loadname);
+// skinrange = Hunk_AllocName (sizeof(int) * (pheader->num_skins * 2), loadname);
// skin = skinrange + pheader->num_skins * 2;
// loadmodel->skinanimrange = (int) skinrange - (int) pheader;
// loadmodel->skinanim = (int) skin - (int) pheader;
swapintblock((void *) (pheader->lump_trizone.start + pbase), pheader->lump_trizone.length);
// model bbox
+ modelradius = pheader->radius;
+// mod->modelradius = pheader->radius;
for (i = 0;i < 3;i++)
{
- mod->mins[i] = pheader->mins[i];
- mod->maxs[i] = pheader->maxs[i];
+ mod->normalmins[i] = pheader->mins[i];
+ mod->normalmaxs[i] = pheader->maxs[i];
+ mod->rotatedmins[i] = -modelradius;
+ mod->rotatedmaxs[i] = modelradius;
}
+ corner[0] = max(fabs(mod->normalmins[0]), fabs(mod->normalmaxs[0]));
+ corner[1] = max(fabs(mod->normalmins[1]), fabs(mod->normalmaxs[1]));
+ mod->yawmaxs[0] = mod->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
+ if (mod->yawmaxs[0] > modelradius)
+ mod->yawmaxs[0] = mod->yawmaxs[1] = modelradius;
+ mod->yawmins[0] = mod->yawmins[1] = -mod->yawmaxs[0];
+ mod->yawmins[2] = mod->normalmins[2];
+ mod->yawmaxs[2] = mod->normalmaxs[2];
+
+ mod->SERAddEntity = Mod_Alias_SERAddEntity;
+ mod->DrawEarly = NULL;
+ mod->DrawLate = R_DrawAliasModel;
+ mod->DrawShadow = NULL;
// move the complete, relocatable alias model to the cache
end = Hunk_LowMark ();
mod->cachesize = total = end - start;
-
+
Cache_Alloc (&mod->cache, total, loadname);
if (!mod->cache.data)
return;
#include "quakedef.h"
-byte mod_novis[MAX_MAP_LEAFS/8];
+byte mod_novis[(MAX_MAP_LEAFS + 7)/ 8];
qboolean hlbsp; // LordHavoc: true if it is a HalfLife BSP file (version 30)
Cvar_RegisterVariable (&gl_subdivide_size);
Cvar_RegisterVariable (&halflifebsp);
Cvar_RegisterVariable (&r_novis);
- memset (mod_novis, 0xff, sizeof(mod_novis));
+ memset(mod_novis, 0xff, sizeof(mod_novis));
+}
+
+void Mod_Brush_SERAddEntity(void)
+{
+ R_Clip_AddBox(currentrenderentity->mins, currentrenderentity->maxs, R_Entity_Callback, currentrenderentity, NULL);
}
/*
mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
{
mnode_t *node;
-
+
// if (!model || !model->nodes)
// Sys_Error ("Mod_PointInLeaf: bad model");
mnode_t *node;
float d;
mplane_t *plane;
-
+
if (!model || !model->nodes)
Sys_Error ("Mod_PointInLeaf: bad model");
Mod_DecompressVis
===================
*/
-byte *Mod_DecompressVis (byte *in, model_t *model)
+static byte *Mod_DecompressVis (byte *in, model_t *model)
{
static byte decompressed[MAX_MAP_LEAFS/8];
int c;
*out++ = 0xff;
row--;
}
- return decompressed;
+ return decompressed;
}
*/
*out++ = *in++;
continue;
}
-
+
c = in[1];
in += 2;
while (c)
c--;
}
} while (out - decompressed < row);
-
+
return decompressed;
}
Mod_LoadTextures
=================
*/
-void Mod_LoadTextures (lump_t *l)
+static void Mod_LoadTextures (lump_t *l)
{
int i, j, k, num, max, altmax, mtwidth, mtheight, *dofs;
miptex_t *dmiptex;
m = (dmiptexlump_t *)(mod_base + l->fileofs);
m->nummiptex = LittleLong (m->nummiptex);
-
+
loadmodel->numtextures = m->nummiptex;
loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures), va("%s texture headers", loadname));
Host_Error ("Texture %s is corrupt or incomplete\n", dmiptex->name);
mtdata = (byte *)dmiptex + j;
}
-
+
if ((mtwidth & 15) || (mtheight & 15))
Host_Error ("Texture %s is not 16 aligned", dmiptex->name);
// LordHavoc: rewriting the map texture loader for GLQuake
tx = Hunk_AllocName (sizeof(texture_t), va("%s textures", loadname));
+ memset(tx, 0, sizeof(texture_t));
+ tx->anim_total = 0;
+ tx->alternate_anims = NULL;
loadmodel->textures[i] = tx;
// LordHavoc: force all names to lowercase and make sure they are terminated while copying
// find the number of frames in the animation
memset (anims, 0, sizeof(anims));
memset (altanims, 0, sizeof(altanims));
+ max = altmax = 0;
- max = tx->name[1];
- altmax = 0;
- if (max >= '0' && max <= '9')
- {
- max -= '0';
- altmax = 0;
- anims[max] = tx;
- max++;
- }
- else if (max >= 'a' && max <= 'j')
- {
- altmax = max - 'a';
- max = 0;
- altanims[altmax] = tx;
- altmax++;
- }
- else
- Host_Error ("Bad animating texture %s", tx->name);
-
- for (j = i + 1;j < m->nummiptex;j++)
+ for (j = i;j < m->nummiptex;j++)
{
tx2 = loadmodel->textures[j];
- if (!tx2 || tx2->name[0] != '+')
- continue;
- if (strcmp (tx2->name+2, tx->name+2))
+ if (!tx2 || tx2->name[0] != '+' || strcmp (tx2->name+2, tx->name+2))
continue;
num = tx2->name[1];
if (num >= '0' && num <= '9')
- {
- num -= '0';
- anims[num] = tx2;
- if (num+1 > max)
- max = num + 1;
- }
+ anims[num - '0'] = tx2;
else if (num >= 'a' && num <= 'j')
- {
- num = num - 'a';
- altanims[num] = tx2;
- if (num+1 > altmax)
- altmax = num+1;
- }
+ altanims[num - 'a'] = tx2;
else
Host_Error ("Bad animating texture %s", tx->name);
}
+ for (j = 0;j < 10;j++)
+ {
+ if (anims[j] != NULL)
+ max = j + 1;
+ if (altanims[j] != NULL)
+ altmax = j + 1;
+ }
+
// link them all together
for (j = 0;j < max;j++)
{
if (!tx2)
Host_Error ("Missing frame %i of %s", j, tx->name);
tx2->anim_total = max;
- if (altmax)
- tx2->alternate_anims = altanims[0];
+ tx2->alternate_anims = altanims[0]; // NULL if there is no alternate
for (k = 0;k < 10;k++)
- tx2->anim_frames[k] = anims[j];
+ tx2->anim_frames[k] = anims[k];
}
+
for (j = 0;j < altmax;j++)
{
tx2 = altanims[j];
if (!tx2)
Host_Error ("Missing frame %i of %s", j, tx->name);
tx2->anim_total = altmax;
- if (max)
- tx2->alternate_anims = anims[0];
+ tx2->alternate_anims = anims[0]; // NULL if there is no alternate
for (k = 0;k < 10;k++)
- tx2->anim_frames[k] = altanims[j];
+ tx2->anim_frames[k] = altanims[k];
}
}
}
Mod_LoadLighting
=================
*/
-void Mod_LoadLighting (lump_t *l)
+static void Mod_LoadLighting (lump_t *l)
{
int i;
byte *in, *out, *data;
Mod_LoadVisibility
=================
*/
-void Mod_LoadVisibility (lump_t *l)
+static void Mod_LoadVisibility (lump_t *l)
{
if (!l->filelen)
{
Mod_LoadEntities
=================
*/
-void Mod_LoadEntities (lump_t *l)
+static void Mod_LoadEntities (lump_t *l)
{
if (!l->filelen)
{
Mod_LoadVertexes
=================
*/
-void Mod_LoadVertexes (lump_t *l)
+static void Mod_LoadVertexes (lump_t *l)
{
dvertex_t *in;
mvertex_t *out;
Mod_LoadSubmodels
=================
*/
-void Mod_LoadSubmodels (lump_t *l)
+static void Mod_LoadSubmodels (lump_t *l)
{
dmodel_t *in;
dmodel_t *out;
Mod_LoadEdges
=================
*/
-void Mod_LoadEdges (lump_t *l)
+static void Mod_LoadEdges (lump_t *l)
{
dedge_t *in;
medge_t *out;
Mod_LoadTexinfo
=================
*/
-void Mod_LoadTexinfo (lump_t *l)
+static void Mod_LoadTexinfo (lump_t *l)
{
texinfo_t *in;
mtexinfo_t *out;
miptex = LittleLong (in->miptex);
out->flags = LittleLong (in->flags);
-
+
if (!loadmodel->textures)
{
out->texture = &r_notexture_mip; // checkerboard texture
Fills in s->texturemins[] and s->extents[]
================
*/
-void CalcSurfaceExtents (msurface_t *s)
+static void CalcSurfaceExtents (msurface_t *s)
{
float mins[2], maxs[2], val;
int i,j, e;
maxs[0] = maxs[1] = -99999;
tex = s->texinfo;
-
+
for (i=0 ; i<s->numedges ; i++)
{
e = loadmodel->surfedges[s->firstedge+i];
Mod_LoadFaces
=================
*/
-void Mod_LoadFaces (lump_t *l)
+static void Mod_LoadFaces (lump_t *l)
{
dface_t *in;
msurface_t *out;
for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
{
out->firstedge = LittleLong(in->firstedge);
- out->numedges = LittleShort(in->numedges);
+ out->numedges = LittleShort(in->numedges);
out->flags = 0;
planenum = LittleShort(in->planenum);
side = LittleShort(in->side);
if (side)
- out->flags |= SURF_PLANEBACK;
+ out->flags |= SURF_PLANEBACK;
out->plane = loadmodel->planes + planenum;
else if (hlbsp) // LordHavoc: HalfLife map (bsp version 30)
out->samples = loadmodel->lightdata + i;
else // LordHavoc: white lighting (bsp version 29)
- out->samples = loadmodel->lightdata + (i * 3);
-
+ out->samples = loadmodel->lightdata + (i * 3);
+
// set the drawing flags flag
-
+
// if (!strncmp(out->texinfo->texture->name,"sky",3)) // sky
// LordHavoc: faster check
if ((out->texinfo->texture->name[0] == 's' || out->texinfo->texture->name[0] == 'S')
GL_SubdivideSurface (out); // cut up polygon for warps
continue;
}
-
+
// if (!strncmp(out->texinfo->texture->name,"*",1)) // turbulent
if (out->texinfo->texture->name[0] == '*') // LordHavoc: faster check
{
if (!strncmp(out->texinfo->texture->name,"*lava",5)
|| !strncmp(out->texinfo->texture->name,"*teleport",9)
|| !strncmp(out->texinfo->texture->name,"*rift",5)) // Scourge of Armagon texture
- out->flags |= (SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA);
+ out->flags |= (SURF_DRAWFULLBRIGHT | SURF_DRAWNOALPHA | SURF_CLIPSOLID);
for (i=0 ; i<2 ; i++)
{
out->extents[i] = 16384;
GL_SubdivideSurface (out); // cut up polygon for warps
continue;
}
-
- out->flags |= SURF_CLIPSOLID;
+
+ if (!out->texinfo->texture->transparent)
+ out->flags |= SURF_CLIPSOLID;
}
}
Mod_SetParent
=================
*/
-void Mod_SetParent (mnode_t *node, mnode_t *parent)
+static void Mod_SetParent (mnode_t *node, mnode_t *parent)
{
node->parent = parent;
if (node->contents < 0)
Mod_LoadNodes
=================
*/
-void Mod_LoadNodes (lump_t *l)
+static void Mod_LoadNodes (lump_t *l)
{
int i, j, count, p;
dnode_t *in;
Mod_LoadLeafs
=================
*/
-void Mod_LoadLeafs (lump_t *l)
+static void Mod_LoadLeafs (lump_t *l)
{
dleaf_t *in;
mleaf_t *out;
out->firstmarksurface = loadmodel->marksurfaces +
LittleShort(in->firstmarksurface);
out->nummarksurfaces = LittleShort(in->nummarksurfaces);
-
+
p = LittleLong(in->visofs);
if (p == -1)
out->compressed_vis = NULL;
Mod_LoadClipnodes
=================
*/
-void Mod_LoadClipnodes (lump_t *l)
+static void Mod_LoadClipnodes (lump_t *l)
{
dclipnode_t *in, *out;
int i, count;
Duplicate the drawing hull structure as a clipping hull
=================
*/
-void Mod_MakeHull0 (void)
+static void Mod_MakeHull0 (void)
{
mnode_t *in;
dclipnode_t *out;
hull_t *hull;
hull = &loadmodel->hulls[0];
-
+
in = loadmodel->nodes;
count = loadmodel->numnodes;
out = Hunk_AllocName ( count*sizeof(*out), va("%s hull0", loadname));
Mod_LoadMarksurfaces
=================
*/
-void Mod_LoadMarksurfaces (lump_t *l)
-{
+static void Mod_LoadMarksurfaces (lump_t *l)
+{
int i, j, count;
short *in;
msurface_t **out;
-
+
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
Mod_LoadSurfedges
=================
*/
-void Mod_LoadSurfedges (lump_t *l)
-{
+static void Mod_LoadSurfedges (lump_t *l)
+{
int i, count;
int *in, *out;
Mod_LoadPlanes
=================
*/
-void Mod_LoadPlanes (lump_t *l)
+static void Mod_LoadPlanes (lump_t *l)
{
int i, j;
mplane_t *out;
dplane_t *in;
int count;
-
+
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Host_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
NewWinding
==================
*/
-winding_t *NewWinding (int points)
+static winding_t *NewWinding (int points)
{
winding_t *w;
int size;
return w;
}
-void FreeWinding (winding_t *w)
+static void FreeWinding (winding_t *w)
{
qfree (w);
}
BaseWindingForPlane
=================
*/
-winding_t *BaseWindingForPlane (mplane_t *p)
+static winding_t *BaseWindingForPlane (mplane_t *p)
{
vec3_t org, vright, vup;
winding_t *w;
it will be clipped away.
==================
*/
-winding_t *ClipWinding (winding_t *in, mplane_t *split, int keepon)
+static winding_t *ClipWinding (winding_t *in, mplane_t *split, int keepon)
{
vec_t dists[MAX_POINTS_ON_WINDING + 1];
int sides[MAX_POINTS_ON_WINDING + 1];
new windings will be created.
==================
*/
-void DivideWinding (winding_t *in, mplane_t *split, winding_t **front, winding_t **back)
+static void DivideWinding (winding_t *in, mplane_t *split, winding_t **front, winding_t **back)
{
vec_t dists[MAX_POINTS_ON_WINDING + 1];
int sides[MAX_POINTS_ON_WINDING + 1];
AllocPortal
===========
*/
-portal_t *AllocPortal (void)
+static portal_t *AllocPortal (void)
{
portal_t *p;
p = qmalloc(sizeof(portal_t));
return p;
}
-void Mod_RecursiveRecalcNodeBBox(mnode_t *node)
+static void Mod_RecursiveRecalcNodeBBox(mnode_t *node)
{
// calculate children first
if (node->children[0]->contents >= 0)
node->maxs[2] = max(node->children[0]->maxs[2], node->children[1]->maxs[2]);
}
-void Mod_FinalizePortals(void)
+static void Mod_FinalizePortals(void)
{
int i, j, numportals, numpoints;
portal_t *p, *pnext;
AddPortalToNodes
=============
*/
-void AddPortalToNodes (portal_t *p, mnode_t *front, mnode_t *back)
+static void AddPortalToNodes (portal_t *p, mnode_t *front, mnode_t *back)
{
if (!front)
Host_Error ("AddPortalToNodes: NULL front node");
RemovePortalFromNode
=============
*/
-void RemovePortalFromNodes(portal_t *portal)
+static void RemovePortalFromNodes(portal_t *portal)
{
int i;
mnode_t *node;
}
}
-void Mod_RecursiveNodePortals (mnode_t *node)
+static void Mod_RecursiveNodePortals (mnode_t *node)
{
int side;
mnode_t *front, *back, *other_node;
}
*/
-void Mod_MakePortals(void)
+static void Mod_MakePortals(void)
{
// Con_Printf("building portals for %s\n", loadmodel->name);
//
for (i = 0;i < mod->numsubmodels;i++)
{
+ int k, l;
+ float dist, modelyawradius, modelradius, *vec;
+ msurface_t *surf;
+
+ mod->normalmins[0] = mod->normalmins[1] = mod->normalmins[2] = 1000000000.0f;
+ mod->normalmaxs[0] = mod->normalmaxs[1] = mod->normalmaxs[2] = -1000000000.0f;
+ modelyawradius = 0;
+ modelradius = 0;
+
bm = &mod->submodels[i];
mod->hulls[0].firstclipnode = bm->headnode[0];
mod->firstmodelsurface = bm->firstface;
mod->nummodelsurfaces = bm->numfaces;
- VectorCopy (bm->maxs, mod->maxs);
- VectorCopy (bm->mins, mod->mins);
+ // LordHavoc: calculate bmodel bounding box rather than trusting what it says
+ for (j = 0, surf = &mod->surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surf++)
+ {
+ for (k = 0;k < surf->numedges;k++)
+ {
+ l = mod->surfedges[k + surf->firstedge];
+ if (l > 0)
+ vec = mod->vertexes[mod->edges[l].v[0]].position;
+ else
+ vec = mod->vertexes[mod->edges[-l].v[1]].position;
+ if (mod->normalmins[0] > vec[0]) mod->normalmins[0] = vec[0];
+ if (mod->normalmins[1] > vec[1]) mod->normalmins[1] = vec[1];
+ if (mod->normalmins[2] > vec[2]) mod->normalmins[2] = vec[2];
+ if (mod->normalmaxs[0] < vec[0]) mod->normalmaxs[0] = vec[0];
+ if (mod->normalmaxs[1] < vec[1]) mod->normalmaxs[1] = vec[1];
+ if (mod->normalmaxs[2] < vec[2]) mod->normalmaxs[2] = vec[2];
+ dist = vec[0]*vec[0]+vec[1]*vec[1];
+ if (modelyawradius < dist)
+ modelyawradius = dist;
+ dist += vec[2]*vec[2];
+ if (modelradius < dist)
+ modelradius = dist;
+ }
+ }
+ modelyawradius = sqrt(modelyawradius);
+ modelradius = sqrt(modelradius);
+ mod->yawmins[0] = mod->yawmins[1] = -(mod->yawmaxs[0] = mod->yawmaxs[1] = modelyawradius);
+ mod->yawmins[2] = mod->normalmins[2];
+ mod->yawmaxs[2] = mod->normalmaxs[2];
+ mod->rotatedmins[0] = mod->rotatedmins[1] = mod->rotatedmins[2] = -modelradius;
+ mod->rotatedmaxs[0] = mod->rotatedmaxs[1] = mod->rotatedmaxs[2] = modelradius;
+// mod->modelradius = modelradius;
+
+// VectorCopy (bm->maxs, mod->maxs);
+// VectorCopy (bm->mins, mod->mins);
- mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
+// mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
mod->numleafs = bm->visleafs;
+ mod->SERAddEntity = Mod_Brush_SERAddEntity;
+ mod->DrawEarly = R_DrawBrushModel;
+ mod->DrawLate = NULL;
+ mod->DrawShadow = NULL;
+
if (isworldmodel && i < (mod->numsubmodels - 1)) // LordHavoc: only register submodels if it is the world (prevents bsp models from replacing world submodels)
{ // duplicate the basic information
char name[10];
{
struct glpoly_s *next;
int numverts;
- int flags; // for SURF_UNDERWATER
} glpolysizeof_t;
typedef struct msurface_s
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
int flags2; // engine calculated flags, ones that can not be set in the file
// volume occupied by the model graphics
- vec3_t mins, maxs;
- float radius;
+ vec3_t normalmins, normalmaxs; // bounding box at angles '0 0 0'
+ vec3_t yawmins, yawmaxs; // bounding box if yaw angle is not 0, but pitch and roll are
+ vec3_t rotatedmins, rotatedmaxs; // bounding box if pitch or roll are used
+// float modelradius; // usable at any angles
// solid volume for clipping
qboolean clipbox;
// LordHavoc: useful for sprites and models
int numtris;
int numskins;
+
int skinanimrange[MAX_SKINS*2]; // array of start and length pairs
rtexture_t *skinanim[MAX_SKINS*5]; // texture numbers for each frame (indexed by animrange), note: normal pants shirt glow body (normal contains no shirt/pants/glow colors and body is normal + pants + shirt, but not glow)
+
int ofs_scenes; // offset from Mod_ExtraData(model) memory to array of animscene_t structs
// these are used simply to simplify model/sprite/whatever processing and are specific to each type
int ofs_frames; // offset from Mod_ExtraData(model) memory to array of model specific frame structs
int framesize; // size of model specific frame structs
+ void (*SERAddEntity)(void);
+ void (*DrawEarly)(void);
+ void (*DrawLate)(void);
+ void (*DrawShadow)(void);
+
// additional model data
cache_user_t cache; // only access through Mod_Extradata
int cachesize; // size of cached data (zero if not cached)
Mod_LoadSpriteFrame
=================
*/
-void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t *frame, int framenum, int bytesperpixel, byte *palette)
+void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t *frame, int framenum, int bytesperpixel, byte *palette, float *modelradius)
{
dspriteframe_t *pinframe;
mspriteframe_t *pspriteframe;
+ float dist;
int i, width, height, size, origin[2];
char name[256], tempname[256];
byte *pixbuf, *pixel, *inpixel;
pinframe = (dspriteframe_t *)pin;
+ origin[0] = LittleLong (pinframe->origin[0]);
+ origin[1] = LittleLong (pinframe->origin[1]);
width = LittleLong (pinframe->width);
height = LittleLong (pinframe->height);
size = width * height * bytesperpixel;
memset (pspriteframe, 0, sizeof (mspriteframe_t));
-// pspriteframe->width = width;
-// pspriteframe->height = height;
- origin[0] = LittleLong (pinframe->origin[0]);
- origin[1] = LittleLong (pinframe->origin[1]);
-
+ pspriteframe->left = origin[0];
+ pspriteframe->right = origin[0] + width;
pspriteframe->up = origin[1];
pspriteframe->down = origin[1] - height;
- pspriteframe->left = origin[0];
- pspriteframe->right = width + origin[0];
+
+ dist = pspriteframe->left*pspriteframe->left+pspriteframe->up*pspriteframe->up;
+ if (*modelradius < dist)
+ *modelradius = dist;
+ dist = pspriteframe->right*pspriteframe->right+pspriteframe->down*pspriteframe->down;
+ if (*modelradius < dist)
+ *modelradius = dist;
Mod_Sprite_StripExtension(loadmodel->name, tempname);
sprintf (name, "%s_%i", tempname, framenum);
// this actually handles both quake sprite and darkplaces sprite32
void Mod_LoadQuakeSprite (model_t *mod, void *buffer)
{
- int i, j, version, numframes, realframes, size, bytesperpixel, start, end, total, maxwidth, maxheight;
+ int i, j, version, numframes, realframes, size, bytesperpixel, start, end, total;
dsprite_t *pin;
msprite_t *psprite;
dspriteframetype_t *pframetype;
animscene_t *animscenes;
mspriteframe_t *frames;
dspriteframe_t **framedata;
+ float modelradius;
+
+ modelradius = 0;
start = Hunk_LowMark ();
// mod->cache.data = psprite;
psprite->type = LittleLong (pin->type);
- maxwidth = LittleLong (pin->width);
- maxheight = LittleLong (pin->height);
+// maxwidth = LittleLong (pin->width);
+// maxheight = LittleLong (pin->height);
// psprite->beamlength = LittleFloat (pin->beamlength);
mod->synctype = LittleLong (pin->synctype);
// psprite->numframes = numframes;
- mod->mins[0] = mod->mins[1] = -maxwidth/2;
- mod->maxs[0] = mod->maxs[1] = maxwidth/2;
- mod->mins[2] = -maxheight/2;
- mod->maxs[2] = maxheight/2;
+// mod->mins[0] = mod->mins[1] = -maxwidth/2;
+// mod->maxs[0] = mod->maxs[1] = maxwidth/2;
+// mod->mins[2] = -maxheight/2;
+// mod->maxs[2] = maxheight/2;
//
// load the frames
{
for (j = 0;j < animscenes[i].framecount;j++)
{
- Mod_LoadSpriteFrame (framedata[realframes], frames + realframes, i, bytesperpixel, (byte *)&d_8to24table);
+ Mod_LoadSpriteFrame (framedata[realframes], frames + realframes, i, bytesperpixel, (byte *)&d_8to24table, &modelradius);
realframes++;
}
}
mod->type = mod_sprite;
+ modelradius = sqrt(modelradius);
+ for (i = 0;i < 3;i++)
+ {
+ mod->normalmins[i] = mod->yawmins[i] = mod->rotatedmins[i] = -modelradius;
+ mod->normalmaxs[i] = mod->yawmaxs[i] = mod->rotatedmaxs[i] = modelradius;
+ }
+// mod->modelradius = modelradius;
+
// move the complete, relocatable sprite model to the cache
end = Hunk_LowMark ();
mod->cachesize = total = end - start;
void Mod_LoadHLSprite (model_t *mod, void *buffer)
{
- int i, j, numframes, realframes, size, start, end, total, maxwidth, maxheight, rendermode;
+ int i, j, numframes, realframes, size, start, end, total, rendermode;
byte palette[256][4], *in;
dspritehl_t *pin;
msprite_t *psprite;
animscene_t *animscenes;
mspriteframe_t *frames;
dspriteframe_t **framedata;
+ float modelradius;
+
+ modelradius = 0;
start = Hunk_LowMark ();
psprite = Hunk_AllocName (sizeof(msprite_t), va("%s info", loadname));
psprite->type = LittleLong (pin->type);
- maxwidth = LittleLong (pin->width);
- maxheight = LittleLong (pin->height);
+// maxwidth = LittleLong (pin->width);
+// maxheight = LittleLong (pin->height);
mod->synctype = LittleLong (pin->synctype);
rendermode = pin->rendermode;
- mod->mins[0] = mod->mins[1] = -maxwidth/2;
- mod->maxs[0] = mod->maxs[1] = maxwidth/2;
- mod->mins[2] = -maxheight/2;
- mod->maxs[2] = maxheight/2;
+// mod->mins[0] = mod->mins[1] = -maxwidth/2;
+// mod->maxs[0] = mod->maxs[1] = maxwidth/2;
+// mod->mins[2] = -maxheight/2;
+// mod->maxs[2] = maxheight/2;
//
// load the frames
{
for (j = 0;j < animscenes[i].framecount;j++)
{
- Mod_LoadSpriteFrame (framedata[realframes], frames + realframes, i, 1, &palette[0][0]);
+ Mod_LoadSpriteFrame (framedata[realframes], frames + realframes, i, 1, &palette[0][0], &modelradius);
realframes++;
}
}
mod->type = mod_sprite;
+ modelradius = sqrt(modelradius);
+ for (i = 0;i < 3;i++)
+ {
+ mod->normalmins[i] = mod->yawmins[i] = mod->rotatedmins[i] = -modelradius;
+ mod->normalmaxs[i] = mod->yawmaxs[i] = mod->rotatedmaxs[i] = modelradius;
+ }
+
// move the complete, relocatable sprite model to the cache
end = Hunk_LowMark ();
mod->cachesize = total = end - start;
Hunk_FreeToLowMark (start);
}
+void Mod_Sprite_SERAddEntity(void)
+{
+ R_ClipSprite();
+}
+
/*
=================
Host_Error ("Mod_LoadSpriteModel: %s has wrong version number (%i should be 1 (quake) or 32 (sprite32) or 2 (halflife)", mod->name, version);
break;
}
+ mod->SERAddEntity = Mod_Sprite_SERAddEntity;
+ mod->DrawEarly = R_DrawSpriteModel;
+ mod->DrawLate = NULL;
+ mod->DrawShadow = NULL;
}
//float viewportalpoints[16*3];
static float boxpoints[4*3];
-int R_ClipPolygonToPlane(float *in, float *out, int inpoints, int maxoutpoints, tinyplane_t *p)
+int Portal_ClipPolygonToPlane(float *in, float *out, int inpoints, int maxoutpoints, tinyplane_t *p)
{
int i, outpoints, prevside, side;
float *prevpoint, prevdist, dist, dot;
}
/*
-void R_TriangleToPlane(vec3_t point1, vec3_t point2, vec3_t point3, tinyplane_t *p)
+void Portal_TriangleToPlane(vec3_t point1, vec3_t point2, vec3_t point3, tinyplane_t *p)
{
vec3_t v1, v2;
VectorSubtract(point1, point2, v1);
}
*/
-int R_PortalThroughPortalPlanes(tinyplane_t *clipplanes, int clipnumplanes, float *targpoints, int targnumpoints, float *out, int maxpoints)
+int Portal_PortalThroughPortalPlanes(tinyplane_t *clipplanes, int clipnumplanes, float *targpoints, int targnumpoints, float *out, int maxpoints)
{
int numpoints, i;
if (targnumpoints < 3)
memcpy(&portaltemppoints[0][0][0], targpoints, numpoints * 3 * sizeof(float));
for (i = 0;i < clipnumplanes;i++)
{
- numpoints = R_ClipPolygonToPlane(&portaltemppoints[0][0][0], &portaltemppoints[1][0][0], numpoints, 256, clipplanes + i);
+ numpoints = Portal_ClipPolygonToPlane(&portaltemppoints[0][0][0], &portaltemppoints[1][0][0], numpoints, 256, clipplanes + i);
if (numpoints < 3)
return numpoints;
memcpy(&portaltemppoints[0][0][0], &portaltemppoints[1][0][0], numpoints * 3 * sizeof(float));
// only flow through portals facing away from the viewer
if (PlaneDiff(eye, (&p->plane)) < 0)
{
- newpoints = R_PortalThroughPortalPlanes(&portalplanes[firstclipplane], numclipplanes, (float *) p->points, p->numpoints, &portaltemppoints2[0][0], 256);
+ newpoints = Portal_PortalThroughPortalPlanes(&portalplanes[firstclipplane], numclipplanes, (float *) p->points, p->numpoints, &portaltemppoints2[0][0], 256);
if (newpoints < 3)
continue;
else if (firstclipplane + numclipplanes + newpoints > MAXRECURSIVEPORTALPLANES)
newplanes = &portalplanes[firstclipplane + numclipplanes];
for (prev = newpoints - 1, i = 0;i < newpoints;prev = i, i++)
{
-// R_TriangleToPlane(eye, portaltemppoints2[i], portaltemppoints2[prev], newplanes + i);
+// Portal_TriangleToPlane(eye, portaltemppoints2[i], portaltemppoints2[prev], newplanes + i);
VectorSubtract(eye, portaltemppoints2[i], v1);
VectorSubtract(portaltemppoints2[prev], portaltemppoints2[i], v2);
CrossProduct(v1, v2, newplanes[i].normal);
// calculate the planes, and make sure the polygon can see it's own center
for (prev = numpoints - 1, i = 0;i < numpoints;prev = i, i++)
{
-// R_TriangleToPlane(eye, portaltemppoints2[i], portaltemppoints2[prev], newplanes + i);
+// Portal_TriangleToPlane(eye, portaltemppoints2[i], portaltemppoints2[prev], newplanes + i);
VectorSubtract(eye, (&polypoints[i * 3]), v1);
VectorSubtract((&polypoints[prev * 3]), (&polypoints[i * 3]), v2);
CrossProduct(v1, v2, portalplanes[i].normal);
VectorCopy (min, bounds[0]);
VectorCopy (max, bounds[1]);
-
+
rmin[0] = rmin[1] = rmin[2] = 9999;
rmax[0] = rmax[1] = rmax[2] = -9999;
for (i=0, check = sv.model_precache ; *check ; i++, check++)
if (!strcmp(*check, m))
break;
-
+
if (!*check)
PR_RunError ("no precache: %s\n", m);
-
+
e->v.model = m - pr_strings;
e->v.modelindex = i; //SV_ModelIndex (m);
mod = sv.models[ (int)e->v.modelindex]; // Mod_ForName (m, true);
-
+
if (mod)
/*
{ // LordHavoc: corrected model bounding box, but for compatibility that means I have to break it here
SetMinMaxSize (e, mod->mins, mod->maxs, true);
}
*/
- SetMinMaxSize (e, mod->mins, mod->maxs, true);
+ SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
else
SetMinMaxSize (e, vec3_origin, vec3_origin, true);
}
pr_global_struct->trace_inopen = trace.inopen;
VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
- pr_global_struct->trace_plane_dist = trace.plane.dist;
+ pr_global_struct->trace_plane_dist = trace.plane.dist;
if (trace.ent)
pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
else
pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
+ // FIXME: add trace_endcontents
}
case ev_string:
sprintf (line, "%s", pr_strings + val->string);
break;
- case ev_entity:
+ case ev_entity:
sprintf (line, "%i", NUM_FOR_EDICT(PROG_TO_EDICT(val->edict)));
break;
case ev_function:
val = (void *)&pr_globals[ofs];
def = ED_GlobalAtOfs(ofs);
if (!def)
- sprintf (line,"%i(??\?)", ofs); // LordHavoc: escaping the third ? so it is not a trigraph
+ sprintf (line,"%i(\?\?\?)", ofs); // LordHavoc: escaping the ?s so it is not a trigraph
else
{
s = PR_ValueString (def->type, val);
def = ED_GlobalAtOfs(ofs);
if (!def)
- sprintf (line,"%i(??\?)", ofs); // LordHavoc: escaping the third ? so it is not a trigraph
+ sprintf (line,"%i(\?\?\?)", ofs); // LordHavoc: escaping the ?s so it is not a trigraph
else
sprintf (line,"%i(%s)", ofs, pr_strings + def->s_name);
else
*new_p++ = string[i];
}
-
+
return new;
}
char *v, *w;
void *d;
dfunction_t *func;
-
+
d = (void *)((int *)base + key->ofs);
-
+
switch (key->type & ~DEF_SAVEGLOBAL)
{
case ev_string:
n--;
}
- // parse value
+ // parse value
data = COM_Parse (data);
if (!data)
Host_Error ("ED_ParseEntity: EOF without closing brace");
pr_global_struct->self = EDICT_TO_PROG(ent);
PR_ExecuteProgram (func - pr_functions, "");
- }
+ }
Con_DPrintf ("%i entities inhibited\n", inhibit);
}
+typedef struct dpfield_s
+{
+ int type;
+ char *string;
+}
+dpfield_t;
+
+#define DPFIELDS (sizeof(dpfields) / sizeof(dpfield_t))
+
+dpfield_t dpfields[] =
+{
+ {ev_float, "gravity"},
+ {ev_float, "button3"},
+ {ev_float, "button4"},
+ {ev_float, "button5"},
+ {ev_float, "button6"},
+ {ev_float, "button7"},
+ {ev_float, "button8"},
+ {ev_float, "glow_size"},
+ {ev_float, "glow_trail"},
+ {ev_float, "glow_color"},
+ {ev_float, "items2"},
+ {ev_float, "scale"},
+ {ev_float, "alpha"},
+ {ev_float, "renderamt"},
+ {ev_float, "rendermode"},
+ {ev_float, "fullbright"},
+ {ev_float, "ammo_shells1"},
+ {ev_float, "ammo_nails1"},
+ {ev_float, "ammo_lava_nails"},
+ {ev_float, "ammo_rockets1"},
+ {ev_float, "ammo_multi_rockets"},
+ {ev_float, "ammo_cells1"},
+ {ev_float, "ammo_plasma"},
+ {ev_float, "idealpitch"},
+ {ev_float, "pitch_speed"},
+ {ev_entity, "viewmodelforclient"},
+ {ev_entity, "nodrawtoclient"},
+ {ev_entity, "exteriormodeltoclient"},
+ {ev_entity, "drawonlytoclient"},
+ {ev_vector, "colormod"},
+ {ev_float, "ping"},
+ {ev_vector, "movement"},
+ {ev_float, "pmodel"},
+ {ev_vector, "punchvector"}
+};
+
/*
===============
PR_LoadProgs
*/
void PR_LoadProgs (void)
{
- int i;
+ int i;
dstatement_t *st;
+ ddef_t *infielddefs;
// flush the non-C variable lookup cache
for (i=0 ; i<GEFV_CACHESIZE ; i++)
// byte swap the header
for (i=0 ; i<sizeof(*progs)/4 ; i++)
- ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
+ ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
if (progs->version != PROG_VERSION)
Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
pr_strings = (char *)progs + progs->ofs_strings;
pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
- pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
+
+ // we need to expand the fielddefs list to include all the engine fields,
+ // so allocate a new place for it
+ infielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
+ pr_fielddefs = Hunk_AllocName((progs->numfielddefs + DPFIELDS) * sizeof(ddef_t), "progs fields\n");
+
pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements);
+ // moved edict_size calculation down below field adding code
+
pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals);
pr_globals = (float *)pr_global_struct;
-
- pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
-
- pr_edictareasize = pr_edict_size * MAX_EDICTS;
// byte swap the lumps
for (i=0 ; i<progs->numstatements ; i++)
pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
pr_functions[i].locals = LittleLong (pr_functions[i].locals);
- }
+ }
for (i=0 ; i<progs->numglobaldefs ; i++)
{
pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
}
- for (i=0 ; i<progs->numfielddefs ; i++)
+ // copy the progs fields to the new fields list
+ for (i = 0;i < progs->numfielddefs;i++)
{
- pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type);
+ pr_fielddefs[i].type = LittleShort (infielddefs[i].type);
if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
- pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs);
- pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name);
+ pr_fielddefs[i].ofs = LittleShort (infielddefs[i].ofs);
+ pr_fielddefs[i].s_name = LittleLong (infielddefs[i].s_name);
+ }
+
+ // append the darkplaces fields
+ for (i = 0;i < DPFIELDS;i++)
+ {
+ pr_fielddefs[progs->numfielddefs].type = dpfields[i].type;
+ pr_fielddefs[progs->numfielddefs].ofs = progs->entityfields;
+ pr_fielddefs[progs->numfielddefs].s_name = dpfields[i].string - pr_strings;
+ if (pr_fielddefs[progs->numfielddefs].type == ev_vector)
+ progs->entityfields += 3;
+ else
+ progs->entityfields++;
+ progs->numfielddefs++;
}
for (i=0 ; i<progs->numglobals ; i++)
((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
+ // moved edict_size calculation down here, below field adding code
+ pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t);
+
+ pr_edictareasize = pr_edict_size * MAX_EDICTS;
+
// LordHavoc: bounds check anything static
for (i = 0,st = pr_statements;i < progs->numstatements;i++,st++)
{
// LordHavoc: for DarkPlaces, this overrides the number of decors (shell casings, gibs, etc)
Cvar_RegisterVariable (&decors);
// LordHavoc: Nehahra uses these to pass data around cutscene demos
- if (nehahra)
+ if (gamemode == GAME_NEHAHRA)
{
Cvar_RegisterVariable (&nehx00);Cvar_RegisterVariable (&nehx01);
Cvar_RegisterVariable (&nehx02);Cvar_RegisterVariable (&nehx03);
#define QUAKE_GAME // as opposed to utilities
-#define VERSION 1.50
-
extern int buildnumber;
#ifndef FALSE
{
int i;
int newwidth, newheight, newmaxedges, newmaxsurfs;
- newwidth = bound(80, (int) r_clipwidth.value, vid.width * 2);
- newheight = bound(60, (int) r_clipheight.value, vid.height * 2);
+ newwidth = bound(80, (int) r_clipwidth.value, vid.realwidth * 2);
+ newheight = bound(60, (int) r_clipheight.value, vid.realheight * 2);
newmaxedges = bound(128, (int) r_clipedges.value, 262144);
newmaxsurfs = bound(32, (int) r_clipsurfaces.value, 65536);
if (newwidth != clipwidth || newheight != clipheight || maxclipedges != newmaxedges || maxclipsurfs != newmaxsurfs)
}
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, clipwidth, clipheight, GL_LUMINANCE, GL_UNSIGNED_BYTE, clipbuffertex);
glBegin (GL_QUADS);
- glTexCoord2f (0 , 0 );glVertex2f (0 , 0 );
- glTexCoord2f (clipwidth / 256.0f, 0 );glVertex2f (vid.width, 0 );
- glTexCoord2f (clipwidth / 256.0f, clipheight / 256.0f);glVertex2f (vid.width, vid.height);
- glTexCoord2f (0 , clipheight / 256.0f);glVertex2f (0 , vid.height);
+ glTexCoord2f (0 , 0 );glVertex2f (0 , 0 );
+ glTexCoord2f (clipwidth / 256.0f, 0 );glVertex2f (vid.conwidth, 0 );
+ glTexCoord2f (clipwidth / 256.0f, clipheight / 256.0f);glVertex2f (vid.conwidth, vid.conheight);
+ glTexCoord2f (0 , clipheight / 256.0f);glVertex2f (0 , vid.conheight);
glEnd ();
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
{
byte *color;
float scale, base;
-// Draw_Character (r_refdef.vrect.x + r_refdef.vrect.width/2, r_refdef.vrect.y + r_refdef.vrect.height/2, '+');
if (num < 0 || num >= NUMCROSSHAIRS)
num = 0;
if (cl.viewentity)
else
base = 0.0f;
scale = crosshair_brightness.value / 255.0f;
- Draw_GenericPic(crosshairtex[num], color[0] * scale + base, color[1] * scale + base, color[2] * scale + base, crosshair_alpha.value, r_refdef.vrect.x + r_refdef.vrect.width * 0.5f - 8.0f, r_refdef.vrect.y + r_refdef.vrect.height * 0.5f - 8.0f, 16.0f, 16.0f);
+ Draw_GenericPic(crosshairtex[num], color[0] * scale + base, color[1] * scale + base, color[2] * scale + base, crosshair_alpha.value, vid.conwidth * 0.5f - 8.0f, vid.conheight * 0.5f - 8.0f, 16.0f, 16.0f);
}
{
vec3_t org;
vec3_t direction;
+ vec2_t texcoord[4];
vec3_t vert[4];
byte color[4];
rtexture_t *tex;
return;
ndist = PlaneDiff(decalorg, node->plane);
-
+
if (ndist > 16)
{
node = node->children[0];
}
}
-void R_Decal(vec3_t org, rtexture_t *tex, float scale, int cred, int cgreen, int cblue, int alpha)
+void R_Decal(vec3_t org, rtexture_t *tex, float s1, float t1, float s2, float t2, float scale, int cred, int cgreen, int cblue, int alpha)
{
vec3_t center, right, up;
decal_t *decal;
// set up the 4 corners
scale *= 0.5f;
VectorVectors(decal->direction, right, up);
- decal->vert[0][0] = center[0] - right[0] * scale - up[0] * scale; // texcoords 0 1
+ decal->texcoord[0][0] = s1;
+ decal->texcoord[0][1] = t1;
+ decal->vert[0][0] = center[0] - right[0] * scale - up[0] * scale;
decal->vert[0][1] = center[1] - right[1] * scale - up[1] * scale;
decal->vert[0][2] = center[2] - right[2] * scale - up[2] * scale;
- decal->vert[1][0] = center[0] - right[0] * scale + up[0] * scale; // texcoords 0 0
+ decal->texcoord[1][0] = s1;
+ decal->texcoord[1][1] = t2;
+ decal->vert[1][0] = center[0] - right[0] * scale + up[0] * scale;
decal->vert[1][1] = center[1] - right[1] * scale + up[1] * scale;
decal->vert[1][2] = center[2] - right[2] * scale + up[2] * scale;
- decal->vert[2][0] = center[0] + right[0] * scale + up[0] * scale; // texcoords 1 0
+ decal->texcoord[2][0] = s2;
+ decal->texcoord[2][1] = t2;
+ decal->vert[2][0] = center[0] + right[0] * scale + up[0] * scale;
decal->vert[2][1] = center[1] + right[1] * scale + up[1] * scale;
decal->vert[2][2] = center[2] + right[2] * scale + up[2] * scale;
- decal->vert[3][0] = center[0] + right[0] * scale - up[0] * scale; // texcoords 1 1
+ decal->texcoord[3][0] = s2;
+ decal->texcoord[3][1] = t1;
+ decal->vert[3][0] = center[0] + right[0] * scale - up[0] * scale;
decal->vert[3][1] = center[1] + right[1] * scale - up[1] * scale;
decal->vert[3][2] = center[2] + right[2] * scale - up[2] * scale;
// store the color
void GL_DrawDecals (void)
{
decal_t *p;
- int i, j, k, dynamiclight, bits, texnum;
- float scale, fr, fg, fb, dist, rad, mindist;
+ int i, j, k, dynamiclight, bits, texnum, iscale, ir, ig, ib, lit, cr, cg, cb;
+ float /*fscale, */fr, fg, fb, dist, rad, mindist;
byte *lightmap;
vec3_t v;
msurface_t *surf;
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_BLEND);
- glShadeModel(GL_FLAT);
+// glShadeModel(GL_FLAT);
glDepthMask(0); // disable zbuffer updates
glDisable(GL_ALPHA_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// get the surface lighting
surf = p->surface;
lightmap = p->lightmapaddress;
- fr = fg = fb = 0.0f;
- if (lightmap)
- {
- if (surf->styles[0] != 255)
- {
- scale = d_lightstylevalue[surf->styles[0]] * (1.0f / 256.0f);
- fr += lightmap[0] * scale;
- fg += lightmap[1] * scale;
- fb += lightmap[2] * scale;
- if (surf->styles[1] != 255)
- {
- lightmap += p->lightmapstep;
- scale = d_lightstylevalue[surf->styles[1]] * (1.0f / 256.0f);
- fr += lightmap[0] * scale;
- fg += lightmap[1] * scale;
- fb += lightmap[2] * scale;
- if (surf->styles[2] != 255)
- {
- lightmap += p->lightmapstep;
- scale = d_lightstylevalue[surf->styles[2]] * (1.0f / 256.0f);
- fr += lightmap[0] * scale;
- fg += lightmap[1] * scale;
- fb += lightmap[2] * scale;
- if (surf->styles[3] != 255)
- {
- lightmap += p->lightmapstep;
- scale = d_lightstylevalue[surf->styles[3]] * (1.0f / 256.0f);
- fr += lightmap[0] * scale;
- fg += lightmap[1] * scale;
- fb += lightmap[2] * scale;
- }
- }
- }
- }
- /*
- for (j = 0;j < MAXLIGHTMAPS && surf->styles[j] != 255;j++)
- {
- scale = d_lightstylevalue[surf->styles[j]] * (1.0f / 256.0f);
- fr += lightmap[0] * scale;
- fg += lightmap[1] * scale;
- fb += lightmap[2] * scale;
- lightmap += p->lightmapstep;
- }
- */
- }
// dynamic lighting
+ lit = false;
if (dynamiclight)
{
+ fr = fg = fb = 0.0f;
if (surf->dlightframe == r_framecount)
{
for (j = 0;j < 8;j++)
fr += rad * dl->color[0];
fg += rad * dl->color[1];
fb += rad * dl->color[2];
+ lit = true;
}
}
}
}
}
}
+ if (lit)
+ {
+#if SLOWMATH
+ ir = fr * 256.0f;
+ ig = fg * 256.0f;
+ ib = fb * 256.0f;
+#else
+ fr += 8388608.0f;
+ fg += 8388608.0f;
+ fb += 8388608.0f;
+ ir = (*((long *)&fr) & 0x7FFFFF) << 8;
+ ig = (*((long *)&fg) & 0x7FFFFF) << 8;
+ ib = (*((long *)&fb) & 0x7FFFFF) << 8;
+#endif
+ }
+ else
+ ir = ig = ib = 0;
+#if 1
+ if (lightmap)
+ {
+ if (surf->styles[0] != 255)
+ {
+ iscale = d_lightstylevalue[surf->styles[0]];
+ ir += lightmap[0] * iscale;
+ ig += lightmap[1] * iscale;
+ ib += lightmap[2] * iscale;
+ if (surf->styles[1] != 255)
+ {
+ lightmap += p->lightmapstep;
+ iscale = d_lightstylevalue[surf->styles[1]];
+ ir += lightmap[0] * iscale;
+ ig += lightmap[1] * iscale;
+ ib += lightmap[2] * iscale;
+ if (surf->styles[2] != 255)
+ {
+ lightmap += p->lightmapstep;
+ iscale = d_lightstylevalue[surf->styles[2]];
+ ir += lightmap[0] * iscale;
+ ig += lightmap[1] * iscale;
+ ib += lightmap[2] * iscale;
+ if (surf->styles[3] != 255)
+ {
+ lightmap += p->lightmapstep;
+ iscale = d_lightstylevalue[surf->styles[3]];
+ ir += lightmap[0] * iscale;
+ ig += lightmap[1] * iscale;
+ ib += lightmap[2] * iscale;
+ }
+ }
+ }
+ }
+ }
+#else
+ fr = fg = fb = 0.0f;
+ if (lightmap)
+ {
+ if (surf->styles[0] != 255)
+ {
+ fscale = d_lightstylevalue[surf->styles[0]] * (1.0f / 256.0f);
+ fr += lightmap[0] * fscale;
+ fg += lightmap[1] * fscale;
+ fb += lightmap[2] * fscale;
+ if (surf->styles[1] != 255)
+ {
+ lightmap += p->lightmapstep;
+ fscale = d_lightstylevalue[surf->styles[1]] * (1.0f / 256.0f);
+ fr += lightmap[0] * fscale;
+ fg += lightmap[1] * fscale;
+ fb += lightmap[2] * fscale;
+ if (surf->styles[2] != 255)
+ {
+ lightmap += p->lightmapstep;
+ fscale = d_lightstylevalue[surf->styles[2]] * (1.0f / 256.0f);
+ fr += lightmap[0] * fscale;
+ fg += lightmap[1] * fscale;
+ fb += lightmap[2] * fscale;
+ if (surf->styles[3] != 255)
+ {
+ lightmap += p->lightmapstep;
+ fscale = d_lightstylevalue[surf->styles[3]] * (1.0f / 256.0f);
+ fr += lightmap[0] * fscale;
+ fg += lightmap[1] * fscale;
+ fb += lightmap[2] * fscale;
+ }
+ }
+ }
+ }
+ /*
+ for (j = 0;j < MAXLIGHTMAPS && surf->styles[j] != 255;j++)
+ {
+ fscale = d_lightstylevalue[surf->styles[j]] * (1.0f / 256.0f);
+ fr += lightmap[0] * fscale;
+ fg += lightmap[1] * fscale;
+ fb += lightmap[2] * fscale;
+ lightmap += p->lightmapstep;
+ }
+ */
+ }
+#endif
/*
{
int ir, ig, ib;
glBindTexture(GL_TEXTURE_2D, texnum);
glBegin(GL_QUADS);
}
+ /*
if (lighthalf)
glColor4f(fr * p->color[0] * (1.0f / 255.0f / 256.0f), fg * p->color[1] * (1.0f / 255.0f / 256.0f), fb * p->color[2] * (1.0f / 255.0f / 256.0f), p->color[3] * (1.0f / 255.0f));
else
glColor4f(fr * p->color[0] * (1.0f / 255.0f / 128.0f), fg * p->color[1] * (1.0f / 255.0f / 128.0f), fb * p->color[2] * (1.0f / 255.0f / 128.0f), p->color[3] * (1.0f / 255.0f));
- glTexCoord2f(0, 1);
+ */
+ if (lighthalf)
+ {
+ cr = (ir * p->color[0]) >> 16;
+ cg = (ig * p->color[1]) >> 16;
+ cb = (ib * p->color[2]) >> 16;
+ }
+ else
+ {
+ cr = (ir * p->color[0]) >> 15;
+ cg = (ig * p->color[1]) >> 15;
+ cb = (ib * p->color[2]) >> 15;
+ }
+ cr = min(cr, 255);
+ cg = min(cg, 255);
+ cb = min(cb, 255);
+ glColor4ub(cr, cg, cb, p->color[3]);
+
+ glTexCoord2f(p->texcoord[0][0], p->texcoord[0][1]);
glVertex3fv(p->vert[0]);
- glTexCoord2f(0, 0);
+ glTexCoord2f(p->texcoord[1][0], p->texcoord[1][1]);
glVertex3fv(p->vert[1]);
- glTexCoord2f(1, 0);
+ glTexCoord2f(p->texcoord[2][0], p->texcoord[2][1]);
glVertex3fv(p->vert[2]);
- glTexCoord2f(1, 1);
+ glTexCoord2f(p->texcoord[3][0], p->texcoord[3][1]);
glVertex3fv(p->vert[3]);
}
}
-
+
if (r_render.value)
{
glEnd();
void GL_DrawDecals(void);
-void R_Decal(vec3_t org, rtexture_t *tex, float scale, int cred, int cgreen, int cblue, int alpha);
+void R_Decal(vec3_t org, rtexture_t *tex, float s1, float t1, float s2, float t2, float scale, int cred, int cgreen, int cblue, int alpha);
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
#include "quakedef.h"
-float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal);
-
#define MAX_EXPLOSIONS 64
#define EXPLOSIONGRID 16
#define EXPLOSIONVERTS ((EXPLOSIONGRID+1)*(EXPLOSIONGRID+1))
#define EXPLOSIONTRIS (EXPLOSIONVERTS*2)
-#define EXPLOSIONSTARTRADIUS (0.0f)
-#define EXPLOSIONSTARTVELOCITY (500.0f)
+#define EXPLOSIONSTARTRADIUS (20.0f)
+#define EXPLOSIONSTARTVELOCITY (256.0f)
#define EXPLOSIONFADESTART (1.5f)
-#define EXPLOSIONFADERATE (6.0f)
+#define EXPLOSIONFADERATE (4.5f)
+/*
+#define MAX_EXPLOSIONGAS (MAX_EXPLOSIONS * EXPLOSIONGAS)
+#define EXPLOSIONGAS 8
+#define EXPLOSIONGASSTARTRADIUS (15.0f)
+#define EXPLOSIONGASSTARTVELOCITY (50.0f)
+#define GASDENSITY_SCALER (32768.0f / EXPLOSIONGAS)
+#define GASFADERATE (GASDENSITY_SCALER * EXPLOSIONGAS * 2)
+
+typedef struct explosiongas_s
+{
+ float pressure;
+ vec3_t origin;
+ vec3_t velocity;
+}
+explosiongas_t;
+
+explosiongas_t explosiongas[MAX_EXPLOSIONGAS];
+*/
vec3_t explosionspherevert[EXPLOSIONVERTS];
vec3_t explosionspherevertvel[EXPLOSIONVERTS];
}
explosion_t;
-explosion_t explosion[128];
+explosion_t explosion[MAX_EXPLOSIONS];
rtexture_t *explosiontexture;
rtexture_t *explosiontexturefog;
void r_explosion_start(void)
{
int x, y;
- byte noise1[128][128], noise2[128][128], data[128][128][4];
- fractalnoise(&noise1[0][0], 128, 2);
- fractalnoise(&noise2[0][0], 128, 2);
+ byte noise1[128][128], noise2[128][128], noise3[128][128], data[128][128][4];
+ fractalnoise(&noise1[0][0], 128, 32);
+ fractalnoise(&noise2[0][0], 128, 4);
+ fractalnoise(&noise3[0][0], 128, 4);
for (y = 0;y < 128;y++)
{
for (x = 0;x < 128;x++)
{
int j, r, g, b, a;
- j = noise1[y][x] * 3 - 128;
+ j = (noise1[y][x] * noise2[y][x]) * 3 / 256 - 128;
r = (j * 512) / 256;
g = (j * 256) / 256;
b = (j * 128) / 256;
- a = noise2[y][x];
+ a = noise3[y][x] * 3 - 128;
data[y][x][0] = bound(0, r, 255);
data[y][x][1] = bound(0, g, 255);
data[y][x][2] = bound(0, b, 255);
void r_explosion_newmap(void)
{
memset(explosion, 0, sizeof(explosion));
+// memset(explosiongas, 0, sizeof(explosiongas));
}
void R_Explosion_Init(void)
void R_NewExplosion(vec3_t org)
{
int i, j;
- float dist;
+ float dist, v[3];
byte noise[EXPLOSIONGRID*EXPLOSIONGRID];
- fractalnoise(noise, EXPLOSIONGRID, 2);
+ fractalnoise(noise, EXPLOSIONGRID, 4);
for (i = 0;i < MAX_EXPLOSIONS;i++)
{
if (explosion[i].alpha <= 0.0f)
explosion[i].alpha = EXPLOSIONFADESTART;
for (j = 0;j < EXPLOSIONVERTS;j++)
{
- dist = noise[explosionnoiseindex[j]] * (1.0f / 512.0f) + 0.5;
- explosion[i].vert[j][0] = explosionspherevert[j][0] * dist + org[0];
- explosion[i].vert[j][1] = explosionspherevert[j][1] * dist + org[1];
- explosion[i].vert[j][2] = explosionspherevert[j][2] * dist + org[2];
- explosion[i].vertvel[j][0] = explosionspherevertvel[j][0] * dist;
- explosion[i].vertvel[j][1] = explosionspherevertvel[j][1] * dist;
- explosion[i].vertvel[j][2] = explosionspherevertvel[j][2] * dist;
+ dist = noise[explosionnoiseindex[j]] * (1.0f / 256.0f) + 0.5;
+ VectorMA(org, dist, explosionspherevert[j], v);
+ TraceLine(org, v, explosion[i].vert[j], NULL, 0);
+ VectorScale(explosionspherevertvel[j], dist, explosion[i].vertvel[j]);
}
break;
}
}
+
+ /*
+ i = 0;
+ j = EXPLOSIONGAS;
+ while (i < MAX_EXPLOSIONGAS && j > 0)
+ {
+ while (explosiongas[i].pressure > 0)
+ {
+ i++;
+ if (i >= MAX_EXPLOSIONGAS)
+ return;
+ }
+ VectorRandom(v);
+ VectorMA(org, EXPLOSIONGASSTARTRADIUS, v, v);
+ TraceLine(org, v, explosiongas[i].origin, NULL, 0);
+ VectorRandom(v);
+ VectorScale(v, EXPLOSIONGASSTARTVELOCITY, explosiongas[i].velocity);
+ explosiongas[i].pressure = j * GASDENSITY_SCALER;
+ j--;
+ }
+ */
}
void R_DrawExplosion(explosion_t *e)
}
}
-void R_MoveExplosion(explosion_t *e, float frametime)
+void R_MoveExplosion(explosion_t *e, /*explosiongas_t **list, explosiongas_t **listend, */float frametime)
{
int i;
vec3_t end;
+ vec_t frictionscale;
+ /*
+ vec3_t diff;
+ vec_t dist;
+ explosiongas_t **l;
+ */
e->alpha -= frametime * EXPLOSIONFADERATE;
+ frictionscale = 1 - frametime;
+ frictionscale = bound(0, frictionscale, 1);
for (i = 0;i < EXPLOSIONVERTS;i++)
{
if (e->vertvel[i][0] || e->vertvel[i][1] || e->vertvel[i][2])
{
float f, dot;
vec3_t impact, normal;
- f = TraceLine(e->vert[i], end, impact, normal);
+ f = TraceLine(e->vert[i], end, impact, normal, 0);
VectorCopy(impact, e->vert[i]);
if (f < 1)
{
// clip velocity against the wall
- dot = -DotProduct(e->vertvel[i], normal);
+ dot = DotProduct(e->vertvel[i], normal) * -1.125f;
e->vertvel[i][0] += normal[0] * dot;
e->vertvel[i][1] += normal[1] * dot;
e->vertvel[i][2] += normal[2] * dot;
{
VectorCopy(end, e->vert[i]);
}
+ e->vertvel[i][2] += sv_gravity.value * frametime * -0.25f;
+ VectorScale(e->vertvel[i], frictionscale, e->vertvel[i]);
+ }
+ /*
+ for (l = list;l < listend;l++)
+ {
+ VectorSubtract(e->vert[i], (*l)->origin, diff);
+ dist = DotProduct(diff, diff);
+ if (dist < 4096 && dist >= 1)
+ {
+ dist = (*l)->pressure * frametime / dist;
+ VectorMA(e->vertvel[i], dist, diff, e->vertvel[i]);
+ }
+ }
+ */
+ }
+}
+
+/*
+void R_MoveExplosionGas(explosiongas_t *e, explosiongas_t **list, explosiongas_t **listend, float frametime)
+{
+ vec3_t end, diff;
+ vec_t dist, frictionscale;
+ explosiongas_t **l;
+ frictionscale = 1 - frametime;
+ frictionscale = bound(0, frictionscale, 1);
+ if (e->velocity[0] || e->velocity[1] || e->velocity[2])
+ {
+ end[0] = e->origin[0] + frametime * e->velocity[0];
+ end[1] = e->origin[1] + frametime * e->velocity[1];
+ end[2] = e->origin[2] + frametime * e->velocity[2];
+ if (r_explosionclip.value)
+ {
+ float f, dot;
+ vec3_t impact, normal;
+ f = TraceLine(e->origin, end, impact, normal, 0);
+ VectorCopy(impact, e->origin);
+ if (f < 1)
+ {
+ // clip velocity against the wall
+ dot = DotProduct(e->velocity, normal) * -1.3f;
+ e->velocity[0] += normal[0] * dot;
+ e->velocity[1] += normal[1] * dot;
+ e->velocity[2] += normal[2] * dot;
+ }
+ }
+ else
+ {
+ VectorCopy(end, e->origin);
+ }
+ e->velocity[2] += sv_gravity.value * frametime;
+ VectorScale(e->velocity, frictionscale, e->velocity);
+ }
+ for (l = list;l < listend;l++)
+ {
+ if (*l != e)
+ {
+ VectorSubtract(e->origin, (*l)->origin, diff);
+ dist = DotProduct(diff, diff);
+ if (dist < 4096 && dist >= 1)
+ {
+ dist = (*l)->pressure * frametime / dist;
+ VectorMA(e->velocity, dist, diff, e->velocity);
+ }
}
}
}
+*/
void R_MoveExplosions(void)
{
int i;
float frametime;
+// explosiongas_t *gaslist[MAX_EXPLOSIONGAS], **l, **end;
frametime = cl.time - cl.oldtime;
+ /*
+ l = &gaslist[0];
+ for (i = 0;i < MAX_EXPLOSIONGAS;i++)
+ {
+ if (explosiongas[i].pressure > 0)
+ {
+ explosiongas[i].pressure -= frametime * GASFADERATE;
+ if (explosiongas[i].pressure > 0)
+ *l++ = &explosiongas[i];
+ }
+ }
+ end = l;
+ for (l = gaslist;l < end;l++)
+ R_MoveExplosionGas(*l, gaslist, end, frametime);
+ */
+
for (i = 0;i < MAX_EXPLOSIONS;i++)
{
if (explosion[i].alpha > 0.0f)
explosion[i].alpha = 0;
continue;
}
- R_MoveExplosion(&explosion[i], frametime);
+ R_MoveExplosion(&explosion[i], /*gaslist, end, */frametime);
}
}
}
-
#include "quakedef.h"
// LordHavoc: quite tempting to break apart this function to reuse the
// duplicated code, but I suspect it is better for performance
// this way
-void R_LerpAnimation(model_t *mod, int frame1, int frame2, double frame1start, double frame2start, double framelerp, frameblend_t *blend)
+// LordHavoc: later note: made FRAMEBLENDINSERT macro
+void R_LerpAnimation(entity_render_t *r)
{
int sub1, sub2, numframes, f, i, data;
- double sublerp, lerp, l;
+ double sublerp, lerp, d;
animscene_t *scene, *scenes;
+ frameblend_t *blend;
+ blend = r->frameblend;
- data = (int) Mod_Extradata(mod);
- if (!data)
- Host_Error("R_LerpAnimation: model not loaded\n");
- scenes = (animscene_t *) (mod->ofs_scenes + data);
-
- numframes = mod->numframes;
+ numframes = r->model->numframes;
- if ((frame1 >= numframes))
+ if ((r->frame1 >= numframes))
{
- Con_Printf ("R_LerpAnimation: no such frame %d\n", frame1);
- frame1 = 0;
+ Con_Printf ("CL_LerpAnimation: no such frame %d\n", r->frame1);
+ r->frame1 = 0;
}
- if ((frame2 >= numframes))
+ if ((r->frame2 >= numframes))
{
- Con_Printf ("R_LerpAnimation: no such frame %d\n", frame2);
- frame2 = 0;
+ Con_Printf ("CL_LerpAnimation: no such frame %d\n", r->frame2);
+ r->frame2 = 0;
}
- if (frame1 < 0)
- Host_Error ("R_LerpAnimation: frame1 is NULL\n");
+ // note: this could be removed, if the rendering code allows an empty blend array
+ if (r->frame1 < 0)
+ Host_Error ("CL_LerpAnimation: frame1 is NULL\n");
// round off very close blend percentages
- if (framelerp < (1.0f / 65536.0f))
- framelerp = 0;
- if (framelerp >= (65535.0f / 65536.0f))
- framelerp = 1;
+ if (r->framelerp < (1.0f / 65536.0f))
+ r->framelerp = 0;
+ if (r->framelerp >= (65535.0f / 65536.0f))
+ r->framelerp = 1;
blend[0].frame = blend[1].frame = blend[2].frame = blend[3].frame = -1;
blend[0].lerp = blend[1].lerp = blend[2].lerp = blend[3].lerp = 0;
- if (framelerp < 1)
+ if (r->model->ofs_scenes)
{
- scene = scenes + frame1;
- lerp = 1 - framelerp;
+ if (r->model->cachesize)
+ {
+ data = (int) Mod_Extradata(r->model);
+ if (!data)
+ Host_Error("CL_LerpAnimation: model not loaded\n");
+ scenes = (animscene_t *) (r->model->ofs_scenes + data);
+ }
+ else
+ scenes = (animscene_t *) r->model->ofs_scenes;
- if (scene->framecount > 1)
+ if (r->framelerp < 1 && r->frame1 >= 0)
{
- sublerp = scene->framerate * (cl.time - frame1start);
- sub1 = (int) (sublerp);
- sub2 = sub1 + 1;
- sublerp -= sub1;
- if (sublerp < (1.0f / 65536.0f))
- sublerp = 0;
- if (sublerp >= (65535.0f / 65536.0f))
- sublerp = 1;
- if (scene->loop)
+ scene = scenes + r->frame1;
+ lerp = 1 - r->framelerp;
+
+ if (scene->framecount > 1)
{
- sub1 = (sub1 % scene->framecount) + scene->firstframe;
- sub2 = (sub2 % scene->framecount) + scene->firstframe;
+ sublerp = scene->framerate * (cl.time - r->frame1time);
+ sub1 = (int) (sublerp);
+ sub2 = sub1 + 1;
+ sublerp -= sub1;
+ if (sublerp < (1.0f / 65536.0f))
+ sublerp = 0;
+ if (sublerp >= (65535.0f / 65536.0f))
+ sublerp = 1;
+ if (scene->loop)
+ {
+ sub1 = (sub1 % scene->framecount) + scene->firstframe;
+ sub2 = (sub2 % scene->framecount) + scene->firstframe;
+ }
+ else
+ {
+ sub1 = bound(0, sub1, (scene->framecount - 1)) + scene->firstframe;
+ sub2 = bound(0, sub2, (scene->framecount - 1)) + scene->firstframe;
+ }
+ f = sub1;
+ d = (1 - sublerp) * lerp;
+#define FRAMEBLENDINSERT\
+ if (d > 0)\
+ {\
+ for (i = 0;i < 4;i++)\
+ {\
+ if (blend[i].frame == f)\
+ {\
+ blend[i].lerp += d;\
+ break;\
+ }\
+ if (blend[i].lerp <= 0)\
+ {\
+ blend[i].frame = f;\
+ blend[i].lerp = d;\
+ break;\
+ }\
+ }\
+ }
+ FRAMEBLENDINSERT
+ f = sub2;
+ d = sublerp * lerp;
}
else
{
- sub1 = bound(0, sub1, (scene->framecount - 1)) + scene->firstframe;
- sub2 = bound(0, sub2, (scene->framecount - 1)) + scene->firstframe;
- }
- f = sub1;
- l = (1 - sublerp) * lerp;
- if (l > 0)
- {
- for (i = 0;i < 4;i++)
- {
- if (blend[i].frame == f)
- {
- blend[i].lerp += l;
- break;
- }
- if (blend[i].lerp <= 0)
- {
- blend[i].frame = f;
- blend[i].lerp = l;
- break;
- }
- }
+ f = scene->firstframe;
+ d = lerp;
}
- f = sub2;
- l = sublerp * lerp;
+ FRAMEBLENDINSERT
}
- else
- {
- f = scene->firstframe;
- l = lerp;
- }
- if (l > 0)
+ if (r->framelerp > 0 && r->frame2 >= 0)
{
- for (i = 0;i < 4;i++)
+ scene = scenes + r->frame2;
+ lerp = r->framelerp;
+
+ if (scene->framecount > 1)
{
- if (blend[i].frame == f)
+ sublerp = scene->framerate * (cl.time - r->frame1time);
+ sub1 = (int) (sublerp);
+ sub2 = sub1 + 1;
+ sublerp -= sub1;
+ if (sublerp < (1.0f / 65536.0f))
+ sublerp = 0;
+ if (sublerp >= (65535.0f / 65536.0f))
+ sublerp = 1;
+ if (scene->loop)
{
- blend[i].lerp += l;
- break;
+ sub1 = (sub1 % scene->framecount) + scene->firstframe;
+ sub2 = (sub2 % scene->framecount) + scene->firstframe;
}
- if (blend[i].lerp <= 0)
+ else
{
- blend[i].frame = f;
- blend[i].lerp = l;
- break;
+ sub1 = bound(0, sub1, (scene->framecount - 1)) + scene->firstframe;
+ sub2 = bound(0, sub2, (scene->framecount - 1)) + scene->firstframe;
}
- }
- }
- }
- if (framelerp > 0 && frame2 >= 0)
- {
- scene = scenes + frame2;
- lerp = framelerp;
-
- if (scene->framecount > 1)
- {
- sublerp = scene->framerate * (cl.time - frame1start);
- sub1 = (int) (sublerp);
- sub2 = sub1 + 1;
- sublerp -= sub1;
- if (sublerp < (1.0f / 65536.0f))
- sublerp = 0;
- if (sublerp >= (65535.0f / 65536.0f))
- sublerp = 1;
- if (scene->loop)
- {
- sub1 = (sub1 % scene->framecount) + scene->firstframe;
- sub2 = (sub2 % scene->framecount) + scene->firstframe;
+ f = sub1;
+ d = (1 - sublerp) * lerp;
+ FRAMEBLENDINSERT
+ f = sub2;
+ d = sublerp * lerp;
}
else
{
- sub1 = bound(0, sub1, (scene->framecount - 1)) + scene->firstframe;
- sub2 = bound(0, sub2, (scene->framecount - 1)) + scene->firstframe;
- }
- f = sub1;
- l = (1 - sublerp) * lerp;
- if (l > 0)
- {
- for (i = 0;i < 4;i++)
- {
- if (blend[i].frame == f)
- {
- blend[i].lerp += l;
- break;
- }
- if (blend[i].lerp <= 0)
- {
- blend[i].frame = f;
- blend[i].lerp = l;
- break;
- }
- }
+ f = scene->firstframe;
+ d = lerp;
}
- f = sub2;
- l = sublerp * lerp;
+ FRAMEBLENDINSERT
}
- else
+ }
+ else
+ {
+ // if there are no scenes, assume it is all single-frame groups
+ if (r->framelerp < 1 && r->frame1 >= 0)
{
- f = scene->firstframe;
- l = lerp;
+ f = r->frame1;
+ d = 1 - r->framelerp;
+ FRAMEBLENDINSERT
}
- if (l > 0)
+ if (r->framelerp > 0 && r->frame2 >= 0)
{
- for (i = 0;i < 4;i++)
- {
- if (blend[i].frame == f)
- {
- blend[i].lerp += l;
- break;
- }
- if (blend[i].lerp <= 0)
- {
- blend[i].frame = f;
- blend[i].lerp = l;
- break;
- }
- }
+ f = r->frame2;
+ d = r->framelerp;
+ FRAMEBLENDINSERT
}
}
}
+
-typedef struct
-{
- int frame;
- float lerp;
-}
-frameblend_t;
-
-void R_LerpAnimation(model_t *mod, int frame1, int frame2, double frame1start, double frame2start, double framelerp, frameblend_t *blend);
+void R_LerpAnimation(entity_render_t *r);
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
void R_AnimateLight (void)
{
int i,j,k;
-
+
//
// light animations
// 'm' is normal light, 'a' is no light, 'z' is double bright
surf = cl.worldmodel->surfaces + node->firstsurface;
for (i=0 ; i<node->numsurfaces ; i++, surf++)
{
- int d;
+ int d, impacts, impactt;
float dist, dist2, impact[3];
if (surf->visframe != r_framecount)
continue;
impact[1] = light->origin[1] - surf->plane->normal[1] * dist;
impact[2] = light->origin[2] - surf->plane->normal[2] * dist;
+ impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
+
+ d = bound(0, impacts, surf->extents[0] + 16) - impacts;
+ dist2 += d * d;
+ if (dist2 > maxdist)
+ continue;
+
+ impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
+
+ d = bound(0, impactt, surf->extents[1] + 16) - impactt;
+ dist2 += d * d;
+ if (dist2 > maxdist)
+ continue;
+
+
+ /*
d = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
if (d < 0)
continue;
}
}
+ */
if (surf->dlightframe != r_framecount) // not dynamic until now
{
{
if (c & (1<<i))
{
+ // warning to the clumsy: numleafs is one less than it should be, it only counts leafs with vis bits (skips leaf 0)
leafnum = (k << 3)+i+1;
if (leafnum > model->numleafs)
return;
// LordHavoc: make sure it is infront of the surface and not too far away
if (dist < radius && (dist > -0.25f || ((surf->flags & SURF_LIGHTBOTHSIDES) && dist > -radius)))
{
- int d;
+ int d, impacts, impactt;
float dist2, impact[3];
dist2 = dist * dist;
impact[1] = light->origin[1] - surf->plane->normal[1] * dist;
impact[2] = light->origin[2] - surf->plane->normal[2] * dist;
+ impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
+
+ d = bound(0, impacts, surf->extents[0] + 16) - impacts;
+ dist2 += d * d;
+ if (dist2 > maxdist)
+ continue;
+
+ impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
+
+ d = bound(0, impactt, surf->extents[1] + 16) - impactt;
+ dist2 += d * d;
+ if (dist2 > maxdist)
+ continue;
+
+ /*
d = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
if (d < 0)
continue;
}
}
+ */
if (surf->dlightframe != r_framecount) // not dynamic until now
{
k++;
continue;
}
-
+
k += *in++;
}
}
if (ds < surf->texturemins[0] || dt < surf->texturemins[1])
continue;
-
+
ds -= surf->texturemins[0];
dt -= surf->texturemins[1];
-
+
if (ds > surf->extents[0] || dt > surf->extents[1])
continue;
}
}
-void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic)
+void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic, mleaf_t *leaf)
{
- mleaf_t *leaf;
- leaf = Mod_PointInLeaf(p, cl.worldmodel);
+ if (leaf == NULL)
+ leaf = Mod_PointInLeaf(p, cl.worldmodel);
+
if (leaf->contents == CONTENTS_SOLID)
{
color[0] = color[1] = color[2] = 0;
dlightbits[0] = dlightbits[1] = dlightbits[2] = dlightbits[3] = dlightbits[4] = dlightbits[5] = dlightbits[6] = dlightbits[7] = 0;
return;
}
-
+
color[0] = color[1] = color[2] = r_ambient.value * 2.0f;
RecursiveLightPoint (color, cl.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536);
}
*/
-void R_LightModel(entity_t *ent, int numverts, vec3_t center, vec3_t basecolor)
+void R_LightModel(int numverts)
{
// LordHavoc: warning: reliance on int being 4 bytes here (of course the d_8to24table relies on that too...)
int i, j, nearlights = 0, color;
- vec3_t dist, mod;
- float t, t1, t2, t3, *avn;
+ vec3_t dist, mod, basecolor, center;
+ float t, t1, t2, t3, *avn, number;
byte r,g,b,a, *avc;
struct
{
int modeldlightbits[8];
avc = aliasvertcolor;
avn = aliasvertnorm;
- a = (byte) bound((int) 0, (int) (modelalpha * 255.0f), (int) 255);
+ VectorCopy(currentrenderentity->origin, center);
+ a = (byte) bound((int) 0, (int) (currentrenderentity->alpha * 255.0f), (int) 255);
if (lighthalf)
{
- mod[0] = ent->render.colormod[0] * 0.5f;
- mod[1] = ent->render.colormod[1] * 0.5f;
- mod[2] = ent->render.colormod[2] * 0.5f;
+ mod[0] = currentrenderentity->colormod[0] * 0.5f;
+ mod[1] = currentrenderentity->colormod[1] * 0.5f;
+ mod[2] = currentrenderentity->colormod[2] * 0.5f;
}
else
{
- mod[0] = ent->render.colormod[0];
- mod[1] = ent->render.colormod[1];
- mod[2] = ent->render.colormod[2];
+ mod[0] = currentrenderentity->colormod[0];
+ mod[1] = currentrenderentity->colormod[1];
+ mod[2] = currentrenderentity->colormod[2];
}
- if (ent->render.effects & EF_FULLBRIGHT)
+ if (currentrenderentity->effects & EF_FULLBRIGHT)
{
- ((byte *)&color)[0] = (byte) (255.0f * mod[0]);
- ((byte *)&color)[1] = (byte) (255.0f * mod[1]);
- ((byte *)&color)[2] = (byte) (255.0f * mod[2]);
- ((byte *)&color)[3] = a;
- for (i = 0;i < numverts;i++)
+ if (a == 255)
+ memset(avc, 0, 4 * numverts);
+ else
{
- *((int *)avc) = color;
- avc += 4;
+ ((byte *)&color)[0] = (byte) (255.0f * mod[0]);
+ ((byte *)&color)[1] = (byte) (255.0f * mod[1]);
+ ((byte *)&color)[2] = (byte) (255.0f * mod[2]);
+ ((byte *)&color)[3] = a;
+ for (i = 0;i < numverts;i++)
+ {
+ *((int *)avc) = color;
+ avc += 4;
+ }
}
return;
}
t1 = cl_dlights[i].radius*cl_dlights[i].radius;
if (t2 < t1)
{
- // transform the light into the model's coordinate system
- if (gl_transform.value)
- softwareuntransform(cl_dlights[i].origin, nearlight[nearlights].origin);
- else
- {
- VectorCopy(cl_dlights[i].origin, nearlight[nearlights].origin);
- }
- nearlight[nearlights].color[0] = cl_dlights[i].color[0] * t1 * mod[0];
- nearlight[nearlights].color[1] = cl_dlights[i].color[1] * t1 * mod[1];
- nearlight[nearlights].color[2] = cl_dlights[i].color[2] * t1 * mod[2];
- if (r_lightmodels.value && (ent == NULL || ent != cl_dlights[i].ent))
- nearlights++;
- else
+ if (TraceLine(center, cl_dlights[i].origin, NULL, NULL, 0))
{
- t1 = 1.0f / t2;
- basecolor[0] += nearlight[nearlights].color[0] * t1;
- basecolor[1] += nearlight[nearlights].color[1] * t1;
- basecolor[2] += nearlight[nearlights].color[2] * t1;
+ // transform the light into the model's coordinate system
+ if (gl_transform.value)
+ softwareuntransform(cl_dlights[i].origin, nearlight[nearlights].origin);
+ else
+ VectorCopy(cl_dlights[i].origin, nearlight[nearlights].origin);
+ nearlight[nearlights].color[0] = cl_dlights[i].color[0] * t1 * mod[0];
+ nearlight[nearlights].color[1] = cl_dlights[i].color[1] * t1 * mod[1];
+ nearlight[nearlights].color[2] = cl_dlights[i].color[2] * t1 * mod[2];
+ if (r_lightmodels.value && currentrenderentity != cl_dlights[i].ent)
+ {
+ // boost color, to compensate for dark lighting calcs
+ VectorScale(nearlight[nearlights].color, cl_dlights[i].radius * 16.0f, nearlight[nearlights].color);
+ nearlights++;
+ }
+ else
+ {
+#if SLOWMATH
+ t1 = 1.0f / sqrt(t2);
+#else
+ number = t1;
+ *((long *)&t1) = 0x5f3759df - ((* (long *) &number) >> 1);
+ t1 = t1 * (1.5f - (number * 0.5f * t1 * t1));
+#endif
+ t1 = t1 * t1;
+ basecolor[0] += nearlight[nearlights].color[0] * t1;
+ basecolor[1] += nearlight[nearlights].color[1] * t1;
+ basecolor[2] += nearlight[nearlights].color[2] * t1;
+ }
}
}
}
((byte *)&color)[3] = a;
if (nearlights)
{
- int temp;
+ int i1, i2, i3;
vec3_t v;
- float *av;
+ float *av, number;
av = aliasvert;
- if (nearlights == 1)
+ for (i = 0;i < numverts;i++)
{
- for (i = 0;i < numverts;i++)
+ t1 = basecolor[0];
+ t2 = basecolor[1];
+ t3 = basecolor[2];
+ for (j = 0;j < nearlights;j++)
{
- VectorSubtract(nearlight[0].origin, av, v);
+ VectorSubtract(nearlight[j].origin, av, v);
t = DotProduct(avn,v);
if (t > 0)
{
- t /= (DotProduct(v,v) + LIGHTOFFSET);
- temp = (int) ((float) (basecolor[0] + nearlight[0].color[0] * t));
- avc[0] = bound(0, temp, 255);
- temp = (int) ((float) (basecolor[1] + nearlight[0].color[1] * t));
- avc[1] = bound(0, temp, 255);
- temp = (int) ((float) (basecolor[2] + nearlight[0].color[2] * t));
- avc[2] = bound(0, temp, 255);
- avc[3] = a;
+#if SLOWMATH
+ t = 1.0f / sqrt(DotProduct(v,v) + 1.0f);
+#else
+ number = DotProduct(v, v) + LIGHTOFFSET;
+ *((long *)&t) = 0x5f3759df - ((* (long *) &number) >> 1);
+ t = t * (1.5f - (number * 0.5f * t * t));
+#endif
+ t = t * t * t;
+ t1 += nearlight[j].color[0] * t;
+ t2 += nearlight[j].color[1] * t;
+ t3 += nearlight[j].color[2] * t;
}
- else
- *((int *)avc) = color;
- avc += 4;
- av += 3;
- avn += 3;
- }
- }
- else
- {
- for (i = 0;i < numverts;i++)
- {
- int lit;
- t1 = basecolor[0];
- t2 = basecolor[1];
- t3 = basecolor[2];
- lit = false;
- for (j = 0;j < nearlights;j++)
- {
- VectorSubtract(nearlight[j].origin, av, v);
- t = DotProduct(avn,v);
- if (t > 0)
- {
- t /= (DotProduct(v,v) + LIGHTOFFSET);
- t1 += nearlight[j].color[0] * t;
- t2 += nearlight[j].color[1] * t;
- t3 += nearlight[j].color[2] * t;
- lit = true;
- }
- }
- if (lit)
- {
- int i1, i2, i3;
- i1 = (int) t1;
- avc[0] = bound(0, i1, 255);
- i2 = (int) t2;
- avc[1] = bound(0, i2, 255);
- i3 = (int) t3;
- avc[2] = bound(0, i3, 255);
- avc[3] = a;
- }
- else // dodge the costly float -> int conversions
- *((int *)avc) = color;
- avc += 4;
- av += 3;
- avn += 3;
}
+
+ // FIXME: float to int conversions are very slow on x86 because of
+ // mode switchs (switch from nearest rounding to down, then back,
+ // each time), reimplement this part in assembly, SSE and 3DNow!
+ // versions recommended as well
+#if SLOWMATH
+ i1 = (int) t1;
+ i2 = (int) t2;
+ i3 = (int) t3;
+#else
+ // later note: implemented bit hacking float to integer,
+ // probably makes the issue irrelevant
+ t1 += 8388608.0f;
+ i1 = *((long *)&t1) & 0x007FFFFF;
+ t2 += 8388608.0f;
+ i2 = *((long *)&t2) & 0x007FFFFF;
+ t3 += 8388608.0f;
+ i3 = *((long *)&t3) & 0x007FFFFF;
+#endif
+
+ avc[0] = bound(0, i1, 255);
+ avc[1] = bound(0, i2, 255);
+ avc[2] = bound(0, i3, 255);
+ avc[3] = a;
+ avc += 4;
+ av += 3;
+ avn += 3;
}
}
else
-// LordHavoc: 256 dynamic lights
-#define MAX_DLIGHTS 256
-typedef struct
-{
- vec3_t origin;
- float radius;
- float die; // stop lighting after this time
- float decay; // drop this each second
- entity_t *ent; // the entity that spawned this light (can be NULL if it is not to be replaced repeatedly)
- vec3_t color; // LordHavoc: colored lighting
-} dlight_t;
-
-// LordHavoc: this affects the lighting scale of the whole game
-#define LIGHTOFFSET 4096.0f
-
-extern void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic);
+extern void R_CompleteLightPoint (vec3_t color, vec3_t p, int dynamic, mleaf_t *leaf);
extern void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits);
extern void R_DynamicLightPointNoMask(vec3_t color, vec3_t org);
extern void R_LightPoint (vec3_t color, vec3_t p);
+extern void R_AnimateLight (void);
+extern void R_LightModel (int numverts);
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
#define MAX_PARTICLES 16384 // default max # of particles at one time
#define ABSOLUTE_MIN_PARTICLES 512 // no fewer than this no matter what's on the command line
-// LordHavoc: added dust, smoke, snow, bloodcloud, and many others
typedef enum
{
- pt_static, pt_grav, pt_slowgrav, pt_blob, pt_blob2, pt_bulletsmoke, pt_smoke, pt_snow, pt_rain, pt_spark, pt_bubble, pt_fade, pt_steam, pt_splash, pt_splashpuff, pt_flame/*, pt_decal*/, pt_blood, pt_oneframe, pt_lavasplash
+ pt_static, pt_grav, pt_blob, pt_blob2, pt_bulletsmoke, pt_smoke, pt_snow, pt_rain, pt_spark, pt_bubble, pt_fade, pt_steam, pt_splash, pt_splashpuff, pt_flame, pt_blood, pt_oneframe, pt_lavasplash, pt_raindropsplash, pt_underwaterspark, pt_explosionsplash
}
ptype_t;
+typedef struct
+{
+ float s1, t1, s2, t2;
+}
+particletexture_t;
+
typedef struct particle_s
{
ptype_t type;
vec3_t org;
vec3_t vel;
- rtexture_t *tex;
- byte dynlight; // if set the particle will be dynamically lit (if r_dynamicparticles is on), used for smoke and blood
- byte rendermode; // a TPOLYTYPE_ value
- byte color;
- byte pad2;
+ particletexture_t *tex;
float die;
float scale;
float alpha; // 0-255
float bounce; // how much bounce-back from a surface the particle hits (0 = no physics, 1 = stop and slide, 2 = keep bouncing forever, 1.5 is typical)
vec3_t oldorg;
vec3_t vel2; // used for snow fluttering (base velocity, wind for instance)
-// vec3_t direction; // used by decals
-// vec3_t decalright; // used by decals
-// vec3_t decalup; // used by decals
+ float friction; // how much air friction affects this object (objects with a low mass/size ratio tend to get more air friction)
+ float pressure; // if non-zero, apply pressure to other particles
+ int dynlight; // if set the particle will be dynamically lit (if r_dynamicparticles is on), used for smoke and blood
+ int rendermode; // a TPOLYTYPE_ value
+ byte color[4];
}
particle_t;
-float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal);
-
-int ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61};
-int ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66};
-int ramp3[8] = {0x6d, 0x6b, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
-
-rtexture_t *particletexture;
-rtexture_t *smokeparticletexture[8];
-rtexture_t *rainparticletexture;
-rtexture_t *bubbleparticletexture;
-rtexture_t *bulletholetexture[8];
-rtexture_t *rocketglowparticletexture;
-
-particle_t *particles;
-int r_numparticles;
-
-vec3_t r_pright, r_pup, r_ppn;
-
-int numparticles;
-particle_t **freeparticles; // list used only in compacting particles array
-
-cvar_t r_particles = {CVAR_SAVE, "r_particles", "1"};
-cvar_t r_drawparticles = {0, "r_drawparticles", "1"};
-cvar_t r_particles_lighting = {CVAR_SAVE, "r_particles_lighting", "1"};
-cvar_t r_particles_bloodshowers = {CVAR_SAVE, "r_particles_bloodshowers", "1"};
-cvar_t r_particles_blood = {CVAR_SAVE, "r_particles_blood", "1"};
-cvar_t r_particles_smoke = {CVAR_SAVE, "r_particles_smoke", "1"};
-cvar_t r_particles_sparks = {CVAR_SAVE, "r_particles_sparks", "1"};
-cvar_t r_particles_bubbles = {CVAR_SAVE, "r_particles_bubbles", "1"};
-
-byte shadebubble(float dx, float dy, vec3_t light)
+static int particlepalette[256] =
+{
+ 0x000000,0x0f0f0f,0x1f1f1f,0x2f2f2f,0x3f3f3f,0x4b4b4b,0x5b5b5b,0x6b6b6b,
+ 0x7b7b7b,0x8b8b8b,0x9b9b9b,0xababab,0xbbbbbb,0xcbcbcb,0xdbdbdb,0xebebeb,
+ 0x0f0b07,0x170f0b,0x1f170b,0x271b0f,0x2f2313,0x372b17,0x3f2f17,0x4b371b,
+ 0x533b1b,0x5b431f,0x634b1f,0x6b531f,0x73571f,0x7b5f23,0x836723,0x8f6f23,
+ 0x0b0b0f,0x13131b,0x1b1b27,0x272733,0x2f2f3f,0x37374b,0x3f3f57,0x474767,
+ 0x4f4f73,0x5b5b7f,0x63638b,0x6b6b97,0x7373a3,0x7b7baf,0x8383bb,0x8b8bcb,
+ 0x000000,0x070700,0x0b0b00,0x131300,0x1b1b00,0x232300,0x2b2b07,0x2f2f07,
+ 0x373707,0x3f3f07,0x474707,0x4b4b0b,0x53530b,0x5b5b0b,0x63630b,0x6b6b0f,
+ 0x070000,0x0f0000,0x170000,0x1f0000,0x270000,0x2f0000,0x370000,0x3f0000,
+ 0x470000,0x4f0000,0x570000,0x5f0000,0x670000,0x6f0000,0x770000,0x7f0000,
+ 0x131300,0x1b1b00,0x232300,0x2f2b00,0x372f00,0x433700,0x4b3b07,0x574307,
+ 0x5f4707,0x6b4b0b,0x77530f,0x835713,0x8b5b13,0x975f1b,0xa3631f,0xaf6723,
+ 0x231307,0x2f170b,0x3b1f0f,0x4b2313,0x572b17,0x632f1f,0x733723,0x7f3b2b,
+ 0x8f4333,0x9f4f33,0xaf632f,0xbf772f,0xcf8f2b,0xdfab27,0xefcb1f,0xfff31b,
+ 0x0b0700,0x1b1300,0x2b230f,0x372b13,0x47331b,0x533723,0x633f2b,0x6f4733,
+ 0x7f533f,0x8b5f47,0x9b6b53,0xa77b5f,0xb7876b,0xc3937b,0xd3a38b,0xe3b397,
+ 0xab8ba3,0x9f7f97,0x937387,0x8b677b,0x7f5b6f,0x775363,0x6b4b57,0x5f3f4b,
+ 0x573743,0x4b2f37,0x43272f,0x371f23,0x2b171b,0x231313,0x170b0b,0x0f0707,
+ 0xbb739f,0xaf6b8f,0xa35f83,0x975777,0x8b4f6b,0x7f4b5f,0x734353,0x6b3b4b,
+ 0x5f333f,0x532b37,0x47232b,0x3b1f23,0x2f171b,0x231313,0x170b0b,0x0f0707,
+ 0xdbc3bb,0xcbb3a7,0xbfa39b,0xaf978b,0xa3877b,0x977b6f,0x876f5f,0x7b6353,
+ 0x6b5747,0x5f4b3b,0x533f33,0x433327,0x372b1f,0x271f17,0x1b130f,0x0f0b07,
+ 0x6f837b,0x677b6f,0x5f7367,0x576b5f,0x4f6357,0x475b4f,0x3f5347,0x374b3f,
+ 0x2f4337,0x2b3b2f,0x233327,0x1f2b1f,0x172317,0x0f1b13,0x0b130b,0x070b07,
+ 0xfff31b,0xefdf17,0xdbcb13,0xcbb70f,0xbba70f,0xab970b,0x9b8307,0x8b7307,
+ 0x7b6307,0x6b5300,0x5b4700,0x4b3700,0x3b2b00,0x2b1f00,0x1b0f00,0x0b0700,
+ 0x0000ff,0x0b0bef,0x1313df,0x1b1bcf,0x2323bf,0x2b2baf,0x2f2f9f,0x2f2f8f,
+ 0x2f2f7f,0x2f2f6f,0x2f2f5f,0x2b2b4f,0x23233f,0x1b1b2f,0x13131f,0x0b0b0f,
+ 0x2b0000,0x3b0000,0x4b0700,0x5f0700,0x6f0f00,0x7f1707,0x931f07,0xa3270b,
+ 0xb7330f,0xc34b1b,0xcf632b,0xdb7f3b,0xe3974f,0xe7ab5f,0xefbf77,0xf7d38b,
+ 0xa77b3b,0xb79b37,0xc7c337,0xe7e357,0x7fbfff,0xabe7ff,0xd7ffff,0x670000,
+ 0x8b0000,0xb30000,0xd70000,0xff0000,0xfff393,0xfff7c7,0xffffff,0x9f5b53
+};
+
+static int explosparkramp[8] = {0x4b0700, 0x6f0f00, 0x931f07, 0xb7330f, 0xcf632b, 0xe3974f, 0xffe7b5, 0xffffff};
+//static int explounderwatersparkramp[8] = {0x00074b, 0x000f6f, 0x071f93, 0x0f33b7, 0x2b63cf, 0x4f97e3, 0xb5e7ff, 0xffffff};
+
+static rtexture_t *particlefonttexture;
+
+static particletexture_t particletexture;
+static particletexture_t smokeparticletexture[8];
+static particletexture_t rainparticletexture;
+static particletexture_t bubbleparticletexture;
+static particletexture_t bulletholetexture[8];
+static particletexture_t rocketglowparticletexture;
+static particletexture_t raindropsplashparticletexture[16];
+
+static particle_t *particles;
+static int r_numparticles;
+
+static int numparticles;
+static particle_t **freeparticles; // list used only in compacting particles array
+
+static cvar_t r_particles = {CVAR_SAVE, "r_particles", "1"};
+static cvar_t r_drawparticles = {0, "r_drawparticles", "1"};
+static cvar_t r_particles_lighting = {CVAR_SAVE, "r_particles_lighting", "1"};
+static cvar_t r_particles_bloodshowers = {CVAR_SAVE, "r_particles_bloodshowers", "1"};
+static cvar_t r_particles_blood = {CVAR_SAVE, "r_particles_blood", "1"};
+static cvar_t r_particles_smoke = {CVAR_SAVE, "r_particles_smoke", "1"};
+static cvar_t r_particles_sparks = {CVAR_SAVE, "r_particles_sparks", "1"};
+static cvar_t r_particles_bubbles = {CVAR_SAVE, "r_particles_bubbles", "1"};
+static cvar_t r_particles_explosions = {CVAR_SAVE, "r_particles_explosions", "0"};
+
+static byte shadebubble(float dx, float dy, vec3_t light)
{
float dz, f, dot;
vec3_t normal;
return 0;
}
-void R_InitParticleTexture (void)
+static void R_InitParticleTexture (void)
{
- int x,y,d,i,m;
- float dx, dy;
+ int x,y,d,i,m, texnum;
+ float dx, dy, radius, f, f2;
byte data[32][32][4], noise1[64][64], noise2[64][64];
vec3_t light;
+ byte particletexturedata[256][256][4];
+
+ memset(&particletexturedata[0][0][0], 255, sizeof(particletexturedata));
+ texnum = 0;
+ #define SETUPTEX(var)\
+ {\
+ int basex, basey, y;\
+ if (texnum >= 64)\
+ {\
+ Sys_Error("R_InitParticleTexture: ran out of textures (64)\n");\
+ return; /* only to hush compiler */ \
+ }\
+ basex = (texnum & 7) * 32;\
+ basey = ((texnum >> 3) & 7) * 32;\
+ var.s1 = (basex + 1) / 256.0f;\
+ var.t1 = (basey + 1) / 256.0f;\
+ var.s2 = (basex + 31) / 256.0f;\
+ var.t2 = (basey + 31) / 256.0f;\
+ for (y = 0;y < 32;y++)\
+ memcpy(&particletexturedata[basey + y][basex][0], &data[y][0][0], 32*4);\
+ texnum++;\
+ }
for (y = 0;y < 32;y++)
{
data[y][x][3] = (byte) d;
}
}
- particletexture = R_LoadTexture ("particletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+ SETUPTEX(particletexture)
+// particletexture = R_LoadTexture ("particletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
for (i = 0;i < 8;i++)
{
dy = y - 16;
for (x = 0;x < 32;x++)
{
- d = (noise1[y][x] - 128) * 2 + 128;
+ d = (noise1[y][x] - 128) * 2 + 64; // was + 128
d = bound(0, d, 255);
data[y][x][0] = data[y][x][1] = data[y][x][2] = d;
dx = x - 16;
- d = (noise2[y][x] - 128) * 4 + 128;
+ d = (noise2[y][x] - 128) * 3 + 192;
if (d > 0)
d = (d * (256 - (int) (dx*dx+dy*dy))) >> 8;
d = bound(0, d, 255);
}
while (m < 224);
- smokeparticletexture[i] = R_LoadTexture (va("smokeparticletexture%d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+ SETUPTEX(smokeparticletexture[i])
+// smokeparticletexture[i] = R_LoadTexture (va("smokeparticletexture%02d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
}
light[0] = 1;light[1] = 1;light[2] = 1;
data[y][x][3] = shadebubble((x - 16) * (1.0 / 8.0), y < 24 ? (y - 24) * (1.0 / 24.0) : (y - 24) * (1.0 / 8.0), light);
}
}
- rainparticletexture = R_LoadTexture ("rainparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+ SETUPTEX(rainparticletexture)
+// rainparticletexture = R_LoadTexture ("rainparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
light[0] = 1;light[1] = 1;light[2] = 1;
VectorNormalize(light);
data[y][x][3] = shadebubble((x - 16) * (1.0 / 16.0), (y - 16) * (1.0 / 16.0), light);
}
}
- bubbleparticletexture = R_LoadTexture ("bubbleparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+ SETUPTEX(bubbleparticletexture)
+// bubbleparticletexture = R_LoadTexture ("bubbleparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
for (i = 0;i < 8;i++)
{
}
}
- bulletholetexture[i] = R_LoadTexture (va("bulletholetexture%d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+ SETUPTEX(bulletholetexture[i])
+// bulletholetexture[i] = R_LoadTexture (va("bulletholetexture%02d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
}
for (y = 0;y < 32;y++)
data[y][x][3] = bound(0, d * 1.0f, 255);
}
}
- rocketglowparticletexture = R_LoadTexture ("glowparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+ SETUPTEX(rocketglowparticletexture)
+// rocketglowparticletexture = R_LoadTexture ("glowparticletexture", 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+
+ for (i = 0;i < 16;i++)
+ {
+ radius = i * 3.0f / 16.0f;
+ f2 = 255.0f * ((15.0f - i) / 15.0f);
+ for (y = 0;y < 32;y++)
+ {
+ dy = (y - 16) * 0.25f;
+ for (x = 0;x < 32;x++)
+ {
+ dx = (x - 16) * 0.25f;
+ data[y][x][0] = data[y][x][1] = data[y][x][2] = 255;
+ f = (1.0 - fabs(radius - sqrt(dx*dx+dy*dy))) * f2;
+ f = bound(0.0f, f, 255.0f);
+ data[y][x][3] = (int) f;
+ }
+ }
+ SETUPTEX(raindropsplashparticletexture[i])
+// raindropsplashparticletexture[i] = R_LoadTexture (va("raindropslashparticletexture%02d", i), 32, 32, &data[0][0][0], TEXF_MIPMAP | TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
+ }
+
+ particlefonttexture = R_LoadTexture ("particlefont", 256, 256, &particletexturedata[0][0][0], TEXF_ALPHA | TEXF_RGBA | TEXF_PRECACHE);
}
-void r_part_start(void)
+static void r_part_start(void)
{
particles = (particle_t *) qmalloc(r_numparticles * sizeof(particle_t));
freeparticles = (void *) qmalloc(r_numparticles * sizeof(particle_t *));
R_InitParticleTexture ();
}
-void r_part_shutdown(void)
+static void r_part_shutdown(void)
{
numparticles = 0;
qfree(particles);
qfree(freeparticles);
}
-void r_part_newmap(void)
+static void r_part_newmap(void)
{
numparticles = 0;
}
r_numparticles = MAX_PARTICLES;
}
- Cmd_AddCommand ("pointfile", R_ReadPointFile_f);
+ Cmd_AddCommand ("pointfile", R_ReadPointFile_f);
Cvar_RegisterVariable (&r_particles);
Cvar_RegisterVariable (&r_drawparticles);
Cvar_RegisterVariable (&r_particles_smoke);
Cvar_RegisterVariable (&r_particles_sparks);
Cvar_RegisterVariable (&r_particles_bubbles);
+ Cvar_RegisterVariable (&r_particles_explosions);
R_RegisterModule("R_Particles", r_part_start, r_part_shutdown, r_part_newmap);
}
//void particle(int ptype, int pcolor, int ptex, int prendermode, int plight, float pscale, float palpha, float ptime, float pbounce, float px, float py, float pz, float pvx, float pvy, float pvz)
-#define particle(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, px, py, pz, pvx, pvy, pvz)\
+#define particle(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, px, py, pz, pvx, pvy, pvz, ptime2, pvx2, pvy2, pvz2, pfriction, ppressure)\
{\
particle_t *part;\
+ int tempcolor;\
if (numparticles >= r_numparticles)\
return;\
part = &particles[numparticles++];\
part->type = (ptype);\
- part->color = (pcolor);\
- part->tex = (ptex);\
- part->dynlight = (plight);\
- part->rendermode = (prendermode);\
- part->scale = (pscale);\
- part->alpha = (palpha);\
- part->die = cl.time + (ptime);\
- part->bounce = (pbounce);\
- part->org[0] = (px);\
- part->org[1] = (py);\
- part->org[2] = (pz);\
- part->vel[0] = (pvx);\
- part->vel[1] = (pvy);\
- part->vel[2] = (pvz);\
- part->time2 = 0;\
- part->vel2[0] = part->vel2[1] = part->vel2[2] = 0;\
-}
-/*
-#define particle2(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, pbase, poscale, pvscale)\
-{\
- particle_t *part;\
- if (numparticles >= r_numparticles)\
- return;\
- part = &particles[numparticles++];\
- part->type = (ptype);\
- part->color = (pcolor);\
- part->tex = (ptex);\
- part->dynlight = (plight);\
- part->rendermode = (prendermode);\
- part->scale = (pscale);\
- part->alpha = (palpha);\
- part->die = cl.time + (ptime);\
- part->bounce = (pbounce);\
- part->org[0] = lhrandom(-(poscale), (poscale)) + (pbase)[0];\
- part->org[1] = lhrandom(-(poscale), (poscale)) + (pbase)[1];\
- part->org[2] = lhrandom(-(poscale), (poscale)) + (pbase)[2];\
- part->vel[0] = lhrandom(-(pvscale), (pvscale));\
- part->vel[1] = lhrandom(-(pvscale), (pvscale));\
- part->vel[2] = lhrandom(-(pvscale), (pvscale));\
- part->time2 = 0;\
- part->vel2[0] = part->vel2[1] = part->vel2[2] = 0;\
-}
-*/
-/*
-#define particle3(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, pbase, pscalex, pscaley, pscalez, pvscalex, pvscaley, pvscalez)\
-{\
- particle_t *part;\
- if (numparticles >= r_numparticles)\
- return;\
- part = &particles[numparticles++];\
- part->type = (ptype);\
- part->color = (pcolor);\
- part->tex = (ptex);\
- part->dynlight = (plight);\
- part->rendermode = (prendermode);\
- part->scale = (pscale);\
- part->alpha = (palpha);\
- part->die = cl.time + (ptime);\
- part->bounce = (pbounce);\
- part->org[0] = lhrandom(-(pscalex), (pscalex)) + (pbase)[0];\
- part->org[1] = lhrandom(-(pscaley), (pscaley)) + (pbase)[1];\
- part->org[2] = lhrandom(-(pscalez), (pscalez)) + (pbase)[2];\
- part->vel[0] = lhrandom(-(pvscalex), (pvscalex));\
- part->vel[1] = lhrandom(-(pvscaley), (pvscaley));\
- part->vel[2] = lhrandom(-(pvscalez), (pvscalez));\
- part->time2 = 0;\
- part->vel2[0] = part->vel2[1] = part->vel2[2] = 0;\
-}
-*/
-#define particle4(ptype, pcolor, ptex, prendermode, plight, pscale, palpha, ptime, pbounce, px, py, pz, pvx, pvy, pvz, ptime2, pvx2, pvy2, pvz2)\
-{\
- particle_t *part;\
- if (numparticles >= r_numparticles)\
- return;\
- part = &particles[numparticles++];\
- part->type = (ptype);\
- part->color = (pcolor);\
- part->tex = (ptex);\
+ tempcolor = (pcolor);\
+ part->color[0] = ((tempcolor) >> 16) & 0xFF;\
+ part->color[1] = ((tempcolor) >> 8) & 0xFF;\
+ part->color[2] = (tempcolor) & 0xFF;\
+ part->color[3] = 0xFF;\
+ part->tex = (&ptex);\
part->dynlight = (plight);\
part->rendermode = (prendermode);\
part->scale = (pscale);\
part->vel2[0] = (pvx2);\
part->vel2[1] = (pvy2);\
part->vel2[2] = (pvz2);\
+ part->friction = (pfriction);\
+ part->pressure = (ppressure);\
}
/*
float beamlength;
static vec3_t avelocities[NUMVERTEXNORMALS];
if (!r_particles.value) return; // LordHavoc: particles are optional
-
+
dist = 64;
beamlength = 16;
angle = cl.time * avelocities[i][1];
sp = sin(angle);
cp = cos(angle);
-
+
forward[0] = cp*cy;
forward[1] = cp*sy;
forward[2] = -sp;
- particle(pt_oneframe, 0x6f, particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 9999, 0, ent->render.origin[0] + m_bytenormals[i][0]*dist + forward[0]*beamlength, ent->render.origin[1] + m_bytenormals[i][1]*dist + forward[1]*beamlength, ent->render.origin[2] + m_bytenormals[i][2]*dist + forward[2]*beamlength, 0, 0, 0);
+ particle(pt_oneframe, particlepalette[0x6f], particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 9999, 0, ent->render.origin[0] + m_bytenormals[i][0]*dist + forward[0]*beamlength, ent->render.origin[1] + m_bytenormals[i][1]*dist + forward[1]*beamlength, ent->render.origin[2] + m_bytenormals[i][2]*dist + forward[2]*beamlength, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
}
int r;
int c;
char name[MAX_OSPATH];
-
+
sprintf (name,"maps/%s.pts", sv.name);
COM_FOpenFile (name, &f, false, true);
Con_Printf ("couldn't open %s\n", name);
return;
}
-
+
Con_Printf ("Reading %s...\n", name);
c = 0;
for (;;)
if (r != 3)
break;
c++;
-
+
if (numparticles >= r_numparticles)
{
Con_Printf ("Not enough free particles\n");
break;
}
- particle(pt_static, (-c)&15, particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 99999, 0, org[0], org[1], org[2], 0, 0, 0);
+ particle(pt_static, particlepalette[(-c)&15], particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 99999, 0, org[0], org[1], org[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
Qclose (f);
{
vec3_t org, dir;
int i, count, msgcount, color;
-
+
for (i=0 ; i<3 ; i++)
org[i] = MSG_ReadCoord ();
for (i=0 ; i<3 ; i++)
msgcount = MSG_ReadByte ();
color = MSG_ReadByte ();
-if (msgcount == 255)
- count = 1024;
-else
- count = msgcount;
-
+ if (msgcount == 255)
+ count = 1024;
+ else
+ count = msgcount;
+
R_RunParticleEffect (org, dir, color, count);
}
-
+
/*
===============
R_ParticleExplosion
*/
void R_ParticleExplosion (vec3_t org, int smoke)
{
- int i;
- if (!r_particles.value) return; // LordHavoc: particles are optional
-
-// particle(pt_smoke, (rand()&7) + 8, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 30, 255, 2, org[0], org[1], org[2], 0, 0, 0);
+ int i, j;
+ float f;
+ vec3_t v, end, ang;
+ byte noise1[32*32], noise2[32*32];
- i = Mod_PointInLeaf(org, cl.worldmodel)->contents;
- if (i == CONTENTS_SLIME || i == CONTENTS_WATER)
- {
- for (i = 0;i < 128;i++)
- particle(pt_bubble, 254, bubbleparticletexture, TPOLYTYPE_ADD, false, lhrandom(1, 2), 255, 9999, 1.5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-96, 96), lhrandom(-96, 96), lhrandom(-96, 96));
- }
- else
- R_NewExplosion(org);
- /*
- else
+ if (r_particles.value && r_particles_explosions.value)
{
- int j;
-// int color;
- float f, forg[3], fvel[3], fvel2[3];
-// for (i = 0;i < 256;i++)
-// particle(pt_fallfadespark, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 1.5, lhrandom(128, 255), 5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(0, 384));
-// for (i = 0;i < 256;i++)
-// particle(pt_fallfadespark, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 1.5, lhrandom(128, 255), 5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-150, 150), lhrandom(-150, 150), lhrandom(-150, 150));
- for (i = 0;i < 32;i++)
+ i = Mod_PointInLeaf(org, cl.worldmodel)->contents;
+ if (i == CONTENTS_SLIME || i == CONTENTS_WATER)
+ {
+ for (i = 0;i < 128;i++)
+ particle(pt_bubble, 0xFFFFFF, bubbleparticletexture, TPOLYTYPE_ALPHA, false, lhrandom(1, 2), 255, 9999, 1.5, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-96, 96), lhrandom(-96, 96), lhrandom(-96, 96), 0, 0, 0, 0, 0, 0);
+
+ ang[2] = lhrandom(0, 360);
+ fractalnoise(noise1, 32, 4);
+ fractalnoise(noise2, 32, 8);
+ for (i = 0;i < 32;i++)
+ {
+ for (j = 0;j < 32;j++)
+ {
+ VectorRandom(v);
+ VectorMA(org, 16, v, v);
+ TraceLine(org, v, end, NULL, 0);
+ ang[0] = (j + 0.5f) * (360.0f / 32.0f);
+ ang[1] = (i + 0.5f) * (360.0f / 32.0f);
+ AngleVectors(ang, v, NULL, NULL);
+ f = noise1[j*32+i] * 1.5f;
+ VectorScale(v, f, v);
+ particle(pt_underwaterspark, noise2[j*32+i] * 0x010101, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, false, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2], 512.0f, 0, 0, 0, 2, 0);
+ VectorScale(v, 0.75, v);
+ particle(pt_underwaterspark, explosparkramp[(noise2[j*32+i] >> 5)], particletexture, TPOLYTYPE_ALPHA, false, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2], 512.0f, 0, 0, 0, 2, 0);
+ }
+ }
+ }
+ else
{
- fvel[0] = lhrandom(-150, 150);
- fvel[1] = lhrandom(-150, 150);
- fvel[2] = lhrandom(-150, 150) + 80;
-// particle(pt_flamefall, 106 + (rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 3, 255, 5, forg[0] + lhrandom(-5, 5), forg[1] + lhrandom(-5, 5), forg[2] + lhrandom(-5, 5), fvel2[0], fvel2[1], fvel2[2]);
- for (j = 0;j < 64;j++)
+ ang[2] = lhrandom(0, 360);
+ fractalnoise(noise1, 32, 4);
+ fractalnoise(noise2, 32, 8);
+ for (i = 0;i < 32;i++)
{
- forg[0] = lhrandom(-20, 20) + org[0];
- forg[1] = lhrandom(-20, 20) + org[1];
- forg[2] = lhrandom(-20, 20) + org[2];
- fvel2[0] = fvel[0] + lhrandom(-30, 30);
- fvel2[1] = fvel[1] + lhrandom(-30, 30);
- fvel2[2] = fvel[2] + lhrandom(-30, 30);
- f = lhrandom(0.2, 1);
- fvel2[0] *= f;
- fvel2[1] *= f;
- fvel2[2] *= f;
- particle(pt_flamefall, 106 + (rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 5, lhrandom(96, 192), 5, forg[0], forg[1], forg[2], fvel2[0], fvel2[1], fvel2[2]);
+ for (j = 0;j < 32;j++)
+ {
+ VectorRandom(v);
+ VectorMA(org, 16, v, v);
+ TraceLine(org, v, end, NULL, 0);
+ ang[0] = (j + 0.5f) * (360.0f / 32.0f);
+ ang[1] = (i + 0.5f) * (360.0f / 32.0f);
+ AngleVectors(ang, v, NULL, NULL);
+ f = noise1[j*32+i] * 1.5f;
+ VectorScale(v, f, v);
+ particle(pt_spark, noise2[j*32+i] * 0x010101, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, false, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0);
+ VectorScale(v, 0.75, v);
+ particle(pt_spark, explosparkramp[(noise2[j*32+i] >> 5)], particletexture, TPOLYTYPE_ALPHA, false, 10, lhrandom(128, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0);
+ // VectorRandom(v);
+ // VectorScale(v, 384, v);
+ // particle(pt_spark, explosparkramp[rand()&7], particletexture, TPOLYTYPE_ALPHA, false, 2, lhrandom(16, 255), 9999, 1.5, end[0], end[1], end[2], v[0], v[1], v[2] + 160.0f, 512.0f, 0, 0, 0, 2, 0);
+ }
}
}
-// for (i = 0;i < 16;i++)
-// particle(pt_smoke, 12+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 20, 192, 99, org[0] + lhrandom(-20, 20), org[1] + lhrandom(-20, 20), org[2] + lhrandom(-20, 20), 0, 0, 0);
-// for (i = 0;i < 50;i++)
-// particle(pt_flamingdebris, ramp3[rand()%6], particletexture, TPOLYTYPE_ALPHA, false, 3, 255, 99, org[0] + lhrandom(-10, 10), org[1] + lhrandom(-10, 10), org[2] + lhrandom(-10, 10), lhrandom(-200, 200), lhrandom(-200, 200), lhrandom(-200, 200));
-// for (i = 0;i < 30;i++)
-// particle(pt_smokingdebris, 10 + (rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 2, 255, 99, org[0] + lhrandom(-10, 10), org[1] + lhrandom(-10, 10), org[2] + lhrandom(-10, 10), lhrandom(-100, 100), lhrandom(-100, 100), lhrandom(-100, 100));
}
- */
+ else
+ R_NewExplosion(org);
}
/*
if (!r_particles.value) return; // LordHavoc: particles are optional
for (i = 0;i < 512;i++)
- particle(pt_fade, colorStart + (i % colorLength), particletexture, TPOLYTYPE_ALPHA, false, 1.5, 255, 0.3, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192));
+ particle(pt_fade, particlepalette[colorStart + (i % colorLength)], particletexture, TPOLYTYPE_ALPHA, false, 1.5, 255, 0.3, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-192, 192), lhrandom(-192, 192), lhrandom(-192, 192), 0, 0, 0, 0, 0.1f, 0);
}
/*
{
int i;
if (!r_particles.value) return; // LordHavoc: particles are optional
-
+
for (i = 0;i < 256;i++)
- particle(pt_blob, 66+(rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128));
+ particle(pt_blob , particlepalette[ 66+(rand()%6)], particletexture, TPOLYTYPE_ALPHA, false, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128), 0, 0, 0, 0, 0, 0);
for (i = 0;i < 256;i++)
- particle(pt_blob2, 150+(rand()%6), particletexture, TPOLYTYPE_ALPHA, false, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128));
+ particle(pt_blob2, particlepalette[150+(rand()%6)], particletexture, TPOLYTYPE_ALPHA, false, 4, 255, 9999, 0, org[0] + lhrandom(-16, 16), org[1] + lhrandom(-16, 16), org[2] + lhrandom(-16, 16), lhrandom(-4, 4), lhrandom(-4, 4), lhrandom(-128, 128), 0, 0, 0, 0, 0, 0);
}
/*
void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
{
if (!r_particles.value) return; // LordHavoc: particles are optional
-
+
if (count == 1024)
{
R_ParticleExplosion(org, false);
return;
}
while (count--)
- particle(pt_fade, color + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 1, 128, 9999, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-15, 15), lhrandom(-15, 15), lhrandom(-15, 15));
+ particle(pt_fade, particlepalette[color + (rand()&7)], particletexture, TPOLYTYPE_ALPHA, false, 1, 128, 9999, 0, org[0] + lhrandom(-8, 8), org[1] + lhrandom(-8, 8), org[2] + lhrandom(-8, 8), lhrandom(-15, 15), lhrandom(-15, 15), lhrandom(-15, 15), 0, 0, 0, 0, 0, 0);
}
// LordHavoc: added this for spawning sparks/dust (which have strong gravity)
*/
void R_SparkShower (vec3_t org, vec3_t dir, int count)
{
+ particletexture_t *tex;
if (!r_particles.value) return; // LordHavoc: particles are optional
- R_Decal(org, bulletholetexture[rand()&7], 16, 0, 0, 0, 255);
+ tex = &bulletholetexture[rand()&7];
+ R_Decal(org, particlefonttexture, tex->s1, tex->t1, tex->s2, tex->t2, 16, 0, 0, 0, 255);
// smoke puff
if (r_particles_smoke.value)
- particle(pt_bulletsmoke, 10, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 5, 255, 9999, 0, org[0], org[1], org[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(0, 16));
+ particle(pt_bulletsmoke, 0xA0A0A0, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 5, 255, 9999, 0, org[0], org[1], org[2], lhrandom(-8, 8), lhrandom(-8, 8), lhrandom(0, 16), 0, 0, 0, 0, 0, 0);
if (r_particles_sparks.value)
{
// sparks
while(count--)
- particle(pt_spark, ramp3[rand()%6], particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(0, 255), 9999, 1.5, org[0], org[1], org[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(0, 128));
+ particle(pt_spark, particlepalette[0x68 + (rand() & 7)], particletexture, TPOLYTYPE_ALPHA, false, 1, lhrandom(0, 255), 9999, 1.5, org[0], org[1], org[2], lhrandom(-64, 64), lhrandom(-64, 64), lhrandom(0, 128), 512.0f, 0, 0, 0, 0.2f, 0);
}
}
bloodcount += count;
while(bloodcount >= 10)
{
- particle(pt_blood, 68+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64));
+ particle(pt_blood, 0x300000, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1.0f, 0);
bloodcount -= 10;
}
}
velscale[0] = velspeed * 2.0 / diff[0];
velscale[1] = velspeed * 2.0 / diff[1];
velscale[2] = velspeed * 2.0 / diff[2];
-
+
while (count--)
{
vec3_t org, vel;
vel[0] = (org[0] - center[0]) * velscale[0];
vel[1] = (org[1] - center[1]) * velscale[1];
vel[2] = (org[2] - center[2]) * velscale[2];
- particle(pt_blood, 68+(rand()&3), smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0], vel[1], vel[2]);
+ particle(pt_blood, 0x300000, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, true, 24, 255, 9999, -1, org[0], org[1], org[2], vel[0], vel[1], vel[2], 0, 0, 0, 0, 1.0f, 0);
}
}
if (maxs[2] <= mins[2]) {t = mins[2];mins[2] = maxs[2];maxs[2] = t;}
while (count--)
- particle(gravity ? pt_grav : pt_static, colorbase + (rand()&3), particletexture, TPOLYTYPE_ALPHA, false, 2, 255, lhrandom(1, 2), 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), dir[0] + lhrandom(-randomvel, randomvel), dir[1] + lhrandom(-randomvel, randomvel), dir[2] + lhrandom(-randomvel, randomvel));
+ particle(gravity ? pt_grav : pt_static, particlepalette[colorbase + (rand()&3)], particletexture, TPOLYTYPE_ALPHA, false, 2, 255, lhrandom(1, 2), 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), dir[0] + lhrandom(-randomvel, randomvel), dir[1] + lhrandom(-randomvel, randomvel), dir[2] + lhrandom(-randomvel, randomvel), 0, 0, 0, 0, 0, 0);
}
void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int type)
vel[0] = dir[0] + lhrandom(-16, 16);
vel[1] = dir[1] + lhrandom(-16, 16);
vel[2] = dir[2] + lhrandom(-32, 32);
- particle4(pt_rain, colorbase + (rand()&3), rainparticletexture, TPOLYTYPE_ALPHA, true, 3, 255, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2]);
+ particle(pt_rain, particlepalette[colorbase + (rand()&3)], rainparticletexture, TPOLYTYPE_ALPHA, true, 3, 255, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2], 0, 0);
}
break;
case 1:
vel[0] = dir[0] + lhrandom(-16, 16);
vel[1] = dir[1] + lhrandom(-16, 16);
vel[2] = dir[2] + lhrandom(-32, 32);
- particle4(pt_snow, colorbase + (rand()&3), particletexture, TPOLYTYPE_ALPHA, false, 2, 255, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2]);
+ particle(pt_snow, particlepalette[colorbase + (rand()&3)], particletexture, TPOLYTYPE_ALPHA, false, 2, 255, t, 0, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), z, vel[0], vel[1], vel[2], 0, vel[0], vel[1], vel[2], 0, 0);
}
break;
default:
if (maxs[2] <= mins[2]) {t = mins[2];mins[2] = maxs[2];maxs[2] = t;}
while (count--)
- particle(pt_flame, 224 + (rand()&15), smokeparticletexture[rand()&7], TPOLYTYPE_ADD, false, 8, 255, 9999, 1.1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 64));
+ particle(pt_flame, particlepalette[224 + (rand()&15)], smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, false, 8, 255, 9999, 1.1, lhrandom(mins[0], maxs[0]), lhrandom(mins[1], maxs[1]), lhrandom(mins[2], maxs[2]), lhrandom(-32, 32), lhrandom(-32, 32), lhrandom(-32, 64), 0, 0, 0, 0, 0.1f, 0);
}
void R_Flames (vec3_t org, vec3_t vel, int count)
if (!r_particles.value) return; // LordHavoc: particles are optional
while (count--)
- particle(pt_flame, 224 + (rand()&15), smokeparticletexture[rand()&7], TPOLYTYPE_ADD, false, 8, 255, 9999, 1.1, org[0], org[1], org[2], vel[0] + lhrandom(-128, 128), vel[1] + lhrandom(-128, 128), vel[2] + lhrandom(-128, 128));
+ particle(pt_flame, particlepalette[224 + (rand()&15)], smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, false, 8, 255, 9999, 1.1, org[0], org[1], org[2], vel[0] + lhrandom(-128, 128), vel[1] + lhrandom(-128, 128), vel[2] + lhrandom(-128, 128), 0, 0, 0, 0, 0.1f, 0);
}
org[1] = origin[1] + dir[1];
org[2] = origin[2] + lhrandom(0, 64);
vel = lhrandom(50, 120) / VectorLength(dir); // normalize and scale
- particle(pt_lavasplash, 224 + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 7, 255, 9999, 0, org[0], org[1], org[2], dir[0] * vel, dir[1] * vel, dir[2] * vel);
-// particle(pt_lavasplash, 224 + (rand()&7), particletexture, TPOLYTYPE_ALPHA, false, 7, 255, 9999, 0, origin[0] + i, origin[1] + j, origin[2] + lhrandom(0, 63), i * lhrandom(0.125, 0.25), j * lhrandom(0.125, 0.25), lhrandom(64, 128));
+ particle(pt_lavasplash, particlepalette[224 + (rand()&7)], particletexture, TPOLYTYPE_ALPHA, false, 7, 255, 9999, 0, org[0], org[1], org[2], dir[0] * vel, dir[1] * vel, dir[2] * vel, 0, 0, 0, 0, 0, 0);
}
}
}
for (i=-16 ; i<16 ; i+=8)
for (j=-16 ; j<16 ; j+=8)
for (k=-24 ; k<32 ; k+=8)
- particle(pt_fade, 254, particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(64, 128), 9999, 0, org[0] + i + lhrandom(0, 8), org[1] + j + lhrandom(0, 8), org[2] + k + lhrandom(0, 8), i*2 + lhrandom(-12.5, 12.5), j*2 + lhrandom(-12.5, 12.5), k*2 + lhrandom(27.5, 52.5));
+ particle(pt_fade, 0xFFFFFF, particletexture, TPOLYTYPE_ALPHA, false, 1, lhrandom(64, 128), 9999, 0, org[0] + i + lhrandom(0, 8), org[1] + j + lhrandom(0, 8), org[2] + k + lhrandom(0, 8), i*2 + lhrandom(-12.5, 12.5), j*2 + lhrandom(-12.5, 12.5), k*2 + lhrandom(27.5, 52.5), 0, 0, 0, 0, 0.1f, -512.0f);
}
void R_RocketTrail (vec3_t start, vec3_t end, int type, entity_t *ent)
VectorNormalize(dir);
if (type == 0 && host_frametime != 0) // rocket glow
- particle(pt_oneframe, 254, rocketglowparticletexture, TPOLYTYPE_ADD, false, 24, 255, 9999, 0, end[0] - 12 * dir[0], end[1] - 12 * dir[1], end[2] - 12 * dir[2], 0, 0, 0);
+ particle(pt_oneframe, 0xFFFFFF, rocketglowparticletexture, TPOLYTYPE_ALPHA, false, 24, 255, 9999, 0, end[0] - 12 * dir[0], end[1] - 12 * dir[1], end[2] - 12 * dir[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
- t = ent->render.trail_time;
+ t = ent->persistent.trail_time;
if (t >= cl.time)
return; // no particles to spawn this frame (sparse trail)
if (len <= 0.01f)
{
// advance the trail time
- ent->render.trail_time = cl.time;
+ ent->persistent.trail_time = cl.time;
return;
}
speed = len / (cl.time - cl.oldtime);
if (contents == CONTENTS_SKY || contents == CONTENTS_LAVA)
{
// advance the trail time
- ent->render.trail_time = cl.time;
+ ent->persistent.trail_time = cl.time;
return;
}
dec = cl.time - t;
else if (bubbles && r_particles_bubbles.value)
{
- dec = 0.01f;
- particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16));
- particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16));
- particle(pt_smoke, 254, smokeparticletexture[rand()&7], polytype, false, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
+ dec = 0.005f;
+ particle(pt_bubble, 0xFFFFFF, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
+ particle(pt_bubble, 0xFFFFFF, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
+ particle(pt_smoke, 0xFFFFFF, smokeparticletexture[rand()&7], polytype, false, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
else
{
- dec = 0.01f;
- particle(pt_smoke, 12, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
-// particle(pt_spark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25);
-// particle(pt_spark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25);
-// particle(pt_spark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25);
-// particle(pt_spark, 0x68 + (rand() & 7), particletexture, TPOLYTYPE_ADD, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.25, lhrandom(-64, 64) - vel[1] * 0.25, lhrandom(-64, 64) - vel[2] * 0.25);
+ dec = 0.005f;
+ particle(pt_smoke, 0xC0C0C0, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ //particle(pt_spark, particlepalette[0x68 + (rand() & 7)], particletexture, TPOLYTYPE_ALPHA, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
+ //particle(pt_spark, particlepalette[0x68 + (rand() & 7)], particletexture, TPOLYTYPE_ALPHA, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
+ //particle(pt_spark, particlepalette[0x68 + (rand() & 7)], particletexture, TPOLYTYPE_ALPHA, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
+ //particle(pt_spark, particlepalette[0x68 + (rand() & 7)], particletexture, TPOLYTYPE_ALPHA, false, 1, lhrandom(128, 255), 9999, 1.5, start[0], start[1], start[2], lhrandom(-64, 64) - vel[0] * 0.0625, lhrandom(-64, 64) - vel[1] * 0.0625, lhrandom(-64, 64) - vel[2] * 0.0625, 512.0f, 0, 0, 0, 0.1f, 0);
}
break;
else if (bubbles && r_particles_bubbles.value)
{
dec = 0.02f;
- particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16));
- particle(pt_bubble, 254, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16));
- particle(pt_smoke, 254, smokeparticletexture[rand()&7], polytype, false, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
+ particle(pt_bubble, 0xFFFFFF, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
+ particle(pt_bubble, 0xFFFFFF, bubbleparticletexture, polytype, false, lhrandom(1, 2), 255, 9999, 1.5, start[0], start[1], start[2], lhrandom(-16, 16), lhrandom(-16, 16), lhrandom(-16, 16), 0, 0, 0, 0, 0, 0);
+ particle(pt_smoke, 0xFFFFFF, smokeparticletexture[rand()&7], polytype, false, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
else
{
dec = 0.02f;
- particle(pt_smoke, 8, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
+ particle(pt_smoke, 0x808080, smokeparticletexture[rand()&7], polytype, true, 2, 160, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
break;
dec = cl.time - t;
else
{
- dec = 0.2f;
- particle(pt_blood, 67+(rand()&3), smokeparticletexture[rand()&7], polytype, true, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64));
+ dec = 0.1f;
+ particle(pt_blood, 0x300000, smokeparticletexture[rand()&7], polytype, true, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1.0f, 0);
}
break;
dec = cl.time - t;
else
{
- dec = 0.3f;
- particle(pt_blood, 67+(rand()&3), smokeparticletexture[rand()&7], polytype, true, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64));
+ dec = 0.15f;
+ particle(pt_blood, 0x300000, smokeparticletexture[rand()&7], polytype, true, 24, 255, 9999, -1, start[0], start[1], start[2], vel[0] + lhrandom(-64, 64), vel[1] + lhrandom(-64, 64), vel[2] + lhrandom(-64, 64), 0, 0, 0, 0, 1.0f, 0);
}
break;
case 3: // green tracer
dec = 0.02f;
- particle(pt_fade, 56, smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
+ particle(pt_fade, 0x373707, smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
break;
case 5: // flame tracer
dec = 0.02f;
- particle(pt_fade, 234, smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
+ particle(pt_fade, 0xCF632B, smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
break;
case 6: // voor trail
dec = 0.05f; // sparse trail
- particle(pt_fade, 152 + (rand()&3), smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
+ particle(pt_fade, 0x47232B, smokeparticletexture[rand()&7], polytype, false, 4, 255, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
break;
case 7: // Nehahra smoke tracer
else
{
dec = 0.14f;
- particle(pt_smoke, 12, smokeparticletexture[rand()&7], polytype, true, 10, 64, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
+ particle(pt_smoke, 0xC0C0C0, smokeparticletexture[rand()&7], polytype, true, 10, 64, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
break;
}
dec *= speed;
VectorMA (start, dec, vec, start);
}
- ent->render.trail_time = t;
+ ent->persistent.trail_time = t;
}
void R_RocketTrail2 (vec3_t start, vec3_t end, int color, entity_t *ent)
VectorSubtract (end, start, vec);
len = (int) (VectorNormalizeLength (vec) * (1.0f / 3.0f));
VectorScale(vec, 3, vec);
+ color = particlepalette[color];
while (len--)
{
- particle(pt_smoke, color, particletexture, TPOLYTYPE_ALPHA, false, 8, 192, 9999, 0, start[0], start[1], start[2], 0, 0, 0);
+ particle(pt_smoke, color, particletexture, TPOLYTYPE_ALPHA, false, 8, 192, 9999, 0, start[0], start[1], start[2], 0, 0, 0, 0, 0, 0, 0, 0, 0);
VectorAdd (start, vec, start);
}
}
void R_MoveParticles (void)
{
particle_t *p;
- int i, activeparticles, maxparticle, j, a;
- vec3_t v;
- float gravity, dvel, frametime;
+ int i, activeparticles, maxparticle, j, a, b, pressureused = false;
+ vec3_t v, org, o, normal;
+ float gravity, dvel, frametime, f;
// LordHavoc: early out condition
if (!numparticles)
}
VectorCopy(p->org, p->oldorg);
- p->org[0] += p->vel[0]*frametime;
- p->org[1] += p->vel[1]*frametime;
- p->org[2] += p->vel[2]*frametime;
+ VectorMA(p->org, frametime, p->vel, p->org);
+ if (p->friction)
+ {
+ f = 1.0f - (p->friction * frametime);
+ VectorScale(p->vel, f, p->vel);
+ }
+ VectorCopy(p->org, org);
if (p->bounce)
{
vec3_t normal;
float dist;
- if (TraceLine(p->oldorg, p->org, v, normal) < 1)
+ if (TraceLine(p->oldorg, p->org, v, normal, 0) < 1)
{
VectorCopy(v, p->org);
if (p->bounce < 0)
{
- byte *color24 = (byte *) &d_8to24table[(int)p->color];
- R_Decal(v, p->tex, p->scale, color24[0], color24[1], color24[2], p->alpha);
+ R_Decal(v, particlefonttexture, p->tex->s1, p->tex->t1, p->tex->s2, p->tex->t2, p->scale, p->color[0], p->color[1], p->color[2], p->alpha);
p->die = -1;
freeparticles[j++] = p;
continue;
- /*
- VectorClear(p->vel);
- p->type = pt_decal;
- // have to negate the direction (why?)
- VectorNegate(normal, p->direction);
- VectorVectors(p->direction, p->decalright, p->decalup);
- VectorSubtract(p->org, p->direction, p->org); // push off the surface a bit so it doesn't flicker
- p->bounce = 0;
- p->time2 = cl.time + 30;
- */
}
else
{
dist = DotProduct(p->vel, normal) * -p->bounce;
- VectorMAQuick(p->vel, dist, normal, p->vel);
+ VectorMA(p->vel, dist, normal, p->vel);
if (DotProduct(p->vel, p->vel) < 0.03)
VectorClear(p->vel);
}
}
}
-
+
switch (p->type)
{
case pt_static:
case pt_grav:
p->vel[2] -= gravity;
break;
- case pt_slowgrav:
- p->vel[2] -= gravity * 0.05;
- break;
case pt_lavasplash:
p->vel[2] -= gravity * 0.05;
p->alpha -= frametime * 192;
{
case CONTENTS_LAVA:
case CONTENTS_SLIME:
- p->tex = smokeparticletexture[rand()&7];
+ p->tex = &smokeparticletexture[rand()&7];
p->type = pt_steam;
p->alpha = 96;
p->scale = 5;
p->vel[2] = 96;
break;
case CONTENTS_WATER:
- p->tex = smokeparticletexture[rand()&7];
+ p->tex = &smokeparticletexture[rand()&7];
p->type = pt_splash;
p->alpha = 96;
p->scale = 5;
p->vel[2] = 96;
break;
default: // CONTENTS_SOLID and any others
- TraceLine(p->oldorg, p->org, v, normal);
+ TraceLine(p->oldorg, p->org, v, normal, 0);
VectorCopy(v, p->org);
- p->tex = smokeparticletexture[rand()&7];
+ p->tex = &smokeparticletexture[rand()&7];
p->type = pt_fade;
VectorClear(p->vel);
break;
}
break;
case pt_blood:
- if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
+ p->friction = 1;
+ a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
+ if (a != CONTENTS_EMPTY)
{
- p->die = -1;
- break;
+ if (a == CONTENTS_WATER || a == CONTENTS_SLIME)
+ {
+ p->friction = 5;
+ p->scale += frametime * 32.0f;
+ p->alpha -= frametime * 128.0f;
+ p->vel[2] += gravity * 0.125f;
+ if (p->alpha < 1)
+ p->die = -1;
+ break;
+ }
+ else
+ {
+ p->die = -1;
+ break;
+ }
}
p->vel[2] -= gravity * 0.5;
break;
case pt_spark:
- p->alpha -= frametime * 512;
+ p->alpha -= frametime * p->time2;
p->vel[2] -= gravity;
+ if (p->alpha < 1)
+ p->die = -1;
+ else if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
+ p->type = pt_underwaterspark;
+ break;
+ case pt_underwaterspark:
+ if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_EMPTY)
+ {
+ p->tex = &smokeparticletexture[rand()&7];
+ p->color[0] = p->color[1] = p->color[2] = 255;
+ p->scale = 16;
+ p->type = pt_explosionsplash;
+ }
+ else
+ p->vel[2] += gravity * 0.5f;
+ p->alpha -= frametime * p->time2;
+ if (p->alpha < 1)
+ p->die = -1;
+ break;
+ case pt_explosionsplash:
+ if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents == CONTENTS_EMPTY)
+ p->vel[2] -= gravity;
+ else
+ p->alpha = 0;
+ p->scale += frametime * 64.0f;
+ p->alpha -= frametime * 1024.0f;
if (p->alpha < 1)
p->die = -1;
break;
a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
if (a != CONTENTS_WATER && a != CONTENTS_SLIME)
{
- p->tex = smokeparticletexture[rand()&7];
+ p->tex = &smokeparticletexture[rand()&7];
p->type = pt_splashpuff;
p->scale = 4;
p->vel[0] = p->vel[1] = p->vel[2] = 0;
case pt_bulletsmoke:
p->scale += frametime * 16;
p->alpha -= frametime * 1024;
- p->vel[2] += gravity * 0.05;
+ p->vel[2] += gravity * 0.1;
if (p->alpha < 1)
p->die = -1;
break;
case pt_smoke:
- p->scale += frametime * 32;
- p->alpha -= frametime * 512;
- p->vel[2] += gravity * 0.05;
+ p->scale += frametime * 24;
+ p->alpha -= frametime * 256;
+ p->vel[2] += gravity * 0.1;
if (p->alpha < 1)
p->die = -1;
break;
p->die = -1;
break;
case pt_splashpuff:
-// p->scale += frametime * 24;
p->alpha -= frametime * 1024;
if (p->alpha < 1)
p->die = -1;
break;
case pt_rain:
- a = Mod_PointInLeaf(p->org, cl.worldmodel)->contents;
- if (a != CONTENTS_EMPTY && a != CONTENTS_SKY)
+ f = 0;
+ b = Mod_PointInLeaf(p->oldorg, cl.worldmodel)->contents;
+ VectorCopy(p->oldorg, o);
+ while (f < 1)
{
- vec3_t normal;
- if (a == CONTENTS_SOLID && Mod_PointInLeaf(p->oldorg, cl.worldmodel)->contents == CONTENTS_SOLID)
- break; // still in solid
- p->die = cl.time + 1000;
- p->vel[0] = p->vel[1] = p->vel[2] = 0;
- switch (a)
+ a = b;
+ f = TraceLine(o, p->org, v, normal, a);
+ b = traceline_endcontents;
+ if (f < 1 && b != CONTENTS_EMPTY && b != CONTENTS_SKY)
{
- case CONTENTS_LAVA:
- case CONTENTS_SLIME:
- p->tex = smokeparticletexture[rand()&7];
- p->type = pt_steam;
- p->scale = 3;
- p->vel[2] = 96;
- break;
- case CONTENTS_WATER:
- p->tex = smokeparticletexture[rand()&7];
- p->type = pt_splashpuff;
- p->scale = 4;
- break;
- default: // CONTENTS_SOLID and any others
- TraceLine(p->oldorg, p->org, v, normal);
+ p->die = cl.time + 1000;
+ p->vel[0] = p->vel[1] = p->vel[2] = 0;
VectorCopy(v, p->org);
- p->tex = smokeparticletexture[rand()&7];
- p->type = pt_splashpuff;
- p->scale = 4;
- break;
+ switch (b)
+ {
+ case CONTENTS_LAVA:
+ case CONTENTS_SLIME:
+ p->tex = &smokeparticletexture[rand()&7];
+ p->type = pt_steam;
+ p->scale = 3;
+ p->vel[2] = 96;
+ break;
+ default: // water, solid, and anything else
+ p->tex = &raindropsplashparticletexture[0];
+ p->time2 = 0;
+ VectorCopy(normal, p->vel2);
+ // VectorAdd(p->org, normal, p->org);
+ p->type = pt_raindropsplash;
+ p->scale = 8;
+ break;
+ }
}
}
break;
- case pt_flame:
- p->alpha -= frametime * 512;
- p->vel[2] += gravity;
-// p->scale -= frametime * 16;
- if (p->alpha < 16)
- p->die = -1;
- break;
- /*
- case pt_flamingdebris:
- if (cl.time >= p->time2)
+ case pt_raindropsplash:
+ p->time2 += frametime * 64.0f;
+ if (p->time2 >= 16.0f)
{
- p->time2 = cl.time + 0.01;
- particle(pt_flame, p->color, particletexture, TPOLYTYPE_ADD, false, 4, p->alpha, 9999, 0, org[0], org[1], org[2], lhrandom(-50, 50), lhrandom(-50, 50), lhrandom(-50, 50));
- }
- p->alpha -= frametime * 512;
- p->vel[2] -= gravity * 0.5f;
- if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
- p->die = -1;
- if (p->alpha < 1)
p->die = -1;
- break;
- case pt_smokingdebris:
- if (cl.time >= p->time2)
- {
- p->time2 = cl.time + 0.01;
- particle2(pt_flame, 15, smokeparticletexture[rand()&7], TPOLYTYPE_ALPHA, false, 4, p->alpha, 9999, 0, org[0], org[1], org[2], lhrandom(-50, 50), lhrandom(-50, 50), lhrandom(-50, 50));
+ break;
}
- p->alpha -= frametime * 512;
- p->vel[2] -= gravity * 0.5f;
- if (Mod_PointInLeaf(p->org, cl.worldmodel)->contents != CONTENTS_EMPTY)
- p->die = -1;
- if (p->alpha < 1)
- p->die = -1;
+ p->tex = &raindropsplashparticletexture[(int) p->time2];
break;
- case pt_flamefall:
+ case pt_flame:
p->alpha -= frametime * 512;
- p->vel[2] -= gravity * 0.5f;
- if (p->alpha < 1)
- p->die = -1;
- break;
- */
- /*
- case pt_decal:
- if (cl.time > p->time2)
- {
- p->alpha -= frametime * 256;
- if (p->alpha < 1)
- p->die = -1;
- }
- if (p->alpha < 64)
+ p->vel[2] += gravity;
+ if (p->alpha < 16)
p->die = -1;
break;
- */
case pt_oneframe:
if (p->time2)
p->die = -1;
{
maxparticle = i;
activeparticles++;
+ if (p->pressure)
+ pressureused = true;
}
}
// fill in gaps to compact the array
maxparticle--;
}
numparticles = activeparticles;
+
+ if (pressureused)
+ {
+ activeparticles = 0;
+ for (i = 0, p = particles;i < numparticles;i++, p++)
+ if (p->pressure)
+ freeparticles[activeparticles++] = p;
+
+ if (activeparticles)
+ {
+ for (i = 0, p = particles;i < numparticles;i++, p++)
+ {
+ for (j = 0;j < activeparticles;j++)
+ {
+ if (freeparticles[j] != p)
+ {
+ float dist, diff[3];
+ VectorSubtract(p->org, freeparticles[j]->org, diff);
+ dist = DotProduct(diff, diff);
+ if (dist < 4096 && dist >= 1)
+ {
+ dist = freeparticles[j]->scale * 4.0f * frametime / sqrt(dist);
+ VectorMA(p->vel, dist, diff, p->vel);
+ //dist = freeparticles[j]->scale * 4.0f * frametime / dist;
+ //VectorMA(p->vel, dist, freeparticles[j]->vel, p->vel);
+ }
+ }
+ }
+ }
+ }
+ }
}
void R_DrawParticles (void)
{
particle_t *p;
- int i, dynamiclight, staticlight, r, g, b;
- byte br, bg, bb, ba;
- float scale, scale2, minparticledist;
- byte *color24;
- vec3_t uprightangles, up2, right2, tempcolor, corner;
-// mleaf_t *leaf;
+ int i, dynamiclight, staticlight, r, g, b, texnum;
+ float minparticledist;
+ vec3_t uprightangles, up2, right2, v, right, up;
+ mleaf_t *leaf;
// LordHavoc: early out condition
if ((!numparticles) || (!r_drawparticles.value))
minparticledist = DotProduct(r_origin, vpn) + 16.0f;
+ texnum = R_GetTexture(particlefonttexture);
for (i = 0, p = particles;i < numparticles;i++, p++)
{
- // LordHavoc: unnecessary (array was already compacted)
-// if (p->die < cl.time)
-// continue;
+ if (p->tex == NULL || p->alpha < 1 || p->scale < 0.1f)
+ continue;
// LordHavoc: only render if not too close
if (DotProduct(p->org, vpn) < minparticledist)
continue;
// LordHavoc: check if it's in a visible leaf
-// leaf = Mod_PointInLeaf(p->org, cl.worldmodel);
-// if (leaf->visframe != r_framecount)
-// continue;
-
- /*
- if (p->type == pt_decal)
- {
- VectorSubtract(p->org, r_origin, v);
- if (DotProduct(p->direction, v) < 0)
- continue;
- }
- */
+ leaf = leaf = Mod_PointInLeaf(p->org, cl.worldmodel);
+ if (leaf->visframe != r_framecount)
+ continue;
- color24 = (byte *) &d_8to24table[(int)p->color];
- r = color24[0];
- g = color24[1];
- b = color24[2];
+ r = p->color[0];
+ g = p->color[1];
+ b = p->color[2];
if (staticlight && (p->dynlight || staticlight >= 2)) // LordHavoc: only light blood and smoke
{
- R_CompleteLightPoint(tempcolor, p->org, dynamiclight);
- r = (r * (int) tempcolor[0]) >> 7;
- g = (g * (int) tempcolor[1]) >> 7;
- b = (b * (int) tempcolor[2]) >> 7;
+ R_CompleteLightPoint(v, p->org, dynamiclight, leaf);
+#if SLOWMATH
+ r = (r * (int) v[0]) >> 7;
+ g = (g * (int) v[1]) >> 7;
+ b = (b * (int) v[2]) >> 7;
+#else
+ v[0] += 8388608.0f;
+ v[1] += 8388608.0f;
+ v[2] += 8388608.0f;
+ r = (r * (*((long *) &v[0]) & 0x7FFFFF)) >> 7;
+ g = (g * (*((long *) &v[1]) & 0x7FFFFF)) >> 7;
+ b = (b * (*((long *) &v[2]) & 0x7FFFFF)) >> 7;
+#endif
}
- br = (byte) min(r, 255);
- bg = (byte) min(g, 255);
- bb = (byte) min(b, 255);
- ba = (byte) p->alpha;
- transpolybegin(R_GetTexture(p->tex), 0, R_GetTexture(p->tex), p->rendermode);
- scale = p->scale * -0.5;scale2 = p->scale;
- /*
- if (p->type == pt_decal)
+ if (p->type == pt_raindropsplash)
{
- corner[0] = p->org[0] + p->decalup[0]*scale + p->decalright[0]*scale;
- corner[1] = p->org[1] + p->decalup[1]*scale + p->decalright[1]*scale;
- corner[2] = p->org[2] + p->decalup[2]*scale + p->decalright[2]*scale;
- transpolyvertub(corner[0] , corner[1] , corner[2] , 0,1,br,bg,bb,ba);
- transpolyvertub(corner[0] + p->decalup[0]*scale2 , corner[1] + p->decalup[1]*scale2 , corner[2] + p->decalup[2]*scale2 , 0,0,br,bg,bb,ba);
- transpolyvertub(corner[0] + p->decalup[0]*scale2 + p->decalright[0]*scale2, corner[1] + p->decalup[1]*scale2 + p->decalright[1]*scale2, corner[2] + p->decalup[2]*scale2 + p->decalright[2]*scale2, 1,0,br,bg,bb,ba);
- transpolyvertub(corner[0] + p->decalright[0]*scale2, corner[1] + p->decalright[1]*scale2, corner[2] + p->decalright[2]*scale2, 1,1,br,bg,bb,ba);
- }
- else*/ if (p->tex == rainparticletexture) // rain streak
- {
- corner[0] = p->org[0] + up2[0]*scale + right2[0]*scale;
- corner[1] = p->org[1] + up2[1]*scale + right2[1]*scale;
- corner[2] = p->org[2] + up2[2]*scale + right2[2]*scale;
- transpolyvertub(corner[0] , corner[1] , corner[2] , 0,1,br,bg,bb,ba);
- transpolyvertub(corner[0] + up2[0]*scale2 , corner[1] + up2[1]*scale2 , corner[2] + up2[2]*scale2 , 0,0,br,bg,bb,ba);
- transpolyvertub(corner[0] + up2[0]*scale2 + right2[0]*scale2, corner[1] + up2[1]*scale2 + right2[1]*scale2, corner[2] + up2[2]*scale2 + right2[2]*scale2, 1,0,br,bg,bb,ba);
- transpolyvertub(corner[0] + right2[0]*scale2, corner[1] + right2[1]*scale2, corner[2] + right2[2]*scale2, 1,1,br,bg,bb,ba);
+ // treat as double-sided
+ if (DotProduct(p->vel2, r_origin) > DotProduct(p->vel2, p->org))
+ {
+ VectorNegate(p->vel2, v);
+ VectorVectors(v, right, up);
+ }
+ else
+ VectorVectors(p->vel2, right, up);
+ transpolyparticle(p->org, right, up, p->scale, texnum, p->rendermode, r, g, b, p->alpha, p->tex->s1, p->tex->t1, p->tex->s2, p->tex->t2);
}
+ else if (p->tex == &rainparticletexture) // rain streak
+ transpolyparticle(p->org, right2, up2, p->scale, texnum, p->rendermode, r, g, b, p->alpha, p->tex->s1, p->tex->t1, p->tex->s2, p->tex->t2);
else
- {
- corner[0] = p->org[0] + vup[0]*scale + vright[0]*scale;
- corner[1] = p->org[1] + vup[1]*scale + vright[1]*scale;
- corner[2] = p->org[2] + vup[2]*scale + vright[2]*scale;
- transpolyvertub(corner[0] , corner[1] , corner[2] , 0,1,br,bg,bb,ba);
- transpolyvertub(corner[0] + vup[0]*scale2 , corner[1] + vup[1]*scale2 , corner[2] + vup[2]*scale2 , 0,0,br,bg,bb,ba);
- transpolyvertub(corner[0] + vup[0]*scale2 + vright[0]*scale2, corner[1] + vup[1]*scale2 + vright[1]*scale2, corner[2] + vup[2]*scale2 + vright[2]*scale2, 1,0,br,bg,bb,ba);
- transpolyvertub(corner[0] + vright[0]*scale2, corner[1] + vright[1]*scale2, corner[2] + vright[2]*scale2, 1,1,br,bg,bb,ba);
- }
- transpolyend();
+ transpolyparticle(p->org, vright, vup, p->scale, texnum, p->rendermode, r, g, b, p->alpha, p->tex->s1, p->tex->t1, p->tex->s2, p->tex->t2);
}
}
#include "quakedef.h"
-void R_ClipSpriteImage (entity_t *e, msprite_t *psprite, frameblend_t *blend, vec3_t origin, vec3_t up, vec3_t right)
+void R_ClipSpriteImage (msprite_t *psprite, vec3_t origin, vec3_t right, vec3_t up)
{
int i;
mspriteframe_t *frame;
vec3_t points[4];
float fleft, fright, fdown, fup;
- frame = ((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[0].frame;
+ frame = ((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + currentrenderentity->frameblend[0].frame;
fleft = frame->left;
fdown = frame->down;
fright = frame->right;
fup = frame->up;
- for (i = 1;i < 4 && blend[i].lerp;i++)
+ for (i = 1;i < 4 && currentrenderentity->frameblend[i].lerp;i++)
{
- frame = ((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[i].frame;
+ frame = ((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + currentrenderentity->frameblend[i].frame;
fleft = min(fleft , frame->left );
fdown = min(fdown , frame->down );
fright = max(fright, frame->right);
points[1][0] = origin[0] + fup * up[0] + fleft * right[0];points[1][1] = origin[1] + fup * up[1] + fleft * right[1];points[1][2] = origin[2] + fup * up[2] + fleft * right[2];
points[2][0] = origin[0] + fup * up[0] + fright * right[0];points[2][1] = origin[1] + fup * up[1] + fright * right[1];points[2][2] = origin[2] + fup * up[2] + fright * right[2];
points[3][0] = origin[0] + fdown * up[0] + fright * right[0];points[3][1] = origin[1] + fdown * up[1] + fright * right[1];points[3][2] = origin[2] + fdown * up[2] + fright * right[2];
- R_Clip_AddPolygon(&points[0][0], 4, sizeof(float[3]), false, R_Entity_Callback, e, NULL, NULL);
+ R_Clip_AddPolygon(&points[0][0], 4, sizeof(float[3]), false, R_Entity_Callback, currentrenderentity, NULL, NULL);
}
-void R_ClipSprite (entity_t *e, frameblend_t *blend)
+int R_SpriteSetup (int type, float org[3], float right[3], float up[3])
{
- vec3_t forward, right, up, org;
- msprite_t *psprite;
-
- if (!blend[0].lerp)
- return;
-
- psprite = Mod_Extradata(e->render.model);
+ float matrix1[3][3], matrix2[3][3], matrix3[3][3];
- if (psprite->type == SPR_ORIENTED)
+ VectorCopy(currentrenderentity->origin, org);
+ switch(type)
{
+ case SPR_VP_PARALLEL_UPRIGHT:
+ // flames and such
+ // vertical beam sprite, faces view plane
+ VectorNegate(vpn, matrix3[0]);
+ matrix3[0][2] = 0;
+ VectorNormalizeFast(matrix3[0]);
+ VectorVectors(matrix3[0], matrix3[1], matrix3[2]);
+ break;
+ case SPR_FACING_UPRIGHT:
+ // flames and such
+ // vertical beam sprite, faces viewer's origin (not the view plane)
+ VectorSubtract(r_origin, currentrenderentity->origin, matrix3[0]);
+ matrix3[0][2] = 0;
+ VectorNormalizeFast(matrix3[0]);
+ VectorVectors(matrix3[0], matrix3[1], matrix3[2]);
+ break;
+ default:
+ Con_Printf("R_SpriteSetup: unknown sprite type %i\n", type);
+ // fall through to normal sprite
+ case SPR_VP_PARALLEL:
+ // normal sprite
+ // faces view plane
+ VectorCopy(vpn, matrix3[0]);
+ VectorCopy(vright, matrix3[1]);
+ VectorCopy(vup, matrix3[2]);
+ break;
+ case SPR_ORIENTED:
// bullet marks on walls
- AngleVectors (e->render.angles, forward, right, up);
+ // ignores viewer entirely
+ AngleVectors (currentrenderentity->angles, matrix3[0], matrix3[1], matrix3[2]);
// nudge it toward the view, so it will be infront of the wall
- VectorSubtract(e->render.origin, vpn, org);
- // don't draw if it's a backface
- if (DotProduct(r_origin, forward) > (DotProduct(org, forward) - 1.0f))
- return;
- }
- else
- {
- // normal sprite
- VectorCopy(vup, up);
- VectorCopy(vright, right);
- VectorCopy(e->render.origin, org);
- // don't draw if it's a backface
- if (DotProduct(org, vpn) < (DotProduct(r_origin, vpn) + 1.0f))
- return;
+ VectorSubtract(org, vpn, org);
+ break;
+ case SPR_VP_PARALLEL_ORIENTED:
+ // I have no idea what people would use this for
+ // oriented relative to view space
+ // FIXME: test this and make sure it mimicks software
+ AngleVectors (currentrenderentity->angles, matrix1[0], matrix1[1], matrix1[2]);
+ VectorCopy(vpn, matrix2[0]);
+ VectorCopy(vright, matrix2[1]);
+ VectorCopy(vup, matrix2[2]);
+ R_ConcatRotations (matrix1, matrix2, matrix3);
+ break;
}
+ // don't draw if view origin is behind it
+ if (DotProduct(org, matrix3[0]) < (DotProduct(r_origin, matrix3[0]) - 1.0f))
+ return true;
- if (e->render.scale != 1)
+ if (currentrenderentity->scale != 1)
{
- VectorScale(up, e->render.scale, up);
- VectorScale(right, e->render.scale, right);
+ VectorScale(matrix3[1], currentrenderentity->scale, matrix3[1]);
+ VectorScale(matrix3[2], currentrenderentity->scale, matrix3[2]);
}
+ VectorCopy(matrix3[1], right);
+ VectorCopy(matrix3[2], up);
+ return false;
+}
+
+void R_ClipSprite (void)
+{
+ vec3_t org, right, up;
+ msprite_t *psprite;
+
+ if (currentrenderentity->frameblend[0].frame < 0)
+ return;
+
+ psprite = Mod_Extradata(currentrenderentity->model);
+ if (R_SpriteSetup(psprite->type, org, right, up))
+ return;
+
// LordHavoc: interpolated sprite rendering
- R_ClipSpriteImage(e, psprite, blend, org, up, right);
+ R_ClipSpriteImage(psprite, org, right, up);
}
void GL_DrawSpriteImage (mspriteframe_t *frame, vec3_t origin, vec3_t up, vec3_t right, byte red, byte green, byte blue, int alpha)
{
byte alphaub;
alphaub = bound(0, alpha, 255);
- transpolybegin(R_GetTexture(frame->texture), 0, R_GetTexture(frame->fogtexture), ((currententity->render.effects & EF_ADDITIVE) || (currententity->render.model->flags & EF_ADDITIVE)) ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
+ transpolybegin(R_GetTexture(frame->texture), 0, R_GetTexture(frame->fogtexture), ((currentrenderentity->effects & EF_ADDITIVE) || (currentrenderentity->model->flags & EF_ADDITIVE)) ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
transpolyvertub(origin[0] + frame->down * up[0] + frame->left * right[0], origin[1] + frame->down * up[1] + frame->left * right[1], origin[2] + frame->down * up[2] + frame->left * right[2], 0, 1, red, green, blue, alphaub);
transpolyvertub(origin[0] + frame->up * up[0] + frame->left * right[0], origin[1] + frame->up * up[1] + frame->left * right[1], origin[2] + frame->up * up[2] + frame->left * right[2], 0, 0, red, green, blue, alphaub);
transpolyvertub(origin[0] + frame->up * up[0] + frame->right * right[0], origin[1] + frame->up * up[1] + frame->right * right[1], origin[2] + frame->up * up[2] + frame->right * right[2], 1, 0, red, green, blue, alphaub);
R_DrawSpriteModel
=================
*/
-void R_DrawSpriteModel (entity_t *e, frameblend_t *blend)
+void R_DrawSpriteModel ()
{
- vec3_t forward, right, up, org, color, mins, maxs;
+ int i;
+ vec3_t right, up, org, color;
byte colorub[4];
msprite_t *psprite;
- if (!blend[0].lerp)
+ if (currentrenderentity->frameblend[0].frame < 0)
return;
- VectorAdd (e->render.origin, e->render.model->mins, mins);
- VectorAdd (e->render.origin, e->render.model->maxs, maxs);
-
-// if (R_CullBox (mins, maxs))
-// return;
+ psprite = Mod_Extradata(currentrenderentity->model);
+ if (R_SpriteSetup(psprite->type, org, right, up))
+ return;
c_sprites++;
- psprite = Mod_Extradata(e->render.model);
- //psprite = e->model->cache.data;
-
- if (psprite->type == SPR_ORIENTED)
- {
- // bullet marks on walls
- AngleVectors (e->render.angles, forward, right, up);
- VectorSubtract(e->render.origin, vpn, org);
- }
- else
- {
- // normal sprite
- VectorCopy(vup, up);
- VectorCopy(vright, right);
- VectorCopy(e->render.origin, org);
- }
-
- if (e->render.scale != 1)
- {
- VectorScale(up, e->render.scale, up);
- VectorScale(right, e->render.scale, right);
- }
-
- if (e->render.model->flags & EF_FULLBRIGHT || e->render.effects & EF_FULLBRIGHT)
+ if ((currentrenderentity->model->flags & EF_FULLBRIGHT) || (currentrenderentity->effects & EF_FULLBRIGHT))
{
- color[0] = e->render.colormod[0] * 255;
- color[1] = e->render.colormod[1] * 255;
- color[2] = e->render.colormod[2] * 255;
+ color[0] = currentrenderentity->colormod[0] * 255;
+ color[1] = currentrenderentity->colormod[1] * 255;
+ color[2] = currentrenderentity->colormod[2] * 255;
}
else
- R_CompleteLightPoint(color, e->render.origin, true);
+ R_CompleteLightPoint(color, currentrenderentity->origin, true, NULL);
colorub[0] = bound(0, color[0], 255);
colorub[1] = bound(0, color[1], 255);
colorub[2] = bound(0, color[2], 255);
// LordHavoc: interpolated sprite rendering
- if (blend[0].lerp)
- GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[0].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->render.alpha*255*blend[0].lerp);
- if (blend[1].lerp)
- GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[1].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->render.alpha*255*blend[1].lerp);
- if (blend[2].lerp)
- GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[2].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->render.alpha*255*blend[2].lerp);
- if (blend[3].lerp)
- GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + blend[3].frame, org, up, right, colorub[0],colorub[1],colorub[2], e->render.alpha*255*blend[3].lerp);
+ for (i = 0;i < 4;i++)
+ if (currentrenderentity->frameblend[i].lerp)
+ GL_DrawSpriteImage(((mspriteframe_t *)(psprite->ofs_frames + (int) psprite)) + currentrenderentity->frameblend[i].frame, org, up, right, colorub[0],colorub[1],colorub[2], currentrenderentity->alpha*255*currentrenderentity->frameblend[i].lerp);
}
extern float *aliasvert;
extern float *aliasvertnorm;
extern byte *aliasvertcolor;
-extern float modelalpha;
// vis stuff
extern cvar_t r_novis;
//=============================================================================
-typedef struct entity_render_s
+typedef struct frameblend_s
{
- vec3_t origin;
- vec3_t angles;
+ int frame;
+ float lerp;
+}
+frameblend_t;
- int visframe; // last frame this entity was found in an active leaf
+// LordHavoc: nothing in this structure is persistant, it may be overwritten by the client every frame, for persistant data use entity_lerp_t.
+typedef struct entity_render_s
+{
+ vec3_t origin; // location
+ vec3_t angles; // orientation
+ float colormod[3]; // color tint for model
+ float alpha; // opacity (alpha) of the model
+ float scale; // size the model is shown
model_t *model; // NULL = no model
- int frame; // current desired frame (usually identical to frame2, but frame2 is not always used)
+ int frame; // current uninterpolated animation frame (for things which do not use interpolation)
int colormap; // entity shirt and pants colors
int effects; // light, particles, etc
int skinnum; // for Alias models
int flags; // render flags
- float alpha; // opacity (alpha) of the model
- float scale; // size the model is shown
- float trail_time; // last time for trail rendering
- float colormod[3]; // color tint for model
-
- model_t *lerp_model; // lerp resets when model changes
+ // these are copied from the persistent data
int frame1; // frame that the model is interpolating from
int frame2; // frame that the model is interpolating to
- double lerp_starttime; // start of this transition
- double framelerp; // interpolation factor, usually computed from lerp_starttime
- double frame1start; // time frame1 began playing (for framegroup animations)
- double frame2start; // time frame2 began playing (for framegroup animations)
+ double framelerp; // interpolation factor, usually computed from frame2time
+ double frame1time; // time frame1 began playing (for framegroup animations)
+ double frame2time; // time frame2 began playing (for framegroup animations)
+
+ // calculated by the renderer (but not persistent)
+ int visframe; // if visframe == r_framecount, it is visible
+ vec3_t mins, maxs; // calculated during R_AddModelEntities
+ frameblend_t frameblend[4]; // 4 frame numbers (-1 if not used) and their blending scalers (0-1), if interpolation is not desired, use frame instead
}
entity_render_t;
+typedef struct entity_persistent_s
+{
+ // particles
+ vec3_t trail_origin; // trail rendering
+ float trail_time; // trail rendering
+
+ // interpolated animation
+ int modelindex; // lerp resets when model changes
+ int frame1; // frame that the model is interpolating from
+ int frame2; // frame that the model is interpolating to
+ double framelerp; // interpolation factor, usually computed from frame2time
+ double frame1time; // time frame1 began playing (for framegroup animations)
+ double frame2time; // time frame2 began playing (for framegroup animations)
+}
+entity_persistent_t;
+
typedef struct entity_s
{
- entity_state_t state_baseline; // baseline for entity
+ entity_state_t state_baseline; // baseline state (default values)
entity_state_t state_previous; // previous state (interpolating from this)
entity_state_t state_current; // current state (interpolating to this)
- entity_render_t render;
-} entity_t;
+ entity_persistent_t persistent; // used for regenerating parts of render
+
+ entity_render_t render; // the only data the renderer should know about
+}
+entity_t;
typedef struct
{
- vrect_t vrect; // subwindow in video for refresh
+ // area to render in
+ int x, y, width, height;
+ float fov_x, fov_y;
- vec3_t vieworg;
- vec3_t viewangles;
+ // view point
+ vec3_t vieworg;
+ vec3_t viewangles;
+}
+refdef_t;
- float fov_x, fov_y;
-} refdef_t;
+extern qboolean hlbsp;
+//extern qboolean r_cache_thrash; // compatability
+extern vec3_t modelorg;
+extern entity_render_t *currentrenderentity;
+extern int r_framecount;
+extern mplane_t frustum[4];
+extern int c_brush_polys, c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights;
//
-// refresh
+// view origin
//
+extern vec3_t vup;
+extern vec3_t vpn;
+extern vec3_t vright;
+extern vec3_t r_origin;
-
+//
+// screen size info
+//
extern refdef_t r_refdef;
-extern vec3_t r_origin, vpn, vright, vup;
-extern qboolean hlbsp;
+extern mleaf_t *r_viewleaf, *r_oldviewleaf;
+extern unsigned short d_lightstylevalue[256]; // 8.8 fraction of base light value
+
+extern qboolean envmap;
+
+extern cvar_t r_drawentities;
+extern cvar_t r_drawviewmodel;
+extern cvar_t r_speeds;
+extern cvar_t r_fullbright;
+extern cvar_t r_wateralpha;
+extern cvar_t r_dynamic;
+extern cvar_t r_waterripple;
+
+//extern float r_world_matrix[16];
void R_Init (void);
void R_RenderView (void); // must set r_refdef first
-void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect); // called whenever r_refdef or vid change
// LordHavoc: changed this for sake of GLQuake
void R_InitSky (byte *src, int bytesperpixel); // called at level load
void GL_LockArray(int first, int count);
void GL_UnlockArray(void);
-void R_DrawBrushModel (entity_t *e);
-void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, frameblend_t *blend, int skin, vec3_t org, vec3_t angles, vec_t scale, int effects, int flags, int colormap);
-void R_DrawSpriteModel (entity_t *e, frameblend_t *blend);
+void R_DrawBrushModel (void);
+void R_DrawAliasModel (void);
+void R_DrawSpriteModel (void);
-void R_ClipSprite (entity_t *e, frameblend_t *blend);
+void R_ClipSprite (void);
void R_Entity_Callback(void *data, void *junk);
extern cvar_t r_render;
extern cvar_t r_upload;
extern cvar_t r_ser;
#include "image.h"
+
+// if contents is not zero, it will impact on content changes
+// (leafs matching contents are considered empty, others are solid)
+extern int traceline_endcontents; // set by TraceLine
+float TraceLine (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal, int contents);
sb_scorebar = Draw_PicFromWad ("scorebar");
//MED 01/04/97 added new hipnotic weapons
- if (hipnotic)
+ if (gamemode == GAME_HIPNOTIC)
{
- hsb_weapons[0][0] = Draw_PicFromWad ("inv_laser");
- hsb_weapons[0][1] = Draw_PicFromWad ("inv_mjolnir");
- hsb_weapons[0][2] = Draw_PicFromWad ("inv_gren_prox");
- hsb_weapons[0][3] = Draw_PicFromWad ("inv_prox_gren");
- hsb_weapons[0][4] = Draw_PicFromWad ("inv_prox");
-
- hsb_weapons[1][0] = Draw_PicFromWad ("inv2_laser");
- hsb_weapons[1][1] = Draw_PicFromWad ("inv2_mjolnir");
- hsb_weapons[1][2] = Draw_PicFromWad ("inv2_gren_prox");
- hsb_weapons[1][3] = Draw_PicFromWad ("inv2_prox_gren");
- hsb_weapons[1][4] = Draw_PicFromWad ("inv2_prox");
-
- for (i=0 ; i<5 ; i++)
- {
- hsb_weapons[2+i][0] = Draw_PicFromWad (va("inva%i_laser",i+1));
- hsb_weapons[2+i][1] = Draw_PicFromWad (va("inva%i_mjolnir",i+1));
- hsb_weapons[2+i][2] = Draw_PicFromWad (va("inva%i_gren_prox",i+1));
- hsb_weapons[2+i][3] = Draw_PicFromWad (va("inva%i_prox_gren",i+1));
- hsb_weapons[2+i][4] = Draw_PicFromWad (va("inva%i_prox",i+1));
- }
-
- hsb_items[0] = Draw_PicFromWad ("sb_wsuit");
- hsb_items[1] = Draw_PicFromWad ("sb_eshld");
+ hsb_weapons[0][0] = Draw_PicFromWad ("inv_laser");
+ hsb_weapons[0][1] = Draw_PicFromWad ("inv_mjolnir");
+ hsb_weapons[0][2] = Draw_PicFromWad ("inv_gren_prox");
+ hsb_weapons[0][3] = Draw_PicFromWad ("inv_prox_gren");
+ hsb_weapons[0][4] = Draw_PicFromWad ("inv_prox");
+
+ hsb_weapons[1][0] = Draw_PicFromWad ("inv2_laser");
+ hsb_weapons[1][1] = Draw_PicFromWad ("inv2_mjolnir");
+ hsb_weapons[1][2] = Draw_PicFromWad ("inv2_gren_prox");
+ hsb_weapons[1][3] = Draw_PicFromWad ("inv2_prox_gren");
+ hsb_weapons[1][4] = Draw_PicFromWad ("inv2_prox");
+
+ for (i=0 ; i<5 ; i++)
+ {
+ hsb_weapons[2+i][0] = Draw_PicFromWad (va("inva%i_laser",i+1));
+ hsb_weapons[2+i][1] = Draw_PicFromWad (va("inva%i_mjolnir",i+1));
+ hsb_weapons[2+i][2] = Draw_PicFromWad (va("inva%i_gren_prox",i+1));
+ hsb_weapons[2+i][3] = Draw_PicFromWad (va("inva%i_prox_gren",i+1));
+ hsb_weapons[2+i][4] = Draw_PicFromWad (va("inva%i_prox",i+1));
+ }
+
+ hsb_items[0] = Draw_PicFromWad ("sb_wsuit");
+ hsb_items[1] = Draw_PicFromWad ("sb_eshld");
}
- if (rogue)
+ else if (gamemode == GAME_ROGUE)
{
rsb_invbar[0] = Draw_PicFromWad ("r_invbar1");
rsb_invbar[1] = Draw_PicFromWad ("r_invbar2");
rsb_weapons[4] = Draw_PicFromWad ("r_plasma");
rsb_items[0] = Draw_PicFromWad ("r_shield1");
- rsb_items[1] = Draw_PicFromWad ("r_agrav1");
+ rsb_items[1] = Draw_PicFromWad ("r_agrav1");
// PGM 01/19/97 - team color border
- rsb_teambord = Draw_PicFromWad ("r_teambord");
+ rsb_teambord = Draw_PicFromWad ("r_teambord");
// PGM 01/19/97 - team color border
rsb_ammo[0] = Draw_PicFromWad ("r_ammolava");
void Sbar_DrawPic (int x, int y, qpic_t *pic)
{
if (cl.gametype == GAME_DEATHMATCH)
- Draw_Pic (x /* + ((vid.width - 320)>>1)*/, y + (vid.height-SBAR_HEIGHT), pic);
+ Draw_Pic (x, y + (vid.conheight-SBAR_HEIGHT), pic);
else
- Draw_Pic (x + ((vid.width - 320)>>1), y + (vid.height-SBAR_HEIGHT), pic);
+ Draw_Pic (x + ((vid.conwidth - 320)>>1), y + (vid.conheight-SBAR_HEIGHT), pic);
}
void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha);
void Sbar_DrawAlphaPic (int x, int y, qpic_t *pic, float alpha)
{
if (cl.gametype == GAME_DEATHMATCH)
- Draw_AlphaPic (x /* + ((vid.width - 320)>>1)*/, y + (vid.height-SBAR_HEIGHT), pic, alpha);
+ Draw_AlphaPic (x, y + (vid.conheight-SBAR_HEIGHT), pic, alpha);
else
- Draw_AlphaPic (x + ((vid.width - 320)>>1), y + (vid.height-SBAR_HEIGHT), pic, alpha);
+ Draw_AlphaPic (x + ((vid.conwidth - 320)>>1), y + (vid.conheight-SBAR_HEIGHT), pic, alpha);
}
/*
void Sbar_DrawCharacter (int x, int y, int num)
{
if (cl.gametype == GAME_DEATHMATCH)
- Draw_Character ( x /*+ ((vid.width - 320)>>1) */ + 4 , y + vid.height-SBAR_HEIGHT, num);
+ Draw_Character ( x + 4 , y + vid.conheight-SBAR_HEIGHT, num);
else
- Draw_Character ( x + ((vid.width - 320)>>1) + 4 , y + vid.height-SBAR_HEIGHT, num);
+ Draw_Character ( x + ((vid.conwidth - 320)>>1) + 4 , y + vid.conheight-SBAR_HEIGHT, num);
}
/*
void Sbar_DrawString (int x, int y, char *str)
{
if (cl.gametype == GAME_DEATHMATCH)
- Draw_String (x /*+ ((vid.width - 320)>>1)*/, y+ vid.height-SBAR_HEIGHT, str, 0);
+ Draw_String (x, y+ vid.conheight-SBAR_HEIGHT, str, 0);
else
- Draw_String (x + ((vid.width - 320)>>1), y+ vid.height-SBAR_HEIGHT, str, 0);
+ Draw_String (x + ((vid.conwidth - 320)>>1), y+ vid.conheight-SBAR_HEIGHT, str, 0);
}
/*
float time;
int flashon;
- if (rogue)
+ if (gamemode == GAME_ROGUE)
{
if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], 0.4);
// MED 01/04/97
// hipnotic weapons
- if (hipnotic)
+ if (gamemode == GAME_HIPNOTIC)
{
int grenadeflashing=0;
for (i=0 ; i<4 ; i++)
}
}
- if (rogue)
+ if (gamemode == GAME_ROGUE)
{
// check for powered up weapon.
if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
}
- flashon = 0;
// items
for (i=0 ; i<6 ; i++)
if (cl.items & (1<<(17+i)))
{
- time = cl.item_gettime[17+i];
- if (time && time > cl.time - 2 && flashon )
- { // flash frame
- }
- else
//MED 01/04/97 changed keys
- if (!hipnotic || (i>1))
- Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
+ if (gamemode != GAME_HIPNOTIC || (i>1))
+ Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
}
+
//MED 01/04/97 added hipnotic items
// hipnotic items
- if (hipnotic)
+ if (gamemode == GAME_HIPNOTIC)
{
for (i=0 ; i<2 ; i++)
if (cl.items & (1<<(24+i)))
- {
- time = cl.item_gettime[24+i];
- if (!time || time <= cl.time - 2 || !flashon)
- Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
- }
+ Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
}
- if (rogue)
+ if (gamemode == GAME_ROGUE)
{
// new rogue items
for (i=0 ; i<2 ; i++)
if (cl.items & (1<<(29+i)))
- {
- time = cl.item_gettime[29+i];
- if (!time || time <= cl.time - 2 || !flashon)
- Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
- }
+ Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
}
else
{
// sigils
for (i=0 ; i<4 ; i++)
- {
if (cl.items & (1<<(28+i)))
- {
- time = cl.item_gettime[28+i];
- if (!time || time <= cl.time - 2 || !flashon)
- Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
- }
- }
+ Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
}
}
if (cl.gametype == GAME_DEATHMATCH)
xofs = 0;
else
- xofs = (vid.width - 320)>>1;
- y = vid.height - SBAR_HEIGHT - 23;
+ xofs = (vid.conwidth - 320)>>1;
+ y = vid.conheight - SBAR_HEIGHT - 23;
for (i=0 ; i<l ; i++)
{
*/
void Sbar_DrawFace (void)
{
- int f, anim;
+ int f;
// PGM 01/19/97 - team color drawing
// PGM 03/02/97 - fixed so color swatch only appears in CTF modes
- if (rogue &&
- (cl.maxclients != 1) &&
- (teamplay.value>3) &&
- (teamplay.value<7))
+ if (gamemode == GAME_ROGUE && (cl.maxclients != 1) && (teamplay.value > 3) && (teamplay.value < 7))
{
int top, bottom;
int xofs;
char num[12];
scoreboard_t *s;
-
+
s = &cl.scores[cl.viewentity - 1];
// draw background
top = (s->colors & 0xf0) + 8;
if (cl.gametype == GAME_DEATHMATCH)
xofs = 113;
else
- xofs = ((vid.width - 320)>>1) + 113;
+ xofs = ((vid.conwidth - 320)>>1) + 113;
Sbar_DrawPic (112, 0, rsb_teambord);
- Draw_Fill (xofs, vid.height-SBAR_HEIGHT+3, 22, 9, top);
- Draw_Fill (xofs, vid.height-SBAR_HEIGHT+12, 22, 9, bottom);
+ Draw_Fill (xofs, vid.conheight-SBAR_HEIGHT+3, 22, 9, top);
+ Draw_Fill (xofs, vid.conheight-SBAR_HEIGHT+12, 22, 9, bottom);
// draw number
f = s->frags;
Sbar_DrawCharacter ( 116, 3, num[1]);
Sbar_DrawCharacter ( 123, 3, num[2]);
}
-
+
return;
}
// PGM 01/19/97 - team color drawing
- if ( (cl.items & (IT_INVISIBILITY | IT_INVULNERABILITY) )
- == (IT_INVISIBILITY | IT_INVULNERABILITY) )
- {
+ if ( (cl.items & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
Sbar_DrawPic (112, 0, sb_face_invis_invuln);
- return;
- }
- if (cl.items & IT_QUAD)
- {
+ else if (cl.items & IT_QUAD)
Sbar_DrawPic (112, 0, sb_face_quad );
- return;
- }
- if (cl.items & IT_INVISIBILITY)
- {
+ else if (cl.items & IT_INVISIBILITY)
Sbar_DrawPic (112, 0, sb_face_invis );
- return;
- }
- if (cl.items & IT_INVULNERABILITY)
- {
+ else if (cl.items & IT_INVULNERABILITY)
Sbar_DrawPic (112, 0, sb_face_invuln);
- return;
- }
-
- if (cl.stats[STAT_HEALTH] >= 100)
- f = 4;
else
- f = cl.stats[STAT_HEALTH] / 20;
- // LordHavoc: I don't even know how the game didn't crash without this
- if (f < 0)
- f = 0;
-
- if (cl.time <= cl.faceanimtime)
{
- anim = 1;
-// sb_updates = 0; // make sure the anim gets drawn over
+ f = cl.stats[STAT_HEALTH] / 20;
+ f = bound(0, f, 4);
+ Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
}
- else
- anim = 0;
- Sbar_DrawPic (112, 0, sb_faces[f][anim]);
}
/*
*/
void Sbar_Draw (void)
{
- if (scr_con_current == vid.height)
+ if (scr_con_current == vid.conheight)
return; // console is full screen
-// sb_updates++;
-
if (sb_lines > 24)
{
Sbar_DrawInventory ();
{
Sbar_DrawAlphaPic (0, 0, sb_scorebar, 0.4);
Sbar_DrawScoreboard ();
-// sb_updates = 0;
}
else if (sb_lines)
{
Sbar_DrawAlphaPic (0, 0, sb_sbar, 0.4);
- // keys (hipnotic only)
- //MED 01/04/97 moved keys here so they would not be overwritten
- if (hipnotic)
- {
- if (cl.items & IT_KEY1)
- Sbar_DrawPic (209, 3, sb_items[0]);
- if (cl.items & IT_KEY2)
- Sbar_DrawPic (209, 12, sb_items[1]);
- }
- // armor
+// keys (hipnotic only)
+ //MED 01/04/97 moved keys here so they would not be overwritten
+ if (gamemode == GAME_HIPNOTIC)
+ {
+ if (cl.items & IT_KEY1)
+ Sbar_DrawPic (209, 3, sb_items[0]);
+ if (cl.items & IT_KEY2)
+ Sbar_DrawPic (209, 12, sb_items[1]);
+ }
+// armor
if (cl.items & IT_INVULNERABILITY)
{
Sbar_DrawNum (24, 0, 666, 3, 1);
}
else
{
- if (rogue)
+ if (gamemode == GAME_ROGUE)
{
- Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3,
- cl.stats[STAT_ARMOR] <= 25);
+ Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
if (cl.items & RIT_ARMOR3)
Sbar_DrawPic (0, 0, sb_armor[2]);
else if (cl.items & RIT_ARMOR2)
}
else
{
- Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3
- , cl.stats[STAT_ARMOR] <= 25);
+ Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
if (cl.items & IT_ARMOR3)
Sbar_DrawPic (0, 0, sb_armor[2]);
else if (cl.items & IT_ARMOR2)
Sbar_DrawFace ();
// health
- Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3
- , cl.stats[STAT_HEALTH] <= 25);
+ Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
// ammo icon
- if (rogue)
+ if (gamemode == GAME_ROGUE)
{
if (cl.items & RIT_SHELLS)
Sbar_DrawPic (224, 0, sb_ammo[0]);
Sbar_DrawPic (224, 0, sb_ammo[3]);
}
- Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3,
- cl.stats[STAT_AMMO] <= 10);
+ Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
}
- if (vid.width > 320) {
- if (cl.gametype == GAME_DEATHMATCH)
- Sbar_MiniDeathmatchOverlay ();
- }
+ if (vid.conwidth > 320 && cl.gametype == GAME_DEATHMATCH)
+ Sbar_MiniDeathmatchOverlay ();
}
//=============================================================================
// draw the text
l = scoreboardlines;
- x = ((vid.width - 320)>>1) - 140;
+ x = ((vid.conwidth - 320)>>1) - 140;
y = 40;
for (i = 0;i < l;i++)
{
char num[128];
scoreboard_t *s;
- if (vid.width < 512 || !sb_lines)
+ if (vid.conwidth < 512 || !sb_lines)
return;
// scores
// draw the text
l = scoreboardlines;
- y = vid.height - sb_lines;
+ y = vid.conheight - sb_lines;
numlines = sb_lines/8;
if (numlines < 3)
return;
i = 0;
x = 324;
- for (;i < scoreboardlines && y < vid.height - 8;i++)
+ for (;i < scoreboardlines && y < vid.conheight - 8;i++)
{
k = fragsort[i];
s = &cl.scores[k];
qpic_t *pic;
pic = Draw_CachePic ("gfx/finale.lmp");
- Draw_Pic ( (vid.width-pic->width)/2, 16, pic);
+ Draw_Pic ( (vid.conwidth-pic->width)/2, 16, pic);
}
#include "quakedef.h"
cvar_t sv_pvscheckentities = {0, "sv_pvscheckentities", "1"};
-cvar_t sv_vischeckentities = {0, "sv_vischeckentities", "1"};
+cvar_t sv_vischeckentities = {0, "sv_vischeckentities", "0"}; // extremely accurate visibility checking, but too slow
cvar_t sv_reportvischeckentities = {0, "sv_reportvischeckentities", "0"};
int sv_vischeckentitycullcount = 0;
char message[2048];
MSG_WriteByte (&client->message, svc_print);
- sprintf (message, "%c\nDARKPLACES VERSION %4.2f BUILD %i SERVER (%i CRC)", 2, VERSION, buildnumber, pr_crc);
+ sprintf (message, "\002\nServer: %s build %i (progs %i crc)", gamename, buildnumber, pr_crc);
MSG_WriteString (&client->message,message);
MSG_WriteByte (&client->message, svc_serverinfo);
MSG_WriteByte (&client->message, sv.edicts->v.sounds);
MSG_WriteByte (&client->message, sv.edicts->v.sounds);
-// set view
+// set view
MSG_WriteByte (&client->message, svc_setview);
MSG_WriteShort (&client->message, NUM_FOR_EDICT(client->edict));
}
return;
}
-
+
plane = node->plane;
d = DotProduct (org, plane->normal) - plane->dist;
if (d > 8)
vec3_t org, origin, angles, entmins, entmaxs;
float movelerp, moveilerp, nextfullupdate;
edict_t *ent;
- eval_t *val;
- entity_state_t *baseline; // LordHavoc: delta or startup baseline
+ eval_t *val;
+ entity_state_t *baseline; // LordHavoc: delta or startup baseline
trace_t trace;
+ model_t *model;
// find the client's PVS
VectorAdd (clent->v.origin, clent->v.view_ofs, org);
*/
clentnum = EDICT_TO_PROG(clent); // LordHavoc: for comparison purposes
-// send over all entities (except the client) that touch the pvs
+ // send all entities that touch the pvs
ent = NEXT_EDICT(sv.edicts);
for (e = 1;e < sv.num_edicts;e++, ent = NEXT_EDICT(ent))
{
if (val->_float != 0)
bits |= U_GLOWTRAIL;
- if (ent->v.modelindex == 0 || pr_strings[ent->v.model] == 0) // no model
+ if (ent->v.modelindex >= 0 && ent->v.modelindex < MAX_MODELS && pr_strings[ent->v.model])
+ model = sv.models[(int)ent->v.modelindex];
+ else
+ {
+ model = NULL;
if (ent != clent) // LordHavoc: always send player
if (glowsize == 0 && (bits & U_GLOWTRAIL) == 0) // no effects
continue;
+ }
if (ent->v.movetype == MOVETYPE_STEP && ((int) ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM))) // monsters have smoothed walking/flying/swimming movement
{
}
else // copy as they are
{
+ if (ent->v.movetype == MOVETYPE_STEP) // monster, but airborn, update lerp info
+ {
+ // update lerp positions
+ ent->steplerptime = sv.time;
+ VectorCopy(ent->v.origin, ent->stepoldorigin);
+ VectorCopy(ent->v.angles, ent->stepoldangles);
+ VectorCopy(ent->v.origin, ent->steporigin);
+ VectorCopy(ent->v.angles, ent->stepangles);
+ }
+
VectorCopy(ent->v.angles, angles);
if (DotProduct(ent->v.velocity, ent->v.velocity) >= 1.0f)
{
{
VectorCopy(ent->v.origin, origin);
}
- if (ent->v.movetype == MOVETYPE_STEP) // monster, but airborn, update lerp info
- {
- // update lerp positions
- ent->steplerptime = sv.time;
- VectorCopy(ent->v.origin, ent->stepoldorigin);
- VectorCopy(ent->v.angles, ent->stepoldangles);
- VectorCopy(ent->v.origin, ent->steporigin);
- VectorCopy(ent->v.angles, ent->stepangles);
- }
}
// ent has survived every check so far, check if it is visible
if (ent != clent && ((bits & U_VIEWMODEL) == 0))
{
// use the predicted origin
- entmins[0] = ent->v.mins[0] + origin[0] - 1.0f;
- entmins[1] = ent->v.mins[1] + origin[1] - 1.0f;
- entmins[2] = ent->v.mins[2] + origin[2] - 1.0f;
- entmaxs[0] = ent->v.maxs[0] + origin[0] + 1.0f;
- entmaxs[1] = ent->v.maxs[1] + origin[1] + 1.0f;
- entmaxs[2] = ent->v.maxs[2] + origin[2] + 1.0f;
+ entmins[0] = origin[0] - 1.0f;
+ entmins[1] = origin[1] - 1.0f;
+ entmins[2] = origin[2] - 1.0f;
+ entmaxs[0] = origin[0] + 1.0f;
+ entmaxs[1] = origin[1] + 1.0f;
+ entmaxs[2] = origin[2] + 1.0f;
+ // using the model's bounding box to ensure things are visible regardless of their physics box
+ if (model)
+ {
+ if (ent->v.angles[0] || ent->v.angles[2]) // pitch and roll
+ {
+ VectorAdd(entmins, model->rotatedmins, entmins);
+ VectorAdd(entmaxs, model->rotatedmaxs, entmaxs);
+ }
+ else if (ent->v.angles[1])
+ {
+ VectorAdd(entmins, model->yawmins, entmins);
+ VectorAdd(entmaxs, model->yawmaxs, entmaxs);
+ }
+ else
+ {
+ VectorAdd(entmins, model->normalmins, entmins);
+ VectorAdd(entmaxs, model->normalmaxs, entmaxs);
+ }
+ }
// if not touching a visible leaf
if (sv_pvscheckentities.value && !SV_BoxTouchingPVS(pvs, entmins, entmaxs, sv.worldmodel->nodes))
{
if (glowsize == 0 && (bits & U_GLOWTRAIL) == 0) // no effects
{
- if (ent->v.modelindex && pr_strings[ent->v.model]) // model
+ if (model) // model
{
// don't send if flagged for NODRAW and there are no effects
- if (sv.models[(int)ent->v.modelindex]->flags == 0 && ((effects & EF_NODRAW) || scale <= 0 || alpha <= 0))
+ if (model->flags == 0 && ((effects & EF_NODRAW) || scale <= 0 || alpha <= 0))
continue;
}
else // no model and no effects
MSG_WriteByte (msg, ent->v.ammo_rockets);
MSG_WriteByte (msg, ent->v.ammo_cells);
- if (standard_quake)
- {
- MSG_WriteByte (msg, ent->v.weapon);
- }
- else
+ if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
{
for(i=0;i<32;i++)
{
}
}
}
+ else
+ {
+ MSG_WriteByte (msg, ent->v.weapon);
+ }
}
/*
return 7;
}
CrossProduct (planes[0], planes[1], dir);
+ // LordHavoc: thanks to taniwha of QuakeForge for pointing out this fix for slowed falling in corners
+ VectorNormalize(dir);
d = DotProduct (dir, ent->v.velocity);
VectorScale (dir, d, ent->v.velocity);
}
|| Q_strncasecmp(s, "ping", 4) == 0
|| Q_strncasecmp(s, "ban", 3) == 0
|| Q_strncasecmp(s, "pmodel", 6) == 0
- || (nehahra && (Q_strncasecmp(s, "max", 3) == 0 || Q_strncasecmp(s, "monster", 7) == 0 || Q_strncasecmp(s, "scrag", 5) == 0 || Q_strncasecmp(s, "gimme", 5) == 0 || Q_strncasecmp(s, "wraith", 6) == 0))
- || (!nehahra && (Q_strncasecmp(s, "god", 3) == 0 || Q_strncasecmp(s, "notarget", 8) == 0 || Q_strncasecmp(s, "fly", 3) == 0 || Q_strncasecmp(s, "give", 4) == 0 || Q_strncasecmp(s, "noclip", 6) == 0)))
+ || (gamemode == GAME_NEHAHRA && (Q_strncasecmp(s, "max", 3) == 0 || Q_strncasecmp(s, "monster", 7) == 0 || Q_strncasecmp(s, "scrag", 5) == 0 || Q_strncasecmp(s, "gimme", 5) == 0 || Q_strncasecmp(s, "wraith", 6) == 0))
+ || (gamemode != GAME_NEHAHRA && (Q_strncasecmp(s, "god", 3) == 0 || Q_strncasecmp(s, "notarget", 8) == 0 || Q_strncasecmp(s, "fly", 3) == 0 || Q_strncasecmp(s, "give", 4) == 0 || Q_strncasecmp(s, "noclip", 6) == 0)))
{
ret = 1;
Cmd_ExecuteString (s, src_client);
void Sys_SendKeyEvents (void);
// Perform Key_Event () callbacks until the input que is empty
+// called after Com_InitArgv
+void Sys_Shared_EarlyInit (void);
+// called after Host_init
+void Sys_Shared_LateInit (void);
fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
+ Sys_Shared_EarlyInit();
+
Host_Init();
- Sys_Shared_Init();
+ Sys_Shared_LateInit();
oldtime = Sys_DoubleTime () - 0.1;
while (1)
//#endif
}
-void Sys_Shared_Init(void)
+char engineversion[40];
+
+void Sys_Shared_EarlyInit(void)
{
- if (COM_CheckParm("-nostdout"))
- sys_nostdout = 1;
- else
- {
#if defined(__linux__)
- fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);
- printf ("DarkPlaces Linux GL %.2f build %3i", (float) VERSION, buildnumber);
+ sprintf (engineversion, "%s Linux GL build %3i", gamename, buildnumber);
#elif defined(WIN32)
- printf ("DarkPlaces Windows GL %.2f build %3i", (float) VERSION, buildnumber);
+ sprintf (engineversion, "%s Windows GL build %3i", gamename, buildnumber);
#else
- printf ("DarkPlaces Unknown GL %.2f build %3i", (float) VERSION, buildnumber);
+ sprintf (engineversion, "%s Unknown GL build %3i", gamename, buildnumber);
#endif
- }
+
+ if (COM_CheckParm("-nostdout"))
+ sys_nostdout = 1;
+ else
+ printf("%s\n", engineversion);
+}
+
+void Sys_Shared_LateInit(void)
+{
}
*lpCmdLine = 0;
lpCmdLine++;
}
-
+
}
}
host_parms.argc = com_argc;
host_parms.argv = com_argv;
- Sys_Shared_Init();
+ Sys_Shared_EarlyInit();
// take the greater of all the available memory or half the total memory,
// but at least 8 Mb and no more than 16 Mb, unless they explicitly
if (t < com_argc)
hFile = (HANDLE)atoi (com_argv[t+1]);
}
-
+
if ((t = COM_CheckParm ("-HPARENT")) > 0)
{
if (t < com_argc)
heventParent = (HANDLE)atoi (com_argv[t+1]);
}
-
+
if ((t = COM_CheckParm ("-HCHILD")) > 0)
{
if (t < com_argc)
timeBeginPeriod (1);
#endif
- Sys_Printf ("Host_Init\n");
Host_Init ();
+ Sys_Shared_LateInit();
+
oldtime = Sys_DoubleTime ();
/* main window message loop */
softwaretransform_classify();
}
-void softwaretransformforentity (entity_t *e)
+void softwaretransformforentity (entity_render_t *r)
{
vec3_t angles;
- angles[0] = -e->render.angles[0];
- angles[1] = e->render.angles[1];
- angles[2] = e->render.angles[2];
- softwaretransformset(e->render.origin, angles, e->render.scale);
+ angles[0] = -r->angles[0];
+ angles[1] = r->angles[1];
+ angles[2] = r->angles[2];
+ softwaretransformset(r->origin, angles, r->scale);
}
// brush entities are not backwards like models and sprites are
-void softwaretransformforbrushentity (entity_t *e)
+void softwaretransformforbrushentity (entity_render_t *r)
{
- softwaretransformset(e->render.origin, e->render.angles, e->render.scale);
+ softwaretransformset(r->origin, r->angles, r->scale);
}
extern vec3_t softwaretransform_z;
extern int softwaretransform_type;
-extern void softwaretransformforentity (entity_t *e);
-extern void softwaretransformforbrushentity (entity_t *e);
+extern void softwaretransformforentity (entity_render_t *r);
+extern void softwaretransformforbrushentity (entity_render_t *r);
extern void softwaretransformidentity (void);
extern void softwaretransformset (vec3_t origin, vec3_t angles, vec_t scale);
extern void (*softwaretransform) (vec3_t in, vec3_t out);
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
{
// ui_mousepointer = Draw_CachePic("ui/mousepointer.lmp");
ui_mousepointertexture = R_LoadTexture("mousepointer", 16, 16, pointerimage, TEXF_ALPHA | TEXF_PRECACHE);
- ui_mouse_x = vid.width * 0.5;
- ui_mouse_y = vid.height * 0.5;
+ ui_mouse_x = vid.conwidth * 0.5;
+ ui_mouse_y = vid.conheight * 0.5;
ui_alive = true;
}
{
if (ui_alive)
{
- ui_mouse_x = bound(0, x, vid.width);
- ui_mouse_y = bound(0, y, vid.height);
+ ui_mouse_x = bound(0, x, vid.conwidth);
+ ui_mouse_y = bound(0, y, vid.conheight);
}
}
{
ui_mouse_x += x;
ui_mouse_y += y;
- ui_mouse_x = bound(0, ui_mouse_x, vid.width);
- ui_mouse_y = bound(0, ui_mouse_y, vid.height);
+ ui_mouse_x = bound(0, ui_mouse_x, vid.conwidth);
+ ui_mouse_y = bound(0, ui_mouse_y, vid.conheight);
}
}
void ui_item
(
ui_t *ui, char *basename, int number,
- float x, float y, qpic_t *pic,
+ float x, float y, qpic_t *pic, char *string,
float left, float top, float width, float height,
void(*leftkey)(void *nativedata1, void *nativedata2, float data1, float data2),
void(*rightkey)(void *nativedata1, void *nativedata2, float data1, float data2),
}
ui->item_count++;
}
+ memset(it, 0, sizeof(ui_item_t));
strncpy(it->name, itemname, 32);
it->flags = 0;
+ if (pic || string)
+ {
+ it->flags |= ITEM_DRAWABLE;
+ it->draw_pic = pic;
+ it->draw_string = string;
+ it->draw_x = x;
+ it->draw_y = y;
+ }
if (leftkey || rightkey || enterkey || mouseclick)
+ {
it->flags |= ITEM_CLICKABLE;
- if (pic)
- it->flags |= ITEM_DRAWABLE;
- it->draw_x = x;
- it->draw_y = y;
- it->click_x = x + left;
- it->click_y = y + top;
- it->click_x2 = it->click_x + width;
- it->click_y2 = it->click_y + height;
- it->leftkey = leftkey;
- it->rightkey = rightkey;
- it->enterkey = enterkey;
- it->mouseclick = mouseclick;
- if (it->mouseclick == NULL)
- it->mouseclick = (void *)it->enterkey;
- if (it->leftkey == NULL)
- it->leftkey = it->enterkey;
- if (it->rightkey == NULL)
- it->rightkey = it->enterkey;
- it->nativedata1 = nativedata1;
- it->nativedata2 = nativedata2;
+ it->click_x = x + left;
+ it->click_y = y + top;
+ it->click_x2 = it->click_x + width;
+ it->click_y2 = it->click_y + height;
+ it->leftkey = leftkey;
+ it->rightkey = rightkey;
+ it->enterkey = enterkey;
+ it->mouseclick = mouseclick;
+ if (it->mouseclick == NULL)
+ it->mouseclick = (void *)it->enterkey;
+ if (it->leftkey == NULL)
+ it->leftkey = it->enterkey;
+ if (it->rightkey == NULL)
+ it->rightkey = it->enterkey;
+ it->nativedata1 = nativedata1;
+ it->nativedata2 = nativedata2;
+ }
}
void ui_item_remove(ui_t *ui, char *basename, int number)
ui_item_t *startitem, *it;
if (ui_alive)
{
- ui_mouse_x = bound(0, ui_mouse_x, vid.width);
- ui_mouse_y = bound(0, ui_mouse_y, vid.height);
+ ui_mouse_x = bound(0, ui_mouse_x, vid.conwidth);
+ ui_mouse_y = bound(0, ui_mouse_y, vid.conheight);
if ((ui_active = ui_isactive()))
{
if (ui->item_count)
for (i = 0, it = ui->items;i < ui->item_count;i++, it++)
if (it->flags & ITEM_DRAWABLE)
- Draw_Pic(it->draw_x, it->draw_y, it->draw_pic);
+ {
+ if (it->draw_pic)
+ Draw_Pic(it->draw_x, it->draw_y, it->draw_pic);
+ if (it->draw_string)
+ Draw_String(it->draw_x, it->draw_y, it->draw_string, 9999);
+ }
if ((it = ui_hititem(ui_mouse_x, ui_mouse_y)))
{
- Draw_AdditivePic(it->draw_x, it->draw_y, it->draw_pic);
+ if (it->draw_pic)
+ Draw_AdditivePic(it->draw_x, it->draw_y, it->draw_pic);
+ if (it->draw_string)
+ Draw_AdditiveString(it->draw_x, it->draw_y, it->draw_string, 9999);
if (ui_showname.value)
Draw_String(ui_mouse_x, ui_mouse_y + 16, it->name, 9999);
}
it = ui_keyrealitem;
- Draw_AdditivePic(it->draw_x, it->draw_y, it->draw_pic);
+ if (it->draw_pic)
+ Draw_AdditivePic(it->draw_x, it->draw_y, it->draw_pic);
+ if (it->draw_string)
+ Draw_AdditiveString(it->draw_x, it->draw_y, it->draw_string, 9999);
// Draw_Pic(ui_mouse_x, ui_mouse_y, ui_mousepointer);
Draw_GenericPic(ui_mousepointertexture, 1, 1, 1, 1, ui_mouse_x, ui_mouse_y, 16, 16);
char name[32];
int flags;
qpic_t *draw_pic;
+ char *draw_string;
int draw_x, draw_y;
int click_x, click_y, click_x2, click_y2;
void(*leftkey)(void *nativedata1, void *nativedata2, float data1, float data2);
void ui_item
(
ui_t *ui, char *basename, int number,
- float x, float y, qpic_t *pic,
+ float x, float y, qpic_t *pic, char *string,
float left, float top, float width, float height,
void(*leftkey)(void *nativedata1, void *nativedata2, float data1, float data2),
void(*rightkey)(void *nativedata1, void *nativedata2, float data1, float data2),
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*/
// vid.h -- video driver defs
-typedef struct vrect_s
-{
- int x,y,width,height;
- struct vrect_s *pnext;
-} vrect_t;
-
typedef struct
{
- int width;
- int height;
- int recalc_refdef; // if true, recalc vid-based stuff
+ // these are set with GL_BeginRendering and can change from frame to frame
+ int realx;
+ int realy;
+ int realwidth;
+ int realheight;
+// int recalc_refdef; // if true, recalc vid-based stuff
+
int conwidth;
int conheight;
} viddef_t;
vid.conheight = height;
if (vid.conwidth > width)
vid.conwidth = width;
- vid.width = vid.conwidth;
- vid.height = vid.conheight;
InitSig(); // trap evil signals
Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height);
- vid.recalc_refdef = 1; // force a surface cache flush
+// vid.recalc_refdef = 1; // force a surface cache flush
}
void VID_ExtraOptionDraw(unsigned int options_draw_cursor)
#include <X11/extensions/xf86dga.h>
#include <X11/extensions/xf86vmode.h>
-static Display *dpy = NULL;
+static Display *vidx11_display = NULL;
static int scrnum;
static Window win;
static GLXContext ctx = NULL;
static int num_vidmodes;
static qboolean vidmode_active = false;
+static Visual *vidx11_visual;
+static Colormap vidx11_colormap;
+
/*-----------------------------------------------------------------------*/
float gldepthmin, gldepthmax;
XWindowAttributes attribs_1;
XSetWindowAttributes attribs_2;
- XGetWindowAttributes(dpy, win, &attribs_1);
+ XGetWindowAttributes(vidx11_display, win, &attribs_1);
attribs_2.event_mask = attribs_1.your_event_mask | KEY_MASK | MOUSE_MASK;
- XChangeWindowAttributes(dpy, win, CWEventMask, &attribs_2);
+ XChangeWindowAttributes(vidx11_display, win, CWEventMask, &attribs_2);
// inviso cursor
- XDefineCursor(dpy, win, CreateNullCursor(dpy, win));
+ XDefineCursor(vidx11_display, win, CreateNullCursor(vidx11_display, win));
- XGrabPointer(dpy, win, True, 0, GrabModeAsync, GrabModeAsync, win, None, CurrentTime);
+ XGrabPointer(vidx11_display, win, True, 0, GrabModeAsync, GrabModeAsync, win, None, CurrentTime);
if (vid_dga.value)
{
int MajorVersion, MinorVersion;
- if (!XF86DGAQueryVersion(dpy, &MajorVersion, &MinorVersion))
+ if (!XF86DGAQueryVersion(vidx11_display, &MajorVersion, &MinorVersion))
{
// unable to query, probalby not supported
Con_Printf( "Failed to detect XF86DGA Mouse\n" );
else
{
vid_dga.value = 1;
- XF86DGADirectVideo(dpy, DefaultScreen(dpy), XF86DGADirectMouse);
- XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0);
+ XF86DGADirectVideo(vidx11_display, DefaultScreen(vidx11_display), XF86DGADirectMouse);
+ XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, 0, 0);
}
}
else
- XWarpPointer(dpy, None, win, 0, 0, 0, 0, vid.width / 2, vid.height / 2);
+ XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, scr_width / 2, scr_height / 2);
- XGrabKeyboard(dpy, win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
+ XGrabKeyboard(vidx11_display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
mouse_active = true;
mouse_x = mouse_y = 0;
-// XSync(dpy, True);
+// XSync(vidx11_display, True);
}
static void uninstall_grabs(void)
{
- if (!dpy || !win)
+ if (!vidx11_display || !win)
return;
if (vid_dga.value == 1)
- XF86DGADirectVideo(dpy, DefaultScreen(dpy), 0);
+ XF86DGADirectVideo(vidx11_display, DefaultScreen(vidx11_display), 0);
- XUngrabPointer(dpy, CurrentTime);
- XUngrabKeyboard(dpy, CurrentTime);
+ XUngrabPointer(vidx11_display, CurrentTime);
+ XUngrabKeyboard(vidx11_display, CurrentTime);
// inviso cursor
- XUndefineCursor(dpy, win);
+ XUndefineCursor(vidx11_display, win);
mouse_active = false;
}
// KeySym ks;
qboolean dowarp = false;
- if (!dpy)
+ if (!vidx11_display)
return;
- while (XPending(dpy))
+ while (XPending(vidx11_display))
{
- XNextEvent(dpy, &event);
+ XNextEvent(vidx11_display, &event);
switch (event.type)
{
{
mouse_x += event.xmotion.x - p_mouse_x;
mouse_y += event.xmotion.y - p_mouse_y;
- if (abs(vid.width/2 - event.xmotion.x) > vid.width / 4 || abs(vid.height/2 - event.xmotion.y) > vid.height / 4)
+ if (abs(scr_width/2 - event.xmotion.x) > scr_width / 4 || abs(scr_height/2 - event.xmotion.y) > scr_height / 4)
dowarp = true;
}
}
if (dowarp)
{
/* move the mouse to the window center again */
- p_mouse_x = vid.width / 2;
- p_mouse_y = vid.height / 2;
- XWarpPointer(dpy, None, win, 0, 0, 0, 0, p_mouse_x, p_mouse_y);
+ p_mouse_x = scr_width / 2;
+ p_mouse_y = scr_height / 2;
+ XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, p_mouse_x, p_mouse_y);
}
}
static void IN_DeactivateMouse( void )
{
- if (!mouse_avail || !dpy || !win)
+ if (!mouse_avail || !vidx11_display || !win)
return;
if (mouse_active)
static void IN_ActivateMouse( void )
{
- if (!mouse_avail || !dpy || !win)
+ if (!mouse_avail || !vidx11_display || !win)
return;
if (!mouse_active)
void VID_Shutdown(void)
{
- if (!ctx || !dpy)
+ if (!ctx || !vidx11_display)
return;
- if (dpy)
+ if (vidx11_display)
{
uninstall_grabs();
if (vidmode_active)
- XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[0]);
+ XF86VidModeSwitchToMode(vidx11_display, scrnum, vidmodes[0]);
/* Disabled, causes a segfault during shutdown.
if (ctx)
- glXDestroyContext(dpy, ctx);
+ glXDestroyContext(vidx11_display, ctx);
*/
if (win)
- XDestroyWindow(dpy, win);
- XCloseDisplay(dpy);
+ XDestroyWindow(vidx11_display, win);
+ XCloseDisplay(vidx11_display);
}
vidmode_active = false;
- dpy = NULL;
+ vidx11_display = NULL;
win = 0;
ctx = NULL;
}
if (!r_render.value)
return;
glFlush();
- glXSwapBuffers(dpy, win);
+ glXSwapBuffers(vidx11_display, win);
// handle the mouse state when windowed if that's changed
usemouse = false;
}
}
+// LordHavoc: ported from SDL 1.2.2, this was far more difficult to port from
+// SDL than to simply use the XFree gamma ramp extension, but that affects the
+// whole screen even when the game window is inactive, this only affects the
+// screen while the window is active, very desirable behavior :)
int VID_SetGamma(float prescale, float gamma, float scale, float base)
{
+// LordHavoc: FIXME: finish this code, we need to allocate colors before we can store them
+#if 1
return FALSE;
+#else
+ int i, ncolors, c;
+ unsigned int Rmask, Gmask, Bmask, Rloss, Gloss, Bloss, Rshift, Gshift, Bshift, mask;
+ XColor xcmap[256];
+ unsigned short ramp[256];
+
+ if (COM_CheckParm("-nogamma"))
+ return FALSE;
+
+ if (vidx11_visual->class != DirectColor)
+ {
+ Con_Printf("X11 Visual class is %d, can only do gamma on %d\n", vidx11_visual->class, DirectColor);
+ return FALSE;
+ }
+
+ Rmask = vidx11_visual->red_mask;
+ Gmask = vidx11_visual->green_mask;
+ Bmask = vidx11_visual->blue_mask;
+
+ Rshift = 0;
+ Rloss = 8;
+ if ((mask = Rmask))
+ {
+ for (;!(mask & 1);mask >>= 1)
+ ++Rshift;
+ for (;(mask & 1);mask >>= 1)
+ --Rloss;
+ }
+ Gshift = 0;
+ Gloss = 8;
+ if ((mask = Gmask))
+ {
+ for (;!(mask & 1);mask >>= 1)
+ ++Gshift;
+ for (;(mask & 1);mask >>= 1)
+ --Gloss;
+ }
+ Bshift = 0;
+ Bloss = 8;
+ if ((mask = Bmask))
+ {
+ for (;!(mask & 1);mask >>= 1)
+ ++Bshift;
+ for (;(mask & 1);mask >>= 1)
+ --Bloss;
+ }
+
+ BuildGammaTable16(prescale, gamma, scale, base, ramp);
+
+ // convert gamma ramp to palette (yes this seems odd)
+ ncolors = vidx11_visual->map_entries;
+ for (i = 0;i < ncolors;i++)
+ {
+ c = (256 * i / ncolors);
+ xcmap[i].pixel = ((c >> Rloss) << Rshift) | ((c >> Gloss) << Gshift) | ((c >> Bloss) << Bshift);
+ xcmap[i].red = ramp[c];
+ xcmap[i].green = ramp[c];
+ xcmap[i].blue = ramp[c];
+ xcmap[i].flags = (DoRed|DoGreen|DoBlue);
+ }
+ XStoreColors(vidx11_display, vidx11_colormap, xcmap, ncolors);
+ XSync(vidx11_display, false);
+ // FIXME: should this check for BadAccess/BadColor/BadValue errors produced by XStoreColors before setting this true?
+ return TRUE;
+#endif
}
void VID_Init(void)
{
int i;
- int attrib[] =
+// LordHavoc: FIXME: finish this code, we need to allocate colors before we can store them
+#if 0
+ int gammaattrib[] =
+ {
+ GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ GLX_DEPTH_SIZE, 1,
+ GLX_X_VISUAL_TYPE, GLX_DIRECT_COLOR,
+ None
+ };
+#endif
+ int nogammaattrib[] =
{
GLX_RGBA,
GLX_RED_SIZE, 1,
XVisualInfo *visinfo;
qboolean fullscreen = true;
int MajorVersion, MinorVersion;
- int actualWidth, actualHeight;
Cvar_RegisterVariable (&vid_mouse);
Cvar_RegisterVariable (&vid_dga);
if (vid.conheight < 200)
vid.conheight = 200;
- if (!(dpy = XOpenDisplay(NULL)))
+ if (!(vidx11_display = XOpenDisplay(NULL)))
{
fprintf(stderr, "Error couldn't open the X display\n");
exit(1);
}
- scrnum = DefaultScreen(dpy);
- root = RootWindow(dpy, scrnum);
+ scrnum = DefaultScreen(vidx11_display);
+ root = RootWindow(vidx11_display, scrnum);
// Get video mode list
MajorVersion = MinorVersion = 0;
- if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion))
+ if (!XF86VidModeQueryVersion(vidx11_display, &MajorVersion, &MinorVersion))
vidmode_ext = false;
else
{
vidmode_ext = true;
}
- visinfo = glXChooseVisual(dpy, scrnum, attrib);
+ visinfo = NULL;
+// LordHavoc: FIXME: finish this code, we need to allocate colors before we can store them
+#if 0
+ if (!COM_CheckParm("-nogamma"))
+ visinfo = glXChooseVisual(vidx11_display, scrnum, gammaattrib);
+#endif
if (!visinfo)
{
- fprintf(stderr, "qkHack: Error couldn't get an RGB, Double-buffered, Depth visual\n");
- exit(1);
+ visinfo = glXChooseVisual(vidx11_display, scrnum, nogammaattrib);
+ if (!visinfo)
+ {
+ fprintf(stderr, "qkHack: Error couldn't get an RGB, Double-buffered, Depth visual\n");
+ exit(1);
+ }
}
if (vidmode_ext)
{
int best_fit, best_dist, dist, x, y;
- XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes);
+ XF86VidModeGetAllModeLines(vidx11_display, scrnum, &num_vidmodes, &vidmodes);
// Are we going fullscreen? If so, let's change video mode
if (fullscreen)
if (best_fit != -1)
{
- actualWidth = vidmodes[best_fit]->hdisplay;
- actualHeight = vidmodes[best_fit]->vdisplay;
+ // LordHavoc: changed from ActualWidth/ActualHeight =,
+ // to width/height =, so the window will take the full area of
+ // the mode chosen
+ width = vidmodes[best_fit]->hdisplay;
+ height = vidmodes[best_fit]->vdisplay;
// change to the mode
- XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]);
+ XF86VidModeSwitchToMode(vidx11_display, scrnum, vidmodes[best_fit]);
vidmode_active = true;
// Move the viewport to top left
- XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
+ XF86VidModeSetViewPort(vidx11_display, scrnum, 0, 0);
}
else
fullscreen = 0;
}
}
+ // LordHavoc: save the visual for use in gamma ramp settings later
+ vidx11_visual = visinfo->visual;
+
/* window attributes */
attr.background_pixel = 0;
attr.border_pixel = 0;
- attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
+ // LordHavoc: save the colormap for later, too
+ vidx11_colormap = attr.colormap = XCreateColormap(vidx11_display, root, visinfo->visual, AllocNone);
attr.event_mask = X_MASK;
if (vidmode_active)
{
else
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- win = XCreateWindow(dpy, root, 0, 0, width, height, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr);
- XStoreName(dpy, win, "DarkPlaces-GLX");
- XMapWindow(dpy, win);
+ win = XCreateWindow(vidx11_display, root, 0, 0, width, height, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr);
+ XStoreName(vidx11_display, win, gamename);
+ XMapWindow(vidx11_display, win);
if (vidmode_active)
{
- XMoveWindow(dpy, win, 0, 0);
- XRaiseWindow(dpy, win);
- XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0);
- XFlush(dpy);
+ XMoveWindow(vidx11_display, win, 0, 0);
+ XRaiseWindow(vidx11_display, win);
+ XWarpPointer(vidx11_display, None, win, 0, 0, 0, 0, 0, 0);
+ XFlush(vidx11_display);
// Move the viewport to top left
- XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
+ XF86VidModeSetViewPort(vidx11_display, scrnum, 0, 0);
}
- XFlush(dpy);
+ XFlush(vidx11_display);
- ctx = glXCreateContext(dpy, visinfo, NULL, True);
+ ctx = glXCreateContext(vidx11_display, visinfo, NULL, True);
- glXMakeCurrent(dpy, win, ctx);
+ glXMakeCurrent(vidx11_display, win, ctx);
scr_width = width;
scr_height = height;
vid.conheight = height;
if (vid.conwidth > width)
vid.conwidth = width;
- vid.width = vid.conwidth;
- vid.height = vid.conheight;
InitSig(); // trap evil signals
Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height);
// force a surface cache flush
- vid.recalc_refdef = 1;
+// vid.recalc_refdef = 1;
}
void Sys_SendKeyEvents(void)
if (/*freelook && */!(in_strafe.state & 1))
{
cl.viewangles[PITCH] += m_pitch.value * mouse_y;
- cl.viewangles[PITCH] = bound (-70, cl.viewangles[PITCH], 80);
+ cl.viewangles[PITCH] = bound (-90, cl.viewangles[PITCH], 90);
}
else
{
height = rect.bottom - rect.top;
// Create the DIB window
- mainwindow = CreateWindowEx (ExWindowStyle, "DarkPlaces", "DarkPlacesGL", WindowStyle, rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL);
+ mainwindow = CreateWindowEx (ExWindowStyle, gamename, gamename, WindowStyle, rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL);
if (!mainwindow)
Sys_Error ("Couldn't create DIB window");
vid.conheight = modelist[modenum].height;
if (vid.conwidth > modelist[modenum].width)
vid.conwidth = modelist[modenum].width;
- vid.width = vid.conwidth;
- vid.height = vid.conheight;
SendMessage (mainwindow, WM_SETICON, (WPARAM)true, (LPARAM)hIcon);
SendMessage (mainwindow, WM_SETICON, (WPARAM)false, (LPARAM)hIcon);
height = rect.bottom - rect.top;
// Create the DIB window
- mainwindow = CreateWindowEx (ExWindowStyle, "DarkPlaces", "DarkPlacesGL", WindowStyle, rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL);
+ mainwindow = CreateWindowEx (ExWindowStyle, gamename, gamename, WindowStyle, rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL);
if (!mainwindow)
Sys_Error ("Couldn't create DIB window");
vid.conheight = modelist[modenum].height;
if (vid.conwidth > modelist[modenum].width)
vid.conwidth = modelist[modenum].width;
- vid.width = vid.conwidth;
- vid.height = vid.conheight;
// needed because we're not getting WM_MOVE messages fullscreen on NT
window_x = 0;
if (!msg_suppress_1)
Con_SafePrintf ("Video mode %s initialized.\n", VID_GetModeDescription (vid_modenum));
- vid.recalc_refdef = 1;
+// vid.recalc_refdef = 1;
return true;
}
}
void VID_RestoreGameGamma(void);
+extern qboolean hostloopactive;
void AppActivate(BOOL fActive, BOOL minimize)
/****************************************************************************
// IN_ActivateMouse ();
// IN_HideMouse ();
// }
- VID_RestoreGameGamma();
+ if (hostloopactive)
+ VID_RestoreGameGamma();
}
if (!fActive)
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = 0;
- wc.lpszClassName = "DarkPlaces";
+ wc.lpszClassName = gamename;
if (!RegisterClass (&wc) )
Sys_Error ("Couldn't register window class");
==================
*/
void CalcGunAngle (void)
-{
+{
/*
float yaw, pitch, move;
static float oldyaw = 0;
v_idlescale.value = old;
}
+extern void CL_LerpUpdate(entity_t *e, int frame, int modelindex);
+
/*
==================
V_CalcRefdef
V_BoundOffsets ();
// set up gun position
+ VectorCopy (ent->render.origin, view->render.origin);
+ view->render.origin[2] += cl.viewheight;
VectorCopy (cl.viewangles, view->render.angles);
CalcGunAngle ();
- VectorCopy (ent->render.origin, view->render.origin);
- view->render.origin[2] += cl.viewheight;
-
for (i=0 ; i<3 ; i++)
{
view->render.origin[i] += forward[i]*bob*0.4;
}
view->render.origin[2] += bob;
+ // FIXME: this setup code is somewhat evil (CL_LerpUpdate should be private)
+ CL_LerpUpdate(view, cl.stats[STAT_WEAPONFRAME], cl.stats[STAT_WEAPON]);
+
view->render.model = cl.model_precache[cl.stats[STAT_WEAPON]];
view->render.frame = cl.stats[STAT_WEAPONFRAME];
view->render.colormap = -1; // no special coloring
+ view->render.alpha = ent->render.alpha; // LordHavoc: if the player is transparent, so is the gun
+ view->render.effects = ent->render.effects;
+ view->render.scale = 1;
+ VectorCopy(ent->render.colormod, view->render.colormod);
// set up the refresh position
void V_RenderView (void);
float V_CalcRoll (vec3_t angles, vec3_t velocity);
void V_UpdateBlends (void);
+void V_CalcBlend (void);
memset (sv_areanodes, 0, sizeof(sv_areanodes));
sv_numareanodes = 0;
- SV_CreateAreaNode (0, sv.worldmodel->mins, sv.worldmodel->maxs);
+ SV_CreateAreaNode (0, sv.worldmodel->normalmins, sv.worldmodel->normalmaxs);
}
*/
// 1/32 epsilon to keep floating point happy
-#define DIST_EPSILON (0.03125)
+//#define DIST_EPSILON (0.03125)
+#define DIST_EPSILON (0.125)
-/*
-==================
-SV_RecursiveHullCheck
+#define HULLCHECKSTATE_EMPTY 0
+#define HULLCHECKSTATE_SOLID 1
+#define HULLCHECKSTATE_DONE 2
-==================
-*/
-/*
-qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace)
+// LordHavoc: FIXME: this is not thread safe, if threading matters here, pass
+// this as a struct to RecursiveHullCheck, RecursiveHullCheck_Impact, etc...
+RecursiveHullCheckTraceInfo_t RecursiveHullCheckInfo;
+#define RHC RecursiveHullCheckInfo
+
+void SV_RecursiveHullCheck_Impact (mplane_t *plane, int side)
+{
+ // LordHavoc: using doubles for extra accuracy
+ double t1, t2, frac;
+
+ // LordHavoc: now that we have found the impact, recalculate the impact
+ // point from scratch for maximum accuracy, with an epsilon bias on the
+ // surface distance
+ frac = plane->dist;
+ if (side)
+ {
+ frac -= DIST_EPSILON;
+ VectorNegate (plane->normal, RHC.trace->plane.normal);
+ RHC.trace->plane.dist = -plane->dist;
+ }
+ else
+ {
+ frac += DIST_EPSILON;
+ VectorCopy (plane->normal, RHC.trace->plane.normal);
+ RHC.trace->plane.dist = plane->dist;
+ }
+
+ if (plane->type < 3)
+ {
+ t1 = RHC.start[plane->type] - frac;
+ t2 = RHC.start[plane->type] + RHC.dist[plane->type] - frac;
+ }
+ else
+ {
+ t1 = plane->normal[0] * RHC.start[0] + plane->normal[1] * RHC.start[1] + plane->normal[2] * RHC.start[2] - frac;
+ t2 = plane->normal[0] * (RHC.start[0] + RHC.dist[0]) + plane->normal[1] * (RHC.start[1] + RHC.dist[1]) + plane->normal[2] * (RHC.start[2] + RHC.dist[2]) - frac;
+ }
+
+ frac = t1 / (t1 - t2);
+ frac = bound(0.0f, frac, 1.0f);
+
+ RHC.trace->fraction = frac;
+ RHC.trace->endpos[0] = RHC.start[0] + frac * RHC.dist[0];
+ RHC.trace->endpos[1] = RHC.start[1] + frac * RHC.dist[1];
+ RHC.trace->endpos[2] = RHC.start[2] + frac * RHC.dist[2];
+}
+
+int SV_RecursiveHullCheck (int num, float p1f, float p2f, vec3_t p1, vec3_t p2)
{
dclipnode_t *node;
- mplane_t *plane;
- float t1, t2;
- float frac;
- int i;
vec3_t mid;
int side;
float midf;
+ // LordHavoc: FIXME: this is not thread safe... if threading matters here,
+ // remove the static prefixes
+ static int ret;
+ static mplane_t *plane;
+ static float t1, t2, frac;
+ // LordHavoc: a goto! everyone flee in terror... :)
loc0:
-// check for empty
+ // check for empty
if (num < 0)
{
- if (num != CONTENTS_SOLID)
+ RHC.trace->endcontents = num;
+ if (RHC.trace->startcontents)
{
- trace->allsolid = false;
- if (num == CONTENTS_EMPTY)
- trace->inopen = true;
+ if (num == RHC.trace->startcontents)
+ RHC.trace->allsolid = false;
else
- trace->inwater = true;
+ {
+ // if the first leaf is solid, set startsolid
+ if (RHC.trace->allsolid)
+ RHC.trace->startsolid = true;
+ return HULLCHECKSTATE_SOLID;
+ }
+ return HULLCHECKSTATE_EMPTY;
}
else
- trace->startsolid = true;
- return true; // empty
+ {
+ if (num != CONTENTS_SOLID)
+ {
+ RHC.trace->allsolid = false;
+ if (num == CONTENTS_EMPTY)
+ RHC.trace->inopen = true;
+ else
+ RHC.trace->inwater = true;
+ }
+ else
+ {
+ // if the first leaf is solid, set startsolid
+ if (RHC.trace->allsolid)
+ RHC.trace->startsolid = true;
+ return HULLCHECKSTATE_SOLID;
+ }
+ return HULLCHECKSTATE_EMPTY;
+ }
}
- if (num < hull->firstclipnode || num > hull->lastclipnode)
- Sys_Error ("SV_RecursiveHullCheck: bad node number");
-
-//
-// find the point distances
-//
- node = hull->clipnodes + num;
- plane = hull->planes + node->planenum;
+ // find the point distances
+ node = RHC.hull->clipnodes + num;
- t1 = PlaneDiff(p1, plane);
- t2 = PlaneDiff(p2, plane);
-
-#if 1
- if (t1 >= 0 && t2 >= 0)
- // LordHavoc: optimized recursion
-// return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
- {
- num = node->children[0];
- goto loc0;
- }
- if (t1 < 0 && t2 < 0)
-// return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
+ plane = RHC.hull->planes + node->planenum;
+ if (plane->type < 3)
{
- num = node->children[1];
- goto loc0;
+ t1 = p1[plane->type] - plane->dist;
+ t2 = p2[plane->type] - plane->dist;
}
-#else
- if ( (t1 >= DIST_EPSILON && t2 >= DIST_EPSILON) || (t2 > t1 && t1 >= 0) )
- return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
- if ( (t1 <= -DIST_EPSILON && t2 <= -DIST_EPSILON) || (t2 < t1 && t1 <= 0) )
- return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
-#endif
-
-// put the crosspoint DIST_EPSILON pixels on the near side
- if (t1 < 0)
- frac = bound(0, (t1 + DIST_EPSILON)/(t1-t2), 1);
else
- frac = bound(0, (t1 - DIST_EPSILON)/(t1-t2), 1);
-
- midf = p1f + (p2f - p1f)*frac;
- mid[0] = p1[0] + frac*(p2[0] - p1[0]);
- mid[1] = p1[1] + frac*(p2[1] - p1[1]);
- mid[2] = p1[2] + frac*(p2[2] - p1[2]);
-
- side = (t1 < 0);
-
-// move up to the node
- if (!SV_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) )
- return false;
-
-#ifdef PARANOID
- if (SV_HullPointContents (hull, node->children[side], mid) == CONTENTS_SOLID)
- {
- Con_Printf ("mid PointInHullSolid\n");
- return false;
- }
-#endif
-
- if (SV_HullPointContents (hull, node->children[side^1], mid) != CONTENTS_SOLID)
-// go past the node
- return SV_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace);
- // mid would need to be duplicated during recursion...
-*/
- /*
{
- p1f = midf;
- p1 = mid;
- num = node->children[side^1];
- goto loc0;
+ t1 = DotProduct (plane->normal, p1) - plane->dist;
+ t2 = DotProduct (plane->normal, p2) - plane->dist;
}
- */
-/*
- if (trace->allsolid)
- return false; // never got out of the solid area
-
-//==================
-// the other side of the node is solid, this is the impact point
-//==================
- if (!side)
+ // LordHavoc: rearranged the side/frac code
+ if (t1 >= 0)
{
- VectorCopy (plane->normal, trace->plane.normal);
- trace->plane.dist = plane->dist;
+ if (t2 >= 0)
+ {
+ num = node->children[0];
+ goto loc0;
+ }
+ // put the crosspoint DIST_EPSILON pixels on the near side
+ side = 0;
}
else
{
- VectorNegate (plane->normal, trace->plane.normal);
- trace->plane.dist = -plane->dist;
- }
-
- while (SV_HullPointContents (hull, hull->firstclipnode, mid) == CONTENTS_SOLID)
- { // shouldn't really happen, but does occasionally
- frac -= 0.1;
- if (frac < 0)
+ if (t2 < 0)
{
- trace->fraction = midf;
- VectorCopy (mid, trace->endpos);
- Con_DPrintf ("backup past 0\n");
- return false;
+ num = node->children[1];
+ goto loc0;
}
- midf = p1f + (p2f - p1f)*frac;
- for (i=0 ; i<3 ; i++)
- mid[i] = p1[i] + frac*(p2[i] - p1[i]);
+ // put the crosspoint DIST_EPSILON pixels on the near side
+ side = 1;
}
- trace->fraction = midf;
- VectorCopy (mid, trace->endpos);
+ frac = t1 / (t1 - t2);
+ frac = bound(0.0f, frac, 1.0f);
- return false;
+ midf = p1f + ((p2f - p1f) * frac);
+ mid[0] = RHC.start[0] + midf * RHC.dist[0];
+ mid[1] = RHC.start[1] + midf * RHC.dist[1];
+ mid[2] = RHC.start[2] + midf * RHC.dist[2];
+
+ // front side first
+ ret = SV_RecursiveHullCheck (node->children[side], p1f, midf, p1, mid);
+ if (ret != HULLCHECKSTATE_EMPTY)
+ return ret; // solid or done
+ ret = SV_RecursiveHullCheck (node->children[!side], midf, p2f, mid, p2);
+ if (ret != HULLCHECKSTATE_SOLID)
+ return ret; // empty or done
+
+ // front is air and back is solid, this is the impact point...
+ SV_RecursiveHullCheck_Impact(RHC.hull->planes + node->planenum, side);
+
+ return HULLCHECKSTATE_DONE;
}
-*/
-// LordHavoc: backported from my optimizations to PM_RecursiveHullCheck in QuakeForge newtree (QW)
-qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace)
+/*
+qboolean SV_RecursiveHullCheckContentBoundary (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace)
{
dclipnode_t *node;
mplane_t *plane;
// check for empty
if (num < 0)
{
- if (num != CONTENTS_SOLID)
- {
- trace->allsolid = false;
- if (num == CONTENTS_EMPTY)
- trace->inopen = true;
- else
- trace->inwater = true;
- }
- else
+ if (num != trace->startcontents)
trace->startsolid = true;
+ else
+ trace->allsolid = false;
return true; // empty
}
t2 = DotProduct (plane->normal, p2) - plane->dist;
}
+ // LordHavoc: rearranged the side/frac code
// LordHavoc: recursion optimization
- if (t1 >= 0 && t2 >= 0)
+ if (t1 >= 0)
{
- num = node->children[0];
- goto loc0;
+ if (t2 >= 0)
+ {
+ num = node->children[0];
+ goto loc0;
+ }
+ // put the crosspoint DIST_EPSILON pixels on the near side
+ side = 0;
}
- if (t1 < 0 && t2 < 0)
+ else
{
- num = node->children[1];
- goto loc0;
+ if (t2 < 0)
+ {
+ num = node->children[1];
+ goto loc0;
+ }
+ // put the crosspoint DIST_EPSILON pixels on the near side
+ side = 1;
}
-// put the crosspoint DIST_EPSILON pixels on the near side
- side = (t1 < 0);
- if (side)
- frac = bound(0, (t1 + DIST_EPSILON) / (t1 - t2), 1);
- else
- frac = bound(0, (t1 - DIST_EPSILON) / (t1 - t2), 1);
-
- midf = p1f + (p2f - p1f)*frac;
- for (i=0 ; i<3 ; i++)
- mid[i] = p1[i] + frac*(p2[i] - p1[i]);
+ frac = t1 / (t1 - t2);
+ frac = bound(0.0f, frac, 1.0f);
+
+ midf = p1f + ((p2f - p1f) * frac);
+ mid[0] = p1[0] + ((p2[0] - p1[0]) * frac);
+ mid[1] = p1[1] + ((p2[1] - p1[1]) * frac);
+ mid[2] = p1[2] + ((p2[2] - p1[2]) * frac);
// move up to the node
if (!SV_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) )
return false;
+*/
+ /*
#ifdef PARANOID
- if (SV_HullPointContents (pm_hullmodel, mid, node->children[side]) == CONTENTS_SOLID)
+ if (SV_HullPointContents (pm_hullmodel, mid, node->children[side]) != trace->startcontents)
{
Con_Printf ("mid PointInHullSolid\n");
return false;
}
#endif
+ */
+/*
// LordHavoc: warning to the clumsy, this recursion can not be optimized because mid would need to be duplicated on a stack
- if (SV_HullPointContents (hull, node->children[side^1], mid) != CONTENTS_SOLID)
+ if (SV_HullPointContents (hull, node->children[side^1], mid) == trace->startcontents)
// go past the node
return SV_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace);
-
+
if (trace->allsolid)
return false; // never got out of the solid area
-
+
//==================
// the other side of the node is solid, this is the impact point
//==================
trace->plane.dist = -plane->dist;
}
- while (SV_HullPointContents (hull, hull->firstclipnode, mid) == CONTENTS_SOLID)
- { // shouldn't really happen, but does occasionally
+*/
+ /*
+ while (SV_HullPointContents (hull, hull->firstclipnode, mid) != trace->startcontents)
+ {
+ // shouldn't really happen, but does occasionally
frac -= 0.1;
if (frac < 0)
{
return false;
}
midf = p1f + (p2f - p1f)*frac;
- for (i=0 ; i<3 ; i++)
- mid[i] = p1[i] + frac*(p2[i] - p1[i]);
+ mid[0] = p1[0] + frac*(p2[0] - p1[0]);
+ mid[1] = p1[1] + frac*(p2[1] - p1[1]);
+ mid[2] = p1[2] + frac*(p2[2] - p1[2]);
}
+ */
+/*
+
+ frac = t1;
+ if (side)
+ frac += DIST_EPSILON;
+ else
+ frac -= DIST_EPSILON;
- trace->fraction = midf;
- VectorCopy (mid, trace->endpos);
+ frac /= (t1 - t2);
+ frac = bound(0.0f, frac, 1.0f);
+
+ trace->fraction = p1f + (p2f - p1f)*frac;
+ trace->endpos[0] = p1[0] + frac*(p2[0] - p1[0]);
+ trace->endpos[1] = p1[1] + frac*(p2[1] - p1[1]);
+ trace->endpos[2] = p1[2] + frac*(p2[2] - p1[2]);
return false;
}
+*/
qboolean SV_TestLine (hull_t *hull, int num, vec3_t p1, vec3_t p2)
{
// find the point distances
//
node = hull->clipnodes + num;
+ if (node->children[0] < 0)
+ {
+ if (node->children[0] == CONTENTS_SOLID)
+ return false;
+ if (node->children[1] < 0)
+ return node->children[1] != CONTENTS_SOLID;
+ }
+ else if (node->children[1] == CONTENTS_SOLID)
+ return false;
+
plane = hull->planes + node->planenum;
- t1 = PlaneDiff(p1, plane);
- t2 = PlaneDiff(p2, plane);
-
- if (t1 >= 0 && t2 >= 0)
+ if (plane->type < 3)
{
- num = node->children[0];
- goto loc0;
+ t1 = p1[plane->type] - plane->dist;
+ t2 = p2[plane->type] - plane->dist;
}
- if (t1 < 0 && t2 < 0)
+ else
{
- num = node->children[1];
- goto loc0;
+ t1 = DotProduct (plane->normal, p1) - plane->dist;
+ t2 = DotProduct (plane->normal, p2) - plane->dist;
}
-// put the crosspoint DIST_EPSILON pixels on the near side
- side = (t1 < 0);
-
- if (side)
- frac = bound(0, (t1 + DIST_EPSILON)/(t1-t2), 1);
+ if (t1 >= 0)
+ {
+ if (t2 >= 0)
+ {
+ num = node->children[0];
+ goto loc0;
+ }
+ side = 0;
+ }
else
- frac = bound(0, (t1 - DIST_EPSILON)/(t1-t2), 1);
-
- mid[0] = p1[0] + frac*(p2[0] - p1[0]);
- mid[1] = p1[1] + frac*(p2[1] - p1[1]);
- mid[2] = p1[2] + frac*(p2[2] - p1[2]);
+ {
+ if (t2 < 0)
+ {
+ num = node->children[1];
+ goto loc0;
+ }
+ side = 1;
+ }
if (node->children[side] < 0)
{
if (node->children[side] == CONTENTS_SOLID)
return false;
- return SV_TestLine(hull, node->children[!side], mid, p2);
+
+ if (node->children[!side] < 0)
+ return node->children[!side] != CONTENTS_SOLID;
+ else
+ {
+ frac = t1 / (t1 - t2);
+ frac = bound(0, frac, 1);
+
+ mid[0] = p1[0] + frac*(p2[0] - p1[0]);
+ mid[1] = p1[1] + frac*(p2[1] - p1[1]);
+ mid[2] = p1[2] + frac*(p2[2] - p1[2]);
+
+ return SV_TestLine(hull, node->children[!side], mid, p2);
+ }
}
- else if (SV_TestLine(hull, node->children[side], p1, mid))
- return SV_TestLine(hull, node->children[!side], mid, p2);
else
- return false;
+ {
+ if (node->children[!side] < 0)
+ {
+ if (node->children[!side] == CONTENTS_SOLID)
+ return false;
+
+ frac = t1 / (t1 - t2);
+ frac = bound(0, frac, 1);
+
+ mid[0] = p1[0] + frac*(p2[0] - p1[0]);
+ mid[1] = p1[1] + frac*(p2[1] - p1[1]);
+ mid[2] = p1[2] + frac*(p2[2] - p1[2]);
+
+ return SV_TestLine(hull, node->children[side], p1, mid);
+ }
+ else
+ {
+ frac = t1 / (t1 - t2);
+ frac = bound(0, frac, 1);
+
+ mid[0] = p1[0] + frac*(p2[0] - p1[0]);
+ mid[1] = p1[1] + frac*(p2[1] - p1[1]);
+ mid[2] = p1[2] + frac*(p2[2] - p1[2]);
+
+ if (SV_TestLine(hull, node->children[side], p1, mid))
+ return SV_TestLine(hull, node->children[!side], mid, p2);
+ else
+ return false;
+ }
+ }
}
}
// trace a line through the apropriate clipping hull
- SV_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace);
+ VectorCopy(start_l, RecursiveHullCheckInfo.start);
+ VectorSubtract(end_l, start_l, RecursiveHullCheckInfo.dist);
+ RecursiveHullCheckInfo.hull = hull;
+ RecursiveHullCheckInfo.trace = &trace;
+ SV_RecursiveHullCheck (hull->firstclipnode, 0, 1, start_l, end_l);
// LordHavoc: enabling rotating bmodels
// rotate endpos back to world frame of reference
VectorCopy (mins, clip.mins2);
VectorCopy (maxs, clip.maxs2);
}
-
+
// create the bounding box of the entire move
SV_MoveBounds ( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs );
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
vec3_t endpos; // final position
plane_t plane; // surface normal at impact
edict_t *ent; // entity the surface is on
- // LordHavoc: added texture and lighting to traceline
- char *texturename;
- vec3_t light;
+ int startcontents; // if not zero, treats this value as empty, and
+ // all others as solid (impact on content change)
+ int endcontents; // set to the contents that was hit at the end point
} trace_t;
// passedict is explicitly excluded from clipping checks (normally NULL)
-extern qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace);
+int SV_RecursiveHullCheck (int num, float p1f, float p2f, vec3_t p1, vec3_t p2);
+
+typedef struct
+{
+ hull_t *hull;
+ trace_t *trace;
+ vec3_t start;
+ vec3_t dist;
+}
+RecursiveHullCheckTraceInfo_t;
+
+// LordHavoc: FIXME: this is not thread safe, if threading matters here, pass
+// this as a struct to RecursiveHullCheck, RecursiveHullCheck_Impact, etc...
+extern RecursiveHullCheckTraceInfo_t RecursiveHullCheckInfo;