001: /*
002: * Copyright (c) 2000 Silvere Martin-Michiellot All Rights Reserved.
003: *
004: * Silvere Martin-Michiellot grants you ("Licensee") a non-exclusive,
005: * royalty free, license to use, modify and redistribute this
006: * software in source and binary code form,
007: * provided that i) this copyright notice and license appear on all copies of
008: * the software; and ii) Licensee does not utilize the software in a manner
009: * which is disparaging to Silvere Martin-Michiellot.
010: *
011: * This software is provided "AS IS," without a warranty of any kind. ALL
012: * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
013: * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
014: * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. Silvere Martin-Michiellot
015: * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES
016: * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
017: * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
018: * Silvere Martin-Michiellot OR ITS LICENSORS BE LIABLE
019: * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
020: * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
021: * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
022: * OR INABILITY TO USE SOFTWARE, EVEN IF Silvere Martin-Michiellot HAS BEEN
023: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
024: *
025: * This software is not designed or intended for use in on-line control of
026: * aircraft, air traffic, aircraft navigation or aircraft communications; or in
027: * the design, construction, operation or maintenance of any nuclear
028: * facility. Licensee represents and warrants that it will not use or
029: * redistribute the Software for such purposes.
030: *
031: */
032:
033: package com.db.layers;
034:
035: import java.awt.*;
036: import java.awt.image.BufferedImage;
037: import java.util.ArrayList;
038: import javax.swing.*;
039: import javax.media.j3d.*;
040: import com.sun.j3d.utils.universe.SimpleUniverse;
041:
042: //Builds up a Lightweight Canvas3D from an AWT Canvas3D
043: //slow but useful
044:
045: /**
046: From the J3D mailing list
047: >
048: > I would like to know if the Java3D development team
049: > has in mind to include a Swing, lightweigth component
050: > for rendering in near releases of Java3D.
051: >
052: > Canvas3D is good, but try to integrate it with a
053: > Swing application....
054:
055:
056: I'm not the most informed person on this, but it is my understanding that if
057: you want *FAST* 3D rendering, a Canvas3D component implemented as a
058: lightweight component will never happen. My speculation is that the Canvas3D
059: class maps to a native window handle, which is in turn owned by the OpenGL
060: pipeline. The 3D hardware writes directly to to the screen memory, which is
061: then immediately read by the D/A converter or the DVI subsystem. No frame
062: data is passed across the bus (assuming a modern graphics card with most of
063: the pipeline is implemented in hardware).
064:
065:
066: If a "JCanvas3D" class were to be implemented, every frame would have to be
067: rendered to an off-screen buffer, and then redrawn in the AWT rendering
068: loop. The number of frame copies becomes crazy: assuming the offscreen
069: buffer resides in 3D hardware memory (I guessing here; I don't know enough
070: about hardware design to know), the card would write to the buffer, which
071: would then be copied across the bus to main memory where it is processed by
072: the AWT rendering loop. The frame is then copied to the native Component
073: peer, where it is probably copied again to hardware memory for reading by
074: the output subsystem. Regardless of how fast your CPU or graphics card is,
075: the bus is certainly going to get bogged down with all the copies. Might as
076: well do software rendering....
077:
078:
079: I use Java3D in a Swing app with no problems (menus etc. work fine), and the
080: rendering is FAST!! (even at 1600x1200) All I did was implement the steps
081: outlined at:
082:
083:
084: http://www.j3d.org/faq/swing.html
085:
086:
087: If framerate isn't an issue one could easily implement their own JComponent
088: subclass that does all rendering to an offcreen buffer and then copied in
089: the paintComponent(Graphics) method.
090:
091:
092: Anyone with better technical knowledge feel like filling in the gaps and/or
093: correcting my misunderstandings? This question comes up at lest once a
094: month, and am frankly tired of the Java3D team being accused of "bad design"
095: when the design they have implemented is the best possible given that speed
096: is top priority for many people. And calling the methods described in the
097: FAQ is hardly that big of a deal. Granted, Canvas3D doesn't work very well
098: in the JScrollPane, but I'd argue that if you want scrolling you should be
099: mapping the scroll bar events to view translate operations (i.e. do the
100: scrolling in Java3D space, not AWT space).
101:
102:
103: Simeon
104: **/
105:
106: public class JPanel3D extends JPanel {
107:
108: private Canvas3D canvas3D;
109:
110: public JPanel3D() {
111:
112: super ();
113: initConstructor();
114:
115: }
116:
117: //Creates a new JPanel with a double buffer and a flow layout.
118: public JPanel3D(boolean isDoubleBuffered) {
119:
120: super (isDoubleBuffered);
121: initConstructor();
122:
123: }
124:
125: //Creates a new JPanel with FlowLayout and the specified buffering strategy.
126: public JPanel3D(LayoutManager layout) {
127:
128: super (layout);
129: initConstructor();
130:
131: }
132:
133: //Create a new buffered JPanel with the specified layout manager
134: public JPanel3D(LayoutManager layout, boolean isDoubleBuffered) {
135:
136: super (layout, isDoubleBuffered);
137: initConstructor();
138:
139: }
140:
141: private void initConstructor() {
142:
143: GraphicsConfiguration graphicsConfiguration;
144:
145: graphicsConfiguration = new SimpleUniverse()
146: .getPreferredConfiguration();
147: //graphicsConfiguration = this.getGraphicsConfiguration();
148: this .canvas3D = new Canvas3D(graphicsConfiguration, true);
149: this .canvas3D.setSize(this .getSize());
150:
151: }
152:
153: public void paint(Graphics g) {
154:
155: super .paint(g);
156: Toolkit.getDefaultToolkit().sync();
157:
158: }
159:
160: public void repaint() {
161:
162: Graphics2D graphics2D;
163: BufferedImage sourceBufferedImage;
164: boolean result;
165:
166: graphics2D = (Graphics2D) this .getGraphics();
167: if (canvas3D != null) {
168: this .canvas3D.waitForOffScreenRendering();
169: sourceBufferedImage = this .canvas3D.getOffScreenBuffer()
170: .getImage();
171: result = graphics2D.drawImage(sourceBufferedImage, 0, 0,
172: null);
173: //paint(graphics2D);
174: }
175:
176: }
177:
178: public Canvas3D getCanvas3D() {
179:
180: return this .canvas3D;
181:
182: }
183:
184: //please think about using com.sun.j3d.utils.universe.SimpleUniverse.getPreferredConfiguration()
185: public GraphicsConfiguration[] getGraphicsConfigurations() {
186:
187: GraphicsEnvironment graphicsEnvironment;
188: GraphicsDevice[] graphicsDevices;
189: GraphicsConfiguration[] graphicsConfigurations;
190: ArrayList configurations;
191:
192: configurations = new ArrayList();
193: graphicsEnvironment = GraphicsEnvironment
194: .getLocalGraphicsEnvironment();
195: graphicsDevices = graphicsEnvironment.getScreenDevices();
196: for (int i = 0; i < graphicsDevices.length; i++) {
197: graphicsConfigurations = graphicsDevices[i]
198: .getConfigurations();
199: for (int j = 0; j < graphicsConfigurations.length; j++) {
200: configurations.add(graphicsConfigurations[j]);
201: }
202: }
203:
204: return (GraphicsConfiguration[]) configurations.toArray();
205:
206: }
207:
208: }
|