001    package rendering;
002    
003    import java.io.IOException;
004    import java.net.URL;
005    import java.util.HashMap;
006    import java.util.Map;
007    
008    import javax.media.opengl.GL;
009    import javax.media.opengl.GLAutoDrawable;
010    import javax.media.opengl.GLEventListener;
011    
012    import physics3d.Angle;
013    import physics3d.GameConstants;
014    import physics3d.PhysicsShape;
015    import physics3d.Vect3;
016    import swingui.MainGUI;
017    
018    import com.sun.opengl.util.texture.Texture;
019    import com.sun.opengl.util.texture.TextureIO;
020    import components.GameObject;
021    import components.GameObjectClassification;
022    import components.GameSpace;
023    
024    /**
025     * Renderer is an immutable object that Renders the GameSpace.
026     *
027     *@specfield gs : GameSpace     // The GameSpace that Renderer renders 
028     */
029    
030    /*
031     * Abstraction Function
032     * AF(r) = RE, a renderer such that
033     * RE.gs = r.gs
034     */
035    
036    /*
037     * Rep Invariant
038     * gs != null
039     */
040    
041    public class Renderer extends ShapeRenderer implements GLEventListener {        
042            
043            private GameSpace gs;
044            private boolean playMode;
045            
046            private Map<GameObjectClassification, Texture> texMap;
047            
048            /**
049             * @effects constructs a new rendering instance.
050             */
051            public Renderer(GameSpace gs) {
052                    super();
053                    this.gs = gs;
054                    playMode = true;
055                    texMap = new HashMap<GameObjectClassification, Texture>();
056            }
057            
058            public void setPlayMode(boolean pm) {
059                    playMode = pm;
060            }
061            
062            /** performs one-time OpenGL initalization
063               * (non-Javadoc)
064               * @see javax.media.opengl.GLEventListener#init(javax.media.opengl.GLAutoDrawable)
065               */
066            public void init(GLAutoDrawable gld) {
067                    GL gl = gld.getGL();
068    
069                gl.glClear(GL.GL_COLOR_BUFFER_BIT);
070                gl.glEnable(GL.GL_DEPTH_TEST);
071              //  gl.glEnable(GL.GL_TEXTURE_2D);
072                
073                setView(gld);
074                addLight(gld);
075               // loadTextures();
076            }
077            
078            // configures the light source for the scene
079            private void addLight(GLAutoDrawable drawable) {
080                GL gl = drawable.getGL();
081                    gl.glEnable(GL.GL_DEPTH_TEST);
082            
083                float[] diffuseLight = {0.8f, 0.8f, 0.8f, 0.0f};    
084                float[] ambientLight = {0.5f, 0.5f, 0.5f, 0.0f};    
085                float[] lightPosition= {50f, 50f, -500f, 1f};
086                
087                //Ambient light component
088                gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, ambientLight, 0);
089                //Diffuse light component
090                gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, diffuseLight, 0);
091                //Light position
092                gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, lightPosition, 0);
093                 
094                //Enable the first light and the lighting mode
095                gl.glEnable(GL.GL_LIGHT0);
096                gl.glEnable(GL.GL_LIGHTING);
097            }
098            
099            private void setView(GLAutoDrawable gld) {
100                    GL gl = gld.getGL();
101                    
102                    gl.glMatrixMode(GL.GL_PROJECTION);
103                gl.glLoadIdentity();
104                glu.gluPerspective(90, gld.getWidth() / gld.getHeight(), 50, 100);
105    
106                gl.glMatrixMode(GL.GL_MODELVIEW);
107                gl.glLoadIdentity();
108               // glu.gluLookAt(50, -50, 50, 50, 50, 0, 0, 0, -1);
109                glu.gluLookAt(50, 50, -50,
110                                      50, 50, 0,
111                                      0, -1, 0);
112                                      
113                                    
114            }
115            
116            private void loadTextures() {
117                    if (texMap.isEmpty()) {
118                            Map<GameObjectClassification, String> tl = gs.getTexLocations();
119                            for(GameObjectClassification goc : tl.keySet()) {
120                                    Texture t = loadTexture(tl.get(goc));
121                                    texMap.put(goc, t);
122                            }
123                    }
124            }
125              
126            private Texture loadTexture(String fileName) {
127                    Texture tex = null;
128                    try {
129                            URL u = MainGUI.getFile(".");
130                            System.err.println("u="+u);
131                            u = MainGUI.getFile(fileName);
132                            System.err.println("u="+u);
133                            tex = TextureIO.newTexture(u, false, "");
134                            tex.setTexParameteri(GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
135                            tex.setTexParameterf(GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
136                    }
137                    catch (IOException ex) {
138                            //System.out.println("error loading texture = " + ex.getMessage());
139                    }
140                    return tex;     
141            }
142            
143            /**
144             * @modifies texMap
145             * @effects clears the Textures stored in texMap
146             */
147            public void clearTextures() {
148                    texMap.clear();
149            }
150            
151            /**
152               * Renders all displayable objects
153               * @see javax.media.opengl.GLEventListener#display(javax.media.opengl.GLAutoDrawable)
154               */
155            public void display(GLAutoDrawable drawable) {
156                    GL gl = drawable.getGL();
157            
158                    gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
159                    
160                    //draws the grid if in build mode
161                    if (!playMode) {
162                            drawGrid(drawable, 0);
163                    } else {
164                            //draws the box if in play mode
165                            drawBox(drawable);
166                    }
167                    
168                    loadTextures();
169                    
170                    //draws GameObjects
171                    for (GameObject go : gs.getObjects()) {
172                            if (!go.isVisible()) 
173                                    continue;
174                            Vect3 center = go.getCenter().times(GameConstants.L);
175                            ////System.out.println(go.getName() + " " + center.toString());
176                            Vect3 ov = go.getOrientVector();
177                            Angle oa = go.getOrientAngle();
178                            Texture t = texMap.get(go.getGOClassification());
179                            if (go.isSelected()) {
180                                    t = texMap.get(GameObjectClassification.SELECTED);
181                }
182                            for (PhysicsShape ps : go.getShape().getParts()) {
183                                    switch (ps.getShapeClassification()) {
184                                            case LATERAL_CYLINDER:
185                                                    drawLateralCylinder(drawable, center, ov, oa, ps, t);
186                                                    break;
187                                            case PLANE_CIRCLE:
188                                                    drawPlaneCircle(drawable, center, ov, oa, ps, t);
189                                                    break;
190                                            case PLANE_POLYGON:
191                                                    drawPlanePolygon(drawable, center, ov, oa, ps, t);
192                                                    break;
193                                            case SPHERE:
194                                            //      //System.out.println(center + " renderer");
195                                                    drawSphere(drawable, center, ov, oa, ps, t);
196                                                    break;
197                                            case TORUS:
198                                                    break;
199                                    }
200                            }       
201                    
202                    }       
203            }
204    
205            private void drawGrid(GLAutoDrawable drawable, double z) {
206                    GL gl = drawable.getGL();
207                    gl.glLineWidth(1);
208                    gl.glBegin(GL.GL_LINES);
209                    for (int i = 0; i <= 100; i += GameConstants.L) {
210                            //vertical lines
211                            gl.glVertex3d(i, 0, z);
212                            gl.glVertex3d(i, 100, z);
213                            //horizontal lines
214                            gl.glVertex3d(0, i, z);
215                            gl.glVertex3d(100, i, z);
216                    }                 
217                    gl.glEnd();
218            }
219            
220    
221            private void drawBox(GLAutoDrawable drawable) {
222                    GL gl = drawable.getGL();
223                    
224                    gl.glBegin(GL.GL_LINES);
225                    //inner box top lines
226                    gl.glVertex3d(0, 0, 50);
227                    gl.glVertex3d(100, 0, 50);
228                    gl.glVertex3d(0, 0, 0);
229                    gl.glVertex3d(0, 0, 50);
230                    
231                    //right line
232                    gl.glVertex3d(100, 0, 50);
233                    gl.glVertex3d(100, 100, 50);
234                    gl.glVertex3d(100, 0, 0);
235                    gl.glVertex3d(100, 0, 50);
236            
237                    //bottom line
238                    gl.glVertex3d(100, 100, 50);
239                    gl.glVertex3d(0, 100, 50);
240                    gl.glVertex3d(100, 100, 0);
241                    gl.glVertex3d(100, 100, 50);
242                    
243                    //left line
244                    gl.glVertex3d(0, 100, 50);
245                    gl.glVertex3d(0, 0, 50);
246                    gl.glVertex3d(0, 100, 0);
247                    gl.glVertex3d(0, 100, 50);
248                              
249                    gl.glEnd();
250            }
251                    
252            /**
253             * @requires ps (instance of Torus)
254             */
255            /*
256            private void drawTorus(GLAutoDrawable drawable, Vect3 center, PhysicsShape ps) {
257                    throw new RuntimeException("Method not implemented");
258            }
259            */
260            
261            /**
262             * method required by GLEventListener interface
263             */
264            public void reshape(GLAutoDrawable drawable, int x, int y, int width,
265                            int height) {
266            }       
267            
268            /**
269             * method required by GLEventListener interface
270             */
271            public void displayChanged(GLAutoDrawable drawable, boolean modeChanged,
272                            boolean deviceChanged) {
273            }
274            
275            /**
276             * @return the GameSpace that this Renderer renders
277             */
278            public GameSpace getGameSpace() {
279                    return gs;
280            }
281            
282            /**
283             * @requires g != null
284             * @modifies gs
285             * @effects sets gs to g
286             */
287            public void setGameSpace(GameSpace g) {
288                    gs = g; 
289            }
290    
291    }