Forum

cs_project in csqc

Discuss programming in the QuakeC language.

Moderator: InsideQC Admins

cs_project in csqc

Postby daemon » Sun Dec 30, 2007 2:54 am

can someone explain the ins and outs of cs_project to me? I finally got cs_unproject to do what I want, though I don't fully understand it yet. It's been explained to me a couple different ways, and I'm sure I'm not using it totally correct. One odd thing about it is that the results end up as though I'm facing 90 degrees in the wrong direction, so I ended up swapping the x and y coordinates of the final product after the trace. I also had to multiply my trace distance by 9, which I thought was odd...

this doesn't work too well in a map with any kind of walls, because the trace seems to be happening 90 degrees in the wrong direction, but since I'm not using any walls, it works for now.
Code: Select all
   local vector org, vec, vec2;

   vec = getmousepos();
   vec_x = vec_x*vid_realwidth/vid_width;
   vec_y = vec_y*vid_realheight/vid_height;
   vec_z = 1;
   org = cs_unproject(vec);
   
   vec_z = 0;

   vec2 = cs_unproject(vec);
   
   traceline(vec2, normalize(org)*(cl_org_y-editinglayer)*9, TRUE, world);
   vec = trace_endpos;
   org_x = cl_org_x + vec_y;
   org_z = cl_org_z + vec_z;
   org_y = 0;

(cl_org is the client's org, y being the distance away from the plane to be drawn on)

anyway, now I need to use cs_project because I'm trying to draw some things on the screen, snapped to a grid on that plane, but I have no idea how to use it.
-daemon [ daemonforge.org ]
User avatar
daemon
 
Posts: 63
Joined: Wed Nov 07, 2007 11:10 pm

Postby daemon » Mon Dec 31, 2007 2:29 am

Ok, I THINK the 90 degrees off thing is because I had this:

R_SetView(VF_ANGLES, '0 0 0');

before the previous code... but changing it to '0 -90 0' seems to mess things up even after getting rid of the x and y swap... guess I'll have to mess around with this more.
-daemon [ daemonforge.org ]
User avatar
daemon
 
Posts: 63
Joined: Wed Nov 07, 2007 11:10 pm

Postby daemon » Mon Dec 31, 2007 3:12 am

YAY! I finally got it to work. It was as simple as I thought it was supposed to be. This code works a LOT better (the first two lines are just there because a lot of the HUD stuff messes with the origin and angle settings, so I needed to make them match the camera)

Code: Select all
   R_SetView(VF_ANGLES, '0 -90 0');   
   R_SetView(VF_ORIGIN, cl_org);   
   
   local vector org;

   org = getmousepos();
   org_x = org_x*vid_realwidth/vid_width;
   org_y = org_y*vid_realheight/vid_height;
   org_z = cl_org_y;
   org = cs_unproject(org);


Also note that org_z does not have to be between 0 and 1 as everyone told me it did... No traceline is necessary unless you're trying to hit a surface, but since the plane I'm drawing on is parallel to the camera, and the camera doesn't turn, and I know how far away I am from that plane, then I don't need to bother with any traces.
-daemon [ daemonforge.org ]
User avatar
daemon
 
Posts: 63
Joined: Wed Nov 07, 2007 11:10 pm

Postby Urre » Mon Mar 10, 2008 2:51 pm

In your last post, what does the line org = cs_unproject(org); result in? As I understand it, it's a spot in the world. Am I supposed to project from the camera position to the result from cs_unproject or what (if I want to traceline)? Or is it possibly even simpler, a direction it returns?
I was once a Quake modder
User avatar
Urre
 
Posts: 1109
Joined: Fri Nov 05, 2004 2:36 am
Location: Moon

Postby Spike » Mon Mar 10, 2008 4:21 pm

unproject takes a 2d coordinate with depth (3d...) and converts it into a 3d coordinate.

if you unproject the same point twice with depth of 0 and 1, you'll get the view position (a point on the near clip plane) and a point gl_maxdist away. You can then traceline between the two to see what you hit.

Note that the unproject function uses the view properties state to generate matricies as required, so you will need to clear the scene and set up some stuff before use. At least if you're inside an update event.
Spike
 
Posts: 2892
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Postby Urre » Mon Mar 10, 2008 7:39 pm

Neat, will test soon
I was once a Quake modder
User avatar
Urre
 
Posts: 1109
Joined: Fri Nov 05, 2004 2:36 am
Location: Moon

Postby Urre » Tue Mar 25, 2008 1:26 am

So, this should do the trick?

Code: Select all
   mouse_pos_x = vid_conwidth;
   mouse_pos_y = vid_conheight;
   mouse_pos = mouse_pos*0.5 + getmousepos();
   cam = mouse_pos;
   cam_z = 0;
   cam = cs_unproject(cam);
   proj = mouse_pos;
   proj_z = 1;
   proj = cs_unproject(proj);
   traceline(cam, proj, FALSE, world);
   mouse_trace_ent = trace_ent;
   mouse_trace_endpos = trace_endpos;
I was once a Quake modder
User avatar
Urre
 
Posts: 1109
Joined: Fri Nov 05, 2004 2:36 am
Location: Moon

Postby Spike » Wed Mar 26, 2008 8:42 am

Your asking makes me think it does not.
Spike
 
Posts: 2892
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Postby Urre » Sat Mar 29, 2008 10:54 am

Nope. It traces very close to '0 0 0', but not exactly, max 2 quake units away.
I was once a Quake modder
User avatar
Urre
 
Posts: 1109
Joined: Fri Nov 05, 2004 2:36 am
Location: Moon

Postby LordHavoc » Sat Mar 29, 2008 11:49 am

Urre wrote:Nope. It traces very close to '0 0 0', but not exactly, max 2 quake units away.


From examining the code I would guess that all results are twice as
'wide' as they're supposed to be (meaning you could get correct results by using _x * 0.5 and _y * 0.5), if you could confirm that this 'fixes' it, I'll fix the code to not do the unnecessary *2's.
LordHavoc
 
Posts: 322
Joined: Fri Nov 05, 2004 3:12 am
Location: western Oregon, USA

Postby Urre » Sat Mar 29, 2008 6:27 pm

It resulted in half the result, as I expected. What I wanted, was to trace into the world with my mouse cursor, to select my units and whatnot...

Don't confuse my "2 units off" with '0 0 0' being the correct result. What I meant by that is that it traces towards the world centre, no matter what.
I was once a Quake modder
User avatar
Urre
 
Posts: 1109
Joined: Fri Nov 05, 2004 2:36 am
Location: Moon

Postby Urre » Mon Mar 31, 2008 2:04 pm

After some IRC chat with LH and frank, we came to various conclusions. One conclusion of franks perception which made it somewhat work, was that depth needed to be as far as I wanted it to trace, not between 0-1. I used 10000 on the second unproject for giggles, and that atleast trace into the world. What was still wrong however was that it didn't properly match the mousepointer. It seemed off-scale, or offset strangely. I did lots of tweaking, but to no good result. LH later informed me that I need to set up a view for it to properly work, which basicly means running the code after my R_SetView(VF_ORIGIN, blah); and R_SetView(VF_ANGLES, blah); but that didn't change anything at all... Any thoughts? Anything I've missed?
I was once a Quake modder
User avatar
Urre
 
Posts: 1109
Joined: Fri Nov 05, 2004 2:36 am
Location: Moon

Postby Urre » Wed Apr 02, 2008 4:14 pm

For anyone who wants reference of code that actually works (atleast in DarkPlaces), here goes, shouldn't be hard to understand:

Code: Select all
   getmouse = getmousepos();
   mouse_pos_x = vid_conwidth;
   mouse_pos_y = vid_conheight;
   mouse_pos = mouse_pos*0.5 + getmouse;
   proj = getmouse;
   proj_x = proj_x*vid_width/vid_conwidth;
   proj_y = proj_y*vid_height/vid_conheight;
   start = cs_unproject(proj);
   end = cs_unproject(proj + '0 0 10000');
   traceline(start, end, FALSE, world);
   mouse_trace_ent = trace_ent;
   mouse_trace_endpos = trace_endpos;


Note how the mouse position and the actual traceline require different setup code.
I was once a Quake modder
User avatar
Urre
 
Posts: 1109
Joined: Fri Nov 05, 2004 2:36 am
Location: Moon

Postby Urre » Wed Jul 23, 2008 8:03 pm

There was a bug in the way DarkPlaces handled mouse reading which was fixed, so the above code is no longer valid. And therefore, I figured I should update it! Here goes:

Code: Select all
mouse_pos = getmousepos();
proj = mouse_pos;
proj_x = (proj_x*vid_width/vid_conwidth)-vid_width*0.5;
proj_y = (proj_y*vid_height/vid_conheight)-vid_height*0.5;
start = cs_unproject(proj);
end = cs_unproject(proj + '0 0 10000');
traceline(start, end, FALSE, world);
mouse_trace_ent = trace_ent;
mouse_trace_endpos = trace_endpos;


Enjoy!
I was once a Quake modder
User avatar
Urre
 
Posts: 1109
Joined: Fri Nov 05, 2004 2:36 am
Location: Moon

Postby daemon » Tue Jul 29, 2008 8:22 pm

as requested by Urre, here are a couple functions that make using project and unproject easier. They are fairly similar to what he just posted.

Code: Select all
vector unproject(vector vec) =
{
   vec_x = (vec_x-vid_size_x*0.5)*vid_res_x/vid_size_x;
   vec_y = (vec_y-vid_size_y*0.5)*vid_res_y/vid_size_y;   
   vec = cs_unproject(vec);
   return vec;
}

vector project(vector vec) =
{
   vec = cs_project(vec);
   vec_x = vec_x*vid_size_x/vid_res_x;
   vec_y = vec_y*vid_size_y/vid_res_y;
   vec = vid_size*0.5 + vec;
   vec_z = 0;   
   return vec;
}


if you wanted to do an unproject traceline it would look something like this:

Code: Select all
         start = unproject(org);
         end = unproject(org + '0 0 1000');
         traceline(start, end, IGNOREFLAG, ent);


project is fairly simple. you just give it an origin in the world, and it will give you a 2d origin on the screen.
-daemon [ daemonforge.org ]
User avatar
daemon
 
Posts: 63
Joined: Wed Nov 07, 2007 11:10 pm

Next

Return to QuakeC Programming

Who is online

Users browsing this forum: No registered users and 1 guest