Converting 2-d coords to 3-d?

Archive of the old editing forum
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.
User avatar
Nash
 
 
Posts: 17501
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia
Contact:

Converting 2-d coords to 3-d?

Post by Nash »

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?
carlcyber
Posts: 163
Joined: Thu Jan 27, 2005 1:04 am

Re: Converting 2-d coords to 3-d?

Post by carlcyber »

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

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");
    }
}  
Just passed compilation, don't know how this actually works. :mrgreen:

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.
User avatar
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?

Post by Tormentor667 »

Nash you sick boy, what are you up to again? :)
User avatar
Nash
 
 
Posts: 17501
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia
Contact:

Re: Converting 2-d coords to 3-d?

Post by Nash »

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)

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;

}
carlcyber
Posts: 163
Joined: Thu Jan 27, 2005 1:04 am

Re: Converting 2-d coords to 3-d?

Post by carlcyber »

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.
User avatar
Nash
 
 
Posts: 17501
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia
Contact:

Re: Converting 2-d coords to 3-d?

Post by Nash »

Take your time, carlcyber. :) Thanks again...
User avatar
Isle
Posts: 687
Joined: Fri Nov 21, 2003 1:30 am
Location: Arizona, USA

Re: Converting 2-d coords to 3-d?

Post by Isle »

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;
}
carlcyber
Posts: 163
Joined: Thu Jan 27, 2005 1:04 am

Re: Converting 2-d coords to 3-d?

Post by carlcyber »

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
Attachments
CursorSpawnerExample.pk3
(83.35 KiB) Downloaded 38 times
User avatar
Nash
 
 
Posts: 17501
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia
Contact:

Re: Converting 2-d coords to 3-d?

Post by Nash »

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?
User avatar
Isle
Posts: 687
Joined: Fri Nov 21, 2003 1:30 am
Location: Arizona, USA

Re: Converting 2-d coords to 3-d?

Post by Isle »

mlook works, just not in gzdoom. try it with regular zdoom.
User avatar
Nash
 
 
Posts: 17501
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia
Contact:

Re: Converting 2-d coords to 3-d?

Post by Nash »

Indeed it does. However, I need it to work for both renderers...
User avatar
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?

Post by Tormentor667 »

Now where is my screenie?! :D
User avatar
Isle
Posts: 687
Joined: Fri Nov 21, 2003 1:30 am
Location: Arizona, USA

Re: Converting 2-d coords to 3-d?

Post by Isle »

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.
User avatar
Nash
 
 
Posts: 17501
Joined: Mon Oct 27, 2003 12:07 am
Location: Kuala Lumpur, Malaysia
Contact:

Re: Converting 2-d coords to 3-d?

Post by Nash »

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.
Yeah, I just found this out this morning while doing a comparison between yours and carl's.

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...
User avatar
MG_Man
Posts: 1401
Joined: Sat Jul 28, 2007 1:24 pm
Contact:

Re: Converting 2-d coords to 3-d?

Post by MG_Man »

Nash wrote:If only there was a way to detect if the user is using OpenGL or the software renderer... I'd use both.
You could use an if loop and use int whatrenderer = GetCvar(vid_renderer) to determine if the player is using software or not.
Locked

Return to “Editing (Archive)”