// // $Id: LightApplet.java,v 1.3 1998/06/26 13:42:06 min Exp min $ // // See the method "add_scene_choices", where the specific scene // filenames are added to the Choice scene_choice option menu. // package light; import java.applet.*; import java.awt.*; import java.lang.*; import java.io.*; import java.net.*; import myutil.*; import graphutil.*; import threed.*; import vectors.*; public class LightApplet extends Applet { private ThreeDCanvas my_canvas = new ThreeDCanvas(); private Renderer my_renderer = new Renderer(); private Scene my_scene; private static URL BASE_URL; Scenefile my_scenefile; private int last_selected; // layout stuff private GridBagLayout my_layout = new GridBagLayout(); private Font my_font = new Font("Helvetica", Font.BOLD, 12); private Font courier = new Font("Courier", Font.BOLD, 12); private Panel formula_panel = new Panel(); private String initial_string = "I = "; private String ambient_string = "k_a * I_a"; private String diffuse_string = "k_d * I_l * (N . L)"; private String specular_string = "k_s * I_l * (V . R)^n_s"; private TextField formula = new TextField(""); private Checkbox enable_ambient = new Checkbox("Enable ambient"); private Checkbox enable_diffuse = new Checkbox("Enable diffuse"); private Checkbox enable_specular = new Checkbox("Enable specular"); private Panel fields_panel = new Panel(); private TextField k_a_text = new TextField("k_a"); private TextField I_a_text = new TextField("I_a (R,G & B)"); private TextField k_d_text = new TextField("k_d"); private TextField I_l_text = new TextField("I_l (R,G & B)"); private TextField k_s_text = new TextField("k_s"); private TextField n_s_text = new TextField("n_s"); private TextField k_a_input = new TextField("0.5"); private TextField I_a_input = new TextField("0.5"); private TextField k_d_input = new TextField("0.7"); private TextField I_l_input = new TextField("2.0"); private TextField k_s_input = new TextField("0.7"); private TextField n_s_input = new TextField("5"); // button panel private Panel button_panel = new Panel(); private static final int ROTATE_STEP = 25; private Button rotate_scene_button = new Button("Rotate viewer by " + ROTATE_STEP + " degrees"); private Button rotate_light_button = new Button("Rotate light by " + ROTATE_STEP + " degrees"); private Button light_button = new Button("Light Scene"); private Checkbox attenuation_checkbox = new Checkbox("Light attenuation (1/d^2)"); private Button copy_button = new Button("Copy image to window"); private Choice scene_choice = new Choice(); // status panel & line private Panel status_panel = new Panel(); private TextField status = new TextField("Status: "); // lighting parameters private Double k_a = new Double(0.5); private Double k_d = new Double(0.7); private Double k_s = new Double(0.7); private Double n_s = new Double(5); private Double I_l = new Double(2.0); private Vector ambient_light = new Vector(0.5, 0.5, 0.5); private double light_angle = 0; private Vector light_position = new Vector(); private Light my_light; // viewing parameters private double viewing_angle = Math.PI/3.0; private Vector vrp = new Vector(5, 10, 2); private Vector up = new Vector(0, 0, 1); private Vector lookat = new Vector(0, 0, 1.5); public void start() { add_scene_choices(); create_layout(); create_formula(); create_light(); choose_scene(); set_vrp(viewing_angle); my_renderer.set_view_pars(vrp, lookat, up); my_renderer.set_backface_removal(true); my_renderer.set_lighting_parameters(k_a.doubleValue(), k_d.doubleValue(), k_s.doubleValue(), n_s.doubleValue()); my_renderer.set_ambient_light(ambient_light); my_renderer.add_light(my_light); my_renderer.set_lights(false); my_renderer.set_status_ptr(status); my_canvas.set_renderer(my_renderer); my_canvas.set_scene(my_scene); my_canvas.set_always_repaint(false); } // constructor public String getAppletInfo() { return "Lighting Applet v1.01 by Patrick Min, min@cs.princeton.edu\n$Id: LightApplet.java,v 1.3 1998/06/26 13:42:06 min Exp min $"; } // getAppletInfo private void set_vrp(double viewing_angle) { vrp.set(Math.cos(viewing_angle) * 12, Math.sin(viewing_angle) * 12, 2); } // set_vrp private void create_light() { light_position.set(Math.cos(light_angle) * 5, Math.sin(light_angle) * 5, 1); my_light = new Light(light_position, new Vector(I_l.doubleValue(), I_l.doubleValue(), I_l.doubleValue())); } // create_light private void create_formula() { StringBuffer temp = new StringBuffer(initial_string); if (enable_ambient.getState()) { temp.append(ambient_string); if (enable_diffuse.getState() || enable_specular.getState()) temp.append(" + "); } if (enable_diffuse.getState()) { temp.append(diffuse_string); if (enable_specular.getState()) temp.append(" + "); } if (enable_specular.getState()) { temp.append(specular_string); } if (temp.toString().equals(initial_string)) temp.append("0"); formula.setText(temp.toString()); } // create_formula private void add_scene_choices() { scene_choice.addItem("four_spheres.dat"); scene_choice.addItem("big_white_sphere.dat"); scene_choice.addItem("two_spheres.dat"); scene_choice.addItem("little_spheres.dat"); last_selected = 0; scene_choice.select(3); } // add_scene_choices private void create_layout() { this.setLayout(my_layout); formula_panel.setLayout(my_layout); fields_panel.setLayout(my_layout); button_panel.setLayout(my_layout); status_panel.setLayout(my_layout); // general constraints Layout.constrain(this, my_canvas, 0, 0, 3, 3, GridBagConstraints.BOTH, GridBagConstraints.NORTH, 1.0, 1.0, 2, 2, 2, 2); Layout.constrain(this, formula_panel, 0, 3, 3, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, 1.0, 0.2, 1, 1, 1, 1); Layout.constrain(this, fields_panel, 0, 4, 3, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, 1.0, 0.2, 1, 1, 1, 1); Layout.constrain(this, button_panel, 0, 6, 3, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, 1.0, 0.2, 1, 1, 1, 1); Layout.constrain(this, status_panel, 0, 7, 3, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.SOUTH, 1.0, 0.2, 1, 1, 1, 1); // formula panel constraints (formula & checkboxes) Layout.constrain(formula_panel, formula, 0, 0, 3, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, 1.0, 0.2, 1, 1, 1, 1); formula.setFont(courier); formula.setEditable(false); Layout.constrain(formula_panel, enable_ambient, 0, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.WEST, 1.0, 0.2, 1, 1, 1, 1); enable_ambient.setFont(my_font); enable_ambient.setState(true); Layout.constrain(formula_panel, enable_diffuse, 1, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, 1.0, 0.2, 1, 1, 1, 1); enable_diffuse.setFont(my_font); enable_diffuse.setState(true); Layout.constrain(formula_panel, enable_specular, 2, 1, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.EAST, 1.0, 0.2, 1, 1, 1, 1); enable_specular.setFont(my_font); enable_specular.setState(true); // input fields values & constraints k_a_text.setFont(courier); k_a_text.setEditable(false); I_a_text.setFont(courier); I_a_text.setEditable(false); k_d_text.setFont(courier); k_d_text.setEditable(false); I_l_text.setFont(courier); I_l_text.setEditable(false); k_s_text.setFont(courier); k_s_text.setEditable(false); n_s_text.setFont(courier); n_s_text.setEditable(false); k_a_input.setFont(my_font); I_a_input.setFont(my_font); k_d_input.setFont(my_font); I_l_input.setFont(my_font); k_s_input.setFont(my_font); n_s_input.setFont(my_font); Layout.constrain_field(fields_panel, k_a_text, 0, 0); Layout.constrain_field(fields_panel, k_a_input, 1, 0); Layout.constrain_field(fields_panel, k_d_text, 2, 0); Layout.constrain_field(fields_panel, k_d_input, 3, 0); Layout.constrain_field(fields_panel, k_s_text, 4, 0); Layout.constrain_field(fields_panel, k_s_input, 5, 0); Layout.constrain_field(fields_panel, I_a_text, 0, 1); Layout.constrain_field(fields_panel, I_a_input, 1, 1); Layout.constrain_field(fields_panel, I_l_text, 2, 1); Layout.constrain_field(fields_panel, I_l_input, 3, 1); Layout.constrain_field(fields_panel, n_s_text, 4, 1); Layout.constrain_field(fields_panel, n_s_input, 5, 1); // button panel values & constraints rotate_scene_button.setFont(my_font); rotate_light_button.setFont(my_font); light_button.setFont(my_font); attenuation_checkbox.setFont(my_font); copy_button.setFont(my_font); scene_choice.setFont(my_font); attenuation_checkbox.setState(false); Layout.constrain_button(button_panel, light_button, 0, 0); Layout.constrain_button(button_panel, attenuation_checkbox, 0, 1); Layout.constrain_button(button_panel, copy_button, 0, 2); Layout.constrain_button(button_panel, rotate_scene_button, 1, 0); Layout.constrain_button(button_panel, rotate_light_button, 1, 1); Layout.constrain_button(button_panel, scene_choice, 1, 2); // status panel status.setEditable(false); status.setFont(my_font); Layout.constrain_field(status_panel, status, 0, 0); } // create_layout private void create_scene() { GraphicsObject obj = create_light_object(); my_scene = null; my_scene = new Scene(); my_scene.add_object(obj); add_axes(my_scene); my_canvas.set_scene(my_scene); } // create_scene private GraphicsObject create_light_object() { GraphicsObject light_obj = new GraphicsObject(); double x = light_position.get_x(); double y = light_position.get_y(); double z = light_position.get_z(); MyPolygon p = new MyPolygon(); p.addPoint(x - 0.5, y, z); p.addPoint(x + 0.5, y, z); light_obj.add_polygon(p); p = new MyPolygon(); p.addPoint(x, y - 0.5, z); p.addPoint(x, y + 0.5, z); light_obj.add_polygon(p); p = new MyPolygon(); p.addPoint(x, y, z - 0.5); p.addPoint(x, y, z + 0.5); light_obj.add_polygon(p); light_obj.set_center(light_position); return light_obj; } // create_light_object private void add_axes(Scene scene) { GraphicsObject axes = new GraphicsObject(); axes.set_Color(Color.white); MyPolygon p = new MyPolygon(); p.addPoint(0, 0, 0); p.addPoint(3, 0, 0); axes.add_polygon(p); p = new MyPolygon(); p.addPoint(0, 0, 0); p.addPoint(0, 3, 0); axes.add_polygon(p); p = new MyPolygon(); p.addPoint(0, 0, 0); p.addPoint(0, 0, 3); axes.add_polygon(p); scene.add_object(axes); } // add_axes private boolean choose_scene() { // test if we've got something new if (scene_choice.getSelectedIndex() == last_selected) return false; else last_selected = scene_choice.getSelectedIndex(); try { BASE_URL = getCodeBase(); String url_string = new String(BASE_URL.toString() + "scenes/" + scene_choice.getSelectedItem()); status.setText("Status: reading scene from " + url_string); URL my_url = new URL(url_string); my_scenefile = new Scenefile(my_url.openStream()); create_scene(); my_scenefile.parse(my_scene); status.setText("Status: read " + url_string); } catch (MalformedURLException e) { System.out.println(e.getMessage()); } catch (IOException e) { System.out.println(e.getMessage()); } return true; } // choose_scene private String get_current_parameters() // convert current par's to String { StringBuffer result = new StringBuffer("I_l: " + I_l + " / "); if (enable_ambient.getState()) { result.append("k_a: " + k_a + ", I_a: " + I_a_input.getText() + " / "); } if (enable_diffuse.getState()) { result.append("k_d: " + k_d + " / "); } if (enable_specular.getState()) { result.append("k_s: " + k_s + ", n_s: " + n_s + " / "); } if (attenuation_checkbox.getState()) { result.append("attenuation"); } return (result.toString()); } // get_current_parameters public boolean action(Event e, Object arg) { if (e.target == rotate_scene_button) { viewing_angle += ROTATE_STEP * Math.PI/180; if (viewing_angle > 2*Math.PI) viewing_angle -= 2*Math.PI; set_vrp(viewing_angle); my_renderer.set_view_pars(vrp, lookat, up); my_canvas.invalidate(); my_canvas.paint(); return true; } // rotate_scene_button else if (e.target == rotate_light_button) { light_angle += ROTATE_STEP * Math.PI/180; if (light_angle > 2*Math.PI) light_angle -= 2*Math.PI; create_light(); my_scene.set_object(0, create_light_object()); my_renderer.set_light(0, my_light); my_canvas.invalidate(); my_canvas.paint(); return true; } // rotate_light_button else if (e.target == copy_button) { PictureFrame my_frame = new PictureFrame(my_canvas.get_image(), my_canvas.get_width(), my_canvas.get_height(), scene_choice.getSelectedItem()); my_frame.set_status_line(get_current_parameters()); } // copy button else if (e.target == light_button) { // get the values from the text fields, and set them in my_renderer get_lighting_parameters(); my_renderer.set_lighting_parameters(k_a.doubleValue(), k_d.doubleValue(), k_s.doubleValue(), n_s.doubleValue()); my_renderer.set_light(0, my_light); my_renderer.set_lights(true); my_canvas.invalidate(); my_canvas.paint(); my_renderer.set_lights(false); return true; } // light_button else if (e.target == scene_choice) { if (choose_scene()) { my_canvas.invalidate(); my_canvas.paint(); } return true; } // new scene choice else if (e.target == enable_ambient) { my_renderer.set_ambient(enable_ambient.getState()); create_formula(); return true; } // enable_ambient else if (e.target == enable_diffuse) { my_renderer.set_diffuse(enable_diffuse.getState()); create_formula(); return true; } // enable_diffuse else if (e.target == enable_specular) { my_renderer.set_specular(enable_specular.getState()); create_formula(); return true; } // enable_specular else if (e.target == attenuation_checkbox) { my_renderer.set_attenuation(attenuation_checkbox.getState()); return true; } return false; } // action private void get_lighting_parameters() { try { k_a = Double.valueOf(k_a_input.getText()); } catch (NumberFormatException exc) { System.out.println("Number format error"); k_a = new Double(0.5); k_a_input.setText("0.5"); } try { k_d = Double.valueOf(k_d_input.getText()); } catch (NumberFormatException exc) { System.out.println("Number format error"); k_d = new Double(0.7); k_d_input.setText(""); } try { k_s = Double.valueOf(k_s_input.getText()); } catch (NumberFormatException exc) { System.out.println("Number format error"); k_s = new Double(0.7); k_s_input.setText("0.7"); } try { n_s = Double.valueOf(n_s_input.getText()); } catch (NumberFormatException exc) { System.out.println("Number format error"); n_s = new Double(5); n_s_input.setText("5"); } Double i_a; try { i_a = Double.valueOf(I_a_input.getText()); } catch (NumberFormatException exc) { System.out.println("Number format error"); i_a = new Double(0.5); I_a_input.setText("0.5"); } ambient_light.set(i_a.doubleValue(), i_a.doubleValue(), i_a.doubleValue()); try { I_l = Double.valueOf(I_l_input.getText()); } catch (NumberFormatException exc) { System.out.println("Number format error"); I_l = new Double(2.0); I_l_input.setText("2.0"); } create_light(); } // get_lighting_parameters } // LightApplet class