Converting 2-d coords to 3-d?
Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. This forum is archived - please use this set of forums to ask new questions.
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. This forum is archived - please use this set of forums to ask new questions.
Converting 2-d coords to 3-d?
Hey, I need some help on this. I have no idea how to code this.
I have this 2-d mouse cursor on a 640 x 480 virtual HUD size (uses GetPlayerInput to monitor pitch and yaw)... I want to make it so that when I click the mouse (monitors +attack button), it creates an object in the 3-d world space exactly where the mouse cursor is on the 2-d screen...
It sounds difficult... is such a thing possible?
I have this 2-d mouse cursor on a 640 x 480 virtual HUD size (uses GetPlayerInput to monitor pitch and yaw)... I want to make it so that when I click the mouse (monitors +attack button), it creates an object in the 3-d world space exactly where the mouse cursor is on the 2-d screen...
It sounds difficult... is such a thing possible?
Re: Converting 2-d coords to 3-d?
Once the boundries of the screen (horizontal FOV and vertical FOV) are known, I think the rest of the jobs are trigonometry only. I'm too lazy to get those parameters, but the concepts can be demostrated.
Assume the horizontal angle of sight can range from -0.25 to 0.25 and vertical angle of sight range from -0.1 to 0.1, the center of the screen is both 0.0 at horizontal and vertical angle, then
Just passed compilation, don't know how this actually works. 
EDIT: Camera view height should put into consideration.
Assume the horizontal angle of sight can range from -0.25 to 0.25 and vertical angle of sight range from -0.1 to 0.1, the center of the screen is both 0.0 at horizontal and vertical angle, then
Code: Select all
/*
0 640
-------------------->
-0.25 0.25
0 | 0.1
|
|
|
|
|
480 v -0.1
*/
#include "zcommon.acs"
Function int abs(int x)
{
if(x < 0)
{
return -x;
}
return x;
}
// The following parameters have to change to the actual value, this is just a demostration.
int HorAngleRange = 0.25, // Border of the horizontal angle of sight.
VerAngleRange = 0.1; // Border of the vertical angle of sight.
int CameraViewHeight = 41.0;
int HUDWidth = 640,
HUDHeight = 480;
Function void SpawnAtCursorPosition(int cursorX, // X position in virtual HUD of the cursor.
int cursorY, // Y position in virtual HUD of the cursor.
int distance, // Distance from the spawner, integer value (not fixed point).
int tid, // TID of the spawned object.
str objectName) // Name of the object to be spawned.
{
int horReverse = FixedDiv(HUDWidth << 15, FixedDiv(sin(HorAngleRange), cos(HorAngleRange))),
verReverse = FixedDiv(HUDHeight << 15, FixedDiv(sin(VerAngleRange), cos(VerAngleRange)));
int horAngle = VectorAngle(cursorX << 16 - HUDWidth << 15, horReverse), // Similar to GetActorAngle, but the actor is HUD.
verAngle = VectorAngle(HUDHeight << 15 - cursorY << 16, verReverse); // Similar to GetActorPitch, but the actor is HUD.
// Out of range check, this happens when cursorX or cursorY is out of bounds.
if (horAngle < -HorAngleRange) horAngle = -HorAngleRange;
else if(horAngle > HorAngleRange) horAngle = HorAngleRange;
if (verAngle < -VerAngleRange) verAngle = -VerAngleRange;
else if(verAngle > VerAngleRange) verAngle = VerAngleRange;
int realAngle = GetActorAngle(0) + horAngle,
realPitch = GetActorPitch(0) + verAngle;
int playerX = GetActorX(0),
playerY = GetActorY(0);
int distXY = abs(distance * cos(realPitch));
int spawnX = playerX + FixedMul(distXY, cos(realAngle)),
spawnY = playerY + FixedMul(distXY, sin(realAngle)),
spawnZ = GetActorZ(0) + CameraViewHeight + distance * sin(realPitch);
int angle = VectorAngle(spawnX - playerX, spawnY - playerY) >> 8; // Face to the player.
if(!Spawn(objectName, spawnX, spawnY, spawnZ, tid, angle))
{
// Failed spawning, maybe the destination position is blocked.
Print(s:"Spawning ", s:objectName, s:" at (", f:spawnX, s:", ", f:spawnY, s:", ", f:spawnZ, s:") failed");
}
}

EDIT: Camera view height should put into consideration.
Last edited by carlcyber on Mon Apr 06, 2009 8:14 am, edited 1 time in total.
- Tormentor667
- Posts: 13556
- Joined: Wed Jul 16, 2003 3:52 am
- Preferred Pronouns: He/Him
- Operating System Version (Optional): Windows 11
- Graphics Processor: nVidia (Modern GZDoom)
- Location: Germany
- Contact:
Re: Converting 2-d coords to 3-d?
Nash you sick boy, what are you up to again? 

Re: Converting 2-d coords to 3-d?
Thanks carlcyber. But to be honest, I don't understand your code at all - admittedly, I just copy and pasted it into my project.
Based on what I understand though, I have to change HorAngleRage and VerAngleRange, correct? The problem is, I don't know how to precisely find this number for my mod. What should I do?
As-is, your code kind of works... but it spawns things at the wrong place.
Torm - SECRET I CAN"T TELL YOU!!! Ahem. Well... once carlcyber helps me make the script work, I'll post a screenie.
BTW here's my mouse code. mousex and mousey returns the coordinates of the mouse, which is a simple number from 0 to 640, and 0 t0 400).
(Yeah I made a mistake in my first post... I meant to say that my mouse resolution is 640 x 400)
Based on what I understand though, I have to change HorAngleRage and VerAngleRange, correct? The problem is, I don't know how to precisely find this number for my mod. What should I do?
As-is, your code kind of works... but it spawns things at the wrong place.
Torm - SECRET I CAN"T TELL YOU!!! Ahem. Well... once carlcyber helps me make the script work, I'll post a screenie.
BTW here's my mouse code. mousex and mousey returns the coordinates of the mouse, which is a simple number from 0 to 640, and 0 t0 400).
(Yeah I made a mistake in my first post... I meant to say that my mouse resolution is 640 x 400)
Code: Select all
#include "zcommon.acs"
#include "defs.acs"
#library "mouse"
#import "main.acs"
int mousex, mousey, mousemode;
#libdefine M_NONE 0
#libdefine MCLICK_L 1
#libdefine MCLICK_R 2
#libdefine MDRAG_L 3
#libdefine MDRAG_R 4
//////////////////////////////////////
//
// GLOBAL MOUSE FUNCTIONS
//
//////////////////////////////////////
// mouse click function
// modified code from carlcyber
function int MouseClick (void)
{
int m, newbuttons, oldbuttons;
newButtons = GetPlayerInput(-1, INPUT_BUTTONS);
oldButtons = GetPlayerInput(-1, INPUT_OLDBUTTONS);
// left mouse button
if(newButtons & BT_ATTACK)
{
// drag
if(oldButtons & BT_ATTACK)
{
m = MDRAG_L;
}
// click
else
{
m = MCLICK_L;
}
}
else
{
// released
if(oldButtons & BT_ATTACK)
{
m = M_NONE;
}
// do nothing
else
{
}
}
// right mouse button
if(newButtons & BT_ALTATTACK)
{
// drag
if(oldButtons & BT_ALTATTACK)
{
m = MDRAG_R;
}
// click
else
{
m = MCLICK_R;
}
}
else
{
// released
if(oldButtons & BT_ALTATTACK)
{
m = M_NONE;
}
// do nothing
else
{
}
}
// negate if both buttons pressed
if(newButtons & BT_ATTACK && newButtons & BT_ALTATTACK)
{
// drag
if(oldButtons & BT_ATTACK && oldButtons & BT_ALTATTACK)
{
m = M_NONE;
}
// click
else
{
m = M_NONE;
}
}
else
{
// released
if(oldButtons & BT_ATTACK && oldButtons & BT_ALTATTACK)
{
m = M_NONE;
}
// do nothing
else
{
}
}
return m;
}
// some wrapper functions for mouse clicking
function int Mouse_LeftClick (void)
{
int result;
if (MouseClick() == MCLICK_L)
result = TRUE;
else
result = FALSE;
return result;
}
function int Mouse_LeftDrag (void)
{
int result;
if (MouseClick() == MDRAG_L)
result = TRUE;
else
result = FALSE;
return result;
}
function int Mouse_RightClick (void)
{
int result;
if (MouseClick() == MCLICK_R)
result = TRUE;
else
result = FALSE;
return result;
}
function int Mouse_RightDrag (void)
{
int result;
if (MouseClick() == MDRAG_R)
result = TRUE;
else
result = FALSE;
return result;
}
// misc mouse functions
function int ActivateMouse (void)
{
mousemode = 1;
ACS_Execute(SC_MOUSE, 0);
return TRUE;
}
function int DeactivateMouse (void)
{
mousemode = 0;
//ACS_Terminate(SC_MOUSE, 0);
return TRUE;
}
//////////////////////////////////////
//
// MOUSE CODE
//
//////////////////////////////////////
script SC_MOUSE (void)
{
SetPlayerProperty(0, ON, PROP_TOTALLYFROZEN);
// centre the mouse
mousex = 320;
mousey = 200;
while(mousemode)
{
// poll mouse movement
// to-do: add customizable mouse sensivity
mousex -= (GetPlayerInput(-1, INPUT_YAW) / 50);
mousey -= (GetPlayerInput(-1, INPUT_PITCH) / 50);
// horizontal limits
if (GetAspectRatio() == ASPECT_4_3 || GetAspectRatio() == ASPECT_5_4)
{
if (mousex < 0) mousex = 0;
if (mousex > 640) mousex = 640;
}
if (GetAspectRatio() == ASPECT_16_9)
{
if (mousex < -108) mousex = -108;
if (mousex > 748) mousex = 748;
}
if (GetAspectRatio() == ASPECT_16_10)
{
if (mousex < -64) mousex = -64;
if (mousex > 704) mousex = 704;
}
// vertical limits
if (GetAspectRatio() != ASPECT_5_4)
{
if (mousey < 0) mousey = 0;
if (mousey > 400) mousey = 400;
}
else
{
if (mousey < -16) mousey = -16;
if (mousey > 416) mousey = 416;
}
// draw mouse cursor on screen
SetHUDSize(640, 400, 1);
SetFont("cursor");
HUDMessage(s: "a"; HUDMSG_PLAIN, HUDMSGID_MOUSE, CR_UNTRANSLATED, (mousex << 16) + 0.1, (mousey << 16) + 0.1, 0.05);
// debug: print mouse coords
int heh = 0;
if (heh)
{
SetFont("smallfont");
print(d: mousex, s: "/", d: mousey);
}
delay(1);
}
// restore control to player
SetPlayerProperty(0, OFF, PROP_TOTALLYFROZEN);
mousemode = 0;
}
Re: Converting 2-d coords to 3-d?
Hmm, I've found some flaws in it, this might take some time to solve. And I'll write a (hacky) mechanism to find those parameters.
Re: Converting 2-d coords to 3-d?
Take your time, carlcyber. :) Thanks again...
Re: Converting 2-d coords to 3-d?
heres one i threw together based on what i think the other one was trying to do. it spawns things on a plane DIST to the player by just scaling the mouse coordinates to the plane's area on the screen. takes integer coordinates and a fixed point distance. returns 1 on success.
Code: Select all
#DEFINE CameraViewHeight 41.0
#DEFINE HUDWidth 640
#DEFINE HUDHeight 400
function int SpawnAtCursorPosition(int Cursorx, int Cursory, int dist, int tid, str name)
{
Cursorx = (Cursorx - (HUDWidth/2))<<16;
Cursory = (Cursory - (HUDHeight/2))<<16;
int ratio = fixeddiv(HUDHeight<<16, HUDWidth<<16);
int vx = dist*2;
int vy = fixedmul(vx, ratio);
int vratio = fixeddiv(vx, HUDWidth<<16);
int x = fixedmul(Cursorx, vratio);
int z = -fixedmul(Cursory, vratio);
//move to player
int ang = -vectorangle(dist, x);
int len;
if(((ang+0.125)%0.5) > 0.25) len = fixeddiv(x, sin(ang));
else len = fixeddiv(dist, cos(ang));
ang += getactorangle(0);
x = fixedmul(len, cos(ang)) + getactorx(0);
int y = fixedmul(len, sin(ang)) + getactory(0);
ang = -getactorpitch(0);
z += fixedmul(dist, fixeddiv(sin(ang), cos(ang))) + getactorz(0) + CameraViewHeight;
if(Spawn(name, x, y, z, tid, 0)) return 1;
return 0;
}
Re: Converting 2-d coords to 3-d?
The attachment is the example to show how it works, MAP01 is for finding the borders of sight (the demo has already found a set of borders for 640x400), MAP02 is demostrating cursor spawner. Once you found the X markers in MAP01 don't symmetric to the center of the screen, those borders of sight cannot be found, and cursor spawner is broken. Small errors might be there, but I think they are acceptable.
EDIT: Re-upload the attachment
EDIT: Re-upload the attachment
- Attachments
-
CursorSpawnerExample.pk3
- (83.35 KiB) Downloaded 38 times
Re: Converting 2-d coords to 3-d?
Isle - Thanks for trying to help... unfortunately, your version has problems. I tested your code, but it only works right when the player is facing straight. The further up or down I change my pitch, the more inaccurate it gets. Looking 90 degrees downwards does not spawn the object correctly at all. I guess you never meant the plane to rotate with the player's pitch?
carlcyber, your version works perfectly, in 360 degrees. Your MAP01 is definitely useful should I ever need to change my mouse's resolution and need to know the boundaries. Thanks again. :D
I have one more small request though... can you modifiy your SpawnAtCursorPosition function so that, instead of completely failing the spawn (and spawning nothing), it spawns at whatever space it can find? So let's say I am standing 256 units from a wall and I do SpawnAtCursorPosition(mousex, mousey, 512, 0, "Medikit"). It still spawns the medikit, but directly in front of the wall. Is this possible?
carlcyber, your version works perfectly, in 360 degrees. Your MAP01 is definitely useful should I ever need to change my mouse's resolution and need to know the boundaries. Thanks again. :D
I have one more small request though... can you modifiy your SpawnAtCursorPosition function so that, instead of completely failing the spawn (and spawning nothing), it spawns at whatever space it can find? So let's say I am standing 256 units from a wall and I do SpawnAtCursorPosition(mousex, mousey, 512, 0, "Medikit"). It still spawns the medikit, but directly in front of the wall. Is this possible?
Re: Converting 2-d coords to 3-d?
mlook works, just not in gzdoom. try it with regular zdoom.
Re: Converting 2-d coords to 3-d?
Indeed it does. However, I need it to work for both renderers...
- Tormentor667
- Posts: 13556
- Joined: Wed Jul 16, 2003 3:52 am
- Preferred Pronouns: He/Him
- Operating System Version (Optional): Windows 11
- Graphics Processor: nVidia (Modern GZDoom)
- Location: Germany
- Contact:
Re: Converting 2-d coords to 3-d?
Now where is my screenie?! 

Re: Converting 2-d coords to 3-d?
well then don't use carl's either, it's mlook is screwed up in software.
due to how diffrent software mlook is from real mlook you are going to need a different function for each render method.
due to how diffrent software mlook is from real mlook you are going to need a different function for each render method.
Re: Converting 2-d coords to 3-d?
Yeah, I just found this out this morning while doing a comparison between yours and carl's.Isle wrote:well then don't use carl's either, it's mlook is screwed up in software.
due to how diffrent software mlook is from real mlook you are going to need a different function for each render method.
Yours works great in the software renderer because mouselook in it is really just plane shifting the view anyway (and also looks much "cleaner" in code because I don't have to mess around with horizontal and vertical angle ranges like in carl's).
Carl's works great in OpenGL, but not in the software renderer.
If only there was a way to detect if the user is using OpenGL or the software renderer... I'd use both.
EDIT: Torm - It's coming... just you wait! Actually I don't think you'd be too interested in it anyway, it probably won't look THAT interesting...
Re: Converting 2-d coords to 3-d?
You could use an if loop and use int whatrenderer = GetCvar(vid_renderer) to determine if the player is using software or not.Nash wrote:If only there was a way to detect if the user is using OpenGL or the software renderer... I'd use both.