Last active
February 24, 2024 15:47
-
-
Save companje/832c33c61d9b6b39e4b30193419373da to your computer and use it in GitHub Desktop.
Sphere ArcBall rotate with Quaternion, also with inverse rotation
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); | |
PShape globe; | |
PImage tex; | |
ArrayList<PVector> points = new ArrayList(); | |
float radius; | |
void setup() { | |
size(800, 800, P3D); | |
tex = loadImage("earth.jpg"); | |
radius = height/2; | |
globe = createShape(SPHERE, radius); | |
globe.rotateY(HALF_PI); | |
globe.setTexture(tex); | |
globe.setStroke(false); | |
for (int i=0; i<20; i++) { | |
PVector p = PVector.random3D(); | |
p.setMag(radius); | |
points.add(p); | |
} | |
} | |
void draw() { | |
background(0); | |
ortho(); | |
lights(); | |
translate(width/2, height/2); | |
//grote bol | |
PVector axis = new PVector(); | |
float[] angle = new float[1]; | |
q.toAxisAngle(axis, angle); | |
fill(255); | |
stroke(0); | |
pushMatrix(); | |
rotate(angle[0], axis.x, axis.y, axis.z); | |
shape(globe); | |
//red dots that turn yellow when mouse nearby | |
for (PVector point : points) { | |
pushMatrix(); | |
translate(point.x, point.y, point.z); | |
if (dist(mouseX,mouseY,screenX(0,0,0),screenY(0,0,0))<20) { | |
fill(255, 255, 0); | |
} else { | |
fill(255, 0, 0); | |
} | |
noStroke(); | |
sphere(5); | |
popMatrix(); | |
} | |
popMatrix(); | |
} | |
void mouseDragged() { | |
float angle = dist(mouseX, mouseY, pmouseX, pmouseY) * 0.005; | |
PVector axis = new PVector(pmouseY - mouseY, mouseX - pmouseX, 0).normalize(); | |
Quaternion dragQuaternion = new Quaternion( | |
cos(angle / 2), | |
axis.x * sin(angle / 2), | |
axis.y * sin(angle / 2), | |
axis.z * sin(angle / 2)); | |
q = dragQuaternion.mult(q); | |
q.normalize(); | |
} |
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) { | |
this.w = w; | |
this.x = x; | |
this.y = y; | |
this.z = z; | |
} | |
// Normaliseer de quaternion | |
void normalize() { | |
float mag = sqrt(w*w + x*x + y*y + z*z); | |
w /= mag; | |
x /= mag; | |
y /= mag; | |
z /= mag; | |
} | |
// Quaternion vermenigvuldiging | |
Quaternion mult(Quaternion q) { | |
return new Quaternion( | |
this.w*q.w - this.x*q.x - this.y*q.y - this.z*q.z, | |
this.w*q.x + this.x*q.w + this.y*q.z - this.z*q.y, | |
this.w*q.y - this.x*q.z + this.y*q.w + this.z*q.x, | |
this.w*q.z + this.x*q.y - this.y*q.x + this.z*q.w | |
); | |
} | |
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); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment