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