001: /*
002: * $RCSfile: TextureByReference.java,v $
003: *
004: * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * - Redistribution of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * - Redistribution in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * Neither the name of Sun Microsystems, Inc. or the names of
019: * contributors may be used to endorse or promote products derived
020: * from this software without specific prior written permission.
021: *
022: * This software is provided "AS IS," without a warranty of any
023: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
024: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
025: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
026: * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
027: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
028: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
029: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
030: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
031: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
032: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
033: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
034: * POSSIBILITY OF SUCH DAMAGES.
035: *
036: * You acknowledge that this software is not designed, licensed or
037: * intended for use in the design, construction, operation or
038: * maintenance of any nuclear facility.
039: *
040: * $Revision: 1.3 $
041: * $Date: 2007/02/09 17:21:55 $
042: * $State: Exp $
043: */
044:
045: package org.jdesktop.j3d.examples.texture_by_ref;
046:
047: import java.applet.Applet;
048: import java.awt.*;
049: import java.awt.event.*;
050: import com.sun.j3d.utils.applet.MainFrame;
051: import com.sun.j3d.utils.universe.*;
052: import javax.media.j3d.*;
053: import javax.vecmath.*;
054: import java.awt.image.*;
055: import com.sun.j3d.utils.image.TextureLoader;
056: import javax.swing.*;
057: import javax.swing.event.*;
058: import org.jdesktop.j3d.examples.Resources;
059:
060: public class TextureByReference extends Applet implements ItemListener,
061: ActionListener, ChangeListener {
062:
063: // need reference to animation behavior
064: private AnimateTexturesBehavior animate;
065:
066: // need reference to tetrahedron
067: private Tetrahedron tetra;
068:
069: // the gui buttons
070: private JCheckBox flipB;
071: private JRadioButton texByRef;
072: private JRadioButton texByCopy;
073: private JRadioButton geomByRef;
074: private JRadioButton geomByCopy;
075: private JRadioButton img4ByteABGR;
076: private JRadioButton img3ByteBGR;
077: private JRadioButton imgIntARGB;
078: private JRadioButton imgCustomRGBA;
079: private JRadioButton imgCustomRGB;
080: private JRadioButton yUp;
081: private JRadioButton yDown;
082: private JButton animationB;
083: private JSlider frameDelay;
084:
085: private SimpleUniverse universe = null;
086:
087: // image files used for the Texture animation for the applet,
088: // or if no parameters are passed in for the application
089: public static final String[] defaultFiles = {
090: "resources/images/animation1.gif",
091: "resources/images/animation2.gif",
092: "resources/images/animation3.gif",
093: "resources/images/animation4.gif",
094: "resources/images/animation5.gif",
095: "resources/images/animation6.gif",
096: "resources/images/animation7.gif",
097: "resources/images/animation8.gif",
098: "resources/images/animation9.gif",
099: "resources/images/animation10.gif" };
100:
101: private java.net.URL[] urls = null;
102:
103: public TextureByReference() {
104: }
105:
106: public TextureByReference(java.net.URL[] fnamesP) {
107: urls = fnamesP;
108: }
109:
110: public void init() {
111: if (urls == null) {
112: urls = new java.net.URL[defaultFiles.length];
113: for (int i = 0; i < defaultFiles.length; i++) {
114: urls[i] = Resources.getResource(defaultFiles[i]);
115: if (urls[i] == null) {
116: System.err.println(defaultFiles[i] + " not found");
117: System.exit(1);
118: }
119: /*
120: try {
121: urls[i] = new java.net.URL(getCodeBase().toString() +
122: defaultFiles[i]);
123: }
124: catch (java.net.MalformedURLException ex) {
125: System.out.println(ex.getMessage());
126: System.exit(1);
127: }
128: */
129: }
130: }
131: setLayout(new BorderLayout());
132: GraphicsConfiguration config = SimpleUniverse
133: .getPreferredConfiguration();
134:
135: Canvas3D canvas = new Canvas3D(config);
136:
137: add("Center", canvas);
138:
139: // create a simple scene graph and attach it to a simple universe
140: BranchGroup scene = createSceneGraph();
141: universe = new SimpleUniverse(canvas);
142: universe.getViewingPlatform().setNominalViewingTransform();
143: universe.addBranchGraph(scene);
144:
145: // create the gui
146: JPanel gui = buildGui();
147:
148: this .add("South", gui);
149: }
150:
151: public void destroy() {
152: universe.cleanup();
153: }
154:
155: public JPanel buildGui() {
156: flipB = new JCheckBox("flip image", true);
157: flipB.addItemListener(this );
158: javax.swing.Box flipBox = new javax.swing.Box(BoxLayout.Y_AXIS);
159: flipBox.add(flipB);
160: Component strut1 = flipBox.createVerticalStrut(flipB
161: .getPreferredSize().height);
162: Component strut2 = flipBox.createVerticalStrut(flipB
163: .getPreferredSize().height);
164: Component strut3 = flipBox.createVerticalStrut(flipB
165: .getPreferredSize().height);
166: Component strut4 = flipBox.createVerticalStrut(flipB
167: .getPreferredSize().height);
168: Component strut5 = flipBox.createVerticalStrut(flipB
169: .getPreferredSize().height);
170: flipBox.add(strut1);
171: flipBox.add(strut2);
172: flipBox.add(strut3);
173: flipBox.add(strut4);
174: flipBox.add(strut5);
175:
176: yUp = new JRadioButton("y up");
177: yUp.addActionListener(this );
178: yUp.setSelected(true);
179: yDown = new JRadioButton("y down");
180: yDown.addActionListener(this );
181: ButtonGroup yGroup = new ButtonGroup();
182: yGroup.add(yUp);
183: yGroup.add(yDown);
184: JLabel yLabel = new JLabel("Image Orientation:");
185: javax.swing.Box yBox = new javax.swing.Box(BoxLayout.Y_AXIS);
186: yBox.add(yLabel);
187: yBox.add(yUp);
188: yBox.add(yDown);
189: strut1 = yBox
190: .createVerticalStrut(yUp.getPreferredSize().height);
191: strut2 = yBox
192: .createVerticalStrut(yUp.getPreferredSize().height);
193: strut3 = yBox
194: .createVerticalStrut(yUp.getPreferredSize().height);
195: yBox.add(strut1);
196: yBox.add(strut2);
197: yBox.add(strut3);
198:
199: texByRef = new JRadioButton("by reference");
200: texByRef.addActionListener(this );
201: texByRef.setSelected(true);
202: texByCopy = new JRadioButton("by copy");
203: texByCopy.addActionListener(this );
204: ButtonGroup texGroup = new ButtonGroup();
205: texGroup.add(texByRef);
206: texGroup.add(texByCopy);
207: JLabel texLabel = new JLabel("Texture:*");
208: javax.swing.Box texBox = new javax.swing.Box(BoxLayout.Y_AXIS);
209: texBox.add(texLabel);
210: texBox.add(texByRef);
211: texBox.add(texByCopy);
212: strut1 = texBox
213: .createVerticalStrut(texByRef.getPreferredSize().height);
214: strut2 = texBox
215: .createVerticalStrut(texByRef.getPreferredSize().height);
216: strut3 = texBox
217: .createVerticalStrut(texByRef.getPreferredSize().height);
218: texBox.add(strut1);
219: texBox.add(strut2);
220: texBox.add(strut3);
221:
222: geomByRef = new JRadioButton("by reference");
223: geomByRef.addActionListener(this );
224: geomByRef.setSelected(true);
225: geomByCopy = new JRadioButton("by copy");
226: geomByCopy.addActionListener(this );
227: ButtonGroup geomGroup = new ButtonGroup();
228: geomGroup.add(geomByRef);
229: geomGroup.add(geomByCopy);
230: JLabel geomLabel = new JLabel("Geometry:");
231: javax.swing.Box geomBox = new javax.swing.Box(BoxLayout.Y_AXIS);
232: geomBox.add(geomLabel);
233: geomBox.add(geomByRef);
234: geomBox.add(geomByCopy);
235: strut1 = geomBox.createVerticalStrut(geomByRef
236: .getPreferredSize().height);
237: strut2 = geomBox.createVerticalStrut(geomByRef
238: .getPreferredSize().height);
239: strut3 = geomBox.createVerticalStrut(geomByRef
240: .getPreferredSize().height);
241: geomBox.add(strut1);
242: geomBox.add(strut2);
243: geomBox.add(strut3);
244:
245: img4ByteABGR = new JRadioButton("TYPE_4BYTE_ABGR");
246: img4ByteABGR.addActionListener(this );
247: img4ByteABGR.setSelected(true);
248: img3ByteBGR = new JRadioButton("TYPE_3BYTE_BGR");
249: img3ByteBGR.addActionListener(this );
250: imgIntARGB = new JRadioButton("TYPE_INT_ARGB");
251: imgIntARGB.addActionListener(this );
252: imgCustomRGBA = new JRadioButton("TYPE_CUSTOM RGBA");
253: imgCustomRGBA.addActionListener(this );
254: imgCustomRGB = new JRadioButton("TYPE_CUSTOM RGB");
255: imgCustomRGB.addActionListener(this );
256: ButtonGroup imgGroup = new ButtonGroup();
257: imgGroup.add(img4ByteABGR);
258: imgGroup.add(img3ByteBGR);
259: imgGroup.add(imgIntARGB);
260: imgGroup.add(imgCustomRGBA);
261: imgGroup.add(imgCustomRGB);
262: JLabel imgLabel = new JLabel("Image Type:*");
263: javax.swing.Box imgBox = new javax.swing.Box(BoxLayout.Y_AXIS);
264: imgBox.add(imgLabel);
265: imgBox.add(img4ByteABGR);
266: imgBox.add(img3ByteBGR);
267: imgBox.add(imgIntARGB);
268: imgBox.add(imgCustomRGBA);
269: imgBox.add(imgCustomRGB);
270:
271: javax.swing.Box topBox = new javax.swing.Box(BoxLayout.X_AXIS);
272: topBox.add(flipBox);
273: topBox.add(texBox);
274: topBox.add(geomBox);
275: topBox.add(yBox);
276: Component strut = topBox.createRigidArea(new Dimension(10, 10));
277: topBox.add(strut);
278: topBox.add(imgBox);
279:
280: frameDelay = new JSlider(0, 50, 0);
281: frameDelay.addChangeListener(this );
282: frameDelay.setSnapToTicks(true);
283: frameDelay.setPaintTicks(true);
284: frameDelay.setPaintLabels(true);
285: frameDelay.setMajorTickSpacing(10);
286: frameDelay.setMinorTickSpacing(1);
287: frameDelay.setValue(20);
288: JLabel delayL = new JLabel("frame delay");
289: javax.swing.Box delayBox = new javax.swing.Box(BoxLayout.X_AXIS);
290: delayBox.add(delayL);
291: delayBox.add(frameDelay);
292:
293: animationB = new JButton(" stop animation ");
294: animationB.addActionListener(this );
295:
296: JLabel texInfo1 = new JLabel(
297: "*To use ImageComponent by reference feature, use TYPE_4BYTE_ABGR on Solaris");
298: JLabel texInfo2 = new JLabel("and TYPE_3BYTE_BGR on Windows");
299:
300: JPanel buttonP = new JPanel();
301: GridBagLayout gridbag = new GridBagLayout();
302: GridBagConstraints c = new GridBagConstraints();
303: buttonP.setLayout(gridbag);
304: c.anchor = GridBagConstraints.CENTER;
305: c.gridwidth = GridBagConstraints.REMAINDER;
306: gridbag.setConstraints(topBox, c);
307: buttonP.add(topBox);
308: gridbag.setConstraints(delayBox, c);
309: buttonP.add(delayBox);
310: gridbag.setConstraints(animationB, c);
311: buttonP.add(animationB);
312: gridbag.setConstraints(texInfo1, c);
313: buttonP.add(texInfo1);
314: gridbag.setConstraints(texInfo2, c);
315: buttonP.add(texInfo2);
316:
317: return buttonP;
318:
319: }
320:
321: public BranchGroup createSceneGraph() {
322:
323: // create the root of the branch group
324: BranchGroup objRoot = new BranchGroup();
325:
326: // create the transform group node and initialize it
327: // enable the TRANSFORM_WRITE capability so that it can be modified
328: // at runtime. Add it to the root of the subgraph
329: Transform3D rotate = new Transform3D();
330: TransformGroup objTrans = new TransformGroup(rotate);
331: objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
332: objRoot.addChild(objTrans);
333:
334: // bounds
335: BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,
336: 0.0, 0.0), 100.0);
337:
338: // set up some light
339: Color3f lColor1 = new Color3f(0.7f, 0.7f, 0.7f);
340: Vector3f lDir1 = new Vector3f(-1.0f, -0.5f, -1.0f);
341: Color3f alColor = new Color3f(0.2f, 0.2f, 0.2f);
342:
343: AmbientLight aLgt = new AmbientLight(alColor);
344: aLgt.setInfluencingBounds(bounds);
345: DirectionalLight lgt1 = new DirectionalLight(lColor1, lDir1);
346: lgt1.setInfluencingBounds(bounds);
347: objRoot.addChild(aLgt);
348: objRoot.addChild(lgt1);
349:
350: Appearance appearance = new Appearance();
351:
352: // enable the TEXTURE_WRITE so we can modify it at runtime
353: appearance.setCapability(Appearance.ALLOW_TEXTURE_WRITE);
354:
355: // load the first texture
356: TextureLoader loader = new TextureLoader(urls[0],
357: TextureLoader.BY_REFERENCE | TextureLoader.Y_UP, this );
358: // get the texture from the loader
359: Texture2D tex = (Texture2D) loader.getTexture();
360:
361: // get the BufferedImage to convert to TYPE_4BYTE_ABGR and flip
362: // get the ImageComponent because we need it anyway
363: ImageComponent2D imageComp = (ImageComponent2D) tex.getImage(0);
364: BufferedImage bImage = imageComp.getImage();
365: // convert the image
366: bImage = ImageOps.convertImage(bImage,
367: BufferedImage.TYPE_4BYTE_ABGR);
368: // flip the image
369: ImageOps.flipImage(bImage);
370: imageComp.set(bImage);
371:
372: tex.setCapability(Texture.ALLOW_IMAGE_WRITE);
373: tex.setBoundaryModeS(Texture.CLAMP);
374: tex.setBoundaryModeT(Texture.CLAMP);
375: tex.setBoundaryColor(1.0f, 1.0f, 1.0f, 1.0f);
376:
377: // set the image of the texture
378: tex.setImage(0, imageComp);
379:
380: // set the texture on the appearance
381: appearance.setTexture(tex);
382:
383: // set texture attributes
384: TextureAttributes texAttr = new TextureAttributes();
385: texAttr.setTextureMode(TextureAttributes.MODULATE);
386: appearance.setTextureAttributes(texAttr);
387:
388: // set material properties
389: Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
390: Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
391: appearance.setMaterial(new Material(white, black, white, black,
392: 1.0f));
393:
394: // create a scale transform
395: Transform3D scale = new Transform3D();
396: scale.set(.6);
397: TransformGroup objScale = new TransformGroup(scale);
398: objTrans.addChild(objScale);
399:
400: tetra = new Tetrahedron(true);
401: tetra.setAppearance(appearance);
402: objScale.addChild(tetra);
403:
404: // create the behavior
405: animate = new AnimateTexturesBehavior(tex, urls, appearance,
406: this );
407: animate.setSchedulingBounds(bounds);
408:
409: objTrans.addChild(animate);
410:
411: // add a rotation behavior so we can see all sides of the tetrahedron
412: Transform3D yAxis = new Transform3D();
413: Alpha rotorAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0,
414: 4000, 0, 0, 0, 0, 0);
415: RotationInterpolator rotator = new RotationInterpolator(
416: rotorAlpha, objTrans, yAxis, 0.0f,
417: (float) Math.PI * 2.0f);
418: rotator.setSchedulingBounds(bounds);
419: objTrans.addChild(rotator);
420:
421: // have java3d perform optimizations on this scene graph
422: objRoot.compile();
423:
424: return objRoot;
425: }
426:
427: // callback for the animation button and delay text field
428: public void actionPerformed(ActionEvent e) {
429: Object o = e.getSource();
430:
431: // for the animation button
432: if (o == animationB) {
433: if (animate.getEnable()) {
434: animate.setEnable(false);
435: animationB.setText("start animation");
436: } else {
437: animate.setEnable(true);
438: animationB.setText(" stop animation ");
439: }
440: }
441:
442: // for the texByRef button
443: else if (o == texByRef && texByRef.isSelected()) {
444: animate.setByReference(true);
445: }
446: // texByCopy button
447: else if (o == texByCopy && texByCopy.isSelected()) {
448: animate.setByReference(false);
449: }
450: // yUp button
451: else if (o == yUp && yUp.isSelected()) {
452: animate.setYUp(true);
453: }
454: // ydown button
455: else if (o == yDown && yDown.isSelected()) {
456: animate.setYUp(false);
457: }
458: //geomByRef button
459: else if (o == geomByRef) {
460: tetra.setByReference(true);
461: }
462: // geomByCopy button
463: else if (o == geomByCopy) {
464: tetra.setByReference(false);
465: }
466: // TYPE_INT_ARGB
467: else if (o == imgIntARGB) {
468: animate.setImageType(BufferedImage.TYPE_INT_ARGB);
469: }
470: // TYPE_4BYTE_ABGR
471: else if (o == img4ByteABGR) {
472: animate.setImageType(BufferedImage.TYPE_4BYTE_ABGR);
473: }
474: // TYPE_3BYTE_BGR
475: else if (o == img3ByteBGR) {
476: animate.setImageType(BufferedImage.TYPE_3BYTE_BGR);
477: }
478: // TYPE_CUSTOM RGBA
479: else if (o == imgCustomRGBA) {
480: animate.setImageTypeCustomRGBA();
481: }
482: // TYPE_CUSTOM RGB
483: else if (o == imgCustomRGB) {
484: animate.setImageTypeCustomRGB();
485: }
486: }
487:
488: // callback for the checkboxes
489: public void itemStateChanged(ItemEvent e) {
490: Object o = e.getSource();
491: // for the flip checkbox
492: if (o == flipB) {
493: if (e.getStateChange() == ItemEvent.DESELECTED) {
494: animate.setFlipImages(false);
495: } else
496: animate.setFlipImages(true);
497: }
498: }
499:
500: // callback for the slider
501: public void stateChanged(ChangeEvent e) {
502: Object o = e.getSource();
503: // for the frame delay
504: if (o == frameDelay) {
505: animate.setFrameDelay(frameDelay.getValue());
506: }
507: }
508:
509: // allows TextureByReference to be run as an application as well as an applet
510: public static void main(String[] args) {
511: java.net.URL fnames[] = null;
512: if (args.length > 1) {
513: fnames = new java.net.URL[args.length];
514: for (int i = 0; i < args.length; i++) {
515: try {
516: fnames[i] = new java.net.URL("file:" + args[i]);
517: } catch (java.net.MalformedURLException ex) {
518: System.out.println(ex.getMessage());
519: }
520: }
521: } else {
522: fnames = new java.net.URL[TextureByReference.defaultFiles.length];
523: for (int i = 0; i < TextureByReference.defaultFiles.length; i++) {
524: fnames[i] = Resources.getResource(defaultFiles[i]);
525: if (fnames[i] == null) {
526: System.err
527: .println(TextureByReference.defaultFiles[i]
528: + " not found");
529: System.exit(1);
530: }
531:
532: /*
533: try {
534: fnames[i] = new java.net.URL("file:" +
535: TextureByReference.defaultFiles[i]);
536: }
537: catch (java.net.MalformedURLException ex) {
538: System.out.println(ex.getMessage());
539: System.exit(1);
540: }
541: */
542: }
543: }
544: new MainFrame((new TextureByReference(fnames)), 650, 750);
545: }
546: }
|