|
@@ -15384,6 +15384,7 @@ var BABYLON;
|
|
|
var bindTarget = texture.isCube ? gl.TEXTURE_CUBE_MAP : gl.TEXTURE_2D;
|
|
|
this._bindTextureDirectly(bindTarget, texture, true);
|
|
|
this._uploadDataToTextureDirectly(texture, texture.width, texture.height, imageData, faceIndex, lod);
|
|
|
+ this._bindTextureDirectly(bindTarget, null, true);
|
|
|
};
|
|
|
/** @hidden */
|
|
|
Engine.prototype._uploadImageToTexture = function (texture, image, faceIndex, lod) {
|
|
@@ -47904,16 +47905,16 @@ var BABYLON;
|
|
|
this.beta = this.upperBetaLimit;
|
|
|
}
|
|
|
}
|
|
|
- if (this.lowerAlphaLimit && this.alpha < this.lowerAlphaLimit) {
|
|
|
+ if (this.lowerAlphaLimit !== null && this.alpha < this.lowerAlphaLimit) {
|
|
|
this.alpha = this.lowerAlphaLimit;
|
|
|
}
|
|
|
- if (this.upperAlphaLimit && this.alpha > this.upperAlphaLimit) {
|
|
|
+ if (this.upperAlphaLimit !== null && this.alpha > this.upperAlphaLimit) {
|
|
|
this.alpha = this.upperAlphaLimit;
|
|
|
}
|
|
|
- if (this.lowerRadiusLimit && this.radius < this.lowerRadiusLimit) {
|
|
|
+ if (this.lowerRadiusLimit !== null && this.radius < this.lowerRadiusLimit) {
|
|
|
this.radius = this.lowerRadiusLimit;
|
|
|
}
|
|
|
- if (this.upperRadiusLimit && this.radius > this.upperRadiusLimit) {
|
|
|
+ if (this.upperRadiusLimit !== null && this.radius > this.upperRadiusLimit) {
|
|
|
this.radius = this.upperRadiusLimit;
|
|
|
}
|
|
|
};
|
|
@@ -73348,16 +73349,44 @@ var BABYLON;
|
|
|
*/
|
|
|
function GearVRController(vrGamepad) {
|
|
|
var _this = _super.call(this, vrGamepad) || this;
|
|
|
+ _this._maxRotationDistFromHeadset = Math.PI / 5;
|
|
|
+ _this._draggedRoomRotation = 0;
|
|
|
+ _this._tmpVector = new BABYLON.Vector3();
|
|
|
_this._buttonIndexToObservableNameMap = [
|
|
|
'onTrackpadChangedObservable',
|
|
|
'onTriggerStateChangedObservable' // Trigger
|
|
|
];
|
|
|
_this.controllerType = BABYLON.PoseEnabledControllerType.GEAR_VR;
|
|
|
// Initial starting position defaults to where hand would be (incase of only 3dof controller)
|
|
|
- _this._calculatedPosition = new BABYLON.Vector3(_this.hand == "left" ? -0.15 : 0.15, -0.5, 0.4);
|
|
|
+ _this._calculatedPosition = new BABYLON.Vector3(_this.hand == "left" ? -0.15 : 0.15, -0.5, 0.25);
|
|
|
return _this;
|
|
|
}
|
|
|
/**
|
|
|
+ * Updates the state of the pose enbaled controller based on the raw pose data from the device
|
|
|
+ * @param poseData raw pose fromthe device
|
|
|
+ */
|
|
|
+ GearVRController.prototype.updateFromDevice = function (poseData) {
|
|
|
+ _super.prototype.updateFromDevice.call(this, poseData);
|
|
|
+ if (BABYLON.Engine.LastCreatedScene && BABYLON.Engine.LastCreatedScene.activeCamera) {
|
|
|
+ if (BABYLON.Engine.LastCreatedScene.activeCamera.deviceRotationQuaternion) {
|
|
|
+ var camera = BABYLON.Engine.LastCreatedScene.activeCamera;
|
|
|
+ camera._deviceRoomRotationQuaternion.toEulerAnglesToRef(this._tmpVector);
|
|
|
+ // Find the radian distance away that the headset is from the controllers rotation
|
|
|
+ var distanceAway = Math.atan2(Math.sin(this._tmpVector.y - this._draggedRoomRotation), Math.cos(this._tmpVector.y - this._draggedRoomRotation));
|
|
|
+ if (Math.abs(distanceAway) > this._maxRotationDistFromHeadset) {
|
|
|
+ // Only rotate enouph to be within the _maxRotationDistFromHeadset
|
|
|
+ var rotationAmount = distanceAway - (distanceAway < 0 ? -this._maxRotationDistFromHeadset : this._maxRotationDistFromHeadset);
|
|
|
+ this._draggedRoomRotation += rotationAmount;
|
|
|
+ // Rotate controller around headset
|
|
|
+ var sin = Math.sin(-rotationAmount);
|
|
|
+ var cos = Math.cos(-rotationAmount);
|
|
|
+ this._calculatedPosition.x = this._calculatedPosition.x * cos - this._calculatedPosition.z * sin;
|
|
|
+ this._calculatedPosition.z = this._calculatedPosition.x * sin + this._calculatedPosition.z * cos;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ /**
|
|
|
* Implements abstract method on WebVRController class, loading controller meshes and calling this.attachToMesh if successful.
|
|
|
* @param scene scene in which to add meshes
|
|
|
* @param meshLoaded optional callback function that will be called if the mesh loads successfully.
|
|
@@ -73365,7 +73394,11 @@ var BABYLON;
|
|
|
GearVRController.prototype.initControllerMesh = function (scene, meshLoaded) {
|
|
|
var _this = this;
|
|
|
BABYLON.SceneLoader.ImportMesh("", GearVRController.MODEL_BASE_URL, GearVRController.MODEL_FILENAME, scene, function (newMeshes) {
|
|
|
- _this._defaultModel = newMeshes[1];
|
|
|
+ // Offset the controller so it will rotate around the users wrist
|
|
|
+ var mesh = new BABYLON.Mesh("", scene);
|
|
|
+ newMeshes[1].parent = mesh;
|
|
|
+ newMeshes[1].position.z = -0.15;
|
|
|
+ _this._defaultModel = mesh;
|
|
|
_this.attachToMesh(_this._defaultModel);
|
|
|
if (meshLoaded) {
|
|
|
meshLoaded(_this._defaultModel);
|
|
@@ -87699,7 +87732,7 @@ var BABYLON;
|
|
|
var func = '_getImageData' + (use_grey ? 'Grey' : '') + (header.pixel_size) + 'bits';
|
|
|
var imageData = TGATools[func](header, palettes, pixel_data, y_start, y_step, y_end, x_start, x_step, x_end);
|
|
|
var engine = texture.getEngine();
|
|
|
- engine._uploadArrayBufferViewToTexture(texture, imageData);
|
|
|
+ engine._uploadDataToTextureDirectly(texture, texture.width, texture.height, imageData);
|
|
|
};
|
|
|
TGATools._getImageData8bits = function (header, palettes, pixel_data, y_start, y_step, y_end, x_start, x_step, x_end) {
|
|
|
var image = pixel_data, colormap = palettes;
|
|
@@ -90072,10 +90105,18 @@ var BABYLON;
|
|
|
* Detaches the behavior from the mesh
|
|
|
*/
|
|
|
SixDofDragBehavior.prototype.detach = function () {
|
|
|
- this._scene.onPointerObservable.remove(this._pointerObserver);
|
|
|
- this._ownerNode.getScene().onBeforeRenderObservable.remove(this._sceneRenderObserver);
|
|
|
- this._virtualOriginMesh.dispose();
|
|
|
- this._virtualDragMesh.dispose();
|
|
|
+ if (this._scene) {
|
|
|
+ this._scene.onPointerObservable.remove(this._pointerObserver);
|
|
|
+ }
|
|
|
+ if (this._ownerNode) {
|
|
|
+ this._ownerNode.getScene().onBeforeRenderObservable.remove(this._sceneRenderObserver);
|
|
|
+ }
|
|
|
+ if (this._virtualOriginMesh) {
|
|
|
+ this._virtualOriginMesh.dispose();
|
|
|
+ }
|
|
|
+ if (this._virtualDragMesh) {
|
|
|
+ this._virtualDragMesh.dispose();
|
|
|
+ }
|
|
|
};
|
|
|
return SixDofDragBehavior;
|
|
|
}());
|
|
@@ -90141,7 +90182,11 @@ var BABYLON;
|
|
|
_this._rootMesh.position.copyFrom(_this.attachedMesh.absolutePosition);
|
|
|
}
|
|
|
if (_this._updateScale && _this.gizmoLayer.utilityLayerScene.activeCamera && _this.attachedMesh) {
|
|
|
- _this._rootMesh.position.subtractToRef(_this.gizmoLayer.utilityLayerScene.activeCamera.position, tempVector);
|
|
|
+ var cameraPosition = _this.gizmoLayer.utilityLayerScene.activeCamera.position;
|
|
|
+ if (_this.gizmoLayer.utilityLayerScene.activeCamera.devicePosition) {
|
|
|
+ cameraPosition = _this.gizmoLayer.utilityLayerScene.activeCamera.devicePosition;
|
|
|
+ }
|
|
|
+ _this._rootMesh.position.subtractToRef(cameraPosition, tempVector);
|
|
|
var dist = tempVector.length() / _this._scaleFactor;
|
|
|
_this._rootMesh.scaling.set(dist, dist, dist);
|
|
|
}
|
|
@@ -91168,74 +91213,182 @@ var BABYLON;
|
|
|
/**
|
|
|
* Instatiates a gizmo manager
|
|
|
* @param scene the scene to overlay the gizmos on top of
|
|
|
- * @param options If only a single gizmo should exist at one time
|
|
|
*/
|
|
|
- function GizmoManager(scene, options) {
|
|
|
+ function GizmoManager(scene) {
|
|
|
var _this = this;
|
|
|
this.scene = scene;
|
|
|
- // Set of gizmos that are currently in the scene for each mesh
|
|
|
- this._gizmoSet = {};
|
|
|
this._pointerObserver = null;
|
|
|
- this._gizmoLayer = new BABYLON.UtilityLayerRenderer(scene);
|
|
|
- // Options parsing
|
|
|
- if (!options) {
|
|
|
- options = {};
|
|
|
- }
|
|
|
- if (options.singleGizmo === undefined) {
|
|
|
- options.singleGizmo = true;
|
|
|
- }
|
|
|
+ this._attachedMesh = null;
|
|
|
+ this._boundingBoxColor = BABYLON.Color3.FromHexString("#0984e3");
|
|
|
+ this._boundingBoxUtilLayer = null;
|
|
|
+ this._dragBehavior = new BABYLON.SixDofDragBehavior();
|
|
|
+ /**
|
|
|
+ * Array of meshes which will have the gizmo attached when a pointer selected them. If null, all meshes are attachable. (Default: null)
|
|
|
+ */
|
|
|
+ this.attachableMeshes = null;
|
|
|
+ /**
|
|
|
+ * If pointer events should perform attaching/detaching a gizmo, if false this can be done manually via attachToMesh. (Default: true)
|
|
|
+ */
|
|
|
+ this.usePointerToAttachGizmos = true;
|
|
|
+ this._gizmoSet = { positionGizmo: null, rotationGizmo: null, scaleGizmo: null, boundingBoxGizmo: null };
|
|
|
// Instatiate/dispose gizmos based on pointer actions
|
|
|
this._pointerObserver = scene.onPointerObservable.add(function (pointerInfo, state) {
|
|
|
+ if (!_this.usePointerToAttachGizmos) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
if (pointerInfo.type == BABYLON.PointerEventTypes.POINTERDOWN) {
|
|
|
if (pointerInfo.pickInfo && pointerInfo.pickInfo.pickedMesh) {
|
|
|
- if (!_this._gizmoSet[pointerInfo.pickInfo.pickedMesh.uniqueId]) {
|
|
|
- if (options.singleGizmo) {
|
|
|
- _this._clearGizmos();
|
|
|
+ var node = pointerInfo.pickInfo.pickedMesh;
|
|
|
+ if (_this.attachableMeshes == null) {
|
|
|
+ // Attach to the most parent node
|
|
|
+ while (node && node.parent != null) {
|
|
|
+ node = node.parent;
|
|
|
}
|
|
|
- // Enable gizmo when mesh is selected
|
|
|
- _this._gizmoSet[pointerInfo.pickInfo.pickedMesh.uniqueId] = { positionGizmo: new BABYLON.PositionGizmo(_this._gizmoLayer), rotationGizmo: new BABYLON.RotationGizmo(_this._gizmoLayer) };
|
|
|
- _this._gizmoSet[pointerInfo.pickInfo.pickedMesh.uniqueId].positionGizmo.attachedMesh = pointerInfo.pickInfo.pickedMesh;
|
|
|
- _this._gizmoSet[pointerInfo.pickInfo.pickedMesh.uniqueId].rotationGizmo.attachedMesh = pointerInfo.pickInfo.pickedMesh;
|
|
|
}
|
|
|
else {
|
|
|
- if (!options.singleGizmo) {
|
|
|
- // Disable gizmo when clicked again
|
|
|
- _this._gizmoSet[pointerInfo.pickInfo.pickedMesh.uniqueId].positionGizmo.dispose();
|
|
|
- _this._gizmoSet[pointerInfo.pickInfo.pickedMesh.uniqueId].rotationGizmo.dispose();
|
|
|
- delete _this._gizmoSet[pointerInfo.pickInfo.pickedMesh.uniqueId];
|
|
|
+ // Attach to the parent node that is an attachableMesh
|
|
|
+ var found = false;
|
|
|
+ _this.attachableMeshes.forEach(function (mesh) {
|
|
|
+ if (node && (node == mesh || node.isDescendantOf(mesh))) {
|
|
|
+ node = mesh;
|
|
|
+ found = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (!found) {
|
|
|
+ node = null;
|
|
|
}
|
|
|
}
|
|
|
+ if (node instanceof BABYLON.AbstractMesh) {
|
|
|
+ _this.attachToMesh(node);
|
|
|
+ }
|
|
|
}
|
|
|
else {
|
|
|
- if (options.singleGizmo) {
|
|
|
- // Disable gizmo when clicked away
|
|
|
- if (pointerInfo.pickInfo && pointerInfo.pickInfo.ray) {
|
|
|
- var gizmoPick = _this._gizmoLayer.utilityLayerScene.pickWithRay(pointerInfo.pickInfo.ray);
|
|
|
- if (gizmoPick && !gizmoPick.hit) {
|
|
|
- _this._clearGizmos();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ _this.attachToMesh(null);
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
/**
|
|
|
+ * Attaches a set of gizmos to the specified mesh
|
|
|
+ * @param mesh The mesh the gizmo's should be attached to
|
|
|
+ */
|
|
|
+ GizmoManager.prototype.attachToMesh = function (mesh) {
|
|
|
+ if (this._attachedMesh) {
|
|
|
+ this._attachedMesh.removeBehavior(this._dragBehavior);
|
|
|
+ }
|
|
|
+ this._attachedMesh = mesh;
|
|
|
+ for (var key in this._gizmoSet) {
|
|
|
+ var gizmo = (this._gizmoSet[key]);
|
|
|
+ if (gizmo) {
|
|
|
+ gizmo.attachedMesh = mesh;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (this.boundingBoxGizmoEnabled && this._attachedMesh) {
|
|
|
+ this._attachedMesh.addBehavior(this._dragBehavior);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ Object.defineProperty(GizmoManager.prototype, "positionGizmoEnabled", {
|
|
|
+ get: function () {
|
|
|
+ return this._gizmoSet.positionGizmo != null;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * If the position gizmo is enabled
|
|
|
+ */
|
|
|
+ set: function (value) {
|
|
|
+ if (value) {
|
|
|
+ this._gizmoSet.positionGizmo = this._gizmoSet.positionGizmo || new BABYLON.PositionGizmo();
|
|
|
+ this._gizmoSet.positionGizmo.updateGizmoRotationToMatchAttachedMesh = false;
|
|
|
+ this._gizmoSet.positionGizmo.attachedMesh = this._attachedMesh;
|
|
|
+ }
|
|
|
+ else if (this._gizmoSet.positionGizmo) {
|
|
|
+ this._gizmoSet.positionGizmo.dispose();
|
|
|
+ this._gizmoSet.positionGizmo = null;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ enumerable: true,
|
|
|
+ configurable: true
|
|
|
+ });
|
|
|
+ Object.defineProperty(GizmoManager.prototype, "rotationGizmoEnabled", {
|
|
|
+ get: function () {
|
|
|
+ return this._gizmoSet.rotationGizmo != null;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * If the rotation gizmo is enabled
|
|
|
+ */
|
|
|
+ set: function (value) {
|
|
|
+ if (value) {
|
|
|
+ this._gizmoSet.rotationGizmo = this._gizmoSet.rotationGizmo || new BABYLON.RotationGizmo();
|
|
|
+ this._gizmoSet.rotationGizmo.updateGizmoRotationToMatchAttachedMesh = false;
|
|
|
+ this._gizmoSet.rotationGizmo.attachedMesh = this._attachedMesh;
|
|
|
+ }
|
|
|
+ else if (this._gizmoSet.rotationGizmo) {
|
|
|
+ this._gizmoSet.rotationGizmo.dispose();
|
|
|
+ this._gizmoSet.rotationGizmo = null;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ enumerable: true,
|
|
|
+ configurable: true
|
|
|
+ });
|
|
|
+ Object.defineProperty(GizmoManager.prototype, "scaleGizmoEnabled", {
|
|
|
+ get: function () {
|
|
|
+ return this._gizmoSet.scaleGizmo != null;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * If the scale gizmo is enabled
|
|
|
+ */
|
|
|
+ set: function (value) {
|
|
|
+ if (value) {
|
|
|
+ this._gizmoSet.scaleGizmo = this._gizmoSet.scaleGizmo || new BABYLON.ScaleGizmo();
|
|
|
+ this._gizmoSet.scaleGizmo.attachedMesh = this._attachedMesh;
|
|
|
+ }
|
|
|
+ else if (this._gizmoSet.scaleGizmo) {
|
|
|
+ this._gizmoSet.scaleGizmo.dispose();
|
|
|
+ this._gizmoSet.scaleGizmo = null;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ enumerable: true,
|
|
|
+ configurable: true
|
|
|
+ });
|
|
|
+ Object.defineProperty(GizmoManager.prototype, "boundingBoxGizmoEnabled", {
|
|
|
+ get: function () {
|
|
|
+ return this._gizmoSet.boundingBoxGizmo != null;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * If the boundingBox gizmo is enabled
|
|
|
+ */
|
|
|
+ set: function (value) {
|
|
|
+ if (value) {
|
|
|
+ if (!this._boundingBoxUtilLayer) {
|
|
|
+ this._boundingBoxUtilLayer = new BABYLON.UtilityLayerRenderer(this.scene);
|
|
|
+ this._boundingBoxUtilLayer.utilityLayerScene.autoClearDepthAndStencil = false;
|
|
|
+ }
|
|
|
+ this._gizmoSet.boundingBoxGizmo = this._gizmoSet.boundingBoxGizmo || new BABYLON.BoundingBoxGizmo(this._boundingBoxColor, this._boundingBoxUtilLayer);
|
|
|
+ this._gizmoSet.boundingBoxGizmo.attachedMesh = this._attachedMesh;
|
|
|
+ if (this._attachedMesh) {
|
|
|
+ this._attachedMesh.removeBehavior(this._dragBehavior);
|
|
|
+ this._attachedMesh.addBehavior(this._dragBehavior);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (this._gizmoSet.boundingBoxGizmo) {
|
|
|
+ this._gizmoSet.boundingBoxGizmo.dispose();
|
|
|
+ this._gizmoSet.boundingBoxGizmo = null;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ enumerable: true,
|
|
|
+ configurable: true
|
|
|
+ });
|
|
|
+ /**
|
|
|
* Disposes of the gizmo manager
|
|
|
*/
|
|
|
GizmoManager.prototype.dispose = function () {
|
|
|
this.scene.onPointerObservable.remove(this._pointerObserver);
|
|
|
- this._clearGizmos();
|
|
|
- this._gizmoLayer.dispose();
|
|
|
- };
|
|
|
- GizmoManager.prototype._clearGizmos = function () {
|
|
|
for (var key in this._gizmoSet) {
|
|
|
- if (this._gizmoSet.hasOwnProperty(key)) {
|
|
|
- this._gizmoSet[key].positionGizmo.dispose();
|
|
|
- this._gizmoSet[key].rotationGizmo.dispose();
|
|
|
- delete this._gizmoSet[key];
|
|
|
+ var gizmo = (this._gizmoSet[key]);
|
|
|
+ if (gizmo) {
|
|
|
+ gizmo.dispose();
|
|
|
}
|
|
|
}
|
|
|
+ this._gizmoLayer.dispose();
|
|
|
};
|
|
|
return GizmoManager;
|
|
|
}());
|
|
@@ -92556,6 +92709,7 @@ var BABYLON;
|
|
|
_this._descendants = [];
|
|
|
// Represents device position and rotation in room space. Should only be used to help calculate babylon space values
|
|
|
_this._deviceRoomPosition = BABYLON.Vector3.Zero();
|
|
|
+ /** @hidden */
|
|
|
_this._deviceRoomRotationQuaternion = BABYLON.Quaternion.Identity();
|
|
|
_this._standingMatrix = null;
|
|
|
/**
|