| class Camera { |
| // camera's field of view |
| float fov; |
| // camera's position, look at point and axis |
| PVector pos, center, axis; |
| PVector init_pos, init_center, init_axis; |
| float move_speed; |
| float rot_speed; |
| Camera(float fov, PVector pos, PVector center, PVector axis) { |
| this.fov = fov; |
| this.pos = pos; |
| this.center = center; |
| this.axis = axis; |
| this.axis.normalize(); |
| move_speed = 0.001; |
| rot_speed = 0.01 * PI; |
| init_pos = pos.copy(); |
| init_center = center.copy(); |
| init_axis = axis.copy(); |
| } |
| |
| Camera copy() { |
| Camera cam = new Camera(fov, pos.copy(), center.copy(), axis.copy()); |
| return cam; |
| } |
| |
| PVector project(PVector pos) { |
| PVector proj = MatxVec3(getCameraMat(), PVector.sub(pos, this.pos)); |
| proj.x = (float)height / 2.0 * proj.x / proj.z / tan(fov / 2.0f); |
| proj.y = (float)height / 2.0 * proj.y / proj.z / tan(fov / 2.0f); |
| proj.z = proj.z; |
| return proj; |
| } |
| |
| float[] getCameraMat() { |
| float[] mat = new float[9]; |
| PVector dir = PVector.sub(center, pos); |
| dir.normalize(); |
| PVector left = dir.cross(axis); |
| left.normalize(); |
| // processing camera system does not follow right hand rule |
| mat[0] = -left.x; |
| mat[1] = -left.y; |
| mat[2] = -left.z; |
| mat[3] = axis.x; |
| mat[4] = axis.y; |
| mat[5] = axis.z; |
| mat[6] = dir.x; |
| mat[7] = dir.y; |
| mat[8] = dir.z; |
| |
| return mat; |
| } |
| |
| void run() { |
| PVector dir, left; |
| if (mousePressed) { |
| float angleX = (float)mouseX / width * PI - PI / 2; |
| float angleY = (float)mouseY / height * PI - PI; |
| PVector diff = PVector.sub(center, pos); |
| float radius = diff.mag(); |
| pos.x = radius * sin(angleY) * sin(angleX) + center.x; |
| pos.y = radius * cos(angleY) + center.y; |
| pos.z = radius * sin(angleY) * cos(angleX) + center.z; |
| dir = PVector.sub(center, pos); |
| dir.normalize(); |
| PVector up = new PVector(0, 1, 0); |
| left = up.cross(dir); |
| left.normalize(); |
| axis = dir.cross(left); |
| axis.normalize(); |
| } |
| |
| if (keyPressed) { |
| switch (key) { |
| case 'w': |
| dir = PVector.sub(center, pos); |
| dir.normalize(); |
| pos = PVector.add(pos, PVector.mult(dir, move_speed)); |
| center = PVector.add(center, PVector.mult(dir, move_speed)); |
| break; |
| case 's': |
| dir = PVector.sub(center, pos); |
| dir.normalize(); |
| pos = PVector.sub(pos, PVector.mult(dir, move_speed)); |
| center = PVector.sub(center, PVector.mult(dir, move_speed)); |
| break; |
| case 'a': |
| dir = PVector.sub(center, pos); |
| dir.normalize(); |
| left = axis.cross(dir); |
| left.normalize(); |
| pos = PVector.add(pos, PVector.mult(left, move_speed)); |
| center = PVector.add(center, PVector.mult(left, move_speed)); |
| break; |
| case 'd': |
| dir = PVector.sub(center, pos); |
| dir.normalize(); |
| left = axis.cross(dir); |
| left.normalize(); |
| pos = PVector.sub(pos, PVector.mult(left, move_speed)); |
| center = PVector.sub(center, PVector.mult(left, move_speed)); |
| break; |
| case 'r': |
| dir = PVector.sub(center, pos); |
| dir.normalize(); |
| float[] mat = getRotationMat3x3(rot_speed, dir.x, dir.y, dir.z); |
| axis = MatxVec3(mat, axis); |
| axis.normalize(); |
| break; |
| case 'b': |
| pos = init_pos.copy(); |
| center = init_center.copy(); |
| axis = init_axis.copy(); |
| break; |
| case '+': move_speed *= 2.0f; break; |
| case '-': move_speed /= 2.0; break; |
| case CODED: |
| if (keyCode == UP) { |
| pos = PVector.add(pos, PVector.mult(axis, move_speed)); |
| center = PVector.add(center, PVector.mult(axis, move_speed)); |
| } else if (keyCode == DOWN) { |
| pos = PVector.sub(pos, PVector.mult(axis, move_speed)); |
| center = PVector.sub(center, PVector.mult(axis, move_speed)); |
| } |
| } |
| } |
| } |
| void open() { |
| perspective(fov, float(width) / height, 1e-6, 1e5); |
| camera(pos.x, pos.y, pos.z, center.x, center.y, center.z, axis.x, axis.y, |
| axis.z); |
| } |
| void close() { |
| ortho(-width, 0, -height, 0); |
| camera(0, 0, 0, 0, 0, 1, 0, 1, 0); |
| } |
| } |