labeling edicts

Discuss programming topics for the various GPL'd game engine sources.
Post Reply
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

labeling edicts

Post by r00k »

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...

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
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: labeling edicts

Post by Baker »

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 :D I mean it isn't like I haven't benefitted from all your Qrack enhancements :D And even if I didn't or you didn't, it's all GPL :)

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
Image
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Re: labeling edicts

Post by r00k »

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
Image
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: labeling edicts

Post by Baker »

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. :( My source seems to be missing an entire "folder" of gl_ files ... but I was using a single folder. I did bundle the source archive from my Mac and then flash drive it over to Windows prior to upload, but I fail to see how that could have anything to do with missing files.

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? 8) 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

Post by Baker »

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

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. :D I drew them in 3D, hahaha :D

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? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Re: labeling edicts

Post by r00k »

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... :(

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.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: labeling edicts

Post by Baker »

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? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Re: labeling edicts

Post by r00k »

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!

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.
Post Reply