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