Hi everyone,
I’m trying to zoom in on a sphere. Instead of zooming in from the center I would like to zoom in such a way that the red square stays in the yellow ellipse.
What would be a good way to achieve this do you think?
float r = 400;
void setup() {
size(800, 800, P3D);
smooth();
}
void draw() {
background(0);
ortho();
translate(width/2, height/2);
float scaler = map(mouseY, 0, height, 1, 1.5);
//draw sphere with red box
pushMatrix();
scale(scaler);
rotateX(-.7);
//how should I rotate back here to correct for zoom
//so that the red box stays within the yellow ellipse?
noFill();
strokeWeight(1);
fill(128);
stroke(255);
sphere(r);
strokeWeight(10);
noStroke();
fill(255, 0, 0);
translate(0, 0, r);
box(20);
popMatrix();
//draw yellow circle
hint(DISABLE_DEPTH_TEST);
rotateX(-.7);
translate(0, 0, r);
noFill();
strokeWeight(2);
stroke(255,255,0);
ellipse(0, 0, 40, 40);
hint(ENABLE_DEPTH_TEST);
}
1 Like
Hi Rick,
I think, below is a solution of what you want to achieve. This might not be the only solution and might also be optimized somehow.
float r = 400;
void setup() {
size(800, 800, P3D);
smooth();
}
void draw() {
background(0);
ortho();
translate(width/2, height/2);
float scaler = map(mouseY, 0, height, 1, 1.5);
// calculate screen position of the red box
pushMatrix();
scale(scaler);
rotateX(-.7);
translate(0, 0, r);
float redY = screenY(0, 0, 0);
popMatrix();
// calculate screen position of yellow circle
pushMatrix();
rotateX(-.7);
translate(0, 0, r);
float yellowY = screenY(0, 0, 0);
popMatrix();
float dy = yellowY - redY;
//draw sphere with red box
pushMatrix();
translate(0, dy, 0); // move the sphere
scale(scaler);
rotateX(-.7);
//how should I rotate back here to correct for zoom
//so that the red box stays within the yellow ellipse?
noFill();
strokeWeight(1);
fill(128);
stroke(255);
sphere(r);
strokeWeight(10);
noStroke();
fill(255, 0, 0);
translate(0, 0, r);
box(20);
popMatrix();
//draw yellow circle
hint(DISABLE_DEPTH_TEST);
rotateX(-.7);
translate(0, 0, r);
noFill();
strokeWeight(2);
stroke(255,255,0);
ellipse(0, 0, 40, 40);
hint(ENABLE_DEPTH_TEST);
}
2 Likes
quark
October 23, 2019, 10:23am
3
I assume the red square is a position on the sphere and its 3D coordinates are [rx, ry, rz] if my assumption is correct then this might work
translate(width/2, height/2);
Get the screen position with screenX(rx, ry, rz) and screenY(rx, ry, rz)
translate to the calculated position
scale the screen
draw the sphere
You might have to play with the translation and scaling in steps 3 & 4
2 Likes
Hi @bohnacker and @quark ,
Thank you so much for your help. It works! Here is my updated example where you can see it also working for a moving target (mouse on sphere)
Here’s the updated code:
float scaler = 1;
float r = 400;
void setup() {
size(800, 800, P3D);
smooth();
}
void draw() {
background(0);
ortho();
translate(width/2, height/2);
//mouse on sphere
PVector p = new PVector(mouseX-width/2,mouseY-height/2);
p.z = sqrt(r*r - p.mag());
//calculate screen position of the mouse in scaled and unscaled mode
pushMatrix();
PVector unscaled = new PVector(screenX(p.x, p.y, p.z), screenY(p.x, p.y, p.z));
scale(scaler);
PVector scaled = new PVector(screenX(p.x, p.y, p.z), screenY(p.x, p.y, p.z));
popMatrix();
PVector delta = unscaled.sub(scaled);
//draw sphere and mouse on sphere
pushMatrix();
translate(delta.x, delta.y, 0);
scale(scaler);
noFill();
stroke(255);
strokeWeight(1);
sphere(r);
noStroke();
fill(255, 0, 0);
translate(p.x, p.y, p.z);
box(20);
popMatrix();
saveFrame();
}
void mouseWheel(MouseEvent event) {
//zoom factor needs to be between about 0.99 and 1.01 to be able to multiply so add 1
scaler = constrain(scaler * (-event.getCount()*.01f + 1.0f), 1, 1.7);
}
1 Like