mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 18:56:55 +02:00
Merge pull request #10468 from AndrewMeadows/cleanup-actions
cleanup Actions and Constraints part-1
This commit is contained in:
commit
8a88b30da7
14 changed files with 49 additions and 585 deletions
|
@ -53,31 +53,3 @@ QVariantMap AssignmentDynamic::getArguments() {
|
||||||
qDebug() << "UNEXPECTED -- AssignmentDynamic::getArguments called in assignment-client.";
|
qDebug() << "UNEXPECTED -- AssignmentDynamic::getArguments called in assignment-client.";
|
||||||
return QVariantMap();
|
return QVariantMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 AssignmentDynamic::getPosition() {
|
|
||||||
qDebug() << "UNEXPECTED -- AssignmentDynamic::getPosition called in assignment-client.";
|
|
||||||
return glm::vec3(0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::quat AssignmentDynamic::getRotation() {
|
|
||||||
qDebug() << "UNEXPECTED -- AssignmentDynamic::getRotation called in assignment-client.";
|
|
||||||
return glm::quat();
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 AssignmentDynamic::getLinearVelocity() {
|
|
||||||
qDebug() << "UNEXPECTED -- AssignmentDynamic::getLinearVelocity called in assignment-client.";
|
|
||||||
return glm::vec3(0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AssignmentDynamic::setLinearVelocity(glm::vec3 linearVelocity) {
|
|
||||||
qDebug() << "UNEXPECTED -- AssignmentDynamic::setLinearVelocity called in assignment-client.";
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 AssignmentDynamic::getAngularVelocity() {
|
|
||||||
qDebug() << "UNEXPECTED -- AssignmentDynamic::getAngularVelocity called in assignment-client.";
|
|
||||||
return glm::vec3(0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AssignmentDynamic::setAngularVelocity(glm::vec3 angularVelocity) {
|
|
||||||
qDebug() << "UNEXPECTED -- AssignmentDynamic::setAngularVelocity called in assignment-client.";
|
|
||||||
}
|
|
||||||
|
|
|
@ -39,13 +39,6 @@ private:
|
||||||
QByteArray _data;
|
QByteArray _data;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual glm::vec3 getPosition() override;
|
|
||||||
virtual glm::quat getRotation() override;
|
|
||||||
virtual glm::vec3 getLinearVelocity() override;
|
|
||||||
virtual void setLinearVelocity(glm::vec3 linearVelocity) override;
|
|
||||||
virtual glm::vec3 getAngularVelocity() override;
|
|
||||||
virtual void setAngularVelocity(glm::vec3 angularVelocity) override;
|
|
||||||
|
|
||||||
bool _active;
|
bool _active;
|
||||||
EntityItemWeakPointer _ownerEntity;
|
EntityItemWeakPointer _ownerEntity;
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include <avatar/AvatarActionHold.h>
|
#include <avatar/AvatarActionHold.h>
|
||||||
#include <avatar/AvatarActionFarGrab.h>
|
#include <avatar/AvatarActionFarGrab.h>
|
||||||
#include <ObjectActionOffset.h>
|
#include <ObjectActionOffset.h>
|
||||||
#include <ObjectActionSpring.h>
|
|
||||||
#include <ObjectActionTractor.h>
|
#include <ObjectActionTractor.h>
|
||||||
#include <ObjectActionTravelOriented.h>
|
#include <ObjectActionTravelOriented.h>
|
||||||
#include <ObjectConstraintHinge.h>
|
#include <ObjectConstraintHinge.h>
|
||||||
|
@ -33,7 +32,7 @@ EntityDynamicPointer interfaceDynamicFactory(EntityDynamicType type, const QUuid
|
||||||
case DYNAMIC_TYPE_OFFSET:
|
case DYNAMIC_TYPE_OFFSET:
|
||||||
return std::make_shared<ObjectActionOffset>(id, ownerEntity);
|
return std::make_shared<ObjectActionOffset>(id, ownerEntity);
|
||||||
case DYNAMIC_TYPE_SPRING:
|
case DYNAMIC_TYPE_SPRING:
|
||||||
return std::make_shared<ObjectActionSpring>(id, ownerEntity);
|
qDebug() << "The 'spring' Action is deprecated. Replacing with 'tractor' Action.";
|
||||||
case DYNAMIC_TYPE_TRACTOR:
|
case DYNAMIC_TYPE_TRACTOR:
|
||||||
return std::make_shared<ObjectActionTractor>(id, ownerEntity);
|
return std::make_shared<ObjectActionTractor>(id, ownerEntity);
|
||||||
case DYNAMIC_TYPE_HOLD:
|
case DYNAMIC_TYPE_HOLD:
|
||||||
|
|
|
@ -43,14 +43,14 @@
|
||||||
| |
|
| |
|
||||||
+--------------------+ +-----------------------+
|
+--------------------+ +-----------------------+
|
||||||
| | | |
|
| | | |
|
||||||
| ObjectActionSpring | | ObjectConstraintHinge |
|
| ObjectActionTractor| | ObjectConstraintHinge |
|
||||||
| (physics) | | (physics) |
|
| (physics) | | (physics) |
|
||||||
+--------------------+ +-----------------------+
|
+--------------------+ +-----------------------+
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
A dynamic is a callback which is registered with bullet. A dynamic is called-back every physics
|
A dynamic is a callback which is registered with bullet. A dynamic is called-back every physics
|
||||||
simulation step and can do whatever it wants with the various datastructures it has available. An
|
simulation step and can do whatever it wants with the various datastructures it has available. A
|
||||||
dynamic, for example, can pull an EntityItem toward a point as if that EntityItem were connected to that
|
dynamic, for example, can pull an EntityItem toward a point as if that EntityItem were connected to that
|
||||||
point by a spring.
|
point by a spring.
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ script or when receiving information via an EntityTree data-stream (either over
|
||||||
svo file).
|
svo file).
|
||||||
|
|
||||||
In the interface, if an EntityItem has dynamics, this EntityItem will have pointers to ObjectDynamic
|
In the interface, if an EntityItem has dynamics, this EntityItem will have pointers to ObjectDynamic
|
||||||
subclass (like ObjectDynamicSpring) instantiations. Code in the entities library affects a dynamic-object
|
subclass (like ObjectDynamicTractor) instantiations. Code in the entities library affects a dynamic-object
|
||||||
via the EntityDynamicInterface (which knows nothing about bullet). When the ObjectDynamic subclass
|
via the EntityDynamicInterface (which knows nothing about bullet). When the ObjectDynamic subclass
|
||||||
instance is created, it is registered as a dynamic with bullet. Bullet will call into code in this
|
instance is created, it is registered as a dynamic with bullet. Bullet will call into code in this
|
||||||
instance with the btDynamicInterface every physics-simulation step.
|
instance with the btDynamicInterface every physics-simulation step.
|
||||||
|
@ -75,11 +75,11 @@ right now the AssignmentDynamic class is a place-holder.
|
||||||
|
|
||||||
The dynamic-objects are instantiated by singleton (dependecy) subclasses of EntityDynamicFactoryInterface.
|
The dynamic-objects are instantiated by singleton (dependecy) subclasses of EntityDynamicFactoryInterface.
|
||||||
In the interface, the subclass is an InterfaceDynamicFactory and it will produce things like
|
In the interface, the subclass is an InterfaceDynamicFactory and it will produce things like
|
||||||
ObjectDynamicSpring. In an entity-server the subclass is an AssignmentDynamicFactory and it always
|
ObjectDynamicTractor. In an entity-server the subclass is an AssignmentDynamicFactory and it always
|
||||||
produces AssignmentDynamics.
|
produces AssignmentDynamics.
|
||||||
|
|
||||||
Depending on the dynamic's type, it will have various arguments. When a script changes an argument of an
|
Depending on the dynamic's type, it will have various arguments. When a script changes an argument of an
|
||||||
dynamic, the argument-holding member-variables of ObjectDynamicSpring (in this example) are updated and
|
dynamic, the argument-holding member-variables of ObjectDynamicTractor (in this example) are updated and
|
||||||
also serialized into _dynamicData in the EntityItem. Each subclass of ObjectDynamic knows how to serialize
|
also serialized into _dynamicData in the EntityItem. Each subclass of ObjectDynamic knows how to serialize
|
||||||
and deserialize its own arguments. _dynamicData is what gets sent over the wire or saved in an svo file.
|
and deserialize its own arguments. _dynamicData is what gets sent over the wire or saved in an svo file.
|
||||||
When a packet-reader receives data for _dynamicData, it will save it in the EntityItem; this causes the
|
When a packet-reader receives data for _dynamicData, it will save it in the EntityItem; this causes the
|
||||||
|
@ -103,7 +103,7 @@ EntityDynamicType EntityDynamicInterface::dynamicTypeFromString(QString dynamicT
|
||||||
return DYNAMIC_TYPE_OFFSET;
|
return DYNAMIC_TYPE_OFFSET;
|
||||||
}
|
}
|
||||||
if (normalizedDynamicTypeString == "spring") {
|
if (normalizedDynamicTypeString == "spring") {
|
||||||
return DYNAMIC_TYPE_SPRING;
|
return DYNAMIC_TYPE_TRACTOR;
|
||||||
}
|
}
|
||||||
if (normalizedDynamicTypeString == "tractor") {
|
if (normalizedDynamicTypeString == "tractor") {
|
||||||
return DYNAMIC_TYPE_TRACTOR;
|
return DYNAMIC_TYPE_TRACTOR;
|
||||||
|
@ -142,7 +142,6 @@ QString EntityDynamicInterface::dynamicTypeToString(EntityDynamicType dynamicTyp
|
||||||
case DYNAMIC_TYPE_OFFSET:
|
case DYNAMIC_TYPE_OFFSET:
|
||||||
return "offset";
|
return "offset";
|
||||||
case DYNAMIC_TYPE_SPRING:
|
case DYNAMIC_TYPE_SPRING:
|
||||||
return "spring";
|
|
||||||
case DYNAMIC_TYPE_TRACTOR:
|
case DYNAMIC_TYPE_TRACTOR:
|
||||||
return "tractor";
|
return "tractor";
|
||||||
case DYNAMIC_TYPE_HOLD:
|
case DYNAMIC_TYPE_HOLD:
|
||||||
|
|
|
@ -94,15 +94,6 @@ public:
|
||||||
QString argumentName, bool& ok, bool required = true);
|
QString argumentName, bool& ok, bool required = true);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual glm::vec3 getPosition() = 0;
|
|
||||||
// virtual void setPosition(glm::vec3 position) = 0;
|
|
||||||
virtual glm::quat getRotation() = 0;
|
|
||||||
// virtual void setRotation(glm::quat rotation) = 0;
|
|
||||||
virtual glm::vec3 getLinearVelocity() = 0;
|
|
||||||
virtual void setLinearVelocity(glm::vec3 linearVelocity) = 0;
|
|
||||||
virtual glm::vec3 getAngularVelocity() = 0;
|
|
||||||
virtual void setAngularVelocity(glm::vec3 angularVelocity) = 0;
|
|
||||||
|
|
||||||
QUuid _id;
|
QUuid _id;
|
||||||
EntityDynamicType _type;
|
EntityDynamicType _type;
|
||||||
bool _active { false };
|
bool _active { false };
|
||||||
|
|
|
@ -1,378 +0,0 @@
|
||||||
//
|
|
||||||
// ObjectActionSpring.cpp
|
|
||||||
// libraries/physics/src
|
|
||||||
//
|
|
||||||
// Created by Seth Alves 2015-6-5
|
|
||||||
// Copyright 2015 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
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "QVariantGLM.h"
|
|
||||||
|
|
||||||
#include "ObjectActionSpring.h"
|
|
||||||
|
|
||||||
#include "PhysicsLogging.h"
|
|
||||||
|
|
||||||
const float SPRING_MAX_SPEED = 10.0f;
|
|
||||||
const float MAX_SPRING_TIMESCALE = 600.0f; // 10 min is a long time
|
|
||||||
|
|
||||||
const uint16_t ObjectActionSpring::springVersion = 1;
|
|
||||||
|
|
||||||
|
|
||||||
ObjectActionSpring::ObjectActionSpring(const QUuid& id, EntityItemPointer ownerEntity) :
|
|
||||||
ObjectAction(DYNAMIC_TYPE_SPRING, id, ownerEntity),
|
|
||||||
_positionalTarget(glm::vec3(0.0f)),
|
|
||||||
_desiredPositionalTarget(glm::vec3(0.0f)),
|
|
||||||
_linearTimeScale(FLT_MAX),
|
|
||||||
_positionalTargetSet(true),
|
|
||||||
_rotationalTarget(glm::quat()),
|
|
||||||
_desiredRotationalTarget(glm::quat()),
|
|
||||||
_angularTimeScale(FLT_MAX),
|
|
||||||
_rotationalTargetSet(true) {
|
|
||||||
#if WANT_DEBUG
|
|
||||||
qCDebug(physics) << "ObjectActionSpring::ObjectActionSpring";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectActionSpring::~ObjectActionSpring() {
|
|
||||||
#if WANT_DEBUG
|
|
||||||
qCDebug(physics) << "ObjectActionSpring::~ObjectActionSpring";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ObjectActionSpring::getTarget(float deltaTimeStep, glm::quat& rotation, glm::vec3& position,
|
|
||||||
glm::vec3& linearVelocity, glm::vec3& angularVelocity,
|
|
||||||
float& linearTimeScale, float& angularTimeScale) {
|
|
||||||
SpatiallyNestablePointer other = getOther();
|
|
||||||
withReadLock([&]{
|
|
||||||
linearTimeScale = _linearTimeScale;
|
|
||||||
angularTimeScale = _angularTimeScale;
|
|
||||||
|
|
||||||
if (!_otherID.isNull()) {
|
|
||||||
if (other) {
|
|
||||||
rotation = _desiredRotationalTarget * other->getRotation();
|
|
||||||
position = other->getRotation() * _desiredPositionalTarget + other->getPosition();
|
|
||||||
} else {
|
|
||||||
// we should have an "other" but can't find it, so disable the spring.
|
|
||||||
linearTimeScale = FLT_MAX;
|
|
||||||
angularTimeScale = FLT_MAX;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rotation = _desiredRotationalTarget;
|
|
||||||
position = _desiredPositionalTarget;
|
|
||||||
}
|
|
||||||
linearVelocity = glm::vec3();
|
|
||||||
angularVelocity = glm::vec3();
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ObjectActionSpring::prepareForSpringUpdate(btScalar deltaTimeStep) {
|
|
||||||
auto ownerEntity = _ownerEntity.lock();
|
|
||||||
if (!ownerEntity) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::quat rotation;
|
|
||||||
glm::vec3 position;
|
|
||||||
glm::vec3 linearVelocity;
|
|
||||||
glm::vec3 angularVelocity;
|
|
||||||
|
|
||||||
bool linearValid = false;
|
|
||||||
int linearSpringCount = 0;
|
|
||||||
bool angularValid = false;
|
|
||||||
int angularSpringCount = 0;
|
|
||||||
|
|
||||||
QList<EntityDynamicPointer> springDerivedActions;
|
|
||||||
springDerivedActions.append(ownerEntity->getActionsOfType(DYNAMIC_TYPE_SPRING));
|
|
||||||
springDerivedActions.append(ownerEntity->getActionsOfType(DYNAMIC_TYPE_FAR_GRAB));
|
|
||||||
springDerivedActions.append(ownerEntity->getActionsOfType(DYNAMIC_TYPE_HOLD));
|
|
||||||
|
|
||||||
foreach (EntityDynamicPointer action, springDerivedActions) {
|
|
||||||
std::shared_ptr<ObjectActionSpring> springAction = std::static_pointer_cast<ObjectActionSpring>(action);
|
|
||||||
glm::quat rotationForAction;
|
|
||||||
glm::vec3 positionForAction;
|
|
||||||
glm::vec3 linearVelocityForAction;
|
|
||||||
glm::vec3 angularVelocityForAction;
|
|
||||||
float linearTimeScale;
|
|
||||||
float angularTimeScale;
|
|
||||||
bool success = springAction->getTarget(deltaTimeStep,
|
|
||||||
rotationForAction, positionForAction,
|
|
||||||
linearVelocityForAction, angularVelocityForAction,
|
|
||||||
linearTimeScale, angularTimeScale);
|
|
||||||
if (success) {
|
|
||||||
if (angularTimeScale < MAX_SPRING_TIMESCALE) {
|
|
||||||
angularValid = true;
|
|
||||||
angularSpringCount++;
|
|
||||||
angularVelocity += angularVelocityForAction;
|
|
||||||
if (springAction.get() == this) {
|
|
||||||
// only use the rotation for this action
|
|
||||||
rotation = rotationForAction;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (linearTimeScale < MAX_SPRING_TIMESCALE) {
|
|
||||||
linearValid = true;
|
|
||||||
linearSpringCount++;
|
|
||||||
position += positionForAction;
|
|
||||||
linearVelocity += linearVelocityForAction;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((angularValid && angularSpringCount > 0) || (linearValid && linearSpringCount > 0)) {
|
|
||||||
withWriteLock([&]{
|
|
||||||
if (linearValid && linearSpringCount > 0) {
|
|
||||||
position /= linearSpringCount;
|
|
||||||
linearVelocity /= linearSpringCount;
|
|
||||||
_positionalTarget = position;
|
|
||||||
_linearVelocityTarget = linearVelocity;
|
|
||||||
_positionalTargetSet = true;
|
|
||||||
_active = true;
|
|
||||||
}
|
|
||||||
if (angularValid && angularSpringCount > 0) {
|
|
||||||
angularVelocity /= angularSpringCount;
|
|
||||||
_rotationalTarget = rotation;
|
|
||||||
_angularVelocityTarget = angularVelocity;
|
|
||||||
_rotationalTargetSet = true;
|
|
||||||
_active = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return linearValid || angularValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectActionSpring::updateActionWorker(btScalar deltaTimeStep) {
|
|
||||||
if (!prepareForSpringUpdate(deltaTimeStep)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
withReadLock([&]{
|
|
||||||
auto ownerEntity = _ownerEntity.lock();
|
|
||||||
if (!ownerEntity) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* physicsInfo = ownerEntity->getPhysicsInfo();
|
|
||||||
if (!physicsInfo) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo);
|
|
||||||
btRigidBody* rigidBody = motionState->getRigidBody();
|
|
||||||
if (!rigidBody) {
|
|
||||||
qCDebug(physics) << "ObjectActionSpring::updateActionWorker no rigidBody";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_linearTimeScale < MAX_SPRING_TIMESCALE) {
|
|
||||||
btVector3 targetVelocity(0.0f, 0.0f, 0.0f);
|
|
||||||
btVector3 offset = rigidBody->getCenterOfMassPosition() - glmToBullet(_positionalTarget);
|
|
||||||
float offsetLength = offset.length();
|
|
||||||
if (offsetLength > FLT_EPSILON) {
|
|
||||||
float speed = glm::min(offsetLength / _linearTimeScale, SPRING_MAX_SPEED);
|
|
||||||
targetVelocity = (-speed / offsetLength) * offset;
|
|
||||||
if (speed > rigidBody->getLinearSleepingThreshold()) {
|
|
||||||
forceBodyNonStatic();
|
|
||||||
rigidBody->activate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// this action is aggresively critically damped and defeats the current velocity
|
|
||||||
rigidBody->setLinearVelocity(targetVelocity);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_angularTimeScale < MAX_SPRING_TIMESCALE) {
|
|
||||||
btVector3 targetVelocity(0.0f, 0.0f, 0.0f);
|
|
||||||
|
|
||||||
btQuaternion bodyRotation = rigidBody->getOrientation();
|
|
||||||
auto alignmentDot = bodyRotation.dot(glmToBullet(_rotationalTarget));
|
|
||||||
const float ALMOST_ONE = 0.99999f;
|
|
||||||
if (glm::abs(alignmentDot) < ALMOST_ONE) {
|
|
||||||
btQuaternion target = glmToBullet(_rotationalTarget);
|
|
||||||
if (alignmentDot < 0.0f) {
|
|
||||||
target = -target;
|
|
||||||
}
|
|
||||||
// if dQ is the incremental rotation that gets an object from Q0 to Q1 then:
|
|
||||||
//
|
|
||||||
// Q1 = dQ * Q0
|
|
||||||
//
|
|
||||||
// solving for dQ gives:
|
|
||||||
//
|
|
||||||
// dQ = Q1 * Q0^
|
|
||||||
btQuaternion deltaQ = target * bodyRotation.inverse();
|
|
||||||
float speed = deltaQ.getAngle() / _angularTimeScale;
|
|
||||||
targetVelocity = speed * deltaQ.getAxis();
|
|
||||||
if (speed > rigidBody->getAngularSleepingThreshold()) {
|
|
||||||
rigidBody->activate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// this action is aggresively critically damped and defeats the current velocity
|
|
||||||
rigidBody->setAngularVelocity(targetVelocity);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const float MIN_TIMESCALE = 0.1f;
|
|
||||||
|
|
||||||
|
|
||||||
bool ObjectActionSpring::updateArguments(QVariantMap arguments) {
|
|
||||||
glm::vec3 positionalTarget;
|
|
||||||
float linearTimeScale;
|
|
||||||
glm::quat rotationalTarget;
|
|
||||||
float angularTimeScale;
|
|
||||||
QUuid otherID;
|
|
||||||
|
|
||||||
|
|
||||||
bool needUpdate = false;
|
|
||||||
bool somethingChanged = ObjectDynamic::updateArguments(arguments);
|
|
||||||
withReadLock([&]{
|
|
||||||
// targets are required, spring-constants are optional
|
|
||||||
bool ok = true;
|
|
||||||
positionalTarget = EntityDynamicInterface::extractVec3Argument("spring action", arguments, "targetPosition", ok, false);
|
|
||||||
if (!ok) {
|
|
||||||
positionalTarget = _desiredPositionalTarget;
|
|
||||||
}
|
|
||||||
ok = true;
|
|
||||||
linearTimeScale = EntityDynamicInterface::extractFloatArgument("spring action", arguments, "linearTimeScale", ok, false);
|
|
||||||
if (!ok || linearTimeScale <= 0.0f) {
|
|
||||||
linearTimeScale = _linearTimeScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = true;
|
|
||||||
rotationalTarget = EntityDynamicInterface::extractQuatArgument("spring action", arguments, "targetRotation", ok, false);
|
|
||||||
if (!ok) {
|
|
||||||
rotationalTarget = _desiredRotationalTarget;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = true;
|
|
||||||
angularTimeScale =
|
|
||||||
EntityDynamicInterface::extractFloatArgument("spring action", arguments, "angularTimeScale", ok, false);
|
|
||||||
if (!ok) {
|
|
||||||
angularTimeScale = _angularTimeScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = true;
|
|
||||||
otherID = QUuid(EntityDynamicInterface::extractStringArgument("spring action",
|
|
||||||
arguments, "otherID", ok, false));
|
|
||||||
if (!ok) {
|
|
||||||
otherID = _otherID;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (somethingChanged ||
|
|
||||||
positionalTarget != _desiredPositionalTarget ||
|
|
||||||
linearTimeScale != _linearTimeScale ||
|
|
||||||
rotationalTarget != _desiredRotationalTarget ||
|
|
||||||
angularTimeScale != _angularTimeScale ||
|
|
||||||
otherID != _otherID) {
|
|
||||||
// something changed
|
|
||||||
needUpdate = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (needUpdate) {
|
|
||||||
withWriteLock([&] {
|
|
||||||
_desiredPositionalTarget = positionalTarget;
|
|
||||||
_linearTimeScale = glm::max(MIN_TIMESCALE, glm::abs(linearTimeScale));
|
|
||||||
_desiredRotationalTarget = rotationalTarget;
|
|
||||||
_angularTimeScale = glm::max(MIN_TIMESCALE, glm::abs(angularTimeScale));
|
|
||||||
_otherID = otherID;
|
|
||||||
_active = true;
|
|
||||||
|
|
||||||
auto ownerEntity = _ownerEntity.lock();
|
|
||||||
if (ownerEntity) {
|
|
||||||
ownerEntity->setDynamicDataDirty(true);
|
|
||||||
ownerEntity->setDynamicDataNeedsTransmit(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
activateBody();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantMap ObjectActionSpring::getArguments() {
|
|
||||||
QVariantMap arguments = ObjectDynamic::getArguments();
|
|
||||||
withReadLock([&] {
|
|
||||||
arguments["linearTimeScale"] = _linearTimeScale;
|
|
||||||
arguments["targetPosition"] = glmToQMap(_desiredPositionalTarget);
|
|
||||||
|
|
||||||
arguments["targetRotation"] = glmToQMap(_desiredRotationalTarget);
|
|
||||||
arguments["angularTimeScale"] = _angularTimeScale;
|
|
||||||
|
|
||||||
arguments["otherID"] = _otherID;
|
|
||||||
});
|
|
||||||
return arguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectActionSpring::serializeParameters(QDataStream& dataStream) const {
|
|
||||||
withReadLock([&] {
|
|
||||||
dataStream << _desiredPositionalTarget;
|
|
||||||
dataStream << _linearTimeScale;
|
|
||||||
dataStream << _positionalTargetSet;
|
|
||||||
dataStream << _desiredRotationalTarget;
|
|
||||||
dataStream << _angularTimeScale;
|
|
||||||
dataStream << _rotationalTargetSet;
|
|
||||||
dataStream << localTimeToServerTime(_expires);
|
|
||||||
dataStream << _tag;
|
|
||||||
dataStream << _otherID;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray ObjectActionSpring::serialize() const {
|
|
||||||
QByteArray serializedActionArguments;
|
|
||||||
QDataStream dataStream(&serializedActionArguments, QIODevice::WriteOnly);
|
|
||||||
|
|
||||||
dataStream << DYNAMIC_TYPE_SPRING;
|
|
||||||
dataStream << getID();
|
|
||||||
dataStream << ObjectActionSpring::springVersion;
|
|
||||||
|
|
||||||
serializeParameters(dataStream);
|
|
||||||
|
|
||||||
return serializedActionArguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectActionSpring::deserializeParameters(QByteArray serializedArguments, QDataStream& dataStream) {
|
|
||||||
withWriteLock([&] {
|
|
||||||
dataStream >> _desiredPositionalTarget;
|
|
||||||
dataStream >> _linearTimeScale;
|
|
||||||
dataStream >> _positionalTargetSet;
|
|
||||||
|
|
||||||
dataStream >> _desiredRotationalTarget;
|
|
||||||
dataStream >> _angularTimeScale;
|
|
||||||
dataStream >> _rotationalTargetSet;
|
|
||||||
|
|
||||||
quint64 serverExpires;
|
|
||||||
dataStream >> serverExpires;
|
|
||||||
_expires = serverTimeToLocalTime(serverExpires);
|
|
||||||
|
|
||||||
dataStream >> _tag;
|
|
||||||
|
|
||||||
dataStream >> _otherID;
|
|
||||||
|
|
||||||
_active = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectActionSpring::deserialize(QByteArray serializedArguments) {
|
|
||||||
QDataStream dataStream(serializedArguments);
|
|
||||||
|
|
||||||
EntityDynamicType type;
|
|
||||||
dataStream >> type;
|
|
||||||
assert(type == getType());
|
|
||||||
|
|
||||||
QUuid id;
|
|
||||||
dataStream >> id;
|
|
||||||
assert(id == getID());
|
|
||||||
|
|
||||||
uint16_t serializationVersion;
|
|
||||||
dataStream >> serializationVersion;
|
|
||||||
if (serializationVersion != ObjectActionSpring::springVersion) {
|
|
||||||
assert(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
deserializeParameters(serializedArguments, dataStream);
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
//
|
|
||||||
// ObjectActionSpring.h
|
|
||||||
// libraries/physics/src
|
|
||||||
//
|
|
||||||
// Created by Seth Alves 2015-6-5
|
|
||||||
// Copyright 2015 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
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef hifi_ObjectActionSpring_h
|
|
||||||
#define hifi_ObjectActionSpring_h
|
|
||||||
|
|
||||||
#include "ObjectAction.h"
|
|
||||||
|
|
||||||
class ObjectActionSpring : public ObjectAction {
|
|
||||||
public:
|
|
||||||
ObjectActionSpring(const QUuid& id, EntityItemPointer ownerEntity);
|
|
||||||
virtual ~ObjectActionSpring();
|
|
||||||
|
|
||||||
virtual bool updateArguments(QVariantMap arguments) override;
|
|
||||||
virtual QVariantMap getArguments() override;
|
|
||||||
|
|
||||||
virtual void updateActionWorker(float deltaTimeStep) override;
|
|
||||||
|
|
||||||
virtual QByteArray serialize() const override;
|
|
||||||
virtual void deserialize(QByteArray serializedArguments) override;
|
|
||||||
|
|
||||||
virtual bool getTarget(float deltaTimeStep, glm::quat& rotation, glm::vec3& position,
|
|
||||||
glm::vec3& linearVelocity, glm::vec3& angularVelocity,
|
|
||||||
float& linearTimeScale, float& angularTimeScale);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static const uint16_t springVersion;
|
|
||||||
|
|
||||||
glm::vec3 _positionalTarget;
|
|
||||||
glm::vec3 _desiredPositionalTarget;
|
|
||||||
float _linearTimeScale;
|
|
||||||
bool _positionalTargetSet;
|
|
||||||
|
|
||||||
glm::quat _rotationalTarget;
|
|
||||||
glm::quat _desiredRotationalTarget;
|
|
||||||
float _angularTimeScale;
|
|
||||||
bool _rotationalTargetSet;
|
|
||||||
|
|
||||||
glm::vec3 _linearVelocityTarget;
|
|
||||||
glm::vec3 _angularVelocityTarget;
|
|
||||||
|
|
||||||
virtual bool prepareForSpringUpdate(btScalar deltaTimeStep);
|
|
||||||
|
|
||||||
void serializeParameters(QDataStream& dataStream) const;
|
|
||||||
void deserializeParameters(QByteArray serializedArguments, QDataStream& dataStream);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // hifi_ObjectActionSpring_h
|
|
|
@ -160,56 +160,6 @@ btRigidBody* ObjectDynamic::getRigidBody() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 ObjectDynamic::getPosition() {
|
|
||||||
auto rigidBody = getRigidBody();
|
|
||||||
if (!rigidBody) {
|
|
||||||
return glm::vec3(0.0f);
|
|
||||||
}
|
|
||||||
return bulletToGLM(rigidBody->getCenterOfMassPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::quat ObjectDynamic::getRotation() {
|
|
||||||
auto rigidBody = getRigidBody();
|
|
||||||
if (!rigidBody) {
|
|
||||||
return glm::quat(0.0f, 0.0f, 0.0f, 1.0f);
|
|
||||||
}
|
|
||||||
return bulletToGLM(rigidBody->getOrientation());
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 ObjectDynamic::getLinearVelocity() {
|
|
||||||
auto rigidBody = getRigidBody();
|
|
||||||
if (!rigidBody) {
|
|
||||||
return glm::vec3(0.0f);
|
|
||||||
}
|
|
||||||
return bulletToGLM(rigidBody->getLinearVelocity());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectDynamic::setLinearVelocity(glm::vec3 linearVelocity) {
|
|
||||||
auto rigidBody = getRigidBody();
|
|
||||||
if (!rigidBody) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rigidBody->setLinearVelocity(glmToBullet(glm::vec3(0.0f)));
|
|
||||||
rigidBody->activate();
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 ObjectDynamic::getAngularVelocity() {
|
|
||||||
auto rigidBody = getRigidBody();
|
|
||||||
if (!rigidBody) {
|
|
||||||
return glm::vec3(0.0f);
|
|
||||||
}
|
|
||||||
return bulletToGLM(rigidBody->getAngularVelocity());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectDynamic::setAngularVelocity(glm::vec3 angularVelocity) {
|
|
||||||
auto rigidBody = getRigidBody();
|
|
||||||
if (!rigidBody) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rigidBody->setAngularVelocity(glmToBullet(angularVelocity));
|
|
||||||
rigidBody->activate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectDynamic::activateBody(bool forceActivation) {
|
void ObjectDynamic::activateBody(bool forceActivation) {
|
||||||
auto rigidBody = getRigidBody();
|
auto rigidBody = getRigidBody();
|
||||||
if (rigidBody) {
|
if (rigidBody) {
|
||||||
|
|
|
@ -56,12 +56,6 @@ protected:
|
||||||
btRigidBody* getOtherRigidBody(EntityItemID otherEntityID);
|
btRigidBody* getOtherRigidBody(EntityItemID otherEntityID);
|
||||||
EntityItemPointer getEntityByID(EntityItemID entityID) const;
|
EntityItemPointer getEntityByID(EntityItemID entityID) const;
|
||||||
virtual btRigidBody* getRigidBody();
|
virtual btRigidBody* getRigidBody();
|
||||||
virtual glm::vec3 getPosition() override;
|
|
||||||
virtual glm::quat getRotation() override;
|
|
||||||
virtual glm::vec3 getLinearVelocity() override;
|
|
||||||
virtual void setLinearVelocity(glm::vec3 linearVelocity) override;
|
|
||||||
virtual glm::vec3 getAngularVelocity() override;
|
|
||||||
virtual void setAngularVelocity(glm::vec3 angularVelocity) override;
|
|
||||||
virtual void activateBody(bool forceActivation = false);
|
virtual void activateBody(bool forceActivation = false);
|
||||||
virtual void forceBodyNonStatic();
|
virtual void forceBodyNonStatic();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// shopItemGrab.js
|
// shopItemGrab.js
|
||||||
//
|
//
|
||||||
// Semplified and coarse version of handControllerGrab.js with the addition of the ownerID concept.
|
// Simplified and coarse version of handControllerGrab.js with the addition of the ownerID concept.
|
||||||
// This grab is the only one which should run in the vrShop. It allows only near grab and add the feature of checking the ownerID. (See shopGrapSwapperEntityScript.js)
|
// This grab is the only one which should run in the vrShop. It allows only near grab and add the feature of checking the ownerID. (See shopGrapSwapperEntityScript.js)
|
||||||
//
|
//
|
||||||
|
|
||||||
|
@ -63,8 +63,8 @@ var NEAR_GRABBING_KINEMATIC = true; // force objects to be kinematic when near-g
|
||||||
// equip
|
// equip
|
||||||
//
|
//
|
||||||
|
|
||||||
var EQUIP_SPRING_SHUTOFF_DISTANCE = 0.05;
|
var EQUIP_TRACTOR_SHUTOFF_DISTANCE = 0.05;
|
||||||
var EQUIP_SPRING_TIMEFRAME = 0.4; // how quickly objects move to their new position
|
var EQUIP_TRACTOR_TIMEFRAME = 0.4; // how quickly objects move to their new position
|
||||||
|
|
||||||
//
|
//
|
||||||
// other constants
|
// other constants
|
||||||
|
@ -121,7 +121,7 @@ var STATE_EQUIP_SEARCHING = 11;
|
||||||
var STATE_EQUIP = 12
|
var STATE_EQUIP = 12
|
||||||
var STATE_CONTINUE_EQUIP_BD = 13; // equip while bumper is still held down
|
var STATE_CONTINUE_EQUIP_BD = 13; // equip while bumper is still held down
|
||||||
var STATE_CONTINUE_EQUIP = 14;
|
var STATE_CONTINUE_EQUIP = 14;
|
||||||
var STATE_EQUIP_SPRING = 16;
|
var STATE_EQUIP_TRACTOR = 16;
|
||||||
|
|
||||||
|
|
||||||
function stateToName(state) {
|
function stateToName(state) {
|
||||||
|
@ -152,8 +152,8 @@ function stateToName(state) {
|
||||||
return "continue_equip_bd";
|
return "continue_equip_bd";
|
||||||
case STATE_CONTINUE_EQUIP:
|
case STATE_CONTINUE_EQUIP:
|
||||||
return "continue_equip";
|
return "continue_equip";
|
||||||
case STATE_EQUIP_SPRING:
|
case STATE_EQUIP_TRACTOR:
|
||||||
return "state_equip_spring";
|
return "state_equip_tractor";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "unknown";
|
return "unknown";
|
||||||
|
@ -216,7 +216,7 @@ function MyController(hand) {
|
||||||
case STATE_EQUIP:
|
case STATE_EQUIP:
|
||||||
this.nearGrabbing();
|
this.nearGrabbing();
|
||||||
break;
|
break;
|
||||||
case STATE_EQUIP_SPRING:
|
case STATE_EQUIP_TRACTOR:
|
||||||
this.pullTowardEquipPosition()
|
this.pullTowardEquipPosition()
|
||||||
break;
|
break;
|
||||||
case STATE_CONTINUE_NEAR_GRABBING:
|
case STATE_CONTINUE_NEAR_GRABBING:
|
||||||
|
@ -404,14 +404,14 @@ function MyController(hand) {
|
||||||
return;
|
return;
|
||||||
} else if (!properties.locked) {
|
} else if (!properties.locked) {
|
||||||
var ownerObj = getEntityCustomData('ownerKey', intersection.entityID, null);
|
var ownerObj = getEntityCustomData('ownerKey', intersection.entityID, null);
|
||||||
|
|
||||||
if (ownerObj == null || ownerObj.ownerID === MyAvatar.sessionUUID) { //I can only grab new or already mine items
|
if (ownerObj == null || ownerObj.ownerID === MyAvatar.sessionUUID) { //I can only grab new or already mine items
|
||||||
this.grabbedEntity = intersection.entityID;
|
this.grabbedEntity = intersection.entityID;
|
||||||
if (this.state == STATE_SEARCHING) {
|
if (this.state == STATE_SEARCHING) {
|
||||||
this.setState(STATE_NEAR_GRABBING);
|
this.setState(STATE_NEAR_GRABBING);
|
||||||
} else { // equipping
|
} else { // equipping
|
||||||
if (typeof grabbableData.spatialKey !== 'undefined') {
|
if (typeof grabbableData.spatialKey !== 'undefined') {
|
||||||
this.setState(STATE_EQUIP_SPRING);
|
this.setState(STATE_EQUIP_TRACTOR);
|
||||||
} else {
|
} else {
|
||||||
this.setState(STATE_EQUIP);
|
this.setState(STATE_EQUIP);
|
||||||
}
|
}
|
||||||
|
@ -558,7 +558,7 @@ function MyController(hand) {
|
||||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES);
|
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES);
|
||||||
var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA);
|
var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA);
|
||||||
|
|
||||||
// use a spring to pull the object to where it will be when equipped
|
// use a tractor to pull the object to where it will be when equipped
|
||||||
var relativeRotation = {
|
var relativeRotation = {
|
||||||
x: 0.0,
|
x: 0.0,
|
||||||
y: 0.0,
|
y: 0.0,
|
||||||
|
@ -582,34 +582,34 @@ function MyController(hand) {
|
||||||
var offset = Vec3.multiplyQbyV(targetRotation, relativePosition);
|
var offset = Vec3.multiplyQbyV(targetRotation, relativePosition);
|
||||||
var targetPosition = Vec3.sum(handPosition, offset);
|
var targetPosition = Vec3.sum(handPosition, offset);
|
||||||
|
|
||||||
if (typeof this.equipSpringID === 'undefined' ||
|
if (typeof this.equipTractorID === 'undefined' ||
|
||||||
this.equipSpringID === null ||
|
this.equipTractorID === null ||
|
||||||
this.equipSpringID === NULL_ACTION_ID) {
|
this.equipTractorID === NULL_ACTION_ID) {
|
||||||
this.equipSpringID = Entities.addAction("spring", this.grabbedEntity, {
|
this.equipTractorID = Entities.addAction("tractor", this.grabbedEntity, {
|
||||||
targetPosition: targetPosition,
|
targetPosition: targetPosition,
|
||||||
linearTimeScale: EQUIP_SPRING_TIMEFRAME,
|
linearTimeScale: EQUIP_TRACTOR_TIMEFRAME,
|
||||||
targetRotation: targetRotation,
|
targetRotation: targetRotation,
|
||||||
angularTimeScale: EQUIP_SPRING_TIMEFRAME,
|
angularTimeScale: EQUIP_TRACTOR_TIMEFRAME,
|
||||||
ttl: ACTION_TTL
|
ttl: ACTION_TTL
|
||||||
});
|
});
|
||||||
if (this.equipSpringID === NULL_ACTION_ID) {
|
if (this.equipTractorID === NULL_ACTION_ID) {
|
||||||
this.equipSpringID = null;
|
this.equipTractorID = null;
|
||||||
this.setState(STATE_OFF);
|
this.setState(STATE_OFF);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Entities.updateAction(this.grabbedEntity, this.equipSpringID, {
|
Entities.updateAction(this.grabbedEntity, this.equipTractorID, {
|
||||||
targetPosition: targetPosition,
|
targetPosition: targetPosition,
|
||||||
linearTimeScale: EQUIP_SPRING_TIMEFRAME,
|
linearTimeScale: EQUIP_TRACTOR_TIMEFRAME,
|
||||||
targetRotation: targetRotation,
|
targetRotation: targetRotation,
|
||||||
angularTimeScale: EQUIP_SPRING_TIMEFRAME,
|
angularTimeScale: EQUIP_TRACTOR_TIMEFRAME,
|
||||||
ttl: ACTION_TTL
|
ttl: ACTION_TTL
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Vec3.distance(grabbedProperties.position, targetPosition) < EQUIP_SPRING_SHUTOFF_DISTANCE) {
|
if (Vec3.distance(grabbedProperties.position, targetPosition) < EQUIP_TRACTOR_SHUTOFF_DISTANCE) {
|
||||||
Entities.deleteAction(this.grabbedEntity, this.equipSpringID);
|
Entities.deleteAction(this.grabbedEntity, this.equipTractorID);
|
||||||
this.equipSpringID = null;
|
this.equipTractorID = null;
|
||||||
this.setState(STATE_EQUIP);
|
this.setState(STATE_EQUIP);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -862,4 +862,4 @@ function cleanup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Script.scriptEnding.connect(cleanup);
|
Script.scriptEnding.connect(cleanup);
|
||||||
Script.update.connect(update);
|
Script.update.connect(update);
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function coneTwistAndSpringLeverTest(params) {
|
function coneTwistAndTractorLeverTest(params) {
|
||||||
var pos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, {x: 0, y: -0.5, z: -2}));
|
var pos = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, {x: 0, y: -0.5, z: -2}));
|
||||||
var lifetime = params.lifetime;
|
var lifetime = params.lifetime;
|
||||||
|
|
||||||
|
@ -84,10 +84,10 @@
|
||||||
tag: "cone-twist test"
|
tag: "cone-twist test"
|
||||||
});
|
});
|
||||||
|
|
||||||
Entities.addAction("spring", leverID, {
|
Entities.addAction("tractor", leverID, {
|
||||||
targetRotation: { x: 0, y: 0, z: 0, w: 1 },
|
targetRotation: { x: 0, y: 0, z: 0, w: 1 },
|
||||||
angularTimeScale: 0.2,
|
angularTimeScale: 0.2,
|
||||||
tag: "cone-twist test spring"
|
tag: "cone-twist test tractor"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -349,11 +349,11 @@
|
||||||
userData: "{ \"grabbableKey\": { \"grabbable\": true, \"kinematic\": false } }"
|
userData: "{ \"grabbableKey\": { \"grabbable\": true, \"kinematic\": false } }"
|
||||||
});
|
});
|
||||||
|
|
||||||
Entities.addAction("spring", headID, {
|
Entities.addAction("tractor", headID, {
|
||||||
targetRotation: { x: 0, y: 0, z: 0, w: 1 },
|
targetRotation: { x: 0, y: 0, z: 0, w: 1 },
|
||||||
angularTimeScale: 2.0,
|
angularTimeScale: 2.0,
|
||||||
otherID: bodyID,
|
otherID: bodyID,
|
||||||
tag: "cone-twist test spring"
|
tag: "cone-twist test tractor"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -705,7 +705,7 @@
|
||||||
|
|
||||||
if (event["dynamics-tests-command"]) {
|
if (event["dynamics-tests-command"]) {
|
||||||
var commandToFunctionMap = {
|
var commandToFunctionMap = {
|
||||||
"cone-twist-and-spring-lever-test": coneTwistAndSpringLeverTest,
|
"cone-twist-and-tractor-lever-test": coneTwistAndTractorLeverTest,
|
||||||
"door-vs-world-test": doorVSWorldTest,
|
"door-vs-world-test": doorVSWorldTest,
|
||||||
"hinge-chain-test": hingeChainTest,
|
"hinge-chain-test": hingeChainTest,
|
||||||
"slider-vs-world-test": sliderVSWorldTest,
|
"slider-vs-world-test": sliderVSWorldTest,
|
||||||
|
|
|
@ -113,4 +113,4 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
return new SpringHold();
|
return new SpringHold();
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// touch.js
|
// touch.js
|
||||||
//
|
//
|
||||||
// Sample file using spring action, haptic vibration, and color change to demonstrate two spheres
|
// Sample file using tractor action, haptic vibration, and color change to demonstrate two spheres
|
||||||
// That can give a sense of touch to the holders.
|
// 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.
|
// Create two standard spheres, make them grabbable, and attach this entity script. Grab them and touch them together.
|
||||||
//
|
//
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
_this = this;
|
_this = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateSpringAction(timescale) {
|
function updateTractorAction(timescale) {
|
||||||
var targetProps = Entities.getEntityProperties(_this.entityID);
|
var targetProps = Entities.getEntityProperties(_this.entityID);
|
||||||
//
|
//
|
||||||
// Look for nearby entities to touch
|
// Look for nearby entities to touch
|
||||||
|
@ -113,7 +113,7 @@
|
||||||
var success = Entities.updateAction(_this.copy, _this.actionID, props);
|
var success = Entities.updateAction(_this.copy, _this.actionID, props);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSpringAction(timescale) {
|
function createTractorAction(timescale) {
|
||||||
|
|
||||||
var targetProps = Entities.getEntityProperties(_this.entityID);
|
var targetProps = Entities.getEntityProperties(_this.entityID);
|
||||||
var props = {
|
var props = {
|
||||||
|
@ -123,7 +123,7 @@
|
||||||
angularTimeScale: timescale,
|
angularTimeScale: timescale,
|
||||||
ttl: ACTION_TTL
|
ttl: ACTION_TTL
|
||||||
};
|
};
|
||||||
_this.actionID = Entities.addAction("spring", _this.copy, props);
|
_this.actionID = Entities.addAction("tractor", _this.copy, props);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteSpringAction() {
|
function deleteTractorAction() {
|
||||||
Entities.deleteAction(_this.copy, _this.actionID);
|
Entities.deleteAction(_this.copy, _this.actionID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,19 +188,19 @@
|
||||||
},
|
},
|
||||||
startNearGrab: function(entityID, data) {
|
startNearGrab: function(entityID, data) {
|
||||||
createCopy();
|
createCopy();
|
||||||
createSpringAction(TIMESCALE);
|
createTractorAction(TIMESCALE);
|
||||||
makeOriginalInvisible();
|
makeOriginalInvisible();
|
||||||
setHand(Entities.getEntityProperties(_this.entityID).position);
|
setHand(Entities.getEntityProperties(_this.entityID).position);
|
||||||
},
|
},
|
||||||
continueNearGrab: function() {
|
continueNearGrab: function() {
|
||||||
updateSpringAction(TIMESCALE);
|
updateTractorAction(TIMESCALE);
|
||||||
},
|
},
|
||||||
releaseGrab: function() {
|
releaseGrab: function() {
|
||||||
deleteSpringAction();
|
deleteTractorAction();
|
||||||
deleteCopy();
|
deleteCopy();
|
||||||
makeOriginalVisible();
|
makeOriginalVisible();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return new TouchExample();
|
return new TouchExample();
|
||||||
});
|
});
|
||||||
|
|
|
@ -89,7 +89,7 @@ LookAtTarget = function(sourceEntityID) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!actionFound) {
|
if (!actionFound) {
|
||||||
Entities.addAction('spring', _sourceEntityID, getNewActionProperties());
|
Entities.addAction('tractor', _sourceEntityID, getNewActionProperties());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue