Hi Justin or others,

I downlowded the code from the cvs repository and I am playing with the
Roam example. Basically I would like to include the Roam code in my
system.
Playing with the Roam example code I encountered the following problem.
Since I don't use data from the data format in the provided example I did
not use that part. I tried to simplify the example a bit for me, for
better understanding. I threw the buttons away and included a little data
array in the code. At the end of the constructor code I included the call
for the loadTerrain() method.
When I start the application I would expect that the terrain is being
loaded and visible. But in fact, it is not. I becomes visible using the
navigation. Maybe the problem lies with the tMatrix variable of
ViewFrustum. I put a System.out.println(tMatrix) in the method
computeFrustumPlanes() of ViewFrustum. When reaching mousePressed() of
NavigationHandler the tMatrix is okay.
When I include setSize(600,400) and setVisible(true) before the call of
loadTerrain() the terrain is rendered when starting the application.
(And that workaround is not working in my project)
Sorry, this is confusing me, when is the tMatrix due for initalization?
What is happening here?
Please see the attached files RoamTest2.java and DemoFrameDesTest.java.

Desiree

oooooooooooooooooooooooooooooooooooooooooooooooo
Desiree Hilbring

Institut fuer Photogrammetrie und Fernerkundung
Universitaet Karlsruhe, Germany
email: [EMAIL PROTECTED]
# 0721 6083676
oooooooooooooooooooooooooooooooooooooooooooooooo

/*****************************************************************************
 *                        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 RoamTest2 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 RoamTest2()
    {
        super("Terrain Culling Demo");

        //topDownCanvas = createCanvas();
        navCanvas = createCanvas();

        /*
        Cursor curse = Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
        navCanvas.setCursor(curse);
        */

        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);

        /*
        // Ratcliff funktioniert nicht, wohl weil ViewPoint falsch
        button = new JRadioButton("Ratcliff Alien");
        button.addItemListener(this);
        grp.add(button);
        p1.add(button);

        terrainFilesMap.put(button, "ratcliff_1k.bt");
        textureFilesMap.put(button, "ratcliff_crater_2048.jpg");
        //        textureFilesMap.put(button, null);
        */

        //add(p1, BorderLayout.SOUTH);

        // Panel for the polygon mode style
        /*
        polyModeMap = new HashMap();

        JPanel p2 = new JPanel(new GridLayout(4, 1));

        p2.add(new JLabel("Render As..."));

        grp = new ButtonGroup();
        button = new JRadioButton("Polygons", true);
        button.addItemListener(this);
        grp.add(button);
        p2.add(button);
        polyModeMap.put(button, new Integer(PolygonAttributes.POLYGON_FILL));


        button = new JRadioButton("Lines");
        button.addItemListener(this);
        grp.add(button);
        p2.add(button);
        polyModeMap.put(button, new Integer(PolygonAttributes.POLYGON_LINE));


        button = new JRadioButton("Points");
        button.addItemListener(this);
        grp.add(button);
        p2.add(button);
        polyModeMap.put(button, new Integer(PolygonAttributes.POLYGON_POINT));


        JPanel p3 = new JPanel(new BorderLayout());
        p3.add(p2, BorderLayout.NORTH);

        add(p3, BorderLayout.EAST);
        */

        // 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);


        /*
        NavigationStateManager gnd_nav_mgr =
            new NavigationStateManager(navCanvas);
        gnd_nav_mgr.setMouseHandler(groundNav); 
        */

        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);
        }
        /*
        else
        {
            Integer mode_int = (Integer)polyModeMap.get(src);
            polyAttr.setPolygonMode(mode_int.intValue());
        }
        */
    }

    //----------------------------------------------------------
    // 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());       

        // Just an axis for reference
        //world_object_group.addChild(new Axis());

        // 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);

        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);

        // Patch size 2, weiss nicht ob geht evtl muss datensatz power of two 
        // sein
        //landscape = new SplitMergeLandscape(viewFrustum, terrain, 2);
        //landscape = new SplitMergeLandscape(viewFrustum, terrain, 1);
        //landscape = new SplitMergeLandscape(viewFrustum, terrain, 4);
        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.z += 5000;
        pos.x = origin[0];
        pos.y = origin[2];
        angle.setTranslation(pos);
        
        //topViewTransform.setTransform(angle);
        
        // the initial view to be some way off the ground too and rotate at
        // 45 deg to look into the "middle" of the terrain.
        terrain.getCoordinate(origin, 0, 0);
        pos.set(origin);
        pos.y += 100;
        pos.x -= 100;
        pos.z -= 100;
        angle.rotY(Math.PI * -0.25); // 45 deg looking into the terrain
        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();
        
        // ?????????????
        // Was macht das, passt irgendwie auf das sich Plattform
        // bewegt?
        // Wie realisiere ich das bei mir?
        //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);
        
        // ?????????????
        // Was macht das?
        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)
    {
        RoamTest2 demo = new RoamTest2();
        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);

        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)
    {
    }
}

Reply via email to