mirror of
https://github.com/lubosz/overte.git
synced 2025-08-08 03:08:00 +02:00
Merge pull request #4041 from AndrewMeadows/inertia
Include damping in model of remote extrapolation
This commit is contained in:
commit
21e3687678
10 changed files with 28 additions and 182 deletions
1
BUILD.md
1
BUILD.md
|
@ -6,6 +6,7 @@
|
||||||
* [OpenSSL](https://www.openssl.org/related/binaries.html) ~> 1.0.1g
|
* [OpenSSL](https://www.openssl.org/related/binaries.html) ~> 1.0.1g
|
||||||
* IMPORTANT: OpenSSL 1.0.1g is critical to avoid a security vulnerability.
|
* IMPORTANT: OpenSSL 1.0.1g is critical to avoid a security vulnerability.
|
||||||
* [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/) ~> 4.3
|
* [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/) ~> 4.3
|
||||||
|
* [Bullet Physics Engine](http://bulletphysics.org) ~> 2.82
|
||||||
|
|
||||||
### OS Specific Build Guides
|
### OS Specific Build Guides
|
||||||
* [BUILD_OSX.md](BUILD_OSX.md) - additional instructions for OS X.
|
* [BUILD_OSX.md](BUILD_OSX.md) - additional instructions for OS X.
|
||||||
|
|
|
@ -29,7 +29,7 @@ var RIGHT_BUTTON_FWD = 11;
|
||||||
var RIGHT_BUTTON_3 = 9;
|
var RIGHT_BUTTON_3 = 9;
|
||||||
|
|
||||||
var BALL_RADIUS = 0.08;
|
var BALL_RADIUS = 0.08;
|
||||||
var GRAVITY_STRENGTH = 0.5;
|
var GRAVITY_STRENGTH = 1.0;
|
||||||
|
|
||||||
var HELD_COLOR = { red: 240, green: 0, blue: 0 };
|
var HELD_COLOR = { red: 240, green: 0, blue: 0 };
|
||||||
var THROWN_COLOR = { red: 128, green: 0, blue: 0 };
|
var THROWN_COLOR = { red: 128, green: 0, blue: 0 };
|
||||||
|
@ -136,7 +136,7 @@ function checkControllerSide(whichSide) {
|
||||||
velocity: { x: 0, y: 0, z: 0},
|
velocity: { x: 0, y: 0, z: 0},
|
||||||
gravity: { x: 0, y: 0, z: 0},
|
gravity: { x: 0, y: 0, z: 0},
|
||||||
inHand: true,
|
inHand: true,
|
||||||
radius: { x: BALL_RADIUS * 2, y: BALL_RADIUS * 2, z: BALL_RADIUS * 2 },
|
dimensions: { x: BALL_RADIUS * 2, y: BALL_RADIUS * 2, z: BALL_RADIUS * 2 },
|
||||||
damping: 0.00001,
|
damping: 0.00001,
|
||||||
color: HELD_COLOR,
|
color: HELD_COLOR,
|
||||||
|
|
||||||
|
@ -185,6 +185,7 @@ function checkControllerSide(whichSide) {
|
||||||
velocity: { x: tipVelocity.x * THROWN_VELOCITY_SCALING,
|
velocity: { x: tipVelocity.x * THROWN_VELOCITY_SCALING,
|
||||||
y: tipVelocity.y * THROWN_VELOCITY_SCALING,
|
y: tipVelocity.y * THROWN_VELOCITY_SCALING,
|
||||||
z: tipVelocity.z * THROWN_VELOCITY_SCALING } ,
|
z: tipVelocity.z * THROWN_VELOCITY_SCALING } ,
|
||||||
|
collisionsWillMove: true,
|
||||||
inHand: false,
|
inHand: false,
|
||||||
color: THROWN_COLOR,
|
color: THROWN_COLOR,
|
||||||
lifetime: 10,
|
lifetime: 10,
|
||||||
|
|
|
@ -4,21 +4,21 @@
|
||||||
// Creates a red 0.2 meter diameter ball right in front of your avatar that lives for 60 seconds
|
// Creates a red 0.2 meter diameter ball right in front of your avatar that lives for 60 seconds
|
||||||
//
|
//
|
||||||
|
|
||||||
var radius = 0.1;
|
var diameter = 0.2;
|
||||||
var position = Vec3.sum(MyAvatar.position, Quat.getFront(MyAvatar.orientation));
|
var position = Vec3.sum(MyAvatar.position, Quat.getFront(MyAvatar.orientation));
|
||||||
var properties = {
|
var properties = {
|
||||||
type: "Sphere",
|
type: "Sphere",
|
||||||
position: position,
|
position: position,
|
||||||
velocity: { x: 0, y: 0, z: 0},
|
velocity: { x: 0, y: 0, z: 0},
|
||||||
gravity: { x: 0, y: -0.05, z: 0},
|
gravity: { x: 0, y: -0.05, z: 0},
|
||||||
radius: radius,
|
dimensions: { x: diameter, y: diameter, z: diameter };
|
||||||
damping: 0.00001,
|
damping: 0.00001,
|
||||||
color: { red: 200, green: 0, blue: 0 },
|
color: { red: 200, green: 0, blue: 0 },
|
||||||
lifetime: 60
|
lifetime: 60
|
||||||
};
|
};
|
||||||
|
|
||||||
var newEntity = Entities.addEntity(properties);
|
var newEntity = Entities.addEntity(properties);
|
||||||
position.x -= radius * 1.0;
|
position.x -= 0.5 * diameter;
|
||||||
properties.position = position;
|
properties.position = position;
|
||||||
var newEntityTwo = Entities.addEntity(properties);
|
var newEntityTwo = Entities.addEntity(properties);
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ const float MAX_VOLUME = 1000000.0f;
|
||||||
const float DEFAULT_FRICTION = 0.5f;
|
const float DEFAULT_FRICTION = 0.5f;
|
||||||
const float MAX_FRICTION = 10.0f;
|
const float MAX_FRICTION = 10.0f;
|
||||||
|
|
||||||
const float DEFAULT_RESTITUTION = 0.0f;
|
const float DEFAULT_RESTITUTION = 0.5f;
|
||||||
|
|
||||||
// origin of physics simulation in world frame
|
// origin of physics simulation in world frame
|
||||||
glm::vec3 _worldOffset(0.0f);
|
glm::vec3 _worldOffset(0.0f);
|
||||||
|
@ -123,9 +123,10 @@ bool ObjectMotionState::doesNotNeedToSendUpdate() const {
|
||||||
|
|
||||||
const float FIXED_SUBSTEP = 1.0f / 60.0f;
|
const float FIXED_SUBSTEP = 1.0f / 60.0f;
|
||||||
|
|
||||||
bool ObjectMotionState::shouldSendUpdate(uint32_t simulationFrame, float subStepRemainder) const {
|
bool ObjectMotionState::shouldSendUpdate(uint32_t simulationFrame, float subStepRemainder) {
|
||||||
assert(_body);
|
assert(_body);
|
||||||
float dt = (float)(simulationFrame - _sentFrame) * FIXED_SUBSTEP + subStepRemainder;
|
float dt = (float)(simulationFrame - _sentFrame) * FIXED_SUBSTEP + subStepRemainder;
|
||||||
|
_sentFrame = simulationFrame;
|
||||||
bool isActive = _body->isActive();
|
bool isActive = _body->isActive();
|
||||||
|
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
|
@ -156,28 +157,35 @@ bool ObjectMotionState::shouldSendUpdate(uint32_t simulationFrame, float subStep
|
||||||
// TODO: Andrew to reconcile Bullet and legacy damping coefficients.
|
// TODO: Andrew to reconcile Bullet and legacy damping coefficients.
|
||||||
|
|
||||||
// compute position error
|
// compute position error
|
||||||
glm::vec3 extrapolatedPosition = _sentPosition + dt * (_sentVelocity + (0.5f * dt) * _sentAcceleration);
|
if (glm::length2(_sentVelocity) > 0.0f) {
|
||||||
|
_sentVelocity += _sentAcceleration * dt;
|
||||||
|
_sentVelocity *= powf(1.0f - _linearDamping, dt);
|
||||||
|
_sentPosition += dt * _sentVelocity;
|
||||||
|
}
|
||||||
|
|
||||||
btTransform worldTrans = _body->getWorldTransform();
|
btTransform worldTrans = _body->getWorldTransform();
|
||||||
glm::vec3 position = bulletToGLM(worldTrans.getOrigin());
|
glm::vec3 position = bulletToGLM(worldTrans.getOrigin());
|
||||||
|
|
||||||
float dx2 = glm::distance2(position, extrapolatedPosition);
|
float dx2 = glm::distance2(position, _sentPosition);
|
||||||
const float MAX_POSITION_ERROR_SQUARED = 0.001f; // 0.001 m^2 ~~> 0.03 m
|
const float MAX_POSITION_ERROR_SQUARED = 0.001f; // 0.001 m^2 ~~> 0.03 m
|
||||||
if (dx2 > MAX_POSITION_ERROR_SQUARED) {
|
if (dx2 > MAX_POSITION_ERROR_SQUARED) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute rotation error
|
if (glm::length2(_sentAngularVelocity) > 0.0f) {
|
||||||
float spin = glm::length(_sentAngularVelocity);
|
// compute rotation error
|
||||||
glm::quat extrapolatedRotation = _sentRotation;
|
_sentAngularVelocity *= powf(1.0f - _angularDamping, dt);
|
||||||
const float MIN_SPIN = 1.0e-4f;
|
|
||||||
if (spin > MIN_SPIN) {
|
float spin = glm::length(_sentAngularVelocity);
|
||||||
glm::vec3 axis = _sentAngularVelocity / spin;
|
const float MIN_SPIN = 1.0e-4f;
|
||||||
extrapolatedRotation = glm::angleAxis(dt * spin, axis) * _sentRotation;
|
if (spin > MIN_SPIN) {
|
||||||
|
glm::vec3 axis = _sentAngularVelocity / spin;
|
||||||
|
_sentRotation = glm::normalize(glm::angleAxis(dt * spin, axis) * _sentRotation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const float MIN_ROTATION_DOT = 0.98f;
|
const float MIN_ROTATION_DOT = 0.98f;
|
||||||
glm::quat actualRotation = bulletToGLM(worldTrans.getRotation());
|
glm::quat actualRotation = bulletToGLM(worldTrans.getRotation());
|
||||||
return (glm::dot(actualRotation, extrapolatedRotation) < MIN_ROTATION_DOT);
|
return (glm::dot(actualRotation, _sentRotation) < MIN_ROTATION_DOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // USE_BULLET_PHYSICS
|
#endif // USE_BULLET_PHYSICS
|
||||||
|
|
|
@ -84,7 +84,7 @@ public:
|
||||||
void clearOutgoingPacketFlags(uint32_t flags) { _outgoingPacketFlags &= ~flags; }
|
void clearOutgoingPacketFlags(uint32_t flags) { _outgoingPacketFlags &= ~flags; }
|
||||||
|
|
||||||
bool doesNotNeedToSendUpdate() const;
|
bool doesNotNeedToSendUpdate() const;
|
||||||
virtual bool shouldSendUpdate(uint32_t simulationFrame, float subStepRemainder) const;
|
virtual bool shouldSendUpdate(uint32_t simulationFrame, float subStepRemainder);
|
||||||
virtual void sendUpdate(OctreeEditPacketSender* packetSender, uint32_t frame) = 0;
|
virtual void sendUpdate(OctreeEditPacketSender* packetSender, uint32_t frame) = 0;
|
||||||
|
|
||||||
virtual MotionType computeMotionType() const = 0;
|
virtual MotionType computeMotionType() const = 0;
|
||||||
|
|
|
@ -24,7 +24,6 @@ PhysicsEngine::PhysicsEngine(const glm::vec3& offset)
|
||||||
_constraintSolver(NULL),
|
_constraintSolver(NULL),
|
||||||
_dynamicsWorld(NULL),
|
_dynamicsWorld(NULL),
|
||||||
_originOffset(offset),
|
_originOffset(offset),
|
||||||
_voxels(),
|
|
||||||
_entityPacketSender(NULL),
|
_entityPacketSender(NULL),
|
||||||
_frameCount(0) {
|
_frameCount(0) {
|
||||||
}
|
}
|
||||||
|
@ -221,62 +220,6 @@ void PhysicsEngine::stepSimulation() {
|
||||||
_frameCount += (uint32_t)numSubSteps;
|
_frameCount += (uint32_t)numSubSteps;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhysicsEngine::addVoxel(const glm::vec3& position, float scale) {
|
|
||||||
glm::vec3 halfExtents = glm::vec3(0.5f * scale);
|
|
||||||
glm::vec3 trueCenter = position + halfExtents;
|
|
||||||
PositionHashKey key(trueCenter);
|
|
||||||
VoxelObject* proxy = _voxels.find(key);
|
|
||||||
if (!proxy) {
|
|
||||||
// create a shape
|
|
||||||
ShapeInfo info;
|
|
||||||
info.setBox(halfExtents);
|
|
||||||
btCollisionShape* shape = _shapeManager.getShape(info);
|
|
||||||
|
|
||||||
// NOTE: the shape creation will fail when the size of the voxel is out of range
|
|
||||||
if (shape) {
|
|
||||||
// create a collisionObject
|
|
||||||
btCollisionObject* object = new btCollisionObject();
|
|
||||||
object->setCollisionShape(shape);
|
|
||||||
btTransform transform;
|
|
||||||
transform.setIdentity();
|
|
||||||
// we shift the center into the simulation's frame
|
|
||||||
glm::vec3 shiftedCenter = (position - _originOffset) + halfExtents;
|
|
||||||
transform.setOrigin(btVector3(shiftedCenter.x, shiftedCenter.y, shiftedCenter.z));
|
|
||||||
object->setWorldTransform(transform);
|
|
||||||
|
|
||||||
// add to map and world
|
|
||||||
_voxels.insert(key, VoxelObject(trueCenter, object));
|
|
||||||
_dynamicsWorld->addCollisionObject(object);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PhysicsEngine::removeVoxel(const glm::vec3& position, float scale) {
|
|
||||||
glm::vec3 halfExtents = glm::vec3(0.5f * scale);
|
|
||||||
glm::vec3 trueCenter = position + halfExtents;
|
|
||||||
PositionHashKey key(trueCenter);
|
|
||||||
VoxelObject* proxy = _voxels.find(key);
|
|
||||||
if (proxy) {
|
|
||||||
// remove from world
|
|
||||||
assert(proxy->_object);
|
|
||||||
_dynamicsWorld->removeCollisionObject(proxy->_object);
|
|
||||||
|
|
||||||
// release shape
|
|
||||||
ShapeInfo info;
|
|
||||||
info.setBox(halfExtents);
|
|
||||||
bool released = _shapeManager.releaseShape(info);
|
|
||||||
assert(released);
|
|
||||||
|
|
||||||
// delete object and remove from voxel map
|
|
||||||
delete proxy->_object;
|
|
||||||
_voxels.remove(key);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bullet collision flags are as follows:
|
// Bullet collision flags are as follows:
|
||||||
// CF_STATIC_OBJECT= 1,
|
// CF_STATIC_OBJECT= 1,
|
||||||
// CF_KINEMATIC_OBJECT= 2,
|
// CF_KINEMATIC_OBJECT= 2,
|
||||||
|
|
|
@ -24,10 +24,8 @@ typedef unsigned int uint32_t;
|
||||||
|
|
||||||
#include "BulletUtil.h"
|
#include "BulletUtil.h"
|
||||||
#include "EntityMotionState.h"
|
#include "EntityMotionState.h"
|
||||||
#include "PositionHashKey.h"
|
|
||||||
#include "ShapeManager.h"
|
#include "ShapeManager.h"
|
||||||
#include "ThreadSafeDynamicsWorld.h"
|
#include "ThreadSafeDynamicsWorld.h"
|
||||||
#include "VoxelObject.h"
|
|
||||||
|
|
||||||
const float HALF_SIMULATION_EXTENT = 512.0f; // meters
|
const float HALF_SIMULATION_EXTENT = 512.0f; // meters
|
||||||
|
|
||||||
|
@ -56,16 +54,6 @@ public:
|
||||||
/// \return position of simulation origin in domain-frame
|
/// \return position of simulation origin in domain-frame
|
||||||
const glm::vec3& getOriginOffset() const { return _originOffset; }
|
const glm::vec3& getOriginOffset() const { return _originOffset; }
|
||||||
|
|
||||||
/// \param position the minimum corner of the voxel
|
|
||||||
/// \param scale the length of the voxel side
|
|
||||||
/// \return true if Voxel added
|
|
||||||
bool addVoxel(const glm::vec3& position, float scale);
|
|
||||||
|
|
||||||
/// \param position the minimum corner of the voxel
|
|
||||||
/// \param scale the length of the voxel side
|
|
||||||
/// \return true if Voxel removed
|
|
||||||
bool removeVoxel(const glm::vec3& position, float scale);
|
|
||||||
|
|
||||||
/// \param motionState pointer to Object's MotionState
|
/// \param motionState pointer to Object's MotionState
|
||||||
/// \return true if Object added
|
/// \return true if Object added
|
||||||
bool addObject(ObjectMotionState* motionState);
|
bool addObject(ObjectMotionState* motionState);
|
||||||
|
@ -103,7 +91,6 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
glm::vec3 _originOffset;
|
glm::vec3 _originOffset;
|
||||||
btHashMap<PositionHashKey, VoxelObject> _voxels;
|
|
||||||
|
|
||||||
// EntitySimulation stuff
|
// EntitySimulation stuff
|
||||||
QSet<EntityMotionState*> _entityMotionStates; // all entities that we track
|
QSet<EntityMotionState*> _entityMotionStates; // all entities that we track
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
//
|
|
||||||
// PositionHashKey.cpp
|
|
||||||
// libraries/physcis/src
|
|
||||||
//
|
|
||||||
// Created by Andrew Meadows 2014.11.05
|
|
||||||
// Copyright 2014 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 <math.h>
|
|
||||||
|
|
||||||
#include "PositionHashKey.h"
|
|
||||||
|
|
||||||
// static
|
|
||||||
int computeHash(const glm::vec3& center) {
|
|
||||||
// NOTE: 0.49f is used to bump the float up almost half a millimeter
|
|
||||||
// so the cast to int produces a round() effect rather than a floor()
|
|
||||||
int hash = DoubleHashKey::hashFunction((int)(center.x * MILLIMETERS_PER_METER + copysignf(1.0f, center.x) * 0.49f), 0);
|
|
||||||
hash ^= DoubleHashKey::hashFunction((int)(center.y * MILLIMETERS_PER_METER + copysignf(1.0f, center.y) * 0.49f), 1);
|
|
||||||
return hash ^ DoubleHashKey::hashFunction((int)(center.z * MILLIMETERS_PER_METER + copysignf(1.0f, center.z) * 0.49f), 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
int computeHash2(const glm::vec3& center) {
|
|
||||||
// NOTE: 0.49f is used to bump the float up almost half a millimeter
|
|
||||||
// so the cast to int produces a round() effect rather than a floor()
|
|
||||||
int hash = DoubleHashKey::hashFunction2((int)(center.x * MILLIMETERS_PER_METER + copysignf(1.0f, center.x) * 0.49f));
|
|
||||||
hash ^= DoubleHashKey::hashFunction2((int)(center.y * MILLIMETERS_PER_METER + copysignf(1.0f, center.y) * 0.49f));
|
|
||||||
return hash ^ DoubleHashKey::hashFunction2((int)(center.z * MILLIMETERS_PER_METER + copysignf(1.0f, center.z) * 0.49f));
|
|
||||||
}
|
|
||||||
|
|
||||||
PositionHashKey::PositionHashKey(glm::vec3 center) : DoubleHashKey() {
|
|
||||||
_hash = computeHash(center);
|
|
||||||
_hash2 = computeHash2(center);
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
//
|
|
||||||
// PositionHashKey.h
|
|
||||||
// libraries/physcis/src
|
|
||||||
//
|
|
||||||
// Created by Andrew Meadows 2014.11.05
|
|
||||||
// Copyright 2014 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_PositionHashKey_h
|
|
||||||
#define hifi_PositionHashKey_h
|
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
|
|
||||||
#include <SharedUtil.h>
|
|
||||||
|
|
||||||
#include "DoubleHashKey.h"
|
|
||||||
|
|
||||||
class PositionHashKey : public DoubleHashKey {
|
|
||||||
public:
|
|
||||||
PositionHashKey(glm::vec3 center);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // hifi_PositionHashKey_h
|
|
|
@ -1,31 +0,0 @@
|
||||||
//
|
|
||||||
// VoxelObject.h
|
|
||||||
// libraries/physcis/src
|
|
||||||
//
|
|
||||||
// Created by Andrew Meadows 2014.11.05
|
|
||||||
// Copyright 2014 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_VoxelObject_h
|
|
||||||
#define hifi_VoxelObject_h
|
|
||||||
|
|
||||||
#ifdef USE_BULLET_PHYSICS
|
|
||||||
|
|
||||||
#include <btBulletDynamicsCommon.h>
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
|
|
||||||
// VoxelObject is a simple wrapper for tracking a Voxel in a PhysicsEngine
|
|
||||||
class VoxelObject {
|
|
||||||
public:
|
|
||||||
VoxelObject(const glm::vec3& center, btCollisionObject* object) : _object(object), _center(center) {
|
|
||||||
assert(object != NULL);
|
|
||||||
}
|
|
||||||
btCollisionObject* _object;
|
|
||||||
glm::vec3 _center;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // USE_BULLET_PHYSICS
|
|
||||||
#endif // hifi_VoxelObject_h
|
|
Loading…
Reference in a new issue