250 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
		
		
			
		
	
	
			250 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
| 
								 | 
							
								package kha.js.vr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import js.Syntax;
							 | 
						||
| 
								 | 
							
								import js.lib.Float32Array;
							 | 
						||
| 
								 | 
							
								import kha.vr.Pose;
							 | 
						||
| 
								 | 
							
								import kha.vr.PoseState;
							 | 
						||
| 
								 | 
							
								import kha.vr.SensorState;
							 | 
						||
| 
								 | 
							
								import kha.vr.TimeWarpParms;
							 | 
						||
| 
								 | 
							
								import kha.math.FastMatrix4;
							 | 
						||
| 
								 | 
							
								import kha.math.Vector3;
							 | 
						||
| 
								 | 
							
								import kha.math.Quaternion;
							 | 
						||
| 
								 | 
							
								import kha.SystemImpl;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class VrInterface extends kha.vr.VrInterface {
							 | 
						||
| 
								 | 
							
									var vrEnabled: Bool = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var vrDisplay: Dynamic;
							 | 
						||
| 
								 | 
							
									var frameData: Dynamic;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var leftProjectionMatrix: FastMatrix4 = FastMatrix4.identity();
							 | 
						||
| 
								 | 
							
									var rightProjectionMatrix: FastMatrix4 = FastMatrix4.identity();
							 | 
						||
| 
								 | 
							
									var leftViewMatrix: FastMatrix4 = FastMatrix4.identity();
							 | 
						||
| 
								 | 
							
									var rightViewMatrix: FastMatrix4 = FastMatrix4.identity();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var width: Int = 0;
							 | 
						||
| 
								 | 
							
									var height: Int = 0;
							 | 
						||
| 
								 | 
							
									var vrWidth: Int = 0;
							 | 
						||
| 
								 | 
							
									var vrHeight: Int = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public function new() {
							 | 
						||
| 
								 | 
							
										super();
							 | 
						||
| 
								 | 
							
										#if kha_webvr
							 | 
						||
| 
								 | 
							
										var displayEnabled: Bool = Syntax.code("navigator.getVRDisplays");
							 | 
						||
| 
								 | 
							
										#else
							 | 
						||
| 
								 | 
							
										var displayEnabled = false;
							 | 
						||
| 
								 | 
							
										#end
							 | 
						||
| 
								 | 
							
										if (displayEnabled) {
							 | 
						||
| 
								 | 
							
											vrEnabled = true;
							 | 
						||
| 
								 | 
							
											getVRDisplays();
							 | 
						||
| 
								 | 
							
											trace("Display enabled.");
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function getVRDisplays() {
							 | 
						||
| 
								 | 
							
										var vrDisplayInstance = Syntax.code("navigator.getVRDisplays()");
							 | 
						||
| 
								 | 
							
										vrDisplayInstance.then(function(displays) {
							 | 
						||
| 
								 | 
							
											if (displays.length > 0) {
							 | 
						||
| 
								 | 
							
												frameData = Syntax.code("new VRFrameData()");
							 | 
						||
| 
								 | 
							
												vrDisplay = Syntax.code("displays[0]");
							 | 
						||
| 
								 | 
							
												vrDisplay.depthNear = 0.1;
							 | 
						||
| 
								 | 
							
												vrDisplay.depthFar = 1024.0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												var leftEye = vrDisplay.getEyeParameters("left");
							 | 
						||
| 
								 | 
							
												var rightEye = vrDisplay.getEyeParameters("right");
							 | 
						||
| 
								 | 
							
												width = SystemImpl.khanvas.width;
							 | 
						||
| 
								 | 
							
												height = SystemImpl.khanvas.height;
							 | 
						||
| 
								 | 
							
												vrWidth = Std.int(Math.max(leftEye.renderWidth, rightEye.renderWidth) * 2);
							 | 
						||
| 
								 | 
							
												vrHeight = Std.int(Math.max(leftEye.renderHeight, rightEye.renderHeight));
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else {
							 | 
						||
| 
								 | 
							
												trace("There are no VR displays connected.");
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										});
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public override function onVRRequestPresent() {
							 | 
						||
| 
								 | 
							
										try {
							 | 
						||
| 
								 | 
							
											vrDisplay.requestPresent([{source: SystemImpl.khanvas}]).then(function() {
							 | 
						||
| 
								 | 
							
												onResize();
							 | 
						||
| 
								 | 
							
												vrDisplay.requestAnimationFrame(onAnimationFrame);
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										catch (err:Dynamic) {
							 | 
						||
| 
								 | 
							
											trace("Failed to requestPresent.");
							 | 
						||
| 
								 | 
							
											trace(err);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public override function onVRExitPresent() {
							 | 
						||
| 
								 | 
							
										try {
							 | 
						||
| 
								 | 
							
											vrDisplay.exitPresent([{source: SystemImpl.khanvas}]).then(function() {
							 | 
						||
| 
								 | 
							
												onResize();
							 | 
						||
| 
								 | 
							
											});
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										catch (err:Dynamic) {
							 | 
						||
| 
								 | 
							
											trace("Failed to exitPresent.");
							 | 
						||
| 
								 | 
							
											trace(err);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public override function onResetPose() {
							 | 
						||
| 
								 | 
							
										try {
							 | 
						||
| 
								 | 
							
											vrDisplay.resetPose();
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										catch (err:Dynamic) {
							 | 
						||
| 
								 | 
							
											trace("Failed to resetPose");
							 | 
						||
| 
								 | 
							
											trace(err);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function onAnimationFrame(timestamp: Float): Void {
							 | 
						||
| 
								 | 
							
										if (vrDisplay != null && vrDisplay.isPresenting) {
							 | 
						||
| 
								 | 
							
											vrDisplay.requestAnimationFrame(onAnimationFrame);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											vrDisplay.getFrameData(frameData);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											leftProjectionMatrix = createMatrixFromArray(untyped frameData.leftProjectionMatrix);
							 | 
						||
| 
								 | 
							
											leftViewMatrix = createMatrixFromArray(untyped frameData.leftViewMatrix);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											rightProjectionMatrix = createMatrixFromArray(untyped frameData.rightProjectionMatrix);
							 | 
						||
| 
								 | 
							
											rightViewMatrix = createMatrixFromArray(untyped frameData.rightViewMatrix);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Submit the newly rendered layer to be presented by the VRDisplay
							 | 
						||
| 
								 | 
							
											vrDisplay.submitFrame();
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function onResize() {
							 | 
						||
| 
								 | 
							
										if (vrDisplay != null && vrDisplay.isPresenting) {
							 | 
						||
| 
								 | 
							
											SystemImpl.khanvas.width = vrWidth;
							 | 
						||
| 
								 | 
							
											SystemImpl.khanvas.height = vrHeight;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else {
							 | 
						||
| 
								 | 
							
											SystemImpl.khanvas.width = width;
							 | 
						||
| 
								 | 
							
											SystemImpl.khanvas.height = height;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public override function GetSensorState(): SensorState {
							 | 
						||
| 
								 | 
							
										return GetPredictedSensorState(0.0);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public override function GetPredictedSensorState(time: Float): SensorState {
							 | 
						||
| 
								 | 
							
										var result: SensorState = new SensorState();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										result.Predicted = new PoseState();
							 | 
						||
| 
								 | 
							
										result.Recorded = result.Predicted;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										result.Predicted.AngularAcceleration = new Vector3();
							 | 
						||
| 
								 | 
							
										result.Predicted.AngularVelocity = new Vector3();
							 | 
						||
| 
								 | 
							
										result.Predicted.LinearAcceleration = new Vector3();
							 | 
						||
| 
								 | 
							
										result.Predicted.LinearVelocity = new Vector3();
							 | 
						||
| 
								 | 
							
										result.Predicted.TimeInSeconds = time;
							 | 
						||
| 
								 | 
							
										result.Predicted.Pose = new Pose();
							 | 
						||
| 
								 | 
							
										result.Predicted.Pose.Orientation = new Quaternion();
							 | 
						||
| 
								 | 
							
										result.Predicted.Pose.Position = new Vector3();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										var mPose = frameData.pose; // predicted pose of the vrDisplay
							 | 
						||
| 
								 | 
							
										if (mPose != null) {
							 | 
						||
| 
								 | 
							
											result.Predicted.AngularVelocity = createVectorFromArray(untyped mPose.angularVelocity);
							 | 
						||
| 
								 | 
							
											result.Predicted.AngularAcceleration = createVectorFromArray(untyped mPose.angularAcceleration);
							 | 
						||
| 
								 | 
							
											result.Predicted.LinearVelocity = createVectorFromArray(untyped mPose.linearVelocity);
							 | 
						||
| 
								 | 
							
											result.Predicted.LinearAcceleration = createVectorFromArray(untyped mPose.linearAcceleration);
							 | 
						||
| 
								 | 
							
											result.Predicted.Pose.Orientation = createQuaternion(untyped mPose.orientation);
							 | 
						||
| 
								 | 
							
											result.Predicted.Pose.Position = createVectorFromArray(untyped mPose.position);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return result;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Sends a black image to the warp swap thread
							 | 
						||
| 
								 | 
							
									public override function WarpSwapBlack(): Void {
							 | 
						||
| 
								 | 
							
										// TODO: Implement
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Sends the Oculus loading symbol to the warp swap thread
							 | 
						||
| 
								 | 
							
									public override function WarpSwapLoadingIcon(): Void {
							 | 
						||
| 
								 | 
							
										// TODO: Implement
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Sends the set of images to the warp swap thread
							 | 
						||
| 
								 | 
							
									public override function WarpSwap(parms: TimeWarpParms): Void {
							 | 
						||
| 
								 | 
							
										// TODO: Implement
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public override function IsPresenting(): Bool {
							 | 
						||
| 
								 | 
							
										if (vrDisplay != null)
							 | 
						||
| 
								 | 
							
											return vrDisplay.isPresenting;
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public override function IsVrEnabled(): Bool {
							 | 
						||
| 
								 | 
							
										return vrEnabled;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public override function GetTimeInSeconds(): Float {
							 | 
						||
| 
								 | 
							
										return Scheduler.time();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public override function GetProjectionMatrix(eye: Int): FastMatrix4 {
							 | 
						||
| 
								 | 
							
										if (eye == 0) {
							 | 
						||
| 
								 | 
							
											return leftProjectionMatrix;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else {
							 | 
						||
| 
								 | 
							
											return rightProjectionMatrix;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public override function GetViewMatrix(eye: Int): FastMatrix4 {
							 | 
						||
| 
								 | 
							
										if (eye == 0) {
							 | 
						||
| 
								 | 
							
											return leftViewMatrix;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else {
							 | 
						||
| 
								 | 
							
											return rightViewMatrix;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function createMatrixFromArray(array: Float32Array): FastMatrix4 {
							 | 
						||
| 
								 | 
							
										var matrix: FastMatrix4 = FastMatrix4.identity();
							 | 
						||
| 
								 | 
							
										matrix._00 = array[0];
							 | 
						||
| 
								 | 
							
										matrix._01 = array[1];
							 | 
						||
| 
								 | 
							
										matrix._02 = array[2];
							 | 
						||
| 
								 | 
							
										matrix._03 = array[3];
							 | 
						||
| 
								 | 
							
										matrix._10 = array[4];
							 | 
						||
| 
								 | 
							
										matrix._11 = array[5];
							 | 
						||
| 
								 | 
							
										matrix._12 = array[6];
							 | 
						||
| 
								 | 
							
										matrix._13 = array[7];
							 | 
						||
| 
								 | 
							
										matrix._20 = array[8];
							 | 
						||
| 
								 | 
							
										matrix._21 = array[9];
							 | 
						||
| 
								 | 
							
										matrix._22 = array[10];
							 | 
						||
| 
								 | 
							
										matrix._23 = array[11];
							 | 
						||
| 
								 | 
							
										matrix._30 = array[12];
							 | 
						||
| 
								 | 
							
										matrix._31 = array[13];
							 | 
						||
| 
								 | 
							
										matrix._32 = array[14];
							 | 
						||
| 
								 | 
							
										matrix._33 = array[15];
							 | 
						||
| 
								 | 
							
										return matrix;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function createVectorFromArray(array: Float32Array): Vector3 {
							 | 
						||
| 
								 | 
							
										var vector: Vector3 = new Vector3(0, 0, 0);
							 | 
						||
| 
								 | 
							
										if (array != null) {
							 | 
						||
| 
								 | 
							
											vector.x = array[0];
							 | 
						||
| 
								 | 
							
											vector.y = array[1];
							 | 
						||
| 
								 | 
							
											vector.z = array[2];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return vector;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function createQuaternion(array: Float32Array): Quaternion {
							 | 
						||
| 
								 | 
							
										var quaternion: Quaternion = new Quaternion(0, 0, 0, 0);
							 | 
						||
| 
								 | 
							
										if (array != null) {
							 | 
						||
| 
								 | 
							
											quaternion.x = array[0];
							 | 
						||
| 
								 | 
							
											quaternion.y = array[1];
							 | 
						||
| 
								 | 
							
											quaternion.z = array[2];
							 | 
						||
| 
								 | 
							
											quaternion.w = array[3];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return quaternion;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 |