// entire entity array was cleared, so just fill in a few fields
ent->state_current.active = true;
ent->render.model = cl.worldmodel = NULL; // no world model yet
- ent->render.scale = 1; // some of the renderer still relies on scale
ent->render.alpha = 1;
ent->render.colormap = -1; // no special coloring
ent->render.flags = RENDER_SHADOW | RENDER_LIGHT;
Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, 0, 0, 0, 0, 0, 0, 1);
- Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
- CL_BoundingBoxForEntity(&ent->render);
+ CL_UpdateRenderEntity(&ent->render);
// noclip is turned off at start
noclip_anglehack = false;
entity_t *ent;
int i, j;
char name[32];
- vec3_t org;
for (i = 0, ent = cl.entities;i < cl.num_entities;i++, ent++)
{
strlcpy(name, modelname, 25);
for (j = (int)strlen(name);j < 25;j++)
name[j] = ' ';
- Matrix4x4_OriginFromMatrix(&ent->render.matrix, org);
- Con_Printf("%3i: %s:%4i (%5i %5i %5i) [%3i %3i %3i] %4.2f %5.3f\n", i, name, ent->render.frame, (int) org[0], (int) org[1], (int) org[2], (int) ent->render.angles[0] % 360, (int) ent->render.angles[1] % 360, (int) ent->render.angles[2] % 360, ent->render.scale, ent->render.alpha);
+ Con_Printf("%3i: %s:%4i (%5i %5i %5i) [%3i %3i %3i] %4.2f %5.3f\n", i, name, ent->render.frame, (int) ent->state_current.origin[0], (int) ent->state_current.origin[1], (int) ent->state_current.origin[2], (int) ent->state_current.angles[0] % 360, (int) ent->state_current.angles[1] % 360, (int) ent->state_current.angles[2] % 360, ent->render.scale, ent->render.alpha);
}
}
//static const vec3_t nomodelmins = {-16, -16, -16};
//static const vec3_t nomodelmaxs = {16, 16, 16};
-void CL_BoundingBoxForEntity(entity_render_t *ent)
+void CL_UpdateRenderEntity(entity_render_t *ent)
{
vec3_t org;
+ vec_t scale;
model_t *model = ent->model;
+ // update the inverse matrix for the renderer
+ Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix);
+ // update the animation blend state
+ R_LerpAnimation(ent);
+ // we need the matrix origin to center the box
Matrix4x4_OriginFromMatrix(&ent->matrix, org);
+ // update entity->render.scale because the renderer needs it
+ ent->scale = scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
if (model)
{
// NOTE: this directly extracts vector components from the matrix, which relies on the matrix orientation!
#endif
{
// pitch or roll
- ent->mins[0] = org[0] + model->rotatedmins[0];
- ent->mins[1] = org[1] + model->rotatedmins[1];
- ent->mins[2] = org[2] + model->rotatedmins[2];
- ent->maxs[0] = org[0] + model->rotatedmaxs[0];
- ent->maxs[1] = org[1] + model->rotatedmaxs[1];
- ent->maxs[2] = org[2] + model->rotatedmaxs[2];
+ VectorMA(org, scale, model->rotatedmins, ent->mins);
+ VectorMA(org, scale, model->rotatedmaxs, ent->maxs);
}
#ifdef MATRIX4x4_OPENGLORIENTATION
else if (ent->matrix.m[1][0] != 0 || ent->matrix.m[0][1] != 0)
#endif
{
// yaw
- ent->mins[0] = org[0] + model->yawmins[0];
- ent->mins[1] = org[1] + model->yawmins[1];
- ent->mins[2] = org[2] + model->yawmins[2];
- ent->maxs[0] = org[0] + model->yawmaxs[0];
- ent->maxs[1] = org[1] + model->yawmaxs[1];
- ent->maxs[2] = org[2] + model->yawmaxs[2];
+ VectorMA(org, scale, model->yawmins, ent->mins);
+ VectorMA(org, scale, model->yawmaxs, ent->maxs);
}
else
{
- ent->mins[0] = org[0] + model->normalmins[0];
- ent->mins[1] = org[1] + model->normalmins[1];
- ent->mins[2] = org[2] + model->normalmins[2];
- ent->maxs[0] = org[0] + model->normalmaxs[0];
- ent->maxs[1] = org[1] + model->normalmaxs[1];
- ent->maxs[2] = org[2] + model->normalmaxs[2];
+ VectorMA(org, scale, model->normalmins, ent->mins);
+ VectorMA(org, scale, model->normalmaxs, ent->maxs);
}
}
else
r_refdef.entities[r_refdef.numentities++] = &ent->render;
ent->render.colormap = -1; // no special coloring
- ent->render.scale = 1;
ent->render.alpha = 1;
VectorSet(ent->render.colormod, 1, 1, 1);
return ent;
// attach the flag to the player matrix
Matrix4x4_CreateFromQuakeEntity(&flagmatrix, -f, -22, 0, 0, 0, -45, 1);
Matrix4x4_Concat(&flag->render.matrix, &player->render.matrix, &flagmatrix);
- Matrix4x4_Invert_Simple(&flag->render.inversematrix, &flag->render.matrix);
- R_LerpAnimation(&flag->render);
- CL_BoundingBoxForEntity(&flag->render);
+ CL_UpdateRenderEntity(&flag->render);
}
#define MAXVIEWMODELS 32
e->render.frame2time = cl.time;
e->render.framelerp = 0;
}
- R_LerpAnimation(&e->render);
// set up the render matrix
// FIXME: e->render.scale should go away
// concat the matrices to make the entity relative to its tag
Matrix4x4_Concat(&e->render.matrix, matrix, &matrix2);
// make the other useful stuff
- Matrix4x4_Invert_Simple(&e->render.inversematrix, &e->render.matrix);
- CL_BoundingBoxForEntity(&e->render);
+ CL_UpdateRenderEntity(&e->render);
// handle effects now that we know where this entity is in the world...
if (e->render.model && e->render.model->soundfromcenter)
cl.brushmodel_entities[cl.num_brushmodel_entities++] = 0;
// FIXME: this should be done at load
ent->render.matrix = identitymatrix;
- ent->render.inversematrix = identitymatrix;
- R_LerpAnimation(&ent->render);
- CL_BoundingBoxForEntity(&ent->render);
+ CL_UpdateRenderEntity(&ent->render);
ent->render.flags = RENDER_SHADOW;
if (!r_fullbright.integer)
ent->render.flags |= RENDER_LIGHT;
VectorSet(ent->render.colormod, 1, 1, 1);
Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, e->origin[0], e->origin[1], e->origin[2], 0, 0, 0, 1);
- Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
- R_LerpAnimation(&ent->render);
- CL_BoundingBoxForEntity(&ent->render);
+ CL_UpdateRenderEntity(&ent->render);
}
}
}
//ent->render.angles[1] = yaw;
//ent->render.angles[2] = rand()%360;
Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, org[0], org[1], org[2], -pitch, yaw, lhrandom(0, 360), 1);
- Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
- R_LerpAnimation(&ent->render);
- CL_BoundingBoxForEntity(&ent->render);
+ CL_UpdateRenderEntity(&ent->render);
VectorMA(org, 30, dist, org);
d -= 30;
}
VectorSet(ent->render.colormod, 1, 1, 1);
Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, v[0], v[1], v[2], v[3], v[4], v[5], 1);
- Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
- R_LerpAnimation(&ent->render);
- CL_BoundingBoxForEntity(&ent->render);
+ CL_UpdateRenderEntity(&ent->render);
}
}
// now that we have a world model, set up the world entity, renderer
// modules and csqc
cl.entities[0].render.model = cl.worldmodel = cl.model_precache[1];
- CL_BoundingBoxForEntity(&cl.entities[0].render);
+ CL_UpdateRenderEntity(&cl.entities[0].render);
R_Modules_NewMap();
// we now have the worldmodel so we can set up the game world
cl.entities[0].render.model = cl.worldmodel = cl.model_precache[1];
- CL_BoundingBoxForEntity(&cl.entities[0].render);
+ CL_UpdateRenderEntity(&cl.entities[0].render);
R_Modules_NewMap();
}
ent->render.skinnum = ent->state_baseline.skin;
ent->render.effects = ent->state_baseline.effects;
ent->render.alpha = 1;
- //ent->render.scale = 1;
//VectorCopy (ent->state_baseline.origin, ent->render.origin);
//VectorCopy (ent->state_baseline.angles, ent->render.angles);
Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, ent->state_baseline.origin[0], ent->state_baseline.origin[1], ent->state_baseline.origin[2], ent->state_baseline.angles[0], ent->state_baseline.angles[1], ent->state_baseline.angles[2], 1);
- Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
- CL_BoundingBoxForEntity(&ent->render);
+ CL_UpdateRenderEntity(&ent->render);
// This is definitely cheating...
if (ent->render.model == NULL)
typedef struct entity_render_s
{
// location
- vec3_t origin;
+ //vec3_t origin;
// orientation
- vec3_t angles;
+ //vec3_t angles;
// transform matrix for model to world
matrix4x4_t matrix;
// transform matrix for world to model
float airfriction; // how much air friction affects this object (objects with a low mass/size ratio tend to get more air friction)
float liquidfriction; // how much liquid friction affects this object (objects with a low mass/size ratio tend to get more liquid friction)
unsigned char color[4];
- unsigned short owner; // decal stuck to this entity
+ unsigned int owner; // decal stuck to this entity
model_t *ownermodel; // model the decal is stuck to (used to make sure the entity is still alive)
vec3_t relativeorigin; // decal at this location in entity's coordinate space
vec3_t relativedirection; // decal oriented this way relative to entity's coordinate space
void CL_Disconnect (void);
void CL_Disconnect_f (void);
-void CL_BoundingBoxForEntity(entity_render_t *ent);
+void CL_UpdateRenderEntity(entity_render_t *ent);
//
// cl_input
prog->globals.client->input_buttons = csqc_buttons;
VectorSet(prog->globals.client->input_movevalues, cl.cmd.forwardmove, cl.cmd.sidemove, cl.cmd.upmove);
//VectorCopy(cl.movement_origin, csqc_origin);
- VectorCopy(cl.entities[cl.viewentity].render.origin, csqc_origin);
+ Matrix4x4_OriginFromMatrix(&cl.entities[cl.viewentity].render.matrix, csqc_origin);
VectorCopy(csqc_origin, prog->globals.client->pmove_org);
prog->globals.client->maxclients = cl.maxclients;
//VectorCopy(cl.movement_velocity, prog->globals.client->pmove_vel);
Matrix4x4_CreateFromQuakeEntity(&matrix2, ed->fields.client->origin[0], ed->fields.client->origin[1], ed->fields.client->origin[2], angles[0], angles[1], angles[2], e->render.scale);
}
- // concat the matrices to make the entity relative to its tag
- Matrix4x4_Concat(&e->render.matrix, &tagmatrix, &matrix2);
- // make the other useful stuff
- Matrix4x4_Invert_Simple(&e->render.inversematrix, &e->render.matrix);
- CL_BoundingBoxForEntity(&e->render);
-
// FIXME: csqc has frame1/frame2/frame1time/frame2time/lerpfrac but this implementation's cl_entvars_t lacks those fields
e->render.frame1 = e->render.frame = ed->fields.client->frame;
e->render.frame1time = e->render.frame2time = 0;
e->render.framelerp = 0;
- R_LerpAnimation(&e->render);
+
+ // concat the matrices to make the entity relative to its tag
+ Matrix4x4_Concat(&e->render.matrix, &tagmatrix, &matrix2);
+ // make the other useful stuff
+ CL_UpdateRenderEntity(&e->render);
i = 0;
if((val = PRVM_GETEDICTFIELDVALUE(ed, csqc_fieldoff_renderflags)) && val->_float)
if(msg[2] == 'q')
if(msg[3] == 'c')
{
- Cvar_SetQuick(&csqc_progcrc, "0");
csqc_progcrc.flags = 0;
Cmd_ExecuteString (msg, src_command);
csqc_progcrc.flags = CVAR_READONLY;
void CL_VM_Init (void)
{
+ unsigned char *csprogsdata;
+ fs_offset_t csprogsdatasize;
+ unsigned int csprogsdatacrc;
entity_t *ent;
csqc_loaded = false;
memset(cl.csqc_model_precache, 0, sizeof(cl.csqc_model_precache));
memset(&cl.csqc_vidvars, true, sizeof(csqc_vidvars_t));
- if(!FS_FileExists(csqc_progname.string))
+ // if the server is not requesting a csprogs, then we're done here
+ if (!csqc_progcrc.integer)
+ return;
+
+ // see if there is a csprogs.dat installed, and if so, set the csqc_progcrc accordingly, this will be sent to connecting clients to tell them to only load a matching csprogs.dat file
+ csprogsdatacrc = 0;
+ csprogsdata = FS_LoadFile(csqc_progname.string, tempmempool, true, &csprogsdatasize);
+ if (csprogsdata)
{
- if(!sv.active && csqc_progcrc.integer)
+ csprogsdatacrc = CRC_Block(csprogsdata, csprogsdatasize);
+ Mem_Free(csprogsdata);
+ if(csprogsdatacrc != (unsigned short)csqc_progcrc.integer && !sv.active && !cls.demoplayback)
{
- Con_Printf("CL_VM_Init: server requires CSQC, but \"%s\" wasn't found\n", csqc_progname.string);
+ Con_Printf("^1Your %s is not the same version as the server (CRC is %i but should be %i)\n", csqc_progname.string, prog->filecrc, csqc_progcrc.integer);
+ PRVM_ResetProg();
CL_Disconnect();
+ return;
}
- return;
}
else
{
- if (developer.integer < 100)
- {
- Con_DPrintf("CL_VM_Init: CSQC is broken, and is not being loaded because developer is less than 100.\n");
- return;
- }
- if(!sv.active && !csqc_progcrc.integer) //[515]: because cheaters may use csqc while server didn't allowed it !
+ if(!sv.active && csqc_progcrc.integer)
{
- Con_Printf("CL_VM_Init: server didn't sent CSQC crc, so CSQC is disabled\n");
- return;
+ Con_Printf("CL_VM_Init: server requires CSQC, but \"%s\" wasn't found\n", csqc_progname.string);
+ CL_Disconnect();
}
+ return;
}
PRVM_Begin;
}
if(prog->loaded)
- {
- Cvar_SetValueQuick(&csqc_progcrc, prog->filecrc);
Con_Printf("CSQC ^5loaded (crc=%i)\n", csqc_progcrc.integer);
- }
else
{
CL_VM_Error("CSQC ^2failed to load\n");
// entire entity array was cleared, so just fill in a few fields
ent->state_current.active = true;
ent->render.model = cl.worldmodel = cl.model_precache[1];
- ent->render.scale = 1; // some of the renderer still relies on scale
ent->render.alpha = 1;
ent->render.flags = RENDER_SHADOW | RENDER_LIGHT;
Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, 0, 0, 0, 0, 0, 0, 1);
- Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
- CL_BoundingBoxForEntity(&ent->render);
+ CL_UpdateRenderEntity(&ent->render);
}
void CL_VM_ShutDown (void)
VectorClear(ent->modellight_diffuse);
VectorClear(ent->modellight_lightdir);
if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
- r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
+ {
+ vec3_t org;
+ Matrix4x4_OriginFromMatrix(&ent->matrix, org);
+ r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
+ }
else // highly rare
VectorSet(ent->modellight_ambient, 1, 1, 1);
Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
for (i = 0;i < r_refdef.numentities;i++)
{
entity_render_t *ent = r_refdef.entities[i];
- // some of the renderer still relies on origin...
- Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
- // some of the renderer still relies on scale...
- ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
R_UpdateEntityLighting(ent);
}
}
R_Mesh_VertexPointer(nomodelvertex3f);
if (r_refdef.fogenabled)
{
+ vec3_t org;
memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
R_Mesh_ColorPointer(color4f);
- f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_view.origin));
+ Matrix4x4_OriginFromMatrix(&ent->matrix, org);
+ f2 = VERTEXFOGTABLE(VectorDistance(org, r_view.origin));
f1 = 1 - f2;
for (i = 0, c = color4f;i < 6;i++, c += 4)
{
void R_DrawNoModel(entity_render_t *ent)
{
+ vec3_t org;
+ Matrix4x4_OriginFromMatrix(&ent->matrix, org);
//if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
- R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
+ R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
//else
// R_DrawNoModelCallback(ent, 0);
}
&& (r_refdef.worldmodel == NULL || r_refdef.worldmodel->brush.BoxTouchingLeafPVS == NULL || r_refdef.worldmodel->brush.BoxTouchingLeafPVS(r_refdef.worldmodel, leafpvs, ent->mins, ent->maxs)))
{
// about the VectorDistance2 - light emitting entities should not cast their own shadow
- if ((ent->flags & RENDER_SHADOW) && model->DrawShadowVolume && VectorDistance2(ent->origin, rtlight->shadoworigin) > 0.1)
+ vec3_t org;
+ Matrix4x4_OriginFromMatrix(&ent->matrix, org);
+ if ((ent->flags & RENDER_SHADOW) && model->DrawShadowVolume && VectorDistance2(org, rtlight->shadoworigin) > 0.1)
shadowentities[numshadowentities++] = ent;
if (r_viewcache.entityvisible[i] && (ent->flags & RENDER_LIGHT) && model->DrawLight)
lightentities[numlightentities++] = ent;
color[0] = color[1] = color[2] = 1;
else
{
- R_CompleteLightPoint(color, diffusecolor, diffusenormal, ent->origin, true);
+ vec3_t org;
+ Matrix4x4_OriginFromMatrix(&ent->matrix, org);
+ R_CompleteLightPoint(color, diffusecolor, diffusenormal, org, true);
VectorMA(color, 0.5f, diffusecolor, color);
}
color[0] *= ent->colormod[0];
void R_Model_Sprite_Draw(entity_render_t *ent)
{
+ vec3_t org;
if (ent->frameblend[0].frame < 0)
return;
- R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : ent->origin, R_Model_Sprite_Draw_TransparentCallback, ent, 0, r_shadow_rtlight);
+ Matrix4x4_OriginFromMatrix(&ent->matrix, org);
+ R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_Model_Sprite_Draw_TransparentCallback, ent, 0, r_shadow_rtlight);
}