diff options
Diffstat (limited to 'src/javax/media/j3d/CanvasViewCache.java')
-rw-r--r-- | src/javax/media/j3d/CanvasViewCache.java | 2044 |
1 files changed, 0 insertions, 2044 deletions
diff --git a/src/javax/media/j3d/CanvasViewCache.java b/src/javax/media/j3d/CanvasViewCache.java deleted file mode 100644 index 0360d3c..0000000 --- a/src/javax/media/j3d/CanvasViewCache.java +++ /dev/null @@ -1,2044 +0,0 @@ -/* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - */ - -package javax.media.j3d; - -import java.awt.Rectangle; - -import javax.vecmath.Matrix4d; -import javax.vecmath.Point2d; -import javax.vecmath.Point3d; -import javax.vecmath.Point4d; -import javax.vecmath.SingularMatrixException; -import javax.vecmath.Vector3d; -import javax.vecmath.Vector4d; - -/** - * The CanvasViewCache class is used to cache all data, both API data - * and derived data, that is dependent on the Canvas3D or Screen3D. - * The final view and projection matrices are stored here. - */ - -class CanvasViewCache extends Object { - // Used for debugging only - private static Object debugLock = new Object(); - - // The canvas associated with this canvas view cache - private Canvas3D canvas; - - // Mask that indicates this CanvasViewCache view dependence info. has changed, - // and CanvasViewCache may need to recompute the final view matries. - int cvcDirtyMask = 0; - - // The screen view cache associated with this canvas view cache - private ScreenViewCache screenViewCache; - - // The view cache associated with this canvas view cache - private ViewCache viewCache; - - // ************* - // API/INPUT DATA - // ************* - - // The position and size of the canvas (in pixels) - private int awtCanvasX; - private int awtCanvasY; - private int awtCanvasWidth; - private int awtCanvasHeight; - - // The current RenderBin used for rendering during the frame - // associated with this snapshot. - private RenderBin renderBin; - - // Flag indicating whether or not stereo will be used. Computed by - // Canvas3D as: useStereo = stereoEnable && stereoAvailable - private boolean useStereo; - - // Current monoscopic view policy from canvas - private int monoscopicViewPolicy; - - // The manual positions of the left and right eyes in image-plate - // coordinates. - // Note that these values are only used in non-head-tracked mode - // when the view's window eyepoint policy is one of RELATIVE_TO_SCREEN - // or RELATIVE_TO_WINDOW. - private Point3d leftManualEyeInImagePlate = new Point3d(); - private Point3d rightManualEyeInImagePlate = new Point3d(); - - // ************* - // DERIVED DATA - // ************* - - // The width and height of the screen in meters (from ScreenViewCache) - double physicalScreenWidth; - double physicalScreenHeight; - - // The width and height of the screen in pixels (from ScreenViewCache) - int screenWidth; - int screenHeight; - - // Meters per pixel in the X and Y dimension (from ScreenViewCache) - double metersPerPixelX; - double metersPerPixelY; - - // The position and size of the canvas (in pixels) - private int canvasX; - private int canvasY; - private int canvasWidth; - private int canvasHeight; - - // Either the Canvas' or the View's monoscopicViewPolicy - private int effectiveMonoscopicViewPolicy; - - // The current cached projection transforms. - private Transform3D leftProjection = new Transform3D(); - private Transform3D rightProjection = new Transform3D(); - private Transform3D infLeftProjection = new Transform3D(); - private Transform3D infRightProjection = new Transform3D(); - - // The current cached viewing transforms. - private Transform3D leftVpcToEc = new Transform3D(); - private Transform3D rightVpcToEc = new Transform3D(); - private Transform3D infLeftVpcToEc = new Transform3D(); - private Transform3D infRightVpcToEc = new Transform3D(); - - // The current cached inverse viewing transforms. - private Transform3D leftEcToVpc = new Transform3D(); - private Transform3D rightEcToVpc = new Transform3D(); - private Transform3D infLeftEcToVpc = new Transform3D(); - private Transform3D infRightEcToVpc = new Transform3D(); - - // Arrays of Vector4d objects that represent the plane equations for - // the 6 planes in the viewing frustum in ViewPlatform coordinates. - private Vector4d[] leftFrustumPlanes = new Vector4d[6]; - private Vector4d[] rightFrustumPlanes = new Vector4d[6]; - - // Arrays of Vector4d objects that represent the volume of viewing frustum - private Point4d leftFrustumPoints[] = new Point4d[8]; - private Point4d rightFrustumPoints[] = new Point4d[8]; - - // Calibration matrix from Screen object for HMD mode using - // non-field-sequential stereo - - private Transform3D headTrackerToLeftImagePlate = new Transform3D(); - private Transform3D headTrackerToRightImagePlate = new Transform3D(); - - // Head tracked version of eye in imageplate - private Point3d leftTrackedEyeInImagePlate = new Point3d(); - private Point3d rightTrackedEyeInImagePlate = new Point3d(); - - // Derived version of eye in image plate coordinates - private Point3d leftEyeInImagePlate = new Point3d(); - private Point3d rightEyeInImagePlate = new Point3d(); - private Point3d centerEyeInImagePlate = new Point3d(); - - // Derived version of nominalEyeOffsetFromNominalScreen - private double nominalEyeOffset; - - // Physical window position,size and center (in image plate coordinates) - private double physicalWindowXLeft; - private double physicalWindowYBottom; - private double physicalWindowXRight; - private double physicalWindowYTop; - private double physicalWindowWidth; - private double physicalWindowHeight; - private Point3d physicalWindowCenter = new Point3d(); - - // Screen scale value from viewCache or from screen size. - private double screenScale; - - // Window scale value that compensates for window size if - // the window resize policy is PHYSICAL_WORLD. - private double windowScale; - - // ViewPlatform scale that takes coordinates from view platform - // coordinates and scales them to physical coordinates - private double viewPlatformScale; - - // Various derived transforms - - private Transform3D leftCcToVworld = new Transform3D(); - private Transform3D rightCcToVworld = new Transform3D(); - - private Transform3D coexistenceToLeftPlate = new Transform3D(); - private Transform3D coexistenceToRightPlate = new Transform3D(); - - private Transform3D vpcToCoexistence = new Transform3D(); - - private Transform3D vpcToLeftPlate = new Transform3D(); - private Transform3D vpcToRightPlate = new Transform3D(); - private Transform3D leftPlateToVpc = new Transform3D(); - private Transform3D rightPlateToVpc = new Transform3D(); - private Transform3D vworldToLeftPlate = new Transform3D(); - private Transform3D lastVworldToLeftPlate = new Transform3D(); - private Transform3D vworldToRightPlate = new Transform3D(); - private Transform3D leftPlateToVworld = new Transform3D(); - private Transform3D rightPlateToVworld = new Transform3D(); - private Transform3D headToLeftImagePlate = new Transform3D(); - private Transform3D headToRightImagePlate = new Transform3D(); - - private Transform3D vworldToTrackerBase = new Transform3D(); - private Transform3D tempTrans = new Transform3D(); - private Transform3D headToVworld = new Transform3D(); - private Vector3d coexistenceCenter = new Vector3d(); - - // scale for transformimg clip and fog distances - private double vworldToCoexistenceScale; - private double infVworldToCoexistenceScale; - - // - // Temporary matrices and vectors, so we dont generate garbage - // - private Transform3D tMat1 = new Transform3D(); - private Transform3D tMat2 = new Transform3D(); - private Vector3d tVec1 = new Vector3d(); - private Vector3d tVec2 = new Vector3d(); - private Vector3d tVec3 = new Vector3d(); - private Point3d tPnt1 = new Point3d(); - private Point3d tPnt2 = new Point3d(); - - private Matrix4d tMatrix = new Matrix4d(); - - /** - * The view platform transforms. - */ - private Transform3D vworldToVpc = new Transform3D(); - private Transform3D vpcToVworld = new Transform3D(); - private Transform3D infVworldToVpc = new Transform3D(); - - // This flag is used to remember the last time doInfinite flag - // is true or not. - // If this cache is updated twice, the first time in RenderBin - // updateViewCache() and the second time in Renderer with - // geometryBackground. The first time will reset the vcDirtyMask - // to 0 so that geometry background will not get updated the - // second time doComputeDerivedData() is invoked when view change. - private boolean lastDoInfinite = false; - private boolean updateLastTime = false; - - void getCanvasPositionAndSize() { - if(J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2) { - System.err.println("Get canvas position and size"); - System.err.println("Before"); - System.err.println("Canvas pos = (" + awtCanvasX + ", " + - awtCanvasY + "), size = " + awtCanvasWidth + - "x" + awtCanvasHeight); - System.err.println("After"); - } - awtCanvasX = canvas.newPosition.x; - awtCanvasY = canvas.newPosition.y; - awtCanvasWidth = canvas.newSize.width; - awtCanvasHeight = canvas.newSize.height; - - // The following works around problem when awt creates 0-size - // window at startup - if ((awtCanvasWidth <= 0) || (awtCanvasHeight <= 0)) { - awtCanvasWidth = 1; - awtCanvasHeight = 1; - } - - if (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1) { - System.err.println("Canvas pos = (" + awtCanvasX + ", " + - awtCanvasY + "), size = " + awtCanvasWidth + - "x" + awtCanvasHeight); - } - } - - void computefrustumBBox(BoundingBox frustumBBox) { - int i; - - for(i = 0; i < leftFrustumPoints.length; i++) { - if(frustumBBox.lower.x > leftFrustumPoints[i].x) - frustumBBox.lower.x = leftFrustumPoints[i].x; - if(frustumBBox.lower.y > leftFrustumPoints[i].y) - frustumBBox.lower.y = leftFrustumPoints[i].y; - if(frustumBBox.lower.z > leftFrustumPoints[i].z) - frustumBBox.lower.z = leftFrustumPoints[i].z; - - if(frustumBBox.upper.x < leftFrustumPoints[i].x) - frustumBBox.upper.x = leftFrustumPoints[i].x; - if(frustumBBox.upper.y < leftFrustumPoints[i].y) - frustumBBox.upper.y = leftFrustumPoints[i].y; - if(frustumBBox.upper.z < leftFrustumPoints[i].z) - frustumBBox.upper.z = leftFrustumPoints[i].z; - } - - if(useStereo) { - - for(i = 0; i< rightFrustumPoints.length; i++) { - if(frustumBBox.lower.x > rightFrustumPoints[i].x) - frustumBBox.lower.x = rightFrustumPoints[i].x; - if(frustumBBox.lower.y > rightFrustumPoints[i].y) - frustumBBox.lower.y = rightFrustumPoints[i].y; - if(frustumBBox.lower.z > rightFrustumPoints[i].z) - frustumBBox.lower.z = rightFrustumPoints[i].z; - - if(frustumBBox.upper.x < rightFrustumPoints[i].x) - frustumBBox.upper.x = rightFrustumPoints[i].x; - if(frustumBBox.upper.y < rightFrustumPoints[i].y) - frustumBBox.upper.y = rightFrustumPoints[i].y; - if(frustumBBox.upper.z < rightFrustumPoints[i].z) - frustumBBox.upper.z = rightFrustumPoints[i].z; - } - - } - } - - - void copyComputedCanvasViewCache(CanvasViewCache cvc, boolean doInfinite) { - // For performance reason, only data needed by renderer are copied. - // useStereo, - // canvasWidth, - // canvasHeight, - // leftProjection, - // rightProjection, - // leftVpcToEc, - // rightVpcToEc, - // leftFrustumPlanes, - // rightFrustumPlanes, - // vpcToVworld, - // vworldToVpc. - - cvc.useStereo = useStereo; - cvc.canvasWidth = canvasWidth; - cvc.canvasHeight = canvasHeight; - cvc.leftProjection.set(leftProjection); - cvc.rightProjection.set(rightProjection); - cvc.leftVpcToEc.set(leftVpcToEc) ; - cvc.rightVpcToEc.set(rightVpcToEc) ; - - cvc.vpcToVworld = vpcToVworld; - cvc.vworldToVpc.set(vworldToVpc); - - if (doInfinite) { - cvc.infLeftProjection.set(infLeftProjection); - cvc.infRightProjection.set(infRightProjection); - cvc.infLeftVpcToEc.set(infLeftVpcToEc) ; - cvc.infRightVpcToEc.set(infRightVpcToEc) ; - cvc.infVworldToVpc.set(infVworldToVpc); - } - - for (int i = 0; i < leftFrustumPlanes.length; i++) { - cvc.leftFrustumPlanes[i].x = leftFrustumPlanes[i].x; - cvc.leftFrustumPlanes[i].y = leftFrustumPlanes[i].y; - cvc.leftFrustumPlanes[i].z = leftFrustumPlanes[i].z; - cvc.leftFrustumPlanes[i].w = leftFrustumPlanes[i].w; - - cvc.rightFrustumPlanes[i].x = rightFrustumPlanes[i].x; - cvc.rightFrustumPlanes[i].y = rightFrustumPlanes[i].y; - cvc.rightFrustumPlanes[i].z = rightFrustumPlanes[i].z; - cvc.rightFrustumPlanes[i].w = rightFrustumPlanes[i].w; - } - } - - - /** - * Take snapshot of all per-canvas API parameters and input values. - * NOTE: This is probably not needed, but we'll do it for symmetry - * with the ScreenViewCache and ViewCache objects. - */ - synchronized void snapshot(boolean computeFrustum) { - // Issue 109 : determine the the correct index to use -- either the - // Renderer or RenderBin - int dirtyIndex = computeFrustum ? - Canvas3D.RENDER_BIN_DIRTY_IDX : Canvas3D.RENDERER_DIRTY_IDX; - - synchronized (canvas.dirtyMaskLock) { - // Issue 109 : read/clear the dirty bits for the correct index - cvcDirtyMask = canvas.cvDirtyMask[dirtyIndex]; - canvas.cvDirtyMask[dirtyIndex] = 0; - } - - useStereo = canvas.useStereo; - monoscopicViewPolicy = canvas.monoscopicViewPolicy; - leftManualEyeInImagePlate.set(canvas.leftManualEyeInImagePlate); - rightManualEyeInImagePlate.set(canvas.rightManualEyeInImagePlate); - - if(( cvcDirtyMask & Canvas3D.MOVED_OR_RESIZED_DIRTY) != 0) { - getCanvasPositionAndSize(); - } - - renderBin = canvas.view.renderBin; - - } - - /** - * Compute derived data using the snapshot of the per-canvas, - * per-screen and per-view data. - */ - synchronized void computeDerivedData(boolean currentFlag, - CanvasViewCache cvc, BoundingBox frustumBBox, boolean doInfinite) { - - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1)) { - synchronized(debugLock) { - System.err.println("------------------------------"); - doComputeDerivedData(currentFlag,cvc,frustumBBox,doInfinite); - } - } - else { - doComputeDerivedData(currentFlag,cvc,frustumBBox,doInfinite); - } - } - - /** - * Compute derived data using the snapshot of the per-canvas, - * per-screen and per-view data. Caller must synchronize before - * calling this method. - */ - private void doComputeDerivedData(boolean currentFlag, - CanvasViewCache cvc, BoundingBox frustumBBox, boolean doInfinite) { - - // Issue 109 : determine the the correct index to use -- either the - // Renderer or RenderBin - int dirtyIndex = (frustumBBox != null) ? - Canvas3D.RENDER_BIN_DIRTY_IDX : Canvas3D.RENDERER_DIRTY_IDX; - int scrvcDirtyMask; - - // Issue 109 : read/clear the dirty bits for the correct index - synchronized (screenViewCache) { - scrvcDirtyMask = screenViewCache.scrvcDirtyMask[dirtyIndex]; - // reset screen view dirty mask if canvas is offScreen. Note: - // there is only one canvas per offscreen, so it is ok to - // do the reset here. - if (canvas.offScreen) { - screenViewCache.scrvcDirtyMask[dirtyIndex] = 0; - } - } - - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { - if(cvcDirtyMask != 0) - System.err.println("cvcDirtyMask : " + cvcDirtyMask); - - if(scrvcDirtyMask != 0) - System.err.println("scrvcDirtyMask : "+ scrvcDirtyMask); - - if(viewCache.vcDirtyMask != 0) - System.err.println("vcDirtyMask : " + viewCache.vcDirtyMask); - } - - - // NOTE: This fix is only fixing the symptoms, but not the - // root of the bug. We shouldn't have to check for null here. - if(viewCache.vpRetained == null) { - System.err.println("CanvasViewCache : Error! viewCache.vpRetained is null"); - return; - } - - // This flag is use to force a computation when a ViewPlatformTransform - // is detected. No sync. needed. We're doing a read of t/f. - // XXXX: Peeking at the dirty flag is a hack. Need to revisit this. - boolean vprNotDirty = (viewCache.vpRetained.vprDirtyMask == 0); - - // Issue 131: If not manual, it has to be considered as an onscreen canvas. - if(!canvas.manualRendering && - (vprNotDirty) && - (cvcDirtyMask == 0) && - (scrvcDirtyMask == 0) && - (viewCache.vcDirtyMask == 0) && - !(updateLastTime && (doInfinite != lastDoInfinite))) { - if(frustumBBox != null) - computefrustumBBox(frustumBBox); - - // Copy the computed data into cvc. - if(cvc != null) { - copyComputedCanvasViewCache(cvc, doInfinite); - } - lastDoInfinite = doInfinite; - updateLastTime = false; - return; - } - - lastDoInfinite = doInfinite; - updateLastTime = true; - - if(currentFlag) { - vpcToVworld.set(viewCache.vpRetained.getCurrentLocalToVworld(null)); - } - else { - vpcToVworld.set(viewCache.vpRetained.getLastLocalToVworld(null)); - } - - // System.err.println("vpcToVworld is \n" + vpcToVworld); - - try { - vworldToVpc.invert(vpcToVworld); - } - catch (SingularMatrixException e) { - vworldToVpc.setIdentity(); - //System.err.println("SingularMatrixException encountered when doing vworldToVpc invert"); - } - if (doInfinite) { - vworldToVpc.getRotation(infVworldToVpc); - } - - // Compute global flags - if (monoscopicViewPolicy == View.CYCLOPEAN_EYE_VIEW) - effectiveMonoscopicViewPolicy = viewCache.monoscopicViewPolicy; - else - effectiveMonoscopicViewPolicy = monoscopicViewPolicy; - - // Recompute info about current canvas window - computeCanvasInfo(); - - // Compute coexistence center (in plate coordinates) - computeCoexistenceCenter(); - - // Get Eye position in image-plate coordinates - cacheEyePosition(); - - // Compute VPC to COE and COE to PLATE transforms - computeVpcToCoexistence(); - computeCoexistenceToPlate(); - - // Compute view and projection matrices - computeView(doInfinite); - - - computePlateToVworld(); - - if (!currentFlag) { - // save the result for use in RasterRetained computeWinCoord - lastVworldToLeftPlate.set(vworldToLeftPlate); - } - computeHeadToVworld(); - - if (frustumBBox != null) - computefrustumBBox(frustumBBox); - - // Issue 109: cvc should *always* be null - assert cvc == null; - if(cvc != null) - copyComputedCanvasViewCache(cvc, doInfinite); - - canvas.canvasDirty |= Canvas3D.VIEW_MATRIX_DIRTY; - - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1)) { - // Print some data : - System.err.println("useStereo = " + useStereo); - System.err.println("leftProjection:\n" + leftProjection); - System.err.println("rightProjection:\n " + rightProjection); - System.err.println("leftVpcToEc:\n" + leftVpcToEc); - System.err.println("rightVpcToEc:\n" + rightVpcToEc); - System.err.println("vpcToVworld:\n" + vpcToVworld); - System.err.println("vworldToVpc:\n" + vworldToVpc); - - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { - int i; - for (i = 0; i < leftFrustumPlanes.length; i++) { - System.err.println("leftFrustumPlanes " + i + " is " + - leftFrustumPlanes[i]); - } - - for (i = 0; i < rightFrustumPlanes.length; i++) { - System.err.println("rightFrustumPlanes " + i + " is " + - rightFrustumPlanes[i]); - } - } - } - - } - - private void computeCanvasInfo() { - // Copy the screen width and height info into derived parameters - physicalScreenWidth = screenViewCache.physicalScreenWidth; - physicalScreenHeight = screenViewCache.physicalScreenHeight; - - screenWidth = screenViewCache.screenWidth; - screenHeight = screenViewCache.screenHeight; - - metersPerPixelX = screenViewCache.metersPerPixelX; - metersPerPixelY = screenViewCache.metersPerPixelY; - - // If a multi-screen virtual device (e.g. Xinerama) is being used, - // then awtCanvasX and awtCanvasY are relative to the origin of that - // virtual screen. Subtract the origin of the physical screen to - // compute the origin in physical (image plate) coordinates. - Rectangle screenBounds = canvas.graphicsConfiguration.getBounds(); - canvasX = awtCanvasX - screenBounds.x; - canvasY = awtCanvasY - screenBounds.y; - - // Use awtCanvasWidth and awtCanvasHeight as reported. - canvasWidth = awtCanvasWidth; - canvasHeight = awtCanvasHeight; - - // Convert the window system ``pixel'' coordinate location and size - // of the window into physical units (meters) and coordinate system. - - // Window width and Height in meters - physicalWindowWidth = canvasWidth * metersPerPixelX; - physicalWindowHeight = canvasHeight * metersPerPixelY; - - // Compute the 4 corners of the window in physical units - physicalWindowXLeft = metersPerPixelX * - (double) canvasX; - physicalWindowYBottom = metersPerPixelY * - (double)(screenHeight - canvasHeight - canvasY); - - physicalWindowXRight = physicalWindowXLeft + physicalWindowWidth; - physicalWindowYTop = physicalWindowYBottom + physicalWindowHeight; - - // Cache the physical location of the center of the window - physicalWindowCenter.x = - physicalWindowXLeft + physicalWindowWidth / 2.0; - physicalWindowCenter.y = - physicalWindowYBottom + physicalWindowHeight / 2.0; - physicalWindowCenter.z = 0.0; - - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { - System.err.println("Canvas pos = (" + awtCanvasX + ", " + - awtCanvasY + "), size = " + awtCanvasWidth + - "x" + awtCanvasHeight); - - System.err.println("Window LL corner (in plate coordinates): " + - "(" + physicalWindowXLeft + "," + physicalWindowYBottom + ")"); - - System.err.println("Window size (in plate coordinates): " + - "(" + physicalWindowWidth + "," + physicalWindowHeight + ")"); - - System.err.println("Window center (in plate coordinates): " + - physicalWindowCenter); - - System.err.println(); - } - - // Compute the view platform scale. This combines - // the screen scale and the window scale. - computeViewPlatformScale(); - - if (!viewCache.compatibilityModeEnable && - viewCache.viewPolicy == View.HMD_VIEW) { - if (!useStereo) { - switch(effectiveMonoscopicViewPolicy) { - case View.CYCLOPEAN_EYE_VIEW: - if(J3dDebug.devPhase) { - System.err.println("CanvasViewCache : Should never reach here.\n" + - "HMD_VIEW with CYCLOPEAN_EYE_VIEW is not allowed"); - } - break; - - case View.LEFT_EYE_VIEW: - headTrackerToLeftImagePlate.set(screenViewCache. - headTrackerToLeftImagePlate); - break; - - case View.RIGHT_EYE_VIEW: - headTrackerToLeftImagePlate.set(screenViewCache. - headTrackerToRightImagePlate); - break; - } - } - else { - headTrackerToLeftImagePlate.set(screenViewCache. - headTrackerToLeftImagePlate); - - headTrackerToRightImagePlate.set(screenViewCache. - headTrackerToRightImagePlate); - } - - } - } - - // Routine to compute the center of coexistence coordinates in - // imageplate coordinates. Also compute the scale from Vpc - private void computeViewPlatformScale() { - windowScale = screenScale = 1.0; - - if (!viewCache.compatibilityModeEnable) { - switch (viewCache.screenScalePolicy) { - case View.SCALE_SCREEN_SIZE: - screenScale = physicalScreenWidth / 2.0; - break; - case View.SCALE_EXPLICIT: - screenScale = viewCache.screenScale; - break; - } - - if (viewCache.windowResizePolicy == View.PHYSICAL_WORLD) { - windowScale = physicalWindowWidth / physicalScreenWidth; - } - } - - viewPlatformScale = windowScale * screenScale; - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { - System.err.println("viewCache.windowResizePolicy = " + - viewCache.windowResizePolicy); - System.err.println("physicalWindowWidth = " + physicalWindowWidth); - System.err.println("physicalScreenWidth = " + physicalScreenWidth); - System.err.println("windowScale = " + windowScale); - System.err.println("screenScale = " + screenScale); - System.err.println("viewPlatformScale = " + viewPlatformScale); - } - } - - private void cacheEyePosFixedField() { - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1)) - System.err.println("cacheEyePosFixedField:"); - - // y is always the window center - rightEyeInImagePlate.y = - leftEyeInImagePlate.y = - physicalWindowCenter.y; - - if (!useStereo) { - switch(effectiveMonoscopicViewPolicy) { - case View.CYCLOPEAN_EYE_VIEW: - leftEyeInImagePlate.x = physicalWindowCenter.x; - break; - - case View.LEFT_EYE_VIEW: - leftEyeInImagePlate.x = - physicalWindowCenter.x + viewCache.leftEyePosInHead.x; - break; - - case View.RIGHT_EYE_VIEW: - leftEyeInImagePlate.x = - physicalWindowCenter.x + viewCache.rightEyePosInHead.x; - break; - } - - // Set right as well just in case - rightEyeInImagePlate.x = leftEyeInImagePlate.x; - } - else { - leftEyeInImagePlate.x = - physicalWindowCenter.x + viewCache.leftEyePosInHead.x; - - rightEyeInImagePlate.x = - physicalWindowCenter.x + viewCache.rightEyePosInHead.x; - } - - // - // Derive the z distance by constraining the field of view of the - // window width to be constant. - // - rightEyeInImagePlate.z = - leftEyeInImagePlate.z = - physicalWindowWidth / - (2.0 * Math.tan(viewCache.fieldOfView / 2.0)); - - // Denote that eyes-in-ImagePlate fields have changed so that - // these new values can be sent to the AudioDevice - if (this.viewCache.view.soundScheduler != null) - this.viewCache.view.soundScheduler.setListenerFlag( - SoundScheduler.EYE_POSITIONS_CHANGED); - } - - /** - * Case of view eye position contrainted to center of window, but - * with z distance from plate eye pos. - */ - private void cacheEyePosWindowRelative() { - - if ((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1)) - System.err.println("cacheEyePosWindowRelative:"); - - // y is always the window center - rightEyeInImagePlate.y = - leftEyeInImagePlate.y = - physicalWindowCenter.y; - - // z is always from the existing eye pos - rightEyeInImagePlate.z = - leftEyeInImagePlate.z = - leftManualEyeInImagePlate.z; - - if (!useStereo) { - - switch(effectiveMonoscopicViewPolicy) { - - case View.CYCLOPEAN_EYE_VIEW: - leftEyeInImagePlate.x = - physicalWindowCenter.x; - break; - - case View.LEFT_EYE_VIEW: - leftEyeInImagePlate.x = - physicalWindowCenter.x + - viewCache.leftEyePosInHead.x; - break; - - case View.RIGHT_EYE_VIEW: - leftEyeInImagePlate.x = - physicalWindowCenter.x + - viewCache.rightEyePosInHead.x; - break; - - } - - // Set right as well just in case - rightEyeInImagePlate.x = - leftEyeInImagePlate.x; - - } - else { - - leftEyeInImagePlate.x = - physicalWindowCenter.x + - viewCache.leftEyePosInHead.x; - - rightEyeInImagePlate.x = - physicalWindowCenter.x + - viewCache.rightEyePosInHead.x; - - // Right z gets its own value - rightEyeInImagePlate.z = - rightManualEyeInImagePlate.z; - } - - // Denote that eyes-in-ImagePlate fields have changed so that - // these new values can be sent to the AudioDevice - if (this.viewCache.view.soundScheduler != null) - this.viewCache.view.soundScheduler.setListenerFlag( - SoundScheduler.EYE_POSITIONS_CHANGED); - } - - /** - * Common routine used when head tracking and when using manual - * relative_to_screen eyepoint policy. - */ - private void cacheEyePosScreenRelative(Point3d leftEye, Point3d rightEye) { - if ((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1)) - System.err.println("cacheEyePosScreenRelative:"); - - if (!useStereo) { - switch(effectiveMonoscopicViewPolicy) { - - case View.CYCLOPEAN_EYE_VIEW: - leftEyeInImagePlate.x = (leftEye.x + rightEye.x) / 2.0; - leftEyeInImagePlate.y = (leftEye.y + rightEye.y) / 2.0; - leftEyeInImagePlate.z = (leftEye.z + rightEye.z) / 2.0; - break; - - case View.LEFT_EYE_VIEW: - leftEyeInImagePlate.set(leftEye); - break; - - case View.RIGHT_EYE_VIEW: - leftEyeInImagePlate.set(rightEye); - break; - - } - - // Set right as well just in case - rightEyeInImagePlate.set(leftEyeInImagePlate); - } - else { - leftEyeInImagePlate.set(leftEye); - rightEyeInImagePlate.set(rightEye); - } - - // Denote that eyes-in-ImagePlate fields have changed so that - // these new values can be sent to the AudioDevice - if (this.viewCache.view.soundScheduler != null) - this.viewCache.view.soundScheduler.setListenerFlag( - SoundScheduler.EYE_POSITIONS_CHANGED); - } - - private void cacheEyePosCoexistenceRelative(Point3d leftManualEyeInCoexistence, - Point3d rightManualEyeInCoexistence) { - - tPnt1.set(leftManualEyeInCoexistence); - viewCache.coexistenceToTrackerBase.transform(tPnt1); - screenViewCache.trackerBaseToImagePlate.transform(tPnt1); - tPnt1.add(coexistenceCenter); - - tPnt2.set(rightManualEyeInCoexistence); - viewCache.coexistenceToTrackerBase.transform(tPnt2); - screenViewCache.trackerBaseToImagePlate.transform(tPnt2); - tPnt2.add(coexistenceCenter); - - cacheEyePosScreenRelative(tPnt1, tPnt2); - - } - - /** - * Compute the head-tracked eye position for the right and - * left eyes. - */ - private void computeTrackedEyePosition() { - if ((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { - System.err.println("computeTrackedEyePosition:"); - System.err.println("viewCache.headTrackerToTrackerBase:"); - System.err.println(viewCache.headTrackerToTrackerBase); - - System.err.println("viewCache.headToHeadTracker:"); - System.err.println(viewCache.headToHeadTracker); - } - - if (viewCache.viewPolicy != View.HMD_VIEW) { - if ((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { - System.err.println("screenViewCache.trackerBaseToImagePlate:"); - System.err.println(screenViewCache.trackerBaseToImagePlate); - } - - headToLeftImagePlate.set(coexistenceCenter); - headToLeftImagePlate.mul(screenViewCache.trackerBaseToImagePlate); - headToLeftImagePlate.mul(viewCache.headTrackerToTrackerBase); - headToLeftImagePlate.mul(viewCache.headToHeadTracker); - - headToLeftImagePlate.transform(viewCache.leftEyePosInHead, - leftTrackedEyeInImagePlate); - - headToLeftImagePlate.transform(viewCache.rightEyePosInHead, - rightTrackedEyeInImagePlate); - } - else { - if ((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { - System.err.println("headTrackerToLeftImagePlate:"); - System.err.println(headTrackerToLeftImagePlate); - } - - headToLeftImagePlate.mul(headTrackerToLeftImagePlate, - viewCache.headToHeadTracker); - - headToLeftImagePlate.transform(viewCache.leftEyePosInHead, - leftTrackedEyeInImagePlate); - - if(useStereo) { - headToRightImagePlate.mul(headTrackerToRightImagePlate, - viewCache.headToHeadTracker); - - headToRightImagePlate.transform(viewCache.rightEyePosInHead, - rightTrackedEyeInImagePlate); - } - else { // HMD_VIEW with no stereo. - headToLeftImagePlate.transform(viewCache.rightEyePosInHead, - rightTrackedEyeInImagePlate); - } - - } - - if ((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { - System.err.println("headToLeftImagePlate:"); - System.err.println(headToLeftImagePlate); - System.err.println("headToRightImagePlate:"); - System.err.println(headToRightImagePlate); - - } - } - - /** - * Routine to cache the current eye position in image plate - * coordinates. - */ - private void cacheEyePosition() { - if (viewCache.compatibilityModeEnable) { - // XXXX: Compute compatibility mode eye position in ImagePlate??? - cacheEyePosScreenRelative(leftManualEyeInImagePlate, - rightManualEyeInImagePlate); - } - else if (viewCache.getDoHeadTracking()) { - computeTrackedEyePosition(); - cacheEyePosScreenRelative(leftTrackedEyeInImagePlate, - rightTrackedEyeInImagePlate); - } - else { - switch (viewCache.windowEyepointPolicy) { - - case View.RELATIVE_TO_FIELD_OF_VIEW: - cacheEyePosFixedField(); - break; - - case View.RELATIVE_TO_WINDOW: - cacheEyePosWindowRelative(); - break; - - case View.RELATIVE_TO_SCREEN: - cacheEyePosScreenRelative(leftManualEyeInImagePlate, - rightManualEyeInImagePlate); - break; - - case View.RELATIVE_TO_COEXISTENCE: - cacheEyePosCoexistenceRelative(viewCache.leftManualEyeInCoexistence, - viewCache.rightManualEyeInCoexistence); - break; - } - } - - // Compute center eye - centerEyeInImagePlate.add(leftEyeInImagePlate, rightEyeInImagePlate); - centerEyeInImagePlate.scale(0.5); - - // Compute derived value of nominalEyeOffsetFromNominalScreen - if (viewCache.windowEyepointPolicy == View.RELATIVE_TO_FIELD_OF_VIEW) - nominalEyeOffset = centerEyeInImagePlate.z; - else - nominalEyeOffset = viewCache.nominalEyeOffsetFromNominalScreen; - - if ((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1)) { - System.err.println("leftEyeInImagePlate = " + - leftEyeInImagePlate); - System.err.println("rightEyeInImagePlate = " + - rightEyeInImagePlate); - System.err.println("centerEyeInImagePlate = " + - centerEyeInImagePlate); - System.err.println("nominalEyeOffset = " + - nominalEyeOffset); - System.err.println(); - } - } - - private void computePlateToVworld() { - if (viewCache.compatibilityModeEnable) { - // XXXX: implement this correctly for compat mode - leftPlateToVworld.setIdentity(); - vworldToLeftPlate.setIdentity(); - } - else { - try { - leftPlateToVpc.invert(vpcToLeftPlate); - } - catch (SingularMatrixException e) { - leftPlateToVpc.setIdentity(); - /* - System.err.println("SingularMatrixException encountered when doing" + - " leftPlateToVpc invert"); - */ - } - - leftPlateToVworld.mul(vpcToVworld, leftPlateToVpc); - vworldToLeftPlate.mul(vpcToLeftPlate, vworldToVpc); - - if(useStereo) { - try { - rightPlateToVpc.invert(vpcToRightPlate); - } - catch (SingularMatrixException e) { - rightPlateToVpc.setIdentity(); - /* - System.err.println("SingularMatrixException encountered when doing" + - " rightPlateToVpc invert"); - */ - } - - rightPlateToVworld.mul(vpcToVworld, rightPlateToVpc); - vworldToRightPlate.mul(vpcToRightPlate, vworldToVpc); - - } - - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { - System.err.println("vpcToVworld:"); - System.err.println(vpcToVworld); - System.err.println("vpcToLeftPlate:"); - System.err.println(vpcToLeftPlate); - if(useStereo) { - System.err.println("vpcToRightPlate:"); - System.err.println(vpcToRightPlate); - - } - - } - } - - // Denote that eyes-in-ImagePlate fields have changed so that - // these new values can be sent to the AudioDevice - if (this.viewCache.view.soundScheduler != null) - this.viewCache.view.soundScheduler.setListenerFlag( - SoundScheduler.IMAGE_PLATE_TO_VWORLD_CHANGED); - } - - - private void computeHeadToVworld() { - // Concatenate headToLeftImagePlate with leftPlateToVworld - - if (viewCache.compatibilityModeEnable) { - // XXXX: implement this correctly for compat mode - headToVworld.setIdentity(); - } - else { - headToVworld.mul(leftPlateToVworld, headToLeftImagePlate); - - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { - System.err.println("leftPlateToVworld:"); - System.err.println(leftPlateToVworld); - System.err.println("headToLeftImagePlate:"); - System.err.println(headToLeftImagePlate); - System.err.println("...gives -> headToVworld:"); - System.err.println(headToVworld); - } - } - - // Denote that eyes-in-ImagePlate fields have changed so that - // these new values can be sent to the AudioDevice - if (this.viewCache.view.soundScheduler != null) - this.viewCache.view.soundScheduler.setListenerFlag( - SoundScheduler.HEAD_TO_VWORLD_CHANGED); - } - - private void computeVpcToCoexistence() { - // Create a transform with the view platform to coexistence scale - tMat1.set(viewPlatformScale); - - // XXXX: Is this really correct to ignore HMD? - - if (viewCache.viewPolicy != View.HMD_VIEW) { - switch (viewCache.coexistenceCenterInPworldPolicy) { - case View.NOMINAL_SCREEN : - switch (viewCache.viewAttachPolicy) { - case View.NOMINAL_SCREEN: - tMat2.setIdentity(); - break; - case View.NOMINAL_HEAD: - tVec1.set(0.0, 0.0, nominalEyeOffset); - tMat2.set(tVec1); - break; - case View.NOMINAL_FEET: - tVec1.set(0.0, -viewCache.nominalEyeHeightFromGround, - nominalEyeOffset); - tMat2.set(tVec1); - break; - } - - break; - case View.NOMINAL_HEAD : - switch (viewCache.viewAttachPolicy) { - case View.NOMINAL_SCREEN: - tVec1.set(0.0, 0.0, -nominalEyeOffset); - tMat2.set(tVec1); - break; - case View.NOMINAL_HEAD: - tMat2.setIdentity(); - break; - case View.NOMINAL_FEET: - tVec1.set(0.0, -viewCache.nominalEyeHeightFromGround, - 0.0); - tMat2.set(tVec1); - break; - } - break; - case View.NOMINAL_FEET: - switch (viewCache.viewAttachPolicy) { - case View.NOMINAL_SCREEN: - tVec1.set(0.0, - viewCache.nominalEyeHeightFromGround, -nominalEyeOffset); - tMat2.set(tVec1); - break; - case View.NOMINAL_HEAD: - tVec1.set(0.0, viewCache.nominalEyeHeightFromGround, - 0.0); - tMat2.set(tVec1); - - break; - case View.NOMINAL_FEET: - tMat2.setIdentity(); - break; - } - break; - } - - vpcToCoexistence.mul(tMat2, tMat1); - } - else { - vpcToCoexistence.set(tMat1); - } - - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { - System.err.println("vpcToCoexistence:"); - System.err.println(vpcToCoexistence); - } - } - - private void computeCoexistenceCenter() { - - if ((!viewCache.compatibilityModeEnable) && - (viewCache.viewPolicy != View.HMD_VIEW) && - (viewCache.coexistenceCenteringEnable) && - (viewCache.coexistenceCenterInPworldPolicy == View.NOMINAL_SCREEN)) { - - // Compute the coexistence center in image plate coordinates - - // Image plate cordinates have their orgin in the lower - // left hand corner of the CRT visiable raster. - // The nominal coexistence center is at the *center* of - // targeted area: either the window or screen, depending - // on policy. - if (viewCache.windowMovementPolicy == View.VIRTUAL_WORLD) { - coexistenceCenter.x = physicalScreenWidth / 2.0; - coexistenceCenter.y = physicalScreenHeight / 2.0; - coexistenceCenter.z = 0.0; - } - else { // windowMovementPolicy == PHYSICAL_WORLD - coexistenceCenter.x = physicalWindowCenter.x; - coexistenceCenter.y = physicalWindowCenter.y; - coexistenceCenter.z = 0.0; - } - } - else { - coexistenceCenter.set(0.0, 0.0, 0.0); - } - - if(J3dDebug.devPhase) { - if (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1) { - System.err.println("coexistenceCenter = " + coexistenceCenter); - } - } - } - - private void computeCoexistenceToPlate() { - if (viewCache.compatibilityModeEnable) { - // XXXX: implement this correctly - coexistenceToLeftPlate.setIdentity(); - return; - } - - if (viewCache.viewPolicy != View.HMD_VIEW) { - coexistenceToLeftPlate.set(coexistenceCenter); - coexistenceToLeftPlate.mul(screenViewCache.trackerBaseToImagePlate); - coexistenceToLeftPlate.mul(viewCache.coexistenceToTrackerBase); - - if(useStereo) { - coexistenceToRightPlate.set(coexistenceToLeftPlate); - } - } - else { - coexistenceToLeftPlate.mul(headTrackerToLeftImagePlate, - viewCache.trackerBaseToHeadTracker); - coexistenceToLeftPlate.mul(viewCache.coexistenceToTrackerBase); - - if(useStereo) { - coexistenceToRightPlate.mul(headTrackerToRightImagePlate, - viewCache.trackerBaseToHeadTracker); - coexistenceToRightPlate.mul(viewCache.coexistenceToTrackerBase); - } - } - - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { - System.err.println("coexistenceToLeftPlate:"); - System.err.println(coexistenceToLeftPlate); - if(useStereo) { - System.err.println("coexistenceToRightPlate:"); - System.err.println(coexistenceToRightPlate); - - } - } - } - - /** - * Computes the viewing matrices. - * - * computeView computes the following: - * - * <ul> - * left (& right) eye viewing matrices (only left is valid for mono view) - * </ul> - * - * This call works for both fixed screen and HMD displays. - */ - private void computeView(boolean doInfinite) { - int backClipPolicy; - double Fl, Fr, B, scale, backClipDistance; - - // compute scale used for transforming clip and fog distances - vworldToCoexistenceScale = vworldToVpc.getDistanceScale() - * vpcToCoexistence.getDistanceScale(); - if(doInfinite) { - infVworldToCoexistenceScale = infVworldToVpc.getDistanceScale() - * vpcToCoexistence.getDistanceScale(); - } - - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { - System.err.println("vworldToCoexistenceScale = " + - vworldToCoexistenceScale); - } - - // compute coexistenceToVworld transform -- dirty bit candidate!! - tempTrans.mul(viewCache.coexistenceToTrackerBase, vpcToCoexistence); - vworldToTrackerBase.mul(tempTrans, vworldToVpc); - - // If we are in compatibility mode, compute the view and - // projection matrices accordingly - if (viewCache.compatibilityModeEnable) { - leftProjection.set(viewCache.compatLeftProjection); - leftVpcToEc.set(viewCache.compatVpcToEc); - - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1)) { - System.err.println("Left projection and view matrices"); - System.err.println("ecToCc (leftProjection) :"); - System.err.println(leftProjection); - System.err.println("vpcToEc:"); - System.err.println(leftVpcToEc); - } - - computeFrustumPlanes(leftProjection, leftVpcToEc, - leftFrustumPlanes, leftFrustumPoints, - leftCcToVworld); - - if(useStereo) { - rightProjection.set(viewCache.compatRightProjection); - rightVpcToEc.set(viewCache.compatVpcToEc); - - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1)) { - System.err.println("Right projection and view matrices"); - System.err.println("ecToCc:"); - System.err.println("vpcToEc:"); - System.err.println(rightVpcToEc); - } - - computeFrustumPlanes(rightProjection, rightVpcToEc, - rightFrustumPlanes, rightFrustumPoints, - rightCcToVworld); - } - - return; - } - - // - // The clipping plane distances are set from the internal policy. - // - // Note that the plane distance follows the standard Z axis - // convention, e.g. negative numbers further away. - // Note that for policy from eye, the distance is negative in - // the direction of z in front of the eye. - // Note that for policy from screen, the distance is negative for - // locations behind the screen, and positive in front. - // - // The distance attributes are measured either in physical (plate) - // units, or vworld units. - // - - // Compute scale factor for front clip plane computation - if (viewCache.frontClipPolicy == View.VIRTUAL_EYE || - viewCache.frontClipPolicy == View.VIRTUAL_SCREEN) { - scale = vworldToCoexistenceScale; - } - else { - scale = windowScale; - } - - // Set left and right front clipping plane distances. - if(viewCache.frontClipPolicy == View.PHYSICAL_EYE || - viewCache.frontClipPolicy == View.VIRTUAL_EYE) { - Fl = leftEyeInImagePlate.z + - scale * -viewCache.frontClipDistance; - Fr = rightEyeInImagePlate.z + - scale * -viewCache.frontClipDistance; - } - else { - Fl = scale * -viewCache.frontClipDistance; - Fr = scale * -viewCache.frontClipDistance; - } - - // if there is an active clip node, use it and ignore the view's - // backclip - if ((renderBin != null) && (renderBin.backClipActive)) { - backClipPolicy = View.VIRTUAL_EYE; - backClipDistance = renderBin.backClipDistanceInVworld; - } else { - backClipPolicy = viewCache.backClipPolicy; - backClipDistance = viewCache.backClipDistance; - } - - // Compute scale factor for rear clip plane computation - if (backClipPolicy == View.VIRTUAL_EYE || - backClipPolicy == View.VIRTUAL_SCREEN) { - scale = vworldToCoexistenceScale; - } - else { - scale = windowScale; - } - - // Set left and right rear clipping plane distnaces. - if(backClipPolicy == View.PHYSICAL_EYE || - backClipPolicy == View.VIRTUAL_EYE) { - // Yes, left for both left and right rear. - B = leftEyeInImagePlate.z + - scale * -backClipDistance; - } - else { - B = scale * -backClipDistance; - } - - // XXXX: Can optimize for HMD case. - if (true /*viewCache.viewPolicy != View.HMD_VIEW*/) { - - // Call buildProjView to build the projection and view matrices. - - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { - System.err.println("Left projection and view matrices"); - System.err.println("Fl " + Fl + " B " + B); - System.err.println("leftEyeInImagePlate\n" + leftEyeInImagePlate); - System.err.println("Before : leftProjection\n" + leftProjection); - System.err.println("Before leftVpcToEc\n" + leftVpcToEc); - } - - buildProjView(leftEyeInImagePlate, coexistenceToLeftPlate, - vpcToLeftPlate, Fl, B, leftProjection, leftVpcToEc, false); - - - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { - System.err.println("After : leftProjection\n" + leftProjection); - System.err.println("After leftVpcToEc\n" + leftVpcToEc); - } - - computeFrustumPlanes(leftProjection, leftVpcToEc, - leftFrustumPlanes, leftFrustumPoints, - leftCcToVworld); - - if(useStereo) { - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) - System.err.println("Right projection and view matrices"); - - buildProjView(rightEyeInImagePlate, coexistenceToRightPlate, - vpcToRightPlate, Fr, B, rightProjection, - rightVpcToEc, false); - - computeFrustumPlanes(rightProjection, rightVpcToEc, - rightFrustumPlanes, rightFrustumPoints, - rightCcToVworld); - } - - // - // Now to compute the left (& right) eye (and infinite) - // viewing matrices. - if(doInfinite) { - // Call buildProjView separately for infinite view - buildProjView(leftEyeInImagePlate, coexistenceToLeftPlate, - vpcToLeftPlate, leftEyeInImagePlate.z - 0.05, - leftEyeInImagePlate.z - 1.5, - infLeftProjection, infLeftVpcToEc, true); - - if(useStereo) { - buildProjView(rightEyeInImagePlate, coexistenceToRightPlate, - vpcToRightPlate, rightEyeInImagePlate.z - 0.05, - rightEyeInImagePlate.z - 1.5, - infRightProjection, infRightVpcToEc, true); - - } - } - } - // XXXX: The following code has never been ported -// else { -// Point3d cen_eye; -// -// // HMD case. Just concatenate the approprate matrices together. -// // Additional work just for now -// -// compute_lr_plate_to_cc( &cen_eye, Fl, B, 0, &vb, 0); -// -// if(useStereo) { -// mat_mul_dpt(&right_eye_pos_in_head, -// head_to_right_plate, &cen_eye); -// compute_lr_plate_to_cc( &cen_eye, Fr, B, -// 1, &vb, 0); -// } -// -// // Make sure that coexistence_to_plate is current. -// // (It is usually constant for fixed plates, always varies for HMDs.) -// // For HMD case, computes finial matrices that will be used. -// // -// computeCoexistenceToPlate(); -// } - - } - - /** - * Debugging routine to analyze the projection matrix. - */ - private void analyzeProjection(Transform3D p, double xMax) { - if (viewCache.projectionPolicy == View.PARALLEL_PROJECTION) - System.err.println("PARALLEL_PROJECTION ="); - else - System.err.println("PERSPECTIVE_PROJECTION ="); - - System.err.println(p); - - double projectionPlaneZ = ((p.mat[0] * xMax + p.mat[3] - p.mat[15]) / - (p.mat[14] - p.mat[2])); - - System.err.println("projection plane at z = " + projectionPlaneZ); - } - - /** - * buildProjView creates a projection and viewing matrix. - * - * Inputs: - * ep : eye point, in plate coordinates - * coe2Plate : matrix from coexistence to image plate. - * F, B : front, back clipping planes, in plate coordinates - * doInfinite : flag to indicate ``at infinity'' view desired - * - * Output: - * vpc2Plate : matric from vpc to image plate. - * ecToCc : projection matrix from Eye Coordinates (EC) - * to Clipping Coordinates (CC) - * vpcToEc : view matrix from ViewPlatform Coordinates (VPC) - * to Eye Coordinates (EC) - */ - private void buildProjView(Point3d ep, - Transform3D coe2Plate, - Transform3D vpc2Plate, - double F, - double B, - Transform3D ecToCc, - Transform3D vpcToEc, - boolean doInfinite) { - - // Lx,Ly Hx,Hy will be adjusted window boundaries - double Lx, Hx, Ly, Hy; - Lx = physicalWindowXLeft; Hx = physicalWindowXRight; - Ly = physicalWindowYBottom; Hy = physicalWindowYTop; - - ecToCc.setIdentity(); - - - // XXXX: we have no concept of glass correction in the Java 3D API - // - // Correction in apparent 3D position of window due to glass/CRT - // and spherical/cylinderical curvarure of CRT. - // This boils down to producing modified values of Lx Ly Hx Hy - // and is different for hot spot vs. window center corrections. - // - /* XXXX: - double cx, cy; - if(viewPolicy != HMD_VIEW && enable_crt_glass_correction) { - if (correction_point == CORRECTION_POINT_WINDOW_CENTER) { - correct_crt( ep, Lx, Ly, &cx, &cy); Lx = cx; Ly = cy; - correct_crt( ep, Hx, Hy, &cx, &cy); Hx = cx; Hy = cy; - } - else { // must be hot spot correction - // Not real code yet, for now just do same as above. - correct_crt( ep, Lx, Ly, &cx, &cy); Lx = cx; Ly = cy; - correct_crt( ep, Hx, Hy, &cx, &cy); Hx = cx; Hy = cy; - } - } - */ - - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { - System.err.println("ep = " + ep); - System.err.println("Lx = " + Lx + ", Hx = " + Hx); - System.err.println("Ly = " + Ly + ", Hy = " + Hy); - System.err.println("F = " + F + ", B = " + B); - } - - // Compute the proper projection equation. Note that we - // do this in two steps: first we generate ImagePlateToCc, - // then we translate this by EcToPlate, resulting in a - // projection from EctoCc. - // - // A more efficient (and more accurate) approach would be to - // modify the equations below to directly project from EcToCc. - - if (viewCache.projectionPolicy == View.PARALLEL_PROJECTION) { - double inv_dx, inv_dy, inv_dz; - inv_dx = 1.0 / (Hx - Lx); - inv_dy = 1.0 / (Hy - Ly); - inv_dz = 1.0 / (F - B); - - ecToCc.mat[0] = 2.0 * inv_dx; - ecToCc.mat[3] = -(Hx + Lx) * inv_dx; - ecToCc.mat[5] = 2.0 * inv_dy; - ecToCc.mat[7] = -(Hy + Ly) * inv_dy; - ecToCc.mat[10] = 2.0 * inv_dz; - ecToCc.mat[11] = -(F + B) * inv_dz; - } - else { - double sxy, rzb, inv_dx, inv_dy; - - inv_dx = 1.0 / (Hx - Lx); - inv_dy = 1.0 / (Hy - Ly); - rzb = 1.0/(ep.z - B); - sxy = ep.z*rzb; - - ecToCc.mat[0] = sxy*2.0*inv_dx; - ecToCc.mat[5] = sxy*2.0*inv_dy; - - ecToCc.mat[2] = rzb*(Hx+Lx - 2.0*ep.x)*inv_dx; - ecToCc.mat[6] = rzb*(Hy+Ly - 2.0*ep.y)*inv_dy; - ecToCc.mat[10] = rzb*(B+F-2*ep.z)/(B-F); - ecToCc.mat[14] = -rzb; - - ecToCc.mat[3] = sxy*(-Hx-Lx)*inv_dx; - ecToCc.mat[7] = sxy*(-Hy-Ly)*inv_dy; - ecToCc.mat[11] = rzb*(B - ep.z - B*(B+F - 2*ep.z)/(B-F)); - ecToCc.mat[15] = sxy; - } - - // Since we set the matrix elements ourselves, we need to set the - // type field. A value of 0 means a non-affine matrix. - ecToCc.setOrthoDirtyBit(); - - // EC to ImagePlate matrix is a simple translation. - tVec1.set(ep.x, ep.y, ep.z); - tMat1.set(tVec1); - ecToCc.mul(tMat1); - - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { - System.err.println("ecToCc:"); - analyzeProjection(ecToCc, Hx); - } - - if(!doInfinite) { - // View matrix is: - // [plateToEc] [coexistence_to_plate] [vpc_to_coexistence] - // where vpc_to_coexistence includes the viewPlatformScale - - // First compute ViewPlatform to Plate - vpc2Plate.mul(coe2Plate, vpcToCoexistence); - - // ImagePlate to EC matrix is a simple translation. - tVec1.set(-ep.x, -ep.y, -ep.z); - tMat1.set(tVec1); - vpcToEc.mul(tMat1, vpc2Plate); - - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { - System.err.println("vpcToEc:"); - System.err.println(vpcToEc); - } - } - else { - // Final infinite composite is: - // [coexistence_to_eye] [vpc_to_coexistence (vom)] - // (does vworld_to_coe_scale_factor get used here??? ) - // - // The method is to relocate the coexistence org centered on - // the eye rather than the window center (via coexistence_to_eye). - // Computationaly simpler simplifed equation form may exist. - - // coexistence to eye is a simple translation. -/* - tVec1.set(ep.x, ep.y, ep.z); - tMat1.set(tVec1); - vpcToEc.mul(tMat1, vpcToCoexistence); - // First compute ViewPlatform to Plate - vpcToPlate.mul(coexistenceToPlatevpcToPlate, vpcToCoexistence); -*/ - - // ImagePlate to EC matrix is a simple translation. - tVec1.set(-ep.x, -ep.y, -ep.z); - tMat1.set(tVec1); - tMat1.mul(tMat1, vpc2Plate); - tMat1.getRotation(vpcToEc); // use only rotation component of transform - - } - - } - - /** - * Compute the plane equations for the frustum in ViewPlatform - * coordinates, plus its viewing frustum points. ccToVworld will - * be cached - used by Canavs3D.getInverseVworldProjection(). - */ - private void computeFrustumPlanes(Transform3D ecToCc, - Transform3D vpcToEc, - Vector4d [] frustumPlanes, - Point4d [] frustumPoints, - Transform3D ccToVworld) { - - // Compute the inverse of the Vworld to Cc transform. This - // gives us the Cc to Vworld transform. - tMat2.mul(ecToCc, vpcToEc); - ccToVworld.mul(tMat2, vworldToVpc); - // System.err.println("ccToVworld = " + ccToVworld); - try { - ccToVworld.invert(); - } - catch (SingularMatrixException e) { - ccToVworld.setIdentity(); - // System.err.println("SingularMatrixException encountered when doing invert in computeFrustumPlanes"); - } - - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { - Transform3D t = new Transform3D(); - t.mul(ecToCc, vpcToEc); - t.mul(vworldToVpc); - System.err.println("\nvworldToCc = " + t); - System.err.println("ccToVworld = " + ccToVworld); - t.mul(ccToVworld); - System.err.println("vworldToCc * ccToVworld = " + t); - } - - // Transform the 8 corners of the viewing frustum into Vpc - frustumPoints[0].set(-1.0, -1.0, 1.0, 1.0); // lower-left-front - frustumPoints[1].set(-1.0, 1.0, 1.0, 1.0); // upper-left-front - frustumPoints[2].set( 1.0, 1.0, 1.0, 1.0); // upper-right-front - frustumPoints[3].set( 1.0, -1.0, 1.0, 1.0); // lower-right-front - frustumPoints[4].set(-1.0, -1.0, -1.0, 1.0); // lower-left-back - frustumPoints[5].set(-1.0, 1.0, -1.0, 1.0); // upper-left-back - frustumPoints[6].set( 1.0, 1.0, -1.0, 1.0); // upper-right-back - frustumPoints[7].set( 1.0, -1.0, -1.0, 1.0); // lower-right-back - - ccToVworld.get(tMatrix); - int i; - for (i = 0; i < frustumPoints.length; i++) { - tMatrix.transform(frustumPoints[i]); - double w_inv = 1.0 / frustumPoints[i].w; - frustumPoints[i].x *= w_inv; - frustumPoints[i].y *= w_inv; - frustumPoints[i].z *= w_inv; - } - - // Now compute the 6 plane equations - // left - computePlaneEq(frustumPoints[0], frustumPoints[4], - frustumPoints[5], frustumPoints[1], - frustumPlanes[0]); - - // right - computePlaneEq(frustumPoints[3], frustumPoints[2], - frustumPoints[6], frustumPoints[7], - frustumPlanes[1]); - - // top - computePlaneEq(frustumPoints[1], frustumPoints[5], - frustumPoints[6], frustumPoints[2], - frustumPlanes[2]); - - // bottom - computePlaneEq(frustumPoints[0], frustumPoints[3], - frustumPoints[7], frustumPoints[4], - frustumPlanes[3]); - - // front - computePlaneEq(frustumPoints[0], frustumPoints[1], - frustumPoints[2], frustumPoints[3], - frustumPlanes[4]); - - // back - computePlaneEq(frustumPoints[4], frustumPoints[7], - frustumPoints[6], frustumPoints[5], - frustumPlanes[5]); - - //System.err.println("left plane = " + frustumPlanes[0]); - //System.err.println("right plane = " + frustumPlanes[1]); - //System.err.println("top plane = " + frustumPlanes[2]); - //System.err.println("bottom plane = " + frustumPlanes[3]); - //System.err.println("front plane = " + frustumPlanes[4]); - //System.err.println("back plane = " + frustumPlanes[5]); - } - - private void computePlaneEq(Point4d p1, Point4d p2, Point4d p3, Point4d p4, - Vector4d planeEq) { - tVec1.x = p3.x - p1.x; - tVec1.y = p3.y - p1.y; - tVec1.z = p3.z - p1.z; - - tVec2.x = p2.x - p1.x; - tVec2.y = p2.y - p1.y; - tVec2.z = p2.z - p1.z; - - tVec3.cross(tVec2, tVec1); - tVec3.normalize(); - planeEq.x = tVec3.x; - planeEq.y = tVec3.y; - planeEq.z = tVec3.z; - planeEq.w = -(planeEq.x * p1.x + planeEq.y * p1.y + planeEq.z * p1.z); - } - - // Get methods for returning derived data values. - // Eventually, these get functions will cause some of the parameters - // to be lazily evaluated. - // - // NOTE: in the case of Transform3D, and Tuple objects, a reference - // to the actual derived data is returned. In these cases, the caller - // must ensure that the returned data is not modified. - // - // NOTE: the snapshot and computeDerivedData methods are synchronized. - // Callers of the following methods that can run asynchronously with - // the renderer must call these methods and copy the data from within - // a synchronized block on the canvas view cache object. - - int getCanvasX() { - return canvasX; - } - - int getCanvasY() { - return canvasY; - } - - int getCanvasWidth() { - return canvasWidth; - } - - int getCanvasHeight() { - return canvasHeight; - } - - double getPhysicalWindowWidth() { - return physicalWindowWidth; - } - - double getPhysicalWindowHeight() { - return physicalWindowHeight; - } - - boolean getUseStereo() { - return useStereo; - } - - Transform3D getLeftProjection() { - return leftProjection; - } - - Transform3D getRightProjection() { - return rightProjection; - } - - Transform3D getLeftVpcToEc() { - return leftVpcToEc; - } - - Transform3D getRightVpcToEc() { - return rightVpcToEc; - } - - Transform3D getLeftEcToVpc() { - return leftEcToVpc; - } - - Transform3D getRightEcToVpc() { - return rightEcToVpc; - } - - Transform3D getInfLeftProjection() { - return infLeftProjection; - } - - Transform3D getInfRightProjection() { - return infLeftProjection; - } - - Transform3D getInfLeftVpcToEc() { - return infLeftVpcToEc; - } - - Transform3D getInfRightVpcToEc() { - return infRightVpcToEc; - } - - Transform3D getInfLeftEcToVpc() { - return infLeftEcToVpc; - } - - Transform3D getInfgRightEcToVpc() { - return infRightEcToVpc; - } - - Transform3D getInfVworldToVpc() { - return infVworldToVpc; - } - - Transform3D getLeftCcToVworld() { - return leftCcToVworld; - } - - Transform3D getRightCcToVworld() { - return rightCcToVworld; - } - - Transform3D getImagePlateToVworld() { - // XXXX: Document -- This will return the transform of left plate. - return leftPlateToVworld; - } - - - - Transform3D getLastVworldToImagePlate() { - // XXXX: Document -- This will return the transform of left plate. - return lastVworldToLeftPlate; - - } - - Transform3D getVworldToImagePlate() { - // XXXX: Document -- This will return the transform of left plate. - return vworldToLeftPlate; - } - - Transform3D getVworldToTrackerBase() { - return vworldToTrackerBase; - } - - double getVworldToCoexistenceScale() { - return vworldToCoexistenceScale; - } - - double getInfVworldToCoexistenceScale() { - return infVworldToCoexistenceScale; - } - - Point3d getLeftEyeInImagePlate() { - return leftEyeInImagePlate; - } - - Point3d getRightEyeInImagePlate() { - return rightEyeInImagePlate; - } - - Point3d getCenterEyeInImagePlate() { - return centerEyeInImagePlate; - } - - Transform3D getHeadToVworld() { - return headToVworld; - } - - Transform3D getVpcToVworld() { - return vpcToVworld; - } - - Transform3D getVworldToVpc() { - return vworldToVpc; - } - - - // Transform the specified X point in AWT window-relative coordinates - // to image plate coordinates - double getWindowXInImagePlate(double x) { - double xScreen = x + (double)canvasX; - return metersPerPixelX * xScreen; - } - - // Transform the specified Y point in AWT window-relative coordinates - // to image plate coordinates - double getWindowYInImagePlate(double y) { - double yScreen = y + (double)canvasY; - return metersPerPixelY * ((double)(screenHeight - 1) - yScreen); - } - - Vector4d[] getLeftFrustumPlanesInVworld() { - return leftFrustumPlanes; - } - - Vector4d[] getRightFrustumPlanesInVworld() { - return rightFrustumPlanes; - } - - - void getPixelLocationInImagePlate(double x, double y, double z, - Point3d imagePlatePoint) { - - double screenx = (x + canvasX)*metersPerPixelX; - double screeny = (screenHeight - 1 - canvasY - y)*metersPerPixelY; - - if ((viewCache.projectionPolicy == View.PERSPECTIVE_PROJECTION) && - (centerEyeInImagePlate.z != 0)) { - double zScale = 1.0 - z/centerEyeInImagePlate.z; - imagePlatePoint.x = (screenx - centerEyeInImagePlate.x)*zScale - + centerEyeInImagePlate.x; - imagePlatePoint.y = (screeny - centerEyeInImagePlate.y)*zScale - + centerEyeInImagePlate.y; - } else { - imagePlatePoint.x = screenx; - imagePlatePoint.y = screeny; - } - imagePlatePoint.z = z; - } - - /** - * Projects the specified point from image plate coordinates - * into AWT pixel coordinates. - */ - void getPixelLocationFromImagePlate(Point3d imagePlatePoint, - Point2d pixelLocation) { - - double screenX, screenY; - - if(viewCache.projectionPolicy == View.PERSPECTIVE_PROJECTION) { - // get the vector from centerEyeInImagePlate to imagePlatePoint - tVec1.sub(imagePlatePoint, centerEyeInImagePlate); - - // 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 -tVec1.z (image->eye is in -z dir) - //System.err.println("eye dist = " + (centerEyeInImagePlate.z)); - //System.err.println("image dist = " + (-tVec1.z)); - if (tVec1.z != 0) { - double zScale = centerEyeInImagePlate.z / (-tVec1.z); - screenX = centerEyeInImagePlate.x + tVec1.x * zScale; - screenY = centerEyeInImagePlate.y + tVec1.y * zScale; - - } else { - screenX = imagePlatePoint.x; - screenY = imagePlatePoint.y; - } - - } else { - screenX = imagePlatePoint.x; - screenY = imagePlatePoint.y; - } - - //System.err.println("screenX = " + screenX + " screenY = " + screenY); - // Note: screenPt is in image plate coords, at z=0 - - // Transform from image plate coords to screen coords - pixelLocation.x = (screenX / screenViewCache.metersPerPixelX) - canvasX; - pixelLocation.y = screenViewCache.screenHeight - 1 - - (screenY / screenViewCache.metersPerPixelY) - canvasY; - //System.err.println("pixelLocation = " + pixelLocation); - } - - /** - * Constructs and initializes a CanvasViewCache object. - * Note that the canvas, screen, screenCache, view, and - * viewCache parameters are all fixed at construction time - * and must be non-null. - */ - CanvasViewCache(Canvas3D canvas, - ScreenViewCache screenViewCache, - ViewCache viewCache) { - - this.canvas = canvas; - this.screenViewCache = screenViewCache; - this.viewCache = viewCache; - - // Set up the initial plane equations - int i; - for (i = 0; i < leftFrustumPlanes.length; i++) { - leftFrustumPlanes[i] = new Vector4d(); - rightFrustumPlanes[i] = new Vector4d(); - } - - for (i = 0; i < leftFrustumPoints.length; i++) { - leftFrustumPoints[i] = new Point4d(); - rightFrustumPoints[i] = new Point4d(); - } - - // canvas is null in Renderer copyOfCvCache - if (canvas != null) { - leftEyeInImagePlate.set(canvas.leftManualEyeInImagePlate); - rightEyeInImagePlate.set(canvas.rightManualEyeInImagePlate); - centerEyeInImagePlate.add(leftEyeInImagePlate, - rightEyeInImagePlate); - centerEyeInImagePlate.scale(0.5); - } - - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1)) - System.err.println("Constructed a CanvasViewCache"); - } - - synchronized void setCanvas(Canvas3D c) { - canvas = c; - } - - synchronized void setScreenViewCache(ScreenViewCache svc) { - screenViewCache = svc; - } - - synchronized void setViewCache(ViewCache vc) { - viewCache = vc; - } -} |