> > The basic issue is a fundamental one with the way that Java3D works. > When you ask for the view frustum projection matrix from Java3D it gives > you the value used on the previous frame, not the current one. At a > minimum, you need one frame to be rendered before the ROAM code can do > anything useful. From your description, it sounds like you aren't > setting up the view with the canvas before there is data available and > thus, if you don't get anything to drive a second frame render then > nothing will happen. Ie The event from the navigation will force a > second frame render, as will the resize of the window etc.
I am not sure, if I understood you correctly. Are you saying that, I don't see anything at first because I had no objects or whatever in the view, which I could have seen? Now I added a Box somewhere near the terrain. So starting the application gives me the view of the box, but I still get the terrain only by clicking into the panel (See RoamTest3). > > Note also that we have one or two outstanding bugs with dynamically > tiled terrain currently. We're not quite sure what they are yet but know > they exist. Could you bee a bit more specific on that? What kind of bugs? While playing with your code I stumbled over AbstractStaticTerrainData method getGridDepth() it was returning gridWidth, I guess it should be gridDepth? But this class has nothing to do with the tiling. Thanks for your help Desiree > -- > Justin Couch http://www.vlc.com.au/~justin/ > Java Architect & Bit Twiddler http://www.yumetech.com/ > Author, Java 3D FAQ Maintainer http://www.j3d.org/ > ------------------------------------------------------------------- > "Humanism is dead. Animals think, feel; so do machines now. > Neither man nor woman is the measure of all things. Every organism > processes data according to its domain, its environment; you, with > all your brains, would be useless in a mouse's universe..." > - Greg Bear, Slant > ------------------------------------------------------------------- > > =========================================================================== > To unsubscribe, send email to [EMAIL PROTECTED] and include in the body > of the message "signoff JAVA3D-INTEREST". For general help, send email to > [EMAIL PROTECTED] and include in the body of the message "help". >
/***************************************************************************** * J3D.org Copyright (c) 2000 * Java Source * * This source is licensed under the GNU LGPL v2.1 * Please read http://www.gnu.org/copyleft/lgpl.html for more information * * This software comes with the standard NO WARRANTY disclaimer for any * purpose. Use it at your own risk. If there's a problem you get to fix it. * ****************************************************************************/ // Standard imports import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.media.j3d.*; import javax.vecmath.*; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.HashMap; // Application Specific imports import org.j3d.geom.Box; import org.j3d.loaders.HeightMapTerrainData; import org.j3d.loaders.SimpleTiledTerrainData; import org.j3d.loaders.vterrain.BTHeader; import org.j3d.loaders.vterrain.BTParser; import org.j3d.terrain.AbstractStaticTerrainData; import org.j3d.terrain.AppearanceGenerator; import org.j3d.terrain.Landscape; import org.j3d.terrain.TerrainData; import org.j3d.terrain.roam.SplitMergeLandscape; import org.j3d.texture.TextureCache; import org.j3d.texture.TextureCacheFactory; import org.j3d.ui.navigation.MouseViewHandler; import org.j3d.ui.navigation.NavigationStateManager; import org.j3d.ui.navigation.NavigationState; import org.j3d.util.interpolator.ColorInterpolator; import org.j3d.util.frustum.ViewFrustum; /** * Demonstration of the ROAM code. * * * @author Justin Couch * @version $Revision: 1.5 $ */ public class RoamTest3 extends DemoFrameDesTest implements ItemListener, AppearanceGenerator // public class RoamTest2 extends DemoFrameDesTest //implements AppearanceGenerator { // Achtung front und back hardcodiert private static final double BACK_CLIP_DISTANCE = 3000.0; private static final double FRONT_CLIP_DISTANCE = 1; /** The main canvas that we are navigating on */ private Canvas3D navCanvas; /** The canvas that provides a birds-eye view of the scene */ private Canvas3D topDownCanvas; /** Global material instance to use */ private Material material; /** Global polygon attributes to use */ private PolygonAttributes polyAttr; private MouseViewHandler groundNav; private MouseViewHandler topDownNav; /** The view frustum for the ground canvas */ private ViewFrustum viewFrustum; /** The landscape we are navigating around */ private Landscape landscape; /** The branchgroup to add our terrain to */ private BranchGroup terrainGroup; /** TG that holds the user view position. Used when new terrain set */ private TransformGroup gndViewTransform; /** TG that holds the top-down user view position. Used when new terrain set */ private TransformGroup topViewTransform; private HashMap terrainFilesMap; private HashMap textureFilesMap; /** Mapping of the button to the polygon mode value */ private HashMap polyModeMap; /** The color interpolator for doing height interpolations with */ private ColorInterpolator heightRamp; /** * Construct a new demo with no geometry currently showing, but the * default type is set to quads. */ public RoamTest3() { super("Terrain Culling Demo"); navCanvas = createCanvas(); terrainFilesMap = new HashMap(); textureFilesMap = new HashMap(); Panel p0 = new Panel(new GridLayout(1, 2)); p0.add(navCanvas); //p0.add(topDownCanvas); add(p0, BorderLayout.CENTER); JPanel p1 = new JPanel(new FlowLayout()); // Crater Lake Beispiel funktioniert ButtonGroup grp = new ButtonGroup(); JRadioButton button = new JRadioButton("Crater Lake"); button.addItemListener(this); grp.add(button); p1.add(button); terrainFilesMap.put(button, "crater_0513.bt"); textureFilesMap.put(button, null); // Listener fuer MouseNavigation? groundNav = new MouseViewHandler(); groundNav.setCanvas(navCanvas); groundNav.setButtonNavigation(MouseEvent.BUTTON1_MASK, NavigationState.FLY_STATE); groundNav.setButtonNavigation(MouseEvent.BUTTON2_MASK, NavigationState.TILT_STATE); groundNav.setButtonNavigation(MouseEvent.BUTTON3_MASK, NavigationState.PAN_STATE); buildScene(); viewFrustum = new ViewFrustum(navCanvas); // Now set up the material and appearance handling for the generator material = new Material(); material.setLightingEnable(true); polyAttr = new PolygonAttributes(); polyAttr.setCapability(PolygonAttributes.ALLOW_MODE_WRITE); polyAttr.setCullFace(PolygonAttributes.CULL_NONE); polyAttr.setBackFaceNormalFlip(true); polyAttr.setPolygonMode(PolygonAttributes.POLYGON_FILL); heightRamp = new ColorInterpolator(ColorInterpolator.HSV_SPACE); heightRamp.addRGBKeyFrame(-20, 0, 0, 1, 0); heightRamp.addRGBKeyFrame(0, 0, 0.7f, 0.95f, 0); heightRamp.addRGBKeyFrame(5, 1, 1, 0, 0); heightRamp.addRGBKeyFrame(10, 0, 0.6f, 0, 0); heightRamp.addRGBKeyFrame(100, 0, 1, 0, 0); heightRamp.addRGBKeyFrame(1000, 0.6f, 0.7f, 0, 0); heightRamp.addRGBKeyFrame(1500, 0.5f, 0.5f, 0.3f, 0); heightRamp.addRGBKeyFrame(2500, 1, 1, 1, 0); //setSize(600, 400); //setVisible(true); loadTerrain(new String(),new String()); } //---------------------------------------------------------- // Methods required by ItemListener //---------------------------------------------------------- /** * Process the change of state request from the colour selector panel. * * @param evt The event that caused this method to be called */ // ?????????????????? public void itemStateChanged(ItemEvent evt) { System.out.println("itemStateChanged"); if(evt.getStateChange() != ItemEvent.SELECTED) return; Object src = evt.getSource(); if(textureFilesMap.containsKey(src)) { // map change request String terrain = (String)terrainFilesMap.get(src); String texture = (String)textureFilesMap.get(src); loadTerrain(terrain, texture); } } //---------------------------------------------------------- // Methods required by AppearanceGenerator //---------------------------------------------------------- /** * Create a new appearance instance. We set them all up with different * appearance instances, but share the material information. * * Wieso Appearance neu aber Material teilen ???????????? * * @return The new appearance instance to use */ public Appearance createAppearance() { Appearance app = new Appearance(); app.setMaterial(material); app.setPolygonAttributes(polyAttr); return app; } //---------------------------------------------------------- // Internal convenience methods //---------------------------------------------------------- /** * Build the scenegraph for the canvas */ private void buildScene() { Color3f ambientBlue = new Color3f(0.0f, 0.02f, 0.5f); Color3f white = new Color3f(1, 1, 1); Color3f black = new Color3f(0.0f, 0.0f, 0.0f); Color3f blue = new Color3f(0.00f, 0.20f, 0.80f); Color3f specular = new Color3f(0.7f, 0.7f, 0.7f); VirtualUniverse universe = new VirtualUniverse(); Locale locale = new Locale(universe); BranchGroup view_group = new BranchGroup(); BranchGroup world_object_group = new BranchGroup(); PhysicalBody body = new PhysicalBody(); PhysicalEnvironment env = new PhysicalEnvironment(); Point3d origin = new Point3d(0, 0, 0); BoundingSphere light_bounds = new BoundingSphere(origin, BACK_CLIP_DISTANCE); DirectionalLight headlight = new DirectionalLight(); headlight.setColor(white); headlight.setInfluencingBounds(light_bounds); headlight.setEnable(true); // // View group for the ground navigation system that the // roam code will apply to. // // Das ist die ViewPlatform von der aus bestimmt wird was im // Blickfeld ist und geladen werden muss ?????????? // linker Canvas der Demo ViewPlatform gnd_camera = new ViewPlatform(); Transform3D angle = new Transform3D(); gndViewTransform = new TransformGroup(); gndViewTransform.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); gndViewTransform.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); gndViewTransform.addChild(gnd_camera); gndViewTransform.addChild(headlight); gndViewTransform.addChild(new Box(10, 10, 10)); View gnd_view = new View(); gnd_view.setBackClipDistance(BACK_CLIP_DISTANCE); gnd_view.setFrontClipDistance(FRONT_CLIP_DISTANCE); gnd_view.setPhysicalBody(body); gnd_view.setPhysicalEnvironment(env); gnd_view.addCanvas3D(navCanvas); gnd_view.attachViewPlatform(gnd_camera); //System.out.println("front clip dist "+gnd_view.getFrontClipDistance()); //System.out.println("back clip dist "+gnd_view.getBackClipDistance()); groundNav.setViewInfo(gnd_view, gndViewTransform); groundNav.setNavigationSpeed(50.0f); view_group.addChild(gndViewTransform); view_group.addChild(groundNav.getTimerBehavior()); // Create a new branchgroup that is for the geometry. Initially starts // with a null child at position zero so that we only need to write the // child and not extend. One less capability to set is good. terrainGroup = new BranchGroup(); terrainGroup.setCapability(Group.ALLOW_CHILDREN_WRITE); terrainGroup.setCapability(Group.ALLOW_CHILDREN_EXTEND); TransformGroup testBoxTG = new TransformGroup(); Transform3D testBoxT3d = new Transform3D(); testBoxT3d.setTranslation(new Vector3f(50,3510,-50)); testBoxTG.setTransform(testBoxT3d); testBoxTG.addChild(new Box(10, 10, 10)); //world_object_group.addChild(new Box(100, 100, 100)); world_object_group.addChild(testBoxTG); world_object_group.addChild(terrainGroup); // Add everything to the locale locale.addBranchGraph(view_group); locale.addBranchGraph(world_object_group); } /** * Load the terrain and get it read to roll. If the texture file is not * specified then no texture will be loaded and colour information is * used instead. * * @param filename The name of the terrain file * @param textureName The name of the texture file, or null */ private void loadTerrain(String filename, String textureName) //private void loadTerrain() { // Variante 25 5*5 double eastValues[] = new double[25]; eastValues[0]=3445800.0; eastValues[1]=3445800.0; eastValues[2]=3445800.0; eastValues[3]=3445800.0; eastValues[4]=3445800.0; eastValues[5]=3445850.0; eastValues[6]=3445850.0; eastValues[7]=3445850.0; eastValues[8]=3445850.0; eastValues[9]=3445850.0; eastValues[10]=3445900.0; eastValues[11]=3445900.0; eastValues[12]=3445900.0; eastValues[13]=3445900.0; eastValues[14]=3445900.0; eastValues[15]=3445950.0; eastValues[16]=3445950.0; eastValues[17]=3445950.0; eastValues[18]=3445950.0; eastValues[19]=3445950.0; eastValues[20]=3446000.0; eastValues[21]=3446000.0; eastValues[22]=3446000.0; eastValues[23]=3446000.0; eastValues[24]=3446000.0; double northValues[] = new double[25]; northValues[0]=5408515.20967; northValues[1]=5408565.20967; northValues[2]=5408615.20967; northValues[3]=5408665.20967; northValues[4]=5408715.20967; northValues[5]=5408515.20967; northValues[6]=5408565.20967; northValues[7]=5408615.20967; northValues[8]=5408665.20967; northValues[9]=5408715.20967; northValues[10]=5408515.20967; northValues[11]=5408565.20967; northValues[12]=5408615.20967; northValues[13]=5408665.20967; northValues[14]=5408715.20967; northValues[15]=5408515.20967; northValues[16]=5408565.20967; northValues[17]=5408615.20967; northValues[18]=5408665.20967; northValues[19]=5408715.20967; northValues[20]=5408515.20967; northValues[21]=5408565.20967; northValues[22]=5408615.20967; northValues[23]=5408665.20967; northValues[24]=5408715.20967; double heightValues[] = new double[25]; heightValues[0]=3500.0; heightValues[1]=3500.0; heightValues[2]=3500.0; heightValues[3]=3500.0; heightValues[4]=3550.0; heightValues[5]=3550.0; heightValues[6]=3500.0; heightValues[7]=3500.0; heightValues[8]=3500.0; heightValues[9]=3500.0; heightValues[10]=3550.0; heightValues[11]=3500.0; heightValues[12]=3500.0; heightValues[13]=3500.0; heightValues[14]=3500.0; heightValues[15]=3500.0; heightValues[16]=3500.0; heightValues[17]=3500.0; heightValues[18]=3500.0; heightValues[19]=3500.0; heightValues[20]=3550.0; heightValues[21]=3500.0; heightValues[22]=3500.0; heightValues[23]=3500.0; heightValues[24]=3500.0; // Ende Daten Variante 25 View v = navCanvas.getView(); v.stopView(); if(landscape != null) { landscape.setAppearanceGenerator(null); landscape.detach(); landscape = null; } System.gc(); System.out.println("Loading terrain file. Please wait"); TerrainData terrain = null; // Datenzuweisung Variante 25 5*5 // funkt float data[][] = new float[5][5]; for (int i=0;i<5;i++) { data[i][0]=(float) heightValues[i*2]; data[i][1]=(float) heightValues[(i*2)+1]; data[i][2]=(float) heightValues[(i*2)+2]; data[i][3]=(float) heightValues[(i*2)+3]; data[i][4]=(float) heightValues[(i*2)+4]; } System.out.println("data.length "+data.length); for (int j=0;j<data.length;j++) { for (int k=0;k<data[0].length;k++) { System.out.println("data["+j+"]["+k+"] "+data[j][k]); } } // Keine Kopie anfertigen boolean mustCopy = false; // 50m in x und y Richtung Point2d stepDetails = new Point2d(50,50); SimpleTiledTerrainData simpleTerrain = new SimpleTiledTerrainData(data,mustCopy,stepDetails); terrain = simpleTerrain; System.out.println("Building landscape"); // SplitMergeLandscape implementiert eigentlichen // ROAM Algorithmus landscape = new SplitMergeLandscape(viewFrustum, terrain); Point3d p3dmin = new Point3d(); Point3d p3dmax = new Point3d(); //viewFrustum.getBounds(p3dmin,p3dmax); //System.out.println("p3dmin "+p3dmin+" p3dmax "+p3dmax); landscape.setCapability(BranchGroup.ALLOW_DETACH); landscape.setAppearanceGenerator(this); float[] origin = new float[3]; terrain.getCoordinate(origin, 1, 1); System.out.println("origin[] "+origin[0]+" "+origin[1]+" "+origin[2]); Transform3D angle = new Transform3D(); // Anfangsposition des View definieren, funkt fuer crater aber // nicht fuer alien // setup the top view by just raising it some amount and we want Vector3f pos = new Vector3f(); pos.x = origin[0]; pos.y = origin[1]; pos.z = origin[2]+100; //pos.z += 5000; //pos.x = origin[0]; //pos.y = origin[2]; angle.setTranslation(pos); gndViewTransform.setTransform(angle); // Force a single render so that the view transform is updated // and the projection matrix is correct for the view frustum. v.renderOnce(); //viewFrustum.getBounds(p3dmin,p3dmax); //System.out.println("0! p3dmin "+p3dmin+" p3dmax "+p3dmax); viewFrustum.viewingPlatformMoved(); //viewFrustum.getBounds(p3dmin,p3dmax); //System.out.println("1! p3dmin "+p3dmin+" p3dmax "+p3dmax); Matrix3f mtx = new Matrix3f(); Vector3f orient = new Vector3f(0, 0, -1); angle.get(mtx, pos); mtx.transform(orient); //System.out.println("pos "+pos); //System.out.println("orient "+orient); landscape.initialize(pos, orient); //viewFrustum.getBounds(p3dmin,p3dmax); //System.out.println("2! p3dmin "+p3dmin+" p3dmax "+p3dmax); groundNav.setFrameUpdateListener(landscape); terrainGroup.removeAllChildren(); terrainGroup.addChild(landscape); //viewFrustum.getBounds(p3dmin,p3dmax); //System.out.println("3! p3dmin "+p3dmin+" p3dmax "+p3dmax); // Set the nav speed to be one grid square per second groundNav.setNavigationSpeed((float)terrain.getGridXStep()); v.startView(); System.out.println("Ready for rendering"); } public static void main(String[] argv) { RoamTest3 demo = new RoamTest3(); demo.setSize(600, 400); demo.setVisible(true); } }
/***************************************************************************** * J3D.org Copyright (c) 2000 * Java Source * * This source is licensed under the GNU LGPL v2.1 * Please read http://www.gnu.org/copyleft/lgpl.html for more information * * This software comes with the standard NO WARRANTY disclaimer for any * purpose. Use it at your own risk. If there's a problem you get to fix it. * ****************************************************************************/ // Standard imports import java.awt.*; import java.awt.event.*; import javax.media.j3d.Canvas3D; import javax.media.j3d.GraphicsConfigTemplate3D; // Application Specific imports // none /** * Demonstration of a mouse navigation in a world. * * @author Justin Couch * @version $Revision: 1.1 $ */ public class DemoFrameDesTest extends Frame implements WindowListener { public DemoFrameDesTest(String title) { super(title); setLocation(30, 10); addWindowListener(this); } /** * Creates a new canvas each time this is called. * * @return A new canvas instance */ protected Canvas3D createCanvas() { Canvas3D canvas; GraphicsConfigTemplate3D template = new GraphicsConfigTemplate3D(); template.setDoubleBuffer(template.REQUIRED); GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice dev = env.getDefaultScreenDevice(); //System.out.println("env "+env.toString()); //System.out.println("dev "+dev.toString()); //System.out.println("template "+template.toString()); canvas = new Canvas3D(dev.getBestConfiguration(template)); canvas.setStereoEnable(false); canvas.setDoubleBufferEnable(true); //canvas.setDoubleBufferEnable(false); System.out.println("Canvas "+canvas); return canvas; } /** * Ignored */ public void windowActivated(WindowEvent evt) { } /** * Ignored */ public void windowClosed(WindowEvent evt) { } /** * Exit the application * * @param evt The event that caused this method to be called. */ public void windowClosing(WindowEvent evt) { System.exit(0); } /** * Ignored */ public void windowDeactivated(WindowEvent evt) { } /** * Ignored */ public void windowDeiconified(WindowEvent evt) { } /** * Ignored */ public void windowIconified(WindowEvent evt) { } /** * Ignored */ public void windowOpened(WindowEvent evt) { } }
