package scene3d;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.math.Vector3;
public class Camera3d extends PerspectiveCamera {
private static Camera3d instance;
Camera3d(){
super(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
position.set(10f, 10f, 10f);
lookAt(0,0,0);
near = 0.1f;
far = 300f;
update();
instance = this;
}
private static float offsetX = 10f, offsetY = 10f, offsetZ = 10f;
private static float folllowSpeed = 0.5f;
private static Actor3d followedActor3d;
private static boolean lookAt;
/*
* The camera follows the actor3d as it moves along the scene
* @param actor3d The actor3d the camera has to follow , if it is null the camera stops following
* @param lookAt whether the camera should always be pointing to the actor3d
*/
public static void followActor3d(Actor3d actor3d, boolean la){
followedActor3d = actor3d;
lookAt = la;
}
/*
* This sets the distance between the camera and the actor
* @param offX the x distance from actor
* @param offY the y distance from actor
* @param offZ the z distance from actor
*/
public static void followOffset(float offX, float offY, float offZ){
offsetX = offX;
offsetY = offY;
offsetZ = offZ;
}
private static float moveDuration;
private static float moveTime;
private static boolean moveCompleted;
private static float moveLastPercent;
private static float panSpeedX, panSpeedY, panSpeedZ;
private static float movePercentDelta;
private static float rotateTime;
private static float rotateDuration;
private static float rotateYaw, rotatePitch, rotateRoll;
private static boolean rotateCompleted;
private static float rotateLastPercent;
private static float rotatePercentDelta;
public static void moveTo(float x, float y, float z, float duration) {
moveBy(x-instance.position.x, y-instance.position.y, y-instance.position.y, duration);
}
public static void moveBy(float amountX, float amountY, float amountZ, float duration) {
moveDuration = duration;
panSpeedX = amountX;
panSpeedY = amountY;
panSpeedZ = amountZ;
moveLastPercent = 0;
moveTime = 0;
moveCompleted = false;
}
public static void rotateBy(float yaw, float pitch, float roll, float duration){
rotateLastPercent = 0;
rotateTime = 0;
rotateYaw = yaw;
rotatePitch = pitch;
rotateRoll = roll;
rotateDuration = duration;
rotateCompleted = false;
}
@Override
public void update(){
super.update();
float delta = Gdx.graphics.getDeltaTime();
if(!moveCompleted){
moveTime += delta;
moveCompleted = moveTime >= moveDuration;
float percent;
if (moveCompleted)
percent = 1;
else {
percent = moveTime / moveDuration;
}
movePercentDelta = percent - moveLastPercent;
translate(panSpeedX * movePercentDelta, panSpeedY * movePercentDelta, panSpeedZ * movePercentDelta);
moveLastPercent = percent;
}
if(!rotateCompleted){
rotateTime += delta;
rotateCompleted = rotateTime >= rotateDuration;
float percent;
if (rotateCompleted)
percent = 1;
else
percent = rotateTime / rotateDuration;
rotatePercentDelta = percent - rotateLastPercent;
rotate(Vector3.Y, rotateYaw * rotatePercentDelta);
rotate(Vector3.X, rotatePitch * rotatePercentDelta);
rotate(Vector3.Z, rotateRoll * rotatePercentDelta);
rotateLastPercent = percent;
}
if (followedActor3d != null) {
moveTo(followedActor3d.x+offsetX, followedActor3d.y+offsetY, followedActor3d.z+offsetZ, folllowSpeed);
if(lookAt)
lookAt(followedActor3d.x, followedActor3d.y, followedActor3d.z);
/*
followedActor3d.getTransform().getTranslation(camera.direction);
current.set(position).sub(camera.direction);
desired.set(desiredLocation).rot(followedActor3d.getTransform()).add(desiredOffset);
final float desiredDistance = desired.len();
if (rotationSpeed < 0)
current.set(desired).nor().mul(desiredDistance);
else if (rotationSpeed == 0 || Vector3.tmp.set(current).dst2(desired) < rotationOffsetSq)
current.nor().mul(desiredDistance);
else {
current.nor();
desired.nor();
rotationAxis.set(current).crs(desired);
float angle = (float)Math.acos(current.dot(desired)) * MathUtils.radiansToDegrees;
final float maxAngle = rotationSpeed * delta;
if (Math.abs(angle) > maxAngle) {
angle = (angle < 0) ? -maxAngle : maxAngle;
}
current.rot(rotationMatrix.idt().rotate(rotationAxis, angle));
current.mul(desiredDistance);
}
current.add(camera.direction);
absoluteSpeed = Math.min(absoluteSpeed + acceleration, current.dst(position) / delta);
position.add(speed.set(current).sub(position).nor().mul(absoluteSpeed * delta));
if (bounds.isValid()) {
if (position.x < bounds.min.x) position.x = bounds.min.x;
if (position.x > bounds.max.x) position.x = bounds.max.x;
if (position.y < bounds.min.y) position.y = bounds.min.y;
if (position.y > bounds.max.y) position.y = bounds.max.y;
if (position.z < bounds.min.z) position.z = bounds.min.z;
if (position.z > bounds.max.z) position.z = bounds.max.z;
}
if (offsetBounds.isValid()) {
Vector3.tmp.set(position).sub(camera.direction);
if (Vector3.tmp.x < offsetBounds.min.x) position.x = offsetBounds.min.x + camera.direction.x;
if (Vector3.tmp.x > offsetBounds.max.x) position.x = offsetBounds.max.x + camera.direction.x;
if (Vector3.tmp.y < offsetBounds.min.y) position.y = offsetBounds.min.y + camera.direction.y;
if (Vector3.tmp.y > offsetBounds.max.y) position.y = offsetBounds.max.y + camera.direction.y;
if (Vector3.tmp.z < offsetBounds.min.z) position.z = offsetBounds.min.z + camera.direction.z;
if (Vector3.tmp.z > offsetBounds.max.z) position.z = offsetBounds.max.z + camera.direction.z;
}
camera.direction.add(target.set(targetLocation)
.rot(followedActor3d.getTransform()).add(targetOffset)).sub(position).nor();*/
}
}
public static float getX(){
return instance.position.x;
}
public static float getY(){
return instance.position.y;
}
public static float getZ(){
return instance.position.z;
}
public static float getWidth(){
return instance.viewportWidth;
}
public static float getHeight(){
return instance.viewportHeight;
}
public static void setFar(float far){
instance.far = far;
}
public static float getFar(){
return instance.far;
}
public static void setNear(float near){
instance.near = near;
}
public static float getNear(){
return instance.near;
}
public static void setFieldOfView(float fov){
instance.fieldOfView = fov;
}
public static float getFieldOfView(){
return instance.fieldOfView;
}
}