having latitude and longitude problems with my UV Sphere

I have a UV Sphere using beginShape() with both slices and stacks (lat / lon). The idea is that I'd like to be able to transform it similar to this site: http://www.morphingbook.com/tool.html

However, I am currently having two problems:

  1. When both slices and stacks are enabled in the same loop, the UV Sphere looks like a tangled mess.
  2. When the slices and stacks are in separate loops then beginShape(QUAD_STRIP) doesn't make an outside surface mesh.

Here is my sketch:

    import controlP5.*;
    import peasy.test.*;
    import peasy.org.apache.commons.math.*;
    import peasy.*;
    import peasy.org.apache.commons.math.geometry.*;
    PeasyCam camera;
    ControlP5 cp5;
    Slider uMinSlider;
    Slider uMaxSlider;
    Slider vMinSlider;
    Slider vMaxSlider;

    /* 
     phi = u
     theta = v
     */

    float stepLat, stepLon, radius, phi, theta, u, v;
    float uMin, uMax, vMin, vMax;
    int myColor = color(255, 0, 0);

    void setup() {
      size(800, 800, P3D);
      smooth(8);
      //strokeWeight(2);
      //noFill();
      stepLat = 5;
      stepLon = 5;
      radius = width/25;

      //uMin = 0.0;
      //uMax = 2.0;
      //vMin = 0.0;
      //vMax = 2.0;
      camera = new PeasyCam(this, 0, 0, 0, width * 0.2);
      cp5 = new ControlP5(this);
      uMinSlider = cp5.addSlider("uMin");
      uMinSlider.setPosition(40, 40).setSize(200, 20).setRange(0.0, 2.0).setValue(0.0);
      uMaxSlider = cp5.addSlider("uMax");
      uMaxSlider.setPosition(40, 80).setSize(200, 20).setRange(0.0, 2.0).setValue(2.0);
      vMinSlider = cp5.addSlider("vMin");
      vMinSlider.setPosition(40, 120).setSize(200, 20).setRange(0.0, 2.0).setValue(0.0);
      vMaxSlider = cp5.addSlider("vMax");
      vMaxSlider.setPosition(40, 160).setSize(200, 20).setRange(0.0, 2.0).setValue(2.0);
      cp5.setAutoDraw(false);
    }

    void draw() {
      background(155);
      gui();
      //lights();
      //UVSPHERE
      for (float i = (degrees (vMin * PI)); i <= (degrees(vMax * PI)); i += stepLon) {
        beginShape();
        for (float j = (degrees (uMin * PI)); j <= (degrees(uMax * PI)); j += stepLat) {
          float v = i * ((2 * PI) / (degrees(2.0 * PI)));
          float u = j * ((2 * PI) / (degrees(2.0 * PI)));
          //SLICES
          float x = radius * (sin(u) * cos(v));
          float y = radius * (sin(u) * sin(v));
          float z = radius * (cos(u));
          vertex(x, y, z);
        }
        endShape();
      }
      for (float i = (degrees (vMin * PI)); i <= (degrees(vMax * PI)); i += stepLon) {
        beginShape(QUAD_STRIP);
        for (float j = (degrees (uMin * PI)); j <= (degrees(uMax * PI)); j += stepLat) {
          float v = i * ((2 * PI) / (degrees(2.0 * PI)));
          float u = j * ((2 * PI) / (degrees(2.0 * PI)));
          //STACKS
          float x2 = radius * (sin(v) * cos(u));
          float y2 = radius * (sin(v) * sin(u));
          float z2 = radius * (cos(v));  
          vertex(x2, y2, z2);
        }
        endShape();
      }
    }

    void gui() {
      camera.beginHUD();
      hint(ENABLE_DEPTH_TEST);
      cp5.draw();
      hint(DISABLE_DEPTH_TEST);
      camera.endHUD();
    }

    void controlEvent(ControlEvent theEvent) {
      //println(theEvent.getController().getId());
    }

    void button(float theValue) {
      myColor = color(random(255), random(255), random(255));
      //println("a button event. "+theValue);
    }

Answers

  • Line 67 says QUAD_STRIP but you don't look to be adding quads, only single points, which will make line loops. Try removing the argument.

    Quads would require two points per loop, with different y coords.

  • edited May 2015

    https://www.dropbox.com/sh/5o04zj93ngh15na/AAA2Oqf8OPR7VPpKz2MrN0aYa?dl=0

    OK - that helps a bit. I think I made some progress with this update, however the shape is still wrong. I'm looking for clean horizontal and vertical lats & longs:

      for (float i = (degrees (vMin * PI)); i <= (degrees(vMax * PI)); i += stepLon) {
        beginShape(QUAD_STRIP);
        for (float j = (degrees (uMin * PI)); j <= (degrees(uMax * PI)); j += stepLat) {
          float v = i * ((2 * PI) / (degrees(2.0 * PI)));
          float v2 = (i+stepLon) * ((2 * PI) / (degrees(2.0 * PI)));
          float u = j * ((2 * PI) / (degrees(2.0 * PI)));
          float u2 = (j+stepLat) * ((2 * PI) / (degrees(2.0 * PI)));
          //STACKS
          float x2 = radius * (sin(v) * cos(u));
          float x3 = radius * (sin(v2) * cos(u2));
          float y2 = radius * (sin(v) * sin(u));
          float y3 = radius * (sin(v2) * sin(u2));
          float z2 = radius * (cos(v));  
          float z3 = radius * (cos(v2));  
          vertex(x2, y2, z2);
          vertex(x3, y3, z3);
        }
        endShape();
    
  • edited May 2015

    You're changing more than just the one thing there. Try x2, y3, z3 for second point

    (Untested, am on phone)

  • When I only use one variable or combinations thereof then the mesh starts to get weird. I think something is up with the math and aligning the vertices but I'm getting stumped.

  • "starts to get weird"... maybe a picture would help?

    i don't understand why you're defining both slices and stacks. i'd've thought one or the other would be fine. i think you might just mean latitude and longitude given that your 'slices' are just lines.

    i haven't run your code (no controlP5 library, and won't have a chance until tomorrow).

  • edited May 2015

    Sure, here are some images where I switch out x2 with x3 and so on with y and z as well. Yeah the slices and stacks are just latitude and longitude.

    I feel like I must be close, just can't get it where it doesn't look like its twisting all the way up.

    It looks like these: https://www.dropbox.com/sh/5o04zj93ngh15na/AAA2Oqf8OPR7VPpKz2MrN0aYa?dl=0

    I want it to look like this, but using the code structure I have because I'd like to morph this sphere using parametric math similar to the morphingbook.com link:

  • edited May 2015

    OKAY! I think I got it now. Went in and fixed the u2 variable at the sin*cos definition of x,y.

    If you don't mind I'd love a little critique and comment. This is what the sphere looks like now along with the code:

    import controlP5.*;
    import peasy.test.*;
    import peasy.org.apache.commons.math.*;
    import peasy.*;
    import peasy.org.apache.commons.math.geometry.*;
    PeasyCam camera;
    ControlP5 cp5;
    Slider uMinSlider;
    Slider uMaxSlider;
    Slider vMinSlider;
    Slider vMaxSlider;
    //Cameras camcam;
    
    /** 
     phi = u
     theta = v
     */
    
    float stepLat, stepLon, radius, phi, theta, u, v;
    float uMin, uMax, vMin, vMax, u2Mult, v2Mult;
    int myColor = color(255, 0, 0);
    
    void setup() {
      size(1000, 1000, OPENGL);
      smooth(8);
      strokeWeight(2);
      //noFill();
      radius = width/20;
    
      camera = new PeasyCam(this, 0, 0, 0, width * 0.2);
      //camcam = new Cameras();
      cp5 = new ControlP5(this);
      uMinSlider = cp5.addSlider("uMin");
      uMinSlider.setPosition(40, 40).setSize(200, 20).setRange(0.0, 2.0).setValue(0.0);
      uMaxSlider = cp5.addSlider("uMax");
      uMaxSlider.setPosition(40, 60).setSize(200, 20).setRange(0.0, 2.0).setValue(2.0);
      vMinSlider = cp5.addSlider("vMin");
      vMinSlider.setPosition(40, 80).setSize(200, 20).setRange(0.0, 2.0).setValue(0.0);
      vMaxSlider = cp5.addSlider("vMax");
      vMaxSlider.setPosition(40, 100).setSize(200, 20).setRange(0.0, 2.0).setValue(2.0);
      vMaxSlider = cp5.addSlider("stepLat");
      vMaxSlider.setPosition(40, 120).setSize(200, 20).setRange(0, 50).setValue(5);
      vMaxSlider = cp5.addSlider("stepLon");
      vMaxSlider.setPosition(40, 140).setSize(200, 20).setRange(0, 50).setValue(5);
      vMaxSlider = cp5.addSlider("v2Mult");
      vMaxSlider.setPosition(40, 160).setSize(200, 20).setRange(0, 50).setValue(1);
      vMaxSlider = cp5.addSlider("u2Mult");
      vMaxSlider.setPosition(40, 180).setSize(200, 20).setRange(0, 50).setValue(0);
      cp5.setAutoDraw(false);
    }
    
    void draw() {
      background(155);
      gui();
      lights();
      //camcam.draw();
    
      for (float i = (degrees (vMin * PI)); i <= (degrees(vMax * PI)); i += stepLon) {
        beginShape(QUAD_STRIP);
        for (float j = (degrees (uMin * PI)); j <= (degrees(uMax * PI)); j += stepLat) {
          float v = i * ((2 * PI) / (degrees(2.0 * PI)));
          float u = j * ((2 * PI) / (degrees(2.0 * PI)));
          float v2 = (i + (stepLon * v2Mult)) * ((2 * PI)  / (degrees(2.0 * PI)));
          //u2Mult = 0 for a UVSPHERE
          float u2 = (j + (stepLat * u2Mult)) * ((2 * PI) / (degrees(2.0 * PI)));
          //THESE DO OTHER COOL THINGS!
          //float v2 = (i += stepLon) * ((2 * PI)  / (degrees(2.0 * PI)));
          //float u2 = (j += stepLat) * ((2 * PI) / (degrees(2.0 * PI)));
          float x2 = radius * (cos(v) * sin(u));
          float y2 = radius * (cos(v) * cos(u));
          float z2 = radius * (sin(v));  
          float x3 = radius * (cos(v2) * sin(u2));
          float y3 = radius * (cos(v2) * cos(u2));
          float z3 = radius * (sin(v2));   
          stroke(255, 200, 200);
          fill(200, 155, 155);     
          vertex(x2, y2, z2);
          stroke(200, 200, 255);
          fill(155, 155, 200);
          vertex(x3, y3, z3);
        }
        endShape();
      }
    }
    
    void gui() {
      camera.beginHUD();
      hint(ENABLE_DEPTH_TEST);
      cp5.draw();
      hint(DISABLE_DEPTH_TEST);
      camera.endHUD();
    }
    
    void controlEvent(ControlEvent theEvent) {
      //println(theEvent.getController().getId());
    }
    
    void button(float theValue) {
      myColor = color(random(255), random(255), random(255));
      //println("a button event. "+theValue);
    }
    
    class Cameras {
    
      Cameras() {
      }
    
      void draw() {
        translate(width/2, height/2);
    
        rotateX((radians(frameCount)));
        rotateY((radians(frameCount)));
        rotateZ((radians(frameCount)));
    
        /**
      if (mousePressed == true) {
         rotateX(TWO_PI*mouseY / width);
         rotateY(TWO_PI*mouseX / width);
         }
         */
      }
    }
    

Sign In or Register to comment.