/* * $RCSfile$ * * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or * intended for use in the design, construction, operation or * maintenance of any nuclear facility. * * $Revision$ * $Date$ * $State$ */ package org.jdesktop.j3d.examples.dot3; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.image.BufferedImage; import java.util.Iterator; import javax.swing.JFrame; import javax.swing.JPanel; import org.jdesktop.j3d.examples.Resources; import org.jogamp.java3d.AmbientLight; import org.jogamp.java3d.Appearance; import org.jogamp.java3d.Background; import org.jogamp.java3d.Behavior; import org.jogamp.java3d.BoundingSphere; import org.jogamp.java3d.BranchGroup; import org.jogamp.java3d.Canvas3D; import org.jogamp.java3d.DirectionalLight; import org.jogamp.java3d.GeometryArray; import org.jogamp.java3d.ImageComponent2D; import org.jogamp.java3d.Material; import org.jogamp.java3d.PolygonAttributes; import org.jogamp.java3d.Shape3D; import org.jogamp.java3d.TexCoordGeneration; import org.jogamp.java3d.Texture; import org.jogamp.java3d.Texture2D; import org.jogamp.java3d.TextureAttributes; import org.jogamp.java3d.TextureUnitState; import org.jogamp.java3d.WakeupCriterion; import org.jogamp.java3d.WakeupOnElapsedFrames; import org.jogamp.java3d.utils.behaviors.vp.OrbitBehavior; import org.jogamp.java3d.utils.geometry.GeometryInfo; import org.jogamp.java3d.utils.image.TextureLoader; import org.jogamp.java3d.utils.universe.SimpleUniverse; import org.jogamp.java3d.utils.universe.ViewingPlatform; import org.jogamp.vecmath.Color3f; import org.jogamp.vecmath.Point3d; import org.jogamp.vecmath.Vector3f; /** * This example program is contributed by Alessandro Borges */ /** *
 *  DOT3 per-pixel lighting demo.
 * It uses a Normal map and a Light map, both coded as independent textures.
 * Each pixel color is a vector coded, where color range [0,255] is mapped
 * as vector in range [-1.0,+1.0].
 *
 * A math operation called DOT3 applied to Light vector and Normal vector results
 * a scalar value, interpreted as light intensity. This operation is made for each
 * pixel on texture.  
 * Light Intensity = DOT3(light, normal);
 *
 * This technique allows complex lighting effects, as bumps, on low polygon count
 * geometries.
 * 
* */ public class Dot3Demo extends JFrame { // a external control panel for this demo private TextureControlPanel ctrlPanel = null; // default bounds used in this application private BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0); // TextureUnitStates used in this application TextureUnitState tuLightMap; TextureUnitState tuDOT3NormalMap; TextureUnitState tuColor; /** Where the TUs are applied **/ TextureUnitState[] tusArr; /** appearance will be changed at runtime **/ Appearance appearance; /** polygonAttributes will be changed at runtime **/ PolygonAttributes polygonAttributes; // textures used Texture textureColor; Texture textureDOT3NormalMap; Texture2D textureLightMap; // needs for runtime updates on lightMap ImageComponent2D imageLightMap; // default texture names used String textureColorName= "main/resources/images/wood.jpg"; String textureDOT3NormalMapName = "main/resources/images/Java3Ddot3.jpg"; /** * Constructor. */ public Dot3Demo() { super("Java3D DOT3 demo"); try { init(); } catch (Exception e) { e.printStackTrace(); } } private void init() throws Exception { this.setSize(new Dimension(400, 400)); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel mainPanel = new JPanel(); this.getContentPane().add(mainPanel, null); mainPanel.setLayout(new BorderLayout()); // get default configuration for 3D GraphicsConfiguration conf = SimpleUniverse.getPreferredConfiguration(); Canvas3D canvas = new Canvas3D(conf); // create simpleUniverse SimpleUniverse su = new SimpleUniverse(canvas); // create sceneGraph and add it to universe BranchGroup sceneGraph = createSceneGraph(); su.addBranchGraph(sceneGraph); // This will move the ViewPlatform back a bit so the // objects in the scene can be viewed. su.getViewingPlatform().setNominalViewingTransform(); // Ensure at least 5 msec per frame (i.e., < 200Hz) su.getViewer().getView().setMinimumFrameCycleTime(5); // add the behaviors to the ViewingPlatform ViewingPlatform viewingPlatform = su.getViewingPlatform(); viewingPlatform.setNominalViewingTransform(); // add orbit behavior to ViewingPlatform OrbitBehavior orbit = new OrbitBehavior(canvas, OrbitBehavior.REVERSE_ALL | OrbitBehavior.STOP_ZOOM); orbit.setSchedulingBounds(bounds); viewingPlatform.setViewPlatformBehavior(orbit); mainPanel.add(canvas, BorderLayout.CENTER); this.setVisible(true); //create a control panel to user interaction ctrlPanel = new TextureControlPanel(this); ctrlPanel.setVisible(true); ctrlPanel.setLocation(410,10); } /** * loads all needed textures, and creates light map texture */ private void loadTextures() { try { //java.net.URL urlColor = new java.net.URL("file:" + textureColorName); //java.net.URL urlDot3 = new java.net.URL("file:" + textureDOT3NormalMapName); java.net.URL urlColor = Resources.getResource(textureColorName); java.net.URL urlDot3 = Resources.getResource(textureDOT3NormalMapName); // loading textures textureColor = new TextureLoader(urlColor,this).getTexture(); textureDOT3NormalMap = new TextureLoader(urlDot3,this) .getTexture(); // create Image for textureLightMap BufferedImage image = new BufferedImage(256,256,BufferedImage.TYPE_INT_RGB); Graphics2D graphics = image.createGraphics(); graphics.setPaint(new Color(130,130,250)); graphics.fillRect(0,0,image.getWidth(),image.getHeight()); graphics.dispose(); imageLightMap = new ImageComponent2D(ImageComponent2D.FORMAT_RGB,image,false,false); imageLightMap.setCapability(ImageComponent2D.ALLOW_IMAGE_WRITE); imageLightMap.setCapability(ImageComponent2D.ALLOW_IMAGE_READ); //create textureLightMap with above imageLightMap textureLightMap = new Texture2D(Texture2D.BASE_LEVEL,Texture2D.RGB,256,256); textureLightMap.setImage(0,imageLightMap); textureLightMap.setMagFilter(Texture2D.NICEST); textureLightMap.setMinFilter(Texture2D.NICEST); // application with update textureLightMap at runtime, so lets enable some caps textureLightMap.setCapability(Texture2D.ALLOW_ENABLE_WRITE); textureLightMap.setCapability(Texture2D.ALLOW_ENABLE_READ); textureLightMap.setCapability(Texture2D.ALLOW_IMAGE_WRITE); textureLightMap.setCapability(Texture2D.ALLOW_IMAGE_READ); } catch(Exception e) { System.err.println("Failed to load textures"); e.printStackTrace(); } } /** * setup TextureUnitStates used in this demo. * * @return */ private TextureUnitState[] setupTextureUnitState() { //texture Attributes for DOT3 normal map TextureAttributes textAttDot3 = new TextureAttributes(); // lightMap uses TextureAttributes with default REPLACE mode TextureAttributes textAttLightMap = new TextureAttributes(); TextureAttributes texAttColor = new TextureAttributes(); texAttColor.setTextureMode(TextureAttributes.COMBINE); //CombineRgbMode could be also COMBINE_ADD or COMBINE_ADD_SIGNED, with //different results texAttColor.setCombineRgbMode(TextureAttributes.COMBINE_MODULATE); // increase light depth effect texAttColor.setCombineRgbScale(2); textAttDot3.setTextureMode(TextureAttributes.COMBINE); textAttDot3.setCombineRgbMode(TextureAttributes.COMBINE_DOT3); textAttDot3.setCombineAlphaMode(TextureAttributes.COMBINE_DOT3); textAttDot3.setTextureBlendColor(1.f,1.0f,1.0f,0.0f); // increase light intesity textAttDot3.setCombineRgbScale(2); // setup functions textAttDot3.setCombineRgbFunction(0,TextureAttributes.COMBINE_SRC_COLOR); textAttDot3.setCombineRgbFunction(1,TextureAttributes.COMBINE_SRC_COLOR); textAttDot3.setCombineRgbFunction(2,TextureAttributes.COMBINE_SRC_COLOR); //combine with previous TUS, lightMap textAttDot3.setCombineRgbSource(0,TextureAttributes.COMBINE_PREVIOUS_TEXTURE_UNIT_STATE); textAttDot3.setCombineRgbSource(1,TextureAttributes.COMBINE_TEXTURE_COLOR ); textAttDot3.setCombineRgbSource(2,TextureAttributes.COMBINE_OBJECT_COLOR); TexCoordGeneration tcg1=null; // SphereMap tcg can add nice dynamic effects for curved surfaces, because it // distributes texture like a light bean over geometry. // It os not used in this demo, but you can try yourself at home // with *complex* lightmaps, i.e., spherical light distributions, // multi light sorces, degradee, waves,etc /* tcg1 = new TexCoordGeneration(TexCoordGeneration.SPHERE_MAP, TexCoordGeneration.TEXTURE_COORDINATE_3); */ // create TUS tuLightMap = new TextureUnitState(textureLightMap,textAttLightMap,tcg1); tuDOT3NormalMap = new TextureUnitState(textureDOT3NormalMap,textAttDot3,null); tuColor = new TextureUnitState(textureColor,texAttColor,null); // this TUS array is used by geometry at runtime TextureUnitState[] tus = new TextureUnitState[3]; tus[0] = tuLightMap; tus[1] = tuDOT3NormalMap; tus[2] = tuColor; // enable texture units for read/write at runtime for (int i = 0; i < tus.length; i++) { tus[i].setCapability(TextureUnitState.ALLOW_STATE_WRITE); tus[i].setCapability(TextureUnitState.ALLOW_STATE_READ); } return tus; } /** * creates a single Quad geometry with 4 TextureCoordinateMaps, for multitexture use.
* Dimension is scale*(2m , 1m) * @param scale a scale for this quad * @return quad geometry for multitexture use */ private GeometryArray createGeometry(float scale) { // vertex coordinates float[] verts = { 2.0f, -1.0f, 0.0f, 2.0f, 1.0f, 0.0f, -2.0f, 1.0f, 0.0f, -2.0f, -1.0f, 0.0f }; // 2D texture Coords - each texture unit will use one set of this float[] texCoords = { 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f}; // all texture units will use texCoords from unit 0 int[] texCoordSetMap = {0,0,0,0}; // normals Vector3f normal = new Vector3f( 0.0f, 0.0f, 1.0f); Vector3f[] normals = { normal, normal, normal, normal} ; // resize quad dimension for(int i = 0;i e) { // check if there are a new light map ready to use if (ctrlPanel.hasTextureImageReady()) { updateLighMap(ctrlPanel.getTextureImage()); } //wake up on next frame wakeupOn(wakeup); } } }