Forum

detecting screen position of an entity

Discuss CSQC related programming.

Moderator: InsideQC Admins

detecting screen position of an entity

Postby Nahuel » Tue Sep 20, 2016 9:36 am

Is there a way to detect the relative coordinates of the screen of an entity of the world (items, monsters, etc...) when this is visible?
I wanna to put a csqc image or string, above the relative position of the entity in the screen, only if this is visible :)
without ssqc i could use a sprite only visible to my client, but i do not want to fight with scale.


Any ideas?

Thanks for your help!
hi, I am nahuel, I love quake and qc.
User avatar
Nahuel
 
Posts: 476
Joined: Wed Jan 12, 2011 8:42 pm
Location: mar del plata

Re: detecting screen position of an entity

Postby Spike » Tue Sep 20, 2016 3:59 pm

string thetext = "hello world";
vector charsize = '8 8';
vector screenpos = project(theent.origin);
if (screenpos_z >= 0)
{
screenpos_x -= stringwidth(thetext, TRUE, charsize) * 0.5; //align horizontally to centre
screenpos_y -= charsize_y * 0.5; //align vertically again
screenpos_z = 0; //shut up dp.
drawstring(screenpos, thetext, charsize, '1 1 1', 1, 0);
}


(make sure you already set VF_ORIGIN+VF_ANGLES+VF_AFOV+VF_MIN+VF_SIZE etc, otherwise project won't have the correct model matrix+projection matrix+viewport and will give incorrect results, normally they should still be set from the last renderscene call).
Spike
 
Posts: 2842
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Re: detecting screen position of an entity

Postby Nahuel » Tue Sep 20, 2016 8:22 pm

cool :)
sorry for this noob question.
What is the easy way to share the origin of the ssqc entities with csqc?
hi, I am nahuel, I love quake and qc.
User avatar
Nahuel
 
Posts: 476
Joined: Wed Jan 12, 2011 8:42 pm
Location: mar del plata

Re: detecting screen position of an entity

Postby toneddu2000 » Thu Sep 22, 2016 8:25 am

Nahuel wrote:What is the easy way to share the origin of the ssqc entities with csqc?
CSQC_Ent_Update, I guess. At least it's the function I use to sync entities fields (origin,velocity, angles, health, blah) with CSQC. In ssqc use a theentity.SendEntity = MySendFunction; and, in csqc CSQC_Ent_Update retrieve those datas. I use FTE but it should be the same in DP. Interestingly, you can "filter" sending fields(to save bandwith)accordingly to setting a flag. For example

Code: Select all
ssqc
float SendSomeFlags(entity playerent,float changedflags)
{
   msg_entity = playerent;
   WriteByte(MSG_ENTITY, ENT_MYENTITY);   
   WriteByte(MSG_ENTITY, changedflags);ì
   if (changedflags & 8){
      WriteCoord(MSG_ENTITY,self.origin_x);
      WriteCoord(MSG_ENTITY,self.origin_y);
      WriteCoord(MSG_ENTITY,self.origin_z);
   }
   if (changedflags & 12){
      WriteByte(MSG_ENTITY,self.weapon);
   }
   return TRUE;
}

void EntitySpawnFunction()
{
stupientity = spawn();
stupientity.SendEntity = SendSomeFlags;
}


then, still in ssqc, you can "filter" send fields by flag

Code: Select all
void MyMoveFunction(entity ent)
{
ent.origin_x += 10;
ent.SendFlags |= 8;//send only origin vectors to csqc
}

void MyWeaponChooseFunction(entity ent)
{
ent.weapon = 4;//machinegun ooooyeah
ent.SendFlags |= 12;//send only weapon num
}


Same thing in CSQC, you can filter which flag you'll read
Code: Select all
void CSQC_Ent_Update (float isnew)
{
   local float i = readbyte();
   local float flags;
   if (i == ENT_MYENTITY){
      flags=readbyte();
      if(flags & 8){
         //movements
         self.origin_x = readcoord();
         self.origin_y = readcoord();
         self.origin_z = readcoord();   
      }
      if(flags & 12){
         self.csWeapon = readbyte();
      }
   }
}


Instead, if you want a "just one time" connection with CSQC, you can send in ssqc an event and then parse it in csqc .
ssqc
void SendTempOrigin()
{
msg_entity = self;
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, PE_ORIGIN);
WriteCoord(MSG_ENTITY,self.origin_x);
WriteCoord(MSG_ENTITY,self.origin_y);
WriteCoord(MSG_ENTITY,self.origin_z);
multicast(self.origin, MULTICAST_ALL);//every player will know about me
}


csqc
Code: Select all
noref void() CSQC_Parse_Event =
{
   local float rb = readbyte();
   if(rb == PE_ORIGIN ){
      local float pvector;
      pvector= [readcoord(),readcoord(),readcoord()];
   mycsqcentity.origin = pvector;
   }
}

PE_ORIGIN is a constant which both ssqc and csqc must know. This is useful for a rocket exploding or something else. Not sure if it works in DP, sorry

My next utopian dream is to create all entities in CSQC and in SSQC create a "master server" which reads only entitites coordinates (player,bullets,explosions, etc.) every X milliseconds and re-send it to all players. That's it.
Everything is made in pure CSQC. No more ssqc+csqc crap every sec. Why? Because THIS is utopian
toneddu2000
 
Posts: 1201
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy

Re: detecting screen position of an entity

Postby Nahuel » Thu Dec 15, 2016 1:37 pm

toneddu2000!!
thanks for the clues/explanation :)
hi, I am nahuel, I love quake and qc.
User avatar
Nahuel
 
Posts: 476
Joined: Wed Jan 12, 2011 8:42 pm
Location: mar del plata


Re: detecting screen position of an entity

Postby Nahuel » Thu Mar 09, 2017 4:00 pm

Spike wrote:string thetext = "hello world";
vector charsize = '8 8';
vector screenpos = project(theent.origin);
if (screenpos_z >= 0)
{
screenpos_x -= stringwidth(thetext, TRUE, charsize) * 0.5; //align horizontally to centre
screenpos_y -= charsize_y * 0.5; //align vertically again
screenpos_z = 0; //shut up dp.
drawstring(screenpos, thetext, charsize, '1 1 1', 1, 0);
}


(make sure you already set VF_ORIGIN+VF_ANGLES+VF_AFOV+VF_MIN+VF_SIZE etc, otherwise project won't have the correct model matrix+projection matrix+viewport and will give incorrect results, normally they should still be set from the last renderscene call).



Spike, i did use this method and it works great, but i did try to use it with R_BeginPolygon stuff and it doesnt work properly.
I use R_BeginPolygon in 2d stuff successfully, rotating images and cutting (for life bars), even with zooms. so i know the way to use r_beginPolygon stuff (and it is great)
Itś possible to use R_BeginPolygon stuff to draw a fake polygon in world? I mean, i did try to do it but it works very strange, is there a limitation or r incompatibility with "project" function and R_BeginPolygon?

any clue about it??

thanks
hi, I am nahuel, I love quake and qc.
User avatar
Nahuel
 
Posts: 476
Joined: Wed Jan 12, 2011 8:42 pm
Location: mar del plata

Re: detecting screen position of an entity

Postby Spike » Thu Mar 09, 2017 6:37 pm

be sure to add your 3d polys between your clearscene and renderscene calls.
remember that their verticies will take world-space coords.


there may be some confusion due to older versions of DP having a nasty habit of assuming stuff about whether the polygon is meant to be 2d or 3d. In FTE this was meant to be flags&4 to mean '2d - draw immediately' instead of adding it to the scene. Due to DP's weirdness however, you should use an extra 3rd argument to beginpolygon (FTE will understand this also, if that argument is specified).

Trying to draw '3d' polygons using projected 2d coords will result in affine texture sampling (read: weird depth-related distortions on your textures which might not be noticable if all the verts are the same distance from the camera). So don't do that unless you really have to.

otherwise you're going to hav to clarify what you mean by 'doesnt work properly'.
Spike
 
Posts: 2842
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Re: detecting screen position of an entity

Postby toneddu2000 » Sun Mar 12, 2017 9:53 pm

Try this. Of course replace shd with your shader file

Code: Select all
void Render_TestCube2()
{      
   local string shd = "textures/test/checker";
   local float side = 8192;
   
   // front
   R_BeginPolygon(shd);
      R_PolygonVertex([-side,side,side],[0,1,0],[1,1,1],1);
      R_PolygonVertex([side,side,side],[1,1,0],[1,1,1],1);
      R_PolygonVertex([side,side,-side],[1,0,0],[1,1,1],1);
      R_PolygonVertex([-side,side,-side],[0,0,0],[1,1,1],1);
   R_EndPolygon();
   // top
   R_BeginPolygon(shd);
      R_PolygonVertex([side,-side,side],[0,1,0],[1,1,1],1);
      R_PolygonVertex([side,side,side],[1,1,0],[1,1,1],1);
      R_PolygonVertex([-side,side,side],[1,0,0],[1,1,1],1);
      R_PolygonVertex([-side,-side,side],[0,0,0],[1,1,1],1);
   R_EndPolygon();
   // right
   R_BeginPolygon(shd);
      R_PolygonVertex([side,side,-side],[0,1,0],[1,1,1],1);
      R_PolygonVertex([side,side,side],[1,1,0],[1,1,1],1);
      R_PolygonVertex([side,-side,side],[1,0,0],[1,1,1],1);
      R_PolygonVertex([side,-side,-side],[0,0,0],[1,1,1],1);
   R_EndPolygon();
   // left
   R_BeginPolygon(shd);
      R_PolygonVertex([-side,-side,side],[0,1,0],[1,1,1],1);
      R_PolygonVertex([-side,side,side],[1,1,0],[1,1,1],1);
      R_PolygonVertex([-side,side,-side],[1,0,0],[1,1,1],1);
      R_PolygonVertex([-side,-side,-side],[0,0,0],[1,1,1],1);
   R_EndPolygon();
   // bottom
   R_BeginPolygon(shd);
      R_PolygonVertex([side,-side,side],[0,1,0],[1,1,1],1);
      R_PolygonVertex([-side,-side,side],[1,1,0],[1,1,1],1);
      R_PolygonVertex([-side,-side,-side],[1,0,0],[1,1,1],1);
      R_PolygonVertex([side,-side,-side],[0,0,0],[1,1,1],1);
   R_EndPolygon();
   // back
   R_BeginPolygon(shd);
      R_PolygonVertex([side,side,-side],[0,1,0],[1,1,1],1);
      R_PolygonVertex([side,-side,-side],[1,1,0],[1,1,1],1);
      R_PolygonVertex([-side,-side,-side],[1,0,0],[1,1,1],1);
      R_PolygonVertex([-side,side,-side],[0,0,0],[1,1,1],1);
   R_EndPolygon();
}

In the first argument of each R_PolygonVertex you could *probably* add +org, where org stand for project() origin achieved earlier
Hope it helps

cheers
toneddu2000
 
Posts: 1201
Joined: Tue Feb 24, 2009 4:39 pm
Location: Italy


Return to CSQC Programming

Who is online

Users browsing this forum: No registered users and 1 guest