#### Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

# how to map a 2D coordinate into 3D...

edited February 2017

Hi, I have a set of points in 3D and want to use mouse to alter the position of those points. I have got the equivalent position of these points in 2D using screenX & screenY (mapping 3D into 2D), but have difficulty in mapping 2D back to 3D..

What I want is to use the mouse's position(mouseX mouseY) to determine the position of point's Z axis (height) to be visually in the same position as my mouse.

is there any function to counter-screenX & screenY...? (sort of sine - arcsine..if it can explain it less confusing..)

Let's say the position I would like to alter is

`PVector pos = point.x, point.y, point.z`

and I want the point.z be altered by mouseX and mouseY.. so it should be something like

``````if(mouseClicked)
{
point.z = counterScreen(mouseX, mouseY);.....
}
``````
Tagged:

• edited February 2017
• @kfrajer Thanks! I found it difficult to decide z value in 3D, so I gave up and use keyboard to control z value but I used the website you referred to to get the x & y value, that's very helpful thanks a looooot!!

• Y is height and Z is depth.

Image the space above a table.

Y is how far above the table, Z is back and forth

• You can try

point.z = map(mouseY, 0, height, -200,200);

Or increase the z value when mouseY > pmouseY etc..

• Imagine you are standing in a room looking through a window at a beautiful country scene and you see something of interest at a 3D position [x,y,z]. Now imagine a line that links [x,y,z] to your eye. It will pass through the window and if we note the position it intersects with the window we get a 2D position [sx,sy].

So far so good. Now lets try and reverse the process we draw a line from our eye to infinity through the window position [sx,sy] the 'something of interest' could be anywhere along that line. It means that it is impossible to generate a 3D position from the 2D screen position.

• edited March 2017

It means that it is impossible to generate a 3D position from the 2D screen position.

Unless you have a rule that provides that third dimension. For example:

1. if all points are at a fixed cartesian depth (e.g. all points have the same z value) or
2. if all points are at a known fixed distance (e.g. all points are found on the surface of a sphere centered on the viewer) etc.

Or you can create a depth map. For each point, index it under its screenX, screenY. Then look up a given screenX, screenY in your index / hashmap / whatever and return the point (if any) with the closest z (if more than one). But this is getting complex -- there may be simpler ways of accomplishing what you want depending on the scenario -- for example, if you know that points will never appear in front of each other.

That is: once you have selected a point, you could alter the depth in relative ways with the mouse, for example dragging. Since you know the absolute z in the point object, it doesn't matter that you can't input an absolute z with the mouse -- it can be relative.

Entire

• The depth map idea is the easiest to implement, and serves the purpose well enough.

Superb explanation @quark.

• in this sketch you can drag a sphere with mouse and change its x,y

when you hold a key during drag, ONLY Z changes with mouseY (up and down)

``````// States
final int HELP = 0; // consts
final int GAME = 1;
int state = GAME;   // current

final int viewsTotal = 0;
//final int viewsNeighbours = 1;  // 26 Neighbours
//final int viewsPlaneXY = 2;
//final int viewsNeighboursInThePlaneXZ = 3;  // 8 Neighbours
//final int viewsNeighboursInThePlaneXY = 4;
//final int viewsNeighboursInThePlaneYZ = 5;
//final int viewsNeighboursDiagonally = 6;   // 8 Neighbours

int view = viewsTotal;

// boxes
BoxClass[][][] boxes = new BoxClass[6][6][6];

// cam rotation
float camCurrentAngle=0.0;

PFont font1;

boolean showGrid = false;

boolean hold;
PVectorInt selected = new PVectorInt(-1, 0, 0);

// --------------------------------------------------------
// main funcs

void setup() {
size(1400, 800, P3D);

defineBoxes();
background(111);
font1 = createFont("Arial", 32);
textFont(font1);
} // func

void draw() {
switch (state) {

case HELP:
// to do
background(111);
text("Help\n\nThis is the help..."
+"\n\npress any key.",
32, 344);
break;

case GAME:
playTheGame();
break;

default:
//exit
break;
} // switch
} // func draw()

// ----------------------------------------------------

void playTheGame() {

background(111);

// reset some stuff that was set differently by the HUD
hint(ENABLE_DEPTH_TEST);
textSize(32);
lights();

translate(width/2, 0);

showTheGridDependingOnCurrentView();
strokeWeight(1);

if (hold) {
if (keyPressed) {
float diff=pmouseX-mouseX;
//  boxes[selected.x][selected.y][selected.z].x-=diff;
diff=pmouseY-mouseY;
boxes[selected.x][selected.y][selected.z].z-=diff;
} else
{
float diff=pmouseX-mouseX;
boxes[selected.x][selected.y][selected.z].x-=diff;
diff=pmouseY-mouseY;
boxes[selected.x][selected.y][selected.z].y-=diff;
}
}//if

// camera
if (keyPressed&&key=='r')
camCurrentAngle++;
if (keyPressed&&key=='l')
camCurrentAngle--;

// 2D part / HUD  ---------------------------------------------
camera();
hint(DISABLE_DEPTH_TEST);
noLights();
textMode(MODEL);
//  textMode(SHAPE);
textSize(22);

if (hold) {
fill(255, 2, 2);
text("Hold mode: drag a sphere to change its x,y. Hold a key and drag to change ONLY Z with mouse up and down (y is mapped to Z).",
10, 20 );
} else {
fill(255);
text("Hello. "
+"Use r and l to rotate. "
+"Select a sphere with nouse click. "
+"Demonstrates the usage of screenX,screenY.",
10, 20 );
// text(mouseX + "," + mouseY, mouseX+7, mouseY-7);
}
}

// ------------------------------------------------------------------

void showTheGridDependingOnCurrentView() {

switch (view) {

case viewsTotal:

//   println("here");
// show list
// for (PVectorInt pvInt : listShape) {
stroke(255, 2, 2);

// show boxes : all
boolean showInRed=false;
for (int i = 0; i < boxes.length; i++) {
for (int j = 0; j < boxes[i].length; j++) {
for (int k = 0; k < boxes[i][j].length; k++) {

if (selected.x==i&&selected.y==j&&selected.z==k)
showInRed=true;
else
showInRed=false;

boxes[i][ j][k].show(showInRed);
}
}
}// for
break;

default :
// error
break;
} // switch
} // func

// ----------------------------------------------------
// input funcs

void keyPressed () {

switch (state) {

case HELP :
state = GAME;
break;

case GAME :
if (key!=CODED) {
// not CODED -----------------------------------
if (key=='X') {
// reset
defineBoxes();
} else if (key == 's') {
showGrid=!showGrid;
} else {
// do nothing
}
} else {
// if (key==CODED) { --------------------------------------------
//
switch (keyCode) {

case java.awt.event.KeyEvent.VK_F1 :
// F1
state = HELP;
break;

case java.awt.event.KeyEvent.VK_PAGE_UP :
break;

case java.awt.event.KeyEvent.VK_PAGE_DOWN :
break;

default :
// do nothing
break;
} // switch
} // else

break;
} // switch
//
} // func

// ----------------------------------------------------
// misc funcs

void defineBoxes() {
// define boxes
int k2=0;
char letter=' ';
for (int i = 0; i < boxes.length; i++) {
for (int j = 0; j < boxes[i].length; j++) {
for (int k = 0; k < boxes[i][j].length; k++) {
// prepare values
color currentCol = color (255); //  color (random(255), random(255), random(255));
boolean exist = true;

// create a box
boxes[i][ j][k] = new BoxClass( -180 + i*(height/10),
158 + j*(height/10),
130 - k*(height/10),
currentCol,
exist,
' ' );
}
}
} // for
} // func

// ----------------------------------------

void mousePressed() {

for (int i = 0; i < boxes.length; i++) {
for (int j = 0; j < boxes[i].length; j++) {
for (int k = 0; k < boxes[i][j].length; k++) {

if (dist(mouseX, mouseY, boxes[i][j][k].scX, boxes[i][j][k].scY) < 20) {
selected= new PVectorInt( i, j, k);
hold=true;
return;
}
}
}
}
}

void mouseReleased() {
hold=false; // off
selected= new PVectorInt( -1, -1, -1); //selected is off
}

// =====================================================
// classes

class BoxClass {

// this class represents one Box / Cell

float x;
float y;
float z;

float scX, scY;

color col;
boolean exist = true;

// constr
BoxClass(float x_, float y_, float z_,
color col_,
boolean exist_,
char letter_) {
x = x_;
y = y_;
z = z_;
col = col_;
exist = exist_;
} // constr

void show(boolean showBoxAsRed) {
if (exist||showGrid) {
pushMatrix();
translate(x, y, z);

fill(col);
if (showBoxAsRed)
fill(255, 2, 2); //RED
noStroke();

sphere(7);
scX = screenX(0, 0, 0);
scY = screenY(0, 0, 0);

popMatrix();
}
} // method
} // class

// ==============================================================

class PVectorInt {
// it's like a PVector but int (not float)
int x, y, z;
PVectorInt(int x_, int y_, int z_) {
x=x_;
y=y_;
z=z_;
} // constr

PVectorInt copy() {
return new PVectorInt(x, y, z);
}
}
// =============================================================
``````