package com.nilunder.bdx;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.collision.Ray;
import com.badlogic.gdx.math.Vector3;
import com.bulletphysics.linearmath.Transform;
import com.nilunder.bdx.gl.Viewport;
import com.nilunder.bdx.gl.RenderBuffer;
import com.nilunder.bdx.utils.ArrayListNamed;
import javax.vecmath.Vector2f;
import javax.vecmath.Vector3f;
import javax.vecmath.Matrix4f;
public class Camera extends GameObject{
public enum Type{
PERSPECTIVE,
ORTHOGRAPHIC
}
private Vector2f resolution;
public Type type;
public com.badlogic.gdx.graphics.Camera data;
public boolean renderToTexture;
public RenderBuffer renderBuffer;
public ArrayListNamed<GameObject> ignoreObjects;
public void initData(Type type){
this.type = type;
if (type == Type.PERSPECTIVE){
data = new PerspectiveCamera();
}else{
data = new OrthographicCamera();
}
resolution = new Vector2f();
ignoreObjects = new ArrayListNamed<GameObject>();
}
public void projection(Matrix4f mat){
Transform t = new Transform(mat);
float[] m = new float[16];
t.getOpenGLMatrix(m);
data.projection.set(m);
}
public Matrix4f projection(){
Matrix4f m = new Matrix4f();
m.set(data.projection.getValues());
m.transpose();
return m;
}
public void near(float near){
data.near = near;
}
public float near(){
return data.near;
}
public void far(float far){
data.far = far;
}
public float far(){
return data.far;
}
public void width(int w){
data.viewportWidth = Math.max(w, 1); // A width of 0 crashes BDX
}
public int width(){
return Math.round(data.viewportWidth);
}
public void height(int h){
data.viewportHeight = Math.max(h, 1);
}
public int height(){
return Math.round(data.viewportHeight);
}
public Vector2f size(){
return new Vector2f(data.viewportWidth, data.viewportHeight);
}
public void size(int width, int height){
width(width);
height(height);
}
public void size(Vector2f size){
size(Math.round(size.x), Math.round(size.y));
}
public Vector2f resolution(){
return new Vector2f(resolution);
}
public void resolution(int width, int height){
resolution.x = width;
resolution.y = height;
updateRenderBuffer();
}
public void resolution(Vector2f resolution){
resolution(Math.round(resolution.x), Math.round(resolution.y));
}
public void fov(float fov){
((PerspectiveCamera)data).fieldOfView = (float)Math.toDegrees(fov);
}
public float fov(){
Matrix4f p = projection();
float fov;
if (type == Type.PERSPECTIVE){
fov = (float)(Math.atan(1/p.m11)*2);
}else{
fov = 2/p.m11;
}
return fov;
}
public void zoom(float zoom){
((OrthographicCamera)data).zoom = zoom / width();
}
public float zoom(){
return ((OrthographicCamera)data).zoom * width();
}
public Vector2f screenPosition(Vector3f p){
Viewport vp = scene.viewport;
Vector3 out = data.project(new Vector3(p.x, p.y, p.z), vp.x, vp.y, vp.w, vp.h);
return new Vector2f(Math.round(out.x), Math.round(out.y));
}
public Vector2f screenPositionNormalized(Vector3f p){
return screenPosition(p).div(Bdx.display.size());
}
public Vector3f[] rayData(Vector2f p){
Viewport vp = scene.viewport;
Ray pr = data.getPickRay(p.x, Bdx.display.height() - p.y, vp.x, vp.y, vp.w, vp.h);
return new Vector3f[]{new Vector3f(pr.origin.x, pr.origin.y, pr.origin.z), new Vector3f(pr.direction.x, pr.direction.y, pr.direction.z)};
}
public Vector3f[] rayDataNormalized(Vector2f p){
return rayData(p.div(Bdx.display.size()));
}
public void update(){
Transform t = new Transform();
body.getWorldTransform(t);
data.position.set(t.origin.x, t.origin.y, t.origin.z);
Vector3f axis = axis("-Z");
data.direction.set(axis.x, axis.y, axis.z);
axis = axis("Y");
data.up.set(axis.x, axis.y, axis.z);
data.update();
}
public void initRenderBuffer(){
renderBuffer = new RenderBuffer(null, Math.round(resolution.x), Math.round(resolution.y));
}
public void updateRenderBuffer(){
if (renderBuffer != null)
renderBuffer.dispose();
initRenderBuffer();
}
public TextureRegion texture(){
return renderBuffer != null ? renderBuffer.region : null;
}
}