mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 11:45:36 +02:00
commit
de6afb4d74
20 changed files with 977 additions and 596 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
@ -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};
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue