Thanks Enrique,
 
Thanks for reacting so quickly. This is exactly what I was looking for.
 
Thanks again,
 
Dirk van Krimpen
----- Original Message -----
Sent: Wednesday, October 16, 2002 8:25 PM
Subject: Re: [JAVA3D] Terrain on 30% of the canvas height

Hello !

Well I had the same problem few weeks ago. Mark Hood from sun has posted a WONDERFULL sample to show how to move the origin x0,y0,z0 where you want.

I attached the code, hope that it can help you.

So I think that you want to do the same thing than me : see more terrain on the canvas, for several reasons I did not used the code given by Mark

You can rotate the camera on the Y axis, so you'll see more terrain or you can move the panel containing the canvas to -x, -y so you'll see more terrain too.

I'm using the first tip in my app.

Good luck !

 "Dirk L. van Krimpen" <[EMAIL PROTECTED]> wrote:

 
Hi all,
 
Does anybody know how to move the origin x0,y0,z0 down on the Canvas3D? I know, there are several ways to move up or down the viewers eye point using ViewPlatform or Avatar. However, if doing so the viewer still looks in the direction of the canvas center (slightly up, or down). What I want is the following: Imagine, having your eyeballs centered on the ground, (eye-center height on Z 0 looking towards the origin (x 0,y 0, z0). This all should be on the same canvas height, no looking up or down but just forward. And that all on, let's say, a third of the canvas height from the bottom of the canvas (hope you still can follow me).
 
Of course I checked for examples, but in (probably all) exercises, java 3D demos and java books everything seems to be rotating around the center of the canvas. I suppose there must be some game developers who also don't like to have everything happening on that 50% level. Hopefully, some of them have sorted this out a long time ago already. Suppose, it's not too difficult. However I didn't found a way yet. Must be me.
 
Thanks in advance,
 
Dirk



Do you Yahoo!?
Faith Hill - Exclusive Performances, Videos, & more
faith.yahoo.com


/*
 *      @(#)ManualEyeDemo.java 1.3 02/03/12 19:54:20
 *
 * Copyright (c) 1996-2002 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:
 *
 * - Redistributions 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 AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES
 * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THE 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 SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that Software is not designed,licensed or intended
 * for use in the design, construction, operation or maintenance of
 * any nuclear facility.
 */

import java.awt.* ;
import java.awt.event.* ;
import javax.media.j3d.* ;
import javax.swing.JApplet ;
import javax.swing.JButton ;
import javax.swing.JLabel ;
import javax.swing.JSlider ;
import javax.swing.event.* ;
import javax.vecmath.* ;
import com.sun.j3d.utils.applet.MainFrame ;
import com.sun.j3d.utils.behaviors.vp.* ;
import com.sun.j3d.utils.geometry.* ;
import com.sun.j3d.utils.universe.* ;

/**
 *  This program demonstrates the use of the RELATIVE_TO_SCREEN
eyepoint
 *  policy and how to set the eyepoint using the Canvas3D methods
 *  setLeftManualEyeInImagePlate() and setRightManualEyeInImagePlate().
These
 *  methods allow you position the eyepoint anywhere relative to the
screen or
 *  window, as opposed to the default RELATIVE_TO_FIELD_OF_VIEW
eyepoint
 *  policy, which always centers the eye in the center of the screen or
window
 *  at the appropriate distance to effect the desired field of view.
 *  <p>
 *  Setting the eyepoint at an offset from the center of the window or
screen
 *  produces skewed projection transforms.  These have the effect of
 *  allowing one to see to the sides or the top and bottom of an object
 *  without altering the orientation of the projection plane relative
to the
 *  object being viewed.  Portions of the objects which intersect the
 *  projection plane will not change shape when moving the eyepoint in
this
 *  manner, and lines which are parallel to the projection plane will
not
 *  converge due to the effect of perspective.
 *  <p>
 *  This is useful in architectural renderings where it is often
desirable to
 *  view a building from different eyepoints without having the sides
of the
 *  building converge in the projected image.
 *  <p>
 *  Note that it is not possible to achieve the proper effect while
using the
 *  RELATIVE_TO_WINDOW eyepoint policy.  With that policy the eyepoint
is
 *  still always centered about the window, and only the Z components
of the
 *  LeftManualEyeInImagePlate and RightManualEyeInImagePlate values are
 *  used.  Instead, we have to use RELATIVE_TO_SCREEN and track the
location
 *  of the window on the screen to keep the eyepoint in the desired
location
 *  relative to the window.
 *  <p>
 *  The nested class ManualEyeUpdater encapsulates the code needed to
track
 *  the position of the window and update the manual eye positions
based on
 *  offsets from the center of the window and should be usable by other
 *  applications. The rest of this example program mainly justs sets up
the
 *  content scenegraph and the GUI.
 *  <p>
 *  This program needs Java 3D beta 1 or later to run.  A window will
come up
 *  with sliders to allow you to adjust the X, Y, and Z positions of
the
 *  eyepoint relative to the center of the window.  The reset button
will set
 *  them back to their nominal values.  An OrbitBehavior is also
attached to
 *  the view platform so that you can contrast the effect of moving the
 *  view platform with the effect of moving the eyepoint relative to
the view
 *  platform.  (Note that due to bugs in OrbitBehavior the reset button
will
 *  not correctly reset the view platform transform -- this is fixed in
Java
 *  3D beta 2 and later).
 */
public class ManualEyeDemo extends JApplet
    implements ChangeListener, ActionListener {

    float initialEyeOffsetX = 0.00f ;
    float initialEyeOffsetY = 0.00f ;
    float initialEyeOffsetZ = 0.25f ;

    SimpleUniverse universe ;
    OrbitBehavior orbit ;
    ManualEyeUpdater eyeUpdater ;
    JButton resetButton ;
    JSlider eyeOffsetXSlider, eyeOffsetYSlider, eyeOffsetZSlider ;
    Bounds infiniteBounds = new BoundingSphere(new Point3d(0.0, 0.0,
0.0),
                                               Double.POSITIVE_INFINITY) ;

    public void init() {
        // Create a Canvas3D and add it to the applet.
        Container pane = getContentPane() ;
        Canvas3D c = new
Canvas3D(SimpleUniverse.getPreferredConfiguration()) ;
        pane.add(c, BorderLayout.CENTER) ;

        // Create a simple universe.
        universe = new SimpleUniverse(c) ;

        // Set the clip distances appropriate for the view.
        View v = universe.getViewer().getView() ;
        v.setFrontClipDistance(0.01) ;
        v.setBackClipDistance(5.0) ;

        // Create a simple scene and attach it to the universe.
        universe.addBranchGraph(createSceneGraph()) ;

        // Create the ManualEyeUpdater to manage the manual eye position.
        eyeUpdater = new ManualEyeUpdater(universe, c,
                                          initialEyeOffsetX,
                                          initialEyeOffsetY,
                                          initialEyeOffsetZ) ;

        // Create the GUI for setting the manual eye position.
        pane.add(createEyeUpdaterUI(), BorderLayout.SOUTH) ;

        // Create an OrbitBehavior to move the view platform.
        orbit = new OrbitBehavior(c, OrbitBehavior.REVERSE_ALL) ;
        orbit.setSchedulingBounds(infiniteBounds) ;
        orbit.setHomeTransform(new Transform3D()) ;
        universe.getViewingPlatform().setViewPlatformBehavior(orbit) ;
    }

    public void start() {
        // If the applet is visible, set the initial canvas center.  This is
        // done here instead of init() to ensure that the Canvas3D has been
        // fully sized within the applet.
        if (isShowing())
            eyeUpdater.updateCanvasCenter() ;
    }

    public void destroy() {
        universe.removeAllLocales() ;
    }

    BranchGroup createSceneGraph() {
        // Create the root of the branch graph
        BranchGroup objRoot = new BranchGroup() ;

        // Create some Appearances.
        Appearance app1 = new Appearance() ;
        Material m1 = new Material() ;
        m1.setLightingEnable(true) ;
        app1.setMaterial(m1) ;

        Appearance app2 = new Appearance() ;
        Material m2 = new Material() ;
        m2.setDiffuseColor(new Color3f(0.6f, 0.7f, 0.8f)) ;
        m2.setLightingEnable(true) ;
        app2.setMaterial(m2) ;

        Appearance app3 = new Appearance() ;
        Material m3 = new Material() ;
        m3.setDiffuseColor(new Color3f(0.5f, 0.6f, 0.7f)) ;
        m3.setLightingEnable(true) ;
        app3.setMaterial(m3) ;

        // Create some boxes to resemble buildings.  Put them on a common
        // ground level of -0.60 in Y and put the front faces of two of them
        // directly on the projection plane (Z = 0.0) so that remain invariant
        // when subjected to manual eye movements.
        Box b1 = new Box(0.15f, 0.60f, 0.15f, Box.GENERATE_NORMALS, app1) ;
        Transform3D b1Xfm = new Transform3D() ;
        b1Xfm.set(new Vector3f(-0.40f, 0.00f, -0.15f)) ;
        TransformGroup b1Grp = new TransformGroup(b1Xfm);
        b1Grp.addChild(b1) ;
        objRoot.addChild(b1Grp) ;

        Box b2 = new Box(0.15f, 0.50f, 0.15f, Box.GENERATE_NORMALS, app1) ;
        Transform3D b2Xfm = new Transform3D() ;
        b2Xfm.set(new Vector3f(0.45f, -0.10f, -0.15f)) ;
        TransformGroup b2Grp = new TransformGroup(b2Xfm);
        b2Grp.addChild(b2) ;
        objRoot.addChild(b2Grp) ;

        Box b3 = new Box(0.35f, 0.25f, 0.20f, Box.GENERATE_NORMALS, app2) ;
        Transform3D b3Xfm = new Transform3D() ;
        b3Xfm.set(new Vector3f(-0.50f, -0.35f, -0.60f)) ;
        TransformGroup b3Grp = new TransformGroup(b3Xfm);
        b3Grp.addChild(b3) ;
        objRoot.addChild(b3Grp) ;

        Box b4 = new Box(0.45f, 0.30f, 0.25f, Box.GENERATE_NORMALS, app2) ;
        Transform3D b4Xfm = new Transform3D() ;
        b4Xfm.set(new Vector3f(0.55f, -0.30f, -0.65f)) ;
        TransformGroup b4Grp = new TransformGroup(b4Xfm);
        b4Grp.addChild(b4) ;
        objRoot.addChild(b4Grp) ;

        Box b5 = new Box(0.20f, 0.55f, 0.15f, Box.GENERATE_NORMALS, app3) ;
        Transform3D b5Xfm = new Transform3D() ;
        b5Xfm.set(new Vector3f(-0.05f, -0.05f, -1.2f)) ;
        TransformGroup b5Grp = new TransformGroup(b5Xfm);
        b5Grp.addChild(b5) ;
        objRoot.addChild(b5Grp) ;

        // Set up the ambient light
        Color3f ambientColor = new Color3f(0.2f, 0.2f, 0.2f);
        AmbientLight ambientLight = new AmbientLight(ambientColor);
        ambientLight.setInfluencingBounds(infiniteBounds);
        objRoot.addChild(ambientLight);

        // Set up the directional lights.
        Color3f lColor1 = new Color3f(0.7f, 0.7f, 0.7f) ;
        Color3f lColor2 = new Color3f(0.3f, 0.3f, 0.3f) ;
        Vector3f lDir1  = new Vector3f(-0.7f, -0.8f, -0.9f) ;
        Vector3f lDir2  = new Vector3f(0.1f, 0.1f, -1.0f) ;
        DirectionalLight lgt1 = new DirectionalLight(lColor1, lDir1) ;
        DirectionalLight lgt2 = new DirectionalLight(lColor2, lDir2) ;
        lgt1.setInfluencingBounds(infiniteBounds);
        lgt2.setInfluencingBounds(infiniteBounds);
        objRoot.addChild(lgt1) ;
        objRoot.addChild(lgt2) ;

        // Set up the background
        Color3f bgColor = new Color3f(0.05f, 0.05f, 0.5f) ;
        Background bgNode = new Background(bgColor) ;
        bgNode.setApplicationBounds(infiniteBounds) ;
        objRoot.addChild(bgNode) ;

        return objRoot ;
    }


    javax.swing.Box createEyeUpdaterUI() {
        // Create sliders for setting the eyepoint offsets relative to the
        // middle of the Canvas3D.
        JLabel xLabel = new JLabel("Eye X Offset") ;
        xLabel.setAlignmentX(Component.CENTER_ALIGNMENT) ;
        eyeOffsetXSlider = new JSlider(-50, 50, (int)(initialEyeOffsetX*100))
;
        eyeOffsetXSlider.addChangeListener(this) ;

        JLabel yLabel = new JLabel("Eye Y Offset") ;
        yLabel.setAlignmentX(Component.CENTER_ALIGNMENT) ;
        eyeOffsetYSlider = new JSlider(-50, 50, (int)(initialEyeOffsetY*100))
;
        eyeOffsetYSlider.addChangeListener(this) ;

        JLabel zLabel = new JLabel("Eye Z Offset") ;
        zLabel.setAlignmentX(Component.CENTER_ALIGNMENT) ;
        eyeOffsetZSlider = new JSlider(2, 150, (int)(initialEyeOffsetZ*100)) ;
        eyeOffsetZSlider.addChangeListener(this) ;

        // Create a button to reset the eye and viewplatform position.
        final JButton resetButton = new JButton("Reset") ;
        resetButton.setAlignmentX(Component.CENTER_ALIGNMENT) ;
        resetButton.addActionListener(this) ;

        // Create a Swing Box to hold the UI elements.
        javax.swing.Box box = javax.swing.Box.createVerticalBox() ;
        box.add(xLabel) ;
        box.add(eyeOffsetXSlider) ;
        box.add(yLabel) ;
        box.add(eyeOffsetYSlider) ;
        box.add(zLabel) ;
        box.add(eyeOffsetZSlider) ;
        box.add(resetButton) ;

        return box ;
    }

    public void stateChanged(ChangeEvent e) {
        // Update eye offset from slider values.
        eyeUpdater.updateEyeOffset(eyeOffsetXSlider.getValue() / 100f,
                                   eyeOffsetYSlider.getValue() / 100f,
                                   eyeOffsetZSlider.getValue() / 100f) ;
    }

    public void actionPerformed(ActionEvent e) {
        // Reset eye offset and view platform position.
        eyeUpdater.updateEyeOffset(initialEyeOffsetX,
                                   initialEyeOffsetY,
                                   initialEyeOffsetZ) ;

        eyeOffsetXSlider.setValue((int)(initialEyeOffsetX*100f)) ;
        eyeOffsetYSlider.setValue((int)(initialEyeOffsetY*100f)) ;
        eyeOffsetZSlider.setValue((int)(initialEyeOffsetZ*100f)) ;

        orbit.goHome() ;
    }

    public class ManualEyeUpdater
        implements ComponentListener, HierarchyBoundsListener {

        private Canvas3D canvas ;
        private Point3d eye = new Point3d() ;
        private Rectangle screenBounds ;
        private double metersPerPixelX ;
        private double metersPerPixelY ;
        private double canvasCenterX, canvasCenterY ;
        private float eyeOffsetX, eyeOffsetY, eyeOffsetZ ;

        public ManualEyeUpdater(SimpleUniverse u, Canvas3D canvas,
                                float eyeOffsetX, float eyeOffsetY,
                                float eyeOffsetZ) {

            this.canvas = canvas ;
            this.eyeOffsetX = eyeOffsetX ;
            this.eyeOffsetY = eyeOffsetY ;
            this.eyeOffsetZ = eyeOffsetZ ;

            // Use the RELATIVE_TO_SCREEN eyepoint policy and listen for
            // canvas moves and resizes to manually maintain the eyepoint in
            // the desired position relative to the canvas.
            //
            // RELATIVE_TO_WINDOW can't be used since that policy only uses
            // the Z component of the manual eyepoint and always centers it in
            // the canvas.
            View v = u.getViewer().getView() ;
            v.setWindowEyepointPolicy(View.RELATIVE_TO_SCREEN) ;

            // To simplify eye placement, use the NOMINAL_SCREEN view attach
            // policy to set the view platform origin in physical coordinates
            // to the center of coexistence.  The center of coexistence
            // follows the center of the canvas when using the default window
            // movement policy of PHYSICAL_WORLD.
            ViewingPlatform vp = u.getViewingPlatform();
            vp.getViewPlatform().setViewAttachPolicy(View.NOMINAL_SCREEN) ;

            // Derive information needed to compute the middle of the Canvas3D
            // relative to its position and size on the image plate.
            Screen3D screen = canvas.getScreen3D() ;
            screenBounds = canvas.getGraphicsConfiguration().getBounds() ;
            double physicalScreenWidth = screen.getPhysicalScreenWidth() ;
            double physicalScreenHeight = screen.getPhysicalScreenHeight() ;

            metersPerPixelX =
                physicalScreenWidth / (double)screenBounds.width ;
            metersPerPixelY =
                physicalScreenHeight / (double)screenBounds.height ;

            // Add listeners.
            canvas.addComponentListener(this) ;
            canvas.addHierarchyBoundsListener(this) ;
        }

        public void componentShown(ComponentEvent e) {
            updateCanvasCenter() ;
        }

        public void componentMoved(ComponentEvent e) {
            // Normally the canvas never moves relative to content pane.
            // We have to listen for ancestorMoved events instead.
            updateCanvasCenter() ;
        }

        public void componentResized(ComponentEvent e) {
            updateCanvasCenter() ;
        }

        public void componentHidden(ComponentEvent e) {
            // No need to do anything here.
        }

        public void ancestorMoved(HierarchyEvent e) {
            // Normally the canvas never moves relative to content pane.
            // We have to listen for ancestorMoved events instead.
            updateCanvasCenter() ;
        }

        public void ancestorResized(HierarchyEvent e) {
            // This will always trigger a componentResized on the canvas.
            // No need to update the canvas center for each ancestor resize.
        }

        /**
         * Compute the center of the Canvas3D in physical image plate
         * coordinates.
         */
        public void updateCanvasCenter() {
            int w = canvas.getWidth() ;
            int h = canvas.getHeight() ;

            // Java 3D problem: the getPixelLocationInImagePlate() method of
            // Canvas3D should be able to take pixel values relative to the
            // upper left corner of the canvas and convert them to their
            // corresponding physical image plate coordinates here, but they
            // instead always reflect the previous canvas position.
            //
            // The workaround is to get the location of the canvas center
            // relative to the screen and convert it explicitly to physical
            // image plate coordinates based on the size of a pixel in
            // meters.
            double physicalWidth = w * metersPerPixelX ;
            double physicalHeight = h * metersPerPixelY ;

            // AWT pixel locations are expressed in terms of a contiguous
            // virtual screen area which encompasses all physical screens.
            // Subtract the screen origin to get pixels relative to the
            // physical screen on which the Canvas3D was created.
            Point awtLocation = canvas.getLocationOnScreen() ;
            int x = awtLocation.x - screenBounds.x;
            int y = awtLocation.y - screenBounds.y;

            double physicalXLeft = x * metersPerPixelX ;
            double physicalYBottom =
                (screenBounds.height - (y + h)) * metersPerPixelY ;

            canvasCenterX = physicalXLeft + physicalWidth / 2.0 ;
            canvasCenterY = physicalYBottom + physicalHeight / 2.0 ;

            updateEye() ;
        }

        public void updateEyeOffset(float eyeOffsetX,
                                    float eyeOffsetY, float eyeOffsetZ) {

            this.eyeOffsetX = eyeOffsetX ;
            this.eyeOffsetY = eyeOffsetY ;
            this.eyeOffsetZ = eyeOffsetZ ;

            updateEye() ;
        }

        private void updateEye() {
            eye.x = canvasCenterX + eyeOffsetX ;
            eye.y = canvasCenterY + eyeOffsetY ;
            eye.z = eyeOffsetZ ;

            canvas.setLeftManualEyeInImagePlate(eye) ;
            canvas.setRightManualEyeInImagePlate(eye) ;
        }
    }

    public static void main(String[] args) {
        new MainFrame(new ManualEyeDemo(), 700, 700);
    }
}

Reply via email to