Merge pull request #5660 from sethalves/polyvox

Polyvox improvements
This commit is contained in:
Andrew Meadows 2015-08-31 13:14:01 -07:00
commit de6afb4d74
20 changed files with 977 additions and 596 deletions

View file

@ -448,12 +448,31 @@ var toolBar = (function () {
}
if (newPolyVoxButton === toolBar.clicked(clickedOverlay)) {
createNewEntity({
var polyVoxId = createNewEntity({
type: "PolyVox",
dimensions: { x: 10, y: 10, z: 10 },
voxelVolumeSize: {x:16, y:16, z:16},
voxelSurfaceStyle: 1
voxelSurfaceStyle: 2
});
for (var x = 1; x <= 14; x++) {
Entities.setVoxel(polyVoxId, {x: x, y: 1, z: 1}, 255);
Entities.setVoxel(polyVoxId, {x: x, y: 14, z: 1}, 255);
Entities.setVoxel(polyVoxId, {x: x, y: 1, z: 14}, 255);
Entities.setVoxel(polyVoxId, {x: x, y: 14, z: 14}, 255);
}
for (var y = 2; y <= 13; y++) {
Entities.setVoxel(polyVoxId, {x: 1, y: y, z: 1}, 255);
Entities.setVoxel(polyVoxId, {x: 14, y: y, z: 1}, 255);
Entities.setVoxel(polyVoxId, {x: 1, y: y, z: 14}, 255);
Entities.setVoxel(polyVoxId, {x: 14, y: y, z: 14}, 255);
}
for (var z = 2; z <= 13; z++) {
Entities.setVoxel(polyVoxId, {x: 1, y: 1, z: z}, 255);
Entities.setVoxel(polyVoxId, {x: 14, y: 1, z: z}, 255);
Entities.setVoxel(polyVoxId, {x: 1, y: 14, z: z}, 255);
Entities.setVoxel(polyVoxId, {x: 14, y: 14, z: z}, 255);
}
return true;
}

View file

@ -10,7 +10,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
Overlay2D = function(properties, overlay) { // overlay is an optionnal variable
Overlay2D = function(properties, overlay) { // overlay is an optional variable
if (!(typeof(properties) === 'undefined')) {
if(typeof(overlay) === 'undefined') {
overlay = Overlays.addOverlay("image", properties);

View file

@ -1,10 +1,206 @@
var controlHeld = false;
var shiftHeld = false;
Script.include([
"libraries/toolBars.js",
]);
var isActive = false;
var toolIconUrl = "http://headache.hungry.com/~seth/hifi/";
var toolHeight = 50;
var toolWidth = 50;
var addingVoxels = false;
var deletingVoxels = false;
offAlpha = 0.5;
onAlpha = 0.9;
function floorVector(v) {
return {x: Math.floor(v.x), y: Math.floor(v.y), z: Math.floor(v.z)};
}
function vectorToString(v){
return "{" + v.x + ", " + v.x + ", " + v.x + "}";
}
var toolBar = (function () {
var that = {},
toolBar,
activeButton,
addVoxelButton,
deleteVoxelButton,
addTerrainButton;
function initialize() {
toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.voxel.toolbar", function (windowDimensions, toolbar) {
return {
x: windowDimensions.x - 8*2 - toolbar.width * 2,
y: (windowDimensions.y - toolbar.height) / 2
};
});
activeButton = toolBar.addTool({
imageURL: "http://s3.amazonaws.com/hifi-public/images/tools/polyvox.svg",
width: toolWidth,
height: toolHeight,
alpha: onAlpha,
visible: true,
});
addVoxelButton = toolBar.addTool({
imageURL: toolIconUrl + "voxel-add.svg",
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
width: toolWidth,
height: toolHeight,
alpha: offAlpha,
visible: false
});
deleteVoxelButton = toolBar.addTool({
imageURL: toolIconUrl + "voxel-delete.svg",
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
width: toolWidth,
height: toolHeight,
alpha: offAlpha,
visible: false
});
addTerrainButton = toolBar.addTool({
imageURL: toolIconUrl + "voxel-terrain.svg",
subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT },
width: toolWidth,
height: toolHeight,
alpha: onAlpha,
visible: false
});
that.setActive(false);
}
that.setActive = function(active) {
if (active != isActive) {
isActive = active;
that.showTools(isActive);
}
toolBar.selectTool(activeButton, isActive);
};
// Sets visibility of tool buttons, excluding the power button
that.showTools = function(doShow) {
toolBar.showTool(addVoxelButton, doShow);
toolBar.showTool(deleteVoxelButton, doShow);
toolBar.showTool(addTerrainButton, doShow);
};
that.mousePressEvent = function (event) {
var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
if (activeButton === toolBar.clicked(clickedOverlay)) {
that.setActive(!isActive);
return true;
}
if (addVoxelButton === toolBar.clicked(clickedOverlay)) {
if (addingVoxels) {
addingVoxels = false;
deletingVoxels = false;
toolBar.setAlpha(offAlpha, addVoxelButton);
toolBar.setAlpha(offAlpha, deleteVoxelButton);
toolBar.selectTool(addVoxelButton, false);
toolBar.selectTool(deleteVoxelButton, false);
} else {
addingVoxels = true;
deletingVoxels = false;
toolBar.setAlpha(onAlpha, addVoxelButton);
toolBar.setAlpha(offAlpha, deleteVoxelButton);
}
return true;
}
if (deleteVoxelButton === toolBar.clicked(clickedOverlay)) {
if (deletingVoxels) {
deletingVoxels = false;
addingVoxels = false;
toolBar.setAlpha(offAlpha, addVoxelButton);
toolBar.setAlpha(offAlpha, deleteVoxelButton);
} else {
deletingVoxels = true;
addingVoxels = false;
toolBar.setAlpha(offAlpha, addVoxelButton);
toolBar.setAlpha(onAlpha, deleteVoxelButton);
}
return true;
}
if (addTerrainButton === toolBar.clicked(clickedOverlay)) {
addTerrainBlock();
return true;
}
}
Window.domainChanged.connect(function() {
that.setActive(false);
});
that.cleanup = function () {
toolBar.cleanup();
// Overlays.deleteOverlay(activeButton);
};
initialize();
return that;
}());
function addTerrainBlock() {
var myPosDiv16 = Vec3.multiply(Vec3.sum(MyAvatar.position, {x:8, x:8, z:8}), 1.0 / 16.0);
var myPosDiv16Floored = floorVector(myPosDiv16);
var baseLocation = Vec3.multiply(myPosDiv16Floored, 16.0);
if (baseLocation.y + 8 > MyAvatar.position.y) {
baseLocation.y -= 16;
}
print("myPosDiv16 is " + vectorToString(myPosDiv16));
print("MyPosDiv16Floored is " + vectorToString(myPosDiv16Floored));
print("baseLocation is " + vectorToString(baseLocation));
alreadyThere = Entities.findEntities(baseLocation, 1.0);
for (var i = 0; i < alreadyThere.length; i++) {
var id = alreadyThere[i];
var properties = Entities.getEntityProperties(id);
if (properties.name == "terrain") {
print("already terrain there");
return;
}
}
var polyVoxId = Entities.addEntity({
type: "PolyVox",
name: "terrain",
position: baseLocation,
dimensions: { x: 16, y: 16, z: 16 },
voxelVolumeSize: {x:16, y:16, z:16},
voxelSurfaceStyle: 2
});
Entities.setAllVoxels(polyVoxId, 255);
for (var y = 8; y < 16; y++) {
for (var x = 0; x < 16; x++) {
for (var z = 0; z < 16; z++) {
Entities.setVoxel(polyVoxId, {x: x, y: y, z: z}, 0);
}
}
}
return true;
}
function attemptVoxelChange(pickRayDir, intersection) {
var properties = Entities.getEntityProperties(intersection.entityID);
@ -12,25 +208,30 @@ function attemptVoxelChange(pickRayDir, intersection) {
return false;
}
if (addingVoxels == false && deletingVoxels == false) {
return false;
}
var voxelPosition = Entities.worldCoordsToVoxelCoords(intersection.entityID, intersection.intersection);
voxelPosition = Vec3.subtract(voxelPosition, {x: 0.5, y: 0.5, z: 0.5});
var pickRayDirInVoxelSpace = Entities.localCoordsToVoxelCoords(intersection.entityID, pickRayDir);
pickRayDirInVoxelSpace = Vec3.normalize(pickRayDirInVoxelSpace);
var doAdd = addingVoxels;
var doDelete = deletingVoxels;
if (controlHeld) {
// hold control to erase a voxel
doAdd = deletingVoxels;
doDelete = addingVoxels;
}
if (doDelete) {
var toErasePosition = Vec3.sum(voxelPosition, Vec3.multiply(pickRayDirInVoxelSpace, 0.1));
return Entities.setVoxel(intersection.entityID, floorVector(toErasePosition), 0);
} else if (shiftHeld) {
// hold shift to set all voxels to 255
return Entities.setAllVoxels(intersection.entityID, 255);
} else {
// no modifier key to add a voxel
}
if (doAdd) {
var toDrawPosition = Vec3.subtract(voxelPosition, Vec3.multiply(pickRayDirInVoxelSpace, 0.1));
return Entities.setVoxel(intersection.entityID, floorVector(toDrawPosition), 255);
}
// Entities.setVoxelSphere(id, intersection.intersection, radius, 0)
}
function mousePressEvent(event) {
@ -38,6 +239,10 @@ function mousePressEvent(event) {
return;
}
if (toolBar.mousePressEvent(event)) {
return;
}
var pickRay = Camera.computePickRay(event.x, event.y);
var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking
@ -76,6 +281,15 @@ function keyReleaseEvent(event) {
}
function cleanup() {
for (var i = 0; i < overlays.length; i++) {
Overlays.deleteOverlay(overlays[i]);
}
toolBar.cleanup();
}
Controller.mousePressEvent.connect(mousePressEvent);
Controller.keyPressEvent.connect(keyPressEvent);
Controller.keyReleaseEvent.connect(keyReleaseEvent);
Script.scriptEnding.connect(cleanup);

View file

@ -2804,7 +2804,8 @@ void Application::update(float deltaTime) {
_entities.getTree()->lockForWrite();
_entitySimulation.lock();
_physicsEngine.changeObjects(_entitySimulation.getObjectsToChange());
VectorOfMotionStates stillNeedChange = _physicsEngine.changeObjects(_entitySimulation.getObjectsToChange());
_entitySimulation.setObjectsToChange(stillNeedChange);
_entitySimulation.unlock();
_entities.getTree()->unlock();

View file

@ -28,15 +28,20 @@ AvatarMotionState::~AvatarMotionState() {
}
// virtual
uint32_t AvatarMotionState::getAndClearIncomingDirtyFlags() {
uint32_t AvatarMotionState::getIncomingDirtyFlags() {
uint32_t dirtyFlags = 0;
if (_body && _avatar) {
dirtyFlags = _dirtyFlags;
_dirtyFlags = 0;
}
return dirtyFlags;
}
void AvatarMotionState::clearIncomingDirtyFlags() {
if (_body && _avatar) {
_dirtyFlags = 0;
}
}
MotionType AvatarMotionState::computeObjectMotionType() const {
// TODO?: support non-DYNAMIC motion for avatars? (e.g. when sitting)
return MOTION_TYPE_DYNAMIC;

View file

@ -25,7 +25,8 @@ public:
virtual MotionType getMotionType() const { return _motionType; }
virtual uint32_t getAndClearIncomingDirtyFlags();
virtual uint32_t getIncomingDirtyFlags();
virtual void clearIncomingDirtyFlags();
virtual MotionType computeObjectMotionType() const;
@ -65,6 +66,7 @@ public:
friend class AvatarManager;
protected:
virtual bool isReadyToComputeShape() { return true; }
virtual btCollisionShape* computeNewShape();
virtual void clearObjectBackPointer();
Avatar* _avatar;

File diff suppressed because it is too large Load diff

View file

@ -12,13 +12,18 @@
#ifndef hifi_RenderablePolyVoxEntityItem_h
#define hifi_RenderablePolyVoxEntityItem_h
#include <QSemaphore>
#include <atomic>
#include <PolyVoxCore/SimpleVolume.h>
#include <PolyVoxCore/Raycast.h>
#include <TextureCache.h>
#include "PolyVoxEntityItem.h"
#include "RenderableDebugableEntityItem.h"
#include "RenderableEntityItem.h"
#include "gpu/Context.h"
class PolyVoxPayload {
public:
@ -56,19 +61,16 @@ public:
virtual uint8_t getVoxel(int x, int y, int z);
virtual bool setVoxel(int x, int y, int z, uint8_t toValue);
bool updateOnCount(int x, int y, int z, uint8_t new_value);
void render(RenderArgs* args);
virtual bool supportsDetailedRayIntersection() const { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const;
void getModel();
virtual void setVoxelData(QByteArray voxelData);
virtual void setVoxelVolumeSize(glm::vec3 voxelVolumeSize);
virtual void setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle);
glm::vec3 getSurfacePositionAdjustment() const;
glm::mat4 voxelToWorldMatrix() const;
glm::mat4 worldToVoxelMatrix() const;
@ -103,33 +105,48 @@ public:
std::shared_ptr<render::Scene> scene,
render::PendingChanges& pendingChanges);
protected:
virtual void updateVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle);
private:
// The PolyVoxEntityItem class has _voxelData which contains dimensions and compressed voxel data. The dimensions
// may not match _voxelVolumeSize.
bool setVoxelInternal(int x, int y, int z, uint8_t toValue);
void compressVolumeData();
void decompressVolumeData();
void clearEdges();
PolyVox::SimpleVolume<uint8_t>* _volData = nullptr;
model::Geometry _modelGeometry;
bool _needsModelReload = true;
QVector<QVector<glm::vec3>> _points; // XXX
model::MeshPointer _mesh;
bool _meshDirty; // does collision-shape need to be recomputed?
mutable QReadWriteLock _meshLock{QReadWriteLock::Recursive};
NetworkTexturePointer _xTexture;
NetworkTexturePointer _yTexture;
NetworkTexturePointer _zTexture;
int _onCount = 0; // how many non-zero voxels are in _volData
const int MATERIAL_GPU_SLOT = 3;
render::ItemID _myItem;
static gpu::PipelinePointer _pipeline;
ShapeInfo _shapeInfo;
mutable QReadWriteLock _shapeInfoLock;
PolyVox::SimpleVolume<uint8_t>* _volData = nullptr;
mutable QReadWriteLock _volDataLock{QReadWriteLock::Recursive}; // lock for _volData
bool _volDataDirty = false; // does getMesh need to be called?
int _onCount; // how many non-zero voxels are in _volData
bool inUserBounds(const PolyVox::SimpleVolume<uint8_t>* vol, PolyVoxEntityItem::PolyVoxSurfaceStyle surfaceStyle,
int x, int y, int z);
uint8_t getVoxelInternal(int x, int y, int z);
bool setVoxelInternal(int x, int y, int z, uint8_t toValue);
bool updateOnCount(int x, int y, int z, uint8_t toValue);
PolyVox::RaycastResult doRayCast(glm::vec4 originInVoxel, glm::vec4 farInVoxel, glm::vec4& result) const;
// these are run off the main thread
void decompressVolumeData();
void decompressVolumeDataAsync();
void compressVolumeDataAndSendEditPacket();
void compressVolumeDataAndSendEditPacketAsync();
void getMesh();
void getMeshAsync();
void computeShapeInfoWorker();
void computeShapeInfoWorkerAsync();
QSemaphore _threadRunning{1};
};

View file

@ -431,23 +431,10 @@ bool EntityScriptingInterface::setVoxels(QUuid entityID,
return false;
}
auto now = usecTimestampNow();
auto polyVoxEntity = std::dynamic_pointer_cast<PolyVoxEntityItem>(entity);
_entityTree->lockForWrite();
bool result = actor(*polyVoxEntity);
entity->setLastEdited(now);
entity->setLastBroadcast(now);
_entityTree->unlock();
_entityTree->lockForRead();
EntityItemProperties properties = entity->getProperties();
_entityTree->unlock();
properties.setVoxelDataDirty();
properties.setLastEdited(now);
queueEntityMessage(PacketType::EntityEdit, entityID, properties);
return result;
}

View file

@ -25,7 +25,7 @@ const glm::vec3 PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE = glm::vec3(32, 32,
const float PolyVoxEntityItem::MAX_VOXEL_DIMENSION = 128.0f;
const QByteArray PolyVoxEntityItem::DEFAULT_VOXEL_DATA(PolyVoxEntityItem::makeEmptyVoxelData());
const PolyVoxEntityItem::PolyVoxSurfaceStyle PolyVoxEntityItem::DEFAULT_VOXEL_SURFACE_STYLE =
PolyVoxEntityItem::SURFACE_MARCHING_CUBES;
PolyVoxEntityItem::SURFACE_EDGED_CUBIC;
const QString PolyVoxEntityItem::DEFAULT_X_TEXTURE_URL = QString("");
const QString PolyVoxEntityItem::DEFAULT_Y_TEXTURE_URL = QString("");
const QString PolyVoxEntityItem::DEFAULT_Z_TEXTURE_URL = QString("");
@ -52,6 +52,7 @@ PolyVoxEntityItem::PolyVoxEntityItem(const EntityItemID& entityItemID, const Ent
EntityItem(entityItemID),
_voxelVolumeSize(PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE),
_voxelData(PolyVoxEntityItem::DEFAULT_VOXEL_DATA),
_voxelDataDirty(true),
_voxelSurfaceStyle(PolyVoxEntityItem::DEFAULT_VOXEL_SURFACE_STYLE),
_xTextureURL(PolyVoxEntityItem::DEFAULT_X_TEXTURE_URL),
_yTextureURL(PolyVoxEntityItem::DEFAULT_Y_TEXTURE_URL),
@ -66,7 +67,7 @@ void PolyVoxEntityItem::setVoxelVolumeSize(glm::vec3 voxelVolumeSize) {
assert((int)_voxelVolumeSize.y == _voxelVolumeSize.y);
assert((int)_voxelVolumeSize.z == _voxelVolumeSize.z);
_voxelVolumeSize = voxelVolumeSize;
_voxelVolumeSize = glm::vec3(roundf(voxelVolumeSize.x), roundf(voxelVolumeSize.y), roundf(voxelVolumeSize.z));
if (_voxelVolumeSize.x < 1) {
qDebug() << "PolyVoxEntityItem::setVoxelVolumeSize clamping x of" << _voxelVolumeSize.x << "to 1";
_voxelVolumeSize.x = 1;
@ -185,9 +186,16 @@ void PolyVoxEntityItem::debugDump() const {
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
}
void PolyVoxEntityItem::setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle) {
if (voxelSurfaceStyle == _voxelSurfaceStyle) {
return;
}
updateVoxelSurfaceStyle(voxelSurfaceStyle);
void PolyVoxEntityItem::setVoxelData(QByteArray voxelData) {
_voxelDataLock.lockForWrite();
_voxelData = voxelData;
_voxelDataDirty = true;
_voxelDataLock.unlock();
}
const QByteArray PolyVoxEntityItem::getVoxelData() const {
_voxelDataLock.lockForRead();
auto result = _voxelData;
_voxelDataLock.unlock();
return result;
}

View file

@ -52,8 +52,8 @@ class PolyVoxEntityItem : public EntityItem {
virtual void setVoxelVolumeSize(glm::vec3 voxelVolumeSize);
virtual const glm::vec3& getVoxelVolumeSize() const { return _voxelVolumeSize; }
virtual void setVoxelData(QByteArray voxelData) { _voxelData = voxelData; }
virtual const QByteArray& getVoxelData() const { return _voxelData; }
virtual void setVoxelData(QByteArray voxelData);
virtual const QByteArray getVoxelData() const;
enum PolyVoxSurfaceStyle {
SURFACE_MARCHING_CUBES,
@ -62,7 +62,7 @@ class PolyVoxEntityItem : public EntityItem {
SURFACE_EDGED_MARCHING_CUBES
};
void setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle);
virtual void setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle) { _voxelSurfaceStyle = voxelSurfaceStyle; }
// this other version of setVoxelSurfaceStyle is needed for SET_ENTITY_PROPERTY_FROM_PROPERTIES
void setVoxelSurfaceStyle(uint16_t voxelSurfaceStyle) { setVoxelSurfaceStyle((PolyVoxSurfaceStyle) voxelSurfaceStyle); }
virtual PolyVoxSurfaceStyle getVoxelSurfaceStyle() const { return _voxelSurfaceStyle; }
@ -104,12 +104,12 @@ class PolyVoxEntityItem : public EntityItem {
virtual const QString& getZTextureURL() const { return _zTextureURL; }
protected:
virtual void updateVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle) {
_voxelSurfaceStyle = voxelSurfaceStyle;
}
glm::vec3 _voxelVolumeSize; // this is always 3 bytes
mutable QReadWriteLock _voxelDataLock;
QByteArray _voxelData;
bool _voxelDataDirty;
PolyVoxSurfaceStyle _voxelSurfaceStyle;
QString _xTextureURL;

View file

@ -99,7 +99,7 @@ void EntityMotionState::updateServerPhysicsVariables() {
}
// virtual
void EntityMotionState::handleEasyChanges(uint32_t flags, PhysicsEngine* engine) {
bool EntityMotionState::handleEasyChanges(uint32_t flags, PhysicsEngine* engine) {
assert(entityTreeIsLocked());
updateServerPhysicsVariables();
ObjectMotionState::handleEasyChanges(flags, engine);
@ -131,13 +131,15 @@ void EntityMotionState::handleEasyChanges(uint32_t flags, PhysicsEngine* engine)
if ((flags & EntityItem::DIRTY_PHYSICS_ACTIVATION) && !_body->isActive()) {
_body->activate();
}
return true;
}
// virtual
void EntityMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine) {
bool EntityMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine) {
updateServerPhysicsVariables();
ObjectMotionState::handleHardAndEasyChanges(flags, engine);
return ObjectMotionState::handleHardAndEasyChanges(flags, engine);
}
void EntityMotionState::clearObjectBackPointer() {
@ -222,6 +224,15 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) {
#endif
}
// virtual and protected
bool EntityMotionState::isReadyToComputeShape() {
if (_entity) {
return _entity->isReadyToComputeShape();
}
return false;
}
// virtual and protected
btCollisionShape* EntityMotionState::computeNewShape() {
if (_entity) {
@ -493,12 +504,11 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q
_lastStep = step;
}
uint32_t EntityMotionState::getAndClearIncomingDirtyFlags() {
uint32_t EntityMotionState::getIncomingDirtyFlags() {
assert(entityTreeIsLocked());
uint32_t dirtyFlags = 0;
if (_body && _entity) {
dirtyFlags = _entity->getDirtyFlags();
_entity->clearDirtyFlags();
// we add DIRTY_MOTION_TYPE if the body's motion type disagrees with entity velocity settings
int bodyFlags = _body->getCollisionFlags();
bool isMoving = _entity->isMoving();
@ -510,6 +520,13 @@ uint32_t EntityMotionState::getAndClearIncomingDirtyFlags() {
return dirtyFlags;
}
void EntityMotionState::clearIncomingDirtyFlags() {
assert(entityTreeIsLocked());
if (_body && _entity) {
_entity->clearDirtyFlags();
}
}
// virtual
quint8 EntityMotionState::getSimulationPriority() const {
if (_entity) {

View file

@ -29,8 +29,8 @@ public:
virtual ~EntityMotionState();
void updateServerPhysicsVariables();
virtual void handleEasyChanges(uint32_t flags, PhysicsEngine* engine);
virtual void handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine);
virtual bool handleEasyChanges(uint32_t flags, PhysicsEngine* engine);
virtual bool handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine);
/// \return MOTION_TYPE_DYNAMIC or MOTION_TYPE_STATIC based on params set in EntityItem
virtual MotionType computeObjectMotionType() const;
@ -48,7 +48,8 @@ public:
bool shouldSendUpdate(uint32_t simulationStep, const QUuid& sessionID);
void sendUpdate(OctreeEditPacketSender* packetSender, const QUuid& sessionID, uint32_t step);
virtual uint32_t getAndClearIncomingDirtyFlags();
virtual uint32_t getIncomingDirtyFlags();
virtual void clearIncomingDirtyFlags();
void incrementAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount++; }
void resetAccelerationNearlyGravityCount() { _accelerationNearlyGravityCount = 0; }
@ -91,6 +92,7 @@ protected:
bool entityTreeIsLocked() const;
#endif
virtual bool isReadyToComputeShape();
virtual btCollisionShape* computeNewShape();
virtual void clearObjectBackPointer();
virtual void setMotionType(MotionType motionType);

View file

@ -125,7 +125,7 @@ void ObjectMotionState::setRigidBody(btRigidBody* body) {
}
}
void ObjectMotionState::handleEasyChanges(uint32_t flags, PhysicsEngine* engine) {
bool ObjectMotionState::handleEasyChanges(uint32_t flags, PhysicsEngine* engine) {
if (flags & EntityItem::DIRTY_POSITION) {
btTransform worldTrans;
if (flags & EntityItem::DIRTY_ROTATION) {
@ -156,11 +156,16 @@ void ObjectMotionState::handleEasyChanges(uint32_t flags, PhysicsEngine* engine)
if (flags & EntityItem::DIRTY_MASS) {
updateBodyMassProperties();
}
return true;
}
void ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine) {
bool ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine) {
if (flags & EntityItem::DIRTY_SHAPE) {
// make sure the new shape is valid
if (!isReadyToComputeShape()) {
return false;
}
btCollisionShape* newShape = computeNewShape();
if (!newShape) {
qCDebug(physics) << "Warning: failed to generate new shape!";
@ -172,7 +177,7 @@ void ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine*
if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
handleEasyChanges(flags, engine);
}
return;
return true;
}
}
getShapeManager()->releaseShape(_shape);
@ -192,6 +197,8 @@ void ObjectMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine*
if (flags & HARD_DIRTY_PHYSICS_FLAGS) {
engine->reinsertObject(this);
}
return true;
}
void ObjectMotionState::updateBodyMaterialProperties() {

View file

@ -71,8 +71,8 @@ public:
ObjectMotionState(btCollisionShape* shape);
~ObjectMotionState();
virtual void handleEasyChanges(uint32_t flags, PhysicsEngine* engine);
virtual void handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine);
virtual bool handleEasyChanges(uint32_t flags, PhysicsEngine* engine);
virtual bool handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine);
void updateBodyMaterialProperties();
void updateBodyVelocities();
@ -92,7 +92,8 @@ public:
glm::vec3 getBodyAngularVelocity() const;
virtual glm::vec3 getObjectLinearVelocityChange() const;
virtual uint32_t getAndClearIncomingDirtyFlags() = 0;
virtual uint32_t getIncomingDirtyFlags() = 0;
virtual void clearIncomingDirtyFlags() = 0;
virtual MotionType computeObjectMotionType() const = 0;
@ -132,6 +133,7 @@ public:
friend class PhysicsEngine;
protected:
virtual bool isReadyToComputeShape() = 0;
virtual btCollisionShape* computeNewShape() = 0;
void setMotionType(MotionType motionType);

View file

@ -173,6 +173,12 @@ VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToAdd() {
return _tempVector;
}
void PhysicalEntitySimulation::setObjectsToChange(VectorOfMotionStates& objectsToChange) {
for (auto object : objectsToChange) {
_pendingChanges.insert(static_cast<EntityMotionState*>(object));
}
}
VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToChange() {
_tempVector.clear();
for (auto stateItr : _pendingChanges) {

View file

@ -46,11 +46,14 @@ protected: // only called by EntitySimulation
public:
VectorOfMotionStates& getObjectsToDelete();
VectorOfMotionStates& getObjectsToAdd();
void setObjectsToChange(VectorOfMotionStates& objectsToChange);
VectorOfMotionStates& getObjectsToChange();
void handleOutgoingChanges(VectorOfMotionStates& motionStates, const QUuid& sessionID);
void handleCollisionEvents(CollisionEvents& collisionEvents);
EntityEditPacketSender* getPacketSender() { return _entityPacketSender; }
private:
// incoming changes
SetOfEntityMotionStates _pendingRemoves; // EntityMotionStates to be removed from PhysicsEngine (and deleted)

View file

@ -140,7 +140,7 @@ void PhysicsEngine::addObject(ObjectMotionState* motionState) {
int16_t group = motionState->computeCollisionGroup();
_dynamicsWorld->addRigidBody(body, group, getCollisionMask(group));
motionState->getAndClearIncomingDirtyFlags();
motionState->clearIncomingDirtyFlags();
}
void PhysicsEngine::removeObject(ObjectMotionState* object) {
@ -188,15 +188,25 @@ void PhysicsEngine::addObjects(VectorOfMotionStates& objects) {
}
}
void PhysicsEngine::changeObjects(VectorOfMotionStates& objects) {
VectorOfMotionStates PhysicsEngine::changeObjects(VectorOfMotionStates& objects) {
VectorOfMotionStates stillNeedChange;
for (auto object : objects) {
uint32_t flags = object->getAndClearIncomingDirtyFlags() & DIRTY_PHYSICS_FLAGS;
uint32_t flags = object->getIncomingDirtyFlags() & DIRTY_PHYSICS_FLAGS;
if (flags & HARD_DIRTY_PHYSICS_FLAGS) {
object->handleHardAndEasyChanges(flags, this);
if (object->handleHardAndEasyChanges(flags, this)) {
object->clearIncomingDirtyFlags();
} else {
stillNeedChange.push_back(object);
}
} else if (flags & EASY_DIRTY_PHYSICS_FLAGS) {
object->handleEasyChanges(flags, this);
if (object->handleEasyChanges(flags, this)) {
object->clearIncomingDirtyFlags();
} else {
stillNeedChange.push_back(object);
}
}
}
return stillNeedChange;
}
void PhysicsEngine::reinsertObject(ObjectMotionState* object) {

View file

@ -60,7 +60,7 @@ public:
void deleteObjects(VectorOfMotionStates& objects);
void deleteObjects(SetOfMotionStates& objects); // only called during teardown
void addObjects(VectorOfMotionStates& objects);
void changeObjects(VectorOfMotionStates& objects);
VectorOfMotionStates changeObjects(VectorOfMotionStates& objects);
void reinsertObject(ObjectMotionState* object);
void stepSimulation();

View file

@ -94,7 +94,6 @@ btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) {
if (numSubShapes == 1) {
shape = createConvexHull(info.getPoints()[0]);
} else {
assert(numSubShapes > 1);
auto compound = new btCompoundShape();
btTransform trans;
trans.setIdentity();