Integrated controller display from tutorial scripts + assets
After Width: | Height: | Size: 788 KiB |
After Width: | Height: | Size: 558 KiB |
BIN
interface/resources/meshes/controller/vive_body.fbx
Normal file
BIN
interface/resources/meshes/controller/vive_button.fbx
Normal file
BIN
interface/resources/meshes/controller/vive_l_grip.fbx
Normal file
BIN
interface/resources/meshes/controller/vive_r_grip.fbx
Normal file
BIN
interface/resources/meshes/controller/vive_sys_button.fbx
Normal file
BIN
interface/resources/meshes/controller/vive_tips.fbm/Blank.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
interface/resources/meshes/controller/vive_tips.fbm/Grip.png
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
interface/resources/meshes/controller/vive_tips.fbm/Rotate.png
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
interface/resources/meshes/controller/vive_tips.fbm/Teleport.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
interface/resources/meshes/controller/vive_tips.fbm/Trigger.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
interface/resources/meshes/controller/vive_tips.fbx
Normal file
BIN
interface/resources/meshes/controller/vive_trackpad.fbx
Normal file
BIN
interface/resources/meshes/controller/vive_trigger.fbx
Normal file
|
@ -37,6 +37,7 @@
|
|||
#include <EntityScriptingInterface.h>
|
||||
#include <MessagesClient.h>
|
||||
#include <NetworkAccessManager.h>
|
||||
#include <PathUtils.h>
|
||||
#include <ResourceScriptingInterface.h>
|
||||
#include <NodeList.h>
|
||||
#include <udt/PacketHeaders.h>
|
||||
|
@ -1136,6 +1137,10 @@ QUrl ScriptEngine::resolvePath(const QString& include) const {
|
|||
return url;
|
||||
}
|
||||
|
||||
QUrl ScriptEngine::resourcesPath() const {
|
||||
return QUrl::fromLocalFile(PathUtils::resourcesPath());
|
||||
}
|
||||
|
||||
void ScriptEngine::print(const QString& message) {
|
||||
emit printedMessage(message);
|
||||
}
|
||||
|
|
|
@ -133,6 +133,7 @@ public:
|
|||
Q_INVOKABLE void clearTimeout(QObject* timer) { stopTimer(reinterpret_cast<QTimer*>(timer)); }
|
||||
Q_INVOKABLE void print(const QString& message);
|
||||
Q_INVOKABLE QUrl resolvePath(const QString& path) const;
|
||||
Q_INVOKABLE QUrl resourcesPath() const;
|
||||
|
||||
// Entity Script Related methods
|
||||
static void loadEntityScript(QWeakPointer<ScriptEngine> theEngine, const EntityItemID& entityID, const QString& entityScript, bool forceRedownload);
|
||||
|
|
186
scripts/system/controllers/controllerDisplay.js
Normal file
|
@ -0,0 +1,186 @@
|
|||
//
|
||||
// controllerDisplay.js
|
||||
//
|
||||
// Created by Anthony J. Thibault on 10/20/16
|
||||
// Originally created by Ryan Huffman on 9/21/2016
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
/* globals createControllerDisplay:true deleteControllerDisplay:true */
|
||||
|
||||
var PARENT_ID = "{00000000-0000-0000-0000-000000000001}";
|
||||
|
||||
function clamp(value, min, max) {
|
||||
if (value < min) {
|
||||
return min;
|
||||
} else if (value > max) {
|
||||
return max;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function resolveHardware(path) {
|
||||
var parts = path.split(".");
|
||||
function resolveInner(base, path, i) {
|
||||
if (i >= path.length) {
|
||||
return base;
|
||||
}
|
||||
return resolveInner(base[path[i]], path, ++i);
|
||||
}
|
||||
return resolveInner(Controller.Hardware, parts, 0);
|
||||
}
|
||||
|
||||
createControllerDisplay = function(config) {
|
||||
var controllerDisplay = {
|
||||
overlays: [],
|
||||
partOverlays: {},
|
||||
parts: {},
|
||||
mappingName: "mapping-display",
|
||||
|
||||
setVisible: function(visible) {
|
||||
for (var i = 0; i < this.overlays.length; ++i) {
|
||||
Overlays.editOverlay(this.overlays[i], {
|
||||
visible: visible
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
setPartVisible: function(partName, visible) {
|
||||
return;
|
||||
if (partName in this.partOverlays) {
|
||||
for (var i = 0; i < this.partOverlays[partName].length; ++i) {
|
||||
Overlays.editOverlay(this.partOverlays[partName][i], {
|
||||
//visible: visible
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setLayerForPart: function(partName, layerName) {
|
||||
if (partName in this.parts) {
|
||||
var part = this.parts[partName];
|
||||
if (part.textureLayers && layerName in part.textureLayers) {
|
||||
var layer = part.textureLayers[layerName];
|
||||
var textures = {};
|
||||
if (layer.defaultTextureURL) {
|
||||
textures[part.textureName] = layer.defaultTextureURL;
|
||||
}
|
||||
for (var i = 0; i < this.partOverlays[partName].length; ++i) {
|
||||
Overlays.editOverlay(this.partOverlays[partName][i], {
|
||||
textures: textures
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
var mapping = Controller.newMapping(controllerDisplay.mappingName);
|
||||
for (var i = 0; i < config.controllers.length; ++i) {
|
||||
var controller = config.controllers[i];
|
||||
var position = controller.position;
|
||||
|
||||
if (controller.naturalPosition) {
|
||||
position = Vec3.sum(Vec3.multiplyQbyV(controller.rotation, controller.naturalPosition), position);
|
||||
}
|
||||
|
||||
var overlayID = Overlays.addOverlay("model", {
|
||||
url: controller.modelURL,
|
||||
dimensions: controller.dimensions,
|
||||
localRotation: controller.rotation,
|
||||
localPosition: position,
|
||||
parentID: PARENT_ID,
|
||||
parentJointIndex: controller.jointIndex,
|
||||
ignoreRayIntersection: true
|
||||
});
|
||||
|
||||
controllerDisplay.overlays.push(overlayID);
|
||||
overlayID = null;
|
||||
|
||||
if (controller.parts) {
|
||||
for (var partName in controller.parts) {
|
||||
var part = controller.parts[partName];
|
||||
var partPosition = Vec3.sum(controller.position, Vec3.multiplyQbyV(controller.rotation, part.naturalPosition));
|
||||
var innerRotation = controller.rotation;
|
||||
|
||||
controllerDisplay.parts[partName] = controller.parts[partName];
|
||||
|
||||
var properties = {
|
||||
url: part.modelURL,
|
||||
localPosition: partPosition,
|
||||
localRotation: innerRotation,
|
||||
parentID: PARENT_ID,
|
||||
parentJointIndex: controller.jointIndex,
|
||||
ignoreRayIntersection: true
|
||||
};
|
||||
|
||||
if (part.defaultTextureLayer) {
|
||||
var textures = {};
|
||||
textures[part.textureName] = part.textureLayers[part.defaultTextureLayer].defaultTextureURL;
|
||||
properties['textures'] = textures;
|
||||
}
|
||||
|
||||
overlayID = Overlays.addOverlay("model", properties);
|
||||
|
||||
if (part.type === "rotational") {
|
||||
mapping.from([part.input]).peek().to(function(controller, overlayID, part) {
|
||||
return function(value) {
|
||||
value = clamp(value, part.minValue, part.maxValue);
|
||||
|
||||
var pct = (value - part.minValue) / part.maxValue;
|
||||
var angle = pct * part.maxAngle;
|
||||
var rotation = Quat.angleAxis(angle, part.axis);
|
||||
|
||||
var offset = { x: 0, y: 0, z: 0 };
|
||||
if (part.origin) {
|
||||
offset = Vec3.multiplyQbyV(rotation, part.origin);
|
||||
offset = Vec3.subtract(offset, part.origin);
|
||||
}
|
||||
|
||||
var partPosition = Vec3.sum(controller.position,
|
||||
Vec3.multiplyQbyV(controller.rotation, Vec3.sum(offset, part.naturalPosition)));
|
||||
|
||||
Overlays.editOverlay(overlayID, {
|
||||
localPosition: partPosition,
|
||||
localRotation: Quat.multiply(controller.rotation, rotation)
|
||||
});
|
||||
};
|
||||
}(controller, overlayID, part));
|
||||
} else if (part.type === "touchpad") {
|
||||
var visibleInput = resolveHardware(part.visibleInput);
|
||||
var xinput = resolveHardware(part.xInput);
|
||||
var yinput = resolveHardware(part.yInput);
|
||||
|
||||
// TODO: Touchpad inputs are currently only working for half
|
||||
// of the touchpad. When that is fixed, it would be useful
|
||||
// to update these to display the current finger position.
|
||||
mapping.from([visibleInput]).peek().to(function(value) {
|
||||
});
|
||||
mapping.from([xinput]).peek().to(function(value) {
|
||||
});
|
||||
mapping.from([yinput]).peek().invert().to(function(value) {
|
||||
});
|
||||
} else if (part.type === "static") {
|
||||
// do nothing
|
||||
} else {
|
||||
print("TYPE NOT SUPPORTED: ", part.type);
|
||||
}
|
||||
|
||||
controllerDisplay.overlays.push(overlayID);
|
||||
if (!(partName in controllerDisplay.partOverlays)) {
|
||||
controllerDisplay.partOverlays[partName] = [];
|
||||
}
|
||||
controllerDisplay.partOverlays[partName].push(overlayID);
|
||||
}
|
||||
}
|
||||
}
|
||||
Controller.enableMapping(controllerDisplay.mappingName);
|
||||
return controllerDisplay;
|
||||
};
|
||||
|
||||
deleteControllerDisplay = function(controllerDisplay) {
|
||||
for (var i = 0; i < controllerDisplay.overlays.length; ++i) {
|
||||
Overlays.deleteOverlay(controllerDisplay.overlays[i]);
|
||||
}
|
||||
Controller.disableMapping(controllerDisplay.mappingName);
|
||||
};
|
150
scripts/system/controllers/controllerDisplayManager.js
Normal file
|
@ -0,0 +1,150 @@
|
|||
//
|
||||
// controllerDisplayManager.js
|
||||
//
|
||||
// Created by Anthony J. Thibault on 10/20/16
|
||||
// Originally created by Ryan Huffman on 9/21/2016
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
/* globals ControllerDisplayManager:true createControllerDisplay deleteControllerDisplay
|
||||
VIVE_CONTROLLER_CONFIGURATION_LEFT VIVE_CONTROLLER_CONFIGURATION_RIGHT */
|
||||
|
||||
Script.include("controllerDisplay.js");
|
||||
Script.include("viveControllerConfiguration.js");
|
||||
|
||||
//
|
||||
// Management of controller display
|
||||
//
|
||||
ControllerDisplayManager = function() {
|
||||
var self = this;
|
||||
var controllerLeft = null;
|
||||
var controllerRight = null;
|
||||
var controllerCheckerIntervalID = null;
|
||||
|
||||
this.setLeftVisible = function(visible) {
|
||||
if (controllerLeft) {
|
||||
controllerLeft.setVisible(visible);
|
||||
}
|
||||
};
|
||||
|
||||
this.setRightVisible = function(visible) {
|
||||
if (controllerRight) {
|
||||
controllerRight.setVisible(visible);
|
||||
}
|
||||
};
|
||||
|
||||
function updateControllers() {
|
||||
if (HMD.active) {
|
||||
if ("Vive" in Controller.Hardware) {
|
||||
if (!controllerLeft) {
|
||||
controllerLeft = createControllerDisplay(VIVE_CONTROLLER_CONFIGURATION_LEFT);
|
||||
}
|
||||
if (!controllerRight) {
|
||||
controllerRight = createControllerDisplay(VIVE_CONTROLLER_CONFIGURATION_RIGHT);
|
||||
}
|
||||
// We've found the controllers, we no longer need to look for active controllers
|
||||
if (controllerCheckerIntervalID) {
|
||||
Script.clearInterval(controllerCheckerIntervalID);
|
||||
controllerCheckerIntervalID = null;
|
||||
}
|
||||
} else {
|
||||
self.deleteControllerDisplays();
|
||||
if (!controllerCheckerIntervalID) {
|
||||
controllerCheckerIntervalID = Script.setInterval(updateControllers, 1000);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We aren't in HMD mode, we no longer need to look for active controllers
|
||||
if (controllerCheckerIntervalID) {
|
||||
Script.clearInterval(controllerCheckerIntervalID);
|
||||
controllerCheckerIntervalID = null;
|
||||
}
|
||||
self.deleteControllerDisplays();
|
||||
}
|
||||
}
|
||||
|
||||
Messages.subscribe('Controller-Display');
|
||||
var handleMessages = function(channel, message, sender) {
|
||||
var i, data, name, visible;
|
||||
if (!controllerLeft && !controllerRight) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sender === MyAvatar.sessionUUID) {
|
||||
if (channel === 'Controller-Display') {
|
||||
data = JSON.parse(message);
|
||||
name = data.name;
|
||||
visible = data.visible;
|
||||
if (controllerLeft) {
|
||||
if (name in controllerLeft.annotations) {
|
||||
for (i = 0; i < controllerLeft.annotations[name].length; ++i) {
|
||||
Overlays.editOverlay(controllerLeft.annotations[name][i], { visible: visible });
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controllerRight) {
|
||||
if (name in controllerRight.annotations) {
|
||||
for (i = 0; i < controllerRight.annotations[name].length; ++i) {
|
||||
Overlays.editOverlay(controllerRight.annotations[name][i], { visible: visible });
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (channel === 'Controller-Display-Parts') {
|
||||
data = JSON.parse(message);
|
||||
for (name in data) {
|
||||
visible = data[name];
|
||||
if (controllerLeft) {
|
||||
controllerLeft.setPartVisible(name, visible);
|
||||
}
|
||||
if (controllerRight) {
|
||||
controllerRight.setPartVisible(name, visible);
|
||||
}
|
||||
}
|
||||
} else if (channel === 'Controller-Set-Part-Layer') {
|
||||
data = JSON.parse(message);
|
||||
for (name in data) {
|
||||
var layer = data[name];
|
||||
if (controllerLeft) {
|
||||
controllerLeft.setLayerForPart(name, layer);
|
||||
}
|
||||
if (controllerRight) {
|
||||
controllerRight.setLayerForPart(name, layer);
|
||||
}
|
||||
}
|
||||
} else if (channel === 'Hifi-Object-Manipulation') {
|
||||
data = JSON.parse(message);
|
||||
visible = data.action !== 'equip';
|
||||
if (data.joint === "LeftHand") {
|
||||
self.setLeftVisible(visible);
|
||||
} else if (data.joint === "RightHand") {
|
||||
self.setRightVisible(visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Messages.messageReceived.connect(handleMessages);
|
||||
|
||||
this.deleteControllerDisplays = function() {
|
||||
if (controllerLeft) {
|
||||
deleteControllerDisplay(controllerLeft);
|
||||
controllerLeft = null;
|
||||
}
|
||||
if (controllerRight) {
|
||||
deleteControllerDisplay(controllerRight);
|
||||
controllerRight = null;
|
||||
}
|
||||
};
|
||||
|
||||
this.destroy = function() {
|
||||
Messages.messageReceived.disconnect(handleMessages);
|
||||
self.deleteControllerDisplays();
|
||||
};
|
||||
|
||||
HMD.displayModeChanged.connect(updateControllers);
|
||||
|
||||
updateControllers();
|
||||
};
|
||||
|
||||
var controllerDisplayManager = new ControllerDisplayManager();
|
|
@ -11,7 +11,10 @@
|
|||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
/* global setEntityCustomData, getEntityCustomData, flatten, Xform, Script, Quat, Vec3, MyAvatar, Entities, Overlays, Settings, Reticle, Controller, Camera, Messages, Mat4, getControllerWorldLocation, getGrabPointSphereOffset, setGrabCommunications */
|
||||
|
||||
/* global setEntityCustomData, getEntityCustomData, flatten, Xform, Script, Quat, Vec3, MyAvatar, Entities, Overlays, Settings,
|
||||
Reticle, Controller, Camera, Messages, Mat4, getControllerWorldLocation, getGrabPointSphereOffset, setGrabCommunications */
|
||||
/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */
|
||||
|
||||
(function() { // BEGIN LOCAL_SCOPE
|
||||
|
||||
|
|
298
scripts/system/controllers/viveControllerConfiguration.js
Normal file
|
@ -0,0 +1,298 @@
|
|||
//
|
||||
// viveControllerConfiguration.js
|
||||
//
|
||||
// Created by Anthony J. Thibault on 10/20/16
|
||||
// Originally created by Ryan Huffman on 9/21/2016
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
/* globals VIVE_CONTROLLER_CONFIGURATION_LEFT:true VIVE_CONTROLLER_CONFIGURATION_RIGHT:true */
|
||||
/* eslint camelcase: ["error", { "properties": "never" }] */
|
||||
|
||||
var LEFT_JOINT_INDEX = MyAvatar.getJointIndex("_CONTROLLER_LEFTHAND");
|
||||
var RIGHT_JOINT_INDEX = MyAvatar.getJointIndex("_CONTROLLER_RIGHTHAND");
|
||||
|
||||
var leftBaseRotation = Quat.multiply(
|
||||
Quat.fromPitchYawRollDegrees(0, 0, 45),
|
||||
Quat.multiply(
|
||||
Quat.fromPitchYawRollDegrees(90, 0, 0),
|
||||
Quat.fromPitchYawRollDegrees(0, 0, 90)
|
||||
)
|
||||
);
|
||||
|
||||
var rightBaseRotation = Quat.multiply(
|
||||
Quat.fromPitchYawRollDegrees(0, 0, -45),
|
||||
Quat.multiply(
|
||||
Quat.fromPitchYawRollDegrees(90, 0, 0),
|
||||
Quat.fromPitchYawRollDegrees(0, 0, -90)
|
||||
)
|
||||
);
|
||||
|
||||
// keep these in sync with the values from plugins/openvr/src/OpenVrHelpers.cpp:303
|
||||
var CONTROLLER_LATERAL_OFFSET = 0.0381;
|
||||
var CONTROLLER_VERTICAL_OFFSET = 0.0495;
|
||||
var CONTROLLER_FORWARD_OFFSET = 0.1371;
|
||||
var leftBasePosition = {
|
||||
x: CONTROLLER_VERTICAL_OFFSET,
|
||||
y: CONTROLLER_FORWARD_OFFSET,
|
||||
z: CONTROLLER_LATERAL_OFFSET
|
||||
};
|
||||
var rightBasePosition = {
|
||||
x: -CONTROLLER_VERTICAL_OFFSET,
|
||||
y: CONTROLLER_FORWARD_OFFSET,
|
||||
z: CONTROLLER_LATERAL_OFFSET
|
||||
};
|
||||
|
||||
var viveNaturalDimensions = {
|
||||
x: 0.1174320001155138,
|
||||
y: 0.08361100335605443,
|
||||
z: 0.21942697931081057
|
||||
};
|
||||
|
||||
var viveNaturalPosition = {
|
||||
x: 0,
|
||||
y: -0.034076502197422087,
|
||||
z: 0.06380049744620919
|
||||
};
|
||||
|
||||
var BASE_URL = Script.resourcesPath();
|
||||
var viveModelURL = BASE_URL + "meshes/controller/vive_body.fbx";
|
||||
var viveTipsModelURL = BASE_URL + "meshes/controller/vive_tips.fbx";
|
||||
|
||||
VIVE_CONTROLLER_CONFIGURATION_LEFT = {
|
||||
name: "Vive",
|
||||
controllers: [
|
||||
{
|
||||
modelURL: viveModelURL,
|
||||
jointIndex: MyAvatar.getJointIndex("_CONTROLLER_LEFTHAND"),
|
||||
naturalPosition: viveNaturalPosition,
|
||||
rotation: leftBaseRotation,
|
||||
position: Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, 0, 45), leftBasePosition),
|
||||
|
||||
dimensions: viveNaturalDimensions,
|
||||
|
||||
parts: {
|
||||
tips: {
|
||||
type: "static",
|
||||
modelURL: viveTipsModelURL,
|
||||
naturalPosition: {"x":-0.004377640783786774,"y":-0.034371938556432724,"z":0.06769277155399323},
|
||||
|
||||
textureName: "Tex.Blank",
|
||||
|
||||
defaultTextureLayer: "blank",
|
||||
textureLayers: {
|
||||
blank: {
|
||||
defaultTextureURL: viveTipsModelURL + "meshes/Controller-Tips.fbm/Blank.png"
|
||||
},
|
||||
trigger: {
|
||||
defaultTextureURL: viveTipsModelURL + "meshes/Controller-Tips.fbm/Trigger.png"
|
||||
},
|
||||
arrows: {
|
||||
defaultTextureURL: viveTipsModelURL + "meshes/Controller-Tips.fbm/Rotate.png"
|
||||
},
|
||||
grip: {
|
||||
defaultTextureURL: viveTipsModelURL + "meshes/Controller-Tips.fbm/Grip.png"
|
||||
},
|
||||
teleport: {
|
||||
defaultTextureURL: viveTipsModelURL + "meshes/Controller-Tips.fbm/Teleport.png"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// The touchpad type draws a dot indicating the current touch/thumb position
|
||||
// and swaps in textures based on the thumb position.
|
||||
touchpad: {
|
||||
type: "touchpad",
|
||||
modelURL: BASE_URL + "meshes/controller/vive_trackpad.fbx",
|
||||
visibleInput: "Vive.RSTouch",
|
||||
xInput: "Vive.LX",
|
||||
yInput: "Vive.LY",
|
||||
naturalPosition: {"x":0,"y":0.000979491975158453,"z":0.04872849956154823},
|
||||
minValue: 0.0,
|
||||
maxValue: 1.0,
|
||||
minPosition: { x: -0.035, y: 0.004, z: -0.005 },
|
||||
maxPosition: { x: -0.035, y: 0.004, z: -0.005 },
|
||||
disable_textureName: "Tex.touchpad-blank",
|
||||
|
||||
disable_defaultTextureLayer: "blank",
|
||||
disable_textureLayers: {
|
||||
blank: {
|
||||
defaultTextureURL: BASE_URL + "meshes/controller/vive_trackpad.fbx/Touchpad.fbm/touchpad-blank.jpg"
|
||||
},
|
||||
teleport: {
|
||||
defaultTextureURL: BASE_URL + "meshes/controller/vive_trackpad.fbx/Touchpad.fbm/touchpad-teleport-active-LG.jpg"
|
||||
},
|
||||
arrows: {
|
||||
defaultTextureURL: BASE_URL + "meshes/controller/vive_trackpad.fbx/Touchpad.fbm/touchpad-look-arrows.jpg"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
trigger: {
|
||||
type: "rotational",
|
||||
modelURL: BASE_URL + "meshes/controller/vive_trigger.fbx",
|
||||
input: Controller.Standard.LT,
|
||||
naturalPosition: {"x":0.000004500150680541992,"y":-0.027690507471561432,"z":0.04830199480056763},
|
||||
origin: { x: 0, y: -0.015, z: -0.00 },
|
||||
minValue: 0.0,
|
||||
maxValue: 1.0,
|
||||
axis: { x: -1, y: 0, z: 0 },
|
||||
maxAngle: 20
|
||||
},
|
||||
|
||||
l_grip: {
|
||||
type: "static",
|
||||
modelURL: BASE_URL + "meshes/controller/vive_l_grip.fbx",
|
||||
naturalPosition: {"x":-0.01720449887216091,"y":-0.014324013143777847,"z":0.08714400231838226}
|
||||
},
|
||||
|
||||
r_grip: {
|
||||
type: "static",
|
||||
modelURL: BASE_URL + "meshes/controller/vive_r_grip.fbx",
|
||||
naturalPosition: {"x":0.01720449887216091,"y":-0.014324013143777847,"z":0.08714400231838226}
|
||||
},
|
||||
|
||||
sys_button: {
|
||||
type: "static",
|
||||
modelURL: BASE_URL + "meshes/controller/vive_sys_button.fbx",
|
||||
naturalPosition: {"x":0,"y":0.0020399854984134436,"z":0.08825899660587311}
|
||||
},
|
||||
|
||||
button: {
|
||||
type: "static",
|
||||
modelURL: BASE_URL + "meshes/controller/vive_button.fbx",
|
||||
naturalPosition: {"x":0,"y":0.005480996798723936,"z":0.019918499514460564}
|
||||
},
|
||||
button2: {
|
||||
type: "static",
|
||||
modelURL: BASE_URL + "meshes/controller/vive_button.fbx",
|
||||
naturalPosition: {"x":0,"y":0.005480996798723936,"z":0.019918499514460564}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
VIVE_CONTROLLER_CONFIGURATION_RIGHT = {
|
||||
name: "Vive Right",
|
||||
controllers: [
|
||||
{
|
||||
modelURL: viveModelURL,
|
||||
jointIndex: MyAvatar.getJointIndex("_CONTROLLER_RIGHTHAND"),
|
||||
|
||||
rotation: rightBaseRotation,
|
||||
position: Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, 0, -45), rightBasePosition),
|
||||
|
||||
dimensions: viveNaturalDimensions,
|
||||
|
||||
naturalPosition: {
|
||||
x: 0,
|
||||
y: -0.034076502197422087,
|
||||
z: 0.06380049744620919
|
||||
},
|
||||
|
||||
parts: {
|
||||
tips: {
|
||||
type: "static",
|
||||
modelURL: viveTipsModelURL,
|
||||
naturalPosition: {"x":-0.004377640783786774,"y":-0.034371938556432724,"z":0.06769277155399323},
|
||||
|
||||
textureName: "Tex.Blank",
|
||||
|
||||
defaultTextureLayer: "blank",
|
||||
textureLayers: {
|
||||
blank: {
|
||||
defaultTextureURL: viveTipsModelURL + "meshes/Controller-Tips.fbm/Blank.png"
|
||||
},
|
||||
trigger: {
|
||||
defaultTextureURL: viveTipsModelURL + "meshes/Controller-Tips.fbm/Trigger.png"
|
||||
},
|
||||
arrows: {
|
||||
defaultTextureURL: viveTipsModelURL + "meshes/Controller-Tips.fbm/Rotate.png"
|
||||
},
|
||||
grip: {
|
||||
defaultTextureURL: viveTipsModelURL + "meshes/Controller-Tips.fbm/Grip.png"
|
||||
},
|
||||
teleport: {
|
||||
defaultTextureURL: viveTipsModelURL + "meshes/Controller-Tips.fbm/Teleport.png"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// The touchpad type draws a dot indicating the current touch/thumb position
|
||||
// and swaps in textures based on the thumb position.
|
||||
touchpad: {
|
||||
type: "touchpad",
|
||||
modelURL: BASE_URL + "meshes/controller/vive_trackpad.fbx",
|
||||
visibleInput: "Vive.RSTouch",
|
||||
xInput: "Vive.RX",
|
||||
yInput: "Vive.RY",
|
||||
naturalPosition: { x: 0, y: 0.000979491975158453, z: 0.04872849956154823 },
|
||||
minValue: 0.0,
|
||||
maxValue: 1.0,
|
||||
minPosition: { x: -0.035, y: 0.004, z: -0.005 },
|
||||
maxPosition: { x: -0.035, y: 0.004, z: -0.005 },
|
||||
disable_textureName: "Tex.touchpad-blank",
|
||||
|
||||
disable_defaultTextureLayer: "blank",
|
||||
disable_textureLayers: {
|
||||
blank: {
|
||||
defaultTextureURL: BASE_URL + "meshes/controller/vive_trackpad.fbx/Touchpad.fbm/touchpad-blank.jpg"
|
||||
},
|
||||
teleport: {
|
||||
defaultTextureURL: BASE_URL + "meshes/controller/vive_trackpad.fbx/Touchpad.fbm/touchpad-teleport-active-LG.jpg"
|
||||
},
|
||||
arrows: {
|
||||
defaultTextureURL: BASE_URL + "meshes/controller/vive_trackpad.fbx/Touchpad.fbm/touchpad-look-arrows-active.jpg"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
trigger: {
|
||||
type: "rotational",
|
||||
modelURL: BASE_URL + "meshes/controller/vive_trigger.fbx",
|
||||
input: Controller.Standard.RT,
|
||||
naturalPosition: {"x":0.000004500150680541992,"y":-0.027690507471561432,"z":0.04830199480056763},
|
||||
origin: { x: 0, y: -0.015, z: -0.00 },
|
||||
minValue: 0.0,
|
||||
maxValue: 1.0,
|
||||
axis: { x: -1, y: 0, z: 0 },
|
||||
maxAngle: 25
|
||||
},
|
||||
|
||||
l_grip: {
|
||||
type: "static",
|
||||
modelURL: BASE_URL + "meshes/controller/vive_l_grip.fbx",
|
||||
naturalPosition: {"x":-0.01720449887216091,"y":-0.014324013143777847,"z":0.08714400231838226}
|
||||
},
|
||||
|
||||
r_grip: {
|
||||
type: "static",
|
||||
modelURL: BASE_URL + "meshes/controller/vive_r_grip.fbx",
|
||||
naturalPosition: {"x":0.01720449887216091,"y":-0.014324013143777847,"z":0.08714400231838226}
|
||||
},
|
||||
|
||||
sys_button: {
|
||||
type: "static",
|
||||
modelURL: BASE_URL + "meshes/controller/vive_sys_button.fbx",
|
||||
naturalPosition: {"x":0,"y":0.0020399854984134436,"z":0.08825899660587311}
|
||||
},
|
||||
|
||||
button: {
|
||||
type: "static",
|
||||
modelURL: BASE_URL + "meshes/controller/vive_button.fbx",
|
||||
naturalPosition: {"x":0,"y":0.005480996798723936,"z":0.019918499514460564}
|
||||
},
|
||||
button2: {
|
||||
type: "static",
|
||||
modelURL: BASE_URL + "meshes/controller/vive_button.fbx",
|
||||
naturalPosition: {"x":0,"y":0.005480996798723936,"z":0.019918499514460564}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|