Source Code Cross Referenced for CanvasViewCache.java in  » 6.0-JDK-Modules » java-3d » javax » media » j3d » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » java 3d » javax.media.j3d 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $RCSfile: CanvasViewCache.java,v $
0003:         *
0004:         * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0006:         *
0007:         * This code is free software; you can redistribute it and/or modify it
0008:         * under the terms of the GNU General Public License version 2 only, as
0009:         * published by the Free Software Foundation.  Sun designates this
0010:         * particular file as subject to the "Classpath" exception as provided
0011:         * by Sun in the LICENSE file that accompanied this code.
0012:         *
0013:         * This code is distributed in the hope that it will be useful, but WITHOUT
0014:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0015:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0016:         * version 2 for more details (a copy is included in the LICENSE file that
0017:         * accompanied this code).
0018:         *
0019:         * You should have received a copy of the GNU General Public License version
0020:         * 2 along with this work; if not, write to the Free Software Foundation,
0021:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0022:         *
0023:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0024:         * CA 95054 USA or visit www.sun.com if you need additional information or
0025:         * have any questions.
0026:         *
0027:         * $Revision: 1.9 $
0028:         * $Date: 2008/02/28 20:17:20 $
0029:         * $State: Exp $
0030:         */
0031:
0032:        package javax.media.j3d;
0033:
0034:        import java.awt.Point;
0035:        import java.awt.Dimension;
0036:        import java.awt.Rectangle;
0037:        import java.awt.IllegalComponentStateException;
0038:        import javax.vecmath.*;
0039:
0040:        /**
0041:         * The CanvasViewCache class is used to cache all data, both API data
0042:         * and derived data, that is dependent on the Canvas3D or Screen3D.
0043:         * The final view and projection matrices are stored here.
0044:         */
0045:
0046:        class CanvasViewCache extends Object {
0047:            // Used for debugging only
0048:            private static Object debugLock = new Object();
0049:
0050:            // The canvas associated with this canvas view cache
0051:            private Canvas3D canvas;
0052:
0053:            // Mask that indicates this CanvasViewCache view dependence info. has changed,
0054:            // and CanvasViewCache may need to recompute the final view matries.
0055:            int cvcDirtyMask = 0;
0056:
0057:            // The screen view cache associated with this canvas view cache
0058:            private ScreenViewCache screenViewCache;
0059:
0060:            // The view cache associated with this canvas view cache
0061:            private ViewCache viewCache;
0062:
0063:            // *************
0064:            // API/INPUT DATA
0065:            // *************
0066:
0067:            // The position and size of the canvas (in pixels)
0068:            private int awtCanvasX;
0069:            private int awtCanvasY;
0070:            private int awtCanvasWidth;
0071:            private int awtCanvasHeight;
0072:
0073:            // The current RenderBin used for rendering during the frame
0074:            // associated with this snapshot.
0075:            private RenderBin renderBin;
0076:
0077:            // Flag indicating whether or not stereo will be used.  Computed by
0078:            // Canvas3D as: useStereo = stereoEnable && stereoAvailable
0079:            private boolean useStereo;
0080:
0081:            // Current monoscopic view policy from canvas
0082:            private int monoscopicViewPolicy;
0083:
0084:            // The manual positions of the left and right eyes in image-plate
0085:            // coordinates.
0086:            // Note that these values are only used in non-head-tracked mode
0087:            // when the view's window eyepoint policy is one of RELATIVE_TO_SCREEN
0088:            // or RELATIVE_TO_WINDOW.
0089:            private Point3d leftManualEyeInImagePlate = new Point3d();
0090:            private Point3d rightManualEyeInImagePlate = new Point3d();
0091:
0092:            // *************
0093:            // DERIVED DATA
0094:            // *************
0095:
0096:            // The width and height of the screen in meters (from ScreenViewCache)
0097:            double physicalScreenWidth;
0098:            double physicalScreenHeight;
0099:
0100:            // The width and height of the screen in pixels (from ScreenViewCache)
0101:            int screenWidth;
0102:            int screenHeight;
0103:
0104:            // Meters per pixel in the X and Y dimension (from ScreenViewCache)
0105:            double metersPerPixelX;
0106:            double metersPerPixelY;
0107:
0108:            // The position and size of the canvas (in pixels)
0109:            private int canvasX;
0110:            private int canvasY;
0111:            private int canvasWidth;
0112:            private int canvasHeight;
0113:
0114:            // Either the Canvas' or the View's monoscopicViewPolicy
0115:            private int effectiveMonoscopicViewPolicy;
0116:
0117:            // The current cached projection transforms.
0118:            private Transform3D leftProjection = new Transform3D();
0119:            private Transform3D rightProjection = new Transform3D();
0120:            private Transform3D infLeftProjection = new Transform3D();
0121:            private Transform3D infRightProjection = new Transform3D();
0122:
0123:            // The current cached viewing transforms.
0124:            private Transform3D leftVpcToEc = new Transform3D();
0125:            private Transform3D rightVpcToEc = new Transform3D();
0126:            private Transform3D infLeftVpcToEc = new Transform3D();
0127:            private Transform3D infRightVpcToEc = new Transform3D();
0128:
0129:            // The current cached inverse viewing transforms.
0130:            private Transform3D leftEcToVpc = new Transform3D();
0131:            private Transform3D rightEcToVpc = new Transform3D();
0132:            private Transform3D infLeftEcToVpc = new Transform3D();
0133:            private Transform3D infRightEcToVpc = new Transform3D();
0134:
0135:            // Arrays of Vector4d objects that represent the plane equations for
0136:            // the 6 planes in the viewing frustum in ViewPlatform coordinates.
0137:            private Vector4d[] leftFrustumPlanes = new Vector4d[6];
0138:            private Vector4d[] rightFrustumPlanes = new Vector4d[6];
0139:
0140:            // Arrays of Vector4d objects that represent the volume of viewing frustum
0141:            private Point4d leftFrustumPoints[] = new Point4d[8];
0142:            private Point4d rightFrustumPoints[] = new Point4d[8];
0143:
0144:            // Calibration matrix from Screen object for HMD mode using
0145:            // non-field-sequential stereo
0146:
0147:            private Transform3D headTrackerToLeftImagePlate = new Transform3D();
0148:            private Transform3D headTrackerToRightImagePlate = new Transform3D();
0149:
0150:            // Head tracked version of eye in imageplate
0151:            private Point3d leftTrackedEyeInImagePlate = new Point3d();
0152:            private Point3d rightTrackedEyeInImagePlate = new Point3d();
0153:
0154:            // Derived version of eye in image plate coordinates
0155:            private Point3d leftEyeInImagePlate = new Point3d();
0156:            private Point3d rightEyeInImagePlate = new Point3d();
0157:            private Point3d centerEyeInImagePlate = new Point3d();
0158:
0159:            // Derived version of nominalEyeOffsetFromNominalScreen
0160:            private double nominalEyeOffset;
0161:
0162:            // Physical window position,size and center (in image plate coordinates)
0163:            private double physicalWindowXLeft;
0164:            private double physicalWindowYBottom;
0165:            private double physicalWindowXRight;
0166:            private double physicalWindowYTop;
0167:            private double physicalWindowWidth;
0168:            private double physicalWindowHeight;
0169:            private Point3d physicalWindowCenter = new Point3d();
0170:
0171:            // Screen scale value from viewCache or from screen size.
0172:            private double screenScale;
0173:
0174:            // Window scale value that compensates for window size if
0175:            // the window resize policy is PHYSICAL_WORLD.
0176:            private double windowScale;
0177:
0178:            // ViewPlatform scale that takes coordinates from view platform
0179:            // coordinates and scales them to physical coordinates
0180:            private double viewPlatformScale;
0181:
0182:            // Various derived transforms
0183:
0184:            private Transform3D leftCcToVworld = new Transform3D();
0185:            private Transform3D rightCcToVworld = new Transform3D();
0186:
0187:            private Transform3D coexistenceToLeftPlate = new Transform3D();
0188:            private Transform3D coexistenceToRightPlate = new Transform3D();
0189:
0190:            private Transform3D vpcToCoexistence = new Transform3D();
0191:
0192:            private Transform3D vpcToLeftPlate = new Transform3D();
0193:            private Transform3D vpcToRightPlate = new Transform3D();
0194:            private Transform3D leftPlateToVpc = new Transform3D();
0195:            private Transform3D rightPlateToVpc = new Transform3D();
0196:            private Transform3D vworldToLeftPlate = new Transform3D();
0197:            private Transform3D lastVworldToLeftPlate = new Transform3D();
0198:            private Transform3D vworldToRightPlate = new Transform3D();
0199:            private Transform3D leftPlateToVworld = new Transform3D();
0200:            private Transform3D rightPlateToVworld = new Transform3D();
0201:            private Transform3D headToLeftImagePlate = new Transform3D();
0202:            private Transform3D headToRightImagePlate = new Transform3D();
0203:
0204:            private Transform3D vworldToTrackerBase = new Transform3D();
0205:            private Transform3D tempTrans = new Transform3D();
0206:            private Transform3D headToVworld = new Transform3D();
0207:            private Vector3d coexistenceCenter = new Vector3d();
0208:
0209:            // scale for transformimg clip and fog distances
0210:            private double vworldToCoexistenceScale;
0211:            private double infVworldToCoexistenceScale;
0212:
0213:            //
0214:            // Temporary matrices and vectors, so we dont generate garbage
0215:            //
0216:            private Transform3D tMat1 = new Transform3D();
0217:            private Transform3D tMat2 = new Transform3D();
0218:            private Vector3d tVec1 = new Vector3d();
0219:            private Vector3d tVec2 = new Vector3d();
0220:            private Vector3d tVec3 = new Vector3d();
0221:            private Point3d tPnt1 = new Point3d();
0222:            private Point3d tPnt2 = new Point3d();
0223:
0224:            private Matrix4d tMatrix = new Matrix4d();
0225:
0226:            /**
0227:             * The view platform transforms.
0228:             */
0229:            private Transform3D vworldToVpc = new Transform3D();
0230:            private Transform3D vpcToVworld = new Transform3D();
0231:            private Transform3D infVworldToVpc = new Transform3D();
0232:
0233:            // This flag is used to remember the last time doInfinite flag
0234:            // is true or not.
0235:            // If this cache is updated twice, the first time in RenderBin
0236:            // updateViewCache() and the second time in Renderer with
0237:            // geometryBackground. The first time will reset the vcDirtyMask
0238:            // to 0 so that geometry background will not get updated the
0239:            // second time doComputeDerivedData() is invoked when view change.
0240:            private boolean lastDoInfinite = false;
0241:            private boolean updateLastTime = false;
0242:
0243:            void getCanvasPositionAndSize() {
0244:                if (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2) {
0245:                    System.err.println("Get canvas position and size");
0246:                    System.err.println("Before");
0247:                    System.err.println("Canvas pos = (" + awtCanvasX + ", "
0248:                            + awtCanvasY + "), size = " + awtCanvasWidth + "x"
0249:                            + awtCanvasHeight);
0250:                    System.err.println("After");
0251:                }
0252:                awtCanvasX = canvas.newPosition.x;
0253:                awtCanvasY = canvas.newPosition.y;
0254:                awtCanvasWidth = canvas.newSize.width;
0255:                awtCanvasHeight = canvas.newSize.height;
0256:
0257:                // The following works around problem when awt creates 0-size
0258:                // window at startup
0259:                if ((awtCanvasWidth <= 0) || (awtCanvasHeight <= 0)) {
0260:                    awtCanvasWidth = 1;
0261:                    awtCanvasHeight = 1;
0262:                }
0263:
0264:                if (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1) {
0265:                    System.err.println("Canvas pos = (" + awtCanvasX + ", "
0266:                            + awtCanvasY + "), size = " + awtCanvasWidth + "x"
0267:                            + awtCanvasHeight);
0268:                }
0269:            }
0270:
0271:            void computefrustumBBox(BoundingBox frustumBBox) {
0272:                int i;
0273:
0274:                for (i = 0; i < leftFrustumPoints.length; i++) {
0275:                    if (frustumBBox.lower.x > leftFrustumPoints[i].x)
0276:                        frustumBBox.lower.x = leftFrustumPoints[i].x;
0277:                    if (frustumBBox.lower.y > leftFrustumPoints[i].y)
0278:                        frustumBBox.lower.y = leftFrustumPoints[i].y;
0279:                    if (frustumBBox.lower.z > leftFrustumPoints[i].z)
0280:                        frustumBBox.lower.z = leftFrustumPoints[i].z;
0281:
0282:                    if (frustumBBox.upper.x < leftFrustumPoints[i].x)
0283:                        frustumBBox.upper.x = leftFrustumPoints[i].x;
0284:                    if (frustumBBox.upper.y < leftFrustumPoints[i].y)
0285:                        frustumBBox.upper.y = leftFrustumPoints[i].y;
0286:                    if (frustumBBox.upper.z < leftFrustumPoints[i].z)
0287:                        frustumBBox.upper.z = leftFrustumPoints[i].z;
0288:                }
0289:
0290:                if (useStereo) {
0291:
0292:                    for (i = 0; i < rightFrustumPoints.length; i++) {
0293:                        if (frustumBBox.lower.x > rightFrustumPoints[i].x)
0294:                            frustumBBox.lower.x = rightFrustumPoints[i].x;
0295:                        if (frustumBBox.lower.y > rightFrustumPoints[i].y)
0296:                            frustumBBox.lower.y = rightFrustumPoints[i].y;
0297:                        if (frustumBBox.lower.z > rightFrustumPoints[i].z)
0298:                            frustumBBox.lower.z = rightFrustumPoints[i].z;
0299:
0300:                        if (frustumBBox.upper.x < rightFrustumPoints[i].x)
0301:                            frustumBBox.upper.x = rightFrustumPoints[i].x;
0302:                        if (frustumBBox.upper.y < rightFrustumPoints[i].y)
0303:                            frustumBBox.upper.y = rightFrustumPoints[i].y;
0304:                        if (frustumBBox.upper.z < rightFrustumPoints[i].z)
0305:                            frustumBBox.upper.z = rightFrustumPoints[i].z;
0306:                    }
0307:
0308:                }
0309:            }
0310:
0311:            void copyComputedCanvasViewCache(CanvasViewCache cvc,
0312:                    boolean doInfinite) {
0313:                // For performance reason, only data needed by renderer are copied.
0314:                // useStereo,
0315:                // canvasWidth,
0316:                // canvasHeight,
0317:                // leftProjection,
0318:                // rightProjection,
0319:                // leftVpcToEc,
0320:                // rightVpcToEc,
0321:                // leftFrustumPlanes,
0322:                // rightFrustumPlanes,
0323:                // vpcToVworld,
0324:                // vworldToVpc.
0325:
0326:                cvc.useStereo = useStereo;
0327:                cvc.canvasWidth = canvasWidth;
0328:                cvc.canvasHeight = canvasHeight;
0329:                cvc.leftProjection.set(leftProjection);
0330:                cvc.rightProjection.set(rightProjection);
0331:                cvc.leftVpcToEc.set(leftVpcToEc);
0332:                cvc.rightVpcToEc.set(rightVpcToEc);
0333:
0334:                cvc.vpcToVworld = vpcToVworld;
0335:                cvc.vworldToVpc.set(vworldToVpc);
0336:
0337:                if (doInfinite) {
0338:                    cvc.infLeftProjection.set(infLeftProjection);
0339:                    cvc.infRightProjection.set(infRightProjection);
0340:                    cvc.infLeftVpcToEc.set(infLeftVpcToEc);
0341:                    cvc.infRightVpcToEc.set(infRightVpcToEc);
0342:                    cvc.infVworldToVpc.set(infVworldToVpc);
0343:                }
0344:
0345:                for (int i = 0; i < leftFrustumPlanes.length; i++) {
0346:                    cvc.leftFrustumPlanes[i].x = leftFrustumPlanes[i].x;
0347:                    cvc.leftFrustumPlanes[i].y = leftFrustumPlanes[i].y;
0348:                    cvc.leftFrustumPlanes[i].z = leftFrustumPlanes[i].z;
0349:                    cvc.leftFrustumPlanes[i].w = leftFrustumPlanes[i].w;
0350:
0351:                    cvc.rightFrustumPlanes[i].x = rightFrustumPlanes[i].x;
0352:                    cvc.rightFrustumPlanes[i].y = rightFrustumPlanes[i].y;
0353:                    cvc.rightFrustumPlanes[i].z = rightFrustumPlanes[i].z;
0354:                    cvc.rightFrustumPlanes[i].w = rightFrustumPlanes[i].w;
0355:                }
0356:            }
0357:
0358:            /**
0359:             * Take snapshot of all per-canvas API parameters and input values.
0360:             * NOTE: This is probably not needed, but we'll do it for symmetry
0361:             * with the ScreenViewCache and ViewCache objects.
0362:             */
0363:            synchronized void snapshot(boolean computeFrustum) {
0364:                // Issue 109 : determine the the correct index to use -- either the
0365:                // Renderer or RenderBin
0366:                int dirtyIndex = computeFrustum ? Canvas3D.RENDER_BIN_DIRTY_IDX
0367:                        : Canvas3D.RENDERER_DIRTY_IDX;
0368:
0369:                synchronized (canvas.dirtyMaskLock) {
0370:                    // Issue 109 : read/clear the dirty bits for the correct index
0371:                    cvcDirtyMask = canvas.cvDirtyMask[dirtyIndex];
0372:                    canvas.cvDirtyMask[dirtyIndex] = 0;
0373:                }
0374:
0375:                useStereo = canvas.useStereo;
0376:                monoscopicViewPolicy = canvas.monoscopicViewPolicy;
0377:                leftManualEyeInImagePlate.set(canvas.leftManualEyeInImagePlate);
0378:                rightManualEyeInImagePlate
0379:                        .set(canvas.rightManualEyeInImagePlate);
0380:
0381:                if ((cvcDirtyMask & Canvas3D.MOVED_OR_RESIZED_DIRTY) != 0) {
0382:                    getCanvasPositionAndSize();
0383:                }
0384:
0385:                renderBin = canvas.view.renderBin;
0386:
0387:            }
0388:
0389:            /**
0390:             * Compute derived data using the snapshot of the per-canvas,
0391:             * per-screen and per-view data.
0392:             */
0393:            synchronized void computeDerivedData(boolean currentFlag,
0394:                    CanvasViewCache cvc, BoundingBox frustumBBox,
0395:                    boolean doInfinite) {
0396:
0397:                if ((J3dDebug.devPhase)
0398:                        && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1)) {
0399:                    synchronized (debugLock) {
0400:                        System.err.println("------------------------------");
0401:                        doComputeDerivedData(currentFlag, cvc, frustumBBox,
0402:                                doInfinite);
0403:                    }
0404:                } else {
0405:                    doComputeDerivedData(currentFlag, cvc, frustumBBox,
0406:                            doInfinite);
0407:                }
0408:            }
0409:
0410:            /**
0411:             * Compute derived data using the snapshot of the per-canvas,
0412:             * per-screen and per-view data.  Caller must synchronize before
0413:             * calling this method.
0414:             */
0415:            private void doComputeDerivedData(boolean currentFlag,
0416:                    CanvasViewCache cvc, BoundingBox frustumBBox,
0417:                    boolean doInfinite) {
0418:
0419:                // Issue 109 : determine the the correct index to use -- either the
0420:                // Renderer or RenderBin
0421:                int dirtyIndex = (frustumBBox != null) ? Canvas3D.RENDER_BIN_DIRTY_IDX
0422:                        : Canvas3D.RENDERER_DIRTY_IDX;
0423:                int scrvcDirtyMask;
0424:
0425:                // Issue 109 : read/clear the dirty bits for the correct index
0426:                synchronized (screenViewCache) {
0427:                    scrvcDirtyMask = screenViewCache.scrvcDirtyMask[dirtyIndex];
0428:                    // reset screen view dirty mask if canvas is offScreen. Note:
0429:                    // there is only one canvas per offscreen, so it is ok to
0430:                    // do the reset here.
0431:                    if (canvas.offScreen) {
0432:                        screenViewCache.scrvcDirtyMask[dirtyIndex] = 0;
0433:                    }
0434:                }
0435:
0436:                if ((J3dDebug.devPhase)
0437:                        && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) {
0438:                    if (cvcDirtyMask != 0)
0439:                        System.err.println("cvcDirtyMask : " + cvcDirtyMask);
0440:
0441:                    if (scrvcDirtyMask != 0)
0442:                        System.err
0443:                                .println("scrvcDirtyMask : " + scrvcDirtyMask);
0444:
0445:                    if (viewCache.vcDirtyMask != 0)
0446:                        System.err.println("vcDirtyMask : "
0447:                                + viewCache.vcDirtyMask);
0448:                }
0449:
0450:                // NOTE: This fix is only fixing the symptoms, but not the
0451:                // root of the bug.  We shouldn't have to check for null here.
0452:                if (viewCache.vpRetained == null) {
0453:                    System.err
0454:                            .println("CanvasViewCache : Error! viewCache.vpRetained is null");
0455:                    return;
0456:                }
0457:
0458:                // This flag is use to force a computation when a ViewPlatformTransform
0459:                // is detected. No sync. needed. We're doing a read of t/f.
0460:                // XXXX: Peeking at the dirty flag is a hack. Need to revisit this.
0461:                boolean vprNotDirty = (viewCache.vpRetained.vprDirtyMask == 0);
0462:
0463:                // Issue 131: If not manual, it has to be considered as an onscreen canvas.
0464:                if (!canvas.manualRendering && (vprNotDirty)
0465:                        && (cvcDirtyMask == 0) && (scrvcDirtyMask == 0)
0466:                        && (viewCache.vcDirtyMask == 0)
0467:                        && !(updateLastTime && (doInfinite != lastDoInfinite))) {
0468:                    if (frustumBBox != null)
0469:                        computefrustumBBox(frustumBBox);
0470:
0471:                    // Copy the computed data into cvc.
0472:                    if (cvc != null) {
0473:                        copyComputedCanvasViewCache(cvc, doInfinite);
0474:                    }
0475:                    lastDoInfinite = doInfinite;
0476:                    updateLastTime = false;
0477:                    return;
0478:                }
0479:
0480:                lastDoInfinite = doInfinite;
0481:                updateLastTime = true;
0482:
0483:                if (currentFlag) {
0484:                    vpcToVworld.set(viewCache.vpRetained
0485:                            .getCurrentLocalToVworld(null));
0486:                } else {
0487:                    vpcToVworld.set(viewCache.vpRetained
0488:                            .getLastLocalToVworld(null));
0489:                }
0490:
0491:                // System.err.println("vpcToVworld is \n" + vpcToVworld);
0492:
0493:                try {
0494:                    vworldToVpc.invert(vpcToVworld);
0495:                } catch (SingularMatrixException e) {
0496:                    vworldToVpc.setIdentity();
0497:                    //System.err.println("SingularMatrixException encountered when doing vworldToVpc invert");
0498:                }
0499:                if (doInfinite) {
0500:                    vworldToVpc.getRotation(infVworldToVpc);
0501:                }
0502:
0503:                // Compute global flags
0504:                if (monoscopicViewPolicy == View.CYCLOPEAN_EYE_VIEW)
0505:                    effectiveMonoscopicViewPolicy = viewCache.monoscopicViewPolicy;
0506:                else
0507:                    effectiveMonoscopicViewPolicy = monoscopicViewPolicy;
0508:
0509:                // Recompute info about current canvas window
0510:                computeCanvasInfo();
0511:
0512:                // Compute coexistence center (in plate coordinates)
0513:                computeCoexistenceCenter();
0514:
0515:                // Get Eye position in image-plate coordinates
0516:                cacheEyePosition();
0517:
0518:                // Compute VPC to COE and COE to PLATE transforms
0519:                computeVpcToCoexistence();
0520:                computeCoexistenceToPlate();
0521:
0522:                // Compute view and projection matrices
0523:                computeView(doInfinite);
0524:
0525:                computePlateToVworld();
0526:
0527:                if (!currentFlag) {
0528:                    // save the result for use in RasterRetained computeWinCoord
0529:                    lastVworldToLeftPlate.set(vworldToLeftPlate);
0530:                }
0531:                computeHeadToVworld();
0532:
0533:                if (frustumBBox != null)
0534:                    computefrustumBBox(frustumBBox);
0535:
0536:                // Issue 109: cvc should *always* be null
0537:                assert cvc == null;
0538:                if (cvc != null)
0539:                    copyComputedCanvasViewCache(cvc, doInfinite);
0540:
0541:                canvas.canvasDirty |= Canvas3D.VIEW_MATRIX_DIRTY;
0542:
0543:                if ((J3dDebug.devPhase)
0544:                        && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1)) {
0545:                    // Print some data :
0546:                    System.err.println("useStereo = " + useStereo);
0547:                    System.err.println("leftProjection:\n" + leftProjection);
0548:                    System.err.println("rightProjection:\n " + rightProjection);
0549:                    System.err.println("leftVpcToEc:\n" + leftVpcToEc);
0550:                    System.err.println("rightVpcToEc:\n" + rightVpcToEc);
0551:                    System.err.println("vpcToVworld:\n" + vpcToVworld);
0552:                    System.err.println("vworldToVpc:\n" + vworldToVpc);
0553:
0554:                    if ((J3dDebug.devPhase)
0555:                            && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) {
0556:                        int i;
0557:                        for (i = 0; i < leftFrustumPlanes.length; i++) {
0558:                            System.err.println("leftFrustumPlanes " + i
0559:                                    + " is " + leftFrustumPlanes[i]);
0560:                        }
0561:
0562:                        for (i = 0; i < rightFrustumPlanes.length; i++) {
0563:                            System.err.println("rightFrustumPlanes " + i
0564:                                    + " is " + rightFrustumPlanes[i]);
0565:                        }
0566:                    }
0567:                }
0568:
0569:            }
0570:
0571:            private void computeCanvasInfo() {
0572:                // Copy the screen width and height info into derived parameters
0573:                physicalScreenWidth = screenViewCache.physicalScreenWidth;
0574:                physicalScreenHeight = screenViewCache.physicalScreenHeight;
0575:
0576:                screenWidth = screenViewCache.screenWidth;
0577:                screenHeight = screenViewCache.screenHeight;
0578:
0579:                metersPerPixelX = screenViewCache.metersPerPixelX;
0580:                metersPerPixelY = screenViewCache.metersPerPixelY;
0581:
0582:                // If a multi-screen virtual device (e.g. Xinerama) is being used,
0583:                // then awtCanvasX and awtCanvasY are relative to the origin of that
0584:                // virtual screen.  Subtract the origin of the physical screen to
0585:                // compute the origin in physical (image plate) coordinates.
0586:                Rectangle screenBounds = canvas.graphicsConfiguration
0587:                        .getBounds();
0588:                canvasX = awtCanvasX - screenBounds.x;
0589:                canvasY = awtCanvasY - screenBounds.y;
0590:
0591:                // Use awtCanvasWidth and awtCanvasHeight as reported.
0592:                canvasWidth = awtCanvasWidth;
0593:                canvasHeight = awtCanvasHeight;
0594:
0595:                // Convert the window system ``pixel'' coordinate location and size
0596:                // of the window into physical units (meters) and coordinate system.
0597:
0598:                // Window width and Height in meters
0599:                physicalWindowWidth = canvasWidth * metersPerPixelX;
0600:                physicalWindowHeight = canvasHeight * metersPerPixelY;
0601:
0602:                // Compute the 4 corners of the window in physical units
0603:                physicalWindowXLeft = metersPerPixelX * (double) canvasX;
0604:                physicalWindowYBottom = metersPerPixelY
0605:                        * (double) (screenHeight - canvasHeight - canvasY);
0606:
0607:                physicalWindowXRight = physicalWindowXLeft
0608:                        + physicalWindowWidth;
0609:                physicalWindowYTop = physicalWindowYBottom
0610:                        + physicalWindowHeight;
0611:
0612:                //  Cache the physical location of the center of the window
0613:                physicalWindowCenter.x = physicalWindowXLeft
0614:                        + physicalWindowWidth / 2.0;
0615:                physicalWindowCenter.y = physicalWindowYBottom
0616:                        + physicalWindowHeight / 2.0;
0617:                physicalWindowCenter.z = 0.0;
0618:
0619:                if ((J3dDebug.devPhase)
0620:                        && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) {
0621:                    System.err.println("Canvas pos = (" + awtCanvasX + ", "
0622:                            + awtCanvasY + "), size = " + awtCanvasWidth + "x"
0623:                            + awtCanvasHeight);
0624:
0625:                    System.err
0626:                            .println("Window LL corner (in plate coordinates): "
0627:                                    + "("
0628:                                    + physicalWindowXLeft
0629:                                    + ","
0630:                                    + physicalWindowYBottom + ")");
0631:
0632:                    System.err.println("Window size (in plate coordinates): "
0633:                            + "(" + physicalWindowWidth + ","
0634:                            + physicalWindowHeight + ")");
0635:
0636:                    System.err.println("Window center (in plate coordinates): "
0637:                            + physicalWindowCenter);
0638:
0639:                    System.err.println();
0640:                }
0641:
0642:                // Compute the view platform scale.  This combines
0643:                // the screen scale and the window scale.
0644:                computeViewPlatformScale();
0645:
0646:                if (!viewCache.compatibilityModeEnable
0647:                        && viewCache.viewPolicy == View.HMD_VIEW) {
0648:                    if (!useStereo) {
0649:                        switch (effectiveMonoscopicViewPolicy) {
0650:                        case View.CYCLOPEAN_EYE_VIEW:
0651:                            if (J3dDebug.devPhase) {
0652:                                System.err
0653:                                        .println("CanvasViewCache : Should never reach here.\n"
0654:                                                + "HMD_VIEW with CYCLOPEAN_EYE_VIEW is not allowed");
0655:                            }
0656:                            break;
0657:
0658:                        case View.LEFT_EYE_VIEW:
0659:                            headTrackerToLeftImagePlate
0660:                                    .set(screenViewCache.headTrackerToLeftImagePlate);
0661:                            break;
0662:
0663:                        case View.RIGHT_EYE_VIEW:
0664:                            headTrackerToLeftImagePlate
0665:                                    .set(screenViewCache.headTrackerToRightImagePlate);
0666:                            break;
0667:                        }
0668:                    } else {
0669:                        headTrackerToLeftImagePlate
0670:                                .set(screenViewCache.headTrackerToLeftImagePlate);
0671:
0672:                        headTrackerToRightImagePlate
0673:                                .set(screenViewCache.headTrackerToRightImagePlate);
0674:                    }
0675:
0676:                }
0677:            }
0678:
0679:            // Routine to compute the center of coexistence coordinates in
0680:            // imageplate coordinates.  Also compute the scale from Vpc
0681:            private void computeViewPlatformScale() {
0682:                windowScale = screenScale = 1.0;
0683:
0684:                if (!viewCache.compatibilityModeEnable) {
0685:                    switch (viewCache.screenScalePolicy) {
0686:                    case View.SCALE_SCREEN_SIZE:
0687:                        screenScale = physicalScreenWidth / 2.0;
0688:                        break;
0689:                    case View.SCALE_EXPLICIT:
0690:                        screenScale = viewCache.screenScale;
0691:                        break;
0692:                    }
0693:
0694:                    if (viewCache.windowResizePolicy == View.PHYSICAL_WORLD) {
0695:                        windowScale = physicalWindowWidth / physicalScreenWidth;
0696:                    }
0697:                }
0698:
0699:                viewPlatformScale = windowScale * screenScale;
0700:                if ((J3dDebug.devPhase)
0701:                        && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) {
0702:                    System.err.println("viewCache.windowResizePolicy = "
0703:                            + viewCache.windowResizePolicy);
0704:                    System.err.println("physicalWindowWidth = "
0705:                            + physicalWindowWidth);
0706:                    System.err.println("physicalScreenWidth = "
0707:                            + physicalScreenWidth);
0708:                    System.err.println("windowScale = " + windowScale);
0709:                    System.err.println("screenScale = " + screenScale);
0710:                    System.err.println("viewPlatformScale = "
0711:                            + viewPlatformScale);
0712:                }
0713:            }
0714:
0715:            private void cacheEyePosFixedField() {
0716:                if ((J3dDebug.devPhase)
0717:                        && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1))
0718:                    System.err.println("cacheEyePosFixedField:");
0719:
0720:                // y is always the window center
0721:                rightEyeInImagePlate.y = leftEyeInImagePlate.y = physicalWindowCenter.y;
0722:
0723:                if (!useStereo) {
0724:                    switch (effectiveMonoscopicViewPolicy) {
0725:                    case View.CYCLOPEAN_EYE_VIEW:
0726:                        leftEyeInImagePlate.x = physicalWindowCenter.x;
0727:                        break;
0728:
0729:                    case View.LEFT_EYE_VIEW:
0730:                        leftEyeInImagePlate.x = physicalWindowCenter.x
0731:                                + viewCache.leftEyePosInHead.x;
0732:                        break;
0733:
0734:                    case View.RIGHT_EYE_VIEW:
0735:                        leftEyeInImagePlate.x = physicalWindowCenter.x
0736:                                + viewCache.rightEyePosInHead.x;
0737:                        break;
0738:                    }
0739:
0740:                    // Set right as well just in case
0741:                    rightEyeInImagePlate.x = leftEyeInImagePlate.x;
0742:                } else {
0743:                    leftEyeInImagePlate.x = physicalWindowCenter.x
0744:                            + viewCache.leftEyePosInHead.x;
0745:
0746:                    rightEyeInImagePlate.x = physicalWindowCenter.x
0747:                            + viewCache.rightEyePosInHead.x;
0748:                }
0749:
0750:                //
0751:                // Derive the z distance by constraining the field of view of the
0752:                // window width to be constant.
0753:                //
0754:                rightEyeInImagePlate.z = leftEyeInImagePlate.z = physicalWindowWidth
0755:                        / (2.0 * Math.tan(viewCache.fieldOfView / 2.0));
0756:
0757:                // Denote that eyes-in-ImagePlate fields have changed so that
0758:                // these new values can be sent to the AudioDevice
0759:                if (this .viewCache.view.soundScheduler != null)
0760:                    this .viewCache.view.soundScheduler
0761:                            .setListenerFlag(SoundScheduler.EYE_POSITIONS_CHANGED);
0762:            }
0763:
0764:            /**
0765:             *  Case of view eye position contrainted to center of window, but
0766:             *  with z distance from plate eye pos.
0767:             */
0768:            private void cacheEyePosWindowRelative() {
0769:
0770:                if ((J3dDebug.devPhase)
0771:                        && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1))
0772:                    System.err.println("cacheEyePosWindowRelative:");
0773:
0774:                // y is always the window center
0775:                rightEyeInImagePlate.y = leftEyeInImagePlate.y = physicalWindowCenter.y;
0776:
0777:                // z is always from the existing eye pos
0778:                rightEyeInImagePlate.z = leftEyeInImagePlate.z = leftManualEyeInImagePlate.z;
0779:
0780:                if (!useStereo) {
0781:
0782:                    switch (effectiveMonoscopicViewPolicy) {
0783:
0784:                    case View.CYCLOPEAN_EYE_VIEW:
0785:                        leftEyeInImagePlate.x = physicalWindowCenter.x;
0786:                        break;
0787:
0788:                    case View.LEFT_EYE_VIEW:
0789:                        leftEyeInImagePlate.x = physicalWindowCenter.x
0790:                                + viewCache.leftEyePosInHead.x;
0791:                        break;
0792:
0793:                    case View.RIGHT_EYE_VIEW:
0794:                        leftEyeInImagePlate.x = physicalWindowCenter.x
0795:                                + viewCache.rightEyePosInHead.x;
0796:                        break;
0797:
0798:                    }
0799:
0800:                    // Set right as well just in case
0801:                    rightEyeInImagePlate.x = leftEyeInImagePlate.x;
0802:
0803:                } else {
0804:
0805:                    leftEyeInImagePlate.x = physicalWindowCenter.x
0806:                            + viewCache.leftEyePosInHead.x;
0807:
0808:                    rightEyeInImagePlate.x = physicalWindowCenter.x
0809:                            + viewCache.rightEyePosInHead.x;
0810:
0811:                    // Right z gets its own value
0812:                    rightEyeInImagePlate.z = rightManualEyeInImagePlate.z;
0813:                }
0814:
0815:                // Denote that eyes-in-ImagePlate fields have changed so that
0816:                // these new values can be sent to the AudioDevice
0817:                if (this .viewCache.view.soundScheduler != null)
0818:                    this .viewCache.view.soundScheduler
0819:                            .setListenerFlag(SoundScheduler.EYE_POSITIONS_CHANGED);
0820:            }
0821:
0822:            /**
0823:             * Common routine used when head tracking and when using manual
0824:             * relative_to_screen eyepoint policy.
0825:             */
0826:            private void cacheEyePosScreenRelative(Point3d leftEye,
0827:                    Point3d rightEye) {
0828:                if ((J3dDebug.devPhase)
0829:                        && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1))
0830:                    System.err.println("cacheEyePosScreenRelative:");
0831:
0832:                if (!useStereo) {
0833:                    switch (effectiveMonoscopicViewPolicy) {
0834:
0835:                    case View.CYCLOPEAN_EYE_VIEW:
0836:                        leftEyeInImagePlate.x = (leftEye.x + rightEye.x) / 2.0;
0837:                        leftEyeInImagePlate.y = (leftEye.y + rightEye.y) / 2.0;
0838:                        leftEyeInImagePlate.z = (leftEye.z + rightEye.z) / 2.0;
0839:                        break;
0840:
0841:                    case View.LEFT_EYE_VIEW:
0842:                        leftEyeInImagePlate.set(leftEye);
0843:                        break;
0844:
0845:                    case View.RIGHT_EYE_VIEW:
0846:                        leftEyeInImagePlate.set(rightEye);
0847:                        break;
0848:
0849:                    }
0850:
0851:                    // Set right as well just in case
0852:                    rightEyeInImagePlate.set(leftEyeInImagePlate);
0853:                } else {
0854:                    leftEyeInImagePlate.set(leftEye);
0855:                    rightEyeInImagePlate.set(rightEye);
0856:                }
0857:
0858:                // Denote that eyes-in-ImagePlate fields have changed so that
0859:                // these new values can be sent to the AudioDevice
0860:                if (this .viewCache.view.soundScheduler != null)
0861:                    this .viewCache.view.soundScheduler
0862:                            .setListenerFlag(SoundScheduler.EYE_POSITIONS_CHANGED);
0863:            }
0864:
0865:            private void cacheEyePosCoexistenceRelative(
0866:                    Point3d leftManualEyeInCoexistence,
0867:                    Point3d rightManualEyeInCoexistence) {
0868:
0869:                tPnt1.set(leftManualEyeInCoexistence);
0870:                viewCache.coexistenceToTrackerBase.transform(tPnt1);
0871:                screenViewCache.trackerBaseToImagePlate.transform(tPnt1);
0872:                tPnt1.add(coexistenceCenter);
0873:
0874:                tPnt2.set(rightManualEyeInCoexistence);
0875:                viewCache.coexistenceToTrackerBase.transform(tPnt2);
0876:                screenViewCache.trackerBaseToImagePlate.transform(tPnt2);
0877:                tPnt2.add(coexistenceCenter);
0878:
0879:                cacheEyePosScreenRelative(tPnt1, tPnt2);
0880:
0881:            }
0882:
0883:            /**
0884:             * Compute the head-tracked eye position for the right and
0885:             * left eyes.
0886:             */
0887:            private void computeTrackedEyePosition() {
0888:                if ((J3dDebug.devPhase)
0889:                        && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) {
0890:                    System.err.println("computeTrackedEyePosition:");
0891:                    System.err.println("viewCache.headTrackerToTrackerBase:");
0892:                    System.err.println(viewCache.headTrackerToTrackerBase);
0893:
0894:                    System.err.println("viewCache.headToHeadTracker:");
0895:                    System.err.println(viewCache.headToHeadTracker);
0896:                }
0897:
0898:                if (viewCache.viewPolicy != View.HMD_VIEW) {
0899:                    if ((J3dDebug.devPhase)
0900:                            && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) {
0901:                        System.err
0902:                                .println("screenViewCache.trackerBaseToImagePlate:");
0903:                        System.err
0904:                                .println(screenViewCache.trackerBaseToImagePlate);
0905:                    }
0906:
0907:                    headToLeftImagePlate.set(coexistenceCenter);
0908:                    headToLeftImagePlate
0909:                            .mul(screenViewCache.trackerBaseToImagePlate);
0910:                    headToLeftImagePlate
0911:                            .mul(viewCache.headTrackerToTrackerBase);
0912:                    headToLeftImagePlate.mul(viewCache.headToHeadTracker);
0913:
0914:                    headToLeftImagePlate.transform(viewCache.leftEyePosInHead,
0915:                            leftTrackedEyeInImagePlate);
0916:
0917:                    headToLeftImagePlate.transform(viewCache.rightEyePosInHead,
0918:                            rightTrackedEyeInImagePlate);
0919:                } else {
0920:                    if ((J3dDebug.devPhase)
0921:                            && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) {
0922:                        System.err.println("headTrackerToLeftImagePlate:");
0923:                        System.err.println(headTrackerToLeftImagePlate);
0924:                    }
0925:
0926:                    headToLeftImagePlate.mul(headTrackerToLeftImagePlate,
0927:                            viewCache.headToHeadTracker);
0928:
0929:                    headToLeftImagePlate.transform(viewCache.leftEyePosInHead,
0930:                            leftTrackedEyeInImagePlate);
0931:
0932:                    if (useStereo) {
0933:                        headToRightImagePlate.mul(headTrackerToRightImagePlate,
0934:                                viewCache.headToHeadTracker);
0935:
0936:                        headToRightImagePlate.transform(
0937:                                viewCache.rightEyePosInHead,
0938:                                rightTrackedEyeInImagePlate);
0939:                    } else { // HMD_VIEW with no stereo.
0940:                        headToLeftImagePlate.transform(
0941:                                viewCache.rightEyePosInHead,
0942:                                rightTrackedEyeInImagePlate);
0943:                    }
0944:
0945:                }
0946:
0947:                if ((J3dDebug.devPhase)
0948:                        && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) {
0949:                    System.err.println("headToLeftImagePlate:");
0950:                    System.err.println(headToLeftImagePlate);
0951:                    System.err.println("headToRightImagePlate:");
0952:                    System.err.println(headToRightImagePlate);
0953:
0954:                }
0955:            }
0956:
0957:            /**
0958:             * Routine to cache the current eye position in image plate
0959:             * coordinates.
0960:             */
0961:            private void cacheEyePosition() {
0962:                if (viewCache.compatibilityModeEnable) {
0963:                    // XXXX: Compute compatibility mode eye position in ImagePlate???
0964:                    cacheEyePosScreenRelative(leftManualEyeInImagePlate,
0965:                            rightManualEyeInImagePlate);
0966:                } else if (viewCache.getDoHeadTracking()) {
0967:                    computeTrackedEyePosition();
0968:                    cacheEyePosScreenRelative(leftTrackedEyeInImagePlate,
0969:                            rightTrackedEyeInImagePlate);
0970:                } else {
0971:                    switch (viewCache.windowEyepointPolicy) {
0972:
0973:                    case View.RELATIVE_TO_FIELD_OF_VIEW:
0974:                        cacheEyePosFixedField();
0975:                        break;
0976:
0977:                    case View.RELATIVE_TO_WINDOW:
0978:                        cacheEyePosWindowRelative();
0979:                        break;
0980:
0981:                    case View.RELATIVE_TO_SCREEN:
0982:                        cacheEyePosScreenRelative(leftManualEyeInImagePlate,
0983:                                rightManualEyeInImagePlate);
0984:                        break;
0985:
0986:                    case View.RELATIVE_TO_COEXISTENCE:
0987:                        cacheEyePosCoexistenceRelative(
0988:                                viewCache.leftManualEyeInCoexistence,
0989:                                viewCache.rightManualEyeInCoexistence);
0990:                        break;
0991:                    }
0992:                }
0993:
0994:                // Compute center eye
0995:                centerEyeInImagePlate.add(leftEyeInImagePlate,
0996:                        rightEyeInImagePlate);
0997:                centerEyeInImagePlate.scale(0.5);
0998:
0999:                // Compute derived value of nominalEyeOffsetFromNominalScreen
1000:                if (viewCache.windowEyepointPolicy == View.RELATIVE_TO_FIELD_OF_VIEW)
1001:                    nominalEyeOffset = centerEyeInImagePlate.z;
1002:                else
1003:                    nominalEyeOffset = viewCache.nominalEyeOffsetFromNominalScreen;
1004:
1005:                if ((J3dDebug.devPhase)
1006:                        && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1)) {
1007:                    System.err.println("leftEyeInImagePlate = "
1008:                            + leftEyeInImagePlate);
1009:                    System.err.println("rightEyeInImagePlate = "
1010:                            + rightEyeInImagePlate);
1011:                    System.err.println("centerEyeInImagePlate = "
1012:                            + centerEyeInImagePlate);
1013:                    System.err
1014:                            .println("nominalEyeOffset = " + nominalEyeOffset);
1015:                    System.err.println();
1016:                }
1017:            }
1018:
1019:            private void computePlateToVworld() {
1020:                if (viewCache.compatibilityModeEnable) {
1021:                    // XXXX: implement this correctly for compat mode
1022:                    leftPlateToVworld.setIdentity();
1023:                    vworldToLeftPlate.setIdentity();
1024:                } else {
1025:                    try {
1026:                        leftPlateToVpc.invert(vpcToLeftPlate);
1027:                    } catch (SingularMatrixException e) {
1028:                        leftPlateToVpc.setIdentity();
1029:                        /*
1030:                          System.err.println("SingularMatrixException encountered when doing" +
1031:                          " leftPlateToVpc invert");
1032:                         */
1033:                    }
1034:
1035:                    leftPlateToVworld.mul(vpcToVworld, leftPlateToVpc);
1036:                    vworldToLeftPlate.mul(vpcToLeftPlate, vworldToVpc);
1037:
1038:                    if (useStereo) {
1039:                        try {
1040:                            rightPlateToVpc.invert(vpcToRightPlate);
1041:                        } catch (SingularMatrixException e) {
1042:                            rightPlateToVpc.setIdentity();
1043:                            /*
1044:                              System.err.println("SingularMatrixException encountered when doing" +
1045:                              " rightPlateToVpc invert");
1046:                             */
1047:                        }
1048:
1049:                        rightPlateToVworld.mul(vpcToVworld, rightPlateToVpc);
1050:                        vworldToRightPlate.mul(vpcToRightPlate, vworldToVpc);
1051:
1052:                    }
1053:
1054:                    if ((J3dDebug.devPhase)
1055:                            && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) {
1056:                        System.err.println("vpcToVworld:");
1057:                        System.err.println(vpcToVworld);
1058:                        System.err.println("vpcToLeftPlate:");
1059:                        System.err.println(vpcToLeftPlate);
1060:                        if (useStereo) {
1061:                            System.err.println("vpcToRightPlate:");
1062:                            System.err.println(vpcToRightPlate);
1063:
1064:                        }
1065:
1066:                    }
1067:                }
1068:
1069:                // Denote that eyes-in-ImagePlate fields have changed so that
1070:                // these new values can be sent to the AudioDevice
1071:                if (this .viewCache.view.soundScheduler != null)
1072:                    this .viewCache.view.soundScheduler
1073:                            .setListenerFlag(SoundScheduler.IMAGE_PLATE_TO_VWORLD_CHANGED);
1074:            }
1075:
1076:            private void computeHeadToVworld() {
1077:                // Concatenate headToLeftImagePlate with leftPlateToVworld
1078:
1079:                if (viewCache.compatibilityModeEnable) {
1080:                    // XXXX: implement this correctly for compat mode
1081:                    headToVworld.setIdentity();
1082:                } else {
1083:                    headToVworld.mul(leftPlateToVworld, headToLeftImagePlate);
1084:
1085:                    if ((J3dDebug.devPhase)
1086:                            && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) {
1087:                        System.err.println("leftPlateToVworld:");
1088:                        System.err.println(leftPlateToVworld);
1089:                        System.err.println("headToLeftImagePlate:");
1090:                        System.err.println(headToLeftImagePlate);
1091:                        System.err.println("...gives -> headToVworld:");
1092:                        System.err.println(headToVworld);
1093:                    }
1094:                }
1095:
1096:                // Denote that eyes-in-ImagePlate fields have changed so that
1097:                // these new values can be sent to the AudioDevice
1098:                if (this .viewCache.view.soundScheduler != null)
1099:                    this .viewCache.view.soundScheduler
1100:                            .setListenerFlag(SoundScheduler.HEAD_TO_VWORLD_CHANGED);
1101:            }
1102:
1103:            private void computeVpcToCoexistence() {
1104:                // Create a transform with the view platform to coexistence scale
1105:                tMat1.set(viewPlatformScale);
1106:
1107:                // XXXX: Is this really correct to ignore HMD?
1108:
1109:                if (viewCache.viewPolicy != View.HMD_VIEW) {
1110:                    switch (viewCache.coexistenceCenterInPworldPolicy) {
1111:                    case View.NOMINAL_SCREEN:
1112:                        switch (viewCache.viewAttachPolicy) {
1113:                        case View.NOMINAL_SCREEN:
1114:                            tMat2.setIdentity();
1115:                            break;
1116:                        case View.NOMINAL_HEAD:
1117:                            tVec1.set(0.0, 0.0, nominalEyeOffset);
1118:                            tMat2.set(tVec1);
1119:                            break;
1120:                        case View.NOMINAL_FEET:
1121:                            tVec1.set(0.0,
1122:                                    -viewCache.nominalEyeHeightFromGround,
1123:                                    nominalEyeOffset);
1124:                            tMat2.set(tVec1);
1125:                            break;
1126:                        }
1127:
1128:                        break;
1129:                    case View.NOMINAL_HEAD:
1130:                        switch (viewCache.viewAttachPolicy) {
1131:                        case View.NOMINAL_SCREEN:
1132:                            tVec1.set(0.0, 0.0, -nominalEyeOffset);
1133:                            tMat2.set(tVec1);
1134:                            break;
1135:                        case View.NOMINAL_HEAD:
1136:                            tMat2.setIdentity();
1137:                            break;
1138:                        case View.NOMINAL_FEET:
1139:                            tVec1.set(0.0,
1140:                                    -viewCache.nominalEyeHeightFromGround, 0.0);
1141:                            tMat2.set(tVec1);
1142:                            break;
1143:                        }
1144:                        break;
1145:                    case View.NOMINAL_FEET:
1146:                        switch (viewCache.viewAttachPolicy) {
1147:                        case View.NOMINAL_SCREEN:
1148:                            tVec1.set(0.0,
1149:                                    viewCache.nominalEyeHeightFromGround,
1150:                                    -nominalEyeOffset);
1151:                            tMat2.set(tVec1);
1152:                            break;
1153:                        case View.NOMINAL_HEAD:
1154:                            tVec1.set(0.0,
1155:                                    viewCache.nominalEyeHeightFromGround, 0.0);
1156:                            tMat2.set(tVec1);
1157:
1158:                            break;
1159:                        case View.NOMINAL_FEET:
1160:                            tMat2.setIdentity();
1161:                            break;
1162:                        }
1163:                        break;
1164:                    }
1165:
1166:                    vpcToCoexistence.mul(tMat2, tMat1);
1167:                } else {
1168:                    vpcToCoexistence.set(tMat1);
1169:                }
1170:
1171:                if ((J3dDebug.devPhase)
1172:                        && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) {
1173:                    System.err.println("vpcToCoexistence:");
1174:                    System.err.println(vpcToCoexistence);
1175:                }
1176:            }
1177:
1178:            private void computeCoexistenceCenter() {
1179:
1180:                if ((!viewCache.compatibilityModeEnable)
1181:                        && (viewCache.viewPolicy != View.HMD_VIEW)
1182:                        && (viewCache.coexistenceCenteringEnable)
1183:                        && (viewCache.coexistenceCenterInPworldPolicy == View.NOMINAL_SCREEN)) {
1184:
1185:                    // Compute the coexistence center in image plate coordinates
1186:
1187:                    // Image plate cordinates have their orgin in the lower
1188:                    // left hand corner of the CRT visiable raster.
1189:                    // The nominal coexistence center is at the *center* of
1190:                    // targeted area: either the window or screen, depending
1191:                    // on policy.
1192:                    if (viewCache.windowMovementPolicy == View.VIRTUAL_WORLD) {
1193:                        coexistenceCenter.x = physicalScreenWidth / 2.0;
1194:                        coexistenceCenter.y = physicalScreenHeight / 2.0;
1195:                        coexistenceCenter.z = 0.0;
1196:                    } else { // windowMovementPolicy == PHYSICAL_WORLD
1197:                        coexistenceCenter.x = physicalWindowCenter.x;
1198:                        coexistenceCenter.y = physicalWindowCenter.y;
1199:                        coexistenceCenter.z = 0.0;
1200:                    }
1201:                } else {
1202:                    coexistenceCenter.set(0.0, 0.0, 0.0);
1203:                }
1204:
1205:                if (J3dDebug.devPhase) {
1206:                    if (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1) {
1207:                        System.err.println("coexistenceCenter = "
1208:                                + coexistenceCenter);
1209:                    }
1210:                }
1211:            }
1212:
1213:            private void computeCoexistenceToPlate() {
1214:                if (viewCache.compatibilityModeEnable) {
1215:                    // XXXX: implement this correctly
1216:                    coexistenceToLeftPlate.setIdentity();
1217:                    return;
1218:                }
1219:
1220:                if (viewCache.viewPolicy != View.HMD_VIEW) {
1221:                    coexistenceToLeftPlate.set(coexistenceCenter);
1222:                    coexistenceToLeftPlate
1223:                            .mul(screenViewCache.trackerBaseToImagePlate);
1224:                    coexistenceToLeftPlate
1225:                            .mul(viewCache.coexistenceToTrackerBase);
1226:
1227:                    if (useStereo) {
1228:                        coexistenceToRightPlate.set(coexistenceToLeftPlate);
1229:                    }
1230:                } else {
1231:                    coexistenceToLeftPlate.mul(headTrackerToLeftImagePlate,
1232:                            viewCache.trackerBaseToHeadTracker);
1233:                    coexistenceToLeftPlate
1234:                            .mul(viewCache.coexistenceToTrackerBase);
1235:
1236:                    if (useStereo) {
1237:                        coexistenceToRightPlate.mul(
1238:                                headTrackerToRightImagePlate,
1239:                                viewCache.trackerBaseToHeadTracker);
1240:                        coexistenceToRightPlate
1241:                                .mul(viewCache.coexistenceToTrackerBase);
1242:                    }
1243:                }
1244:
1245:                if ((J3dDebug.devPhase)
1246:                        && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) {
1247:                    System.err.println("coexistenceToLeftPlate:");
1248:                    System.err.println(coexistenceToLeftPlate);
1249:                    if (useStereo) {
1250:                        System.err.println("coexistenceToRightPlate:");
1251:                        System.err.println(coexistenceToRightPlate);
1252:
1253:                    }
1254:                }
1255:            }
1256:
1257:            /**
1258:             * Computes the viewing matrices.
1259:             *
1260:             * computeView computes the following:
1261:             *
1262:             * <ul>
1263:             * left (& right) eye viewing matrices (only left is valid for mono view)
1264:             * </ul>
1265:             *
1266:             * This call works for both fixed screen and HMD displays.
1267:             */
1268:            private void computeView(boolean doInfinite) {
1269:                int i, j;
1270:                int backClipPolicy;
1271:                double Fl, Fr, B, scale, backClipDistance;
1272:
1273:                // compute scale used for transforming clip and fog distances
1274:                vworldToCoexistenceScale = vworldToVpc.getDistanceScale()
1275:                        * vpcToCoexistence.getDistanceScale();
1276:                if (doInfinite) {
1277:                    infVworldToCoexistenceScale = infVworldToVpc
1278:                            .getDistanceScale()
1279:                            * vpcToCoexistence.getDistanceScale();
1280:                }
1281:
1282:                if ((J3dDebug.devPhase)
1283:                        && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) {
1284:                    System.err.println("vworldToCoexistenceScale = "
1285:                            + vworldToCoexistenceScale);
1286:                }
1287:
1288:                // compute coexistenceToVworld transform -- dirty bit candidate!!
1289:                tempTrans.mul(viewCache.coexistenceToTrackerBase,
1290:                        vpcToCoexistence);
1291:                vworldToTrackerBase.mul(tempTrans, vworldToVpc);
1292:
1293:                // If we are in compatibility mode, compute the view and
1294:                // projection matrices accordingly
1295:                if (viewCache.compatibilityModeEnable) {
1296:                    leftProjection.set(viewCache.compatLeftProjection);
1297:                    leftVpcToEc.set(viewCache.compatVpcToEc);
1298:
1299:                    if ((J3dDebug.devPhase)
1300:                            && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1)) {
1301:                        System.err.println("Left projection and view matrices");
1302:                        System.err.println("ecToCc (leftProjection) :");
1303:                        System.err.println(leftProjection);
1304:                        System.err.println("vpcToEc:");
1305:                        System.err.println(leftVpcToEc);
1306:                    }
1307:
1308:                    computeFrustumPlanes(leftProjection, leftVpcToEc,
1309:                            leftFrustumPlanes, leftFrustumPoints,
1310:                            leftCcToVworld);
1311:
1312:                    if (useStereo) {
1313:                        rightProjection.set(viewCache.compatRightProjection);
1314:                        rightVpcToEc.set(viewCache.compatVpcToEc);
1315:
1316:                        if ((J3dDebug.devPhase)
1317:                                && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1)) {
1318:                            System.err
1319:                                    .println("Right projection and view matrices");
1320:                            System.err.println("ecToCc:");
1321:                            System.err.println("vpcToEc:");
1322:                            System.err.println(rightVpcToEc);
1323:                        }
1324:
1325:                        computeFrustumPlanes(rightProjection, rightVpcToEc,
1326:                                rightFrustumPlanes, rightFrustumPoints,
1327:                                rightCcToVworld);
1328:                    }
1329:
1330:                    return;
1331:                }
1332:
1333:                //
1334:                //  The clipping plane distances are set from the internal policy.
1335:                //
1336:                //  Note that the plane distance follows the standard Z axis
1337:                //  convention, e.g. negative numbers further away.
1338:                //  Note that for policy from eye, the distance is negative in
1339:                //  the direction of z in front of the eye.
1340:                //  Note that for policy from screen, the distance is negative for
1341:                //  locations behind the screen, and positive in front.
1342:                //
1343:                //  The distance attributes are measured either in physical (plate)
1344:                //  units, or vworld units.
1345:                //
1346:
1347:                // Compute scale factor for front clip plane computation
1348:                if (viewCache.frontClipPolicy == View.VIRTUAL_EYE
1349:                        || viewCache.frontClipPolicy == View.VIRTUAL_SCREEN) {
1350:                    scale = vworldToCoexistenceScale;
1351:                } else {
1352:                    scale = windowScale;
1353:                }
1354:
1355:                // Set left and right front clipping plane distances.
1356:                if (viewCache.frontClipPolicy == View.PHYSICAL_EYE
1357:                        || viewCache.frontClipPolicy == View.VIRTUAL_EYE) {
1358:                    Fl = leftEyeInImagePlate.z + scale
1359:                            * -viewCache.frontClipDistance;
1360:                    Fr = rightEyeInImagePlate.z + scale
1361:                            * -viewCache.frontClipDistance;
1362:                } else {
1363:                    Fl = scale * -viewCache.frontClipDistance;
1364:                    Fr = scale * -viewCache.frontClipDistance;
1365:                }
1366:
1367:                // if there is an active clip node, use it and ignore the view's
1368:                // backclip
1369:                if ((renderBin != null) && (renderBin.backClipActive)) {
1370:                    backClipPolicy = View.VIRTUAL_EYE;
1371:                    backClipDistance = renderBin.backClipDistanceInVworld;
1372:                } else {
1373:                    backClipPolicy = viewCache.backClipPolicy;
1374:                    backClipDistance = viewCache.backClipDistance;
1375:                }
1376:
1377:                // Compute scale factor for rear clip plane computation
1378:                if (backClipPolicy == View.VIRTUAL_EYE
1379:                        || backClipPolicy == View.VIRTUAL_SCREEN) {
1380:                    scale = vworldToCoexistenceScale;
1381:                } else {
1382:                    scale = windowScale;
1383:                }
1384:
1385:                // Set left and right rear clipping plane distnaces.
1386:                if (backClipPolicy == View.PHYSICAL_EYE
1387:                        || backClipPolicy == View.VIRTUAL_EYE) {
1388:                    // Yes, left for both left and right rear.
1389:                    B = leftEyeInImagePlate.z + scale * -backClipDistance;
1390:                } else {
1391:                    B = scale * -backClipDistance;
1392:                }
1393:
1394:                // XXXX: Can optimize for HMD case.
1395:                if (true /*viewCache.viewPolicy != View.HMD_VIEW*/) {
1396:
1397:                    // Call buildProjView to build the projection and view matrices.
1398:
1399:                    if ((J3dDebug.devPhase)
1400:                            && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) {
1401:                        System.err.println("Left projection and view matrices");
1402:                        System.err.println("Fl " + Fl + " B " + B);
1403:                        System.err.println("leftEyeInImagePlate\n"
1404:                                + leftEyeInImagePlate);
1405:                        System.err.println("Before : leftProjection\n"
1406:                                + leftProjection);
1407:                        System.err
1408:                                .println("Before leftVpcToEc\n" + leftVpcToEc);
1409:                    }
1410:
1411:                    buildProjView(leftEyeInImagePlate, coexistenceToLeftPlate,
1412:                            vpcToLeftPlate, Fl, B, leftProjection, leftVpcToEc,
1413:                            false);
1414:
1415:                    if ((J3dDebug.devPhase)
1416:                            && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) {
1417:                        System.err.println("After : leftProjection\n"
1418:                                + leftProjection);
1419:                        System.err.println("After leftVpcToEc\n" + leftVpcToEc);
1420:                    }
1421:
1422:                    computeFrustumPlanes(leftProjection, leftVpcToEc,
1423:                            leftFrustumPlanes, leftFrustumPoints,
1424:                            leftCcToVworld);
1425:
1426:                    if (useStereo) {
1427:                        if ((J3dDebug.devPhase)
1428:                                && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2))
1429:                            System.err
1430:                                    .println("Right projection and view matrices");
1431:
1432:                        buildProjView(rightEyeInImagePlate,
1433:                                coexistenceToRightPlate, vpcToRightPlate, Fr,
1434:                                B, rightProjection, rightVpcToEc, false);
1435:
1436:                        computeFrustumPlanes(rightProjection, rightVpcToEc,
1437:                                rightFrustumPlanes, rightFrustumPoints,
1438:                                rightCcToVworld);
1439:                    }
1440:
1441:                    //
1442:                    // Now to compute the left (& right) eye (and infinite)
1443:                    // viewing matrices.
1444:                    if (doInfinite) {
1445:                        // Call buildProjView separately for infinite view
1446:                        buildProjView(leftEyeInImagePlate,
1447:                                coexistenceToLeftPlate, vpcToLeftPlate,
1448:                                leftEyeInImagePlate.z - 0.05,
1449:                                leftEyeInImagePlate.z - 1.5, infLeftProjection,
1450:                                infLeftVpcToEc, true);
1451:
1452:                        if (useStereo) {
1453:                            buildProjView(rightEyeInImagePlate,
1454:                                    coexistenceToRightPlate, vpcToRightPlate,
1455:                                    rightEyeInImagePlate.z - 0.05,
1456:                                    rightEyeInImagePlate.z - 1.5,
1457:                                    infRightProjection, infRightVpcToEc, true);
1458:
1459:                        }
1460:                    }
1461:                }
1462:                // XXXX: The following code has never been ported
1463:                //      else {
1464:                //	    Point3d cen_eye;
1465:                //
1466:                //	    // HMD case.  Just concatenate the approprate matrices together.
1467:                //	    // Additional work just for now
1468:                //
1469:                //	    compute_lr_plate_to_cc( &cen_eye, Fl, B, 0, &vb, 0);
1470:                //
1471:                //	    if(useStereo) {
1472:                //		mat_mul_dpt(&right_eye_pos_in_head,
1473:                //			    head_to_right_plate, &cen_eye);
1474:                //		compute_lr_plate_to_cc( &cen_eye, Fr, B,
1475:                //				       1, &vb, 0);
1476:                //	    }
1477:                //
1478:                // 	    //  Make sure that coexistence_to_plate is current.
1479:                // 	    //  (It is usually constant for fixed plates, always varies for HMDs.)
1480:                // 	    //  For HMD case, computes finial matrices that will be used.
1481:                // 	    //
1482:                // 	    computeCoexistenceToPlate();
1483:                //	}
1484:
1485:            }
1486:
1487:            /**
1488:             * Debugging routine to analyze the projection matrix.
1489:             */
1490:            private void analyzeProjection(Transform3D p, double xMax) {
1491:                if (viewCache.projectionPolicy == View.PARALLEL_PROJECTION)
1492:                    System.err.println("PARALLEL_PROJECTION =");
1493:                else
1494:                    System.err.println("PERSPECTIVE_PROJECTION =");
1495:
1496:                System.err.println(p);
1497:
1498:                double projectionPlaneZ = ((p.mat[0] * xMax + p.mat[3] - p.mat[15]) / (p.mat[14] - p.mat[2]));
1499:
1500:                System.err.println("projection plane at z = "
1501:                        + projectionPlaneZ);
1502:            }
1503:
1504:            /**
1505:             *  buildProjView creates a projection and viewing matrix.
1506:             *
1507:             *  Inputs:
1508:             *     ep :		    eye point, in plate coordinates
1509:             * coe2Plate :          matrix from coexistence to image plate.
1510:             *     F, B :	    front, back clipping planes, in plate coordinates
1511:             *     doInfinite :	    flag to indicate ``at infinity'' view desired
1512:             *
1513:             *  Output:
1514:             *   vpc2Plate :       matric from vpc to image plate.
1515:             *     ecToCc :	    projection matrix from Eye Coordinates (EC)
1516:             *			    to Clipping Coordinates (CC)
1517:             *     vpcToEc :        view matrix from ViewPlatform Coordinates (VPC)
1518:             *			    to Eye Coordinates (EC)
1519:             */
1520:            private void buildProjView(Point3d ep, Transform3D coe2Plate,
1521:                    Transform3D vpc2Plate, double F, double B,
1522:                    Transform3D ecToCc, Transform3D vpcToEc, boolean doInfinite) {
1523:
1524:                // Lx,Ly Hx,Hy will be adjusted window boundaries
1525:                double Lx, Hx, Ly, Hy;
1526:                Lx = physicalWindowXLeft;
1527:                Hx = physicalWindowXRight;
1528:                Ly = physicalWindowYBottom;
1529:                Hy = physicalWindowYTop;
1530:
1531:                ecToCc.setIdentity();
1532:
1533:                // XXXX: we have no concept of glass correction in the Java 3D API
1534:                //
1535:                // Correction in apparent 3D position of window due to glass/CRT
1536:                // and spherical/cylinderical curvarure of CRT.
1537:                // This boils down to producing modified values of Lx Ly Hx Hy
1538:                // and is different for hot spot vs. window center corrections.
1539:                //
1540:                /* XXXX:
1541:                double		cx, cy;
1542:                if(viewPolicy != HMD_VIEW && enable_crt_glass_correction) {
1543:                    if (correction_point == CORRECTION_POINT_WINDOW_CENTER) {
1544:                	correct_crt( ep, Lx, Ly, &cx, &cy); Lx = cx; Ly = cy;
1545:                	correct_crt( ep, Hx, Hy, &cx, &cy); Hx = cx; Hy = cy;
1546:                    }
1547:                    else {  // must be hot spot correction
1548:                	// Not real code yet, for now just do same as above.
1549:                	correct_crt( ep, Lx, Ly, &cx, &cy); Lx = cx; Ly = cy;
1550:                	correct_crt( ep, Hx, Hy, &cx, &cy); Hx = cx; Hy = cy;
1551:                    }
1552:                }
1553:                 */
1554:
1555:                if ((J3dDebug.devPhase)
1556:                        && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) {
1557:                    System.err.println("ep = " + ep);
1558:                    System.err.println("Lx = " + Lx + ", Hx = " + Hx);
1559:                    System.err.println("Ly = " + Ly + ", Hy = " + Hy);
1560:                    System.err.println("F = " + F + ", B = " + B);
1561:                }
1562:
1563:                // Compute the proper projection equation.  Note that we
1564:                // do this in two steps: first we generate ImagePlateToCc,
1565:                // then we translate this by EcToPlate, resulting in a
1566:                // projection from EctoCc.
1567:                //
1568:                // A more efficient (and more accurate) approach would be to
1569:                // modify the equations below to directly project from EcToCc.
1570:
1571:                if (viewCache.projectionPolicy == View.PARALLEL_PROJECTION) {
1572:                    double inv_dx, inv_dy, inv_dz;
1573:                    inv_dx = 1.0 / (Hx - Lx);
1574:                    inv_dy = 1.0 / (Hy - Ly);
1575:                    inv_dz = 1.0 / (F - B);
1576:
1577:                    ecToCc.mat[0] = 2.0 * inv_dx;
1578:                    ecToCc.mat[3] = -(Hx + Lx) * inv_dx;
1579:                    ecToCc.mat[5] = 2.0 * inv_dy;
1580:                    ecToCc.mat[7] = -(Hy + Ly) * inv_dy;
1581:                    ecToCc.mat[10] = 2.0 * inv_dz;
1582:                    ecToCc.mat[11] = -(F + B) * inv_dz;
1583:                } else {
1584:                    double sxy, rzb, inv_dx, inv_dy;
1585:
1586:                    inv_dx = 1.0 / (Hx - Lx);
1587:                    inv_dy = 1.0 / (Hy - Ly);
1588:                    rzb = 1.0 / (ep.z - B);
1589:                    sxy = ep.z * rzb;
1590:
1591:                    ecToCc.mat[0] = sxy * 2.0 * inv_dx;
1592:                    ecToCc.mat[5] = sxy * 2.0 * inv_dy;
1593:
1594:                    ecToCc.mat[2] = rzb * (Hx + Lx - 2.0 * ep.x) * inv_dx;
1595:                    ecToCc.mat[6] = rzb * (Hy + Ly - 2.0 * ep.y) * inv_dy;
1596:                    ecToCc.mat[10] = rzb * (B + F - 2 * ep.z) / (B - F);
1597:                    ecToCc.mat[14] = -rzb;
1598:
1599:                    ecToCc.mat[3] = sxy * (-Hx - Lx) * inv_dx;
1600:                    ecToCc.mat[7] = sxy * (-Hy - Ly) * inv_dy;
1601:                    ecToCc.mat[11] = rzb
1602:                            * (B - ep.z - B * (B + F - 2 * ep.z) / (B - F));
1603:                    ecToCc.mat[15] = sxy;
1604:                }
1605:
1606:                // Since we set the matrix elements ourselves, we need to set the
1607:                // type field.  A value of 0 means a non-affine matrix.
1608:                ecToCc.setOrthoDirtyBit();
1609:
1610:                // EC to ImagePlate matrix is a simple translation.
1611:                tVec1.set(ep.x, ep.y, ep.z);
1612:                tMat1.set(tVec1);
1613:                ecToCc.mul(tMat1);
1614:
1615:                if ((J3dDebug.devPhase)
1616:                        && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) {
1617:                    System.err.println("ecToCc:");
1618:                    analyzeProjection(ecToCc, Hx);
1619:                }
1620:
1621:                if (!doInfinite) {
1622:                    // View matrix is:
1623:                    //  [plateToEc] [coexistence_to_plate] [vpc_to_coexistence]
1624:                    //  where vpc_to_coexistence includes the viewPlatformScale
1625:
1626:                    // First compute ViewPlatform to Plate
1627:                    vpc2Plate.mul(coe2Plate, vpcToCoexistence);
1628:
1629:                    // ImagePlate to EC matrix is a simple translation.
1630:                    tVec1.set(-ep.x, -ep.y, -ep.z);
1631:                    tMat1.set(tVec1);
1632:                    vpcToEc.mul(tMat1, vpc2Plate);
1633:
1634:                    if ((J3dDebug.devPhase)
1635:                            && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) {
1636:                        System.err.println("vpcToEc:");
1637:                        System.err.println(vpcToEc);
1638:                    }
1639:                } else {
1640:                    // Final infinite composite is:
1641:                    //   [coexistence_to_eye] [vpc_to_coexistence (vom)]
1642:                    //   (does vworld_to_coe_scale_factor get used here??? )
1643:                    //
1644:                    // The method is to relocate the coexistence org centered on
1645:                    // the eye rather than the window center (via coexistence_to_eye).
1646:                    // Computationaly simpler simplifed equation form may exist.
1647:
1648:                    // coexistence to eye is a simple translation.
1649:                    /*
1650:                     tVec1.set(ep.x, ep.y, ep.z);
1651:                     tMat1.set(tVec1);
1652:                     vpcToEc.mul(tMat1, vpcToCoexistence);
1653:                     // First compute ViewPlatform to Plate
1654:                     vpcToPlate.mul(coexistenceToPlatevpcToPlate, vpcToCoexistence);
1655:                     */
1656:
1657:                    // ImagePlate to EC matrix is a simple translation.
1658:                    tVec1.set(-ep.x, -ep.y, -ep.z);
1659:                    tMat1.set(tVec1);
1660:                    tMat1.mul(tMat1, vpc2Plate);
1661:                    tMat1.getRotation(vpcToEc); // use only rotation component of transform
1662:
1663:                }
1664:
1665:            }
1666:
1667:            /**
1668:             * Compute the plane equations for the frustum in ViewPlatform
1669:             * coordinates, plus its viewing frustum points.  ccToVworld will
1670:             * be cached - used by Canavs3D.getInverseVworldProjection().
1671:             */
1672:            private void computeFrustumPlanes(Transform3D ecToCc,
1673:                    Transform3D vpcToEc, Vector4d[] frustumPlanes,
1674:                    Point4d[] frustumPoints, Transform3D ccToVworld) {
1675:
1676:                // Compute the inverse of the Vworld to Cc transform.  This
1677:                // gives us the Cc to Vworld transform.
1678:                tMat2.mul(ecToCc, vpcToEc);
1679:                ccToVworld.mul(tMat2, vworldToVpc);
1680:                // System.err.println("ccToVworld = " + ccToVworld);
1681:                try {
1682:                    ccToVworld.invert();
1683:                } catch (SingularMatrixException e) {
1684:                    ccToVworld.setIdentity();
1685:                    // System.err.println("SingularMatrixException encountered when doing invert in computeFrustumPlanes");
1686:                }
1687:
1688:                if ((J3dDebug.devPhase)
1689:                        && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) {
1690:                    Transform3D t = new Transform3D();
1691:                    t.mul(ecToCc, vpcToEc);
1692:                    t.mul(vworldToVpc);
1693:                    System.err.println("\nvworldToCc = " + t);
1694:                    System.err.println("ccToVworld = " + ccToVworld);
1695:                    t.mul(ccToVworld);
1696:                    System.err.println("vworldToCc * ccToVworld = " + t);
1697:                }
1698:
1699:                // Transform the 8 corners of the viewing frustum into Vpc
1700:                frustumPoints[0].set(-1.0, -1.0, 1.0, 1.0); // lower-left-front
1701:                frustumPoints[1].set(-1.0, 1.0, 1.0, 1.0); // upper-left-front
1702:                frustumPoints[2].set(1.0, 1.0, 1.0, 1.0); // upper-right-front
1703:                frustumPoints[3].set(1.0, -1.0, 1.0, 1.0); // lower-right-front
1704:                frustumPoints[4].set(-1.0, -1.0, -1.0, 1.0); // lower-left-back
1705:                frustumPoints[5].set(-1.0, 1.0, -1.0, 1.0); // upper-left-back
1706:                frustumPoints[6].set(1.0, 1.0, -1.0, 1.0); // upper-right-back
1707:                frustumPoints[7].set(1.0, -1.0, -1.0, 1.0); // lower-right-back
1708:
1709:                ccToVworld.get(tMatrix);
1710:                int i;
1711:                for (i = 0; i < frustumPoints.length; i++) {
1712:                    tMatrix.transform(frustumPoints[i]);
1713:                    double w_inv = 1.0 / frustumPoints[i].w;
1714:                    frustumPoints[i].x *= w_inv;
1715:                    frustumPoints[i].y *= w_inv;
1716:                    frustumPoints[i].z *= w_inv;
1717:                }
1718:
1719:                // Now compute the 6 plane equations
1720:                // left
1721:                computePlaneEq(frustumPoints[0], frustumPoints[4],
1722:                        frustumPoints[5], frustumPoints[1], frustumPlanes[0]);
1723:
1724:                // right
1725:                computePlaneEq(frustumPoints[3], frustumPoints[2],
1726:                        frustumPoints[6], frustumPoints[7], frustumPlanes[1]);
1727:
1728:                // top
1729:                computePlaneEq(frustumPoints[1], frustumPoints[5],
1730:                        frustumPoints[6], frustumPoints[2], frustumPlanes[2]);
1731:
1732:                // bottom
1733:                computePlaneEq(frustumPoints[0], frustumPoints[3],
1734:                        frustumPoints[7], frustumPoints[4], frustumPlanes[3]);
1735:
1736:                // front
1737:                computePlaneEq(frustumPoints[0], frustumPoints[1],
1738:                        frustumPoints[2], frustumPoints[3], frustumPlanes[4]);
1739:
1740:                // back
1741:                computePlaneEq(frustumPoints[4], frustumPoints[7],
1742:                        frustumPoints[6], frustumPoints[5], frustumPlanes[5]);
1743:
1744:                //System.err.println("left plane = "   + frustumPlanes[0]);
1745:                //System.err.println("right plane = "  + frustumPlanes[1]);
1746:                //System.err.println("top plane = "    + frustumPlanes[2]);
1747:                //System.err.println("bottom plane = " + frustumPlanes[3]);
1748:                //System.err.println("front plane = "  + frustumPlanes[4]);
1749:                //System.err.println("back plane = "   + frustumPlanes[5]);
1750:            }
1751:
1752:            private void computePlaneEq(Point4d p1, Point4d p2, Point4d p3,
1753:                    Point4d p4, Vector4d planeEq) {
1754:                tVec1.x = p3.x - p1.x;
1755:                tVec1.y = p3.y - p1.y;
1756:                tVec1.z = p3.z - p1.z;
1757:
1758:                tVec2.x = p2.x - p1.x;
1759:                tVec2.y = p2.y - p1.y;
1760:                tVec2.z = p2.z - p1.z;
1761:
1762:                tVec3.cross(tVec2, tVec1);
1763:                tVec3.normalize();
1764:                planeEq.x = tVec3.x;
1765:                planeEq.y = tVec3.y;
1766:                planeEq.z = tVec3.z;
1767:                planeEq.w = -(planeEq.x * p1.x + planeEq.y * p1.y + planeEq.z
1768:                        * p1.z);
1769:            }
1770:
1771:            // Get methods for returning derived data values.
1772:            // Eventually, these get functions will cause some of the parameters
1773:            // to be lazily evaluated.
1774:            //
1775:            // NOTE: in the case of Transform3D, and Tuple objects, a reference
1776:            // to the actual derived data is returned.  In these cases, the caller
1777:            // must ensure that the returned data is not modified.
1778:            //
1779:            // NOTE: the snapshot and computeDerivedData methods are synchronized.
1780:            // Callers of the following methods that can run asynchronously with
1781:            // the renderer must call these methods and copy the data from within
1782:            // a synchronized block on the canvas view cache object.
1783:
1784:            int getCanvasX() {
1785:                return canvasX;
1786:            }
1787:
1788:            int getCanvasY() {
1789:                return canvasY;
1790:            }
1791:
1792:            int getCanvasWidth() {
1793:                return canvasWidth;
1794:            }
1795:
1796:            int getCanvasHeight() {
1797:                return canvasHeight;
1798:            }
1799:
1800:            double getPhysicalWindowWidth() {
1801:                return physicalWindowWidth;
1802:            }
1803:
1804:            double getPhysicalWindowHeight() {
1805:                return physicalWindowHeight;
1806:            }
1807:
1808:            boolean getUseStereo() {
1809:                return useStereo;
1810:            }
1811:
1812:            Transform3D getLeftProjection() {
1813:                return leftProjection;
1814:            }
1815:
1816:            Transform3D getRightProjection() {
1817:                return rightProjection;
1818:            }
1819:
1820:            Transform3D getLeftVpcToEc() {
1821:                return leftVpcToEc;
1822:            }
1823:
1824:            Transform3D getRightVpcToEc() {
1825:                return rightVpcToEc;
1826:            }
1827:
1828:            Transform3D getLeftEcToVpc() {
1829:                return leftEcToVpc;
1830:            }
1831:
1832:            Transform3D getRightEcToVpc() {
1833:                return rightEcToVpc;
1834:            }
1835:
1836:            Transform3D getInfLeftProjection() {
1837:                return infLeftProjection;
1838:            }
1839:
1840:            Transform3D getInfRightProjection() {
1841:                return infLeftProjection;
1842:            }
1843:
1844:            Transform3D getInfLeftVpcToEc() {
1845:                return infLeftVpcToEc;
1846:            }
1847:
1848:            Transform3D getInfRightVpcToEc() {
1849:                return infRightVpcToEc;
1850:            }
1851:
1852:            Transform3D getInfLeftEcToVpc() {
1853:                return infLeftEcToVpc;
1854:            }
1855:
1856:            Transform3D getInfgRightEcToVpc() {
1857:                return infRightEcToVpc;
1858:            }
1859:
1860:            Transform3D getInfVworldToVpc() {
1861:                return infVworldToVpc;
1862:            }
1863:
1864:            Transform3D getLeftCcToVworld() {
1865:                return leftCcToVworld;
1866:            }
1867:
1868:            Transform3D getRightCcToVworld() {
1869:                return rightCcToVworld;
1870:            }
1871:
1872:            Transform3D getImagePlateToVworld() {
1873:                // XXXX: Document -- This will return the transform of left plate.
1874:                return leftPlateToVworld;
1875:            }
1876:
1877:            Transform3D getLastVworldToImagePlate() {
1878:                // XXXX: Document -- This will return the transform of left plate.
1879:                return lastVworldToLeftPlate;
1880:
1881:            }
1882:
1883:            Transform3D getVworldToImagePlate() {
1884:                // XXXX: Document -- This will return the transform of left plate.
1885:                return vworldToLeftPlate;
1886:            }
1887:
1888:            Transform3D getVworldToTrackerBase() {
1889:                return vworldToTrackerBase;
1890:            }
1891:
1892:            double getVworldToCoexistenceScale() {
1893:                return vworldToCoexistenceScale;
1894:            }
1895:
1896:            double getInfVworldToCoexistenceScale() {
1897:                return infVworldToCoexistenceScale;
1898:            }
1899:
1900:            Point3d getLeftEyeInImagePlate() {
1901:                return leftEyeInImagePlate;
1902:            }
1903:
1904:            Point3d getRightEyeInImagePlate() {
1905:                return rightEyeInImagePlate;
1906:            }
1907:
1908:            Point3d getCenterEyeInImagePlate() {
1909:                return centerEyeInImagePlate;
1910:            }
1911:
1912:            Transform3D getHeadToVworld() {
1913:                return headToVworld;
1914:            }
1915:
1916:            Transform3D getVpcToVworld() {
1917:                return vpcToVworld;
1918:            }
1919:
1920:            Transform3D getVworldToVpc() {
1921:                return vworldToVpc;
1922:            }
1923:
1924:            // Transform the specified X point in AWT window-relative coordinates
1925:            // to image plate coordinates
1926:            double getWindowXInImagePlate(double x) {
1927:                double xScreen = x + (double) canvasX;
1928:                return metersPerPixelX * xScreen;
1929:            }
1930:
1931:            // Transform the specified Y point in AWT window-relative coordinates
1932:            // to image plate coordinates
1933:            double getWindowYInImagePlate(double y) {
1934:                double yScreen = y + (double) canvasY;
1935:                return metersPerPixelY
1936:                        * ((double) (screenHeight - 1) - yScreen);
1937:            }
1938:
1939:            Vector4d[] getLeftFrustumPlanesInVworld() {
1940:                return leftFrustumPlanes;
1941:            }
1942:
1943:            Vector4d[] getRightFrustumPlanesInVworld() {
1944:                return rightFrustumPlanes;
1945:            }
1946:
1947:            void getPixelLocationInImagePlate(double x, double y, double z,
1948:                    Point3d imagePlatePoint) {
1949:
1950:                double screenx = (x + canvasX) * metersPerPixelX;
1951:                double screeny = (screenHeight - 1 - canvasY - y)
1952:                        * metersPerPixelY;
1953:
1954:                if ((viewCache.projectionPolicy == View.PERSPECTIVE_PROJECTION)
1955:                        && (centerEyeInImagePlate.z != 0)) {
1956:                    double zScale = 1.0 - z / centerEyeInImagePlate.z;
1957:                    imagePlatePoint.x = (screenx - centerEyeInImagePlate.x)
1958:                            * zScale + centerEyeInImagePlate.x;
1959:                    imagePlatePoint.y = (screeny - centerEyeInImagePlate.y)
1960:                            * zScale + centerEyeInImagePlate.y;
1961:                } else {
1962:                    imagePlatePoint.x = screenx;
1963:                    imagePlatePoint.y = screeny;
1964:                }
1965:                imagePlatePoint.z = z;
1966:            }
1967:
1968:            /**
1969:             * Projects the specified point from image plate coordinates
1970:             * into AWT pixel coordinates.
1971:             */
1972:            void getPixelLocationFromImagePlate(Point3d imagePlatePoint,
1973:                    Point2d pixelLocation) {
1974:
1975:                double screenX, screenY;
1976:
1977:                if (viewCache.projectionPolicy == View.PERSPECTIVE_PROJECTION) {
1978:                    // get the vector from centerEyeInImagePlate to imagePlatePoint
1979:                    tVec1.sub(imagePlatePoint, centerEyeInImagePlate);
1980:
1981:                    // Scale this vector to make it end at the projection plane.
1982:                    // Scale is ratio :
1983:                    //     eye->imagePlate Plane dist  / eye->imagePlatePt dist
1984:                    // eye dist to plane is eyePos.z (eye is in +z space)
1985:                    // image->eye dist is -tVec1.z (image->eye is in -z dir)
1986:                    //System.err.println("eye dist = " + (centerEyeInImagePlate.z));
1987:                    //System.err.println("image dist = " + (-tVec1.z));
1988:                    if (tVec1.z != 0) {
1989:                        double zScale = centerEyeInImagePlate.z / (-tVec1.z);
1990:                        screenX = centerEyeInImagePlate.x + tVec1.x * zScale;
1991:                        screenY = centerEyeInImagePlate.y + tVec1.y * zScale;
1992:
1993:                    } else {
1994:                        screenX = imagePlatePoint.x;
1995:                        screenY = imagePlatePoint.y;
1996:                    }
1997:
1998:                } else {
1999:                    screenX = imagePlatePoint.x;
2000:                    screenY = imagePlatePoint.y;
2001:                }
2002:
2003:                //System.err.println("screenX = " + screenX + " screenY = " + screenY);
2004:                // Note: screenPt is in image plate coords, at z=0
2005:
2006:                // Transform from image plate coords to screen coords
2007:                pixelLocation.x = (screenX / screenViewCache.metersPerPixelX)
2008:                        - canvasX;
2009:                pixelLocation.y = screenViewCache.screenHeight - 1
2010:                        - (screenY / screenViewCache.metersPerPixelY) - canvasY;
2011:                //System.err.println("pixelLocation = " + pixelLocation);
2012:            }
2013:
2014:            /**
2015:             * Constructs and initializes a CanvasViewCache object.
2016:             * Note that the canvas, screen, screenCache, view, and
2017:             * viewCache parameters are all fixed at construction time
2018:             * and must be non-null.
2019:             */
2020:            CanvasViewCache(Canvas3D canvas, ScreenViewCache screenViewCache,
2021:                    ViewCache viewCache) {
2022:
2023:                this .canvas = canvas;
2024:                this .screenViewCache = screenViewCache;
2025:                this .viewCache = viewCache;
2026:
2027:                // Set up the initial plane equations
2028:                int i;
2029:                for (i = 0; i < leftFrustumPlanes.length; i++) {
2030:                    leftFrustumPlanes[i] = new Vector4d();
2031:                    rightFrustumPlanes[i] = new Vector4d();
2032:                }
2033:
2034:                for (i = 0; i < leftFrustumPoints.length; i++) {
2035:                    leftFrustumPoints[i] = new Point4d();
2036:                    rightFrustumPoints[i] = new Point4d();
2037:                }
2038:
2039:                // canvas is null in Renderer copyOfCvCache
2040:                if (canvas != null) {
2041:                    leftEyeInImagePlate.set(canvas.leftManualEyeInImagePlate);
2042:                    rightEyeInImagePlate.set(canvas.rightManualEyeInImagePlate);
2043:                    centerEyeInImagePlate.add(leftEyeInImagePlate,
2044:                            rightEyeInImagePlate);
2045:                    centerEyeInImagePlate.scale(0.5);
2046:                }
2047:
2048:                if ((J3dDebug.devPhase)
2049:                        && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1))
2050:                    System.err.println("Constructed a CanvasViewCache");
2051:            }
2052:
2053:            synchronized void setCanvas(Canvas3D c) {
2054:                canvas = c;
2055:            }
2056:
2057:            synchronized void setScreenViewCache(ScreenViewCache svc) {
2058:                screenViewCache = svc;
2059:            }
2060:
2061:            synchronized void setViewCache(ViewCache vc) {
2062:                viewCache = vc;
2063:            }
2064:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.