labeling edicts
Moderator: InsideQC Admins
8 posts
• Page 1 of 1
labeling edicts
I saw t00l_showbbox in enginex, so I sought out to duplicate the feature.
I already have the boxes working but some of the edict names are not showing up....
mostly for triggers.
this is the loop...
and heres where i populate the variable
any suggestions? Do I need to run thru another link list for triggers??
Thanks
I already have the boxes working but some of the edict names are not showing up....
mostly for triggers.
this is the loop...
- Code: Select all
for (i = 0, ed = NEXT_EDICT(sv.edicts) ; i < sv.num_edicts ; i++, ed = NEXT_EDICT(ed))
{
and heres where i populate the variable
- Code: Select all
if (!strcmp((pr_strings + ed->v.classname),"player"))
strlcpy(id->text, (pr_strings + ed->v.netname), 64);
else
{
name = (pr_strings + ed->v.classname);
strlcpy(id->text, name, 64);
}
any suggestions? Do I need to run thru another link list for triggers??
Thanks
- r00k
- Posts: 1110
- Joined: Sat Nov 13, 2004 10:39 pm
Re: labeling edicts
r00k wrote:I saw t00l_showbbox in enginex, so I sought out to duplicate the feature.
I already have the boxes working but some of the edict names are not showing up....
Just steal it in the entirety
As you see from my screen shots, Engine X has no problem showing the trigger entities (so I don't know why you'd be having this issue ???).
... Although maybe since I modified the progs interpreter stuff inspired from the Quore engine you are afraid of my macros? But those are harmless and rather simple really. Just diff the pr_whatever.c files and what I did with the macros is rather crystal clear.
#define PR_GETSTRING(x) pr_strings + x
#define PR_SETSTRING(x) x - pr_strings
#define PR_SETTMPSTRING(x) x - pr_strings

The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
Re: labeling edicts
Ya but your source wasnt up to date. it had the tools_showbbox cvar and nothing codewise. 
Basically im using qglProject from FTE and the autoid code from ezQ as a reference.
So far this is what i have

Basically im using qglProject from FTE and the autoid code from ezQ as a reference.
So far this is what i have

- r00k
- Posts: 1110
- Joined: Sat Nov 13, 2004 10:39 pm
Re: labeling edicts
r00k wrote:Ya but your source wasnt up to date. it had the tools_showbbox cvar and nothing codewise.
At the moment I'm not understanding how that could have happened, but this does appear to be the case.
And certainly not intentional.
[I find this a bit disturbing because I always make the assumption that uploading my source keeps me safe from possible file loss and I often treat uploaded source bases as perfectly deletable on my hard drive, mentally.]
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
Re: labeling edicts
I've re-zipped the source off my Windows desktop:
http://quakeone.com/proquake/interims/E ... in_src.rar
Code to look for: File = insertions_3d.c
As you can see in this code, I didn't draw the captions in 2D.
I drew them in 3D, hahaha 
The 3D drawing of text works like this (really it is exactly the same as drawing a sprite) ...
And as you can see, I used your anti-wallhack code to test for entity visibility to decide whether or not to display the text.
Obviously drawing the text in the 3D phase makes more sense since:
1. I'm drawing boxes around stuff anyways. That has to be in the 3D rendering phase.
2. The 2D phase would introduce irritating factors not drawing over the HUD, how to scale the text for screen resolution and other stuff I didn't want to do.
3. Why do unnecessary projection calculations in the 2D phase ... I mean that's just faking 3D anyway. So do it in the 3D phase. But at the end and ignore depth testing.
http://quakeone.com/proquake/interims/E ... in_src.rar
Code to look for: File = insertions_3d.c
- Code: Select all
// insertions_3d.c -- Adds stuff to 3D world
#include "quakedef.h"
//qbool SV_InvisibleToClient(edict_t *viewer, edict_t *seen);
//void R_EmitBox (const vec_rgba_t myColor, const vec3_t centerpoint, const vec3_t xyz_mins, const vec3_t xyz_maxs, const qbool bTopMost, const qbool bLines, const float Expandsize);
qbool SV_InvisibleToClient(edict_t *viewer, edict_t *seen);
void ShowBBoxes_Draw (void)
{
extern edict_t *sv_player;
edict_t *ed;
int i;
entity_t *clent;
// Cycle through the server entities
for (i=1, ed=NEXT_EDICT(sv.edicts) ; i<sv.num_edicts ; i++, ed=NEXT_EDICT(ed))
{
char *my_classname = PR_GETSTRING(ed->v.classname);
vec_rgba_t BoxColor;
if (ed->free)
continue; // Free edict, just skip
clent = NULL;
if (i<cl.num_entities) // Baker: Not all server ents get communicated to client.
clent = cl_entities + i;
if (ed == sv_player && !chase_active.integer)
continue; // Don't draw in this scenario
// Obtain Quake specific super-special color
do
{
int special_entity = 0;
if (COM_StringMatchCaseless (my_classname, "info_player_start")) special_entity = 1;
else if (COM_StringMatchCaseless (my_classname, "info_player_coop")) special_entity = 2;
else if (COM_StringMatchCaseless (my_classname, "info_player_deathmatch")) special_entity = 3;
switch (special_entity)
{
case 1: VectorSetColor4f (BoxColor, 1, 0, 0, 0.40); break;
case 2: VectorSetColor4f (BoxColor, 1, 1, 0, 0.30); break;
case 3: VectorSetColor4f (BoxColor, 1, 0, 0, 0.40); break;
}
// If we already determined a color, exit stage left ...
if (special_entity)
continue;
// normal color selection
switch ((int)ed->v.solid)
{
case SOLID_NOT: VectorSetColor4f (BoxColor, 1, 1, 1, 0.05);break;
case SOLID_TRIGGER: VectorSetColor4f (BoxColor, 1, 0, 1, 0.10);break;
case SOLID_BBOX: VectorSetColor4f (BoxColor, 0, 1, 0, 0.10);break;
case SOLID_SLIDEBOX: VectorSetColor4f (BoxColor, 1, 0, 0, 0.10);break;
case SOLID_BSP: VectorSetColor4f (BoxColor, 0, 0, 1, 0.05);break;
default: VectorSetColor4f (BoxColor, 0, 0, 0, 0.50);break;
}
} while (0);
// Render box phase
do
{
qbool isPointEntity = VectorCompare(ed->v.mins, ed->v.maxs); // point entities have 0 size
if (isPointEntity)
{
qbool bRenderTopMost = false;
qbool bRenderLines = false;
float size_adjust = 4.0f; // Give it a little bit of size
R_EmitBox (BoxColor, ed->v.origin, NULL, NULL, bRenderTopMost, bRenderLines, size_adjust);
}
else
{
qbool bRenderTopMost = false;
qbool bRenderLines = false;
float size_adjust = -0.10f; // Pull size in just a little
R_EmitBox (BoxColor, ed->v.origin, ed->v.mins, ed->v.maxs, bRenderTopMost, bRenderLines, size_adjust);
}
} while (0);
// Render Caption phase
do
{
extern vec3_t lastbox_mins, lastbox_maxs; // Last box rendering result
vec3_t caption_location;
if (SV_InvisibleToClient (sv_player, ed))
continue; //don't draw if entity cannot be seen
// Averaging the vectors gives the center
LerpVector (lastbox_mins, lastbox_maxs, 0.5, caption_location);
// Except we want the caption to be at the top
caption_location[2] = lastbox_maxs[2];
// Add a couple of height units to make it overhead
caption_location[2] = caption_location[2] + 20;
// Depending on cvar value, have caption show different things
switch (tool_showbboxes.integer)
{
default:
case 1: R_EmitCaption (caption_location, my_classname); break;
case 2: R_EmitCaption (caption_location, ed->v.model ? PR_GETSTRING(ed->v.model) : "No model"); break;
case 3: R_EmitCaption (caption_location, va("ent #%i", i)); break;
case 4: R_EmitCaption (caption_location, va("modelindex %i", (int)ed->v.modelindex)); break;
// Baker: First ... this isn't how you do it with sprites.
case 5: // Client mirror
R_EmitCaption (caption_location,
va("\bServer model:\b\n"
"'%s'\n"
"\bClient model:\b\n"
"'%s'", ed->v.model ? PR_GETSTRING(ed->v.model) : "No model", clent ? clent->model->name : "No entity"));
break;
}
} while (0);
// End of this entity
} // For Loop closing brace
// Now do static entities
for (i=0; i < cl.num_statics; i++)
{
vec_rgba_t BoxColor;
clent = &cl_static_entities[i];
if (!(clent->visframe == r_framecount))
continue; // Not visible this frame
VectorSetColor4f (BoxColor, 1, 0.5, 0, 0.40);
// Render box phase
do
{
qbool isPointEntity = VectorCompare(clent->model->mins, clent->model->maxs); // point entities have 0 size
if (isPointEntity)
{
qbool bRenderTopMost = false;
qbool bRenderLines = false;
float size_adjust = 4.0f; // Give it a little bit of size
R_EmitBox (BoxColor, clent->currentorigin, NULL, NULL, bRenderTopMost, bRenderLines, size_adjust);
}
else
{
qbool bRenderTopMost = false;
qbool bRenderLines = false;
float size_adjust = -0.10f; // Pull size in just a little
R_EmitBox (BoxColor, clent->currentorigin, clent->model->mins, clent->model->maxs, bRenderTopMost, bRenderLines, size_adjust);
}
} while (0);
// Render Caption phase
do
{
extern vec3_t lastbox_mins, lastbox_maxs; // Last box rendering result
vec3_t caption_location;
// Averaging the vectors gives the center
LerpVector (lastbox_mins, lastbox_maxs, 0.5, caption_location);
// Except we want the caption to be at the top
caption_location[2] = lastbox_maxs[2];
// Add a couple of height units to make it overhead
caption_location[2] = caption_location[2] + 20;
// Depending on cvar value, have caption show different things
R_EmitCaption (caption_location, va("\bStatic ent\b %i '%s'\n", clent- cl_static_entities, clent->model->name));
} while (0);
// End of this entity
} // For Loop closing brace
}
As you can see in this code, I didn't draw the captions in 2D.
The 3D drawing of text works like this (really it is exactly the same as drawing a sprite) ...
- Code: Select all
void R_EmitCaption (const vec3_t location, const char *caption)
{
const int string_length = strlen(caption);
const float charwidth = 8;
const float charheight = 8;
vec3_t point;
vec3_t right, up;
int string_columns, string_rows;
float string_width, string_height; // pixels
fRect_t captionbox;
int i, x, y;
qbool bronze = false;
// Step 1: Detemine Rows and columns
Text_Get_Columns_And_Rows (caption, &string_columns, &string_rows);
string_width = (float)string_columns * charwidth;
string_height = (float)string_rows * charheight;
// Step 2: Calculate bounds of rectangle
captionbox.top = -(float)string_height/2;
captionbox.bottom = (float)string_height/2;
captionbox.left = -(float)string_width /2;
captionbox.right = (float)string_width /2;
// Copy the view origin up and right angles
VectorCopy (vup, up);
VectorCopy (vright, right);
mglPushStates ();
GL_Bind (char_texture);
MeglDisable (GL_CULL_FACE);
MeglEnable (GL_ALPHA_TEST);
MeglDepthRange (0, 0.3); // Baker: The "hack the depth range" trick. Not sure why this works, but it does ...
mglFinishedStates ();
for (i=0, x = 0, y =0; i<string_length; i++)
{
// Deal with the string
if (caption[i] == '\n') { x = 0; y ++; continue; } // Reset the row, ignore and carry on
if (caption[i] == '\b')
{
bronze = !bronze;
continue;
} // Toggle the bronzing and carry on
x++; // New character to print
{
fRect_t charcoords;
float s, t;
int charcode = caption[i] | (bronze * 128); // "ascii" ish character code, but Quake character code
int charrow = charcode >> 4; // Fancy way of dividing by 16
int charcol = charcode & 15; // column = mod (16-1)
// Calculate s, t texture coords from character set image
// if (bronze) charcode |=128;
s = charcol * 0.0625f; // 0.0625 = 1/16th
t = charrow * 0.0625f;
// Calculate coords
// charcoords.top = captionbox.top;
// charcoords.bottom = captionbox.bottom;
// charcoords.left = captionbox.left + (x/string_length)*(captionbox.right - captionbox.left);
// charcoords.right = captionbox.left + ((x+1)/string_length)*(captionbox.right - captionbox.left);
// charcoords.top = captionbox.top + (y/(float)string_rows)*(captionbox.bottom - captionbox.top);
// charcoords.bottom = captionbox.top + ((y+1)/(float)string_rows)*(captionbox.bottom - captionbox.top);
charcoords.top = captionbox.top + ((string_rows - 1 - y)/(float)string_rows)*(captionbox.bottom - captionbox.top);
charcoords.bottom = captionbox.top + (((string_rows - 1 - y)+1)/(float)string_rows)*(captionbox.bottom - captionbox.top);
charcoords.left = captionbox.left + (x/(float)string_columns)*(captionbox.right - captionbox.left);
charcoords.right = captionbox.left + ((x+1)/(float)string_columns)*(captionbox.right - captionbox.left);
// Draw box
eglBegin (GL_QUADS);
// top left
eglTexCoord2f (s, t + 0.03125);
VectorMultiplyAdd (location, charcoords.top, up, point);
VectorMultiplyAdd (point, charcoords.left, right, point);
eglVertex3fv (point);
// top, right
eglTexCoord2f (s + 0.0625, t + 0.03125); // 0.03125 = 1/32th;
VectorMultiplyAdd (location, charcoords.top, up, point);
VectorMultiplyAdd (point, charcoords.right, right, point);
eglVertex3fv (point);
// bottom right
eglTexCoord2f (s + 0.0625, t);
VectorMultiplyAdd (location, charcoords.bottom, up, point);
VectorMultiplyAdd (point, charcoords.right, right, point);
eglVertex3fv (point);
// bottom, left
eglTexCoord2f (s, t);
VectorMultiplyAdd (location, charcoords.bottom, up, point);
VectorMultiplyAdd (point, charcoords.left, right, point);
eglVertex3fv (point);
eglEnd ();
}
}
MeglEnable (GL_CULL_FACE);
MeglDisable (GL_ALPHA_TEST);
MeglDepthRange (0, 1);
mglPopStates ();
}
And as you can see, I used your anti-wallhack code to test for entity visibility to decide whether or not to display the text.
Obviously drawing the text in the 3D phase makes more sense since:
1. I'm drawing boxes around stuff anyways. That has to be in the 3D rendering phase.
2. The 2D phase would introduce irritating factors not drawing over the HUD, how to scale the text for screen resolution and other stuff I didn't want to do.
3. Why do unnecessary projection calculations in the 2D phase ... I mean that's just faking 3D anyway. So do it in the 3D phase. But at the end and ignore depth testing.
Last edited by Baker on Tue Jun 05, 2012 12:18 pm, edited 1 time in total.
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
Re: labeling edicts
I've literally been sitting here all night...
weird thing is that if I do a Con_Printf("%s\n",(pr_strings + ed->v.classname)); it shows up
but after running that trace for culling, another Con_Printf("%s\n",(pr_strings + ed->v.classname)); gets lost...
My eyes are burning, I'll look at your code in a bit.
weird thing is that if I do a Con_Printf("%s\n",(pr_strings + ed->v.classname)); it shows up
but after running that trace for culling, another Con_Printf("%s\n",(pr_strings + ed->v.classname)); gets lost...
- Code: Select all
int qglProject (float objx, float objy, float objz, float *model, float *proj, int *view, float* winx, float* winy, float* winz)
{
float in[4], out[4], dist, scale;
int i;
vec3_t org;
org[0] = objx; org[1] = objy; org[2] = objz;
in[0] = objx; in[1] = objy; in[2] = objz; in[3] = 1.0;
if (R_CullSphere (org, 1))
return 0;
dist = VectorDistance(r_refdef.vieworg, org);
if (dist > r_farclip.value)
return 0;
for (i = 0; i < 4; i++)
out[i] = in[0] * model[0 * 4 + i] + in[1] * model[1 * 4 + i] + in[2] * model[2 * 4 + i] + in[3] * model[3 * 4 + i];
for (i = 0; i < 4; i++)
in[i] = out[0] * proj[0 * 4 + i] + out[1] * proj[1 * 4 + i] + out[2] * proj[2 * 4 + i] + out[3] * proj[3 * 4 + i];
if (!in[3])
return 0;
VectorScale(in, 1 / in[3], in);
*winx = view[0] + (1 + in[0]) * view[2] / 2;
*winy = view[1] + (1 + in[1]) * view[3] / 2;
scale = (1 / (dist / 128.0f));
if (scale < 0.1)
return 0;
scale = bound(0.333f, scale, 1);
*winz = scale;
return 1;
}
void SCR_DrawAutoID (void)
{
int i, x, y;
extern void Draw_String_Scaled (int x, int y, char *str, float scale);
float frametime = fabs(cl.time - cl.oldtime);
if (frametime < 0.01)
return;
if (!developer.value)
return;
for (i = 0; i < autoid_count; i++)
{
x = autoids[i].x * vid.width / glwidth;
y = (glheight - autoids[i].y) * vid.height / glheight;
if (autoids[i].classname)
Draw_String_Scaled (x - strlen(autoids[i].classname) * 4 * autoids[i].scale, y - 8 * autoids[i].scale, autoids[i].classname, autoids[i].scale);
if (autoids[i].origin)
Draw_String_Scaled (x - strlen(autoids[i].origin) * 4 * (autoids[i].scale * 0.8), y + 8 * (autoids[i].scale * 0.8), autoids[i].origin, (autoids[i].scale * 0.8));
if (autoids[i].modelname)
Draw_String_Scaled (x - strlen(autoids[i].modelname) * 4 * (autoids[i].scale * 0.8), y + 16 * (autoids[i].scale * 0.8), autoids[i].modelname, (autoids[i].scale * 0.8));
}
}
char *SCR_ED_Print (edict_t * ed, int i)
{
int *v;
ddef_t *d;
char *name;
extern char *PR_ValueString (etype_t type, eval_t *val);
d = &pr_fielddefs[i];
name = pr_strings + d->s_name;
v = (int *) ((char *) &ed->v + d->ofs * 4);
name = PR_ValueString (d->type, (eval_t *) v);
return va("%s",name);
}
void SCR_SetupTagEdicts (void)
{
int view[4];
float model[16], project[16], origin[3];
edict_t *ed;
int i;
autoid_player_t *id;
trace_t trace;
qboolean result;
char *name;
float frametime = fabs(cl.time - cl.oldtime);
extern cvar_t sv_cullentities;
entity_t *ent;
if (frametime < 0.01)
return;
if (autoids[0].classname)
memset(autoids,0,sizeof(autoids));// dont carry over
if (!developer.value)
return;
if (!cl.worldmodel)//Level hasnt loaded yet...
return;
if (cl.maxclients > 1 || !r_drawentities.value || !sv.active)//only in singleplayer mode...
return;
autoid_count = 0;
glGetFloatv(GL_MODELVIEW_MATRIX, model);
glGetFloatv(GL_PROJECTION_MATRIX, project);
glGetIntegerv(GL_VIEWPORT, (GLint *)view);
for (i = 0, ed = NEXT_EDICT(sv.edicts) ; i < sv.num_edicts ; i++, ed = NEXT_EDICT(ed))
{
Con_Printf("a:%s\n",(pr_strings + ed->v.classname));
if (ed->culled)
continue;
if (ed->free)
continue;
origin[0] = ed->v.origin[0];
origin[1] = ed->v.origin[1];
origin[2] = ed->v.origin[2];
id = &autoids[autoid_count];
Con_Printf("b:%s\n",(pr_strings + ed->v.classname));
if (sv_cullentities.value)
{
memset (&trace, 0, sizeof(trace));
trace.fraction = 1;
result = SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, r_refdef.vieworg, origin, &trace);
if (!result)//hit something
{
Con_Printf("c:culled!\n");
continue;
}
}
origin[0] = ed->v.origin[0];
origin[1] = ed->v.origin[1];
origin[2] = ed->v.origin[2];
if (qglProject(origin[0], origin[1], origin[2], model, project, view, &id->x, &id->y, &id->scale))
{
if (!strcmp((pr_strings + ed->v.classname),"player"))
{
strlcpy(id->classname, (pr_strings + ed->v.netname), 64);
name = SCR_ED_Print (ed, 13);
strlcpy(id->origin, name, 64);
name = SCR_ED_Print (ed, 38);
strlcpy(id->modelname, name, 64);
}
else
{
strlcpy(id->classname, (pr_strings + ed->v.classname), 64);
Con_Printf("c:%s\n",id->classname); //TESTING!
name = SCR_ED_Print (ed, 38);
strlcpy(id->modelname, name, 64);
name = SCR_ED_Print (ed, 13);
strlcpy(id->origin, name, 64);
}
autoid_count++;
}
}
for (i = 0, ent = cl_static_entities ; i < MAX_STATIC_ENTITIES ; i++, ent++)
{
if (ent->culled)
continue;
origin[0] = ed->v.origin[0];
origin[1] = ed->v.origin[1];
origin[2] = ed->v.origin[2];
if (sv_cullentities.value)
{
memset (&trace, 0, sizeof(trace));
trace.fraction = 1;
result = SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, r_refdef.vieworg, origin, &trace);
if (!result)//hit something
continue;
}
id = &autoids[autoid_count];
if (qglProject(origin[0], origin[1], origin[2], model, project, view, &id->x, &id->y, &id->scale))
{
name = "óôáôéã entity_t";
strlcpy(id->classname, "óôáôéã entity_t", 64);
name = va("%s",(ent->model->name));
strlcpy(id->modelname, name, 64);
name = va("%3.1f %3.1f %3.1f ",ent->origin[0],ent->origin[1],ent->origin[2]);
strlcpy(id->origin, name, 64);
autoid_count++;
}
}
}
My eyes are burning, I'll look at your code in a bit.
- r00k
- Posts: 1110
- Joined: Sat Nov 13, 2004 10:39 pm
Re: labeling edicts
r00k wrote:I've literally been sitting here all night...
I had some bang my head moments more than a few times (one stupid little mystery after another). But my code worked through all of those until none existed, and I commented it pretty well.
So read the comments in my code and note that every single line is doing something important (dealing with free edicts, situations where the server entity number is higher than the possible client entity numbers, stuff where I dealt with static entities, other stuff).
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
Re: labeling edicts
AH, i just noticed using the "edicts" command that trigger_*" whatever doesnt use an origin field! Atleast thats what my edicts command shows!
So copying the origin field which is 0 culls out!
UGH :O
Edit ok that fixed it. Some edicts didnt have an "origin" field defined, some didnt have mins/maxs, so i had to construct the origin from the absmin/absmax... phew!
I tried using the SV_Invisible_to_client but it just raped my fps. So im just using a simple trace from r_redef.vieworg to the edict's origin(middle) seems soild.
So copying the origin field which is 0 culls out!
UGH :O
Edit ok that fixed it. Some edicts didnt have an "origin" field defined, some didnt have mins/maxs, so i had to construct the origin from the absmin/absmax... phew!
- Code: Select all
int qglProject (float objx, float objy, float objz, float *model, float *proj, int *view, float* winx, float* winy, float* winz)
{
float in[4], out[4], dist, scale;
int i;
vec3_t org;
org[0] = objx; org[1] = objy; org[2] = objz;
in[0] = objx; in[1] = objy; in[2] = objz; in[3] = 1.0;
if (R_CullSphere (org, 1))
return 0;
dist = VectorDistance(r_refdef.vieworg, org);
if (dist > r_farclip.value)
return 0;
for (i = 0; i < 4; i++)
out[i] = in[0] * model[0 * 4 + i] + in[1] * model[1 * 4 + i] + in[2] * model[2 * 4 + i] + in[3] * model[3 * 4 + i];
for (i = 0; i < 4; i++)
in[i] = out[0] * proj[0 * 4 + i] + out[1] * proj[1 * 4 + i] + out[2] * proj[2 * 4 + i] + out[3] * proj[3 * 4 + i];
if (!in[3])
return 0;
VectorScale(in, 1 / in[3], in);
*winx = view[0] + (1 + in[0]) * view[2] / 2;
*winy = view[1] + (1 + in[1]) * view[3] / 2;
scale = (1 / (dist / 128.0f));
if (scale < 0.1)
return 0;
scale = bound(0.4f, scale, 2);
*winz = scale;
return 1;
}
void SCR_DrawAutoID (void)
{
int i, x, y;
extern void Draw_String_Scaled (int x, int y, char *str, float scale);
float frametime = fabs(cl.time - cl.oldtime);
if (frametime < 0.01)
return;
if (!developer.value)
return;
for (i = 0; i < autoid_count; i++)
{
x = autoids[i].x * vid.width / glwidth;
y = (glheight - autoids[i].y) * vid.height / glheight;
if (autoids[i].classname)
Draw_String_Scaled (x - strlen(autoids[i].classname) * 4 * autoids[i].scale, y - 8 * autoids[i].scale, autoids[i].classname, autoids[i].scale);
if (autoids[i].origin)
Draw_String_Scaled (x - strlen(autoids[i].origin) * 4 * (autoids[i].scale * 0.8), y + 8 * (autoids[i].scale * 0.8), autoids[i].origin, (autoids[i].scale * 0.8));
if (autoids[i].modelname)
Draw_String_Scaled (x - strlen(autoids[i].modelname) * 4 * (autoids[i].scale * 0.8), y + 16 * (autoids[i].scale * 0.8), autoids[i].modelname, (autoids[i].scale * 0.8));
}
}
void SCR_SetupTagEdicts (void)
{
int view[4];
float model[16], project[16];
edict_t *ed;
int i;
autoid_player_t *id;
trace_t trace;
qboolean result;
char *name;
float frametime = fabs(cl.time - cl.oldtime);
extern cvar_t sv_cullentities;
extern void GL_DrawSimpleBox(vec3_t org, float minx, float miny, float minz, float maxx, float maxy, float maxz, vec3_t color, qboolean cull);
entity_t *ent;
vec3_t mins, maxs, origin;
if (frametime < 0.01)
return;
if (autoids[0].classname)
memset(autoids,0,sizeof(autoids));// dont carry over
if (!developer.value)
return;
if (!cl.worldmodel)//Level hasnt loaded yet...
return;
if (cl.maxclients > 1 || !r_drawentities.value || !sv.active)//only in singleplayer mode...
return;
autoid_count = 0;
glGetFloatv(GL_MODELVIEW_MATRIX, model);
glGetFloatv(GL_PROJECTION_MATRIX, project);
glGetIntegerv(GL_VIEWPORT, (GLint *)view);
for (i = 0, ed = NEXT_EDICT(sv.edicts) ; i < sv.num_edicts ; i++, ed = NEXT_EDICT(ed))
{
if (ed->free)
{
continue;
}
origin[0] = ed->v.origin[0];
origin[1] = ed->v.origin[1];
origin[2] = ed->v.origin[2];
if (!VectorLength(origin))
{
VectorCopy (ed->v.absmin, mins);
VectorCopy (ed->v.absmax, maxs);
LerpVector (mins, maxs, 0.5, origin);
}
if (sv_cullentities.value)
{
memset (&trace, 0, sizeof(trace));
trace.fraction = 1;
result = SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, r_refdef.vieworg, origin, &trace);
if (!result)//hit something
{
continue;
}
}
id = &autoids[autoid_count];
if (qglProject(origin[0], origin[1], origin[2], model, project, view, &id->x, &id->y, &id->scale))
{
if (!strcmp((pr_strings + ed->v.classname),"player"))
{
strlcpy(id->classname, (pr_strings + ed->v.netname), 64);
strlcpy(id->modelname, (pr_strings + ed->v.model), 64);
name = va("%3.1f %3.1f %3.1f ", origin[0], origin[1], origin[2]);
strlcpy(id->origin, name, 64);
}
else
{
strlcpy(id->classname, (pr_strings + ed->v.classname), 64);
strlcpy(id->modelname, (pr_strings + ed->v.model), 64);
name = va("%3.1f %3.1f %3.1f ", origin[0], origin[1], origin[2]);
strlcpy(id->origin, name, 64);
}
autoid_count++;
}
}
for (i = 0, ent = cl_static_entities ; i < MAX_STATIC_ENTITIES ; i++, ent++)
{
origin[0] = ent->origin[0];
origin[1] = ent->origin[1];
origin[2] = ent->origin[2];
if (sv_cullentities.value)
{
memset (&trace, 0, sizeof(trace));
trace.fraction = 1;
result = SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, r_refdef.vieworg, origin, &trace);
if (!result)//hit something
continue;
}
id = &autoids[autoid_count];
if (qglProject(origin[0], origin[1], origin[2], model, project, view, &id->x, &id->y, &id->scale))
{
name = "óôáôéã entity_t";
strlcpy(id->classname, "óôáôéã entity_t", 64);
name = va("%s",(ent->model->name));
strlcpy(id->modelname, name, 64);
name = va("%3.1f %3.1f %3.1f ",origin[0], origin[1], origin[2]);
strlcpy(id->origin, name, 64);
autoid_count++;
}
}
}
I tried using the SV_Invisible_to_client but it just raped my fps. So im just using a simple trace from r_redef.vieworg to the edict's origin(middle) seems soild.
- r00k
- Posts: 1110
- Joined: Sat Nov 13, 2004 10:39 pm
8 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 1 guest