250 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Haxe
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			250 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Haxe
		
	
	
		
			Executable File
		
	
	
	
	
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;
 | 
						|
	}
 | 
						|
}
 |