mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
springhold, touch, nBody tutorial scripts
This commit is contained in:
parent
c74778116a
commit
6bec948457
4 changed files with 453 additions and 0 deletions
59
scripts/tutorials/createSwords.js
Normal file
59
scripts/tutorials/createSwords.js
Normal file
|
@ -0,0 +1,59 @@
|
|||
// createSwords.js
|
||||
//
|
||||
// Created by Philip Rosedale on April 9, 2017
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
// Makes two grabbable 'swords' in front of the user, that can be held and used
|
||||
// to hit the other. Demonstration of an action that would allow two people to hold
|
||||
// entities that are also colliding.
|
||||
//
|
||||
|
||||
var COLOR = { red: 255, green: 0, blue: 0 };
|
||||
var SIZE = { x: 0.10, y: 1.5, z: 0.10 };
|
||||
|
||||
var SCRIPT_URL = Script.resolvePath("entity_scripts/springHold.js");
|
||||
|
||||
function inFrontOfMe(distance) {
|
||||
return Vec3.sum(Camera.getPosition(), Vec3.multiply(distance, Quat.getForward(Camera.getOrientation())));
|
||||
}
|
||||
|
||||
var sword1 = Entities.addEntity({
|
||||
type: "Box",
|
||||
name: "Sword1",
|
||||
position: inFrontOfMe(2 * SIZE.y),
|
||||
dimensions: SIZE,
|
||||
color: COLOR,
|
||||
angularDamping: 0,
|
||||
damping: 0,
|
||||
script: SCRIPT_URL,
|
||||
userData:JSON.stringify({
|
||||
grabbableKey:{
|
||||
grabbable:true
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
var sword2 = Entities.addEntity({
|
||||
type: "Box",
|
||||
name: "Sword2",
|
||||
position: inFrontOfMe(3 * SIZE.y),
|
||||
dimensions: SIZE,
|
||||
color: COLOR,
|
||||
angularDamping: 0,
|
||||
damping: 0,
|
||||
script: SCRIPT_URL,
|
||||
userData:JSON.stringify({
|
||||
grabbableKey:{
|
||||
grabbable:true
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Script.scriptEnding.connect(function scriptEnding() {
|
||||
Entities.deleteEntity(sword1);
|
||||
Entities.deleteEntity(sword2);
|
||||
});
|
||||
|
121
scripts/tutorials/entity_scripts/springHold.js
Normal file
121
scripts/tutorials/entity_scripts/springHold.js
Normal file
|
@ -0,0 +1,121 @@
|
|||
//
|
||||
// springHold.js
|
||||
//
|
||||
// Created by Philip Rosedale on March 18, 2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Attach this entity script to a model or basic shape and grab it. The object will
|
||||
// follow your hand like a spring, allowing you, for example, to swordfight with others.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
(function() {
|
||||
|
||||
var TIMESCALE = 0.03;
|
||||
var ACTION_TTL = 10;
|
||||
var _this;
|
||||
|
||||
function SpringHold() {
|
||||
_this = this;
|
||||
}
|
||||
|
||||
function updateSpringAction(timescale) {
|
||||
|
||||
var targetProps = Entities.getEntityProperties(_this.entityID);
|
||||
var props = {
|
||||
targetPosition: targetProps.position,
|
||||
targetRotation: targetProps.rotation,
|
||||
linearTimeScale: timescale,
|
||||
angularTimeScale: timescale,
|
||||
ttl: ACTION_TTL
|
||||
};
|
||||
var success = Entities.updateAction(_this.copy, _this.actionID, props);
|
||||
return;
|
||||
}
|
||||
|
||||
function createSpringAction(timescale) {
|
||||
|
||||
var targetProps = Entities.getEntityProperties(_this.entityID);
|
||||
var props = {
|
||||
targetPosition: targetProps.position,
|
||||
targetRotation: targetProps.rotation,
|
||||
linearTimeScale: timescale,
|
||||
angularTimeScale: timescale,
|
||||
ttl: ACTION_TTL
|
||||
};
|
||||
_this.actionID = Entities.addAction("spring", _this.copy, props);
|
||||
return;
|
||||
}
|
||||
|
||||
function createCopy() {
|
||||
var originalProps = Entities.getEntityProperties(_this.entityID);
|
||||
var props = {
|
||||
type: originalProps.type,
|
||||
color: originalProps.color,
|
||||
modelURL: originalProps.modelURL,
|
||||
dimensions: originalProps.dimensions,
|
||||
dynamic: true,
|
||||
damping: 0.0,
|
||||
angularDamping: 0.0,
|
||||
collidesWith: 'dynamic,static,kinematic',
|
||||
rotation: originalProps.rotation,
|
||||
position: originalProps.position,
|
||||
shapeType: originalProps.shapeType,
|
||||
visible: true,
|
||||
userData:JSON.stringify({
|
||||
grabbableKey:{
|
||||
grabbable:false
|
||||
}
|
||||
})
|
||||
}
|
||||
_this.copy = Entities.addEntity(props);
|
||||
}
|
||||
|
||||
function deleteCopy() {
|
||||
print("Delete copy");
|
||||
Entities.deleteEntity(_this.copy);
|
||||
}
|
||||
|
||||
function makeOriginalInvisible() {
|
||||
Entities.editEntity(_this.entityID, {
|
||||
visible: false,
|
||||
collisionless: true
|
||||
});
|
||||
}
|
||||
|
||||
function makeOriginalVisible() {
|
||||
Entities.editEntity(_this.entityID, {
|
||||
visible: true,
|
||||
collisionless: false
|
||||
});
|
||||
}
|
||||
|
||||
function deleteSpringAction() {
|
||||
Entities.deleteAction(_this.copy, _this.actionID);
|
||||
}
|
||||
|
||||
SpringHold.prototype = {
|
||||
preload: function(entityID) {
|
||||
_this.entityID = entityID;
|
||||
},
|
||||
startNearGrab: function(entityID, data) {
|
||||
print("start spring grab");
|
||||
createCopy();
|
||||
createSpringAction(TIMESCALE);
|
||||
makeOriginalInvisible();
|
||||
},
|
||||
continueNearGrab: function() {
|
||||
updateSpringAction(TIMESCALE);
|
||||
},
|
||||
releaseGrab: function() {
|
||||
print("end spring grab");
|
||||
deleteSpringAction();
|
||||
deleteCopy();
|
||||
makeOriginalVisible();
|
||||
}
|
||||
};
|
||||
|
||||
return new SpringHold();
|
||||
});
|
207
scripts/tutorials/entity_scripts/touch.js
Normal file
207
scripts/tutorials/entity_scripts/touch.js
Normal file
|
@ -0,0 +1,207 @@
|
|||
(function() {
|
||||
|
||||
// touch.js
|
||||
//
|
||||
// Sample file using spring action, haptic vibration, and color change to demonstrate two spheres
|
||||
// That can give a sense of touch to the holders.
|
||||
// Create two standard spheres, make them grabbable, and attach this entity script. Grab them and touch them together.
|
||||
//
|
||||
// Created by Philip Rosedale on March 18, 2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var TIMESCALE = 0.03;
|
||||
var ACTION_TTL = 10;
|
||||
var _this;
|
||||
|
||||
var RIGHT_HAND = 1;
|
||||
var LEFT_HAND = 0;
|
||||
var HAPTIC_PULSE_FIRST_STRENGTH = 0.5;
|
||||
var HAPTIC_PULSE_MIN_STRENGTH = 0.20;
|
||||
var HAPTIC_PULSE_MAX_STRENGTH = 0.5;
|
||||
var HAPTIC_PULSE_FIRST_DURATION = 1.0;
|
||||
var HAPTIC_PULSE_DURATION = 16.0;
|
||||
var HAPTIC_PULSE_DISTANCE = 0.0;
|
||||
var MAX_PENETRATION = 0.02;
|
||||
var HAPTIC_MIN_VELOCITY = 0.002;
|
||||
var HAPTIC_MAX_VELOCITY = 0.5;
|
||||
var PENETRATION_PULLBACK_FACTOR = 0.65;
|
||||
var FRAME_TIME = 0.016;
|
||||
|
||||
var isColliding = false;
|
||||
|
||||
var hand = LEFT_HAND;
|
||||
var lastHapticPulseLocation = { x:0, y:0, z:0 };
|
||||
|
||||
|
||||
var GRAY = { red: 128, green: 128, blue: 128 };
|
||||
var RED = { red: 255, green: 0, blue: 0 };
|
||||
|
||||
var targetColor = { x: GRAY.red, y: GRAY.green, z: GRAY.blue };
|
||||
|
||||
var lastPosition = { x: 0, y: 0, z: 0 };
|
||||
var velocity = { x: 0, y: 0, z: 0 };
|
||||
|
||||
var lastOtherPosition = { x: 0, y: 0, z: 0 };
|
||||
var otherVelocity = { x: 0, y: 0, z: 0 };
|
||||
|
||||
|
||||
function TouchExample() {
|
||||
_this = this;
|
||||
}
|
||||
|
||||
function updateSpringAction(timescale) {
|
||||
var targetProps = Entities.getEntityProperties(_this.entityID);
|
||||
//
|
||||
// Look for nearby entities to touch
|
||||
//
|
||||
var copyProps = Entities.getEntityProperties(_this.copy);
|
||||
var nearbyEntities = Entities.findEntities(copyProps.position, copyProps.dimensions.x * 2);
|
||||
var wasColliding = isColliding;
|
||||
var targetAdjust = { x: 0, y: 0, z: 0 };
|
||||
|
||||
isColliding = false;
|
||||
for (var i = 0; i < nearbyEntities.length; i++) {
|
||||
if (_this.copy != nearbyEntities[i] && _this.entityID != nearbyEntities[i]) {
|
||||
var otherProps = Entities.getEntityProperties(nearbyEntities[i]);
|
||||
var penetration = Vec3.distance(copyProps.position, otherProps.position) - (copyProps.dimensions.x / 2 + otherProps.dimensions.x / 2);
|
||||
if (otherProps.type === 'Sphere' && penetration < 0 && penetration > -copyProps.dimensions.x * 3) {
|
||||
isColliding = true;
|
||||
targetAdjust = Vec3.sum(targetAdjust, Vec3.multiply(Vec3.normalize(Vec3.subtract(targetProps.position, otherProps.position)), -penetration * PENETRATION_PULLBACK_FACTOR));
|
||||
if (!wasColliding && false) {
|
||||
targetColor = { x: RED.red, y: RED.green, z: RED.blue };
|
||||
} else {
|
||||
targetColor = { x: 200 + Math.min(-penetration / MAX_PENETRATION, 1.0) * 55, y: GRAY.green, z: GRAY.blue };
|
||||
}
|
||||
if (Vec3.distance(targetProps.position, lastHapticPulseLocation) > HAPTIC_PULSE_DISTANCE || !wasColliding) {
|
||||
if (!wasColliding) {
|
||||
velocity = { x: 0, y: 0, z: 0};
|
||||
otherVelocity = { x: 0, y: 0, z: 0 };
|
||||
Controller.triggerHapticPulse(HAPTIC_PULSE_FIRST_STRENGTH, HAPTIC_PULSE_FIRST_DURATION, hand);
|
||||
} else {
|
||||
velocity = Vec3.distance(targetProps.position, lastPosition) / FRAME_TIME;
|
||||
otherVelocity = Vec3.distance(otherProps.position, lastOtherPosition) / FRAME_TIME;
|
||||
var velocityStrength = Math.min(velocity + otherVelocity / HAPTIC_MAX_VELOCITY, 1.0);
|
||||
var strength = HAPTIC_PULSE_MIN_STRENGTH + Math.min(-penetration / MAX_PENETRATION, 1.0) * (HAPTIC_PULSE_MAX_STRENGTH - HAPTIC_PULSE_MIN_STRENGTH);
|
||||
Controller.triggerHapticPulse(velocityStrength * strength, HAPTIC_PULSE_DURATION, hand);
|
||||
}
|
||||
lastPosition = targetProps.position;
|
||||
lastOtherPosition = otherProps.position;
|
||||
lastHapticPulseLocation = targetProps.position;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((wasColliding != isColliding) && !isColliding) {
|
||||
targetColor = { x: GRAY.red, y: GRAY.green, z: GRAY.blue };
|
||||
}
|
||||
// Interpolate color toward target color
|
||||
var currentColor = { x: copyProps.color.red, y: copyProps.color.green, z: copyProps.color.blue };
|
||||
var newColor = Vec3.sum(currentColor, Vec3.multiply(Vec3.subtract(targetColor, currentColor), 0.1));
|
||||
Entities.editEntity(_this.copy, { color: { red: newColor.x, green: newColor.y, blue: newColor.z } });
|
||||
|
||||
var props = {
|
||||
targetPosition: Vec3.sum(targetProps.position, targetAdjust),
|
||||
targetRotation: targetProps.rotation,
|
||||
linearTimeScale: timescale,
|
||||
angularTimeScale: timescale,
|
||||
ttl: ACTION_TTL
|
||||
};
|
||||
var success = Entities.updateAction(_this.copy, _this.actionID, props);
|
||||
return;
|
||||
}
|
||||
|
||||
function createSpringAction(timescale) {
|
||||
|
||||
var targetProps = Entities.getEntityProperties(_this.entityID);
|
||||
var props = {
|
||||
targetPosition: targetProps.position,
|
||||
targetRotation: targetProps.rotation,
|
||||
linearTimeScale: timescale,
|
||||
angularTimeScale: timescale,
|
||||
ttl: ACTION_TTL
|
||||
};
|
||||
_this.actionID = Entities.addAction("spring", _this.copy, props);
|
||||
return;
|
||||
}
|
||||
|
||||
function createCopy() {
|
||||
var originalProps = Entities.getEntityProperties(_this.entityID);
|
||||
var props = {
|
||||
type: originalProps.type,
|
||||
modelURL: originalProps.modelURL,
|
||||
dimensions: originalProps.dimensions,
|
||||
color: GRAY,
|
||||
dynamic: true,
|
||||
damping: 0.0,
|
||||
angularDamping: 0.0,
|
||||
collidesWith: 'static',
|
||||
rotation: originalProps.rotation,
|
||||
position: originalProps.position,
|
||||
shapeType: originalProps.shapeType,
|
||||
visible: true,
|
||||
userData:JSON.stringify({
|
||||
grabbableKey:{
|
||||
grabbable:false
|
||||
}
|
||||
})
|
||||
}
|
||||
_this.copy = Entities.addEntity(props);
|
||||
}
|
||||
|
||||
function deleteCopy() {
|
||||
print("Delete copy");
|
||||
Entities.deleteEntity(_this.copy);
|
||||
}
|
||||
|
||||
function makeOriginalInvisible() {
|
||||
Entities.editEntity(_this.entityID, {
|
||||
visible: false,
|
||||
collisionless: true
|
||||
});
|
||||
}
|
||||
|
||||
function makeOriginalVisible() {
|
||||
Entities.editEntity(_this.entityID, {
|
||||
visible: true,
|
||||
collisionless: false
|
||||
});
|
||||
}
|
||||
|
||||
function deleteSpringAction() {
|
||||
Entities.deleteAction(_this.copy, _this.actionID);
|
||||
}
|
||||
|
||||
function setHand(position) {
|
||||
if (Vec3.distance(MyAvatar.getLeftPalmPosition(), position) < Vec3.distance(MyAvatar.getRightPalmPosition(), position)) {
|
||||
hand = LEFT_HAND;
|
||||
} else {
|
||||
hand = RIGHT_HAND;
|
||||
}
|
||||
}
|
||||
|
||||
TouchExample.prototype = {
|
||||
preload: function(entityID) {
|
||||
_this.entityID = entityID;
|
||||
},
|
||||
startNearGrab: function(entityID, data) {
|
||||
createCopy();
|
||||
createSpringAction(TIMESCALE);
|
||||
makeOriginalInvisible();
|
||||
setHand(Entities.getEntityProperties(_this.entityID).position);
|
||||
},
|
||||
continueNearGrab: function() {
|
||||
updateSpringAction(TIMESCALE);
|
||||
},
|
||||
releaseGrab: function() {
|
||||
deleteSpringAction();
|
||||
deleteCopy();
|
||||
makeOriginalVisible();
|
||||
}
|
||||
};
|
||||
|
||||
return new TouchExample();
|
||||
});
|
66
scripts/tutorials/nBody.js
Normal file
66
scripts/tutorials/nBody.js
Normal file
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// nBody.js
|
||||
// examples
|
||||
//
|
||||
// Created by Philip Rosedale on March 18, 2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Create some spheres that obey gravity, which is great to teach physics.
|
||||
// You can control how many to create by changing the value of 'n' below.
|
||||
// Grab them and watch the others move around.
|
||||
//
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var bodies = [];
|
||||
var n = 3;
|
||||
var radius = 0.1;
|
||||
var G = 0.25;
|
||||
var EARTH = "https://s3-us-west-1.amazonaws.com/hifi-content/seth/production/NBody/earth.fbx";
|
||||
var MOON = "https://s3-us-west-1.amazonaws.com/hifi-content/seth/production/NBody/moon.fbx";
|
||||
|
||||
var COLOR1 = { red: 51, green: 51, blue: 255 };
|
||||
var COLOR2 = { red: 51, green: 51, blue: 255 };
|
||||
var COLOR3 = { red: 51, green: 51, blue: 255 };
|
||||
|
||||
var inFront = Vec3.sum(Camera.getPosition(), Vec3.multiply(radius * 20, Quat.getFront(Camera.getOrientation())));
|
||||
|
||||
for (var i = 0; i < n; i++) {
|
||||
bodies.push(Entities.addEntity({
|
||||
type: "Model",
|
||||
modelURL: (i == 0) ? EARTH : MOON,
|
||||
shapeType: "sphere",
|
||||
dimensions: { x: radius * 2, y: radius * 2, z: radius * 2},
|
||||
position: Vec3.sum(inFront, { x: 0, y: i * 2 * radius, z: 0 }),
|
||||
gravity: { x: 0, y: 0, z: 0 },
|
||||
damping: 0.0,
|
||||
angularDamping: 0.0,
|
||||
dynamic: true
|
||||
}));
|
||||
}
|
||||
|
||||
Script.update.connect(function(dt) {
|
||||
var props = [];
|
||||
for (var i = 0; i < n; i++) {
|
||||
props.push(Entities.getEntityProperties(bodies[i]));
|
||||
}
|
||||
for (var i = 0; i < n; i++) {
|
||||
if (props[i].dynamic) {
|
||||
var dv = { x: 0, y: 0, z: 0};
|
||||
for (var j = 0; j < n; j++) {
|
||||
if (i != j) {
|
||||
dv = Vec3.sum(dv, Vec3.multiply(G * dt / Vec3.distance(props[i].position, props[j].position), Vec3.normalize(Vec3.subtract(props[j].position, props[i].position))));
|
||||
}
|
||||
}
|
||||
Entities.editEntity(bodies[i], { velocity: Vec3.sum(props[i].velocity, dv)});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Script.scriptEnding.connect(function scriptEnding() {
|
||||
for (var i = 0; i < n; i++) {
|
||||
Entities.deleteEntity(bodies[i]);
|
||||
}
|
||||
});
|
Loading…
Reference in a new issue