// // $Id: BasicRenderer.java,v 1.1 1998/08/03 16:00:22 min Exp min $ // // The renderer without the lighting stuff // package graphutil; import java.lang.*; import java.awt.*; import vectors.*; public class BasicRenderer { public static final boolean DEBUG = false; public static final int PERSPECTIVE = 0; public static final int PARALLEL = 1; private int projection_type = PERSPECTIVE; protected boolean backface_removal = false; protected Matrix modelview = new Matrix(); protected Matrix normalize = new Matrix(); protected Matrix viewport = new Matrix(); protected Vector vrp; protected Vector u, v, n; protected double viewplane_distance; private double z_front, z_back; protected double x_min, x_max, y_min, y_max; // viewplane boundaries protected int image_width, image_height; protected double aspect_ratio; // width divided by height public BasicRenderer() { vrp = new Vector(3, 6, 2); // view reference point v = new Vector(0, 0, 1); // view up vector n = new Vector(3, 6, 2); // view plane normal compute_modelview_matrix(); viewplane_distance = 3; z_front = 1; z_back = 20; x_min = -1; x_max = 1; y_min = -1; y_max = 1; compute_viewport_matrix(400, 300); compute_normalize_matrix(); } // constructor public void set_view_pars(Vector new_vrp, Vector lookat, Vector up) { vrp.set(new_vrp); n = lookat.subtract(vrp); v.set(up); if (BasicRenderer.DEBUG) { System.out.print("New VRP: "); vrp.print(); System.out.println(); } compute_modelview_matrix(); } // set_vrp public Vector get_vrp() { return vrp; } // get_vrp public double get_viewplane_distance() { return viewplane_distance; } // get_viewplane_distance public void set_viewplane_distance(double new_dist) { viewplane_distance = new_dist; } // set_viewplane_distance public void set_viewplane_dimensions(double new_min_x, double new_max_x, double new_min_y, double new_max_y) { x_min = new_min_x; x_max = new_max_x; y_min = new_min_y; y_max = new_max_y; compute_normalize_matrix(); } // set_viewplane_dimensions public void set_projection_type(int new_type) { projection_type = new_type; } // set_projection_type public void set_backface_removal(boolean new_value) { backface_removal = new_value; } // set_backface_removal protected void compute_modelview_matrix() { n.normalize(); u = n.cross_product(v); // keep it right handed u.normalize(); v = u.cross_product(n); Matrix translation = new Matrix(); Vector neg_vrp = new Vector(vrp); neg_vrp.negate(); translation.translate(neg_vrp); modelview.set(u, v, n); modelview = modelview.matrix_multiply(translation); if (BasicRenderer.DEBUG) { System.out.println("Modelview matrix:"); modelview.print(); } } // compute_modelview_matrix public Matrix get_modelview_matrix() { return modelview; } // get_modelview_matrix private void compute_normalize_matrix() { // assuming a view coordinates window from (-1, -1) to (1, 1) double local_x_max = x_max * aspect_ratio; double local_x_min = x_min * aspect_ratio; double scale_x = 2/(local_x_max - local_x_min); double scale_y = 2/(y_max - y_min); double scale_z = 2.0/(z_back - z_front); double trans_x = -1.0 - local_x_min * scale_x; double trans_y = -1.0 - y_min * scale_y; double trans_z = -1.0 - z_front * scale_z; Matrix normalize_scale = new Matrix(); normalize_scale.scale(scale_x, scale_y, scale_z); Matrix normalize_trans = new Matrix(); normalize_trans.translate(trans_x, trans_y, trans_z); normalize = normalize_trans.matrix_multiply(normalize_scale); if (BasicRenderer.DEBUG) { System.out.println("Normalization matrix:"); normalize.print(); } } // compute_normalize_matrix public void compute_viewport_matrix(int new_width, int new_height) { image_width = new_width; image_height = new_height; aspect_ratio = (double) image_width/(double) image_height; compute_normalize_matrix(); // - sign in both matrices to move origin to bottom left viewport.scale(image_width/2, -image_height/2, 0); Matrix viewport_translate = new Matrix(); viewport_translate.translate(1, -1, 0); viewport = viewport.matrix_multiply(viewport_translate); if (BasicRenderer.DEBUG) { System.out.println("Viewport matrix:"); viewport.print(); } } // compute_viewport_matrix public Vector transform(Vector world) { Vector transformed = new Vector(modelview.vec_postmultiply(world)); if (projection_type == BasicRenderer.PERSPECTIVE) { double h = transformed.get_z()/viewplane_distance; if (h == 0) return new Vector(0, 0, 0); transformed = transformed.divided_by(h); } else { Matrix par_proj = new Matrix(); par_proj.set(10, 0); transformed = par_proj.vec_postmultiply(transformed); } // or just set z coordinate to 0 transformed = normalize.vec_postmultiply(transformed); transformed = viewport.vec_postmultiply(transformed); return transformed; } // transform public void render(Graphics g, Scene s) { Matrix saved_modelview = new Matrix(modelview); Matrix viewport_matrix = new Matrix(viewport); viewport_matrix = viewport_matrix.matrix_multiply(normalize); if (BasicRenderer.DEBUG) System.out.println("Request to render scene"); // first set all objects to "not rendered yet" for(int i=0; i < s.get_nr_objects(); i++) s.get_object(i).set_rendered(false); // loop over objects in scene for(int i=0; i < s.get_nr_objects(); i++) { GraphicsObject obj = s.get_object(i); if (obj.get_state() == GraphicsObject.DONT_DISPLAY) continue; // check if obj has matrix if (obj.has_matrix()) modelview = modelview.matrix_multiply(obj.get_matrix()); if (obj.is_sphere()) { // if it's a sphere, do something else Vector center = obj.get_center(); // this is not necessarily the outermost point... Vector outside = v.multiplied_by(obj.get_radius()); outside = outside.add(center); Vector transform_center = transform(center); Vector transform_outside = transform(outside); int dev_radius = Math.abs( (int) (Math.round(transform_outside.get_y() - transform_center.get_y()))); if (obj.get_state() == GraphicsObject.DISPLAY_GREY) g.setColor(Color.gray); else g.setColor(obj.get_Color(0)); g.drawOval( (int) Math.round(transform_center.get_x()) - dev_radius, (int) Math.round(transform_center.get_y()) - dev_radius, dev_radius * 2, dev_radius * 2); } // object is a sphere else { // loop over polygons in object for(int j=0; j < obj.get_nr_polygons(); j++) { MyPolygon p = obj.get_polygon(j); // if backface_removal, check if we can see this polygon if (backface_removal) { if (p.get_normal() != null) { Vector temp = p.get_point(0).subtract(vrp); double dot_product = temp.dot_product(p.get_normal()); if (dot_product > 0) continue; } } // if backface_removal if (obj.get_state() == GraphicsObject.DISPLAY_GREY) g.setColor(Color.gray); else g.setColor(obj.get_Color(j)); int new_x = 0, new_y = 0, first_x = 0, first_y = 0, prev_x = 0, prev_y = 0; for(int k=0; k < p.get_nr_points(); k++) { Vector transformed = transform(p.get_point(k)); new_x = (int) transformed.get_x(); new_y = (int) transformed.get_y(); if (k==0) { first_x = new_x; first_y = new_y; } else g.drawLine(prev_x, prev_y, new_x, new_y); prev_x = new_x; prev_y = new_y; } // for, all points if (p.get_closed()) g.drawLine(new_x, new_y, first_x, first_y); } // for, all polygons } // else, object is list of polygons obj.set_rendered(true); if (obj.has_matrix()) modelview.set(saved_modelview); } // for, all objects } // render } // BasicRenderer class