OSDN Git Service

7a1d20f75bbafd94e4b52916348bbdf1cc2c07a6
[mikumikustudio/MikuMikuStudio.git] / src / com / jme / system / DisplaySystem.java
1 /*
2  * Copyright (c) 2003-2009 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17  *   may be used to endorse or promote products derived from this software
18  *   without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 package com.jme.system;
34
35 import java.util.Collection;
36 import java.util.HashMap;
37 import java.util.Iterator;
38 import java.util.Map;
39 import java.util.logging.Logger;
40
41 import sun.misc.Service;
42 import sun.misc.ServiceConfigurationError;
43
44 import com.jme.image.Image;
45 import com.jme.input.joystick.JoystickInput;
46 import com.jme.math.Ray;
47 import com.jme.math.Vector2f;
48 import com.jme.math.Vector3f;
49 import com.jme.renderer.RenderContext;
50 import com.jme.renderer.Renderer;
51 import com.jme.renderer.TextureRenderer;
52 import com.jme.scene.state.RenderState;
53 import com.jme.system.canvas.CanvasConstructor;
54 import com.jme.system.canvas.JMECanvas;
55 import com.jme.system.dummy.DummySystemProvider;
56 import com.jme.system.jogl.JOGLSystemProvider;
57 import com.jme.system.lwjgl.LWJGLSystemProvider;
58
59 /**
60  * <code>DisplaySystem</code> defines an interface for system creation.
61  * Specifically, any implementing class will create a window for rendering. It
62  * also should create the appropriate <code>Renderer</code> object that allows
63  * the client to render to this window. <p/> Implementing classes should check
64  * for the appropriate libraries to insure these libraries are indeed installed
65  * on the system. This will allow users to cleanly exit if an improper library
66  * was chosen for rendering. <p/> Example usage: <p/> <code>
67  * DisplaySystem ds = DisplaySystem.getDisplaySystem();<br>
68  * ds.createWindow(640,480,32,60,true);<br>
69  * Renderer r = ds.getRenderer();<br>
70  * </code>
71  * 
72  * @author Mark Powell
73  * @author Gregg Patton
74  * @author Joshua Slack - Optimizations, Headless rendering, RenderContexts, AWT integration
75  * @version $Id: DisplaySystem.java,v 1.67 2007/10/05 22:41:20 nca Exp $
76  * @see com.jme.renderer.Renderer
77  */
78 public abstract class DisplaySystem {
79
80     private static final Logger LOGGER = Logger.getLogger(DisplaySystem.class.getName());
81
82     /** The display system that has been created. */
83     private static volatile SystemProvider system;
84
85     /**
86      * Width selected for the renderer.
87      */
88     protected int width;
89
90     /**
91      * height selected for the renderer.
92      */
93     protected int height;
94
95     /**
96      * Bit depth selected for renderer.
97      */
98     protected int bpp;
99
100     /**
101      * Frequency selected for renderer.
102      */
103     protected int frq;
104
105     /**
106      * Is the display full screen?
107      */
108     protected boolean fs;
109
110     /**
111      * Is the display created already?
112      */
113     protected boolean created;
114
115     /**
116      * Alpha bits to use for the renderer.
117      */
118     protected int alphaBits = 0;
119
120     /**
121      * Depth bits to use for the renderer.
122      */
123     protected int depthBits = 8;
124
125     /**
126      * Stencil bits to use for the renderer.
127      */
128     protected int stencilBits = 0;
129
130     /**
131      * Number of samples to use for the multisample buffer.
132      */
133     protected int samples = 0;
134
135     /**
136      * Gamma value of display - default is 1.0f. 0->infinity
137      */
138     protected float gamma = 1.0f;
139
140     /**
141      * Brightness value of display - default is 0f. -1.0 -> 1.0
142      */
143     protected float brightness = 0;
144
145     /**
146      * Contrast value of display - default is 1.0f. 0->infinity
147      */
148     protected float contrast = 1;
149
150     private static final Map<String, SystemProvider> systemProviderMap = new HashMap<String, SystemProvider>();
151             
152     private Map<String, Class<? extends CanvasConstructor>> canvasConstructRegistry = new HashMap<String, Class<? extends CanvasConstructor>>();
153
154     /**
155      * A new display system has been created. The default static display system
156      * is set to the newly created display system.
157      */
158     protected DisplaySystem() {
159     }
160
161     /**
162      * <code>getDisplaySystem</code> is a factory method that creates the
163      * appropriate display system specified by the key parameter. If the key
164      * given is not a valid identifier for a specific display system, the
165      * fallback default is returned.
166      * 
167      * @param key
168      *            the display system to use.
169      * @return the appropriate display system specified by the key.
170      */
171     public static DisplaySystem getDisplaySystem(String key) {
172         // force to initialize joystick input before display system as there are
173         // LWJGL issues with creating it afterwards.
174         // FIXME What about the impact on other display systems?
175         JoystickInput.get();
176
177         try {
178             setSystemProvider(getCachedSystemProvider(key));
179         }
180         catch (IllegalStateException alreadySet) {
181             LOGGER.warning(alreadySet.getMessage());
182         }
183
184         return getDisplaySystem();
185     }
186
187     private static SystemProvider getCachedSystemProvider(String providerId) {
188         return getSystemProviderMap().get(providerId);
189     }
190
191     private static Map<String, SystemProvider> getSystemProviderMap()
192             throws ServiceConfigurationError {
193         if (systemProviderMap.isEmpty()) {
194             @SuppressWarnings("unchecked")
195             Iterator<SystemProvider> displayProviders = Service.providers(SystemProvider.class);
196             while (displayProviders.hasNext()) {
197                 SystemProvider provider = (SystemProvider) displayProviders
198                         .next();
199                 systemProviderMap.put(provider.getProviderIdentifier(),
200                         provider);
201             }
202
203             // if the provider map is still empty (no providers found),
204             if (systemProviderMap.isEmpty()) {
205                 // insert the default
206                 SystemProvider sp = new LWJGLSystemProvider();
207                 systemProviderMap.put(sp.getProviderIdentifier(), sp);
208                 sp = new JOGLSystemProvider();
209                 systemProviderMap.put(sp.getProviderIdentifier(), sp);
210                 sp = new DummySystemProvider();
211                 systemProviderMap.put(sp.getProviderIdentifier(), sp);
212             }
213         }
214
215         return systemProviderMap;
216     }
217
218     /**
219      * Returns all available system providers
220      *
221      * @return String array containing all available system providers
222      */
223     public static String[] getSystemProviderIdentifiers() {
224         Collection<String> ids = getSystemProviderMap().keySet();
225
226         String[] names = new String[ids.size()];
227
228         ids.toArray(names);
229
230         return names;
231     }
232
233     /**
234      * Returns the currently system provider.  If no system provider has been
235      * set, then a default LWJGL system provider is used.
236      * 
237      * @return The current system provider.
238      */
239     public static SystemProvider getSystemProvider() {
240         SystemProvider currentProvider = system;
241         if (currentProvider != null) {
242             return currentProvider;
243         }
244         
245         // if none defined by Service.providers, use fallback default
246         synchronized (DisplaySystem.class) {
247             if (system == null) {
248                 system = new LWJGLSystemProvider();
249             }
250             
251             return system;
252         }
253     }
254
255     
256     /**
257      * Sets the SystemProvider to be provider.
258      * <p>
259      * Once installed, the provider cannot be replaced.
260      * 
261      * @param provider
262      *          the SystemProvider to install.  if <code>null</code>, no
263      *          provider is set.
264      * @throws IllegalStateException
265      *          if a provider was previous installed.
266      * 
267      * @since 2.0
268      */
269     public static synchronized void setSystemProvider(SystemProvider provider) throws IllegalStateException {
270        if (system != null) {
271            throw new IllegalStateException("SystemProvider already set");
272        }
273        
274        system = provider;
275     }
276     
277     /**
278      * Returns the currently created display system.
279      * 
280      * @return The current display system.
281      */
282     public static DisplaySystem getDisplaySystem() {
283         return getSystemProvider().getDisplaySystem();
284     }
285
286     /**
287      * Sets a new width for the display system
288      * @param width
289      */
290     public void setWidth(int width) {
291         this.width = width;
292     }
293
294     /**
295      * Returns the set width for the display system.
296      * 
297      * @return The set width.
298      */
299     public int getWidth() {
300         return width;
301     }
302
303     /**
304      * Sets a new height for the display system
305      * @param height
306      */
307     public void setHeight(int height) {
308         this.height = height;
309     }
310
311     /**
312      * Returns the set height for the display system.
313      * 
314      * @return The set height.
315      */
316     public int getHeight() {
317         return height;
318     }
319
320     /**
321      * Returns the set bitdepth for the display system.
322      * 
323      * @return the set bit depth
324      */
325     public int getBitDepth() {
326         return bpp;
327     }
328
329     /**
330      * Returns the set frequency for the display system.
331      * 
332      * @return the set frequency
333      */
334     public int getFrequency() {
335         return frq;
336     }
337
338     /**
339      * Returns whether or not the display system is set to be full screen.
340      * 
341      * @return true if full screen
342      */
343     public boolean isFullScreen() {
344         return fs;
345     }
346
347     /**
348      * <code>getAdapter</code> returns the name of the underlying system's
349      * graphics adapter for debugging / display purposes.
350      * 
351      * @return the adapter's name as a String
352      */
353     public abstract String getAdapter();
354
355     /**
356      * <code>getDriverVersion</code> returns a string representing the version
357      * of driver installed on the underlying system.
358      * 
359      * @return the version as a String
360      */
361     public abstract String getDriverVersion();
362     
363     /**
364      * <code>getDisplayVendor</code> returns the vendor of the graphics
365      * adapter
366      * 
367      * @return The adapter vendor
368      */
369     public abstract String getDisplayVendor();
370
371     /**
372      * <code>getDisplayRenderer</code> returns details of the adapter
373      * 
374      * @return The adapter details
375      */
376     public abstract String getDisplayRenderer();
377
378     /**
379      * <code>getDisplayAPIVersion</code> returns the API version supported
380      * 
381      * @return The api version supported
382      */
383     public abstract String getDisplayAPIVersion();
384
385     /**
386      * <code>isValidDisplayMode</code> determines if the given parameters
387      * constitute a valid display mode on this system. Returning true does not
388      * necessarily guarantee that the system is capable of running in the
389      * specified display mode, merely that it <i>believes </i> it is possible.
390      * 
391      * @param width
392      *            the width/horizontal resolution of the display.
393      * @param height
394      *            the height/vertical resolution of the display.
395      * @param bpp
396      *            the bit depth of the display.
397      * @param freq
398      *            the frequency of refresh of the display (in Hz).
399      */
400     public abstract boolean isValidDisplayMode(int width, int height, int bpp,
401             int freq);
402
403     /**
404      * <code>setVSyncEnabled</code> attempts to enable or disable monitor
405      * vertical synchronization. The method is a "best attempt" to change the
406      * monitor vertical refresh synchronization, and is <b>not </b> guaranteed
407      * to be successful. This is dependant on OS.
408      * 
409      * @param enabled
410      *            <code>true</code> to synchronize, <code>false</code> to
411      *            ignore synchronization
412      */
413     public abstract void setVSyncEnabled(boolean enabled);
414
415     /**
416      * Sets the title of the display system. This is usually reflected by the
417      * renderer as text in the menu bar.
418      * 
419      * @param title
420      *            The new display title.
421      */
422     public abstract void setTitle(String title);
423
424     /**
425      * <code>createWindow</code> creates a window with the desired settings.
426      * The width and height defined by w and h define the size of the window if
427      * fullscreen is false, otherwise it defines the resolution of the
428      * fullscreen display. The color depth is defined by bpp. The implementing
429      * class should only allow 16, 24, and 32. The monitor frequency is defined
430      * by the frq parameter and should not exceed the capabilities of the
431      * connected hardware, the implementing class should attempt to assure this
432      * does not happen. Lastly, the boolean flag fs determines if the display
433      * should be windowed or fullscreen. If false, windowed is chosen. This
434      * window will be placed in the center of the screen initially. If true
435      * fullscreen mode will be entered with the appropriate settings.
436      * 
437      * @param w
438      *            the width/horizontal resolution of the display.
439      * @param h
440      *            the height/vertical resolution of the display.
441      * @param bpp
442      *            the color depth of the display.
443      * @param frq
444      *            the frequency of refresh of the display.
445      * @param fs
446      *            flag determining if fullscreen is to be used or not. True will
447      *            use fullscreen, false will use windowed mode.
448      */
449     public abstract void createWindow(int w, int h, int bpp, int frq, boolean fs);
450
451     /**
452      * <code>createHeadlessWindow</code> creates a headless window with the
453      * desired settings. A headless window is a rendering target that is not
454      * shown on screen. It is useful for doing offline rendering, integration
455      * and so forth. You can not have a regular and headless window at the same
456      * time. The width and height defined by w and h define the size of the
457      * window. The color depth is defined by bpp.
458      * 
459      * @param w
460      *            the width/horizontal resolution of the display.
461      * @param h
462      *            the height/vertical resolution of the display.
463      * @param bpp
464      *            the color depth of the display.
465      */
466     public abstract void createHeadlessWindow(int w, int h, int bpp);
467
468     /**
469      * <code>createCanvas</code> should create a canvas object with the
470      * desired settings. The width and height defined by w and h define the size
471      * of the canvas.  Makes an AWT canvas by default.
472      * 
473      * @param w
474      *            the width/horizontal resolution of the display.
475      * @param h
476      *            the height/vertical resolution of the display.
477      */
478     public JMECanvas createCanvas(int w, int h) {
479         return createCanvas(w, h, "AWT", new HashMap<String, Object>());
480     }
481
482     /**
483      * <code>createCanvas</code> should create a canvas object with the desired
484      * settings. The width and height defined by w and h define the size of the
485      * canvas.
486      * 
487      * @param w
488      *            the width/horizontal resolution of the display.
489      * @param h
490      *            the height/vertical resolution of the display.
491      * @param type
492      *            the type of canvas to make.  e.g. "AWT", "SWT".
493      * @param props
494      *            the properties we want to use (if any) for constructing our
495      *            canvas.
496      */
497     public abstract JMECanvas createCanvas(int w, int h, String type, HashMap<String, Object> props);
498
499     public void registerCanvasConstructor(String type, Class<? extends CanvasConstructor> constructorClass) {
500         canvasConstructRegistry.put(type, constructorClass);
501     }
502
503     public CanvasConstructor makeCanvasConstructor(String type) {
504         Class<? extends CanvasConstructor> constructorClass = canvasConstructRegistry.get(type);
505         if (constructorClass == null) {
506             throw new JmeException("Unregistered canvas type: "+type);
507         }
508         CanvasConstructor constructor;
509         try {
510             constructor = constructorClass.newInstance();
511         } catch (Exception e) {
512             throw new JmeException("Unable to instantiate canvas constructor: "+constructorClass);
513         }
514         return constructor;
515     }
516
517     /**
518      * <code>recreateWindow</code> recreates a window with the desired
519      * settings.
520      * 
521      * @param w
522      *            the width/horizontal resolution of the display.
523      * @param h
524      *            the height/vertical resolution of the display.
525      * @param bpp
526      *            the color depth of the display.
527      * @param frq
528      *            the frequency of refresh of the display.
529      * @param fs
530      *            flag determining if fullscreen is to be used or not. True will
531      *            use fullscreen, false will use windowed mode.
532      */
533     public abstract void recreateWindow(int w, int h, int bpp, int frq,
534             boolean fs);
535
536     /**
537      * <code>getRenderer</code> returns the <code>Renderer</code>
538      * implementation that is compatible with the chosen
539      * <code>DisplaySystem</code>. For example, if
540      * <code>LWJGLDisplaySystem</code> is used, the returned
541      * <code>Renderer</code> will be</code> LWJGLRenderer</code>.
542      * 
543      * @return the appropriate <code>Renderer</code> implementation that is
544      *         compatible with the used <code>DisplaySystem</code>.
545      * @see com.jme.renderer.Renderer
546      */
547     public abstract Renderer getRenderer();
548
549     /**
550      * <code>setRenderer</code> sets the <code>Renderer</code> object that
551      * is to be used by this display. The implementing class should take
552      * measures to insure that the given Renderer is compatible with the
553      * Display.
554      * 
555      * @param r
556      *            the Renderer to set for this display.
557      */
558     public abstract void setRenderer(Renderer r);
559
560     /**
561      * <code>isCreated</code> returns the current status of the display
562      * system. If the window and renderer are created, true is returned,
563      * otherwise false.
564      * 
565      * @return whether the display system is created.
566      */
567     public boolean isCreated() {
568         return created;
569     }
570     
571     /**
572      * <code>isActive</code> returns true if the display is active.
573      * 
574      * @return whether the display system is active.
575      */
576     public abstract boolean isActive();
577
578
579     /**
580      * <code>isClosing</code> notifies if the window is currently closing.
581      * This could be caused via the application itself or external interrupts
582      * such as alt-f4 etc.
583      * 
584      * @return true if the window is closing, false otherwise.
585      */
586     public abstract boolean isClosing();
587
588     /**
589      * <code>reset</code> cleans up the display system for closing or
590      * restarting.
591      */
592     public abstract void reset();
593
594     /**
595      * <code>close</code> shutdowns and destroys any window contexts.
596      */
597     public abstract void close();
598
599     /**
600      * Returns the minimum bits per pixel in the alpha buffer.
601      * 
602      * @return the int value of alphaBits.
603      */
604     public int getMinAlphaBits() {
605         return alphaBits;
606     }
607
608     /**
609      * Sets the minimum bits per pixel in the alpha buffer.
610      * 
611      * @param alphaBits -
612      *            the new value for alphaBits
613      */
614     public void setMinAlphaBits(int alphaBits) {
615         this.alphaBits = alphaBits;
616     }
617
618     /**
619      * Returns the minimum bits per pixel in the depth buffer.
620      * 
621      * @return the int value of depthBits.
622      */
623     public int getMinDepthBits() {
624         return depthBits;
625     }
626
627     /**
628      * Sets the minimum bits per pixel in the depth buffer.
629      * 
630      * @param depthBits -
631      *            the new value for depthBits
632      */
633     public void setMinDepthBits(int depthBits) {
634         this.depthBits = depthBits;
635     }
636
637     /**
638      * Returns the minimum bits per pixel in the stencil buffer.
639      * 
640      * @return the int value of stencilBits.
641      */
642     public int getMinStencilBits() {
643         return stencilBits;
644     }
645
646     /**
647      * Sets the minimum bits per pixel in the stencil buffer.
648      * 
649      * @param stencilBits -
650      *            the new value for stencilBits
651      */
652     public void setMinStencilBits(int stencilBits) {
653         this.stencilBits = stencilBits;
654     }
655
656     /**
657      * Returns the minimum samples in multisample buffer.
658      * 
659      * @return the int value of samples.
660      */
661     public int getMinSamples() {
662         return samples;
663     }
664
665     /**
666      * Sets the minimum samples in the multisample buffer.
667      * 
668      * @param samples -
669      *            the new value for samples
670      */
671     public void setMinSamples(int samples) {
672         this.samples = samples;
673     }
674
675     /**
676      * Returns the brightness last requested by this display.
677      * 
678      * @return brightness - should be between -1 and 1.
679      */
680     public float getBrightness() {
681         return brightness;
682     }
683
684     /**
685      * Note: This affects the whole screen, not just the game window.
686      * 
687      * @param brightness
688      *            The brightness to set (set -1 to 1) default is 0
689      */
690     public void setBrightness(float brightness) {
691         this.brightness = brightness;
692         updateDisplayBGC();
693     }
694
695     /**
696      * @return Returns the contrast.
697      */
698     public float getContrast() {
699         return contrast;
700     }
701
702     /**
703      * Note: This affects the whole screen, not just the game window.
704      * 
705      * @param contrast
706      *            The contrast to set (set greater than 0) default is 1
707      */
708     public void setContrast(float contrast) {
709         this.contrast = contrast;
710         updateDisplayBGC();
711     }
712
713     /**
714      * @return Returns the gamma.
715      */
716     public float getGamma() {
717         return gamma;
718     }
719
720     /**
721      * Note: This affects the whole screen, not just the game window.
722      * 
723      * @param gamma
724      *            The gamma to set (default is 1)
725      */
726     public void setGamma(float gamma) {
727         this.gamma = gamma;
728         updateDisplayBGC();
729     }
730
731     /**
732      * Sets all three in one call. <p/> Note: This affects the whole screen, not
733      * just the game window.
734      * 
735      * @param brightness
736      * @param gamma
737      * @param contrast
738      */
739     public void setBrightnessGammaContrast(float brightness, float gamma,
740             float contrast) {
741         this.brightness = brightness;
742         this.gamma = gamma;
743         this.contrast = contrast;
744         updateDisplayBGC();
745     }
746
747     /**
748      * Called when the display system is created, this function sets the default
749      * render states for the renderer. It should not be called directly by the
750      * user.
751      * 
752      * @param r
753      *            The renderer to get the default states from.
754      */
755     public static void updateStates(Renderer r) {
756         
757         for (RenderState.StateType type : RenderState.StateType.values()) {
758                 
759                 Renderer.defaultStateList[type.ordinal()] = r.createState(type);
760                 Renderer.defaultStateList[type.ordinal()].setEnabled(false);
761         }
762     }
763
764     /**
765      * Create a TextureRenderer using the underlying system.
766      * 
767      * @param width
768      *            width of texture
769      * @param height
770      *            height of texture
771      * @param target
772      * @return A TextureRenderer for the display system.
773      */
774     public abstract TextureRenderer createTextureRenderer(int width,
775             int height, TextureRenderer.Target target);
776
777     /**
778      * Translate world to screen coordinates
779      * 
780      * @param worldPosition
781      *            Vector3f representing the world position to retrieve.
782      * @return the screen position.
783      */
784     public Vector3f getScreenCoordinates(Vector3f worldPosition) {
785         return getScreenCoordinates(worldPosition, null);
786     }
787
788     /**
789      * Translate world to screen coordinates
790      * 
791      * @param worldPosition
792      *            Vector3f representing the world position to retrieve.
793      * @param store
794      *            Vector3f to store the world position in.
795      * @return Vector3f The store vector3f, after storing.
796      */
797     public Vector3f getScreenCoordinates(Vector3f worldPosition, Vector3f store) {
798         return getRenderer().getCamera().getScreenCoordinates(worldPosition,
799                 store);
800     }
801
802     /**
803      * Translate screen to world coordinates.
804      * 
805      * @param screenPosition
806      *            Vector2f representing the screen position with 0,0 at the
807      *            bottom left.
808      * @param zPos
809      *            The z position away from the viewing plane, between 0 and 1.
810      * @return A Vector3f representing the vector's world position.
811      */
812     public Vector3f getWorldCoordinates(Vector2f screenPosition, float zPos) {
813         return getWorldCoordinates(screenPosition, zPos, null);
814     }
815
816     /**
817      * Translate screen to world coordinates.
818      * 
819      * @param screenPosition
820      *            Vector2f representing the screen position with 0,0 at the
821      *            bottom left
822      * @param zPos
823      *            float The z position away from the viewing plane.
824      * @param store
825      *            Vector3f The vector to store the result in.
826      * @return Vector3f The store vector, after storing it's result.
827      */
828     public Vector3f getWorldCoordinates(Vector2f screenPosition, float zPos,
829             Vector3f store) {
830         return getRenderer().getCamera().getWorldCoordinates(screenPosition,
831                 zPos, store);
832     }
833
834     /**
835      * Generate a pick ray from a 2d screen point. The screen point is assumed
836      * to have origin at the lower left, but when using awt mouse clicks, you'll
837      * want to set flipVertical to true since that system has an origin at the
838      * upper right. The Ray will be in world coordinates and the direction will
839      * be normalized.
840      * 
841      * @param screenPosition
842      *            Vector2f representing the screen position with 0,0 at the
843      *            bottom left
844      * @param flipVertical
845      *            Whether or not to flip the y coordinate of the screen position
846      *            across the middle of the screen.
847      * @param store
848      *            The ray to store the result in. If null, a new Ray is created.
849      * @return the ray
850      */
851     public Ray getPickRay(Vector2f screenPosition, boolean flipVertical,
852             Ray store) {
853         if (flipVertical) {
854             screenPosition.y = getRenderer().getHeight() - screenPosition.y;
855         }
856         if (store == null) store = new Ray();
857         getWorldCoordinates(screenPosition, 0,
858                 store.origin);
859         getWorldCoordinates(screenPosition, 0.3f,
860                 store.direction).subtractLocal(store.origin)
861                 .normalizeLocal();
862         return store;
863     }
864
865     /**
866      * Update the display's gamma, brightness and contrast based on the set
867      * values.
868      */
869     protected abstract void updateDisplayBGC();
870     
871     /**
872      * Sets one or more icons for the DisplaySystem.
873      * <p>
874      * As a reference for usual platforms on number of icons and their sizes:
875      * <ul>
876      * <li>On Windows you should supply at least one 16x16 image and one 32x32.</li>
877      * <li>Linux (and similar platforms) expect one 32x32 image.</li>
878      * <li>Mac OS X should be supplied one 128x128 image.</li>
879      * </ul>
880      * </p>
881      * <p>
882      * Images should be in format RGBA8888. If they are not jME will try to convert them
883      * using ImageUtils. If that fails a <code>JmeException</code> could be thrown.
884      * </p>
885      * 
886      * @param iconImages
887      *            Array of Images to be used as icons.
888      * @author Tony Vera
889      * @author Tijl Houtbeckers - some changes to handling non-RGBA8888 Images.
890      * 
891      */
892     public abstract void setIcon(Image[] iconImages);
893
894     /**
895      * @return a RenderContext object representing the current OpenGL context.
896      */
897     public abstract RenderContext<?> getCurrentContext();
898
899     public static synchronized void resetSystemProvider() {
900         if (system != null) { 
901             system.disposeDisplaySystem();
902             system = null;
903         }
904     }
905
906     /**
907      * If running in windowed mode, move the window's position to the given
908      * display coordinates.
909      * 
910      * @param locX
911      * @param locY
912      */
913     public abstract void moveWindowTo(int locX, int locY);
914 }
915