Try using the attached class. It keeps track of the transformations and has a method to transform from local coordinates to window coordinates. It can probably be simplified using the Canvas3D.getPixelLocationFromImagePlate() method in J3D 1.2 beta (just released). Doug Gehringer Sun Microsytems
/* * @(#)LocalToWindow.java 1.2 99/02/08 15:39:12 * * Copyright (c) 1999 Sun Microsystems, Inc. All Rights Reserved. * * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use, * modify and redistribute this software in source and binary code form, * provided that i) this copyright notice and license appear on all copies of * the software; and ii) Licensee does not utilize the software in a manner * which is disparaging to Sun. * * 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. * * This software is not designed or intended for use in on-line control of * aircraft, air traffic, aircraft navigation or aircraft communications; or in * the design, construction, operation or maintenance of any nuclear * facility. Licensee represents and warrants that it will not use or * redistribute the Software for such purposes. */ /** * Utility class for doing local->window transformations for case where * Canvas3D is a simple display such as a monitor. This won't work for the * more complex cases (i.e. a multiple canvases, head tracking, etc). * * Usage: * // after the canvas and node are created * LocalToWindow locToWindow = LocalToWindow(node, canvas); * ... * // when we need to transform (canvas location and node transforms may have * // changed) * locToWindow.update(); // make sure transforms are up to date * * Point3d[] localPts = <some local coords to transform > * Point[] windowPts = <the area to put the tranformed pts > * for (int i = 0; i < localPts.length; i++) { * locToWindow.transformPt(localPts[i], windowPts[i]); * } */ // standard j3d packages import javax.media.j3d.*; import javax.vecmath.*; import java.awt.Point; import java.awt.Dimension; public class LocalToWindow { Canvas3D canvas = null; Node node = null; // inquired/derived data Transform3D localToVworld = new Transform3D(); Transform3D vworldToImagePlate = new Transform3D(); Transform3D localToImagePlate = new Transform3D(); Point3d eyePos = new Point3d(); int projType; Point canvasScr; Dimension screenSize; double metersPerPixelX; double metersPerPixelY; // Temporaries Point3d imagePlatePt = new Point3d(); Vector3d projVec = new Vector3d(); Point2d screenPt = new Point2d(); Point2d tempPt2d = new Point2d(); /** * Creates a LocalToWindow object with no associated node or canvas. * The node and canvas must be set before transforming points */ public LocalToWindow() {}; /** * Called with the Node which specifies the local coordinates for the * points to be transformed and the Canvas3D where the points are * displayed */ public LocalToWindow(Node node, Canvas3D canvas) { this.canvas = canvas; this.node = node; update(); } /** * Either create LocalToWindow() just before transforming points or call * this method to ensure that the transforms are up to date. Note: if * you are transforming several points, you only need to call this method * once. */ public void update() { if ((this.canvas != null) && (this.node != null)) { node.getLocalToVworld(localToVworld); canvas.getVworldToImagePlate(vworldToImagePlate); // Make a composite transform: // vWorldPt = LocalToVworld * localPt; // imagePlatePt = VworldToImagePlate * vWorldPt; // imagePlatePt = VworldToImagePlate * LocalToVworld * localPt; localToImagePlate.mul(vworldToImagePlate, localToVworld); // we need these to project the point from Image Plate coords to // the actual image plate (i.e. perpsective) canvas.getCenterEyeInImagePlate(eyePos); //System.out.println("eyePos = " + eyePos); projType = canvas.getView().getProjectionPolicy(); // this stuff is to go from image plate coords to window coords canvasScr = canvas.getLocationOnScreen(); //System.out.println("canvasScr = " + canvasScr); screenSize = canvas.getScreen3D().getSize(); double physicalScreenWidth = canvas.getScreen3D().getPhysicalScreenWidth(); double physicalScreenHeight = canvas.getScreen3D().getPhysicalScreenHeight(); metersPerPixelX = physicalScreenWidth / (double) screenSize.width; metersPerPixelY = physicalScreenHeight / (double) screenSize.height; } } /** * Set the node and canvas and call update() */ public void update(Node node, Canvas3D canvas) { this.canvas = canvas; this.node = node; update(); } /** * Transform the point from local coords to window coords */ public void transformPt(Point3d localPt, Point2d windowPt) { // TODO: throw some kind of error if node and canvas haven't been // set //System.out.println("vWorld Pt = " + localPt); localToImagePlate.transform(localPt, imagePlatePt); //System.out.println("imagePlatePt = " + imagePlatePt); double zScale = 1.0; // default, used for PARALELL_PROJECTION if (projType == View.PERSPECTIVE_PROJECTION) { // get the vector from eyePos to imagePlatePt projVec.sub(imagePlatePt, eyePos); // Scale this vector to make it end at the projection plane. // Scale is ratio : // eye->imagePlate Plane dist / eye->imagePlatePt dist // eye dist to plane is eyePos.z (eye is in +z space) // image->eye dist is -projVec.z (image->eye is in -z dir) //System.out.println("eye dist = " + (eyePos.z)); //System.out.println("image dist = " + (-projVec.z)); zScale = eyePos.z / (-projVec.z); screenPt.x = eyePos.x + projVec.x * zScale; screenPt.y = eyePos.y + projVec.y * zScale; } else { screenPt.x = imagePlatePt.x; screenPt.y = imagePlatePt.y; } //System.out.println("screenPt = " + screenPt); // Note: screenPt is in image plate coords, at z=0 // Transform from image plate coords to screen coords windowPt.x = (screenPt.x / metersPerPixelX) - canvasScr.x; windowPt.y = screenSize.height - 1 - (screenPt.y / metersPerPixelY) - canvasScr.y; //System.out.println("windowPt = " + windowPt); } /** * Transform the point from local coords to window coords */ public void transformPt(Point3d localPt, Point windowPt) { transformPt(localPt, tempPt2d); windowPt.x = (int)Math.round(tempPt2d.x); windowPt.y = (int)Math.round(tempPt2d.y); } }