Hello everyone, I am trying to make an accurate sky simulation in the voxel game I am working on, as an update. So far, I have day and night working, with clouds (though they are kind of buggy). However, I want to make a sun that rotates around the camera. I store this in a pshape. However, I was to make it rotateX() (rotate vertically). However, it just spins in tiny circle. How would I make the arc bigger and make it rotate around the camera?
Source:
import processing.core.PApplet;
import processing.core.PImage;
import processing.core.PVector;
import processing.core.PShape;
import processing.core.PConstants;
public class Sky {
PImage clouds;
PApplet app;
int r = 0, g = 0, b = 0;
public PVector pos = new PVector(0, 0, 0);
public PVector pos2 = new PVector(0, 0, 0);
public PVector pos3 = new PVector(0, 0, 0);
public PVector pos4 = new PVector(0, 0, 0);
public PVector pos5 = new PVector(0, 0, 0);
PShape skyShape;
boolean day;
boolean night;
int dayTime = 60000;
int sunsetColor = 0xFFFD5E53;
int dayColor = 0xFF82E6FF;
int nightColor = 0xFF1E1E1E;
int sunsetAnimTime = 10000;
boolean startTimer = false;
int inc = 0;
PShape c, c2, c3;
PShape sun;
int timer = (sunsetAnimTime/1000) * 60;
public Sky(PApplet p) {
app = p;
clouds = Minecraft.clouds;
pos = new PVector(0 * Minecraft.size, 256 * Minecraft.size, 0 * Minecraft.size);
pos2 = new PVector(0 * Minecraft.size, 256 * Minecraft.size, -128 * Minecraft.size);
pos3 = new PVector(0 * Minecraft.size, 256 * Minecraft.size, -256 * Minecraft.size);
pos4 = new PVector(0 * Minecraft.size, 256 * Minecraft.size, -128 * Minecraft.size);
pos5 = new PVector(0 * Minecraft.size, 256 * Minecraft.size, -256 * Minecraft.size);
float x1 = -5000;
float y1 = -5000;
float z1 = -5000;
float x2 = 5000;
float y2 = 5000;
float z2 = 5000;
sun = app.createShape();
sun.setTexture(Minecraft.sunImage);
sun.beginShape(PConstants.QUADS);
sun.noFill();
sun.noStroke();
sun.vertex(x1, y1, z1, 0f, 0f);
sun.vertex(x2, y1, z1, 1f, 0f);
sun.vertex(x2, y2, z1, 1f, 1f);
sun.vertex(x1, y2, z1, 0f, 1f);
sun.endShape();
x1 = -6400;
y1 = -6400;
z1 = -6400;
x2 = 6400;
y2 = 6400;
z2 = 6400;
c = app.createShape();
c.setTexture(Minecraft.clouds);
c.beginShape(PConstants.QUADS);
c.noFill();
c.noStroke();
c.vertex(x1, y1, z2, 0, 0);
c.vertex(x2, y1, z2, 1, 0);
c.vertex(x2, y1, z1, 1, 1);
c.vertex(x1, y1, z1, 0, 1);
c.endShape();
z1 -= 128 * Minecraft.size;
z2 -= 128 * Minecraft.size;
c2 = app.createShape();
c2.setTexture(Minecraft.clouds);
c2.beginShape(PConstants.QUADS);
c2.noFill();
c2.noStroke();
c2.vertex(x1, y1, z2, 0, 0);
c2.vertex(x2, y1, z2, 1, 0);
c2.vertex(x2, y1, z1, 1, 1);
c2.vertex(x1, y1, z1, 0, 1);
c2.endShape();
z1 -= 128 * Minecraft.size;
z2 -= 128 * Minecraft.size;
c3 = app.createShape();
c3.setTexture(Minecraft.clouds);
c3.beginShape(PConstants.QUADS);
c3.noFill();
c3.noStroke();
c3.vertex(x1, y1, z2, 0, 0);
c3.vertex(x2, y1, z2, 1, 0);
c3.vertex(x2, y1, z1, 1, 1);
c3.vertex(x1, y1, z1, 0, 1);
c3.endShape();
c3 = app.createShape();
c3.setTexture(Minecraft.clouds);
c3.beginShape(PConstants.QUADS);
c3.noFill();
c3.noStroke();
c3.vertex(x1, y1, z2, 0, 0);
c3.vertex(x2, y1, z2, 1, 0);
c3.vertex(x2, y1, z1, 1, 1);
c3.vertex(x1, y1, z1, 0, 1);
c3.endShape();
}
public void setColor(int x, int y, int z) {
r = x;
g = y;
b = z;
}
public void draw() {
if (((app.millis() / dayTime) & 1) == 0) {
if((((app.millis() + sunsetAnimTime) / dayTime) & 1) != 0) {
float a = PApplet.constrain(timer, 1, 100);
animateSky(a, sunsetColor, dayColor);
} else {
if((((app.millis() - sunsetAnimTime) / dayTime) & 1) != 0) {
float a = PApplet.constrain(timer, 1, 100);
animateSky(a, dayColor, sunsetColor);
} else {
app.background(dayColor);
}
}
} else {
if((((app.millis() + sunsetAnimTime) / dayTime) & 1) == 0) {
float a = PApplet.constrain(timer, 1, 100);
animateSky(a, sunsetColor, nightColor);
} else {
if((((app.millis() - sunsetAnimTime) / dayTime) & 1) == 0) {
float a = PApplet.constrain(timer, 1, 100);
animateSky(a, nightColor, sunsetColor);
} else {
app.background(nightColor);
}
}
}
if(startTimer) {
timer--;
}
if(timer < 1) {
startTimer = false;
timer = (sunsetAnimTime/1000) * 60;
}
PVector chunkPos = Minecraft.camera.chunkPos;
PVector p = Minecraft.camera.position;
/*
pos.z = chunkPos.z * (Chunk.w * Minecraft.size);
pos2.z = chunkPos.z * (Chunk.w * Minecraft.size);
pos3.z = chunkPos.z * (Chunk.w * Minecraft.size);
*/
pos.x = chunkPos.x * (Chunk.w * Minecraft.size);
pos2.x = chunkPos.x * (Chunk.w * Minecraft.size);
pos3.x = chunkPos.x * (Chunk.w * Minecraft.size);
app.pushMatrix();
app.translate(pos.x, pos.y, pos.z);
app.shape(c);
app.popMatrix();
app.pushMatrix();
app.translate(pos2.x, pos2.y, pos2.z);
app.shape(c2);
app.popMatrix();
app.pushMatrix();
app.translate(pos3.x, pos3.y, pos3.z);
app.shape(c3);
app.popMatrix();
app.pushMatrix();
app.translate(pos.x + 12800, pos.y, pos.z);
app.shape(c);
app.popMatrix();
app.pushMatrix();
app.translate(pos2.x + 12800, pos2.y, pos2.z);
app.shape(c2);
app.popMatrix();
app.pushMatrix();
app.translate(pos3.x + 12800, pos3.y, pos3.z);
app.shape(c3);
app.popMatrix();
app.pushMatrix();
app.translate(pos.x - 12800, pos.y, pos.z);
app.shape(c);
app.popMatrix();
app.pushMatrix();
app.translate(pos2.x - 12800, pos2.y, pos2.z);
app.shape(c2);
app.popMatrix();
app.pushMatrix();
app.translate(pos3.x - 12800, pos3.y, pos3.z);
app.shape(c3);
app.popMatrix();
app.pushMatrix();
app.translate(pos.x, pos.y, pos.z + 12800);
app.shape(c);
app.popMatrix();
app.pushMatrix();
app.translate(pos2.x, pos2.y, pos2.z + 12800);
app.shape(c2);
app.popMatrix();
app.pushMatrix();
app.translate(pos3.x, pos3.y, pos3.z + 12800);
app.shape(c3);
app.popMatrix();
app.pushMatrix();
app.translate(pos.x + 12800, pos.y, pos.z + 12800);
app.shape(c);
app.popMatrix();
app.pushMatrix();
app.translate(pos2.x + 12800, pos2.y, pos2.z + 12800);
app.shape(c2);
app.popMatrix();
app.pushMatrix();
app.translate(pos3.x + 12800, pos3.y, pos3.z + 12800);
app.shape(c3);
app.popMatrix();
app.pushMatrix();
app.translate(pos.x - 12800, pos.y, pos.z + 12800);
app.shape(c);
app.popMatrix();
app.pushMatrix();
app.translate(pos2.x - 12800, pos2.y, pos2.z + 12800);
app.shape(c2);
app.popMatrix();
app.pushMatrix();
app.translate(pos3.x - 12800, pos3.y, pos3.z + 12800);
app.shape(c3);
app.popMatrix();
app.pushMatrix();
app.translate(p.x, p.y, p.z + 12800);
app.rotateX(PApplet.radians(-inc));
app.shape(sun);
app.popMatrix();
if(pos.z >= (128 * Minecraft.size) + chunkPos.z * (Chunk.w * Minecraft.size)) {
pos.z = chunkPos.z * (Chunk.w * Minecraft.size) - (640 * Minecraft.size);
}
if(pos2.z >= (128 * Minecraft.size) + chunkPos.z * (Chunk.w * Minecraft.size) + 6400) {
pos2.z = chunkPos.z * (Chunk.w * Minecraft.size) - (512 * Minecraft.size);
}
if(pos3.z >= (128 * Minecraft.size) + chunkPos.z * (Chunk.w * Minecraft.size) + 12800) {
pos3.z = chunkPos.z * (Chunk.w * Minecraft.size) - (384 * Minecraft.size);
}
if(pos4.z >= (128 * Minecraft.size) + chunkPos.z * (Chunk.w * Minecraft.size) + 6400) {
pos4.z = chunkPos.z * (Chunk.w * Minecraft.size) - (256 * Minecraft.size);
}
if(pos5.z >= (128 * Minecraft.size) + chunkPos.z * (Chunk.w * Minecraft.size) + 12800) {
pos5.z = chunkPos.z * (Chunk.w * Minecraft.size) - (128 * Minecraft.size);
}
pos.z += 16;
pos2.z += 16;
pos3.z += 16;
pos4.z += 16;
pos5.z += 16;
inc++;
}
public void animateSky(float x, int col1, int col2) {
startTimer = true;
app.background(app.lerpColor(col1, col2, x / 100));
}
}
Minecraft is the class that holds data that this class uses, such as cube size and PImages. I am not showing it here.
Hey buddy, could you make a simple (simplified) version of the problem in the shape of a sketch we can run and take a look at, without any of the sky and dependent classes? You just want a sphere to rotate around the camera?
For a simplified version I would make a camera by using the QueasyCam library, and then get information from the camera to determine its position, and draw the sphere accordingly.
in a simple sketch like this:
import queasycam.*;
QueasyCam camera;
void setup() {
size(1000, 800, P3D);
camera = new QueasyCam(this);
}
void draw() {
background(0);
pushMatrix();
translate(0, 0, 0);
sphere(100);
popMatrix();
}
How would I get the sphere to rotate on the x axis, around the camera?
You can make an object rotate around a point by using basic trig:
float rad = 1000; // radius
float angle = frameCount / 100.f; // arbitrary value that determines the rotation speed
float x = rad * cos(angle);
float z = rad * sin(angle); // x, z is the horizontal plane
Add the camera.position to these values, translate to this position before you draw the sphere and you should be done?
Whats the difference between QueasyCam and PeasyCam?
http://mrfeinberg.com/peasycam/#about
It says in the description… (I wondered the same…) he named it in honour of Peasy; it’s a FPS adaptation, allowing you to move the camera with WASD.
Thank you for the solution. However, I have 1 more question.
- Would I use
tan()
to make the sphere rotate on the y-axis?
Well, yes and no. You can look up spherical coordinates on wiki to understand how coordinates around a sphere work, but in this case it’d probably be easier to rotate your orbit using rotateX/Y/Z or rotation matrices. Like I suggested in my example, the combination of cos for one, and sin for the other makes a circle - to which components you connect them; x, y or z, determines how the circle is oriented.
x = cos(angle)
y = sin(angle)
makes the circle go vertical, aligned with the camera plane (you see a circle)
z = cos(angle)
x = sin(angle)
creates a horizontal circle
z = cos(angle)
y = sin(angle)
creates a vertical circle that’s perpendicular to the camera plane (you see the circle from the side: a line)