Shapes3D is beyond Coool : But can I do dynamic textures

edited December 2017 in Library Questions

I'm using Shapes3D with Processing 2. I downloaded a starmap and used the library to project onto an ellipsoid as a texture. If I zoom into the ellipsoid, I get a planetarium view of the stars. Now, that's so cool but what I want to do is add some arcs. I successfully connected my 9 DOF IMU and can rotate the view in pitch,roll,yaw. I basically have a sextant and I want to point at a star and get the Right Ascension and Declination. I tilted the ellipsoid to my current latitude(actually, 90-lat) and when I point at Polaris, the IMU pitch reads my latitude within .05 of a degree.

The library question is how can I draw arcs onto the ellipsoid? Do I have to "extend" or "Override" one or more of the shapes3D classes? My java skills are sketchy, but determined and growing.

«1

Answers

  • Answer ✓

    The library does not provide methods to draw directly onto the surface but the easiest way is simple draw on the texture image.

    Assuming you have loaded an PImage called original using loadImage then create a PGraphics object which is a copy of the texture image like this.

    PImage original;
    PGraphics texture;
    Ellipsoid starBall;
    
    void setup(){
      size(480, 320, P3D);
      // create the star ball here
      original = loadImage("filename.png");
      texture = createGraphics(original.width, original.height);
      initStars();
      starBall.setTexture(texture);
    }
    
    // Call this method to reset the star map
    void initStars(){
      texture.beginDraw();
      texture.image(original); // draw the image into the graphics object
      texture.endDraw();
    }
    
    // Example method showing how to modify the texture
    // could be called from mouse click or other event handler.
    void addDiagonalLine(){
      texture.beginDraw();
      texture.stroke(255,255,0); // yellow
      texture.strokeWeight(3); // need some weight to make sure it shows
      texture.line(0,0,texture.width, texture.height);
      texture.endDraw();
    }
    

    BEWARE: I have just typed this code into the forum so may have some syntax errors.

    OK final point, since you are viewing the star map from the inside of the ellipsoid it may look reversed. (Shapes3D draws textures as if viewed from outside the object) if this is the case then simple reverse the star map image in a graphics program, it will also affect the end points of any arcs.

    Hope this helps.

  • Thanks, I'll give drawing on the image a try. It will probably lead to more wonder and questions. I appreciate your awesome work and help. I noticed early what you say about image being reversed if viewed from inside the ellipsoid, letters were backwards. MSpaint fixed that. I originally tried projecting NASA images(reversed? who could tell) of Iapetus and Encelada from Cassini mission. That was how I accidentally realized I could zoom inside the ellipsoid and then I was off finding star maps and playing with an IMU.

    you call it starBall, ha,ha.

  • edited November 2017

    OK, that worked. The more I think about what I want the more confused I get. The diagonal line function goes across the stars at an equal angle from one corner to the opposite which I think makes it an Ioxadrome. If I draw it from the top to the bottom parallel to longitude, it is a great circle. I'll have to play around with it to get what I'm after.

    Thanks, I never would have thought to draw on the original as you suggested.

  • edited December 2017

    Here is a screenshot of drawing some lat and lon lines on Enceladus.

  • Next I'll add some Pvectors and points.

  • Nice one!

  • edited November 2017

    In case anyone wants to do something similar, here's what I added to your addDiagonalLine() function.

    void addDiagonalLine(){
      texture.beginDraw();
      texture.stroke(255,0,0);
      texture.strokeWeight(2);
      
     //longitude lines
      texture.line(0,0,0, texture.height);
      texture.line(texture.width/12, 0,texture.width/12,texture.height);
      texture.line(texture.width/12 * 2, 0,texture.width/12 * 2,texture.height);
      texture.line(texture.width/12 * 3, 0,texture.width/12 * 3,texture.height);
      texture.line(texture.width/12 * 4, 0,texture.width/12 * 4,texture.height);
      texture.line(texture.width/12 * 5, 0,texture.width/12 * 5,texture.height);
      texture.line(texture.width/12 * 6, 0,texture.width/12 * 6,texture.height);
      texture.line(texture.width/12 * 7, 0,texture.width/12 * 7,texture.height);
      texture.line(texture.width/12 * 8, 0,texture.width/12 * 8,texture.height);
      texture.line(texture.width/12 * 9, 0,texture.width/12 * 9,texture.height);
      texture.line(texture.width/12 * 10, 0,texture.width/12 * 10,texture.height);
      texture.line(texture.width/12 * 11, 0,texture.width/12 * 11,texture.height);
    //latitude lines  
      texture.line(0, texture.height/2,texture.width,texture.height/2);
      texture.line(0, texture.height/2/3,texture.width,texture.height/2/3);
      texture.line(0, texture.height/2/3 * 2,texture.width,texture.height/2/3 * 2);
      texture.line(0, texture.height - texture.height/2/3 * 2,texture.width,texture.height -texture.height/2/3 * 2);
      texture.line(0, texture.height -texture.height/2/3,texture.width,texture.height -texture.height/2/3);
      texture.endDraw();
    }
    
    

  • Here is another screenshot of a starmap downloaded from NASA and projected onto a Shapes3D ellipsoid. For comparison and identification, another shot of a star identification chart from the Air Almanac.

  • edited December 2017

    Thanks so much for sharing this, @HarryCodes.

    Could you give an example URL of a starmap image that you downloaded, so that people could try playing with the technique?

    I'm assuming that this technique working depends on the image using a specific projection format.

  • Here'[s where I got the star map image. Make sure it uses celestial coordinates and not galactic. https://svs.gsfc.nasa.gov/cgi-bin/details.cgi?aid=3895

    Here's another linkimg.4plebs.org/boards/pol/image/1474/59/1474593316124.png that shows a map with borders, which is typical when searching for maps. I tried a few and with varying success cropped out the borders. If not carefully cropped, you get a line where left and right sides meet. I didn't pay much attention to the map projection as long as it looks like coverage is 360 degrees.

    BTW, shapes3D does all the heavy lifting.

  • edited December 2017

    I took the image from the second link above and cropped it. If you look carefully at the latitude lines, the ones I added don't quite match up with the map. This is because I didn't crop it exactly going vertically and left some slop. Plus, you can see what quark was warning about the image being reversed. This image is reversed on the outside but from inside the ellipsoid it is not.

    What I want to do now is sync the rotation using rotateBy() with system time and longitude. Then when I start the sketch, it will always be oriented according to my time and location.

  • Exciting -- thanks for sharing these examples, great progress!

    You can also reverse your image in Processing dynamically.

    For example, if you wanted to pass the camera through the sky to see it from the outside, you could draw two spheres with almost the same radius (with a small gap between them). The inside one can be textured to view from the inside, the outside image can be reversed to be viewed from the outside.

  • Others may find this discussion useful so I have modified the title to make it more likely to be hit when searching on textures.

  • edited December 2017

    Two spheres works! The radii differ by 1. Enter at the north pole and bam, looking at the south pole. Except, there is something goofy. Its as if the camera immediately turns 180. For instance, I entered at the constellation Orion and should see the "antipode", Sagitarius. Instead, I see Orion again, thus the camera swung 180 on entry. Now if I zoom all the way in the opposite direction, everything flips and Sagitarius appears but Orion is now backwards when I zoom out.

    I don't think I can get the camera view correct.

  • I got it! I flipped the second texture and rotated It 180. Now I can enter at wherever and once inside see the antipode.

  • Glad it worked, @HarryCodes!

    Would you be willing to share the flip/rotation code you used that worked for you for others interested in this approach?

  • I'll post what I have soon, but I just used MSpaint to flip and flop the images and then " starBall2.rotateTo(0,radians(-180f),0) " to get the second texture right.

  • edited December 2017

    I said I wanted to sync the star map with system time and longitude. I borrowed from the Processing clock example and it rotates. The problem is it only moves once a minute And the real night sky rotates faster(slower? I don't know, its different and may vary) than a clock by about 2 minutes per (day?)hour.

    `

    float t = map(hour() + norm(minute(),0,60) ,0,24,0,TWO_PI) - radians(77.4f);
    starBall.rotateTo(0,t,0);
    
    

    `

    Well, duh, I added norm(second(),0,3600) to hour() and norm minute() and it moves once a second. I guess I can just add a correction to t to speed it up, by mapping the extra 2 minutes per hour to 0 and TWO_PI. Its hard to test because I cant just let it run for 24 hours, it runs out of memory.

  • re:

    it runs out of memory.

    What do you mean? What is using up memory? What is the specific error message?

  • You can increase the memory in the settings maybe that helps

    Not sure why it runs out of memory in the first place though

  • Yeah, it stops after about 2 hours. The error says Out of Memory:Java Heap Space. I had a similar problem when I tried using a .jpg that was too big and it couldn't load it.

    As for the difference in time between a clock day and a star day, I'll pretend 15 degrees per hour is exact.

  • @HarryCodes consider sharing your code -- this could be a bug in Processing, but is it possible that you are constantly creating / loading an increasing list of new objects in your draw loop?

  • edited December 2017

    Here's what I have so far:

    `

    import shapes3d.utils.*;
    import shapes3d.animation.*;
    import shapes3d.*;
    
    import java.awt.event.*;
    
    PImage original;
    PImage original2;
    PGraphics texture;
    PGraphics texture2;
    Ellipsoid starBall;
    Ellipsoid starBall2;
    float zoom = 0.5;
    
    
    
    
    public void setup() {
    
      size(1275, 750, P3D);
      
        
      original = loadImage("100lightyears.jpg");
      original2 = loadImage("100lightyears2.jpg");
      frame.addMouseWheelListener(new MouseWheelInput());
      texture = createGraphics(original.width, original.height);
      texture2 = createGraphics(original2.width, original2.height);
      initStars();
      starBall = new Ellipsoid(this, 64, 64);
      starBall.setTexture(texture);
      starBall.setRadius(400);
      starBall.drawMode(Shape3D.TEXTURE); 
     
      starBall2 = new Ellipsoid(this, 64, 64);
      starBall2.setTexture(texture2);
      starBall2.setRadius(399);
      starBall2.drawMode(Shape3D.TEXTURE);
     
    
    }
    
    void initStars(){
      texture.beginDraw();
      texture.image(original,0,0);
      texture2.image(original2,0,0);
      texture.endDraw();
    }
    
    void addDiagonalLine(){
      texture.beginDraw();
      texture.stroke(255,0,0);
      texture.strokeWeight(2);
      
     //longitude lines
      texture.line(0,0,0, texture.height);
      texture.line(texture.width/12, 0,texture.width/12,texture.height);
      texture.line(texture.width/12*2, 0,texture.width/12*2,texture.height);
      texture.line(texture.width/12*3, 0,texture.width/12*3,texture.height);     
      texture.line(texture.width/12*4, 0,texture.width/12*4,texture.height);
      texture.line(texture.width/12*5, 0,texture.width/12*5,texture.height);
      texture.line(texture.width/12*6, 0,texture.width/12*6,texture.height);
      texture.line(texture.width/12*7, 0,texture.width/12*7,texture.height);
      texture.line(texture.width/12*8, 0,texture.width/12*8,texture.height);
      texture.line(texture.width/12*9, 0,texture.width/12*9,texture.height);
      texture.line(texture.width/12*10, 0,texture.width/12*10,texture.height);
      texture.line(texture.width/12*11, 0,texture.width/12*11,texture.height);
      texture.line(texture.width/12 * 11 -texture.width/12/3, 0,texture.width/12 * 11 -texture.width/12/3,texture.height);
     
    
      texture.line(texture.width/12 -texture.width/12/2, 0,texture.width/12 -texture.width/12/2,texture.height);
      texture.line(texture.width/12+texture.width/12/2, 0,texture.width/12+texture.width/12/2,texture.height);
      texture.line(texture.width/12/2+texture.width/12/2, 0,texture.width/12/2+texture.width/12/2,texture.height);
      texture.line(texture.width/12 * 2+texture.width/12/2, 0,texture.width/12 * 2+texture.width/12/2,texture.height);
     
      texture.line((texture.width/12 * 3)+texture.width/12/2, 0,(texture.width/12 * 3)+texture.width/12/2,texture.height);
      texture.line((texture.width/12 * 4)+texture.width/12/2, 0,(texture.width/12 * 4)+texture.width/12/2,texture.height);
      texture.line((texture.width/12 * 5)+texture.width/12/2, 0,(texture.width/12 * 5)+texture.width/12/2,texture.height);
      texture.line((texture.width/12 * 6)+texture.width/12/2, 0,(texture.width/12 * 6)+texture.width/12/2,texture.height);
      texture.line((texture.width/12 * 7)+texture.width/12/2, 0,(texture.width/12 * 7)+texture.width/12/2,texture.height);
      texture.line((texture.width/12 * 8)+texture.width/12/2+texture.width/12/3, 0,(texture.width/12 * 8)+texture.width/12/2+texture.width/12/3,texture.height);//////////////
      texture.line((texture.width/12 * 9)+texture.width/12/2, 0,(texture.width/12 * 9)+texture.width/12/2,texture.height);
      texture.line((texture.width/12 * 10)+texture.width/12/2, 0,(texture.width/12 * 10)+texture.width/12/2,texture.height);
      texture.line((texture.width/12 * 11)+texture.width/12/2, 0,(texture.width/12 * 11)+texture.width/12/2,texture.height);
      
    
     
    
    
    //latitude lines  
      texture.line(0, texture.height/2,texture.width,texture.height/2);
      texture.line(0, texture.height/2/3,texture.width,texture.height/2/3);
      texture.line(0, texture.height/2/3 * 2,texture.width,texture.height/2/3 * 2);
      texture.line(0, texture.height - texture.height/2/3 * 2,texture.width,texture.height -texture.height/2/3 * 2);
      texture.line(0, texture.height -texture.height/2/3,texture.width,texture.height -texture.height/2/3); 
      texture.endDraw();
    }
    
    public void draw() {
    
      background(0);  
     
     translate(width/2, height/2);
     pushStyle();
     float r = -0.01 * (mouseY - 500);
     rotateX(r); 
       
      float s = map(second(), 0, 60, 0, TWO_PI);
      float m = map(minute() + norm(second(), 0, 60), 0, 60, 0, TWO_PI); 
      float h = map(hour() + norm(minute(), 0, 60), 0, 24, 0, TWO_PI * 2)- HALF_PI;
      float t = map(hour() + norm(minute(),0,60)+ norm(second(), 0, 3600) ,0,24,0,TWO_PI) - radians(77.4f);
      scale(zoom, -zoom, zoom);
      addDiagonalLine();
      starBall.rotateTo(0,t,0);
      System.out.println(degrees(h));
      starBall2.rotateTo(0,t -radians(-180f),0);
      starBall.draw();
      starBall2.draw();
    
    
    
    
     
      }           
             
    
    
    
    
    class MouseWheelInput implements MouseWheelListener{
      void mouseWheelMoved(MouseWheelEvent e) {
        zoom -= 0.15 * e.getWheelRotation();
    
      }
    }

    `

  • edited December 2017

    Hmm. First guesses without running:

    • Is addDiagonalLine() supposed to be redrawing texture each frame, or adding more even more lines to texture each time?
    • Is System.out.println(degrees(h)) expending memory?

    You could try commenting them out and cranking up the frameRate to hopefully get a crash faster (like 1 hr, or 30 minutes). If the current bugged version shows increasing RAM use over time under inspection, then you can also see what causes that behavior to stop without waiting until the heap is full.

    ...but I'm no Java debugging expert, others may have better advice...?

  • Answer ✓

    In line 103 you have used pushStyle which will save the current drawing style but you do not have a matching popStyle, this is your memory leak.

    Also as pointed out the method addDiagonalLine only needs to be executed once because there are no changes between calls to this method.

  • edited December 2017

    Thanks, I got rid of the pushStyle which came from another sketch and I moved addDiagonalLine to setup.

    I think that fixed it. I thought it crapped out again, but I was running the old version.

    I tested the orientation of the map by comparing to an online planetarium and I needed to subtract HALF_PI from t. I guess if you live east of Greenwich, then you add your longitude and still subtract Pi/2.

  • edited December 2017

    Interesting -- a mismatched pushStyle() in e.g. a loop normally crashes the sketch in moments due to a matrix stack overflow. I didn't realize it could leak like that without maxing out the number of stack layers if it was open at the end of draw()

    Edit: Not accurate -- mismatched pushMatrix() crashes; mismatched pushStyle() consumes memory -- see @quark explanation below.

  • I let it run while I went to work, and it stopped when Dubhe(big dipper) was about 45 degrees from meridian. That's about 7 hours running which is a big improvement over only 2 hours but something is still using up memory. The error message is slightly different now and has hints and instructions about images being loaded thousands of times and try increasing available memory.

    In any case, I'm pretty happy with the accuracy. I used Interactive Computer Ephemeris and calculated meridian passage for a few stars and was within a minute the best I could tell.

  • Man, I am stupid. I just looked at the version I am running and the pushStyle() was in there again. I deleted and saved and running it again.

  • @jeremydouglass pushStyle() is part of the Processing API and when called creates a PStyle object which holds the current drawing variable status and then pushes it onto an expandable array (uses PApllet.expand(...)). Processing has no upper size constraint on the style array.

    It should not be confused with pushMatrix() which stores an OpenGL transformation matrix on a stack, the maximum size depends on the OpenGL implementation but all will throw an exception if we attempt to exceed it.

  • edited December 2017

    Its been running for 8+ hours and no problem, honest, no errant pushStyle(). I have added something though and that is a gnomon(meridian line) at line 103 I added:

    stroke(0, 255, 0); strokeWeight(1); line(0,-500,0 , 0, 500, 0);

  • I've been studying and experimenting with this, including porting to android which is where I use my IMU connected to serial. I use Interactive Computer Ephemeris, running on a DOS Emulator, to get navigation stuff on a star like meridian passage. Then I compare this to what my star clock shows. My clock and IMU always agrees with the GHA(Greenwich Hour Angle), SHA(Sidereal Hour Angle) and declination, but the ephemeris also gives the altitude(sighting) and this is where things always differ and I don't know why. Its just a few degrees and refraction, parallax, usual corrections don't add up to the difference.

  • Is the amount a constant offset, or is it cumulative? It sounds like it is constant...?

  • I think I see it now. Heres a little experiment I set up. At 1000(GMT), ICE(ephemeris) says Dubhe will be observed at a corrected altitude(Hc) of 67 02.4' . This of course is calculated for My latitude. I observed 27.6, measured from the celestial pole and Not the horizon. 67 - 27 = 40 and that is my latitude. I thought I could subtract Hc from 90 and get 27, but that gives 23, a difference of 4. That constant difference is what puzzled me.

  • Its probably not actually constant but varies from horizon to zenith within a small range that doesn't add up to 90 degrees. If I want to do something more useful with this, I need to understand what I'm looking at.

  • Aha, I will read up on spherical trigonometry. A spherical triangle does not add up to 180. I'm probably seeing that?

  • Good detective work: a spherical triangle definitely does not add up to 180!

    You might want the equation for spherical excess:

    1. http://mathworld.wolfram.com/SphericalTriangle.html
    2. http://mathworld.wolfram.com/SphericalExcess.html
  • edited December 2017

    Awesome links, thanks. I'll work on that. My star clock is basically like the image in the first link. I am inside that sphere at (0,0,0) instead of on the surface. They mention an inner and outer triangle. I suspect I'm measuring with my IMU an angle that is part of a different triangle.

    One thing always leads to another. This link looks more like my star clock. demonstrations.wolfram.com/SphericalTrigonometryOnAGnomonicProjection/

  • I realize what caused my confusion on this and it is from reading a manual on celestial navigation, which said that the zenith distance(my clock/IMU is setup to measure that) and H(altitude) are complements and add up to 90. I wasn't seeing that, hence the spherical trig quest.

    Brushing up on spherical trig is awesome but not totally necessary to get a reading that agrees with ICE(ephemeris). Originally, I tilted the sphere at 90 - Lat and got an accurate reading. I changed the tilt to 90 degrees to get it looking like a typical gnomonic projection. I've gone back to 90 - Lat and it works at more than just meridian passage - (special case of Spherical Excess = 0 ? ).

  • edited December 2017

    I had to step back from this but not totally. I changed gears and worked on adding some controlP5 stuff. I came up with an interesting version of TextureSphere which uses sliders and/or mouse to rotate a sphere and it uses quark's texture trick to add lat and lon lines. TextureSphere came from Processing 3 android mode examples, so it does run on android or java mode.

    `

    /**
     * Texture Sphere 
     * by Mike 'Flux' Chang (cleaned up by Aaron Koblin). 
     * Based on code by Toxi. 
     * 
     * A 3D textured sphere with simple rotation control.
     * Note: Controls will be inverted when sphere is upside down. 
     * Use an "arc ball" to deal with this appropriately.
     */ 
    
    // The next line is needed if running in JavaScript Mode with Processing.js
    /* @pjs preload="world32k.jpg"; */ 
    
    import controlP5.*;
    
    PImage bg;
    PImage texmap;
    PGraphics texture;
    
    ControlP5 cp5;
    int sliderValue = 10;
    int sliderValue2 = 10;
    
    int sDetail = 65;  // Sphere detail setting
    float rotationX = 0;
    float rotationY = 0;
    float velocityX = 0;
    float velocityY = 0;
    float globeRadius = 600;
    float pushBack = 0;
    
    float[] cx, cz, sphereX, sphereY, sphereZ;
    float sinLUT[];
    float cosLUT[];
    float SINCOS_PRECISION = 0.5;
    
    int SINCOS_LENGTH = int(360.0 / SINCOS_PRECISION);
    
    color [] colors = new color[7];
    
    
    void setup() {
      //  fullScreen(P3D);
    //  size(640, 360, P3D);
        size(1275, 750, P3D);
     
       cp5 = new ControlP5(this);
    
      cp5.addSlider("sliderX")
         .setRange(0,360)
         .setValue(120)
         .setPosition(100,200)
         .setSize(200,50)
         ;
         
           cp5.addSlider("sliderY")
         .setRange(0,360)
         .setValue(120)
         .setPosition(100,500)
         .setSize(50,200)
         ;
         
      orientation(LANDSCAPE);  
      texmap = loadImage("world32k.jpg"); 
        texture = createGraphics(texmap.width, texmap.height);
      initStars();
      addDiagonalLine();
      initializeSphere(sDetail);
    }
    
    void draw() {    
      background(0);            
      renderGlobe(); 
    }
    
    void initStars(){
      texture.beginDraw();
      texture.image(texmap,0,0);
    
      texture.endDraw();
    }
    
    void addDiagonalLine(){
      texture.beginDraw();
      texture.stroke(0,0,0);
      texture.strokeWeight(1);
      
     //longitude lines
      texture.line(0,0,0, texture.height);
      texture.line(texture.width/12, 0,texture.width/12,texture.height);
      texture.line(texture.width/12*2, 0,texture.width/12*2,texture.height);
      texture.line(texture.width/12*3, 0,texture.width/12*3,texture.height);     
      texture.line(texture.width/12*4, 0,texture.width/12*4,texture.height);
      texture.line(texture.width/12*5, 0,texture.width/12*5,texture.height);
      texture.line(texture.width/12*6, 0,texture.width/12*6,texture.height);
      texture.line(texture.width/12*7, 0,texture.width/12*7,texture.height);
      texture.line(texture.width/12*8, 0,texture.width/12*8,texture.height);
      texture.line(texture.width/12*9, 0,texture.width/12*9,texture.height);
      texture.line(texture.width/12*10, 0,texture.width/12*10,texture.height);
      texture.line(texture.width/12*11, 0,texture.width/12*11,texture.height);
    /////  texture.line(texture.width/12 * 11 -texture.width/12/3, 0,texture.width/12 * 11 -texture.width/12/3,texture.height);
     
    
      texture.line(texture.width/12 -texture.width/12/2, 0,texture.width/12 -texture.width/12/2,texture.height);
      texture.line(texture.width/12+texture.width/12/2, 0,texture.width/12+texture.width/12/2,texture.height);
      texture.line(texture.width/12/2+texture.width/12/2, 0,texture.width/12/2+texture.width/12/2,texture.height);
      texture.line(texture.width/12 * 2+texture.width/12/2, 0,texture.width/12 * 2+texture.width/12/2,texture.height);
     
      texture.line((texture.width/12 * 3)+texture.width/12/2, 0,(texture.width/12 * 3)+texture.width/12/2,texture.height);
      texture.line((texture.width/12 * 4)+texture.width/12/2, 0,(texture.width/12 * 4)+texture.width/12/2,texture.height);
      texture.line((texture.width/12 * 5)+texture.width/12/2, 0,(texture.width/12 * 5)+texture.width/12/2,texture.height);
      texture.line((texture.width/12 * 6)+texture.width/12/2, 0,(texture.width/12 * 6)+texture.width/12/2,texture.height);
      texture.line((texture.width/12 * 7)+texture.width/12/2, 0,(texture.width/12 * 7)+texture.width/12/2,texture.height);
      texture.line((texture.width/12 * 8)+texture.width/12/2, 0,(texture.width/12 * 8)+texture.width/12/2,texture.height);//////////////
      texture.line((texture.width/12 * 9)+texture.width/12/2, 0,(texture.width/12 * 9)+texture.width/12/2,texture.height);
      texture.line((texture.width/12 * 10)+texture.width/12/2, 0,(texture.width/12 * 10)+texture.width/12/2,texture.height);
      texture.line((texture.width/12 * 11)+texture.width/12/2, 0,(texture.width/12 * 11)+texture.width/12/2,texture.height);
      
    
     
    
    
    //latitude lines  
      texture.line(0, texture.height/2,texture.width,texture.height/2);
      texture.line(0, texture.height/2/3,texture.width,texture.height/2/3);
      texture.line(0, texture.height/2/3 * 2,texture.width,texture.height/2/3 * 2);
      texture.line(0, texture.height/2/6,texture.width,texture.height/2/6 );
      texture.line(0, texture.height/2/3 + texture.height/2/6,texture.width,texture.height/2/3 + texture.height/2/6);
      texture.line(0, texture.height/2/3 * 2 + texture.height/2/6 ,texture.width,texture.height/2/3 * 2 + texture.height/2/6);
      texture.line(0, texture.height/2 + texture.height/2/3/2 ,texture.width,texture.height/2 + texture.height/2/3/2);
      texture.line(0, texture.height/2 -texture.height/2/3 ,texture.width,texture.height/2 -texture.height/2/3);
      texture.line(0, texture.height - texture.height/2/3 * 2,texture.width,texture.height -texture.height/2/3 * 2);
      texture.line(0, texture.height -texture.height/2/3,texture.width,texture.height -texture.height/2/3);
      texture.line(0, texture.height - texture.height/2/3 * 2 + texture.height/2/6,texture.width,texture.height -texture.height/2/3 * 2 + texture.height/2/6);
      texture.line(0, texture.height -texture.height/2/3 + texture.height/2/6,texture.width,texture.height -texture.height/2/3 + texture.height/2/6); 
      texture.endDraw();
    }
    
    void renderGlobe() {
      pushMatrix();
     // translate(width * 0.33, height * 0.5, pushBack);
      translate(width/2, height/2, pushBack);
      pushMatrix();
      noFill();
      stroke(255,200);
      strokeWeight(2);
      smooth();
      popMatrix();
      lights();    
      pushMatrix();
      rotateX( radians(-rotationX) );
    rotateX( radians(-sliderValue2) );  
      rotateY( radians(270 - rotationY) );
      rotateY( radians(270 - sliderValue) );
      fill(200);
      noStroke();
      textureMode(IMAGE);  
    //  texturedSphere(globeRadius, texmap);
       texturedSphere(globeRadius, texture);
      popMatrix();  
      popMatrix();
      rotationX += velocityX;
      rotationY += velocityY;
      velocityX *= 0.95;
      velocityY *= 0.95;
      
      // Implements mouse control (interaction will be inverse when sphere is  upside down)
      if(mousePressed){
        if(mouseY < height/2){ //confines mouse to upper screen half
       velocityX += (mouseY-pmouseY) * 0.01;
        }
        if (mouseX > width/2){ //confines mouse to right screen half
       velocityY -= (mouseX-pmouseX) * 0.01;
        }
      }
    
    }
    void controlEvent(ControlEvent Event) {
    
     
     if(Event.isController()) { 
     
     print("control event from : "+Event.getController().getName());
     println(", value : "+Event.getController().getValue());
     
     if(Event.getController().getName()=="sliderX") {
     sliderValue2 = (int)Event.getController().getValue();
     
    // colors[3] = 0;
     } 
     if(Event.getController().getName()=="sliderY") {
     sliderValue = (int)(Event.getController().getValue());
     } 
     } 
    }
    
    
    
    void initializeSphere(int res)
    {
      sinLUT = new float[SINCOS_LENGTH];
      cosLUT = new float[SINCOS_LENGTH];
    
      for (int i = 0; i < SINCOS_LENGTH; i++) {
        sinLUT[i] = (float) Math.sin(i * DEG_TO_RAD * SINCOS_PRECISION);
        cosLUT[i] = (float) Math.cos(i * DEG_TO_RAD * SINCOS_PRECISION);
      }
    
      float delta = (float)SINCOS_LENGTH/res;
      float[] cx = new float[res];
      float[] cz = new float[res];
      
      // Calc unit circle in XZ plane
      for (int i = 0; i < res; i++) {
        cx[i] = -cosLUT[(int) (i*delta) % SINCOS_LENGTH];
        cz[i] = sinLUT[(int) (i*delta) % SINCOS_LENGTH];
      }
      
      // Computing vertexlist vertexlist starts at south pole
      int vertCount = res * (res-1) + 2;
      int currVert = 0;
      
      // Re-init arrays to store vertices
      sphereX = new float[vertCount];
      sphereY = new float[vertCount];
      sphereZ = new float[vertCount];
      float angle_step = (SINCOS_LENGTH*0.5f)/res;
      float angle = angle_step;
      
      // Step along Y axis
      for (int i = 1; i < res; i++) {
        float curradius = sinLUT[(int) angle % SINCOS_LENGTH];
        float currY = -cosLUT[(int) angle % SINCOS_LENGTH];
        for (int j = 0; j < res; j++) {
          sphereX[currVert] = cx[j] * curradius;
          sphereY[currVert] = currY;
          sphereZ[currVert++] = cz[j] * curradius;
        }
        angle += angle_step;
      }
      sDetail = res;
    }
    
    // Generic routine to draw textured sphere
    void texturedSphere(float r, PGraphics t) {
      int v1,v11,v2;
      r = (r + 240 ) * 0.33;
      beginShape(TRIANGLE_STRIP);
      texture(t);
      float iu=(float)(t.width-1)/(sDetail);
      float iv=(float)(t.height-1)/(sDetail);
      float u=0,v=iv;
      for (int i = 0; i < sDetail; i++) {
        vertex(0, -r, 0,u,0);
        vertex(sphereX[i]*r, sphereY[i]*r, sphereZ[i]*r, u, v);
        u+=iu;
      }
      vertex(0, -r, 0,u,0);
      vertex(sphereX[0]*r, sphereY[0]*r, sphereZ[0]*r, u, v);
      endShape();   
      
      // Middle rings
      int voff = 0;
      for(int i = 2; i < sDetail; i++) {
        v1=v11=voff;
        voff += sDetail;
        v2=voff;
        u=0;
        beginShape(TRIANGLE_STRIP);
        texture(t);
        for (int j = 0; j < sDetail; j++) {
          vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1++]*r, u, v);
          vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2++]*r, u, v+iv);
          u+=iu;
        }
      
        // Close each ring
        v1=v11;
        v2=voff;
        vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1]*r, u, v);
        vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r, u, v+iv);
        endShape();
        v+=iv;
      }
      u=0;
      
      // Add the northern cap
      beginShape(TRIANGLE_STRIP);
      texture(t);
      for (int i = 0; i < sDetail; i++) {
        v2 = voff + i;
        vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r, u, v);
        vertex(0, r, 0,u,v+iv);    
        u+=iu;
      }
      vertex(sphereX[voff]*r, sphereY[voff]*r, sphereZ[voff]*r, u, v);
      endShape();
      
    }

    `

  • I did another little experiment, this time with the TextureSphere example. I downloaded the celestial grid jpg and used that as the texture and drew my lat and lon lines over it. There is good agreement with my lat lines and the grid jpg, but the lon lines are slightly off. I saw this before with shapes3D and figured I cropped wrong. The error is not on every lon line.

    3 of the lines agree exactly. so am I looking at some kind of roundoff error in my lon lines? Why does the lat not show the same errors?

  • Arrrgggh, I think the source of error is from MSpaint. I downloaded the big jpg grid and then resized it a few times until it fit in memory. That did something to the image. I tried it by downloading the the smallest jpg grid and my lines agree almost exactly with the grid image. I then I tried the medium sized grid and resized it by 50 percent once and the errors were there again but small, so small that upping the strokeweight by 1 and the errors are not noticeable.

  • I solved it. I downloaded the big .TIF version and used MSpaint to resize it. At first it failed to load because "processing only likes .tiff that it creates" so I converted to .png and it loaded. There is no misalignment or disagreement with my longitude lines or lat lines. Whatever it was causing the error, its gone by starting with a .TIF and converting to .png instead of .jpg .

  • Now I have a grid that I'm satisfied is pretty accurate, its time to add some stars. I found the right ascension and declination for the only star I seem to know(ha,ha), Dubhe, and I tried to map it to the texture.width and texture.height of the Pgraphic grid image. Here's the code that gets added to the beginning of addDiagonalLine() before the Lat and Lon lines.

    `

    void addDiagonalLine(){
      float RAvalue = 165.0620666f;
      float DecValue = 61.75169444f; 
      float x = map(radians(RAvalue), radians(0),radians(180),texture.width/2,texture.width - texture.width);
      float y = map(radians(DecValue),radians(0),radians(90),texture.height/2,texture.height - texture.height);
      texture.stroke(0,255,0);
      texture.strokeWeight(4);
    
      texture.point( x,y);

    `

  • Did that approach work for you? It sounds like this is coming along nicely!

    It also sounds like you might soon want to add a large collection of starts from a standard data import source....

  • You see where I'm headed eventually. Its working. For stars with Right Ascension greater than 12 hours, I have to do it slightly different than for 0 to 12. The stars get plotted relative to the middle of the texture. I used the star_map4k from the link to verify that I converted hours minutes seconds correctly to decimal degrees. if the green blob lands on the star in the image texture, that's considered good.

  • edited January 5

    Here's how I have to plot a star with RA greater than 12 hours. float RAvalue8 = -152.937708333f; // //Alkaid float DecValue8 = 49.22355554666f; float x6 = map(radians(RAvalue8),radians(0),-PI ,texture.width/2,texture.width ); float y6 = map(radians(DecValue8),radians(0),radians(90),texture.height/2,texture.height - texture.height);

    I probably need to start using arrays and for loops but I'm clumsy and fuzzy headed.

  • One limitation I find is that this approach wont draw Polaris with its declination almost 90 degrees. It seems anything over 80 degrees doesn't show. Even the lon lines get kinda funny at the pole.

  • edited January 2

    The list of stars I want to draw is getting bigger. There has to be a better way than this, so I looked at some SQLite examples. The problem there is I don't know how to create the .db file......yet. I've downloaded SQLite and will see if I can create a stars.db that I can read to get RAValue and DecValue and name.

  • edited January 2

    I think this is where I need a for loop. I created a stars.db file with the name of the star, the right ascension and declination as the columns in a table. I am able to read the .db file in a sketch and display the result using the example class that uses String.format().

    What I want is to read the data and assign it to points(x,y), so maybe point(x,y) needs to be point(x[],y[])?

Sign In or Register to comment.