Created
February 27, 2024 06:55
-
-
Save companje/d7bef829be4e460dd69d1298e0323784 to your computer and use it in GitHub Desktop.
Sphere
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Quaternion q = new Quaternion(1, 0, 0, 0); | |
ArrayList<PVector> dots = new ArrayList(); | |
PImage tex; | |
PShape sphere; | |
PShader shader; | |
void setup() { | |
size(900, 900, P3D); | |
tex = loadImage("earth.jpg"); | |
sphere = createShape(SPHERE, height/2); | |
sphere.rotateY(HALF_PI); | |
sphere.setTexture(tex); | |
sphere.setStroke(false); | |
shader = loadShader("lens.glsl"); | |
textSize(20); | |
} | |
void draw() { | |
ortho(); | |
background(0); | |
translate(width/2, height/2); | |
PVector uv = sphereToUV(q.getInverse().rotate(mouseToSphere())); | |
//shader.set("dotPos", uv.x, uv.y); | |
//NU NOG ARRAY TOEVOEGEN. EN MISSCHIEN EEN VARIABELE VAN HOEVEEL LENSEN ER ZIJN | |
//BIJNA KLAAR | |
for (int i=0; i<dots.size(); i++) | |
shader.set("lensCenter["+i+"]",q.getInverse().rotate(mouseToSphere())); | |
shader.set("zoom",2.0); | |
shader.set("numLenses",dots.size()); | |
//uniform vec3 lensCenter; | |
//uniform float zoom; | |
pushMatrix(); | |
q.apply(this); | |
shader(shader); | |
shape(sphere); | |
resetShader(); | |
for (PVector dot : dots) { | |
pushMatrix(); | |
translate(dot.x, dot.y, dot.z); | |
fill(255, 255, 0); | |
noStroke(); | |
sphere(10); | |
popMatrix(); | |
} | |
popMatrix(); | |
fill(255, 255, 0); | |
text(sphereToLatLon(q.getInverse().rotate(mouseToSphere()))+"", 25-width/2, 50-height/2); | |
} | |
void mouseDragged() { | |
PVector from = screenToSphere(pmouseX, pmouseY); | |
PVector to = mouseToSphere(); | |
q.drag(from, to); | |
} | |
void mouseClicked() { | |
PVector dot = q.getInverse().rotate(mouseToSphere()).setMag(height/2); | |
dots.add(dot); | |
} | |
PVector toSphere(float x, float y) { //-1..1 to unit sphere | |
PVector v = new PVector(x, y); | |
if (v.mag()>1.0f) v.normalize(); | |
else v.z = sqrt(1.0-v.magSq()); | |
return v.normalize(); | |
} | |
PVector screenToSphere(float x, float y) { //screen coords to unit sphere | |
return toSphere(map(x, 0, width, -1, 1), map(y, 0, height, -1, 1)); | |
} | |
PVector mouseToSphere() { | |
return screenToSphere(mouseX, mouseY); | |
} | |
PVector sphereToUV(PVector p ) { | |
float u = (atan2(p.z, -p.x) / TWO_PI + 1.25 ) % 1; | |
float v = 1-acos(p.y)/PI; | |
return new PVector(u, v); | |
} | |
PVector sphereToLatLon(PVector p) { | |
PVector uv = sphereToUV(p); | |
float lat = map(uv.x, 0, 1, -180, 180); | |
float lon = map(uv.y, 0, 1, 90, -90); | |
return new PVector(lat, lon); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Quaternion { | |
float w, x, y, z; | |
Quaternion(float w, float x, float y, float z) { | |
set(w, x, y, z); | |
} | |
void set(Quaternion q) { | |
set(q.w,q.x,q.y,q.z); | |
} | |
void set(float w, float x, float y, float z) { | |
this.w = w; | |
this.x = x; | |
this.y = y; | |
this.z = z; | |
} | |
void normalize() { | |
set(normalized()); | |
} | |
Quaternion normalized() { | |
float mag = sqrt(w*w + x*x + y*y + z*z); | |
return new Quaternion(w/mag, x/mag, y/mag, z/mag); | |
} | |
Quaternion mult(Quaternion q) { | |
set( | |
w*q.w - x*q.x - y*q.y - z*q.z, | |
w*q.x + x*q.w + y*q.z - z*q.y, | |
w*q.y - x*q.z + y*q.w + z*q.x, | |
w*q.z + x*q.y - y*q.x + z*q.w | |
); | |
return this; | |
} | |
PVector rotate(PVector v) { | |
Quaternion vecQuat = new Quaternion(0, v.x, v.y, v.z); | |
Quaternion conjQuat = this.getInverse(); | |
Quaternion rotatedQuat = this.mult(vecQuat).mult(conjQuat); | |
return new PVector(rotatedQuat.x, rotatedQuat.y, rotatedQuat.z); | |
} | |
void toAxisAngle(PVector axis, float[] angle) { | |
normalize(); // Ensure the quaternion is normalized | |
angle[0] = 2 * acos(w); | |
float s = sqrt(1 - w * w); | |
if (s < 0.001) { // Test to avoid divide by zero, s is always positive due to sqrt | |
// If s close to zero then direction of axis not important | |
axis.x = x; // If it is important that axis is normalized then replace with x=1; y=z=0; | |
axis.y = y; | |
axis.z = z; | |
} else { | |
axis.x = x / s; // Normalize axis | |
axis.y = y / s; | |
axis.z = z / s; | |
} | |
} | |
Quaternion getInverse() { | |
return new Quaternion(w, -x, -y, -z); | |
} | |
void apply(PGraphics g) { | |
PVector axis = new PVector(); | |
float[] angle = new float[1]; | |
q.toAxisAngle(axis, angle); | |
g.rotate(angle[0], axis.x, axis.y, axis.z); | |
} | |
void apply(PApplet app) { | |
apply(app.g); | |
} | |
void drag(PVector from, PVector to) { | |
PVector axis = from.cross(to); | |
float angle = from.dot(to); | |
Quaternion q_drag = new Quaternion(cos(angle / 2), | |
axis.x * sin(angle / 2), | |
axis.y * sin(angle / 2), | |
axis.z * sin(angle / 2)); | |
set(q_drag.mult(this)); | |
normalize(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment