package com.momega.spacesimulator.opengl;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.glu.GLU;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.momega.spacesimulator.MainWindow;
import com.momega.spacesimulator.context.Application;
import com.momega.spacesimulator.context.ModelHolder;
import com.momega.spacesimulator.model.Camera;
import com.momega.spacesimulator.model.Model;
import com.momega.spacesimulator.model.RunStep;
import com.momega.spacesimulator.model.Vector3d;
import com.momega.spacesimulator.renderer.ModelRenderer;
import com.momega.spacesimulator.renderer.RendererModel;
/**
* The class contains main OPENGL renderer for the application. It is the subclass for #AbstractRenderer which is the super class
* for all my OPENGL implementation
* Created by martin on 4/19/14.
*/
public class MainGLRenderer extends AbstractGLRenderer {
public final static double UNIVERSE_RADIUS = 1E16;
private static final Logger logger = LoggerFactory.getLogger(MainGLRenderer.class);
private final ModelRenderer renderer;
private GLU glu;
public double znear = 100;
private MainWindow window;
public MainGLRenderer(MainWindow window) {
this.window = window;
this.renderer = new ModelRenderer();
}
@Override
protected void setup(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
glu = new GLU();
renderer.init(gl);
}
@Override
protected boolean isModelReady() {
return (ModelHolder.getModel() !=null);
}
@Override
protected void draw(GLAutoDrawable drawable) {
renderer.draw(drawable);
RendererModel.getInstance().runDelayedActions(drawable, renderer, window);
}
@Override
public void dispose(GL2 gl) {
renderer.dispose(gl);
}
protected void computeView(GLAutoDrawable drawable) {
RendererModel.getInstance().clearViewCoordinates();
RendererModel.getInstance().updateViewData(drawable);
RendererModel.getInstance().modelChanged();
}
@Override
public void setCamera() {
Camera camera = ModelHolder.getModel().getCamera();
Vector3d p = camera.getPosition();
logger.debug("Camera Position = {}", p.asArray());
Vector3d n = camera.getOppositeOrientation().getN().negate();
glu.gluLookAt(p.getX(), p.getY(), p.getZ(),
p.getX() + n.getX() * 1E8,
p.getY() + n.getY() * 1E8,
p.getZ() + n.getZ() * 1E8,
camera.getOppositeOrientation().getV().getX(),
camera.getOppositeOrientation().getV().getY(),
camera.getOppositeOrientation().getV().getZ());
}
protected void setPerspective(GL2 gl, double aspect) {
glu.gluPerspective(RendererModel.FOVY, aspect, znear, UNIVERSE_RADIUS);
}
public double getZnear() {
return znear;
}
public void changeZnear(double factor) {
znear *= factor;
logger.info("change z near: {}",znear);
setReshape();
}
@Override
protected void computeScene() {
Model model = ModelHolder.getModel();
RunStep step = RunStep.create(model.getTime(), RendererModel.getInstance().getWarpFactor(), false);
Application.getInstance().next(model, step);
// // TODO: place this into the method
// double x = drawable.getWidth();
// double y = drawable.getHeight();
// double aratio = Math.sqrt(x * x + y * y) / y;
double z = ModelHolder.getModel().getCamera().getDistance();
z = z / 10.0d;
if (z < znear) {
znear = z;
setReshape();
logger.debug("new z-near = {}", znear);
}
if (z > znear) {
znear = z;
setReshape();
logger.debug("new z-near = {}", znear);
}
}
// //TODO: Does not work exactly, new algorithm has to be created
// public double computeZNear(double aratio) {
// Vector3d viewVector = ModelHolder.getModel().getCamera().getOrientation().getN();
// double znear = UNIVERSE_RADIUS * 2;
//
// for(PhysicalBody dp : ModelHolder.getModel().getMovingObjects()) {
//
// // only valid for object with radius
// if (dp.getRadius() <= 0) {
// continue;
// }
//
// double distance = dp.getPosition().subtract(ModelHolder.getModel().getCamera().getPosition()).length();
// double distanceFactor = distance / dp.getRadius();
// if (distanceFactor > UNIVERSE_RADIUS * 0.001) {
// continue; // If it's too far to be visible discard it
// }
//
// // check whether the dynamic point is visible
// Vector3d diffVector = dp.getPosition().subtract(ModelHolder.getModel().getCamera().getPosition()).normalize();
// double dot = viewVector.dot(diffVector);
// if (Math.abs(dot) < 0.01) {
// continue;
// }
// double eyeAngle = Math.acos(dot);
//
// double radiusAngle = Math.atan2(dp.getRadius(), distance);
//
// double diffAngle = Math.abs(eyeAngle) - Math.abs(radiusAngle);
// if (diffAngle > Math.toRadians(aratio * 45)) {
// continue;
// }
//
// double clip = Math.abs(Math.cos(diffAngle) * distance - dp.getRadius()) - 1;
// if (clip < 1) {
// clip = 1;
// }
//
// if (clip < znear) {
// znear = clip;
// }
// }
//
// if (znear > UNIVERSE_RADIUS * 0.001) {
// znear = UNIVERSE_RADIUS * 0.001;
// }
//
// return znear;
// }
}