Hello everybody,
Someone knows how to set the camera in processing in order to have the TOP view? and move It in x or y to find the object ?
Thanks!
Hello everybody,
Someone knows how to set the camera in processing in order to have the TOP view? and move It in x or y to find the object ?
Thanks!
The idea of 3D space
The idea of 3D space (with size(1600, 900, P3D);
) is that you draw not on a canvas but inside a box / room where you can place stuff further away (away from you, into the screen depth) or nearer to you.
Imagine the room as the space on a table where you place your scene:
The idea is that
The camera
The camera has 9 parameters: 3 for position, 3 for lookAt, 3 for UP vector.
For Top Down view:
top down camera is
Chrisir
// house
float inc = 0;
int depth= 125;
void setup() {
size(1600, 900, P3D);
noStroke();
}
void draw() {
//
background(0);
lights();
if (!keyPressed) {
// top down !!!!!!!!!!!!!!!!!!!!!!!!
camera(width/2, height/2-300, 0,
width/2, height/2, 0,
0, 0, 1);
} else {
camera(width/2.0, height/2.0, (height/2.0) / tan(PI*30.0 / 180.0),
width/2.0, height/2.0, 0,
0, 1, 0);
}
translate(width/2, height/2);
rotateY(inc);
arrow();
inc += .01;
}
// ------------------------------------------------------------------
void arrow() {
// house
fill(255);
int[] x = {
-50, 0, 50, 25
};
int[] y = {
50, 0, 50, 50
//
};
int[] xWalls = {
25, 25, -25, -25, -50
};
int[] yWalls = {
50, 100, 100, 50, 50
}
;
fill(255, 0, 0);
beginShape();
for (int i = 0; i<4; i++)
vertex(x[i], y[i]);
endShape(CLOSE);
fill(255, 0, 0);
beginShape();
for (int i = 0; i<4; i++)
vertex(x[i], y[i], depth+10);
endShape(CLOSE);
fill(0, 255, 255);
fill(255, 0, 0);
beginShape(QUAD_STRIP);
for (int i = 0; i<4; i++) {
vertex(x[i], y[i]);
vertex(x[i], y[i], depth+10);
}
int i2 = 0;
vertex(x[i2], y[i2]);
vertex(x[i2], y[i2], depth);
endShape(CLOSE);
fill(0, 255, 255);
beginShape(QUAD_STRIP);
for (int i = 0; i<4; i++) {
vertex(xWalls[i], yWalls[i]);
vertex(xWalls[i], yWalls[i], depth);
}
i2 = 4;
vertex(xWalls[i2], yWalls[i2]);
vertex(xWalls[i2], yWalls[i2], depth);
endShape(CLOSE);
// ---------------------------------------
fill(255, 0, 0);
fill(0, 255, 255);
beginShape();
for (int i = 0; i<4; i++)
vertex(xWalls[i], yWalls[i]);
endShape(CLOSE);
fill(255, 0, 0);
fill(0, 255, 255);
beginShape();
for (int i = 0; i<4; i++)
vertex(xWalls[i], yWalls[i], depth);
endShape(CLOSE);
}
//
in this new version, use mouse to move the camera (not the objects) in x and z direction
(As discussed above, in top view when you search something, search in in x and z direction,
so mouseX and mouseY is used as x and y position of the camera)
Chrisir
// house
float inc = 0;
int depth= 125;
PVector mousePV = new PVector();
void setup() {
size(1600, 900, P3D);
noStroke();
}
void draw() {
//
background(0);
lights();
if (!keyPressed) {
// top down !!!!!!!!!!!!!!!!!!!!!!!!
//mousePV.set(mouseX, mouseY);
mousePV.set (
map(mouseX, 0, width, -50, width+50),
map(mouseY, 0, height, -300, 300)
);
camera(mousePV.x, height/2-300, mousePV.y,
mousePV.x, height/2, mousePV.y,
0, 0, 1);
} else {
camera(width/2.0, height/2.0, (height/2.0) / tan(PI*30.0 / 180.0),
width/2.0, height/2.0, 0,
0, 1, 0);
}
translate(width/2, height/2);
rotateY(inc);
arrow();
inc += .01;
camera();
fill(255);
text("camera is at "
+int(mousePV.x)
+", "
+int(mousePV.y),
14, 17);
}
// ------------------------------------------------------------------
void arrow() {
// house
fill(255);
int[] x = {
-50, 0, 50, 25
};
int[] y = {
50, 0, 50, 50
//
};
int[] xWalls = {
25, 25, -25, -25, -50
};
int[] yWalls = {
50, 100, 100, 50, 50
}
;
fill(255, 0, 0);
beginShape();
for (int i = 0; i<4; i++)
vertex(x[i], y[i]);
endShape(CLOSE);
fill(255, 0, 0);
beginShape();
for (int i = 0; i<4; i++)
vertex(x[i], y[i], depth+10);
endShape(CLOSE);
fill(0, 255, 255);
fill(255, 0, 0);
beginShape(QUAD_STRIP);
for (int i = 0; i<4; i++) {
vertex(x[i], y[i]);
vertex(x[i], y[i], depth+10);
}
int i2 = 0;
vertex(x[i2], y[i2]);
vertex(x[i2], y[i2], depth);
endShape(CLOSE);
fill(0, 255, 255);
beginShape(QUAD_STRIP);
for (int i = 0; i<4; i++) {
vertex(xWalls[i], yWalls[i]);
vertex(xWalls[i], yWalls[i], depth);
}
i2 = 4;
vertex(xWalls[i2], yWalls[i2]);
vertex(xWalls[i2], yWalls[i2], depth);
endShape(CLOSE);
// ---------------------------------------
fill(255, 0, 0);
fill(0, 255, 255);
beginShape();
for (int i = 0; i<4; i++)
vertex(xWalls[i], yWalls[i]);
endShape(CLOSE);
fill(255, 0, 0);
fill(0, 255, 255);
beginShape();
for (int i = 0; i<4; i++)
vertex(xWalls[i], yWalls[i], depth);
endShape(CLOSE);
}
//
another sketch with 5 different views:
/*
New version with camera class AND smooth transitions (damping) ============================================================
This sketch is based on the following assumptions:
* in 3D the scene is on a table. So placing things left and right on the table is x,
* placing it more in front or in the back is Z and
* placing it above the scene (blue box) is Y.
* The center of the scene is at width/2, height/2, 0
https://discourse.processing.org/t/camera-how-top-down-view/1178/3
wenn man von 2 auf 4 geht oder 1 auf 3, schiesst er durch den Würfel durch.
besser wäre lerp auf einer Kreisbahn über einen radius
*/
// demonstrates view from top down (above the sceen),
// and from north, east, south and west.
// The interesting part: the UP-vector when view from top.
// default values are
// camera(width/2.0, height/2.0, (height/2.0) / tan(PI*30.0 / 180.0),
// width/2.0, height/2.0, 0,
// 0, 1, 0).
CameraMy cam;
// view mode and its texts :
int viewMode=3; // This var dictates how current camera mode!!!!!!!
String[] viewText={
"top view",
"from north",
"from east",
"from south (processing default)",
"from west",
"rotating"
};
// -------------------------------------------------------
void setup() {
size(1500, 600, P3D);
stroke(255, 0, 0);
cam = new CameraMy();
}
void draw() {
background(0);
lights();
if (!mousePressed) {
// apply view mode
cam.apply();
//
} else {
// default (from south)
camera();
}//else
// draw scene
drawScene();
// HUD : text
camera();
fill(255);
text("Camera test: Hit 0..5 for top view (0, from top) / north (1) / east (2) / south (=3, processing default) / west view (4) / rotate (5). "
+"\nClick and hold mouse to see processing default view."
+"\nCurrent view: "
+viewText[viewMode],
15, 15);
}//func
// ---------------------------------------------------------------------------
void drawScene() {
// the sculpture
translate(width/2, height/2, 0);
fill(255); //white
box(100); // big box
translate(100, 0, 0); // right
fill(255, 0, 0); // red
box(50);
translate(-200, 0, 0); // left
fill(0, 255, 0); // green
box(50);
translate(100, -100, 0); // center above
fill(0, 0, 255); // blue
box(50);
translate(0, 100, 100); // center above
fill(0, 0, 255); // blue
noStroke();
sphere(12);
translate(0, 0, -200); // center above
fill(0, 255, 0); // green
noStroke();
sphere(12);
}
//-----------------------------------------------------------------------------
void keyPressed() {
// for keys from 0 to 5
if (key>='0'&&key<='5') {
// apply as camera mode
viewMode=int(key+"");
setViewFromViewMode();
}//if
}
void setViewFromViewMode() {
// radius = 400
cam.rotateFlag=false;
switch (viewMode) {
case 0:
// top down
cam.setEye(width/2, height/2-400, 0);
cam.setUpVector(0, 0, 1);
break;
case 1:
//from north
cam.setEye(width/2, height/2, -400);
cam.setUpVectorToStandard();
break;
case 2:
//from east
cam.setEye(width/2+400, height/2, 0);
cam.setUpVectorToStandard();
break;
case 3:
//from south // default
// cam.reset();
cam.setEye(width/2, height/2, 400);
cam.setUpVectorToStandard();
break;
case 4:
//from west
cam.setEye(width/2-400, height/2, 0);
cam.setUpVectorToStandard();
break;
case 5:
cam.setUpVectorToStandard();
cam.rotate();
break;
default:
// Error
println("error 55 in switch");
exit();
return;
}//switch
//
}//func
//===========================================================
class CameraMy {
// to use the camera more easily
// standard values
final PVector eyePV_Standard = new PVector ( width/2.0, height/2.0, (height/2.0) / tan(PI*30.0 / 180.0)); // eye = camera position
final PVector lookAtPV_Standard = new PVector ( width/2, height/2, 0 ); // look At or center
final PVector upPV_Standard = new PVector ( 0, 1, 0); // the up vector for rotating the camera around itself
// the changing values:
PVector eyePV, lookAtPV, upPV;
// old PVectors
PVector eyePVold, lookAtPVold, upPVold;
// for lerp
float amt = 0;
// for rotation
boolean rotateFlag=false;
float angle=0;
// constr
CameraMy() {
eyePV = eyePV_Standard.copy();
lookAtPV = lookAtPV_Standard.copy();
upPV = upPV_Standard.copy();
eyePVold = eyePV.copy();
lookAtPVold = lookAtPV.copy();
upPVold = upPV.copy();
}//constr
// -----
// 3 set methods :
void setEye( float x, float y, float z) {
eyePVold=eyePV.copy();
eyePV=new PVector(x, y, z);
amt=0;
}
void setLookAt( float x, float y, float z) {
lookAtPVold=lookAtPV.copy();
lookAtPV=new PVector(x, y, z);
amt=0;
}
void setUpVector( float x, float y, float z) {
upPVold=upPV.copy();
// set UP vector
upPV=new PVector(x, y, z);
amt=0;
}
// ----
// 3 set methods for standard :
void setEyeToStandard() {
eyePVold=eyePV.copy();
eyePV = eyePV_Standard.copy();
amt=0;
}
void setLookAtToStandard() {
lookAtPVold=lookAtPV.copy();
lookAtPV = lookAtPV_Standard.copy();
amt=0;
}
void setUpVectorToStandard() {
upPVold=upPV.copy();
upPV = upPV_Standard.copy();
amt=0;
}
// ----
void reset() {
// reset
// store old values
eyePVold=eyePV.copy();
lookAtPVold=lookAtPV.copy();
upPVold=upPV.copy();
// reset
eyePV = eyePV_Standard.copy();
lookAtPV = lookAtPV_Standard.copy();
upPV = upPV_Standard.copy();
// set amt to 0 for lerp
amt=0;
}
//----
void rotate() {
//init rotate
rotateFlag = true;
setLookAtToStandard();
}
// ----
void apply() {
// apply values
// rotation mode ?
if (rotateFlag) {
// rotation mode
eyePV = new PVector ( width/2.0 + cos(angle) * 400,
height/2.0,
sin(angle) * 400 ); // eye = camera position
angle+=.05;
camera (eyePV.x, eyePV.y, eyePV.z,
lookAtPV.x, lookAtPV.y, lookAtPV.z,
upPV.x, upPV.y, upPV.z);
return; // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}//if rotateFlag
// normal modes :
// we don't use the new values (eyePV,lookAtPV,upPV) directly but with eyePVold etc. and lerp (and its amt)
PVector eyePV2, lookAtPV2, upPV2;
eyePV2 = lerpPV ( eyePVold, eyePV, amt );
lookAtPV2 = lerpPV ( lookAtPVold, lookAtPV, amt );
upPV2 = lerpPV ( upPVold, upPV, amt );
if (amt<1)
amt+=.025;
else
amt = 1.0;
camera (eyePV2.x, eyePV2.y, eyePV2.z,
lookAtPV2.x, lookAtPV2.y, lookAtPV2.z,
upPV2.x, upPV2.y, upPV2.z);
} //method
PVector lerpPV(PVector pvOld, PVector pvNew, float amt) {
// help function: lerp for a PVector
// lerp:
float x = lerp(pvOld.x, pvNew.x, amt);
float y = lerp(pvOld.y, pvNew.y, amt);
float z = lerp(pvOld.z, pvNew.z, amt);
return new PVector ( x, y, z );
}//method
//
}//class
//
update version of the previous sketch.
Added a new view “From Below” and a Batch Mode.
/*
New version with camera class AND smooth transitions (damping).
Demonstrates view from top down (above the sceen),
and from north, east, south and west and bottom and rotation.
The interesting part: the UP-vector when view from top.
This sketch is based on the following assumptions:
* in 3D the scene is on a table. So placing things left and right on the table is x,
* placing it more in front or in the back is Z and
* placing it above the scene (blue box) is Y.
* The center of the scene is at width/2, height/2, 0
https://discourse.processing.org/t/camera-how-top-down-view/1178/3
Remark:
going from view 2 to 4 or 1 to 3 etc. it wasn't a nice transition.
To avoid this, we have a HashMap hmBatchList which is used to make
one inbetween-view between 2 and 4 (and 4 and 2, 1 and 3 etc.), so it looks nicer.
default values are
camera(width/2.0, height/2.0, (height/2.0) / tan(PI*30.0 / 180.0),
width/2.0, height/2.0, 0,
0, 1, 0);
*/
// The core class
CameraClass cam;
// view mode and its texts :
int viewMode=3; // This var dictates the current camera mode!
String[] viewText={
"top view",
"from north",
"from east",
"from south (processing default)",
"from west",
"rotating",
"From below"
};
// keys to change views
char oldKey=' ',
currentKey=' ';
// A HashMap hmBatchList and Batch variables:
// Note the HashMap's "key" is a String and "value" is a String
HashMap<String, String> hmBatchList = new HashMap<String, String>();
String resultStringBatch=""; // Batch commands
boolean inBatchMode=false;
int inBatchCounter=0;
// -------------------------------------------------------
void setup() {
size(1500, 600, P3D);
stroke(255, 0, 0);
// set cam
cam = new CameraClass();
// set Batch list
hmBatchList.put("from2to4", "34");
hmBatchList.put("from4to2", "32");
hmBatchList.put("from1to3", "23");
hmBatchList.put("from3to1", "21");
hmBatchList.put("from0to6", "36");
hmBatchList.put("from6to0", "30");
hmBatchList.put("from0to1", "21");
hmBatchList.put("from1to0", "20");
hmBatchList.put("from6to1", "21");
hmBatchList.put("from1to6", "26");
}
void draw() {
background(0);
lights();
if (!mousePressed) {
// apply view mode
cam.apply();
//
} else {
// default (from south)
camera();
}//else
// draw scene
drawScene();
// HUD : text
camera();
fill(255);
text("Camera test: Hit 0..6 for: top view (0) / north (1) / east (2) / south (=3, processing default) / west view (4) / rotate (5) / from below (6). "
+"\nClick and hold mouse to see processing default view."
+"\nCurrent view: "
+viewText[viewMode],
15, 15);
}//func
// -------------------------------------------------------
void drawScene() {
// the sculpture
translate(width/2, height/2, 0);
fill(255); // white
box(100); // big box
// ---
translate(100, 0, 0); // right
fill(255, 0, 0); // red box
box(50);
translate(-200, 0, 0); // left
fill(0, 255, 0); // green box
box(50);
translate(100, -100, 0); // center above
fill(0, 0, 255); // blue box
box(50);
// ---
translate(0, 100, 100); // in front
fill(0, 0, 255); // blue sphere
noStroke();
sphere(12);
translate(0, 0, -200); // behind the white center box
fill(0, 255, 0); // green sphere
noStroke();
sphere(12);
// ---
translate(0, 100, 100); // behind the white center box
fill(255, 0, 0); // red sphere
noStroke();
sphere(12);
//
}
//-----------------------------------------------------------------------------
// Inputs
void keyPressed() {
// for keys from 0 to 6
oldKey=currentKey;
currentKey=key;
resultStringBatch=null;
String searchString="from"
+ trim(str(oldKey))
+ "to"
+ trim(str(currentKey));
resultStringBatch = hmBatchList.get(searchString);
// Did we get a Batch result?
if (resultStringBatch==null) {
// No
// normal: just use the key
if (key>='0'&&key<='6') {
// apply as camera mode
cam.amt=0;
viewMode=int(key+"");
setViewFromViewMode();
inBatchMode=false;
}//if
} else {
// Yes
// apply resultStringBatch as camera mode in Batch Mode
inBatchMode=true;
inBatchCounter=0;
cam.amt=0;
viewMode=int(resultStringBatch.charAt(inBatchCounter)+"");
setViewFromViewMode();
} // else
} //func
//-----------------------------------------------------------------------------
void setViewFromViewMode() {
float radius = 400.0;
cam.rotateFlag=false;
switch (viewMode) {
case 0:
// top down
cam.setEye(width/2, height/2-radius, 0);
cam.setUpVector(0, 0, 1); // Good: cam.setUpVector(0, 0, 1);
break;
case 1:
//from north
cam.setEye(width/2, height/2, -radius);
cam.setUpVectorToStandard();
break;
case 2:
//from east
cam.setEye(width/2+radius, height/2, 0);
cam.setUpVectorToStandard();
break;
case 3:
//from south // default
cam.setEye(width/2, height/2, radius);
cam.setUpVectorToStandard();
break;
case 4:
//from west
cam.setEye(width/2-radius, height/2, 0);
cam.setUpVectorToStandard();
break;
case 5:
// rotate
cam.setUpVectorToStandard();
cam.rotate();
break;
case 6:
// from below
cam.setEye(width/2, height/2+radius, 0);
cam.setUpVector(0, 0, -1);
break;
default:
// Error
println("error 55 in switch");
exit();
return;
} // switch
//
}//func
//===========================================================
class CameraClass {
// class to use the camera more easily
// standard values
final PVector eyePV_Standard = new PVector ( width/2.0, height/2.0, (height/2.0) / tan(PI*30.0 / 180.0)); // eye = camera position
final PVector lookAtPV_Standard = new PVector ( width/2, height/2, 0 ); // look At or center
final PVector upPV_Standard = new PVector ( 0, 1, 0); // the up vector for rotating the camera around itself
// the changing values:
PVector eyePV, lookAtPV, upPV;
// old PVectors
PVector eyePVold, lookAtPVold, upPVold;
// for lerp
float amt = 0;
// for rotation
boolean rotateFlag=false;
float angle=0;
// -----
// constr
CameraClass() {
eyePV = eyePV_Standard.copy();
lookAtPV = lookAtPV_Standard.copy();
upPV = upPV_Standard.copy();
eyePVold = eyePV.copy();
lookAtPVold = lookAtPV.copy();
upPVold = upPV.copy();
}//constr
// -----
// 3 set methods :
void setEye( float x, float y, float z) {
eyePVold=eyePV.copy();
eyePV=new PVector(x, y, z);
amt=0;
}
void setLookAt( float x, float y, float z) {
lookAtPVold=lookAtPV.copy();
lookAtPV=new PVector(x, y, z);
amt=0;
}
void setUpVector( float x, float y, float z) {
upPVold=upPV.copy();
// set UP vector
upPV=new PVector(x, y, z);
amt=0;
}
// ----
// 3 set methods for standard :
void setEyeToStandard() {
eyePVold=eyePV.copy();
eyePV = eyePV_Standard.copy();
amt=0;
}
void setLookAtToStandard() {
lookAtPVold=lookAtPV.copy();
lookAtPV = lookAtPV_Standard.copy();
amt=0;
}
void setUpVectorToStandard() {
upPVold=upPV.copy();
upPV = upPV_Standard.copy();
amt=0;
}
// ----
void reset() {
// reset
// store old values
eyePVold=eyePV.copy();
lookAtPVold=lookAtPV.copy();
upPVold=upPV.copy();
// reset
eyePV = eyePV_Standard.copy();
lookAtPV = lookAtPV_Standard.copy();
upPV = upPV_Standard.copy();
// set amt to 0 for lerp
amt=0;
}
void resetPVOld() {
eyePVold=eyePV.copy();
lookAtPVold=lookAtPV.copy();
upPVold=upPV.copy();
}
//----
void rotate() {
//init rotate
rotateFlag = true;
setLookAtToStandard();
}
// ----
// Tools:
void apply() {
// apply values
// rotation mode ?
if (rotateFlag) {
// rotation mode
eyePV = new PVector ( width/2.0 + cos(angle) * 400,
height/2.0,
sin(angle) * 400 ); // eye = camera position
angle+=.05;
camera (eyePV.x, eyePV.y, eyePV.z,
lookAtPV.x, lookAtPV.y, lookAtPV.z,
upPV.x, upPV.y, upPV.z);
return; // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}//if rotateFlag
// normal modes : ------------------------------
// we don't use the new values (eyePV,lookAtPV,upPV) directly but
// with eyePVold etc. and lerp (and its amt) we calculate eyePV2, lookAtPV2 and upPV2
PVector eyePV2, lookAtPV2, upPV2;
eyePV2 = lerpPV ( eyePVold, eyePV, amt );
lookAtPV2 = lerpPV ( lookAtPVold, lookAtPV, amt );
upPV2 = lerpPV ( upPVold, upPV, amt );
if (amt<1) {
amt += 0.025;
} else {
// amt is done
amt = 1.0;
// When we are in Batch Mode we go to next batch command
if (inBatchMode) {
inBatchCounter++; // go to next batch command
resetPVOld();
// if we finished the Batch
if (inBatchCounter >= resultStringBatch.length()) {
//reset
inBatchMode=false;
inBatchCounter=0;
resultStringBatch=null;
} else {
viewMode=int(resultStringBatch.charAt(inBatchCounter)+"");
setViewFromViewMode();
}//else
amt=0;
}
}
camera (eyePV2.x, eyePV2.y, eyePV2.z,
lookAtPV2.x, lookAtPV2.y, lookAtPV2.z,
upPV2.x, upPV2.y, upPV2.z);
} // method
PVector lerpPV(PVector pvOld, PVector pvNew,
float amt) {
// help function: lerp for a PVector
// lerp:
float x = lerp(pvOld.x, pvNew.x, amt);
float y = lerp(pvOld.y, pvNew.y, amt);
float z = lerp(pvOld.z, pvNew.z, amt);
return new PVector ( x, y, z );
}//method
//
}//class
//