content: /*
   * Copyright (C) 2010-2014 - Andreas Maier 
   * CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
   */
  package edu.stanford.rsl.apps.gui.opengl;
  
  
  import java.awt.Color;
  import java.io.IOException;
  import java.util.ArrayList;
  
  import javax.media.opengl.GL;
  import javax.media.opengl.GL4bc;
  import javax.media.opengl.GLAutoDrawable;
  
  import edu.stanford.rsl.conrad.geometry.AbstractShape;
  import edu.stanford.rsl.conrad.geometry.shapes.compound.CompoundShape;
  import edu.stanford.rsl.conrad.geometry.shapes.simple.Edge;
  import edu.stanford.rsl.conrad.geometry.shapes.simple.PointND;
  import edu.stanford.rsl.conrad.geometry.shapes.simple.Triangle;
  import edu.stanford.rsl.conrad.geometry.splines.SurfaceBSpline;
  import edu.stanford.rsl.conrad.geometry.transforms.AffineTransform;
  import edu.stanford.rsl.conrad.geometry.transforms.Translation;
  import edu.stanford.rsl.conrad.numerics.SimpleMatrix;
  import edu.stanford.rsl.conrad.numerics.SimpleVector;
  import edu.stanford.rsl.conrad.utils.DoublePrecisionPointUtil;
  
  /**
   * Class to render Surface B-Splines in an OpenGL viewer.
   * @author Mathias Unberath
   *
   */
  public class BSplineVolumeRenderer extends OpenGLViewer{
  
  	ArrayList<SurfaceBSpline> splines;
  	ArrayList<Triangle> triangles;
  	ArrayList<Color> colors;
  	double sampling = 30;
  	
  	private static final long serialVersionUID = 2752954430998793647L;
  
  	public BSplineVolumeRenderer(String filename) throws IOException {
  		super(filename);
  		this.setSize(640, 480);
  		splines = SurfaceBSpline.readSplinesFromFile(filename);
  		setUp(sampling, sampling);
  	}
  	
  	public BSplineVolumeRenderer(SurfaceBSpline... spline){
  		super("Spline rendering.");
  		this.setSize(640, 480);
  		splines = new ArrayList<SurfaceBSpline>();
  		for(int i = 0; i < spline.length; i++){
  			splines.add(spline[i]);
  		}
  		setUp(sampling, sampling);
  	}
  	
  	public BSplineVolumeRenderer(double samplingU, double samplingV, SurfaceBSpline... spline){
  		super("Spline rendering.");
  		this.setSize(640, 480);
  		splines = new ArrayList<SurfaceBSpline>();
  		for(int i = 0; i < spline.length; i++){
  			splines.add(spline[i]);
  		}
  		setUp(samplingU, samplingV);
  	}
  	
  	private void setUp(double samplingU, double samplingV){
  		this.triangles = new ArrayList<Triangle>();	
  		
  		for( int i = 0; i < splines.size(); i++){
  			CompoundShape cs = (CompoundShape) splines.get(i).tessellateMesh(samplingU, samplingV, 2);
  			for(int j = 0; j < cs.size(); j++){
  				try{
  					CompoundShape cs2 = (CompoundShape) cs.get(j);
  					for(int k = 0; k < cs2.size(); k++){
  						triangles.add((Triangle)cs2.get(k));
  					}
  				}catch(Exception e){
  					//
  				}					
  			}
  		}
  		modify();
  	}
  	
  	private void modify(){
  		ArrayList<PointND> centerPoints = new ArrayList<PointND>();
  		for (Triangle t : triangles) {
  			centerPoints.add(t.getPoint());
  		}
  		PointND center = DoublePrecisionPointUtil.getGeometricCenter(centerPoints);
  		Translation translation = new Translation(center.getAbstractVector().negated());
  		double max = 0;
  		for (Triangle t : triangles) {
  			t.applyTransform(translation);
  			PointND p = t.getPoint();
  			for (int i = 0; i < 3; i++) {
  				if (Math.abs(p.get(i)) > max) {
  					max = Math.abs(p.get(i));
  				}
  			}
  		}
  		AffineTransform affineTransform = new AffineTransform(
  				SimpleMatrix.I_3.dividedBy(max / 1.0),new SimpleVector(0, 0, 0));
  		for (Triangle t : triangles) {
  			// t.applyTransform(translation);
  			t.applyTransform(affineTransform);
  		}
  	}
  	
  	public void display(GLAutoDrawable arg0) {
  		if (!initialized) {
  			return;
  		}
  		GL4bc gl = (GL4bc) arg0.getGL();
  		gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
  		
  		gl.glMatrixMode(GL4bc.GL_PROJECTION);
  		gl.glLoadIdentity();
  		gl.glFrustum(-1.5, 1.5, -1.5, 1.5, 5, 15);
  
  		gl.glMatrixMode(GL4bc.GL_MODELVIEW);
  		gl.glLoadIdentity();
  
  		gl.glTranslated(0, 0, -10);
  		gl.glTranslatef(-translationX, -translationY, -translationZ);
  		gl.glRotatef(-rotationX, 1.0f, 0.0f, 0.0f);
  		gl.glRotatef(-(rotationY), 0.0f, 1.0f, 0.0f);
  
  		// Internal Coordinates we want to use for visualization: (0,0,0) to (1,1,1);
  		for (int i = 0; i < triangles.size(); i++) {
  			Triangle p = triangles.get(i);
  			if (colors == null) {
  					drawTriangle(gl, p, Color.WHITE);
  			} else {
  					Color col = colors.get(i);
  					drawTriangle(gl, p, col);
  			}
  		}
  	}
  
  	public void init(GLAutoDrawable arg0) {
  		// Perform the default GL initialization
  		GL4bc gl = (GL4bc) arg0.getGL();
  		gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  		gl.glShadeModel(GL4bc.GL_SMOOTH);
  		gl.glEnable(GL.GL_DEPTH_TEST);
  		if (initialized) {
  			return;
  		}
  		initialized = true;		
  	}
  
  	public void update(SurfaceBSpline... spline){
  		splines = new ArrayList<SurfaceBSpline>();
  		for(int i = 0; i < spline.length; i++){
  			splines.add(spline[i]);
  		}
  		setUp(sampling, sampling);
  	}
  	
  	public void dispose(GLAutoDrawable arg0) {
  		// TODO Auto-generated method stub
  		
  	}
  
  }