resolve conflicts on merge with upstream/master

This commit is contained in:
Stephen Birarda 2015-10-28 15:19:10 -07:00
commit cee029f752
57 changed files with 857 additions and 684 deletions

View file

@ -226,7 +226,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
// if the allowed editors list is empty then everyone can adjust locks
bool canAdjustLocks = allowedEditors.empty();
if (allowedEditors.contains(username)) {
if (allowedEditors.contains(username, Qt::CaseInsensitive)) {
// we have a non-empty allowed editors list - check if this user is verified to be in it
if (!verifiedUsername) {
if (!verifyUserSignature(username, usernameSignature, HifiSockAddr())) {

View file

@ -96,7 +96,8 @@ else()
endif()
# link required hifi libraries
link_hifi_libraries(shared octree environment gpu procedural model render fbx networking model-networking entities avatars
link_hifi_libraries(shared octree environment gpu gl procedural model render
fbx networking model-networking entities avatars
audio audio-client animation script-engine physics
render-utils entities-renderer ui auto-updater
plugins display-plugins input-plugins)

View file

@ -70,7 +70,7 @@
#include <ObjectMotionState.h>
#include <OctalCode.h>
#include <OctreeSceneStats.h>
#include <OffscreenGlCanvas.h>
#include <gl/OffscreenGlCanvas.h>
#include <PathUtils.h>
#include <PerfStat.h>
#include <PhysicsEngine.h>
@ -2756,7 +2756,6 @@ void Application::update(float deltaTime) {
{
PerformanceTimer perfTimer("physics");
myAvatar->relayDriveKeysToCharacterController();
static VectorOfMotionStates motionStates;
_entitySimulation.getObjectsToDelete(motionStates);
@ -2783,6 +2782,8 @@ void Application::update(float deltaTime) {
avatarManager->getObjectsToChange(motionStates);
_physicsEngine->changeObjects(motionStates);
myAvatar->prepareForPhysicsSimulation();
_entities.getTree()->withWriteLock([&] {
_physicsEngine->stepSimulation();
});
@ -2807,6 +2808,8 @@ void Application::update(float deltaTime) {
// and will simulate entity motion (the EntityTree has been given an EntitySimulation).
_entities.update(); // update the models...
}
myAvatar->harvestResultsFromPhysicsSimulation();
}
}

View file

@ -154,7 +154,8 @@ void MyAvatar::reset(bool andReload) {
}
// Reset dynamic state.
_wasPushing = _isPushing = _isBraking = _billboardValid = _straighteningLean = false;
_wasPushing = _isPushing = _isBraking = _billboardValid = false;
_isFollowingHMD = false;
_skeletonModel.reset();
getHead()->reset();
_targetVelocity = glm::vec3(0.0f);
@ -304,7 +305,7 @@ glm::mat4 MyAvatar::getSensorToWorldMatrix() const {
// returns true if pos is OUTSIDE of the vertical capsule
// where the middle cylinder length is defined by capsuleLen and the radius by capsuleRad.
static bool capsuleCheck(const glm::vec3& pos, float capsuleLen, float capsuleRad) {
static bool pointIsOutsideCapsule(const glm::vec3& pos, float capsuleLen, float capsuleRad) {
const float halfCapsuleLen = capsuleLen / 2.0f;
if (fabs(pos.y) <= halfCapsuleLen) {
// cylinder check for middle capsule
@ -325,6 +326,10 @@ static bool capsuleCheck(const glm::vec3& pos, float capsuleLen, float capsuleRa
// This can also update the avatar's position to follow the HMD
// as it moves through the world.
void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) {
// update the sensorMatrices based on the new hmd pose
_hmdSensorMatrix = hmdSensorMatrix;
_hmdSensorPosition = extractTranslation(hmdSensorMatrix);
_hmdSensorOrientation = glm::quat_cast(hmdSensorMatrix);
// calc deltaTime
auto now = usecTimestampNow();
@ -334,11 +339,6 @@ void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) {
const float BIGGEST_DELTA_TIME_SECS = 0.25f;
float deltaTime = glm::clamp((float)actualDeltaTime, 0.0f, BIGGEST_DELTA_TIME_SECS);
// update the sensorMatrices based on the new hmd pose
_hmdSensorMatrix = hmdSensorMatrix;
_hmdSensorPosition = extractTranslation(hmdSensorMatrix);
_hmdSensorOrientation = glm::quat_cast(hmdSensorMatrix);
bool hmdIsAtRest = _hmdAtRestDetector.update(deltaTime, _hmdSensorPosition, _hmdSensorOrientation);
// It can be more accurate/smooth to use velocity rather than position,
@ -360,58 +360,60 @@ void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) {
bool justStartedMoving = (_lastIsMoving != isMoving) && isMoving;
_lastIsMoving = isMoving;
if (shouldBeginStraighteningLean() || hmdIsAtRest || justStartedMoving) {
beginStraighteningLean();
if (shouldFollowHMD() || hmdIsAtRest || justStartedMoving) {
beginFollowingHMD();
}
processStraighteningLean(deltaTime);
followHMD(deltaTime);
}
void MyAvatar::beginStraighteningLean() {
glm::vec3 MyAvatar::getHMDCorrectionVelocity() const {
// TODO: impelement this
return Vectors::ZERO;
}
void MyAvatar::beginFollowingHMD() {
// begin homing toward derived body position.
if (!_straighteningLean) {
_straighteningLean = true;
_straighteningLeanAlpha = 0.0f;
if (!_isFollowingHMD) {
_isFollowingHMD = true;
_followHMDAlpha = 0.0f;
}
}
bool MyAvatar::shouldBeginStraighteningLean() const {
// define a vertical capsule
const float STRAIGHTENING_LEAN_CAPSULE_RADIUS = 0.2f; // meters
const float STRAIGHTENING_LEAN_CAPSULE_LENGTH = 0.05f; // length of the cylinder part of the capsule in meters.
// detect if the derived body position is outside of a capsule around the _bodySensorMatrix
auto newBodySensorMatrix = deriveBodyFromHMDSensor();
glm::vec3 diff = extractTranslation(newBodySensorMatrix) - extractTranslation(_bodySensorMatrix);
bool isBodyPosOutsideCapsule = capsuleCheck(diff, STRAIGHTENING_LEAN_CAPSULE_LENGTH, STRAIGHTENING_LEAN_CAPSULE_RADIUS);
if (isBodyPosOutsideCapsule) {
return true;
} else {
return false;
bool MyAvatar::shouldFollowHMD() const {
if (!_isFollowingHMD) {
// define a vertical capsule
const float FOLLOW_HMD_CAPSULE_RADIUS = 0.2f; // meters
const float FOLLOW_HMD_CAPSULE_LENGTH = 0.05f; // length of the cylinder part of the capsule in meters.
// detect if the derived body position is outside of a capsule around the _bodySensorMatrix
auto newBodySensorMatrix = deriveBodyFromHMDSensor();
glm::vec3 localPoint = extractTranslation(newBodySensorMatrix) - extractTranslation(_bodySensorMatrix);
return pointIsOutsideCapsule(localPoint, FOLLOW_HMD_CAPSULE_LENGTH, FOLLOW_HMD_CAPSULE_RADIUS);
}
return false;
}
void MyAvatar::processStraighteningLean(float deltaTime) {
if (_straighteningLean) {
void MyAvatar::followHMD(float deltaTime) {
if (_isFollowingHMD) {
const float STRAIGHTENING_LEAN_DURATION = 0.5f; // seconds
const float FOLLOW_HMD_DURATION = 0.5f; // seconds
auto newBodySensorMatrix = deriveBodyFromHMDSensor();
auto worldBodyMatrix = _sensorToWorldMatrix * newBodySensorMatrix;
glm::vec3 worldBodyPos = extractTranslation(worldBodyMatrix);
glm::quat worldBodyRot = glm::normalize(glm::quat_cast(worldBodyMatrix));
_straighteningLeanAlpha += (1.0f / STRAIGHTENING_LEAN_DURATION) * deltaTime;
_followHMDAlpha += (1.0f / FOLLOW_HMD_DURATION) * deltaTime;
if (_straighteningLeanAlpha >= 1.0f) {
_straighteningLean = false;
if (_followHMDAlpha >= 1.0f) {
_isFollowingHMD = false;
nextAttitude(worldBodyPos, worldBodyRot);
_bodySensorMatrix = newBodySensorMatrix;
} else {
// interp position toward the desired pos
glm::vec3 pos = lerp(getPosition(), worldBodyPos, _straighteningLeanAlpha);
glm::quat rot = glm::normalize(safeMix(getOrientation(), worldBodyRot, _straighteningLeanAlpha));
glm::vec3 pos = lerp(getPosition(), worldBodyPos, _followHMDAlpha);
glm::quat rot = glm::normalize(safeMix(getOrientation(), worldBodyRot, _followHMDAlpha));
nextAttitude(pos, rot);
// interp sensor matrix toward desired
@ -419,8 +421,8 @@ void MyAvatar::processStraighteningLean(float deltaTime) {
glm::quat nextBodyRot = glm::normalize(glm::quat_cast(newBodySensorMatrix));
glm::vec3 prevBodyPos = extractTranslation(_bodySensorMatrix);
glm::quat prevBodyRot = glm::normalize(glm::quat_cast(_bodySensorMatrix));
pos = lerp(prevBodyPos, nextBodyPos, _straighteningLeanAlpha);
rot = glm::normalize(safeMix(prevBodyRot, nextBodyRot, _straighteningLeanAlpha));
pos = lerp(prevBodyPos, nextBodyPos, _followHMDAlpha);
rot = glm::normalize(safeMix(prevBodyRot, nextBodyRot, _followHMDAlpha));
_bodySensorMatrix = createMatFromQuatAndPos(rot, pos);
}
}
@ -1274,6 +1276,23 @@ void MyAvatar::rebuildSkeletonBody() {
_characterController.setLocalBoundingBox(corner, scale);
}
void MyAvatar::prepareForPhysicsSimulation() {
relayDriveKeysToCharacterController();
_characterController.setTargetVelocity(getTargetVelocity());
_characterController.setAvatarPositionAndOrientation(getPosition(), getOrientation());
_characterController.setHMDVelocity(getHMDCorrectionVelocity());
}
void MyAvatar::harvestResultsFromPhysicsSimulation() {
glm::vec3 position = getPosition();
glm::quat orientation = getOrientation();
_characterController.getAvatarPositionAndOrientation(position, orientation);
nextAttitude(position, orientation);
setVelocity(_characterController.getLinearVelocity());
// TODO: harvest HMD shift here
//glm::vec3 hmdShift = _characterController.getHMDShift();
}
QString MyAvatar::getScriptedMotorFrame() const {
QString frame = "avatar";
if (_scriptedMotorFrame == SCRIPTED_MOTOR_CAMERA_FRAME) {

View file

@ -12,12 +12,15 @@
#ifndef hifi_MyAvatar_h
#define hifi_MyAvatar_h
#include <glm/glm.hpp>
#include <SettingHandle.h>
#include <DynamicCharacterController.h>
#include <Rig.h>
#include "Avatar.h"
#include "AtRestDetector.h"
#include "MyCharacterController.h"
class ModelItemID;
@ -72,6 +75,8 @@ public:
// as it moves through the world.
void updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix);
glm::vec3 getHMDCorrectionVelocity() const;
// best called at end of main loop, just before rendering.
// update sensor to world matrix from current body position and hmd sensor.
// This is so the correct camera can be used for rendering.
@ -154,10 +159,12 @@ public:
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData) override;
DynamicCharacterController* getCharacterController() { return &_characterController; }
MyCharacterController* getCharacterController() { return &_characterController; }
void prepareForPhysicsSimulation();
void harvestResultsFromPhysicsSimulation();
const QString& getCollisionSoundURL() {return _collisionSoundURL; }
const QString& getCollisionSoundURL() { return _collisionSoundURL; }
void setCollisionSoundURL(const QString& url);
void clearScriptableSettings();
@ -262,9 +269,9 @@ private:
const RecorderPointer getRecorder() const { return _recorder; }
const PlayerPointer getPlayer() const { return _player; }
void beginStraighteningLean();
bool shouldBeginStraighteningLean() const;
void processStraighteningLean(float deltaTime);
void beginFollowingHMD();
bool shouldFollowHMD() const;
void followHMD(float deltaTime);
bool cameraInsideHead() const;
@ -295,7 +302,7 @@ private:
quint32 _motionBehaviors;
QString _collisionSoundURL;
DynamicCharacterController _characterController;
MyCharacterController _characterController;
AvatarWeakPointer _lookAtTargetAvatar;
glm::vec3 _targetAvatarPosition;
@ -348,21 +355,21 @@ private:
RigPointer _rig;
bool _prevShouldDrawHead;
bool _enableDebugDrawBindPose = false;
bool _enableDebugDrawAnimPose = false;
AnimSkeleton::ConstPointer _debugDrawSkeleton = nullptr;
bool _enableDebugDrawBindPose { false };
bool _enableDebugDrawAnimPose { false };
AnimSkeleton::ConstPointer _debugDrawSkeleton { nullptr };
AudioListenerMode _audioListenerMode;
glm::vec3 _customListenPosition;
glm::quat _customListenOrientation;
bool _straighteningLean = false;
float _straighteningLeanAlpha = 0.0f;
bool _isFollowingHMD { false };
float _followHMDAlpha { 0.0f };
quint64 _lastUpdateFromHMDTime = usecTimestampNow();
quint64 _lastUpdateFromHMDTime { usecTimestampNow() };
AtRestDetector _hmdAtRestDetector;
glm::vec3 _lastPosition;
bool _lastIsMoving = false;
bool _lastIsMoving { false };
};
QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode);

View file

@ -1,13 +1,26 @@
//
// MyCharacterController.h
// interface/src/avatar
//
// Created by AndrewMeadows 2015.10.21
// 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 "MyCharacterController.h"
#include <BulletCollision/CollisionShapes/btMultiSphereShape.h>
#include <BulletDynamics/Dynamics/btRigidBody.h>
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
#include <LinearMath/btDefaultMotionState.h>
#include <GLMHelpers.h>
#include <PhysicsLogging.h>
#include <PhysicsCollisionGroups.h>
#include "BulletUtil.h"
#include "DynamicCharacterController.h"
#include "PhysicsLogging.h"
#include "MyAvatar.h"
const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f);
const float DEFAULT_GRAVITY = -5.0f;
@ -15,11 +28,6 @@ const float JUMP_SPEED = 3.5f;
const float MAX_FALL_HEIGHT = 20.0f;
const uint32_t PENDING_FLAG_ADD_TO_SIMULATION = 1U << 0;
const uint32_t PENDING_FLAG_REMOVE_FROM_SIMULATION = 1U << 1;
const uint32_t PENDING_FLAG_UPDATE_SHAPE = 1U << 2;
const uint32_t PENDING_FLAG_JUMP = 1U << 3;
// TODO: improve walking up steps
// TODO: make avatars able to walk up and down steps/slopes
// TODO: make avatars stand on steep slope
@ -41,19 +49,18 @@ protected:
btRigidBody* _me;
};
DynamicCharacterController::DynamicCharacterController(AvatarData* avatarData) {
MyCharacterController::MyCharacterController(MyAvatar* avatar) {
_halfHeight = 1.0f;
_shape = nullptr;
_rigidBody = nullptr;
assert(avatarData);
_avatarData = avatarData;
assert(avatar);
_avatar = avatar;
_enabled = false;
_floorDistance = MAX_FALL_HEIGHT;
_walkVelocity.setValue(0.0f,0.0f,0.0f);
_walkVelocity.setValue(0.0f, 0.0f, 0.0f);
_hmdVelocity.setValue(0.0f, 0.0f, 0.0f);
_jumpSpeed = JUMP_SPEED;
_isOnGround = false;
_isJumping = false;
@ -61,21 +68,16 @@ DynamicCharacterController::DynamicCharacterController(AvatarData* avatarData) {
_isHovering = true;
_isPushingUp = false;
_jumpToHoverStart = 0;
_lastStepDuration = 0.0f;
_pendingFlags = PENDING_FLAG_UPDATE_SHAPE;
updateShapeIfNecessary();
}
DynamicCharacterController::~DynamicCharacterController() {
MyCharacterController::~MyCharacterController() {
}
// virtual
void DynamicCharacterController::setWalkDirection(const btVector3& walkDirection) {
// do nothing -- walkVelocity is upated in preSimulation()
//_walkVelocity = walkDirection;
}
void DynamicCharacterController::preStep(btCollisionWorld* collisionWorld) {
void MyCharacterController::preStep(btCollisionWorld* collisionWorld) {
// trace a ray straight down to see if we're standing on the ground
const btTransform& xform = _rigidBody->getWorldTransform();
@ -96,7 +98,7 @@ void DynamicCharacterController::preStep(btCollisionWorld* collisionWorld) {
}
}
void DynamicCharacterController::playerStep(btCollisionWorld* dynaWorld, btScalar dt) {
void MyCharacterController::playerStep(btCollisionWorld* dynaWorld, btScalar dt) {
btVector3 actualVelocity = _rigidBody->getLinearVelocity();
btScalar actualSpeed = actualVelocity.length();
@ -158,9 +160,20 @@ void DynamicCharacterController::playerStep(btCollisionWorld* dynaWorld, btScala
_rigidBody->setLinearVelocity(actualVelocity + tau * velocityCorrection);
}
}
// Rather than add _hmdVelocity to the velocity of the RigidBody, we explicitly teleport
// the RigidBody forward according to the formula: distance = rate * time
if (_hmdVelocity.length2() > 0.0f) {
btTransform bodyTransform = _rigidBody->getWorldTransform();
bodyTransform.setOrigin(bodyTransform.getOrigin() + dt * _hmdVelocity);
_rigidBody->setWorldTransform(bodyTransform);
}
// MyAvatar will ask us how far we stepped for HMD motion, which will depend on how
// much time has accumulated in _lastStepDuration.
_lastStepDuration += dt;
}
void DynamicCharacterController::jump() {
void MyCharacterController::jump() {
// check for case where user is holding down "jump" key...
// we'll eventually tansition to "hover"
if (!_isJumping) {
@ -178,12 +191,12 @@ void DynamicCharacterController::jump() {
}
}
bool DynamicCharacterController::onGround() const {
bool MyCharacterController::onGround() const {
const btScalar FLOOR_PROXIMITY_THRESHOLD = 0.3f * _radius;
return _floorDistance < FLOOR_PROXIMITY_THRESHOLD;
}
void DynamicCharacterController::setHovering(bool hover) {
void MyCharacterController::setHovering(bool hover) {
if (hover != _isHovering) {
_isHovering = hover;
_isJumping = false;
@ -198,7 +211,7 @@ void DynamicCharacterController::setHovering(bool hover) {
}
}
void DynamicCharacterController::setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale) {
void MyCharacterController::setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale) {
_boxScale = scale;
float x = _boxScale.x;
@ -231,15 +244,7 @@ void DynamicCharacterController::setLocalBoundingBox(const glm::vec3& corner, co
_shapeLocalOffset = corner + 0.5f * _boxScale;
}
bool DynamicCharacterController::needsRemoval() const {
return (bool)(_pendingFlags & PENDING_FLAG_REMOVE_FROM_SIMULATION);
}
bool DynamicCharacterController::needsAddition() const {
return (bool)(_pendingFlags & PENDING_FLAG_ADD_TO_SIMULATION);
}
void DynamicCharacterController::setEnabled(bool enabled) {
void MyCharacterController::setEnabled(bool enabled) {
if (enabled != _enabled) {
if (enabled) {
// Don't bother clearing REMOVE bit since it might be paired with an UPDATE_SHAPE bit.
@ -257,46 +262,9 @@ void DynamicCharacterController::setEnabled(bool enabled) {
}
}
void DynamicCharacterController::setDynamicsWorld(btDynamicsWorld* world) {
if (_dynamicsWorld != world) {
if (_dynamicsWorld) {
if (_rigidBody) {
_dynamicsWorld->removeRigidBody(_rigidBody);
_dynamicsWorld->removeAction(this);
}
_dynamicsWorld = nullptr;
}
if (world && _rigidBody) {
_dynamicsWorld = world;
_pendingFlags &= ~ PENDING_FLAG_JUMP;
_dynamicsWorld->addRigidBody(_rigidBody, COLLISION_GROUP_MY_AVATAR, COLLISION_MASK_MY_AVATAR);
_dynamicsWorld->addAction(this);
//reset(_dynamicsWorld);
}
}
if (_dynamicsWorld) {
if (_pendingFlags & PENDING_FLAG_UPDATE_SHAPE) {
// shouldn't fall in here, but if we do make sure both ADD and REMOVE bits are still set
_pendingFlags |= PENDING_FLAG_ADD_TO_SIMULATION | PENDING_FLAG_REMOVE_FROM_SIMULATION;
} else {
_pendingFlags &= ~PENDING_FLAG_ADD_TO_SIMULATION;
}
} else {
_pendingFlags &= ~ PENDING_FLAG_REMOVE_FROM_SIMULATION;
}
}
void DynamicCharacterController::updateShapeIfNecessary() {
void MyCharacterController::updateShapeIfNecessary() {
if (_pendingFlags & PENDING_FLAG_UPDATE_SHAPE) {
// make sure there is NO pending removal from simulation at this point
// (don't want to delete _rigidBody out from under the simulation)
assert(!(_pendingFlags & PENDING_FLAG_REMOVE_FROM_SIMULATION));
_pendingFlags &= ~ PENDING_FLAG_UPDATE_SHAPE;
// delete shape and RigidBody
delete _rigidBody;
_rigidBody = nullptr;
delete _shape;
_shape = nullptr;
// compute new dimensions from avatar's bounding box
float x = _boxScale.x;
@ -310,19 +278,27 @@ void DynamicCharacterController::updateShapeIfNecessary() {
// NOTE: _shapeLocalOffset is already computed
if (_radius > 0.0f) {
// create new shape
_shape = new btCapsuleShape(_radius, 2.0f * _halfHeight);
// HACK: use some simple mass property defaults for now
float mass = 100.0f;
btVector3 inertia(30.0f, 8.0f, 30.0f);
// create new body
_rigidBody = new btRigidBody(mass, nullptr, _shape, inertia);
// create RigidBody if it doesn't exist
if (!_rigidBody) {
btCollisionShape* shape = new btCapsuleShape(_radius, 2.0f * _halfHeight);
_rigidBody = new btRigidBody(mass, nullptr, shape, inertia);
} else {
btCollisionShape* shape = _rigidBody->getCollisionShape();
if (shape) {
delete shape;
}
shape = new btCapsuleShape(_radius, 2.0f * _halfHeight);
_rigidBody->setCollisionShape(shape);
}
_rigidBody->setSleepingThresholds(0.0f, 0.0f);
_rigidBody->setAngularFactor(0.0f);
_rigidBody->setWorldTransform(btTransform(glmToBullet(_avatarData->getOrientation()),
glmToBullet(_avatarData->getPosition())));
_rigidBody->setWorldTransform(btTransform(glmToBullet(_avatar->getOrientation()),
glmToBullet(_avatar->getPosition())));
if (_isHovering) {
_rigidBody->setGravity(btVector3(0.0f, 0.0f, 0.0f));
} else {
@ -335,7 +311,7 @@ void DynamicCharacterController::updateShapeIfNecessary() {
}
}
void DynamicCharacterController::updateUpAxis(const glm::quat& rotation) {
void MyCharacterController::updateUpAxis(const glm::quat& rotation) {
btVector3 oldUp = _currentUp;
_currentUp = quatRotate(glmToBullet(rotation), LOCAL_UP_AXIS);
if (!_isHovering) {
@ -346,24 +322,50 @@ void DynamicCharacterController::updateUpAxis(const glm::quat& rotation) {
}
}
void DynamicCharacterController::preSimulation(btScalar timeStep) {
void MyCharacterController::setAvatarPositionAndOrientation(
const glm::vec3& position,
const glm::quat& orientation) {
// TODO: update gravity if up has changed
updateUpAxis(orientation);
btQuaternion bodyOrientation = glmToBullet(orientation);
btVector3 bodyPosition = glmToBullet(position + orientation * _shapeLocalOffset);
_avatarBodyTransform = btTransform(bodyOrientation, bodyPosition);
}
void MyCharacterController::getAvatarPositionAndOrientation(glm::vec3& position, glm::quat& rotation) const {
if (_enabled && _rigidBody) {
const btTransform& avatarTransform = _rigidBody->getWorldTransform();
rotation = bulletToGLM(avatarTransform.getRotation());
position = bulletToGLM(avatarTransform.getOrigin()) - rotation * _shapeLocalOffset;
}
}
void MyCharacterController::setTargetVelocity(const glm::vec3& velocity) {
//_walkVelocity = glmToBullet(_avatarData->getTargetVelocity());
_walkVelocity = glmToBullet(velocity);
}
void MyCharacterController::setHMDVelocity(const glm::vec3& velocity) {
_hmdVelocity = glmToBullet(velocity);
}
glm::vec3 MyCharacterController::getLinearVelocity() const {
glm::vec3 velocity(0.0f);
if (_rigidBody) {
velocity = bulletToGLM(_rigidBody->getLinearVelocity());
}
return velocity;
}
void MyCharacterController::preSimulation() {
if (_enabled && _dynamicsWorld) {
glm::quat rotation = _avatarData->getOrientation();
// TODO: update gravity if up has changed
updateUpAxis(rotation);
glm::vec3 position = _avatarData->getPosition() + rotation * _shapeLocalOffset;
_rigidBody->setWorldTransform(btTransform(glmToBullet(rotation), glmToBullet(position)));
// the rotation is dictated by AvatarData
btTransform xform = _rigidBody->getWorldTransform();
xform.setRotation(glmToBullet(rotation));
_rigidBody->setWorldTransform(xform);
// slam body to where it is supposed to be
_rigidBody->setWorldTransform(_avatarBodyTransform);
// scan for distant floor
// rayStart is at center of bottom sphere
btVector3 rayStart = xform.getOrigin() - _halfHeight * _currentUp;
btVector3 rayStart = _avatarBodyTransform.getOrigin() - _halfHeight * _currentUp;
// rayEnd is straight down MAX_FALL_HEIGHT
btScalar rayLength = _radius + MAX_FALL_HEIGHT;
@ -388,8 +390,6 @@ void DynamicCharacterController::preSimulation(btScalar timeStep) {
setHovering(true);
}
_walkVelocity = glmToBullet(_avatarData->getTargetVelocity());
if (_pendingFlags & PENDING_FLAG_JUMP) {
_pendingFlags &= ~ PENDING_FLAG_JUMP;
if (onGround()) {
@ -400,15 +400,9 @@ void DynamicCharacterController::preSimulation(btScalar timeStep) {
}
}
}
_lastStepDuration = 0.0f;
}
void DynamicCharacterController::postSimulation() {
if (_enabled && _rigidBody) {
const btTransform& avatarTransform = _rigidBody->getWorldTransform();
glm::quat rotation = bulletToGLM(avatarTransform.getRotation());
glm::vec3 position = bulletToGLM(avatarTransform.getOrigin());
_avatarData->nextAttitude(position - rotation * _shapeLocalOffset, rotation);
_avatarData->setVelocity(bulletToGLM(_rigidBody->getLinearVelocity()));
}
void MyCharacterController::postSimulation() {
// postSimulation() exists for symmetry and just in case we need to do something here later
}

View file

@ -0,0 +1,106 @@
//
// MyCharacterController.h
// interface/src/avatar
//
// Created by AndrewMeadows 2015.10.21
// 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_MyCharacterController_h
#define hifi_MyCharacterController_h
#include <btBulletDynamicsCommon.h>
#include <glm/glm.hpp>
#include <BulletUtil.h>
#include <CharacterController.h>
#include <SharedUtil.h>
class btCollisionShape;
class MyAvatar;
class MyCharacterController : public CharacterController {
public:
MyCharacterController(MyAvatar* avatar);
~MyCharacterController ();
// TODO: implement these when needed
virtual void setVelocityForTimeInterval(const btVector3 &velocity, btScalar timeInterval) override { assert(false); }
virtual void reset(btCollisionWorld* collisionWorld) override { }
virtual void warp(const btVector3& origin) override { }
virtual void debugDraw(btIDebugDraw* debugDrawer) override { }
virtual void setUpInterpolate(bool value) override { }
// overrides from btCharacterControllerInterface
virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTime) override {
preStep(collisionWorld);
playerStep(collisionWorld, deltaTime);
}
virtual void preStep(btCollisionWorld* collisionWorld) override;
virtual void playerStep(btCollisionWorld* collisionWorld, btScalar dt) override;
virtual bool canJump() const override { assert(false); return false; } // never call this
virtual void jump() override; // call this every frame the jump button is pressed
virtual bool onGround() const override;
// overrides from CharacterController
virtual void preSimulation() override;
virtual void postSimulation() override;
bool isHovering() const { return _isHovering; }
void setHovering(bool enabled);
void setEnabled(bool enabled);
bool isEnabled() const { return _enabled && _dynamicsWorld; }
void setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale);
virtual void updateShapeIfNecessary() override;
void setAvatarPositionAndOrientation( const glm::vec3& position, const glm::quat& orientation);
void getAvatarPositionAndOrientation(glm::vec3& position, glm::quat& rotation) const;
void setTargetVelocity(const glm::vec3& velocity);
void setHMDVelocity(const glm::vec3& velocity);
glm::vec3 getHMDShift() const { return _lastStepDuration * bulletToGLM(_hmdVelocity); }
glm::vec3 getLinearVelocity() const;
protected:
void updateUpAxis(const glm::quat& rotation);
protected:
btVector3 _currentUp;
btVector3 _walkVelocity;
btVector3 _hmdVelocity;
btTransform _avatarBodyTransform;
glm::vec3 _shapeLocalOffset;
glm::vec3 _boxScale; // used to compute capsule shape
quint64 _jumpToHoverStart;
MyAvatar* _avatar { nullptr };
btScalar _halfHeight;
btScalar _radius;
btScalar _floorDistance;
btScalar _gravity;
btScalar _jumpSpeed;
btScalar _lastStepDuration;
bool _enabled;
bool _isOnGround;
bool _isJumping;
bool _isFalling;
bool _isHovering;
bool _isPushingUp;
};
#endif // hifi_MyCharacterController_h

View file

@ -106,8 +106,11 @@ void JSConsole::executeCommand(const QString& command) {
QScriptValue JSConsole::executeCommandInWatcher(const QString& command) {
QScriptValue result;
static const QString filename = "JSConcole";
QMetaObject::invokeMethod(_scriptEngine, "evaluate", Qt::ConnectionType::BlockingQueuedConnection,
Q_RETURN_ARG(QScriptValue, result), Q_ARG(const QString&, command));
Q_RETURN_ARG(QScriptValue, result),
Q_ARG(const QString&, command),
Q_ARG(const QString&, filename));
return result;
}

View file

@ -27,7 +27,7 @@
#include <RegisteredMetaTypes.h>
#include <AbstractViewStateInterface.h>
#include <OffscreenQmlSurface.h>
#include <gl/OffscreenQmlSurface.h>
static const float DPI = 30.47f;
static const float INCHES_TO_METERS = 1.0f / 39.3701f;

View file

@ -366,7 +366,7 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars
if (offsetLength > MIN_HIPS_OFFSET_LENGTH) {
// but only if offset is long enough
float scaleFactor = ((offsetLength - MIN_HIPS_OFFSET_LENGTH) / offsetLength);
_relativePoses[0].trans = underPoses[0].trans + scaleFactor * _hipsOffset;
_relativePoses[_hipsIndex].trans = underPoses[_hipsIndex].trans + scaleFactor * _hipsOffset;
}
solveWithCyclicCoordinateDescent(targets);
@ -758,8 +758,10 @@ void AnimInverseKinematics::setSkeletonInternal(AnimSkeleton::ConstPointer skele
if (skeleton) {
initConstraints();
_headIndex = _skeleton->nameToJointIndex("Head");
_hipsIndex = _skeleton->nameToJointIndex("Hips");
} else {
clearConstraints();
_headIndex = -1;
_hipsIndex = -1;
}
}

View file

@ -80,6 +80,7 @@ protected:
// experimental data for moving hips during IK
int _headIndex = -1;
int _hipsIndex = -1;
glm::vec3 _hipsOffset = Vectors::ZERO;
// _maxTargetIndex is tracked to help optimize the recalculation of absolute poses

View file

@ -1,6 +1,6 @@
set(TARGET_NAME display-plugins)
setup_hifi_library(OpenGL)
link_hifi_libraries(shared plugins gpu render-utils)
link_hifi_libraries(shared plugins gpu gl)
target_opengl()

View file

@ -12,8 +12,8 @@
#include <QPoint>
#include <functional>
#include "gpu/GPUConfig.h"
#include "GLMHelpers.h"
#include <gl/Config.h>
#include <GLMHelpers.h>
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>

View file

@ -9,7 +9,7 @@
#include <QOpenGLContext>
#include <QCoreApplication>
#include <GlWindow.h>
#include <gl/GlWindow.h>
#include <GLMHelpers.h>

View file

@ -7,10 +7,10 @@
//
#pragma once
#include <QTimer>
#include "DisplayPlugin.h"
#include "OglplusHelpers.h"
#include <QTimer>
#include <gl/OglplusHelpers.h>
class GlWindow;
class QOpenGLContext;

View file

@ -12,7 +12,7 @@
#include <QMainWindow>
#include <QGLWidget>
#include <GLMHelpers.h>
#include <GlWindow.h>
#include <gl/GlWindow.h>
#include <QEvent>
#include <QResizeEvent>
#include <QOpenGLContext>
@ -20,7 +20,7 @@
#include <QScreen>
#include <PerfStat.h>
#include <OglplusHelpers.h>
#include <gl/OglplusHelpers.h>
#include <ViewFrustum.h>
#include "plugins/PluginContainer.h"

View file

@ -14,7 +14,7 @@
#include <QMainWindow>
#include <QGLWidget>
#include <GLMHelpers.h>
#include <GlWindow.h>
#include <gl/GlWindow.h>
#include <QEvent>
#include <QResizeEvent>

View file

@ -11,7 +11,7 @@
#include <QApplication>
#include <QDesktopWidget>
#include <GlWindow.h>
#include <gl/GlWindow.h>
#include <ViewFrustum.h>
#include <MatrixStack.h>

View file

@ -12,7 +12,7 @@
#include <QDesktopWidget>
#include <QScreen>
#include <GlWindow.h>
#include <gl/GlWindow.h>
#include <ViewFrustum.h>
#include <MatrixStack.h>

View file

@ -1,7 +1,7 @@
set(TARGET_NAME entities-renderer)
AUTOSCRIBE_SHADER_LIB(gpu model render render-utils)
setup_hifi_library(Widgets Network Script)
link_hifi_libraries(shared gpu procedural model model-networking script-engine render render-utils)
link_hifi_libraries(shared gpu procedural model model-networking script-engine render render-utils gl)
target_bullet()

View file

@ -37,7 +37,7 @@ PolyLineEntityItem(entityItemID, properties) {
gpu::PipelinePointer RenderablePolyLineEntityItem::_pipeline;
gpu::Stream::FormatPointer RenderablePolyLineEntityItem::_format;
gpu::TexturePointer RenderablePolyLineEntityItem::_texture;
GLint RenderablePolyLineEntityItem::PAINTSTROKE_GPU_SLOT;
int32_t RenderablePolyLineEntityItem::PAINTSTROKE_GPU_SLOT;
void RenderablePolyLineEntityItem::createPipeline() {
static const int NORMAL_OFFSET = 12;

View file

@ -18,7 +18,6 @@
#include "RenderableEntityItem.h"
#include <GeometryCache.h>
#include <QReadWriteLock>
#include <gpu/GPUConfig.h>
class RenderablePolyLineEntityItem : public PolyLineEntityItem {
@ -34,7 +33,7 @@ public:
static gpu::PipelinePointer _pipeline;
static gpu::Stream::FormatPointer _format;
static gpu::TexturePointer _texture;
static GLint PAINTSTROKE_GPU_SLOT;
static int32_t PAINTSTROKE_GPU_SLOT;
protected:
void updateGeometry();

View file

@ -18,7 +18,7 @@
#include <DeferredLightingEffect.h>
#include <GeometryCache.h>
#include <PerfStat.h>
#include <OffscreenQmlSurface.h>
#include <gl/OffscreenQmlSurface.h>
#include <AbstractViewStateInterface.h>
#include <GLMHelpers.h>
#include <PathUtils.h>

View file

@ -1790,9 +1790,17 @@ const QByteArray EntityItem::getActionDataInternal() const {
const QByteArray EntityItem::getActionData() const {
QByteArray result;
assertUnlocked();
withReadLock([&] {
result = getActionDataInternal();
});
if (_actionDataDirty) {
withWriteLock([&] {
getActionDataInternal();
result = _allActionsDataCache;
});
} else {
withReadLock([&] {
result = _allActionsDataCache;
});
}
return result;
}

View file

@ -0,0 +1,7 @@
set(TARGET_NAME gl)
setup_hifi_library(OpenGL Qml Quick)
link_hifi_libraries(shared)
target_glew()
target_opengl()
target_oglplus()

View file

@ -8,9 +8,10 @@
#include "GlWindow.h"
#include <QOpenGLContext>
#include <QOpenGLDebugLogger>
#include <GLHelpers.h>
#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLDebugLogger>
#include "GLHelpers.h"
GlWindow::GlWindow(QOpenGLContext* shareContext) : GlWindow(getDefaultOpenGlSurfaceFormat(), shareContext) {
}

View file

@ -12,10 +12,11 @@
#include "OffscreenGlCanvas.h"
#include <GLHelpers.h>
#include <QOpenGLDebugLogger>
#include <QOpenGLContext>
#include <QOffscreenSurface>
#include <QtGui/QOffscreenSurface>
#include <QtGui/QOpenGLDebugLogger>
#include <QtGui/QOpenGLContext>
#include "GLHelpers.h"
OffscreenGlCanvas::OffscreenGlCanvas() : _context(new QOpenGLContext), _offscreenSurface(new QOffscreenSurface){
}

View file

@ -23,7 +23,6 @@
#include "GLEscrow.h"
#include "OffscreenGlCanvas.h"
#include "AbstractViewStateInterface.h"
// FIXME move to threaded rendering with Qt 5.5
// #define QML_THREADED
@ -207,9 +206,7 @@ private:
qreal pixelRatio = 1.0;
if (_renderControl && _renderControl->_renderWindow) {
pixelRatio = _renderControl->_renderWindow->devicePixelRatio();
} else {
pixelRatio = AbstractViewStateInterface::instance()->getDevicePixelRatio();
}
}
uvec2 newOffscreenSize = toGlm(newSize * pixelRatio);
_textures.setSize(newOffscreenSize);

View file

@ -1,7 +1,7 @@
set(TARGET_NAME gpu)
AUTOSCRIBE_SHADER_LIB(gpu)
setup_hifi_library()
link_hifi_libraries(shared)
link_hifi_libraries(shared gl)
target_glew()
target_opengl()

View file

@ -18,7 +18,7 @@
#include <utility>
#include <list>
#include "GPUConfig.h"
#include <gl/Config.h>
#include "Context.h"

View file

@ -167,7 +167,10 @@ void SixenseManager::update(float deltaTime, bool jointsCaptured) {
if (sixenseGetNumActiveControllers() == 0) {
if (_hydrasConnected) {
qCDebug(inputplugins, "hydra disconnected");
qCDebug(inputplugins) << "hydra disconnected" << _badDataCount;
if (_badDataCount++ < _allowedBadDataCount) { // gotta get some no-active in a row before we shut things down
return;
}
}
_hydrasConnected = false;
if (_deviceID != 0) {
@ -181,6 +184,7 @@ void SixenseManager::update(float deltaTime, bool jointsCaptured) {
PerformanceTimer perfTimer("sixense");
if (!_hydrasConnected) {
_hydrasConnected = true;
_badDataCount = 0;
registerToUserInputMapper(*userInputMapper);
assignDefaultInputMapping(*userInputMapper);
UserActivityLogger::getInstance().connectedDevice("spatial_controller", "hydra");
@ -555,6 +559,7 @@ void SixenseManager::saveSettings() const {
settings.setVec3Value(QString("avatarPosition"), _avatarPosition);
settings.setQuatValue(QString("avatarRotation"), _avatarRotation);
settings.setValue(QString("reachLength"), QVariant(_reachLength));
settings.setValue(QString("allowedHydraFailures"), 120);
}
settings.endGroup();
}
@ -567,6 +572,7 @@ void SixenseManager::loadSettings() {
settings.getVec3ValueIfValid(QString("avatarPosition"), _avatarPosition);
settings.getQuatValueIfValid(QString("avatarRotation"), _avatarRotation);
settings.getFloatValueIfValid(QString("reachLength"), _reachLength);
_allowedBadDataCount = settings.value(QString("allowedHydraFailures"), 120).toInt();
}
settings.endGroup();
}

View file

@ -114,6 +114,8 @@ private:
#endif
bool _hydrasConnected;
int _badDataCount;
int _allowedBadDataCount;
static const QString NAME;
static const QString HYDRA_ID_STRING;

View file

@ -0,0 +1,52 @@
//
// CharacterControllerInterface.cpp
// libraries/physcis/src
//
// Created by Andrew Meadows 2015.10.21
// 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 "CharacterController.h"
#include "PhysicsCollisionGroups.h"
bool CharacterController::needsRemoval() const {
return (bool)(_pendingFlags & PENDING_FLAG_REMOVE_FROM_SIMULATION);
}
bool CharacterController::needsAddition() const {
return (bool)(_pendingFlags & PENDING_FLAG_ADD_TO_SIMULATION);
}
void CharacterController::setDynamicsWorld(btDynamicsWorld* world) {
if (_dynamicsWorld != world) {
if (_dynamicsWorld) {
if (_rigidBody) {
_dynamicsWorld->removeRigidBody(_rigidBody);
_dynamicsWorld->removeAction(this);
}
_dynamicsWorld = nullptr;
}
if (world && _rigidBody) {
_dynamicsWorld = world;
_pendingFlags &= ~PENDING_FLAG_JUMP;
_dynamicsWorld->addRigidBody(_rigidBody, COLLISION_GROUP_MY_AVATAR, COLLISION_MASK_MY_AVATAR);
_dynamicsWorld->addAction(this);
//reset(_dynamicsWorld);
}
}
if (_dynamicsWorld) {
if (_pendingFlags & PENDING_FLAG_UPDATE_SHAPE) {
// shouldn't fall in here, but if we do make sure both ADD and REMOVE bits are still set
_pendingFlags |= PENDING_FLAG_ADD_TO_SIMULATION | PENDING_FLAG_REMOVE_FROM_SIMULATION;
} else {
_pendingFlags &= ~PENDING_FLAG_ADD_TO_SIMULATION;
}
} else {
_pendingFlags &= ~PENDING_FLAG_REMOVE_FROM_SIMULATION;
}
}

View file

@ -0,0 +1,59 @@
//
// CharacterControllerInterface.h
// libraries/physcis/src
//
// Created by Andrew Meadows 2015.10.21
// 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_CharacterControllerInterface_h
#define hifi_CharacterControllerInterface_h
#include <assert.h>
#include <stdint.h>
#include <btBulletDynamicsCommon.h>
#include <BulletDynamics/Character/btCharacterControllerInterface.h>
const uint32_t PENDING_FLAG_ADD_TO_SIMULATION = 1U << 0;
const uint32_t PENDING_FLAG_REMOVE_FROM_SIMULATION = 1U << 1;
const uint32_t PENDING_FLAG_UPDATE_SHAPE = 1U << 2;
const uint32_t PENDING_FLAG_JUMP = 1U << 3;
class btRigidBody;
class btCollisionWorld;
class btDynamicsWorld;
class CharacterController : public btCharacterControllerInterface {
public:
bool needsRemoval() const;
bool needsAddition() const;
void setDynamicsWorld(btDynamicsWorld* world);
btCollisionObject* getCollisionObject() { return _rigidBody; }
virtual void updateShapeIfNecessary() = 0;
virtual void preSimulation() = 0;
virtual void postSimulation() = 0;
virtual void setWalkDirection(const btVector3 &walkDirection) { assert(false); }
/* these from btCharacterControllerInterface remain to be overridden
virtual void setVelocityForTimeInterval(const btVector3 &velocity, btScalar timeInterval) = 0;
virtual void reset() = 0;
virtual void warp(const btVector3 &origin) = 0;
virtual void preStep(btCollisionWorld *collisionWorld) = 0;
virtual void playerStep(btCollisionWorld *collisionWorld, btScalar dt) = 0;
virtual bool canJump() const = 0;
virtual void jump() = 0;
virtual bool onGround() const = 0;
*/
protected:
btDynamicsWorld* _dynamicsWorld { nullptr };
btRigidBody* _rigidBody { nullptr };
uint32_t _pendingFlags { 0 };
};
#endif // hifi_CharacterControllerInterface_h

View file

@ -1,95 +0,0 @@
#ifndef hifi_DynamicCharacterController_h
#define hifi_DynamicCharacterController_h
#include <btBulletDynamicsCommon.h>
#include <BulletDynamics/Character/btCharacterControllerInterface.h>
#include <AvatarData.h>
class btCollisionShape;
class btRigidBody;
class btCollisionWorld;
const int NUM_CHARACTER_CONTROLLER_RAYS = 2;
class DynamicCharacterController : public btCharacterControllerInterface
{
protected:
btScalar _halfHeight;
btScalar _radius;
btCollisionShape* _shape;
btRigidBody* _rigidBody;
btVector3 _currentUp;
btScalar _floorDistance;
btVector3 _walkVelocity;
btScalar _gravity;
glm::vec3 _shapeLocalOffset;
glm::vec3 _boxScale; // used to compute capsule shape
AvatarData* _avatarData = nullptr;
bool _enabled;
bool _isOnGround;
bool _isJumping;
bool _isFalling;
bool _isHovering;
bool _isPushingUp;
quint64 _jumpToHoverStart;
uint32_t _pendingFlags;
btDynamicsWorld* _dynamicsWorld = nullptr;
btScalar _jumpSpeed;
public:
DynamicCharacterController(AvatarData* avatarData);
~DynamicCharacterController ();
virtual void setWalkDirection(const btVector3& walkDirection);
virtual void setVelocityForTimeInterval(const btVector3 &velocity, btScalar timeInterval) { assert(false); }
// TODO: implement these when needed
virtual void reset(btCollisionWorld* collisionWorld) { }
virtual void warp(const btVector3& origin) { }
virtual void debugDraw(btIDebugDraw* debugDrawer) { }
virtual void setUpInterpolate(bool value) { }
btCollisionObject* getCollisionObject() { return _rigidBody; }
///btActionInterface interface
virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTime) {
preStep(collisionWorld);
playerStep(collisionWorld, deltaTime);
}
virtual void preStep(btCollisionWorld* collisionWorld);
virtual void playerStep(btCollisionWorld* collisionWorld, btScalar dt);
virtual bool canJump() const { assert(false); return false; } // never call this
virtual void jump(); // call this every frame the jump button is pressed
virtual bool onGround() const;
bool isHovering() const { return _isHovering; }
void setHovering(bool enabled);
bool needsRemoval() const;
bool needsAddition() const;
void setEnabled(bool enabled);
bool isEnabled() const { return _enabled && _dynamicsWorld; }
void setDynamicsWorld(btDynamicsWorld* world);
void setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale);
bool needsShapeUpdate() const;
void updateShapeIfNecessary();
void preSimulation(btScalar timeStep);
void postSimulation();
protected:
void updateUpAxis(const glm::quat& rotation);
};
#endif // hifi_DynamicCharacterController_h

View file

@ -11,6 +11,7 @@
#include <PhysicsCollisionGroups.h>
#include "CharacterController.h"
#include "ObjectMotionState.h"
#include "PhysicsEngine.h"
#include "PhysicsHelpers.h"
@ -23,7 +24,7 @@ uint32_t PhysicsEngine::getNumSubsteps() {
PhysicsEngine::PhysicsEngine(const glm::vec3& offset) :
_originOffset(offset),
_characterController(nullptr) {
_myAvatarController(nullptr) {
// build table of masks with their group as the key
_collisionMasks.insert(btHashInt((int)COLLISION_GROUP_DEFAULT), COLLISION_MASK_DEFAULT);
_collisionMasks.insert(btHashInt((int)COLLISION_GROUP_STATIC), COLLISION_MASK_STATIC);
@ -38,8 +39,8 @@ PhysicsEngine::PhysicsEngine(const glm::vec3& offset) :
}
PhysicsEngine::~PhysicsEngine() {
if (_characterController) {
_characterController->setDynamicsWorld(nullptr);
if (_myAvatarController) {
_myAvatarController->setDynamicsWorld(nullptr);
}
delete _collisionConfig;
delete _collisionDispatcher;
@ -239,16 +240,23 @@ void PhysicsEngine::stepSimulation() {
_clock.reset();
float timeStep = btMin(dt, MAX_TIMESTEP);
// TODO: move character->preSimulation() into relayIncomingChanges
if (_characterController) {
if (_characterController->needsRemoval()) {
_characterController->setDynamicsWorld(nullptr);
if (_myAvatarController) {
// ADEBUG TODO: move this stuff outside and in front of stepSimulation, because
// the updateShapeIfNecessary() call needs info from MyAvatar and should
// be done on the main thread during the pre-simulation stuff
if (_myAvatarController->needsRemoval()) {
_myAvatarController->setDynamicsWorld(nullptr);
// We must remove any existing contacts for the avatar so that any new contacts will have
// valid data. MyAvatar's RigidBody is the ONLY one in the simulation that does not yet
// have a MotionState so we pass nullptr to removeContacts().
removeContacts(nullptr);
}
_characterController->updateShapeIfNecessary();
if (_characterController->needsAddition()) {
_characterController->setDynamicsWorld(_dynamicsWorld);
_myAvatarController->updateShapeIfNecessary();
if (_myAvatarController->needsAddition()) {
_myAvatarController->setDynamicsWorld(_dynamicsWorld);
}
_characterController->preSimulation(timeStep);
_myAvatarController->preSimulation();
}
auto onSubStep = [this]() {
@ -262,8 +270,8 @@ void PhysicsEngine::stepSimulation() {
_numSubsteps += (uint32_t)numSubsteps;
ObjectMotionState::setWorldSimulationStep(_numSubsteps);
if (_characterController) {
_characterController->postSimulation();
if (_myAvatarController) {
_myAvatarController->postSimulation();
}
}
}
@ -271,7 +279,7 @@ void PhysicsEngine::stepSimulation() {
void PhysicsEngine::doOwnershipInfection(const btCollisionObject* objectA, const btCollisionObject* objectB) {
BT_PROFILE("ownershipInfection");
const btCollisionObject* characterObject = _characterController ? _characterController->getCollisionObject() : nullptr;
const btCollisionObject* characterObject = _myAvatarController ? _myAvatarController->getCollisionObject() : nullptr;
ObjectMotionState* motionStateA = static_cast<ObjectMotionState*>(objectA->getUserPointer());
ObjectMotionState* motionStateB = static_cast<ObjectMotionState*>(objectB->getUserPointer());
@ -434,15 +442,15 @@ void PhysicsEngine::bump(ObjectMotionState* motionState) {
}
}
void PhysicsEngine::setCharacterController(DynamicCharacterController* character) {
if (_characterController != character) {
if (_characterController) {
void PhysicsEngine::setCharacterController(CharacterController* character) {
if (_myAvatarController != character) {
if (_myAvatarController) {
// remove the character from the DynamicsWorld immediately
_characterController->setDynamicsWorld(nullptr);
_characterController = nullptr;
_myAvatarController->setDynamicsWorld(nullptr);
_myAvatarController = nullptr;
}
// the character will be added to the DynamicsWorld later
_characterController = character;
_myAvatarController = character;
}
}

View file

@ -21,13 +21,14 @@
#include "BulletUtil.h"
#include "ContactInfo.h"
#include "DynamicCharacterController.h"
#include "ObjectMotionState.h"
#include "ThreadSafeDynamicsWorld.h"
#include "ObjectAction.h"
const float HALF_SIMULATION_EXTENT = 512.0f; // meters
class CharacterController;
// simple class for keeping track of contacts
class ContactKey {
public:
@ -87,7 +88,7 @@ public:
void removeRigidBody(btRigidBody* body);
void setCharacterController(DynamicCharacterController* character);
void setCharacterController(CharacterController* character);
void dumpNextStats() { _dumpNextStats = true; }
@ -117,7 +118,7 @@ private:
uint32_t _lastNumSubstepsAtUpdateInternal = 0;
/// character collisions
DynamicCharacterController* _characterController = NULL;
CharacterController* _myAvatarController;
bool _dumpNextStats = false;
bool _hasOutgoingChanges = false;

View file

@ -19,8 +19,6 @@
#include <FSTReader.h>
#include <NumericalConstants.h>
#include <gpu/GLBackend.h>
#include "TextureCache.h"
#include "RenderUtilsLogging.h"
@ -573,8 +571,8 @@ void GeometryCache::renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions
if (!_gridBuffers.contains(key)) {
auto verticesBuffer = std::make_shared<gpu::Buffer>();
GLfloat* vertexData = new GLfloat[vertices * 2];
GLfloat* vertex = vertexData;
float* vertexData = new float[vertices * 2];
float* vertex = vertexData;
for (int i = 0; i <= xDivisions; i++) {
float x = (float)i / xDivisions;
@ -595,7 +593,7 @@ void GeometryCache::renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions
*(vertex++) = y;
}
verticesBuffer->append(sizeof(GLfloat) * vertices * 2, (gpu::Byte*) vertexData);
verticesBuffer->append(sizeof(float) * vertices * 2, (gpu::Byte*) vertexData);
delete[] vertexData;
_gridBuffers[key] = verticesBuffer;
@ -674,8 +672,8 @@ void GeometryCache::renderGrid(gpu::Batch& batch, int x, int y, int width, int h
_alternateGridBuffers[key] = verticesBuffer;
}
GLfloat* vertexData = new GLfloat[vertices * 2];
GLfloat* vertex = vertexData;
float* vertexData = new float[vertices * 2];
float* vertex = vertexData;
int dx = width / cols;
int dy = height / rows;
@ -702,7 +700,7 @@ void GeometryCache::renderGrid(gpu::Batch& batch, int x, int y, int width, int h
tx += dx;
}
verticesBuffer->append(sizeof(GLfloat) * vertices * 2, (gpu::Byte*) vertexData);
verticesBuffer->append(sizeof(float) * vertices * 2, (gpu::Byte*) vertexData);
delete[] vertexData;
}
@ -785,8 +783,8 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, con
((int(color.z * 255.0f) & 0xFF) << 16) |
((int(color.w * 255.0f) & 0xFF) << 24);
GLfloat* vertexData = new GLfloat[details.vertices * FLOATS_PER_VERTEX];
GLfloat* vertex = vertexData;
float* vertexData = new float[details.vertices * FLOATS_PER_VERTEX];
float* vertex = vertexData;
int* colorData = new int[details.vertices];
int* colorDataAt = colorData;
@ -798,7 +796,7 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, con
*(colorDataAt++) = compactColor;
}
details.verticesBuffer->append(sizeof(GLfloat) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*) vertexData);
details.verticesBuffer->append(sizeof(float) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*) vertexData);
details.colorBuffer->append(sizeof(int) * details.vertices, (gpu::Byte*) colorData);
delete[] vertexData;
delete[] colorData;
@ -846,8 +844,8 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, con
((int(color.z * 255.0f) & 0xFF) << 16) |
((int(color.w * 255.0f) & 0xFF) << 24);
GLfloat* vertexData = new GLfloat[details.vertices * FLOATS_PER_VERTEX];
GLfloat* vertex = vertexData;
float* vertexData = new float[details.vertices * FLOATS_PER_VERTEX];
float* vertex = vertexData;
int* colorData = new int[details.vertices];
int* colorDataAt = colorData;
@ -860,7 +858,7 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, con
*(colorDataAt++) = compactColor;
}
details.verticesBuffer->append(sizeof(GLfloat) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*) vertexData);
details.verticesBuffer->append(sizeof(float) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*) vertexData);
details.colorBuffer->append(sizeof(int) * details.vertices, (gpu::Byte*) colorData);
delete[] vertexData;
delete[] colorData;
@ -912,8 +910,8 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, con
((int(color.z * 255.0f) & 0xFF) << 16) |
((int(color.w * 255.0f) & 0xFF) << 24);
GLfloat* vertexData = new GLfloat[details.vertices * FLOATS_PER_VERTEX];
GLfloat* vertex = vertexData;
float* vertexData = new float[details.vertices * FLOATS_PER_VERTEX];
float* vertex = vertexData;
int* colorData = new int[details.vertices];
int* colorDataAt = colorData;
@ -930,7 +928,7 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, con
*(colorDataAt++) = compactColor;
}
details.verticesBuffer->append(sizeof(GLfloat) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*) vertexData);
details.verticesBuffer->append(sizeof(float) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*) vertexData);
details.colorBuffer->append(sizeof(int) * details.vertices, (gpu::Byte*) colorData);
delete[] vertexData;
delete[] colorData;
@ -997,7 +995,7 @@ void GeometryCache::renderBevelCornersRect(gpu::Batch& batch, int x, int y, int
details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride);
GLfloat vertexBuffer[NUM_FLOATS]; // only vertices, no normals because we're a 2D quad
float vertexBuffer[NUM_FLOATS]; // only vertices, no normals because we're a 2D quad
int vertexPoint = 0;
// Triangle strip points
@ -1438,8 +1436,8 @@ void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start,
int* colorData = new int[details.vertices];
int* colorDataAt = colorData;
GLfloat* vertexData = new GLfloat[details.vertices * FLOATS_PER_VERTEX];
GLfloat* vertex = vertexData;
float* vertexData = new float[details.vertices * FLOATS_PER_VERTEX];
float* vertex = vertexData;
glm::vec3 point = start;
*(vertex++) = point.x;
@ -1465,7 +1463,7 @@ void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start,
*(vertex++) = end.z;
*(colorDataAt++) = compactColor;
details.verticesBuffer->append(sizeof(GLfloat) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*) vertexData);
details.verticesBuffer->append(sizeof(float) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*) vertexData);
details.colorBuffer->append(sizeof(int) * details.vertices, (gpu::Byte*) colorData);
delete[] vertexData;
delete[] colorData;

File diff suppressed because it is too large Load diff

View file

@ -55,62 +55,62 @@ public:
const QString& fileNameString = QString(""),
AbstractControllerScriptingInterface* controllerScriptingInterface = NULL,
bool wantSignals = true);
~ScriptEngine();
/// run the script in a dedicated thread. This will have the side effect of evalulating
/// the current script contents and calling run(). Callers will likely want to register the script with external
/// services before calling this.
void runInThread();
/// run the script in the callers thread, exit when stop() is called.
void run();
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// NOTE - these are NOT intended to be public interfaces available to scripts, the are only Q_INVOKABLE so we can
// properly ensure they are only called on the correct thread
/// registers a global object by name
Q_INVOKABLE void registerGlobalObject(const QString& name, QObject* object);
/// registers a global getter/setter
Q_INVOKABLE void registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter,
QScriptEngine::FunctionSignature setter, const QString& parent = QString(""));
QScriptEngine::FunctionSignature setter, const QString& parent = QString(""));
/// register a global function
Q_INVOKABLE void registerFunction(const QString& name, QScriptEngine::FunctionSignature fun, int numArguments = -1);
/// register a function as a method on a previously registered global object
Q_INVOKABLE void registerFunction(const QString& parent, const QString& name, QScriptEngine::FunctionSignature fun,
int numArguments = -1);
int numArguments = -1);
/// registers a global object by name
Q_INVOKABLE void registerValue(const QString& valueName, QScriptValue value);
/// evaluate some code in the context of the ScriptEngine and return the result
Q_INVOKABLE QScriptValue evaluate(const QString& program, const QString& fileName, int lineNumber = 1); // this is also used by the script tool widget
/// if the script engine is not already running, this will download the URL and start the process of seting it up
/// to run... NOTE - this is used by Application currently to load the url. We don't really want it to be exposed
/// to run... NOTE - this is used by Application currently to load the url. We don't really want it to be exposed
/// to scripts. we may not need this to be invokable
void loadURL(const QUrl& scriptURL, bool reload);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// NOTE - these are intended to be public interfaces available to scripts
// NOTE - these are intended to be public interfaces available to scripts
Q_INVOKABLE void addEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler);
Q_INVOKABLE void removeEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler);
Q_INVOKABLE void load(const QString& loadfile);
Q_INVOKABLE void include(const QStringList& includeFiles, QScriptValue callback = QScriptValue());
Q_INVOKABLE void include(const QString& includeFile, QScriptValue callback = QScriptValue());
Q_INVOKABLE QObject* setInterval(const QScriptValue& function, int intervalMS);
Q_INVOKABLE QObject* setTimeout(const QScriptValue& function, int timeoutMS);
Q_INVOKABLE void clearInterval(QObject* timer) { stopTimer(reinterpret_cast<QTimer*>(timer)); }
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;
// Entity Script Related methods
Q_INVOKABLE void loadEntityScript(const EntityItemID& entityID, const QString& entityScript, bool forceRedownload = false); // will call the preload method once loaded
Q_INVOKABLE void unloadEntityScript(const EntityItemID& entityID); // will call unload method
@ -118,30 +118,30 @@ public:
Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName);
Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const MouseEvent& event);
Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const EntityItemID& otherID, const Collision& collision);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// NOTE - this is intended to be a public interface for Agent scripts, and local scripts, but not for EntityScripts
Q_INVOKABLE void stop();
bool isFinished() const { return _isFinished; } // used by Application and ScriptWidget
bool isRunning() const { return _isRunning; } // used by ScriptWidget
static void stopAllScripts(QObject* application); // used by Application on shutdown
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// NOTE - These are the callback implementations for ScriptUser the get called by ScriptCache when the contents
// of a script are available.
virtual void scriptContentsAvailable(const QUrl& url, const QString& scriptContents);
virtual void errorInLoadingScript(const QUrl& url);
// These are currently used by Application to track if a script is user loaded or not. Consider finding a solution
// inside of Application so that the ScriptEngine class is not polluted by this notion
void setUserLoaded(bool isUserLoaded) { _isUserLoaded = isUserLoaded; }
bool isUserLoaded() const { return _isUserLoaded; }
// NOTE - this is used by the TypedArray implemetation. we need to review this for thread safety
ArrayBufferClass* getArrayBufferClass() { return _arrayBufferClass; }
signals:
void scriptLoaded(const QString& scriptFilename);
void errorLoadingScript(const QString& scriptFilename);
@ -156,7 +156,7 @@ signals:
void loadScript(const QString& scriptName, bool isUserLoaded);
void reloadScript(const QString& scriptName, bool isUserLoaded);
void doneRunning();
protected:
QString _scriptContents;
QString _parentURL;
@ -176,14 +176,11 @@ private:
void timerFired();
void stopAllTimers();
void refreshFileScript(const EntityItemID& entityID);
void setParentURL(const QString& parentURL) { _parentURL = parentURL; }
QObject* setupTimerWithInterval(const QScriptValue& function, int intervalMS, bool isSingleShot);
void stopTimer(QTimer* timer);
static bool checkSyntax(const QScriptProgram& program);
static bool checkExceptions(QScriptEngine& engine, const QString& fileName);
AbstractControllerScriptingInterface* _controllerScriptingInterface;
QString _fileNameString;
@ -192,18 +189,18 @@ private:
ScriptUUID _uuidLibrary;
bool _isUserLoaded;
bool _isReloading;
ArrayBufferClass* _arrayBufferClass;
QHash<EntityItemID, RegisteredEventHandlers> _registeredHandlers;
void forwardHandlerCall(const EntityItemID& entityID, const QString& eventName, QScriptValueList eventHanderArgs);
Q_INVOKABLE void entityScriptContentAvailable(const EntityItemID& entityID, const QString& scriptOrURL, const QString& contents, bool isURL, bool success);
static QSet<ScriptEngine*> _allKnownScriptEngines;
static QMutex _allScriptsMutex;
static bool _stoppingAllScripts;
static bool _doneRunningThisScript;
};
#endif // hifi_ScriptEngine_h
#endif // hifi_ScriptEngine_h

View file

@ -14,7 +14,7 @@
class ReadWriteLockable {
public:
template <typename F>
bool withWriteLock(F f, bool require = true) {
bool withWriteLock(F f, bool require = true) const {
if (!require) {
bool result = _lock.tryLockForWrite();
if (result) {
@ -22,7 +22,7 @@ public:
_lock.unlock();
}
return result;
}
}
QWriteLocker locker(&_lock);
f();
@ -30,7 +30,7 @@ public:
}
template <typename F>
bool withTryWriteLock(F f) {
bool withTryWriteLock(F f) const {
return withWriteLock(f, false);
}

View file

@ -1,3 +1,3 @@
set(TARGET_NAME ui)
setup_hifi_library(OpenGL Network Qml Quick Script XmlPatterns)
link_hifi_libraries(render-utils shared)
link_hifi_libraries(shared networking gl)

View file

@ -12,7 +12,7 @@
#ifndef hifi_OffscreenUi_h
#define hifi_OffscreenUi_h
#include "OffscreenQmlSurface.h"
#include <gl/OffscreenQmlSurface.h>
#include <QMessageBox>
#include <DependencyManager.h>

View file

@ -3,5 +3,5 @@ AUTOSCRIBE_SHADER_LIB(gpu model render-utils)
# This is not a testcase -- just set it up as a regular hifi project
setup_hifi_project(Quick Gui OpenGL Script Widgets)
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/")
link_hifi_libraries(networking gpu procedural shared fbx model model-networking animation script-engine render-utils )
link_hifi_libraries(networking gl gpu procedural shared fbx model model-networking animation script-engine render-utils )
copy_dlls_beside_windows_executable()

View file

@ -6,8 +6,6 @@ setup_hifi_project(Quick Gui OpenGL)
set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/")
# link in the shared libraries
link_hifi_libraries(render-utils gpu shared)
message(${PROJECT_BINARY_DIR})
link_hifi_libraries(render-utils gl gpu shared)
copy_dlls_beside_windows_executable()

View file

@ -8,8 +8,8 @@ set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/")
#include_oglplus()
# link in the shared libraries
link_hifi_libraries(shared octree environment gpu model render fbx networking entities
script-engine physics
link_hifi_libraries(shared octree environment gl gpu model render fbx networking entities
script-engine physics
render-utils entities-renderer)
include_directories("${PROJECT_BINARY_DIR}/../../libraries/gpu/")
@ -17,6 +17,4 @@ include_directories("${PROJECT_BINARY_DIR}/../../libraries/render-utils/")
include_directories("${PROJECT_BINARY_DIR}/../../libraries/entities-renderer/")
include_directories("${PROJECT_BINARY_DIR}/../../libraries/model/")
message(${PROJECT_BINARY_DIR})
copy_dlls_beside_windows_executable()

View file

@ -20,7 +20,7 @@
#include <QDir>
#include <QGuiApplication>
#include <GLHelpers.h>
#include <gl/GLHelpers.h>
#include "../model/Skybox_vert.h"
#include "../model/Skybox_frag.h"

View file

@ -11,6 +11,6 @@ if (WIN32)
endif()
# link in the shared libraries
link_hifi_libraries(ui render-utils gpu shared)
link_hifi_libraries(shared networking gl gpu ui)
copy_dlls_beside_windows_executable()