/*
* Copyright 2013 MovingBlocks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.terasology.rendering.cameras;
import org.terasology.config.Config;
import org.terasology.math.AABB;
import org.terasology.registry.CoreRegistry;
import org.terasology.math.MatrixUtils;
import org.terasology.math.geom.Matrix4f;
import org.terasology.math.geom.Vector3f;
/**
* Provides global access to fonts.
*
*/
/**
* Camera base class.
*
*/
public abstract class Camera {
/* CAMERA PARAMETERS */
protected final Vector3f position = new Vector3f(0, 0, 0);
protected final Vector3f up = new Vector3f(0, 1, 0);
protected final Vector3f viewingDirection = new Vector3f(1, 0, 0);
protected float zNear = 0.1f;
// TODO: This is too large, but many properties have to be adjusted if it changes
protected float zFar = 5000.0f;
protected float targetFov = CoreRegistry.get(Config.class).getRendering().getFieldOfView();
protected float activeFov = targetFov / 4f;
/* VIEW FRUSTUM */
protected final ViewFrustum viewFrustum = new ViewFrustum();
protected final ViewFrustum viewFrustumReflected = new ViewFrustum();
/* MATRICES */
protected Matrix4f projectionMatrix = new Matrix4f();
protected Matrix4f inverseProjectionMatrix = new Matrix4f();
protected Matrix4f normViewMatrix = new Matrix4f();
protected Matrix4f viewMatrix = new Matrix4f();
protected Matrix4f viewProjectionMatrix = new Matrix4f();
protected Matrix4f inverseViewProjectionMatrix = new Matrix4f();
protected Matrix4f prevViewProjectionMatrix = new Matrix4f();
protected Matrix4f reflectionMatrix = new Matrix4f();
protected Matrix4f viewMatrixReflected = new Matrix4f();
protected Matrix4f normViewMatrixReflected = new Matrix4f();
/* USED FOR DIRTY CHECKS */
protected Vector3f cachedPosition = new Vector3f();
protected Vector3f cachedViewigDirection = new Vector3f();
protected float cachedFov;
protected float cachedZNear;
protected float cachedZFar;
protected float cachedReflectionHeight;
/* (Water) Reflection */
private boolean reflected;
private float reflectionHeight = 32;
/**
* Applies the projection and modelview matrix.
*/
public void lookThrough() {
loadProjectionMatrix();
loadModelViewMatrix();
}
/**
* Applies the projection and the normalized modelview matrix (positioned at the origin without any offset like bobbing) .
*/
public void lookThroughNormalized() {
loadProjectionMatrix();
loadNormalizedModelViewMatrix();
}
public void updateFrustum() {
if (getViewMatrix() == null || getProjectionMatrix() == null) {
return;
}
viewFrustum.updateFrustum(MatrixUtils.matrixToFloatBuffer(viewMatrix), MatrixUtils.matrixToFloatBuffer(projectionMatrix));
viewFrustumReflected.updateFrustum(MatrixUtils.matrixToFloatBuffer(viewMatrixReflected), MatrixUtils.matrixToFloatBuffer(projectionMatrix));
}
public abstract boolean isBobbingAllowed();
public abstract void loadProjectionMatrix();
public abstract void loadModelViewMatrix();
public abstract void loadNormalizedModelViewMatrix();
public abstract void updateMatrices();
public abstract void updateMatrices(float fov);
public void update(float delta) {
double diff = Math.abs(activeFov - targetFov);
if (diff < 1.0) {
activeFov = targetFov;
return;
}
if (activeFov < targetFov) {
activeFov += 50.0 * delta;
if (activeFov >= targetFov) {
activeFov = targetFov;
}
} else if (activeFov > targetFov) {
activeFov -= 50.0 * delta;
if (activeFov <= targetFov) {
activeFov = targetFov;
}
}
}
public void extendFov(float fov) {
targetFov = CoreRegistry.get(Config.class).getRendering().getFieldOfView() + fov;
}
public void resetFov() {
targetFov = CoreRegistry.get(Config.class).getRendering().getFieldOfView();
}
public void setReflected(boolean reflected) {
this.reflected = reflected;
}
public float getReflectionHeight() {
return reflectionHeight;
}
public void setReflectionHeight(float reflectionHeight) {
this.reflectionHeight = reflectionHeight;
}
public void updatePrevViewProjectionMatrix() {
prevViewProjectionMatrix.set(viewProjectionMatrix);
}
public float getClipHeight() {
// msteiger: I believe the offset results from the
// slightly lowered water surface height.
return reflectionHeight - 0.5f;
}
public Matrix4f getViewMatrix() {
if (!reflected) {
return viewMatrix;
}
return viewMatrixReflected;
}
public Matrix4f getNormViewMatrix() {
if (!reflected) {
return normViewMatrix;
}
return normViewMatrixReflected;
}
public Matrix4f getProjectionMatrix() {
return projectionMatrix;
}
public Matrix4f getViewProjectionMatrix() {
return viewProjectionMatrix;
}
public Matrix4f getInverseProjectionMatrix() {
return inverseProjectionMatrix;
}
public Matrix4f getInverseViewProjectionMatrix() {
return inverseViewProjectionMatrix;
}
public Matrix4f getPrevViewProjectionMatrix() {
return prevViewProjectionMatrix;
}
public Vector3f getPosition() {
return position;
}
public Vector3f getViewingDirection() {
return viewingDirection;
}
public Vector3f getUp() {
return up;
}
public ViewFrustum getViewFrustum() {
return viewFrustum;
}
public ViewFrustum getViewFrustumReflected() {
return viewFrustumReflected;
}
public float getzNear() {
return zNear;
}
public void setzNear(float zNear) {
this.zNear = zNear;
}
public float getzFar() {
return zFar;
}
public void setzFar(float zFar) {
this.zFar = zFar;
}
public boolean isReflected() {
return reflected;
}
public boolean hasInSight(AABB aabb) {
return viewFrustum.intersects(aabb);
}
}