1 /* 2 * $RCSfile: ViewCache.java,v $ 3 * 4 * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 * 7 * This code is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 only, as 9 * published by the Free Software Foundation. Sun designates this 10 * particular file as subject to the "Classpath" exception as provided 11 * by Sun in the LICENSE file that accompanied this code. 12 * 13 * This code is distributed in the hope that it will be useful, but WITHOUT 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 * version 2 for more details (a copy is included in the LICENSE file that 17 * accompanied this code). 18 * 19 * You should have received a copy of the GNU General Public License version 20 * 2 along with this work; if not, write to the Free Software Foundation, 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 22 * 23 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 24 * CA 95054 USA or visit www.sun.com if you need additional information or 25 * have any questions. 26 * 27 * $Revision: 1.7 $ 28 * $Date: 2008/02/28 20:17:32 $ 29 * $State: Exp $ 30 */ 31 32 package javax.media.j3d; 33 34 import javax.vecmath.*; 35 36 /** 37 * The ViewCache class is used to cache all data, both API data and derived 38 * data, that is independent of the Canvas3D and Screen3D. 39 */ 40 class ViewCache extends Object { 41 // The view associated with this view cache 42 View view; 43 44 // 45 // API/INPUT DATA 46 // 47 48 // ********************* 49 // * From ViewPlatform * 50 // ********************* 51 int viewAttachPolicy; 52 53 // ********************* 54 // * From PhysicalBody * 55 // ********************* 56 57 /** 58 * The user's left eye's position in head coordinates. 59 */ 60 Point3d leftEyePosInHead = new Point3d(); 61 62 /** 63 * The user's right eye's position in head coordinates. 64 */ 65 Point3d rightEyePosInHead = new Point3d(); 66 67 /** 68 * The user's left ear's position in head coordinates. 69 */ 70 Point3d leftEarPosInHead = new Point3d(); 71 72 /** 73 * The user's right ear's position in head coordinates. 74 */ 75 Point3d rightEarPosInHead = new Point3d(); 76 77 /** 78 * The user's nominal eye height as measured 79 * from the ground plane. 80 */ 81 double nominalEyeHeightFromGround; 82 83 /** 84 * The amount to offset the system's 85 * viewpoint from the user's current eye-point. This offset 86 * distance allows an "Over the shoulder" view of the scene 87 * as seen by the user. 88 */ 89 double nominalEyeOffsetFromNominalScreen; 90 91 // Head to head-tracker coordinate system transform. 92 // If head tracking is enabled, this transform is a calibration 93 // constant. If head tracking is not enabled, this transform is 94 // not used. 95 // This is only used in SCREEN_VIEW mode. 96 Transform3D headToHeadTracker = new Transform3D(); 97 98 // **************************** 99 // * From PhysicalEnvironment * 100 // **************************** 101 102 // Coexistence coordinate system to tracker-base coordinate 103 // system transform. If head tracking is enabled, this transform 104 // is a calibration constant. If head tracking is not enabled, 105 // this transform is not used. 106 // This is used in both SCREEN_VIEW and HMD_VIEW modes. 107 Transform3D coexistenceToTrackerBase = new Transform3D(); 108 109 // Transform generated by the head tracker to transform 110 // from tracker base to head tracker coordinates (and the inverse). 111 Transform3D headTrackerToTrackerBase = new Transform3D(); 112 Transform3D trackerBaseToHeadTracker = new Transform3D(); 113 114 // 115 // Indicates whether the underlying hardware implementation 116 // supports tracking. 117 // 118 boolean trackingAvailable; 119 120 // Sensor index for head tracker 121 int headIndex; 122 123 // 124 // This variable specifies the policy Java 3D will use in placing 125 // the user's eye position relative to the user's head position 126 // (NOMINAL_SCREEN, NOMINAL_HEAD, or NOMINAL_FEET). 127 // It is used in the calibration process. 128 // 129 int coexistenceCenterInPworldPolicy; 130 131 132 // ************* 133 // * From View * 134 // ************* 135 136 // View model compatibility mode flag 137 boolean compatibilityModeEnable; 138 139 // coexistenceCenteringEnable flag 140 boolean coexistenceCenteringEnable; 141 142 Point3d leftManualEyeInCoexistence = new Point3d(); 143 Point3d rightManualEyeInCoexistence = new Point3d(); 144 145 // Indicates which major mode of view computation to use: 146 // HMD mode or screen/fish-tank-VR mode. 147 int viewPolicy; 148 149 // The current projection policy (parallel versus perspective) 150 int projectionPolicy; 151 152 // The current screen scale policy and scale value 153 int screenScalePolicy; 154 double screenScale; 155 156 // The current window resize, movement and eyepoint policies 157 int windowResizePolicy; 158 int windowMovementPolicy; 159 int windowEyepointPolicy; 160 161 // The current monoscopic view policy 162 int monoscopicViewPolicy; 163 164 // The view model's field of view. 165 double fieldOfView; 166 167 // The distance away from the clip origin 168 // in the direction of gaze for the front and back clip planes. 169 double frontClipDistance; 170 double backClipDistance; 171 172 // Front and back clip policies 173 int frontClipPolicy; 174 int backClipPolicy; 175 176 // ViewPlatform of this view 177 ViewPlatformRetained vpRetained; 178 179 /** 180 * Defines the visibility policy. 181 */ 182 int visibilityPolicy; 183 184 // Flag to enable tracking, if so allowed by the trackingAvailable flag. 185 boolean trackingEnable; 186 187 // This setting enables the continuous updating by Java 3D of the 188 // userHeadToVworld transform. 189 boolean userHeadToVworldEnable; 190 191 // The current compatibility mode view transform 192 Transform3D compatVpcToEc = new Transform3D(); 193 194 // The current compatibility mode projection transforms 195 Transform3D compatLeftProjection = new Transform3D(); 196 Transform3D compatRightProjection = new Transform3D(); 197 198 // Mask that indicates ViewCache's view dependence info. has changed, 199 // and CanvasViewCache may need to recompute the final view matries. 200 int vcDirtyMask = 0; 201 202 // 203 // DERIVED DATA 204 // 205 206 // Flag indicating that head tracking will be used 207 private boolean doHeadTracking; 208 209 // 210 // Matrix to transform from user-head to 211 // virtual-world coordinates. This matrix is a read-only 212 // value that Java 3D generates continuously, but only if enabled 213 // by userHeadToVworldEnableFlag. 214 // 215 Transform3D userHeadToVworld = new Transform3D(); 216 217 218 /** 219 * Take snapshot of all per-view API parameters and input values. 220 */ snapshot()221 synchronized void snapshot() { 222 223 // View parameters 224 vcDirtyMask = view.vDirtyMask; 225 view.vDirtyMask = 0; 226 compatibilityModeEnable = view.compatibilityModeEnable; 227 coexistenceCenteringEnable = view.coexistenceCenteringEnable; 228 leftManualEyeInCoexistence.set(view.leftManualEyeInCoexistence); 229 rightManualEyeInCoexistence.set(view.rightManualEyeInCoexistence); 230 viewPolicy = view.viewPolicy; 231 projectionPolicy = view.projectionPolicy; 232 screenScalePolicy = view.screenScalePolicy; 233 windowResizePolicy = view.windowResizePolicy; 234 windowMovementPolicy = view.windowMovementPolicy; 235 windowEyepointPolicy = view.windowEyepointPolicy; 236 monoscopicViewPolicy = view.monoscopicViewPolicy; 237 238 fieldOfView = view.fieldOfView; 239 screenScale = view.screenScale; 240 241 frontClipDistance = view.frontClipDistance; 242 backClipDistance = view.backClipDistance; 243 frontClipPolicy = view.frontClipPolicy; 244 backClipPolicy = view.backClipPolicy; 245 246 visibilityPolicy = view.visibilityPolicy; 247 248 trackingEnable = view.trackingEnable; 249 userHeadToVworldEnable = view.userHeadToVworldEnable; 250 251 view.compatVpcToEc.getWithLock(compatVpcToEc); 252 view.compatLeftProjection.getWithLock(compatLeftProjection); 253 view.compatRightProjection.getWithLock(compatRightProjection); 254 255 // ViewPlatform parameters 256 ViewPlatform vpp = view.getViewPlatform(); 257 258 if (vpp == null) { 259 // This happens when user attach a null viewplatform 260 // and MC still call updateViewCache() in run before 261 // the viewDeactivate request get. 262 return; 263 } 264 265 vpRetained = (ViewPlatformRetained) vpp.retained; 266 267 synchronized(vpRetained) { 268 vcDirtyMask |= vpRetained.vprDirtyMask; 269 vpRetained.vprDirtyMask = 0; 270 viewAttachPolicy = vpRetained.viewAttachPolicy; 271 // System.err.println("ViewCache snapshot vcDirtyMask " + vcDirtyMask ); 272 } 273 274 // PhysicalEnvironment parameters 275 PhysicalEnvironment env = view.getPhysicalEnvironment(); 276 277 synchronized(env) { 278 vcDirtyMask |= env.peDirtyMask; 279 env.peDirtyMask = 0; 280 281 env.coexistenceToTrackerBase.getWithLock(coexistenceToTrackerBase); 282 trackingAvailable = env.trackingAvailable; 283 coexistenceCenterInPworldPolicy = env.coexistenceCenterInPworldPolicy; 284 285 // NOTE: this is really derived data, but we need it here in order 286 // to avoid reading head tracked data when no tracker is available 287 // and enabled. 288 doHeadTracking = trackingEnable && trackingAvailable; 289 290 if (doHeadTracking) { 291 headIndex = env.getHeadIndex(); 292 env.getSensor(headIndex).getRead(headTrackerToTrackerBase); 293 vcDirtyMask |= View.TRACKING_ENABLE_DIRTY; 294 } 295 else { 296 headTrackerToTrackerBase.setIdentity(); 297 } 298 } 299 300 // PhysicalBody parameters 301 PhysicalBody body = view.getPhysicalBody(); 302 303 synchronized(body) { 304 vcDirtyMask |= body.pbDirtyMask; 305 body.pbDirtyMask = 0; 306 307 leftEyePosInHead.set(body.leftEyePosition); 308 rightEyePosInHead.set(body.rightEyePosition); 309 leftEarPosInHead.set(body.leftEarPosition); 310 rightEarPosInHead.set(body.rightEarPosition); 311 312 nominalEyeHeightFromGround = body.nominalEyeHeightFromGround; 313 nominalEyeOffsetFromNominalScreen = 314 body.nominalEyeOffsetFromNominalScreen; 315 } 316 317 body.headToHeadTracker.getWithLock(headToHeadTracker); 318 } 319 320 321 /** 322 * Compute derived data using the snapshot of the per-view data. 323 */ computeDerivedData()324 synchronized void computeDerivedData() { 325 if (doHeadTracking) { 326 trackerBaseToHeadTracker.invert(headTrackerToTrackerBase); 327 //System.err.println("trackerBaseToHeadTracker: "); 328 //System.err.println(trackerBaseToHeadTracker); 329 } 330 else { 331 trackerBaseToHeadTracker.setIdentity(); 332 } 333 334 // XXXX: implement head to vworld tracking if userHeadToVworldEnable is set 335 userHeadToVworld.setIdentity(); 336 } 337 338 339 // Get methods for returning derived data values. 340 // Eventually, these get functions will cause some of the parameters 341 // to be lazily evaluated. 342 // 343 // NOTE that in the case of Transform3D, and Tuple objects, a reference 344 // to the actual derived data is returned. In these cases, the caller 345 // must ensure that the returned data is not modified. 346 getDoHeadTracking()347 boolean getDoHeadTracking() { 348 return doHeadTracking; 349 } 350 351 /** 352 * Constructs and initializes a ViewCache object. 353 */ ViewCache(View view)354 ViewCache(View view) { 355 this.view = view; 356 357 if (false) 358 System.err.println("Constructed a ViewCache"); 359 } 360 361 } 362