Merge branch 'master' of https://github.com/highfidelity/hifi into hdr

This commit is contained in:
samcake 2016-01-15 14:44:57 -08:00
commit fef5e3c8da
3 changed files with 130 additions and 200 deletions

View file

@ -93,7 +93,7 @@ var ZERO_VEC = {
z: 0
};
var NULL_ACTION_ID = "{00000000-0000-0000-000000000000}";
var NULL_UUID = "{00000000-0000-0000-0000-000000000000}";
var MSEC_PER_SEC = 1000.0;
// these control how long an abandoned pointer line or action will hang around
@ -109,7 +109,10 @@ var GRABBABLE_PROPERTIES = [
"collisionMask",
"collisionsWillMove",
"locked",
"name"
"name",
"shapeType",
"parentID",
"parentJointIndex"
];
var GRABBABLE_DATA_KEY = "grabbableKey"; // shared with grab.js
@ -117,9 +120,11 @@ var GRAB_USER_DATA_KEY = "grabKey"; // shared with grab.js
var DEFAULT_GRABBABLE_DATA = {
grabbable: true,
disableReleaseVelocity: false
};
// sometimes we want to exclude objects from being picked
var USE_BLACKLIST = true;
var blacklist = [];
@ -160,7 +165,6 @@ var STATE_EQUIP_SPRING = 16;
// the possible list of names is: static, dynamic, kinematic, myAvatar, otherAvatar
var COLLISION_MASK_WHILE_GRABBED = "dynamic,otherAvatar";
function stateToName(state) {
switch (state) {
case STATE_OFF:
@ -279,8 +283,6 @@ function MyController(hand) {
var SPATIAL_CONTROLLERS_PER_PALM = 2;
var TIP_CONTROLLER_OFFSET = 1;
this.palm = SPATIAL_CONTROLLERS_PER_PALM * hand;
this.tip = SPATIAL_CONTROLLERS_PER_PALM * hand + TIP_CONTROLLER_OFFSET;
this.actionID = null; // action this script created...
this.grabbedEntity = null; // on this entity.
@ -726,6 +728,10 @@ function MyController(hand) {
}
};
this.propsArePhysical = function(props) {
var isPhysical = (props.shapeType && props.shapeType != 'none');
return isPhysical;
}
this.turnOffVisualizations = function() {
if (USE_ENTITY_LINES_FOR_SEARCHING === true || USE_ENTITY_LINES_FOR_MOVING === true) {
@ -800,7 +806,6 @@ function MyController(hand) {
// the trigger is being pressed, so do a ray test to see what we are hitting
var handPosition = this.getHandPosition();
var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand;
var currentHandRotation = Controller.getPoseValue(controllerHandInput).rotation;
var handDeltaRotation = Quat.multiply(currentHandRotation, Quat.inverse(this.startingHandRotation));
@ -825,6 +830,9 @@ function MyController(hand) {
this.lastPickTime = now;
}
rayPickedCandidateEntities = []; // the list of candidates to consider grabbing
this.intersectionDistance = 0.0;
for (var index = 0; index < pickRays.length; ++index) {
var pickRay = pickRays[index];
var directionNormalized = Vec3.normalize(pickRay.direction);
@ -834,14 +842,6 @@ function MyController(hand) {
direction: pickRay.direction
};
if (WANT_DEBUG) {
this.debugLine(pickRayBacked.origin, Vec3.multiply(pickRayBacked.direction, NEAR_PICK_MAX_DISTANCE), {
red: 0,
green: 255,
blue: 0
})
}
Messages.sendMessage('Hifi-Light-Overlay-Ray-Check', JSON.stringify(pickRayBacked));
var intersection;
@ -852,189 +852,85 @@ function MyController(hand) {
intersection = Entities.findRayIntersection(pickRayBacked, true);
}
if (intersection.intersects) {
// the ray is intersecting something we can move.
rayPickedCandidateEntities.push(intersection.entityID);
this.intersectionDistance = Vec3.distance(pickRay.origin, intersection.intersection);
var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, intersection.entityID, DEFAULT_GRABBABLE_DATA);
var defaultDisableNearGrabData = {
disableNearGrab: false
};
//sometimes we want things to stay right where they are when we let go.
var disableNearGrabData = getEntityCustomData('handControllerKey', intersection.entityID, defaultDisableNearGrabData);
if (intersection.properties.name == "Grab Debug Entity") {
continue;
}
if (typeof grabbableData.grabbable !== 'undefined' && !grabbableData.grabbable) {
continue;
}
if (this.intersectionDistance > pickRay.length) {
// too far away for this ray.
continue;
}
if (this.intersectionDistance <= NEAR_PICK_MAX_DISTANCE) {
// the hand is very close to the intersected object. go into close-grabbing mode.
if (grabbableData.wantsTrigger) {
this.grabbedEntity = intersection.entityID;
this.setState(STATE_NEAR_TRIGGER);
return;
} else if (!intersection.properties.locked) {
this.grabbedEntity = intersection.entityID;
if (this.state == STATE_SEARCHING) {
if (disableNearGrabData.disableNearGrab !== true) {
this.setState(STATE_NEAR_GRABBING);
} else {
//disable near grab on this thing
}
} else { // equipping
if (typeof grabbableData.spatialKey !== 'undefined') {
// TODO
// if we go to STATE_EQUIP_SPRING the item will be pulled to the hand and will then switch
// to STATE_EQUIP. This needs some debugging, so just jump straight to STATE_EQUIP here.
// this.setState(STATE_EQUIP_SPRING);
this.setState(STATE_EQUIP);
} else {
this.setState(STATE_EQUIP);
}
}
return;
}
} else if (!entityIsGrabbedByOther(intersection.entityID)) {
// don't allow two people to distance grab the same object
if (intersection.properties.collisionsWillMove && !intersection.properties.locked) {
// the hand is far from the intersected object. go into distance-holding mode
this.grabbedEntity = intersection.entityID;
if (this.state == STATE_EQUIP_SEARCHING) {
// if a distance pick in equip mode hits something with a spatialKey, equip it
// TODO use STATE_EQUIP_SPRING here once it works right.
// this.setState(STATE_EQUIP_SPRING);
if (typeof grabbableData.spatialKey === 'undefined') {
// We want to give a temporary position offset to this object so it is pulled close to hand
var intersectionPointToCenterDistance = Vec3.length(Vec3.subtract(intersection.intersection, intersection.properties.position));
this.temporaryPositionOffset = Vec3.normalize(Vec3.subtract(intersection.properties.position, handPosition));
this.temporaryPositionOffset = Vec3.multiply(this.temporaryPositionOffset, intersectionPointToCenterDistance * FAR_TO_NEAR_GRAB_PADDING_FACTOR);
}
this.setState(STATE_EQUIP);
this.turnOffVisualizations();
return;
} else if ((this.state == STATE_SEARCHING) && this.triggerSmoothedGrab()) {
this.setState(STATE_DISTANCE_HOLDING);
return;
}
} else if (grabbableData.wantsTrigger && this.triggerSmoothedGrab()) {
this.grabbedEntity = intersection.entityID;
this.setState(STATE_FAR_TRIGGER);
return;
}
}
}
}
nearPickedCandidateEntities = Entities.findEntities(handPosition, GRAB_RADIUS);
candidateEntities = rayPickedCandidateEntities.concat(nearPickedCandidateEntities);
// forward ray test failed, try sphere test.
if (WANT_DEBUG) {
Entities.addEntity({
type: "Sphere",
name: "Grab Debug Entity",
dimensions: {
x: GRAB_RADIUS,
y: GRAB_RADIUS,
z: GRAB_RADIUS
},
visible: true,
position: handPosition,
color: {
red: 0,
green: 255,
blue: 0
},
lifetime: 0.1,
collisionsWillMove: false,
ignoreForCollisions: true,
userData: JSON.stringify({
grabbableKey: {
grabbable: false
}
})
});
}
var forbiddenNames = ["Grab Debug Entity", "grab pointer"];
var forbiddenTyes = ['Unknown', 'Light', 'ParticleEffect', 'PolyLine', 'Zone'];
var nearbyEntities = Entities.findEntities(handPosition, GRAB_RADIUS);
var minDistance = PICK_MAX_DISTANCE;
var i, props, distance, grabbableData;
this.grabbedEntity = null;
for (i = 0; i < nearbyEntities.length; i++) {
for (i = 0; i < candidateEntities.length; i++) {
var grabbableDataForCandidate =
getEntityCustomData(GRABBABLE_DATA_KEY, nearbyEntities[i], DEFAULT_GRABBABLE_DATA);
if (typeof grabbableDataForCandidate.grabbable !== 'undefined' && !grabbableDataForCandidate.grabbable) {
getEntityCustomData(GRABBABLE_DATA_KEY, candidateEntities[i], DEFAULT_GRABBABLE_DATA);
var propsForCandidate = Entities.getEntityProperties(candidateEntities[i], GRABBABLE_PROPERTIES);
var grabbable = (typeof grabbableDataForCandidate.grabbable === 'undefined' || grabbableDataForCandidate.grabbable);
if (!grabbable && !grabbableDataForCandidate.wantsTrigger) {
continue;
}
var propsForCandidate = Entities.getEntityProperties(nearbyEntities[i], GRABBABLE_PROPERTIES);
if (propsForCandidate.type == 'Unknown') {
if (forbiddenTyes.indexOf(propsForCandidate.type) >= 0) {
continue;
}
if (propsForCandidate.type == 'Light') {
continue;
}
if (propsForCandidate.type == 'ParticleEffect') {
continue;
}
if (propsForCandidate.type == 'PolyLine') {
continue;
}
if (propsForCandidate.type == 'Zone') {
continue;
}
if (propsForCandidate.locked && !grabbableDataForCandidate.wantsTrigger) {
continue;
}
if (propsForCandidate.name == "Grab Debug Entity") {
continue;
}
if (propsForCandidate.name == "grab pointer") {
if (forbiddenNames.indexOf(propsForCandidate.name) >= 0) {
continue;
}
distance = Vec3.distance(propsForCandidate.position, handPosition);
if (distance > PICK_MAX_DISTANCE) {
// too far away, don't grab
continue;
}
if (distance < minDistance) {
this.grabbedEntity = nearbyEntities[i];
this.grabbedEntity = candidateEntities[i];
minDistance = distance;
props = propsForCandidate;
grabbableData = grabbableDataForCandidate;
}
}
if (this.grabbedEntity !== null) {
// We've found an entity that we'll do something with.
var near = (nearPickedCandidateEntities.indexOf(this.grabbedEntity) >= 0);
var isPhysical = this.propsArePhysical(props);
// near or far trigger
if (grabbableData.wantsTrigger) {
this.setState(STATE_NEAR_TRIGGER);
return;
} else if (!props.locked && props.collisionsWillMove) {
var defaultDisableNearGrabData = {
disableNearGrab: false
};
//sometimes we want things to stay right where they are when we let go.
var disableNearGrabData = getEntityCustomData('handControllerKey', this.grabbedEntity, defaultDisableNearGrabData);
if (disableNearGrabData.disableNearGrab === true) {
//do nothing because near grab is disabled for this object
} else {
this.setState(this.state == STATE_SEARCHING ? STATE_NEAR_GRABBING : STATE_EQUIP)
}
this.setState(near ? STATE_NEAR_TRIGGER : STATE_FAR_TRIGGER);
return;
}
// near grab or equip with action
if (isPhysical && near) {
this.setState(this.state == STATE_SEARCHING ? STATE_NEAR_GRABBING : STATE_EQUIP);
return;
}
// far grab or equip with action
if (isPhysical && !near) {
this.temporaryPositionOffset = null;
if (typeof grabbableData.spatialKey === 'undefined') {
// We want to give a temporary position offset to this object so it is pulled close to hand
var intersectionPointToCenterDistance = Vec3.length(Vec3.subtract(intersection.intersection,
intersection.properties.position));
this.temporaryPositionOffset = Vec3.normalize(Vec3.subtract(intersection.properties.position, handPosition));
this.temporaryPositionOffset = Vec3.multiply(this.temporaryPositionOffset,
intersectionPointToCenterDistance *
FAR_TO_NEAR_GRAB_PADDING_FACTOR);
}
this.setState(this.state == STATE_SEARCHING ? STATE_DISTANCE_HOLDING : STATE_EQUIP);
return;
}
// else this thing isn't physical. grab it by reparenting it.
this.setState(STATE_NEAR_GRABBING);
return;
}
//search line visualizations
@ -1046,20 +942,31 @@ function MyController(hand) {
this.handleParticleBeam(distantPickRay.origin, this.getHandRotation(), NO_INTERSECT_COLOR);
}
if (USE_OVERLAY_LINES_FOR_SEARCHING === true) {
this.overlayLineOn(searchVisualizationPickRay.origin, Vec3.sum(searchVisualizationPickRay.origin, Vec3.multiply(searchVisualizationPickRay.direction, LINE_LENGTH)), NO_INTERSECT_COLOR);
}
// if (USE_OVERLAY_LINES_FOR_SEARCHING === true) {
// this.overlayLineOn(searchVisualizationPickRay.origin,
// Vec3.sum(searchVisualizationPickRay.origin,
// Vec3.multiply(searchVisualizationPickRay.direction,
// LINE_LENGTH)),
// NO_INTERSECT_COLOR);
// }
if (this.intersectionDistance > 0) {
var SPHERE_INTERSECTION_SIZE = 0.011;
var SEARCH_SPHERE_FOLLOW_RATE = 0.50;
var SEARCH_SPHERE_CHASE_DROP = 0.2;
this.searchSphereDistance = this.searchSphereDistance * SEARCH_SPHERE_FOLLOW_RATE + this.intersectionDistance * (1.0 - SEARCH_SPHERE_FOLLOW_RATE);
var searchSphereLocation = Vec3.sum(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, this.searchSphereDistance));
searchSphereLocation.y -= ((this.intersectionDistance - this.searchSphereDistance) / this.intersectionDistance) * SEARCH_SPHERE_CHASE_DROP;
this.searchSphereOn(searchSphereLocation, SPHERE_INTERSECTION_SIZE * this.intersectionDistance, this.triggerSmoothedGrab() ? INTERSECT_COLOR : NO_INTERSECT_COLOR);
this.searchSphereDistance = this.searchSphereDistance * SEARCH_SPHERE_FOLLOW_RATE +
this.intersectionDistance * (1.0 - SEARCH_SPHERE_FOLLOW_RATE);
var searchSphereLocation = Vec3.sum(distantPickRay.origin,
Vec3.multiply(distantPickRay.direction, this.searchSphereDistance));
searchSphereLocation.y -= ((this.intersectionDistance - this.searchSphereDistance) /
this.intersectionDistance) * SEARCH_SPHERE_CHASE_DROP;
this.searchSphereOn(searchSphereLocation,
SPHERE_INTERSECTION_SIZE * this.intersectionDistance,
this.triggerSmoothedGrab() ? INTERSECT_COLOR : NO_INTERSECT_COLOR);
if (USE_OVERLAY_LINES_FOR_SEARCHING === true) {
this.overlayLineOn(handPosition, searchSphereLocation, this.triggerSmoothedGrab() ? INTERSECT_COLOR : NO_INTERSECT_COLOR);
this.overlayLineOn(handPosition,
searchSphereLocation,
this.triggerSmoothedGrab() ? INTERSECT_COLOR : NO_INTERSECT_COLOR);
}
}
};
@ -1085,7 +992,7 @@ function MyController(hand) {
this.radiusScalar = 1.0;
}
this.actionID = NULL_ACTION_ID;
this.actionID = NULL_UUID;
this.actionID = Entities.addAction("spring", this.grabbedEntity, {
targetPosition: this.currentObjectPosition,
linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME,
@ -1094,7 +1001,7 @@ function MyController(hand) {
tag: getTag(),
ttl: ACTION_TTL
});
if (this.actionID === NULL_ACTION_ID) {
if (this.actionID === NULL_UUID) {
this.actionID = null;
}
this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC);
@ -1283,7 +1190,6 @@ function MyController(hand) {
}
};
this.setupHoldAction = function() {
this.actionID = Entities.addAction("hold", this.grabbedEntity, {
hand: this.hand === RIGHT_HAND ? "right" : "left",
@ -1295,7 +1201,7 @@ function MyController(hand) {
kinematicSetVelocity: true,
ignoreIK: this.ignoreIK
});
if (this.actionID === NULL_ACTION_ID) {
if (this.actionID === NULL_UUID) {
this.actionID = null;
return false;
}
@ -1330,7 +1236,6 @@ function MyController(hand) {
var projection = Vec3.sum(axisStart, Vec3.multiply(scalar, Vec3.normalize(bPrime)));
return projection
};
this.nearGrabbing = function() {
@ -1378,9 +1283,19 @@ function MyController(hand) {
}
}
if (!this.setupHoldAction()) {
return;
var isPhysical = this.propsArePhysical(grabbedProperties);
if (isPhysical) {
// grab entity via action
if (!this.setupHoldAction()) {
return;
}
} else {
// grab entity via parenting
var handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand");
Entities.editEntity(this.grabbedEntity, {
parentID: MyAvatar.sessionUUID,
parentJointIndex: handJointIndex
});
}
if (this.state == STATE_NEAR_GRABBING) {
@ -1447,7 +1362,13 @@ function MyController(hand) {
Entities.callEntityMethod(this.grabbedEntity, "continueEquip");
}
if (this.actionTimeout - now < ACTION_TTL_REFRESH * MSEC_PER_SEC) {
//// jbp::: SEND UPDATE MESSAGE TO WEARABLES MANAGER
Messages.sendMessage('Hifi-Wearables-Manager', JSON.stringify({
action: 'update',
grabbedEntity: this.grabbedEntity
}))
if (this.actionID && this.actionTimeout - now < ACTION_TTL_REFRESH * MSEC_PER_SEC) {
// if less than a 5 seconds left, refresh the actions ttl
var success = Entities.updateAction(this.grabbedEntity, this.actionID, {
hand: this.hand === RIGHT_HAND ? "right" : "left",
@ -1496,7 +1417,7 @@ function MyController(hand) {
if (typeof this.equipSpringID === 'undefined' ||
this.equipSpringID === null ||
this.equipSpringID === NULL_ACTION_ID) {
this.equipSpringID === NULL_UUID) {
this.equipSpringID = Entities.addAction("spring", this.grabbedEntity, {
targetPosition: targetPosition,
linearTimeScale: EQUIP_SPRING_TIMEFRAME,
@ -1505,7 +1426,7 @@ function MyController(hand) {
ttl: ACTION_TTL,
ignoreIK: ignoreIK
});
if (this.equipSpringID === NULL_ACTION_ID) {
if (this.equipSpringID === NULL_UUID) {
this.equipSpringID = null;
this.setState(STATE_OFF);
return;
@ -1682,12 +1603,10 @@ function MyController(hand) {
if (this.grabbedEntity !== null) {
if (this.actionID !== null) {
//add velocity whatnot
var defaultReleaseVelocityData = {
disableReleaseVelocity: false
};
//sometimes we want things to stay right where they are when we let go.
var releaseVelocityData = getEntityCustomData('handControllerKey', this.grabbedEntity, defaultReleaseVelocityData);
var releaseVelocityData = getEntityCustomData(GRABBABLE_DATA_KEY,
this.grabbedEntity,
DEFAULT_GRABBABLE_DATA);
if (releaseVelocityData.disableReleaseVelocity === true) {
Entities.deleteAction(this.grabbedEntity, this.actionID);
@ -1708,16 +1627,23 @@ function MyController(hand) {
} else {
//don't make adjustments
Entities.deleteAction(this.grabbedEntity, this.actionID);
}
}
}
this.deactivateEntity(this.grabbedEntity);
this.grabbedEntity = null;
this.actionID = null;
this.setState(STATE_OFF);
//// jbp::: SEND RELEASE MESSAGE TO WEARABLES MANAGER
Messages.sendMessage('Hifi-Wearables-Manager', JSON.stringify({
action: 'checkIfWearable',
grabbedEntity: this.grabbedEntity
}))
this.grabbedEntity = null;
};
this.cleanup = function() {
@ -1738,6 +1664,8 @@ function MyController(hand) {
data["gravity"] = grabbedProperties.gravity;
data["collisionMask"] = grabbedProperties.collisionMask;
data["collisionsWillMove"] = grabbedProperties.collisionsWillMove;
data["parentID"] = grabbedProperties.parentID;
data["parentJointIndex"] = grabbedProperties.parentJointIndex;
var whileHeldProperties = {
gravity: {
x: 0,
@ -1761,7 +1689,10 @@ function MyController(hand) {
Entities.editEntity(entityID, {
gravity: data["gravity"],
collisionMask: data["collisionMask"],
collisionsWillMove: data["collisionsWillMove"]
collisionsWillMove: data["collisionsWillMove"],
ignoreForCollisions: data["ignoreForCollisions"],
parentID: data["parentID"],
parentJointIndex: data["parentJointIndex"]
});
data = null;
}

View file

@ -241,7 +241,6 @@ void ObjectAction::activateBody(bool forceActivation) {
auto rigidBody = getRigidBody();
if (rigidBody) {
rigidBody->activate(forceActivation);
assert(rigidBody->isActive());
} else {
qDebug() << "ObjectAction::activateBody -- no rigid body" << (void*)rigidBody;
}

View file

@ -58,16 +58,16 @@ void ObjectActionSpring::updateActionWorker(btScalar deltaTimeStep) {
const float MAX_TIMESCALE = 600.0f; // 10 min is a long time
if (_linearTimeScale < MAX_TIMESCALE) {
btVector3 targetVelocity(0.0f, 0.0f, 0.0f);
btVector3 offset = rigidBody->getCenterOfMassPosition() - glmToBullet(_positionalTarget);
float offsetLength = offset.length();
btVector3 targetVelocity(0.0f, 0.0f, 0.0f);
float speed = (offsetLength > FLT_EPSILON) ? glm::min(offsetLength / _linearTimeScale, SPRING_MAX_SPEED) : 0.0f;
targetVelocity = (-speed / offsetLength) * offset;
if (speed > rigidBody->getLinearSleepingThreshold()) {
rigidBody->activate();
if (offsetLength > FLT_EPSILON) {
float speed = glm::min(offsetLength / _linearTimeScale, SPRING_MAX_SPEED);
targetVelocity = (-speed / offsetLength) * offset;
if (speed > rigidBody->getLinearSleepingThreshold()) {
rigidBody->activate();
}
}
// this action is aggresively critically damped and defeats the current velocity
rigidBody->setLinearVelocity(targetVelocity);
}