#include "csprogs.h"
#include "cl_collision.h"
#include "r_shadow.h"
+#include "jpeg.h"
+#include "image.h"
//============================================================================
// Client
//4 feature darkplaces csqc: add builtin to clientside qc for reading triangles of model meshes (useful to orient a ui along a triangle of a model mesh)
//4 feature darkplaces csqc: add builtins to clientside qc for gl calls
+extern cvar_t v_flipped;
+
sfx_t *S_FindName(const char *name);
int Sbar_GetSortedPlayerIndex (int index);
void Sbar_SortFrags (void);
{
prvm_edict_t *e;
const char *m;
- model_t *mod;
+ dp_model_t *mod;
int i;
VM_SAFEPARMCOUNT(2, VM_CL_setmodel);
{
const char *name;
int i;
- model_t *m;
+ dp_model_t *m;
VM_SAFEPARMCOUNT(1, VM_CL_precache_model);
{
if (!cl.csqc_model_precache[i])
{
- cl.csqc_model_precache[i] = (model_t*)m;
+ cl.csqc_model_precache[i] = (dp_model_t*)m;
PRVM_G_FLOAT(OFS_RETURN) = -(i+1);
return;
}
r_refdef.view.ortho_x = scr_fov.value * (3.0 / 4.0) * (float)r_refdef.view.width / (float)r_refdef.view.height / vid_pixelheight.value;
r_refdef.view.ortho_y = scr_fov.value * (3.0 / 4.0);
r_refdef.view.clear = true;
+ r_refdef.view.isoverlay = false;
// FIXME: restore cl.csqc_origin
// FIXME: restore cl.csqc_angles
cl.csqc_vidvars.drawworld = true;
switch(c)
{
case VF_MIN:
- r_refdef.view.x = (int)(f[0] * vid.width / vid_conwidth.value);
- r_refdef.view.y = (int)(f[1] * vid.height / vid_conheight.value);
+ r_refdef.view.x = (int)(f[0]);
+ r_refdef.view.y = (int)(f[1]);
break;
case VF_MIN_X:
- r_refdef.view.x = (int)(k * vid.width / vid_conwidth.value);
+ r_refdef.view.x = (int)(k);
break;
case VF_MIN_Y:
- r_refdef.view.y = (int)(k * vid.height / vid_conheight.value);
+ r_refdef.view.y = (int)(k);
break;
case VF_SIZE:
- r_refdef.view.width = (int)(f[0] * vid.width / vid_conwidth.value);
- r_refdef.view.height = (int)(f[1] * vid.height / vid_conheight.value);
- break;
- case VF_SIZE_Y:
- r_refdef.view.width = (int)(k * vid.width / vid_conwidth.value);
+ r_refdef.view.width = (int)(f[0]);
+ r_refdef.view.height = (int)(f[1]);
break;
case VF_SIZE_X:
- r_refdef.view.height = (int)(k * vid.height / vid_conheight.value);
+ r_refdef.view.width = (int)(k);
+ break;
+ case VF_SIZE_Y:
+ r_refdef.view.height = (int)(k);
break;
case VF_VIEWPORT:
- r_refdef.view.x = (int)(f[0] * vid.width / vid_conwidth.value);
- r_refdef.view.y = (int)(f[1] * vid.height / vid_conheight.value);
+ r_refdef.view.x = (int)(f[0]);
+ r_refdef.view.y = (int)(f[1]);
f = PRVM_G_VECTOR(OFS_PARM2);
- r_refdef.view.width = (int)(f[0] * vid.width / vid_conwidth.value);
- r_refdef.view.height = (int)(f[1] * vid.height / vid_conheight.value);
+ r_refdef.view.width = (int)(f[0]);
+ r_refdef.view.height = (int)(f[1]);
break;
case VF_FOV:
r_refdef.view.frustum_x = tan(f[0] * M_PI / 360.0);r_refdef.view.ortho_x = f[0];
r_refdef.view.useperspective = k != 0;
break;
case VF_CLEARSCREEN:
- r_refdef.view.clear = k ? true : false;
+ r_refdef.view.isoverlay = !k;
break;
default:
PRVM_G_FLOAT(OFS_RETURN) = 0;
PRVM_G_FLOAT(OFS_RETURN) = 1;
}
-//#304 void() renderscene (EXT_CSQC)
-void VM_CL_R_RenderScene (void)
-{
- VM_SAFEPARMCOUNT(0, VM_CL_R_RenderScene);
- // we need to update any RENDER_VIEWMODEL entities at this point because
- // csqc supplies its own view matrix
- CL_UpdateViewEntities();
- // now draw stuff!
- R_RenderView();
-}
-
-//#305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
+//#305 void(vector org, float radius, vector lightcolours[, float style, string cubemapname, float pflags]) adddynamiclight (EXT_CSQC)
void VM_CL_R_AddDynamicLight (void)
{
- float *pos, *col;
- matrix4x4_t matrix;
- VM_SAFEPARMCOUNTRANGE(3, 3, VM_CL_R_AddDynamicLight);
+ vec_t *org;
+ float radius = 300;
+ vec_t *col;
+ int style = -1;
+ const char *cubemapname = NULL;
+ int pflags = PFLAGS_CORONA | PFLAGS_FULLDYNAMIC;
+ float coronaintensity = 1;
+ float coronasizescale = 0.25;
+ qboolean castshadow = true;
+ float ambientscale = 0;
+ float diffusescale = 1;
+ float specularscale = 1;
+ matrix4x4_t matrix;
+ vec3_t forward, left, up;
+ VM_SAFEPARMCOUNTRANGE(3, 8, VM_CL_R_AddDynamicLight);
// if we've run out of dlights, just return
if (r_refdef.scene.numlights >= MAX_DLIGHTS)
return;
- pos = PRVM_G_VECTOR(OFS_PARM0);
+ org = PRVM_G_VECTOR(OFS_PARM0);
+ radius = PRVM_G_FLOAT(OFS_PARM1);
col = PRVM_G_VECTOR(OFS_PARM2);
- Matrix4x4_CreateFromQuakeEntity(&matrix, pos[0], pos[1], pos[2], 0, 0, 0, PRVM_G_FLOAT(OFS_PARM1));
- R_RTLight_Update(&r_refdef.scene.lights[r_refdef.scene.numlights++], false, &matrix, col, -1, NULL, true, 1, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+ if (prog->argc >= 4)
+ {
+ style = (int)PRVM_G_FLOAT(OFS_PARM3);
+ if (style >= MAX_LIGHTSTYLES)
+ {
+ Con_DPrintf("VM_CL_R_AddDynamicLight: out of bounds lightstyle index %i\n", style);
+ style = -1;
+ }
+ }
+ if (prog->argc >= 5)
+ cubemapname = PRVM_G_STRING(OFS_PARM4);
+ if (prog->argc >= 6)
+ pflags = (int)PRVM_G_FLOAT(OFS_PARM5);
+ coronaintensity = (pflags & PFLAGS_CORONA) != 0;
+ castshadow = (pflags & PFLAGS_NOSHADOW) == 0;
+
+ VectorScale(prog->globals.client->v_forward, radius, forward);
+ VectorScale(prog->globals.client->v_right, -radius, left);
+ VectorScale(prog->globals.client->v_up, radius, up);
+ Matrix4x4_FromVectors(&matrix, forward, left, up, org);
+
+ R_RTLight_Update(&r_refdef.scene.lights[r_refdef.scene.numlights++], false, &matrix, col, style, cubemapname, castshadow, coronaintensity, coronasizescale, ambientscale, diffusescale, specularscale, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
}
//============================================================================
VM_SAFEPARMCOUNT(1, VM_CL_unproject);
f = PRVM_G_VECTOR(OFS_PARM0);
- VectorSet(temp, f[2], f[0] * f[2] * -r_refdef.view.frustum_x * 2.0 / r_refdef.view.width, f[1] * f[2] * -r_refdef.view.frustum_y * 2.0 / r_refdef.view.height);
+ if(v_flipped.integer)
+ f[0] = r_refdef.view.x + r_refdef.view.width - f[0];
+ VectorSet(temp, f[2], (-1.0 + 2.0 * (f[0] - r_refdef.view.x)) / r_refdef.view.width * f[2] * -r_refdef.view.frustum_x, (-1.0 + 2.0 * (f[1] - r_refdef.view.y)) / r_refdef.view.height * f[2] * -r_refdef.view.frustum_y);
Matrix4x4_Transform(&r_refdef.view.matrix, temp, PRVM_G_VECTOR(OFS_RETURN));
}
f = PRVM_G_VECTOR(OFS_PARM0);
Matrix4x4_Invert_Simple(&m, &r_refdef.view.matrix);
Matrix4x4_Transform(&m, f, v);
- VectorSet(PRVM_G_VECTOR(OFS_RETURN), v[1]/v[0]/-r_refdef.view.frustum_x*0.5*r_refdef.view.width, v[2]/v[0]/-r_refdef.view.frustum_y*r_refdef.view.height*0.5, v[0]);
+ if(v_flipped.integer)
+ v[1] = -v[1];
+ VectorSet(PRVM_G_VECTOR(OFS_RETURN), r_refdef.view.x + r_refdef.view.width*0.5*(1.0+v[1]/v[0]/-r_refdef.view.frustum_x), r_refdef.view.y + r_refdef.view.height*0.5*(1.0+v[2]/v[0]/-r_refdef.view.frustum_y), v[0]);
}
//#330 float(float stnum) getstatf (EXT_CSQC)
//#334 string(float mdlindex) modelnameforindex (EXT_CSQC)
static void VM_CL_modelnameforindex (void)
{
- model_t *model;
+ dp_model_t *model;
VM_SAFEPARMCOUNT(1, VM_CL_modelnameforindex);
start = PRVM_G_VECTOR(OFS_PARM2);
end = PRVM_G_VECTOR(OFS_PARM3);
+ if (i < 0)
+ return;
CL_ParticleEffect(i, VectorDistance(start, end), start, end, t->fields.client->velocity, t->fields.client->velocity, NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0);
}
f = PRVM_G_VECTOR(OFS_PARM1);
v = PRVM_G_VECTOR(OFS_PARM2);
n = (int)PRVM_G_FLOAT(OFS_PARM3);
+ if (i < 0)
+ return;
CL_ParticleEffect(i, n, f, f, v, v, NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0);
}
cl_ignoremousemoves = 2;
}
+//#344 vector() getmousepos (EXT_CSQC)
+static void VM_CL_getmousepos(void)
+{
+ VM_SAFEPARMCOUNT(0,VM_CL_getmousepos);
+
+ if (key_consoleactive || key_dest != key_game)
+ VectorSet(PRVM_G_VECTOR(OFS_RETURN), 0, 0, 0);
+ else if (cl.csqc_wantsmousemove)
+ VectorSet(PRVM_G_VECTOR(OFS_RETURN), in_windowmouse_x * vid_conwidth.integer / vid.width, in_windowmouse_y * vid_conheight.integer / vid.height, 0);
+ else
+ VectorSet(PRVM_G_VECTOR(OFS_RETURN), in_mouse_x * vid_conwidth.integer / vid.width, in_mouse_y * vid_conheight.integer / vid.height, 0);
+}
+
//#345 float(float framenum) getinputstate (EXT_CSQC)
static void VM_CL_getinputstate (void)
{
int i, frame;
VM_SAFEPARMCOUNT(1, VM_CL_getinputstate);
frame = (int)PRVM_G_FLOAT(OFS_PARM0);
- for (i = 0;i < cl.movement_numqueue;i++)
- if (cl.movement_queue[i].sequence == frame)
+ for (i = 0;i < CL_MAX_USERCMDS;i++)
+ {
+ if (cl.movecmd[i].sequence == frame)
{
- VectorCopy(cl.movement_queue[i].viewangles, prog->globals.client->input_angles);
- //prog->globals.client->input_buttons = cl.movement_queue[i].//FIXME
- VectorCopy(cl.movement_queue[i].move, prog->globals.client->input_movevalues);
- prog->globals.client->input_timelength = cl.movement_queue[i].frametime;
- if(cl.movement_queue[i].crouch)
+ VectorCopy(cl.movecmd[i].viewangles, prog->globals.client->input_angles);
+ prog->globals.client->input_buttons = cl.movecmd[i].buttons; // FIXME: this should not be directly exposed to csqc (translation layer needed?)
+ prog->globals.client->input_movevalues[0] = cl.movecmd[i].forwardmove;
+ prog->globals.client->input_movevalues[1] = cl.movecmd[i].sidemove;
+ prog->globals.client->input_movevalues[2] = cl.movecmd[i].upmove;
+ prog->globals.client->input_timelength = cl.movecmd[i].frametime;
+ if(cl.movecmd[i].crouch)
{
VectorCopy(cl.playercrouchmins, prog->globals.client->pmove_mins);
VectorCopy(cl.playercrouchmaxs, prog->globals.client->pmove_maxs);
VectorCopy(cl.playerstandmaxs, prog->globals.client->pmove_maxs);
}
}
+ }
}
//#346 void(float sens) setsensitivityscaler (EXT_CSQC)
strlcpy(t, cl.scores[i].name, sizeof(t));
else
if(!strcasecmp(c, "frags"))
- sprintf(t, "%i", cl.scores[i].frags);
+ dpsnprintf(t, sizeof(t), "%i", cl.scores[i].frags);
else
if(!strcasecmp(c, "ping"))
- sprintf(t, "%i", cl.scores[i].qw_ping);
+ dpsnprintf(t, sizeof(t), "%i", cl.scores[i].qw_ping);
else
if(!strcasecmp(c, "pl"))
- sprintf(t, "%i", cl.scores[i].qw_packetloss);
+ dpsnprintf(t, sizeof(t), "%i", cl.scores[i].qw_packetloss);
else
if(!strcasecmp(c, "entertime"))
- sprintf(t, "%f", cl.scores[i].qw_entertime);
+ dpsnprintf(t, sizeof(t), "%f", cl.scores[i].qw_entertime);
else
if(!strcasecmp(c, "colors"))
- sprintf(t, "%i", cl.scores[i].colors);
+ dpsnprintf(t, sizeof(t), "%i", cl.scores[i].colors);
else
if(!strcasecmp(c, "topcolor"))
- sprintf(t, "%i", cl.scores[i].colors & 0xf0);
+ dpsnprintf(t, sizeof(t), "%i", cl.scores[i].colors & 0xf0);
else
if(!strcasecmp(c, "bottomcolor"))
- sprintf(t, "%i", (cl.scores[i].colors &15)<<4);
+ dpsnprintf(t, sizeof(t), "%i", (cl.scores[i].colors &15)<<4);
else
if(!strcasecmp(c, "viewentity"))
- sprintf(t, "%i", i+1);
+ dpsnprintf(t, sizeof(t), "%i", i+1);
if(!t[0])
return;
PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t);
PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadFloat();
}
+//#501 string() readpicture (DP_CSQC_READWRITEPICTURE)
+extern cvar_t cl_readpicture_force;
+static void VM_CL_ReadPicture (void)
+{
+ const char *name;
+ unsigned char *data;
+ unsigned char *buf;
+ int size;
+ int i;
+ cachepic_t *pic;
+
+ VM_SAFEPARMCOUNT(0, VM_CL_ReadPicture);
+
+ name = MSG_ReadString();
+ size = MSG_ReadShort();
+
+ // check if a texture of that name exists
+ // if yes, it is used and the data is discarded
+ // if not, the (low quality) data is used to build a new texture, whose name will get returned
+
+ pic = Draw_CachePic_Flags (name, CACHEPICFLAG_NOTPERSISTENT);
+
+ if(size)
+ {
+ if(pic->tex == r_texture_notexture)
+ pic->tex = NULL; // don't overwrite the notexture by Draw_NewPic
+ if(pic->tex && !cl_readpicture_force.integer)
+ {
+ // texture found and loaded
+ // skip over the jpeg as we don't need it
+ for(i = 0; i < size; ++i)
+ MSG_ReadByte();
+ }
+ else
+ {
+ // texture not found
+ // use the attached jpeg as texture
+ buf = Mem_Alloc(tempmempool, size);
+ MSG_ReadBytes(size, buf);
+ data = JPEG_LoadImage_BGRA(buf, size);
+ Mem_Free(buf);
+ Draw_NewPic(name, image_width, image_height, false, data);
+ Mem_Free(data);
+ }
+ }
+
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(name);
+}
+
//////////////////////////////////////////////////////////
static void VM_CL_makestatic (void)
//====================================================================
//DP_QC_GETSURFACE
-extern void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out);
+extern void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out);
-static msurface_t *cl_getsurface(model_t *model, int surfacenum)
+static msurface_t *cl_getsurface(dp_model_t *model, int surfacenum)
{
if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
return NULL;
// #434 float(entity e, float s) getsurfacenumpoints
static void VM_CL_getsurfacenumpoints(void)
{
- model_t *model;
+ dp_model_t *model;
msurface_t *surface;
VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenumpoints);
// return 0 if no such surface
static void VM_CL_getsurfacepoint(void)
{
prvm_edict_t *ed;
- model_t *model;
+ dp_model_t *model;
msurface_t *surface;
int pointnum;
VM_SAFEPARMCOUNT(3, VM_CL_getsurfacenumpoints);
static void VM_CL_getsurfacepointattribute(void)
{
prvm_edict_t *ed;
- model_t *model;
+ dp_model_t *model;
msurface_t *surface;
int pointnum;
int attributetype;
switch( attributetype ) {
// float SPA_POSITION = 0;
case 0:
- VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
+ VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN));
break;
// float SPA_S_AXIS = 1;
case 1:
// #436 vector(entity e, float s) getsurfacenormal
static void VM_CL_getsurfacenormal(void)
{
- model_t *model;
+ dp_model_t *model;
msurface_t *surface;
vec3_t normal;
VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenormal);
// #437 string(entity e, float s) getsurfacetexture
static void VM_CL_getsurfacetexture(void)
{
- model_t *model;
+ dp_model_t *model;
msurface_t *surface;
VM_SAFEPARMCOUNT(2, VM_CL_getsurfacetexture);
PRVM_G_INT(OFS_RETURN) = OFS_NULL;
vec3_t clipped, p;
vec_t dist, bestdist;
prvm_edict_t *ed;
- model_t *model = NULL;
+ dp_model_t *model = NULL;
msurface_t *surface;
vec_t *point;
VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenearpoint);
static void VM_CL_getsurfaceclippedpoint(void)
{
prvm_edict_t *ed;
- model_t *model;
+ dp_model_t *model;
msurface_t *surface;
vec3_t p, out;
VM_SAFEPARMCOUNT(3, VM_CL_getsurfaceclippedpoint);
const char *tagname;
prvm_eval_t *v;
int modelindex;
- model_t *model;
+ dp_model_t *model;
VM_SAFEPARMCOUNT(3, VM_CL_setattachment);
e = PRVM_G_EDICT(OFS_PARM0);
int CL_GetTagIndex (prvm_edict_t *e, const char *tagname)
{
- model_t *model = CL_GetModelFromEdict(e);
+ dp_model_t *model = CL_GetModelFromEdict(e);
if (model)
return Mod_Alias_GetTagIndexForName(model, (int)e->fields.client->skin, tagname);
else
int reqframe, attachloop;
matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
prvm_edict_t *attachent;
- model_t *model;
+ dp_model_t *model;
float scale;
*out = identitymatrix; // warnings and errors return identical matrix
{
rtexture_t *texture;
int drawflag;
- int element3i[3];
+ unsigned short elements[3];
}vmpolygons_triangle_t;
typedef struct vmpolygons_s
{
mempool_t *pool;
qboolean initialized;
+ double progstarttime;
int max_vertices;
int num_vertices;
int max_triangles;
int num_triangles;
vmpolygons_triangle_t *data_triangles;
- int *data_sortedelement3i;
+ unsigned short *data_sortedelement3s;
qboolean begin_active;
rtexture_t *begin_texture;
// FIXME: make VM_CL_R_Polygon functions use Debug_Polygon functions?
vmpolygons_t vmpolygons[PRVM_MAXPROGS];
+//#304 void() renderscene (EXT_CSQC)
+// moved that here to reset the polygons,
+// resetting them earlier causes R_Mesh_Draw to be called with numvertices = 0
+// --blub
+void VM_CL_R_RenderScene (void)
+{
+ vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+ VM_SAFEPARMCOUNT(0, VM_CL_R_RenderScene);
+ // we need to update any RENDER_VIEWMODEL entities at this point because
+ // csqc supplies its own view matrix
+ CL_UpdateViewEntities();
+ // now draw stuff!
+ R_RenderView();
+
+ polys->num_vertices = polys->num_triangles = 0;
+ polys->progstarttime = prog->starttime;
+}
+
static void VM_ResizePolygons(vmpolygons_t *polys)
{
float *oldvertex3f = polys->data_vertex3f;
float *oldcolor4f = polys->data_color4f;
float *oldtexcoord2f = polys->data_texcoord2f;
vmpolygons_triangle_t *oldtriangles = polys->data_triangles;
- int *oldsortedelement3i = polys->data_sortedelement3i;
- polys->max_vertices = polys->max_triangles*3;
+ unsigned short *oldsortedelement3s = polys->data_sortedelement3s;
+ polys->max_vertices = min(polys->max_triangles*3, 65536);
polys->data_vertex3f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[3]));
polys->data_color4f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[4]));
polys->data_texcoord2f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[2]));
polys->data_triangles = (vmpolygons_triangle_t *)Mem_Alloc(polys->pool, polys->max_triangles*sizeof(vmpolygons_triangle_t));
- polys->data_sortedelement3i = (int *)Mem_Alloc(polys->pool, polys->max_triangles*sizeof(int[3]));
+ polys->data_sortedelement3s = (unsigned short *)Mem_Alloc(polys->pool, polys->max_triangles*sizeof(unsigned short[3]));
if (polys->num_vertices)
{
memcpy(polys->data_vertex3f, oldvertex3f, polys->num_vertices*sizeof(float[3]));
if (polys->num_triangles)
{
memcpy(polys->data_triangles, oldtriangles, polys->num_triangles*sizeof(vmpolygons_triangle_t));
- memcpy(polys->data_sortedelement3i, oldsortedelement3i, polys->num_triangles*sizeof(int[3]));
+ memcpy(polys->data_sortedelement3s, oldsortedelement3s, polys->num_triangles*sizeof(unsigned short[3]));
}
if (oldvertex3f)
Mem_Free(oldvertex3f);
Mem_Free(oldtexcoord2f);
if (oldtriangles)
Mem_Free(oldtriangles);
- if (oldsortedelement3i)
- Mem_Free(oldsortedelement3i);
+ if (oldsortedelement3s)
+ Mem_Free(oldsortedelement3s);
}
static void VM_InitPolygons (vmpolygons_t* polys)
{
int surfacelistindex;
vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+ if(polys->progstarttime != prog->starttime) // from other progs? won't draw these (this can cause crashes!)
+ return;
+ R_Mesh_ResetTextureState();
R_Mesh_Matrix(&identitymatrix);
GL_CullFace(GL_NONE);
R_Mesh_VertexPointer(polys->data_vertex3f, 0, 0);
R_Mesh_ColorPointer(polys->data_color4f, 0, 0);
R_Mesh_TexCoordPointer(0, 2, polys->data_texcoord2f, 0, 0);
R_SetupGenericShader(true);
+
for (surfacelistindex = 0;surfacelistindex < numsurfaces;)
{
int numtriangles = 0;
rtexture_t *tex = polys->data_triangles[surfacelist[surfacelistindex]].texture;
int drawflag = polys->data_triangles[surfacelist[surfacelistindex]].drawflag;
+ // this can't call _DrawQ_ProcessDrawFlag, but should be in sync with it
+ // FIXME factor this out
if(drawflag == DRAWFLAG_ADDITIVE)
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
else if(drawflag == DRAWFLAG_MODULATE)
GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
else if(drawflag == DRAWFLAG_2XMODULATE)
GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
+ else if(drawflag == DRAWFLAG_SCREEN)
+ GL_BlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ONE);
else
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
R_Mesh_TexBind(0, R_GetTexture(tex));
{
if (polys->data_triangles[surfacelist[surfacelistindex]].texture != tex || polys->data_triangles[surfacelist[surfacelistindex]].drawflag != drawflag)
break;
- VectorCopy(polys->data_triangles[surfacelist[surfacelistindex]].element3i, polys->data_sortedelement3i + 3*numtriangles);
+ VectorCopy(polys->data_triangles[surfacelist[surfacelistindex]].elements, polys->data_sortedelement3s + 3*numtriangles);
numtriangles++;
}
- R_Mesh_Draw(0, polys->num_vertices, numtriangles, polys->data_sortedelement3i, 0, 0);
+ R_Mesh_Draw(0, polys->num_vertices, 0, numtriangles, NULL, polys->data_sortedelement3s, 0, 0);
}
}
mesh.texture = polys->begin_texture;
mesh.num_vertices = polys->begin_vertices;
mesh.num_triangles = polys->begin_vertices-2;
- mesh.data_element3i = polygonelements;
+ mesh.data_element3s = polygonelements;
mesh.data_vertex3f = polys->begin_vertex[0];
mesh.data_color4f = polys->begin_color[0];
mesh.data_texcoord2f = polys->begin_texcoord[0];
polys->max_triangles *= 2;
VM_ResizePolygons(polys);
}
- memcpy(polys->data_vertex3f + polys->num_vertices * 3, polys->begin_vertex[0], polys->num_vertices * sizeof(float[3]));
- memcpy(polys->data_color4f + polys->num_vertices * 4, polys->begin_color[0], polys->num_vertices * sizeof(float[4]));
- memcpy(polys->data_texcoord2f + polys->num_vertices * 2, polys->begin_texcoord[0], polys->num_vertices * sizeof(float[2]));
- for (i = 0;i < polys->begin_vertices-2;i++)
+ if (polys->num_vertices + polys->begin_vertices <= polys->max_vertices)
{
- polys->data_triangles[polys->num_triangles].texture = polys->begin_texture;
- polys->data_triangles[polys->num_triangles].drawflag = polys->begin_drawflag;
- polys->data_triangles[polys->num_triangles].element3i[0] = polys->num_vertices;
- polys->data_triangles[polys->num_triangles].element3i[1] = polys->num_vertices + i+1;
- polys->data_triangles[polys->num_triangles].element3i[2] = polys->num_vertices + i+2;
- polys->num_triangles++;
+ // needle in a haystack!
+ // polys->num_vertices was used for copying where we actually want to copy begin_vertices
+ // that also caused it to not render the first polygon that is added
+ // --blub
+ memcpy(polys->data_vertex3f + polys->num_vertices * 3, polys->begin_vertex[0], polys->begin_vertices * sizeof(float[3]));
+ memcpy(polys->data_color4f + polys->num_vertices * 4, polys->begin_color[0], polys->begin_vertices * sizeof(float[4]));
+ memcpy(polys->data_texcoord2f + polys->num_vertices * 2, polys->begin_texcoord[0], polys->begin_vertices * sizeof(float[2]));
+ for (i = 0;i < polys->begin_vertices-2;i++)
+ {
+ polys->data_triangles[polys->num_triangles].texture = polys->begin_texture;
+ polys->data_triangles[polys->num_triangles].drawflag = polys->begin_drawflag;
+ polys->data_triangles[polys->num_triangles].elements[0] = polys->num_vertices;
+ polys->data_triangles[polys->num_triangles].elements[1] = polys->num_vertices + i+1;
+ polys->data_triangles[polys->num_triangles].elements[2] = polys->num_vertices + i+2;
+ polys->num_triangles++;
+ }
+ polys->num_vertices += polys->begin_vertices;
}
- polys->num_vertices += polys->begin_vertices;
}
polys->begin_active = false;
}
for (i = 0;i < polys->num_triangles;i++)
{
- VectorMAMAM(1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].element3i[0], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].element3i[1], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].element3i[2], center);
+ VectorMAMAM(1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[0], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[1], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[2], center);
R_MeshQueue_AddTransparent(center, VM_DrawPolygonCallback, NULL, i, NULL);
}
- polys->num_triangles = 0;
- polys->num_vertices = 0;
+ /*polys->num_triangles = 0; // now done after rendering the scene,
+ polys->num_vertices = 0; // otherwise it's not rendered at all and prints an error message --blub */
}
//void(string texturename, float flag) R_BeginPolygon
void VM_CL_R_PolygonBegin (void)
{
const char *picname;
+ skinframe_t *sf;
vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+ int tf;
+
+ // TODO instead of using skinframes here (which provides the benefit of
+ // better management of flags, and is more suited for 3D rendering), what
+ // about supporting Q3 shaders?
VM_SAFEPARMCOUNT(2, VM_CL_R_PolygonBegin);
if (!polys->initialized)
VM_InitPolygons(polys);
+ if(polys->progstarttime != prog->starttime)
+ {
+ // from another progs? then reset the polys first (fixes crashes on map change, because that can make skinframe textures invalid)
+ polys->num_vertices = polys->num_triangles = 0;
+ polys->progstarttime = prog->starttime;
+ }
if (polys->begin_active)
{
VM_Warning("VM_CL_R_PolygonBegin: called twice without VM_CL_R_PolygonBegin after first\n");
return;
}
picname = PRVM_G_STRING(OFS_PARM0);
- polys->begin_texture = picname[0] ? Draw_CachePic (picname)->tex : r_texture_white;
- polys->begin_drawflag = (int)PRVM_G_FLOAT(OFS_PARM1);
+
+ sf = NULL;
+ if(*picname)
+ {
+ tf = TEXF_ALPHA;
+ if((int)PRVM_G_FLOAT(OFS_PARM1) & DRAWFLAG_MIPMAP)
+ tf |= TEXF_MIPMAP;
+
+ do
+ {
+ sf = R_SkinFrame_FindNextByName(sf, picname);
+ }
+ while(sf && sf->textureflags != tf);
+
+ if(!sf || !sf->base)
+ sf = R_SkinFrame_LoadExternal(picname, tf, true);
+
+ if(sf)
+ R_SkinFrame_MarkUsed(sf);
+ }
+
+ polys->begin_texture = (sf && sf->base) ? sf->base : r_texture_white;
+ polys->begin_drawflag = (int)PRVM_G_FLOAT(OFS_PARM1) & DRAWFLAG_MASK;
polys->begin_vertices = 0;
polys->begin_active = true;
}
VM_drawsetcliparea, // #324 void(float x, float y, float width, float height) drawsetcliparea
VM_drawresetcliparea, // #325 void(void) drawresetcliparea
VM_drawcolorcodedstring, // #326 float drawcolorcodedstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) (EXT_CSQC)
-NULL, // #327 // FIXME add stringwidth() here?
-NULL, // #328 // FIXME add drawsubpic() here?
+VM_stringwidth, // #327 // FIXME is this okay?
+VM_drawsubpic, // #328 // FIXME is this okay?
NULL, // #329
VM_CL_getstatf, // #330 float(float stnum) getstatf (EXT_CSQC)
VM_CL_getstati, // #331 float(float stnum) getstati (EXT_CSQC)
VM_stringtokeynum, // #341 float(string keyname) stringtokeynum (EXT_CSQC)
VM_CL_getkeybind, // #342 string(float keynum) getkeybind (EXT_CSQC)
VM_CL_setcursormode, // #343 void(float usecursor) setcursormode (EXT_CSQC)
-VM_getmousepos, // #344 vector() getmousepos (EXT_CSQC)
+VM_CL_getmousepos, // #344 vector() getmousepos (EXT_CSQC)
VM_CL_getinputstate, // #345 float(float framenum) getinputstate (EXT_CSQC)
VM_CL_setsensitivityscale, // #346 void(float sens) setsensitivityscale (EXT_CSQC)
VM_CL_runplayerphysics, // #347 void() runstandardplayerphysics (EXT_CSQC)
VM_gecko_get_texture_extent, // #493 vector gecko_get_texture_extent( string name )
VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE)
-NULL, // #496
-NULL, // #497
-NULL, // #498
-NULL, // #499
+VM_numentityfields, // #496 float() numentityfields = #496; (QP_QC_ENTITYDATA)
+VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA)
+VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA)
+VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA)
+VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA)
+VM_CL_ReadPicture, // #501 string() ReadPicture = #501;
+NULL, // #502
+VM_whichpack, // #503 string(string) whichpack = #503;
+NULL, // #504
+NULL, // #505
+NULL, // #506
+NULL, // #507
+NULL, // #508
+NULL, // #509
+VM_uri_escape, // #510 string(string in) uri_escape = #510;
+VM_uri_unescape, // #511 string(string in) uri_unescape = #511;
+VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT)
+VM_uri_get, // #513 float(string uril, float id) uri_get = #512; (DP_QC_URI_GET)
+VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE)
+VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE)
+VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE)
+NULL, // #517
+NULL, // #518
+NULL, // #519
+VM_keynumtostring, // #520 string keynumtostring(float keynum)
+VM_findkeysforcommand, // #521 string findkeysforcommand(string command)
};
const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);