mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 02:33:09 +02:00
commit
990dce6795
9 changed files with 456 additions and 172 deletions
|
@ -1072,6 +1072,7 @@
|
||||||
<option value='0'>marching cubes</option>
|
<option value='0'>marching cubes</option>
|
||||||
<option value='1'>cubic</option>
|
<option value='1'>cubic</option>
|
||||||
<option value='2'>edged cubic</option>
|
<option value='2'>edged cubic</option>
|
||||||
|
<option value='3'>edged marching cubes</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
|
||||||
var lineEntityID = null;
|
var lineEntityID = null;
|
||||||
|
var sphereEntityID = null;
|
||||||
var lineIsRezzed = false;
|
var lineIsRezzed = false;
|
||||||
|
|
||||||
var BUTTON_SIZE = 32;
|
var BUTTON_SIZE = 32;
|
||||||
|
@ -56,16 +57,24 @@ function nearLinePoint(targetPosition) {
|
||||||
|
|
||||||
|
|
||||||
function removeLine() {
|
function removeLine() {
|
||||||
if (lineIsRezzed) {
|
if (lineIsRezzed) {
|
||||||
Entities.deleteEntity(lineEntityID);
|
Entities.deleteEntity(lineEntityID);
|
||||||
lineEntityID = null;
|
if (sphereEntityID) {
|
||||||
lineIsRezzed = false;
|
Entities.deleteEntity(sphereEntityID);
|
||||||
}
|
}
|
||||||
|
lineEntityID = null;
|
||||||
|
sphereEntityID = null;
|
||||||
|
lineIsRezzed = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function createOrUpdateLine(event) {
|
function createOrUpdateLine(event) {
|
||||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||||
|
if (sphereEntityID) {
|
||||||
|
Entities.deleteEntity(sphereEntityID);
|
||||||
|
sphereEntityID = null;
|
||||||
|
}
|
||||||
var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking
|
var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking
|
||||||
var props = Entities.getEntityProperties(intersection.entityID);
|
var props = Entities.getEntityProperties(intersection.entityID);
|
||||||
|
|
||||||
|
@ -78,7 +87,6 @@ function createOrUpdateLine(event) {
|
||||||
position: MyAvatar.position,
|
position: MyAvatar.position,
|
||||||
lifetime: 15 + props.lifespan // renew lifetime
|
lifetime: 15 + props.lifespan // renew lifetime
|
||||||
});
|
});
|
||||||
// Entities.setAllPoints(lineEntityID, points);
|
|
||||||
} else {
|
} else {
|
||||||
lineIsRezzed = true;
|
lineIsRezzed = true;
|
||||||
lineEntityID = Entities.addEntity({
|
lineEntityID = Entities.addEntity({
|
||||||
|
@ -90,6 +98,15 @@ function createOrUpdateLine(event) {
|
||||||
lifetime: 15 // if someone crashes while pointing, don't leave the line there forever.
|
lifetime: 15 // if someone crashes while pointing, don't leave the line there forever.
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sphereEntityID = Entities.addEntity({
|
||||||
|
type: "Sphere",
|
||||||
|
position: intersection.intersection,
|
||||||
|
ignoreForCollisions: 1,
|
||||||
|
dimensions: { x: 0.6, y: 0.6, z: 0.6 },
|
||||||
|
color: { red: 0, green: 255, blue: 0 },
|
||||||
|
lifetime: 15 // if someone crashes while pointing, don't leave the line there forever.
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
removeLine();
|
removeLine();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +1,37 @@
|
||||||
var controlHeld = false;
|
var controlHeld = false;
|
||||||
var shiftHeld = false;
|
var shiftHeld = false;
|
||||||
|
|
||||||
|
function floorVector(v) {
|
||||||
function attemptVoxelChange(intersection) {
|
return {x: Math.floor(v.x), y: Math.floor(v.y), z: Math.floor(v.z)};
|
||||||
var ids = Entities.findEntities(intersection.intersection, 10);
|
|
||||||
var success = false;
|
|
||||||
for (var i = 0; i < ids.length; i++) {
|
|
||||||
var id = ids[i];
|
|
||||||
if (controlHeld) {
|
|
||||||
// hold control to erase a sphere
|
|
||||||
if (Entities.setVoxelSphere(id, intersection.intersection, 1.0, 0)) {
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
} else if (shiftHeld) {
|
|
||||||
// hold shift to set all voxels to 255
|
|
||||||
if (Entities.setAllVoxels(id, 255)) {
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// no modifier key means to add a sphere
|
|
||||||
if (Entities.setVoxelSphere(id, intersection.intersection, 1.0, 255)) {
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function attemptVoxelChange(pickRayDir, intersection) {
|
||||||
|
|
||||||
|
var properties = Entities.getEntityProperties(intersection.entityID);
|
||||||
|
if (properties.type != "PolyVox") {
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (controlHeld) {
|
||||||
|
// hold control to erase a voxel
|
||||||
|
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
|
||||||
|
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) {
|
function mousePressEvent(event) {
|
||||||
if (!event.isLeftButton) {
|
if (!event.isLeftButton) {
|
||||||
|
@ -36,10 +41,8 @@ function mousePressEvent(event) {
|
||||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||||
var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking
|
var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking
|
||||||
|
|
||||||
// we've used a picking ray to decide where to add the new sphere of voxels. If we pick nothing
|
|
||||||
// or if we pick a non-PolyVox entity, we fall through to the next picking attempt.
|
|
||||||
if (intersection.intersects) {
|
if (intersection.intersects) {
|
||||||
if (attemptVoxelChange(intersection)) {
|
if (attemptVoxelChange(pickRay.direction, intersection)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,7 +51,7 @@ function mousePressEvent(event) {
|
||||||
// bounding box, instead.
|
// bounding box, instead.
|
||||||
intersection = Entities.findRayIntersection(pickRay, false); // bounding box picking
|
intersection = Entities.findRayIntersection(pickRay, false); // bounding box picking
|
||||||
if (intersection.intersects) {
|
if (intersection.intersects) {
|
||||||
attemptVoxelChange(intersection);
|
attemptVoxelChange(pickRay.direction, intersection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
|
||||||
#if defined(__GNUC__) && !defined(__clang__)
|
#if defined(__GNUC__) && !defined(__clang__)
|
||||||
|
@ -40,9 +41,10 @@
|
||||||
#include "EntityTreeRenderer.h"
|
#include "EntityTreeRenderer.h"
|
||||||
#include "polyvox_vert.h"
|
#include "polyvox_vert.h"
|
||||||
#include "polyvox_frag.h"
|
#include "polyvox_frag.h"
|
||||||
#include "RenderablePolyVoxEntityItem.h"
|
#include "RenderablePolyVoxEntityItem.h"
|
||||||
|
|
||||||
gpu::PipelinePointer RenderablePolyVoxEntityItem::_pipeline = nullptr;
|
gpu::PipelinePointer RenderablePolyVoxEntityItem::_pipeline = nullptr;
|
||||||
|
const float MARCHING_CUBE_COLLISION_HULL_OFFSET = 0.5;
|
||||||
|
|
||||||
EntityItemPointer RenderablePolyVoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
EntityItemPointer RenderablePolyVoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||||
return std::make_shared<RenderablePolyVoxEntityItem>(entityID, properties);
|
return std::make_shared<RenderablePolyVoxEntityItem>(entityID, properties);
|
||||||
|
@ -66,7 +68,7 @@ RenderablePolyVoxEntityItem::~RenderablePolyVoxEntityItem() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inUserBounds(const PolyVox::SimpleVolume<uint8_t>* vol, PolyVoxEntityItem::PolyVoxSurfaceStyle surfaceStyle,
|
bool inUserBounds(const PolyVox::SimpleVolume<uint8_t>* vol, PolyVoxEntityItem::PolyVoxSurfaceStyle surfaceStyle,
|
||||||
int x, int y, int z) {
|
int x, int y, int z) {
|
||||||
// x, y, z are in user voxel-coords, not adjusted-for-edge voxel-coords.
|
// x, y, z are in user voxel-coords, not adjusted-for-edge voxel-coords.
|
||||||
switch (surfaceStyle) {
|
switch (surfaceStyle) {
|
||||||
case PolyVoxEntityItem::SURFACE_MARCHING_CUBES:
|
case PolyVoxEntityItem::SURFACE_MARCHING_CUBES:
|
||||||
|
@ -78,6 +80,7 @@ bool inUserBounds(const PolyVox::SimpleVolume<uint8_t>* vol, PolyVoxEntityItem::
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case PolyVoxEntityItem::SURFACE_EDGED_CUBIC:
|
case PolyVoxEntityItem::SURFACE_EDGED_CUBIC:
|
||||||
|
case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES:
|
||||||
if (x < 0 || y < 0 || z < 0 ||
|
if (x < 0 || y < 0 || z < 0 ||
|
||||||
x >= vol->getWidth() - 2 || y >= vol->getHeight() - 2 || z >= vol->getDepth() - 2) {
|
x >= vol->getWidth() - 2 || y >= vol->getHeight() - 2 || z >= vol->getDepth() - 2) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -112,7 +115,7 @@ void RenderablePolyVoxEntityItem::setVoxelVolumeSize(glm::vec3 voxelVolumeSize)
|
||||||
|
|
||||||
_onCount = 0;
|
_onCount = 0;
|
||||||
|
|
||||||
if (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC) {
|
if (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC || _voxelSurfaceStyle == SURFACE_EDGED_MARCHING_CUBES) {
|
||||||
// with _EDGED_ we maintain an extra box of voxels around those that the user asked for. This
|
// with _EDGED_ we maintain an extra box of voxels around those that the user asked for. This
|
||||||
// changes how the surface extractor acts -- mainly it becomes impossible to have holes in the
|
// changes how the surface extractor acts -- mainly it becomes impossible to have holes in the
|
||||||
// generated mesh. The non _EDGED_ modes will leave holes in the mesh at the edges of the
|
// generated mesh. The non _EDGED_ modes will leave holes in the mesh at the edges of the
|
||||||
|
@ -156,8 +159,10 @@ void RenderablePolyVoxEntityItem::setVoxelVolumeSize(glm::vec3 voxelVolumeSize)
|
||||||
|
|
||||||
void RenderablePolyVoxEntityItem::updateVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle) {
|
void RenderablePolyVoxEntityItem::updateVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle) {
|
||||||
// if we are switching to or from "edged" we need to force a resize of _volData.
|
// if we are switching to or from "edged" we need to force a resize of _volData.
|
||||||
if (voxelSurfaceStyle == SURFACE_EDGED_CUBIC ||
|
bool wasEdged = (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC || _voxelSurfaceStyle == SURFACE_EDGED_MARCHING_CUBES);
|
||||||
_voxelSurfaceStyle == SURFACE_EDGED_CUBIC) {
|
bool willBeEdged = (voxelSurfaceStyle == SURFACE_EDGED_CUBIC || voxelSurfaceStyle == SURFACE_EDGED_MARCHING_CUBES);
|
||||||
|
|
||||||
|
if (wasEdged != willBeEdged) {
|
||||||
if (_volData) {
|
if (_volData) {
|
||||||
delete _volData;
|
delete _volData;
|
||||||
}
|
}
|
||||||
|
@ -182,11 +187,11 @@ glm::vec3 RenderablePolyVoxEntityItem::getSurfacePositionAdjustment() const {
|
||||||
glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units
|
glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units
|
||||||
switch (_voxelSurfaceStyle) {
|
switch (_voxelSurfaceStyle) {
|
||||||
case PolyVoxEntityItem::SURFACE_MARCHING_CUBES:
|
case PolyVoxEntityItem::SURFACE_MARCHING_CUBES:
|
||||||
return scale / 2.0f;
|
|
||||||
case PolyVoxEntityItem::SURFACE_EDGED_CUBIC:
|
|
||||||
return scale / -2.0f;
|
|
||||||
case PolyVoxEntityItem::SURFACE_CUBIC:
|
case PolyVoxEntityItem::SURFACE_CUBIC:
|
||||||
return scale / 2.0f;
|
return scale / 2.0f;
|
||||||
|
case PolyVoxEntityItem::SURFACE_EDGED_CUBIC:
|
||||||
|
case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES:
|
||||||
|
return scale / -2.0f;
|
||||||
}
|
}
|
||||||
return glm::vec3(0.0f, 0.0f, 0.0f);
|
return glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
@ -202,6 +207,11 @@ glm::mat4 RenderablePolyVoxEntityItem::voxelToLocalMatrix() const {
|
||||||
return scaled;
|
return scaled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::mat4 RenderablePolyVoxEntityItem::localToVoxelMatrix() const {
|
||||||
|
glm::mat4 localToModelMatrix = glm::inverse(voxelToLocalMatrix());
|
||||||
|
return localToModelMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
glm::mat4 RenderablePolyVoxEntityItem::voxelToWorldMatrix() const {
|
glm::mat4 RenderablePolyVoxEntityItem::voxelToWorldMatrix() const {
|
||||||
glm::mat4 rotation = glm::mat4_cast(getRotation());
|
glm::mat4 rotation = glm::mat4_cast(getRotation());
|
||||||
glm::mat4 translation = glm::translate(getPosition());
|
glm::mat4 translation = glm::translate(getPosition());
|
||||||
|
@ -223,84 +233,115 @@ uint8_t RenderablePolyVoxEntityItem::getVoxel(int x, int y, int z) {
|
||||||
// voxels all around the requested voxel space. Having the empty voxels around
|
// voxels all around the requested voxel space. Having the empty voxels around
|
||||||
// the edges changes how the surface extractor behaves.
|
// the edges changes how the surface extractor behaves.
|
||||||
|
|
||||||
if (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC) {
|
if (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC || _voxelSurfaceStyle == SURFACE_EDGED_MARCHING_CUBES) {
|
||||||
return _volData->getVoxelAt(x + 1, y + 1, z + 1);
|
return _volData->getVoxelAt(x + 1, y + 1, z + 1);
|
||||||
}
|
}
|
||||||
return _volData->getVoxelAt(x, y, z);
|
return _volData->getVoxelAt(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderablePolyVoxEntityItem::setVoxelInternal(int x, int y, int z, uint8_t toValue) {
|
bool RenderablePolyVoxEntityItem::setVoxelInternal(int x, int y, int z, uint8_t toValue) {
|
||||||
// set a voxel without recompressing the voxel data
|
// set a voxel without recompressing the voxel data
|
||||||
assert(_volData);
|
assert(_volData);
|
||||||
|
bool result = false;
|
||||||
if (!inUserBounds(_volData, _voxelSurfaceStyle, x, y, z)) {
|
if (!inUserBounds(_volData, _voxelSurfaceStyle, x, y, z)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateOnCount(x, y, z, toValue);
|
result = updateOnCount(x, y, z, toValue);
|
||||||
|
|
||||||
if (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC) {
|
if (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC || _voxelSurfaceStyle == SURFACE_EDGED_MARCHING_CUBES) {
|
||||||
_volData->setVoxelAt(x + 1, y + 1, z + 1, toValue);
|
_volData->setVoxelAt(x + 1, y + 1, z + 1, toValue);
|
||||||
} else {
|
} else {
|
||||||
_volData->setVoxelAt(x, y, z, toValue);
|
_volData->setVoxelAt(x, y, z, toValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderablePolyVoxEntityItem::clearEdges() {
|
||||||
void RenderablePolyVoxEntityItem::setVoxel(int x, int y, int z, uint8_t toValue) {
|
// if we are in an edged mode, make sure the outside surfaces are zeroed out.
|
||||||
if (_locked) {
|
if (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC || _voxelSurfaceStyle == SURFACE_EDGED_MARCHING_CUBES) {
|
||||||
return;
|
for (int z = 0; z < _volData->getDepth(); z++) {
|
||||||
|
for (int y = 0; y < _volData->getHeight(); y++) {
|
||||||
|
for (int x = 0; x < _volData->getWidth(); x++) {
|
||||||
|
if (x == 0 || y == 0 || z == 0 ||
|
||||||
|
x == _volData->getWidth() - 1 ||
|
||||||
|
y == _volData->getHeight() - 1 ||
|
||||||
|
z == _volData->getDepth() - 1) {
|
||||||
|
_volData->setVoxelAt(x, y, z, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setVoxelInternal(x, y, z, toValue);
|
|
||||||
compressVolumeData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderablePolyVoxEntityItem::updateOnCount(int x, int y, int z, uint8_t toValue) {
|
bool RenderablePolyVoxEntityItem::setVoxel(int x, int y, int z, uint8_t toValue) {
|
||||||
|
if (_locked) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool result = setVoxelInternal(x, y, z, toValue);
|
||||||
|
if (result) {
|
||||||
|
compressVolumeData();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RenderablePolyVoxEntityItem::updateOnCount(int x, int y, int z, uint8_t toValue) {
|
||||||
// keep _onCount up to date
|
// keep _onCount up to date
|
||||||
if (!inUserBounds(_volData, _voxelSurfaceStyle, x, y, z)) {
|
if (!inUserBounds(_volData, _voxelSurfaceStyle, x, y, z)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t uVoxelValue = getVoxel(x, y, z);
|
uint8_t uVoxelValue = getVoxel(x, y, z);
|
||||||
if (toValue != 0) {
|
if (toValue != 0) {
|
||||||
if (uVoxelValue == 0) {
|
if (uVoxelValue == 0) {
|
||||||
_onCount++;
|
_onCount++;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// toValue == 0
|
// toValue == 0
|
||||||
if (uVoxelValue != 0) {
|
if (uVoxelValue != 0) {
|
||||||
_onCount--;
|
_onCount--;
|
||||||
assert(_onCount >= 0);
|
assert(_onCount >= 0);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderablePolyVoxEntityItem::setAll(uint8_t toValue) {
|
bool RenderablePolyVoxEntityItem::setAll(uint8_t toValue) {
|
||||||
|
bool result = false;
|
||||||
if (_locked) {
|
if (_locked) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int z = 0; z < _voxelVolumeSize.z; z++) {
|
for (int z = 0; z < _voxelVolumeSize.z; z++) {
|
||||||
for (int y = 0; y < _voxelVolumeSize.y; y++) {
|
for (int y = 0; y < _voxelVolumeSize.y; y++) {
|
||||||
for (int x = 0; x < _voxelVolumeSize.x; x++) {
|
for (int x = 0; x < _voxelVolumeSize.x; x++) {
|
||||||
setVoxelInternal(x, y, z, toValue);
|
result |= setVoxelInternal(x, y, z, toValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compressVolumeData();
|
if (result) {
|
||||||
|
compressVolumeData();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderablePolyVoxEntityItem::setVoxelInVolume(glm::vec3 position, uint8_t toValue) {
|
bool RenderablePolyVoxEntityItem::setVoxelInVolume(glm::vec3 position, uint8_t toValue) {
|
||||||
if (_locked) {
|
if (_locked) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// same as setVoxel but takes a vector rather than 3 floats.
|
// same as setVoxel but takes a vector rather than 3 floats.
|
||||||
setVoxel((int)position.x, (int)position.y, (int)position.z, toValue);
|
return setVoxel(roundf(position.x), roundf(position.y), roundf(position.z), toValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) {
|
bool RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) {
|
||||||
|
bool result = false;
|
||||||
if (_locked) {
|
if (_locked) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This three-level for loop iterates over every voxel in the volume
|
// This three-level for loop iterates over every voxel in the volume
|
||||||
|
@ -313,22 +354,24 @@ void RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radi
|
||||||
float fDistToCenter = glm::distance(pos, center);
|
float fDistToCenter = glm::distance(pos, center);
|
||||||
// If the current voxel is less than 'radius' units from the center then we make it solid.
|
// If the current voxel is less than 'radius' units from the center then we make it solid.
|
||||||
if (fDistToCenter <= radius) {
|
if (fDistToCenter <= radius) {
|
||||||
updateOnCount(x, y, z, toValue);
|
result |= setVoxelInternal(x, y, z, toValue);
|
||||||
setVoxelInternal(x, y, z, toValue);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compressVolumeData();
|
if (result) {
|
||||||
|
compressVolumeData();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderablePolyVoxEntityItem::setSphere(glm::vec3 centerWorldCoords, float radiusWorldCoords, uint8_t toValue) {
|
bool RenderablePolyVoxEntityItem::setSphere(glm::vec3 centerWorldCoords, float radiusWorldCoords, uint8_t toValue) {
|
||||||
// glm::vec3 centerVoxelCoords = worldToVoxelCoordinates(centerWorldCoords);
|
// glm::vec3 centerVoxelCoords = worldToVoxelCoordinates(centerWorldCoords);
|
||||||
glm::vec4 centerVoxelCoords = worldToVoxelMatrix() * glm::vec4(centerWorldCoords, 1.0f);
|
glm::vec4 centerVoxelCoords = worldToVoxelMatrix() * glm::vec4(centerWorldCoords, 1.0f);
|
||||||
glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units
|
glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units
|
||||||
float scaleY = scale.y;
|
float scaleY = scale.y;
|
||||||
float radiusVoxelCoords = radiusWorldCoords / scaleY;
|
float radiusVoxelCoords = radiusWorldCoords / scaleY;
|
||||||
setSphereInVolume(glm::vec3(centerVoxelCoords), radiusVoxelCoords, toValue);
|
return setSphereInVolume(glm::vec3(centerVoxelCoords), radiusVoxelCoords, toValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
class RaycastFunctor
|
class RaycastFunctor
|
||||||
|
@ -340,9 +383,10 @@ public:
|
||||||
}
|
}
|
||||||
bool operator()(PolyVox::SimpleVolume<unsigned char>::Sampler& sampler)
|
bool operator()(PolyVox::SimpleVolume<unsigned char>::Sampler& sampler)
|
||||||
{
|
{
|
||||||
int x = sampler.getPosition().getX();
|
PolyVox::Vector3DInt32 positionIndex = sampler.getPosition();
|
||||||
int y = sampler.getPosition().getY();
|
int x = positionIndex.getX();
|
||||||
int z = sampler.getPosition().getZ();
|
int y = positionIndex.getY();
|
||||||
|
int z = positionIndex.getZ();
|
||||||
|
|
||||||
if (!inBounds(_vol, x, y, z)) {
|
if (!inBounds(_vol, x, y, z)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -351,8 +395,8 @@ public:
|
||||||
if (sampler.getVoxel() == 0) {
|
if (sampler.getVoxel() == 0) {
|
||||||
return true; // keep raycasting
|
return true; // keep raycasting
|
||||||
}
|
}
|
||||||
PolyVox::Vector3DInt32 positionIndex = sampler.getPosition();
|
|
||||||
_result = glm::vec4(positionIndex.getX(), positionIndex.getY(), positionIndex.getZ(), 1.0f);
|
_result = glm::vec4((float)x, (float)y, (float)z, 1.0f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
glm::vec4 _result;
|
glm::vec4 _result;
|
||||||
|
@ -367,13 +411,16 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o
|
||||||
void** intersectedObject,
|
void** intersectedObject,
|
||||||
bool precisionPicking) const
|
bool precisionPicking) const
|
||||||
{
|
{
|
||||||
|
// TODO -- correctly pick against marching-cube generated meshes
|
||||||
|
|
||||||
if (_needsModelReload || !precisionPicking) {
|
if (_needsModelReload || !precisionPicking) {
|
||||||
// just intersect with bounding box
|
// just intersect with bounding box
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the PolyVox ray intersection code requires a near and far point.
|
|
||||||
glm::mat4 wtvMatrix = worldToVoxelMatrix();
|
glm::mat4 wtvMatrix = worldToVoxelMatrix();
|
||||||
|
glm::mat4 vtwMatrix = voxelToWorldMatrix();
|
||||||
|
glm::mat4 vtlMatrix = voxelToLocalMatrix();
|
||||||
glm::vec3 normDirection = glm::normalize(direction);
|
glm::vec3 normDirection = glm::normalize(direction);
|
||||||
|
|
||||||
// the PolyVox ray intersection code requires a near and far point.
|
// the PolyVox ray intersection code requires a near and far point.
|
||||||
|
@ -396,23 +443,58 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec4 result = callback._result;
|
// result is in voxel-space coordinates.
|
||||||
switch (_voxelSurfaceStyle) {
|
glm::vec4 result = callback._result - glm::vec4(0.5f, 0.5f, 0.5f, 0.0f);
|
||||||
case PolyVoxEntityItem::SURFACE_EDGED_CUBIC:
|
|
||||||
result -= glm::vec4(1, 1, 1, 0); // compensate for the extra voxel border
|
// set up ray tests against each face of the voxel.
|
||||||
break;
|
glm::vec3 minXPosition = glm::vec3(vtwMatrix * (result + glm::vec4(0.0f, 0.5f, 0.5f, 0.0f)));
|
||||||
case PolyVoxEntityItem::SURFACE_MARCHING_CUBES:
|
glm::vec3 maxXPosition = glm::vec3(vtwMatrix * (result + glm::vec4(1.0f, 0.5f, 0.5f, 0.0f)));
|
||||||
case PolyVoxEntityItem::SURFACE_CUBIC:
|
glm::vec3 minYPosition = glm::vec3(vtwMatrix * (result + glm::vec4(0.5f, 0.0f, 0.5f, 0.0f)));
|
||||||
break;
|
glm::vec3 maxYPosition = glm::vec3(vtwMatrix * (result + glm::vec4(0.5f, 1.0f, 0.5f, 0.0f)));
|
||||||
|
glm::vec3 minZPosition = glm::vec3(vtwMatrix * (result + glm::vec4(0.5f, 0.5f, 0.0f, 0.0f)));
|
||||||
|
glm::vec3 maxZPosition = glm::vec3(vtwMatrix * (result + glm::vec4(0.5f, 0.5f, 1.0f, 0.0f)));
|
||||||
|
|
||||||
|
glm::vec4 baseDimensions = glm::vec4(1.0, 1.0, 1.0, 0.0);
|
||||||
|
glm::vec3 worldDimensions = glm::vec3(vtlMatrix * baseDimensions);
|
||||||
|
glm::vec2 xDimensions = glm::vec2(worldDimensions.z, worldDimensions.y);
|
||||||
|
glm::vec2 yDimensions = glm::vec2(worldDimensions.x, worldDimensions.z);
|
||||||
|
glm::vec2 zDimensions = glm::vec2(worldDimensions.x, worldDimensions.y);
|
||||||
|
|
||||||
|
glm::quat vtwRotation = extractRotation(vtwMatrix);
|
||||||
|
glm::quat minXRotation = vtwRotation * glm::quat(glm::vec3(0.0f, PI_OVER_TWO, 0.0f));
|
||||||
|
glm::quat maxXRotation = vtwRotation * glm::quat(glm::vec3(0.0f, PI_OVER_TWO, 0.0f));
|
||||||
|
glm::quat minYRotation = vtwRotation * glm::quat(glm::vec3(PI_OVER_TWO, 0.0f, 0.0f));
|
||||||
|
glm::quat maxYRotation = vtwRotation * glm::quat(glm::vec3(PI_OVER_TWO, 0.0f, 0.0f));
|
||||||
|
glm::quat minZRotation = vtwRotation * glm::quat(glm::vec3(0.0f, 0.0f, 0.0f));
|
||||||
|
glm::quat maxZRotation = vtwRotation * glm::quat(glm::vec3(0.0f, 0.0f, 0.0f));
|
||||||
|
|
||||||
|
float bestDx = FLT_MAX;
|
||||||
|
bool hit[ 6 ];
|
||||||
|
float dx[ 6 ] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
|
||||||
|
|
||||||
|
hit[0] = findRayRectangleIntersection(origin, direction, minXRotation, minXPosition, xDimensions, dx[0]);
|
||||||
|
hit[1] = findRayRectangleIntersection(origin, direction, maxXRotation, maxXPosition, xDimensions, dx[1]);
|
||||||
|
hit[2] = findRayRectangleIntersection(origin, direction, minYRotation, minYPosition, yDimensions, dx[2]);
|
||||||
|
hit[3] = findRayRectangleIntersection(origin, direction, maxYRotation, maxYPosition, yDimensions, dx[3]);
|
||||||
|
hit[4] = findRayRectangleIntersection(origin, direction, minZRotation, minZPosition, zDimensions, dx[4]);
|
||||||
|
hit[5] = findRayRectangleIntersection(origin, direction, maxZRotation, maxZPosition, zDimensions, dx[5]);
|
||||||
|
|
||||||
|
bool ok = false;
|
||||||
|
for (int i = 0; i < 6; i ++) {
|
||||||
|
if (hit[ i ] && dx[ i ] < bestDx) {
|
||||||
|
face = (BoxFace)i;
|
||||||
|
distance = dx[ i ];
|
||||||
|
ok = true;
|
||||||
|
bestDx = dx[ i ];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result -= glm::vec4(0.5f, 0.5f, 0.5f, 0.0f);
|
if (!ok) {
|
||||||
|
// if the attempt to put the ray against one of the voxel-faces fails, just return the center
|
||||||
glm::vec4 intersectedWorldPosition = voxelToWorldMatrix() * result;
|
glm::vec4 intersectedWorldPosition = vtwMatrix * (result + vec4(0.5f, 0.5f, 0.5f, 0.0f));
|
||||||
|
distance = glm::distance(glm::vec3(intersectedWorldPosition), origin);
|
||||||
distance = glm::distance(glm::vec3(intersectedWorldPosition), origin);
|
face = BoxFace::MIN_X_FACE;
|
||||||
|
}
|
||||||
face = BoxFace::MIN_X_FACE; // XXX
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -421,6 +503,10 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o
|
||||||
// compress the data in _volData and save the results. The compressed form is used during
|
// compress the data in _volData and save the results. The compressed form is used during
|
||||||
// saves to disk and for transmission over the wire
|
// saves to disk and for transmission over the wire
|
||||||
void RenderablePolyVoxEntityItem::compressVolumeData() {
|
void RenderablePolyVoxEntityItem::compressVolumeData() {
|
||||||
|
#ifdef WANT_DEBUG
|
||||||
|
auto startTime = usecTimestampNow();
|
||||||
|
#endif
|
||||||
|
|
||||||
quint16 voxelXSize = _voxelVolumeSize.x;
|
quint16 voxelXSize = _voxelVolumeSize.x;
|
||||||
quint16 voxelYSize = _voxelVolumeSize.y;
|
quint16 voxelYSize = _voxelVolumeSize.y;
|
||||||
quint16 voxelZSize = _voxelVolumeSize.z;
|
quint16 voxelZSize = _voxelVolumeSize.z;
|
||||||
|
@ -471,6 +557,10 @@ void RenderablePolyVoxEntityItem::compressVolumeData() {
|
||||||
|
|
||||||
_dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS;
|
_dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS;
|
||||||
_needsModelReload = true;
|
_needsModelReload = true;
|
||||||
|
|
||||||
|
#ifdef WANT_DEBUG
|
||||||
|
qDebug() << "RenderablePolyVoxEntityItem::compressVolumeData" << (usecTimestampNow() - startTime) << getName();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -506,11 +596,11 @@ void RenderablePolyVoxEntityItem::decompressVolumeData() {
|
||||||
for (int y = 0; y < voxelYSize; y++) {
|
for (int y = 0; y < voxelYSize; y++) {
|
||||||
for (int x = 0; x < voxelXSize; x++) {
|
for (int x = 0; x < voxelXSize; x++) {
|
||||||
int uncompressedIndex = (z * voxelYSize * voxelXSize) + (y * voxelZSize) + x;
|
int uncompressedIndex = (z * voxelYSize * voxelXSize) + (y * voxelZSize) + x;
|
||||||
updateOnCount(x, y, z, uncompressedData[uncompressedIndex]);
|
|
||||||
setVoxelInternal(x, y, z, uncompressedData[uncompressedIndex]);
|
setVoxelInternal(x, y, z, uncompressedData[uncompressedIndex]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
clearEdges();
|
||||||
|
|
||||||
#ifdef WANT_DEBUG
|
#ifdef WANT_DEBUG
|
||||||
qDebug() << "--------------- voxel decompress ---------------";
|
qDebug() << "--------------- voxel decompress ---------------";
|
||||||
|
@ -553,53 +643,112 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_points.clear();
|
_points.clear();
|
||||||
unsigned int i = 0;
|
|
||||||
|
|
||||||
glm::mat4 wToM = voxelToLocalMatrix();
|
|
||||||
|
|
||||||
AABox box;
|
AABox box;
|
||||||
|
glm::mat4 vtoM = voxelToLocalMatrix();
|
||||||
|
|
||||||
for (int z = 0; z < _voxelVolumeSize.z; z++) {
|
if (_voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_MARCHING_CUBES ||
|
||||||
for (int y = 0; y < _voxelVolumeSize.y; y++) {
|
_voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES) {
|
||||||
for (int x = 0; x < _voxelVolumeSize.x; x++) {
|
unsigned int i = 0;
|
||||||
if (getVoxel(x, y, z) > 0) {
|
/* pull top-facing triangles into polyhedrons so they can be walked on */
|
||||||
QVector<glm::vec3> pointsInPart;
|
const model::MeshPointer& mesh = _modelGeometry.getMesh();
|
||||||
|
const gpu::BufferView vertexBufferView = mesh->getVertexBuffer();
|
||||||
|
const gpu::BufferView& indexBufferView = mesh->getIndexBuffer();
|
||||||
|
gpu::BufferView::Iterator<const uint32_t> it = indexBufferView.cbegin<uint32_t>();
|
||||||
|
while (it != indexBufferView.cend<uint32_t>()) {
|
||||||
|
uint32_t p0Index = *(it++);
|
||||||
|
uint32_t p1Index = *(it++);
|
||||||
|
uint32_t p2Index = *(it++);
|
||||||
|
|
||||||
float offL = -0.5f;
|
const glm::vec3& p0 = vertexBufferView.get<const glm::vec3>(p0Index);
|
||||||
float offH = 0.5f;
|
const glm::vec3& p1 = vertexBufferView.get<const glm::vec3>(p1Index);
|
||||||
|
const glm::vec3& p2 = vertexBufferView.get<const glm::vec3>(p2Index);
|
||||||
|
|
||||||
glm::vec3 p000 = glm::vec3(wToM * glm::vec4(x + offL, y + offL, z + offL, 1.0f));
|
glm::vec3 av = (p0 + p1 + p2) / 3.0f; // center of the triangular face
|
||||||
glm::vec3 p001 = glm::vec3(wToM * glm::vec4(x + offL, y + offL, z + offH, 1.0f));
|
glm::vec3 normal = glm::normalize(glm::cross(p1 - p0, p2 - p0));
|
||||||
glm::vec3 p010 = glm::vec3(wToM * glm::vec4(x + offL, y + offH, z + offL, 1.0f));
|
glm::vec3 p3 = av - normal * MARCHING_CUBE_COLLISION_HULL_OFFSET;
|
||||||
glm::vec3 p011 = glm::vec3(wToM * glm::vec4(x + offL, y + offH, z + offH, 1.0f));
|
|
||||||
glm::vec3 p100 = glm::vec3(wToM * glm::vec4(x + offH, y + offL, z + offL, 1.0f));
|
|
||||||
glm::vec3 p101 = glm::vec3(wToM * glm::vec4(x + offH, y + offL, z + offH, 1.0f));
|
|
||||||
glm::vec3 p110 = glm::vec3(wToM * glm::vec4(x + offH, y + offH, z + offL, 1.0f));
|
|
||||||
glm::vec3 p111 = glm::vec3(wToM * glm::vec4(x + offH, y + offH, z + offH, 1.0f));
|
|
||||||
|
|
||||||
box += p000;
|
glm::vec3 p0Model = glm::vec3(vtoM * glm::vec4(p0, 1.0f));
|
||||||
box += p001;
|
glm::vec3 p1Model = glm::vec3(vtoM * glm::vec4(p1, 1.0f));
|
||||||
box += p010;
|
glm::vec3 p2Model = glm::vec3(vtoM * glm::vec4(p2, 1.0f));
|
||||||
box += p011;
|
glm::vec3 p3Model = glm::vec3(vtoM * glm::vec4(p3, 1.0f));
|
||||||
box += p100;
|
|
||||||
box += p101;
|
|
||||||
box += p110;
|
|
||||||
box += p111;
|
|
||||||
|
|
||||||
pointsInPart << p000;
|
box += p0Model;
|
||||||
pointsInPart << p001;
|
box += p1Model;
|
||||||
pointsInPart << p010;
|
box += p2Model;
|
||||||
pointsInPart << p011;
|
box += p3Model;
|
||||||
pointsInPart << p100;
|
|
||||||
pointsInPart << p101;
|
|
||||||
pointsInPart << p110;
|
|
||||||
pointsInPart << p111;
|
|
||||||
|
|
||||||
// add next convex hull
|
QVector<glm::vec3> pointsInPart;
|
||||||
QVector<glm::vec3> newMeshPoints;
|
pointsInPart << p0Model;
|
||||||
_points << newMeshPoints;
|
pointsInPart << p1Model;
|
||||||
// add points to the new convex hull
|
pointsInPart << p2Model;
|
||||||
_points[i++] << pointsInPart;
|
pointsInPart << p3Model;
|
||||||
|
// add next convex hull
|
||||||
|
QVector<glm::vec3> newMeshPoints;
|
||||||
|
_points << newMeshPoints;
|
||||||
|
// add points to the new convex hull
|
||||||
|
_points[i++] << pointsInPart;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unsigned int i = 0;
|
||||||
|
|
||||||
|
for (int z = 0; z < _voxelVolumeSize.z; z++) {
|
||||||
|
for (int y = 0; y < _voxelVolumeSize.y; y++) {
|
||||||
|
for (int x = 0; x < _voxelVolumeSize.x; x++) {
|
||||||
|
if (getVoxel(x, y, z) > 0) {
|
||||||
|
|
||||||
|
if ((x > 0 && getVoxel(x - 1, y, z) > 0) &&
|
||||||
|
(y > 0 && getVoxel(x, y - 1, z) > 0) &&
|
||||||
|
(z > 0 && getVoxel(x, y, z - 1) > 0) &&
|
||||||
|
(x < _voxelVolumeSize.x - 1 && getVoxel(x + 1, y, z) > 0) &&
|
||||||
|
(y < _voxelVolumeSize.y - 1 && getVoxel(x, y + 1, z) > 0) &&
|
||||||
|
(z < _voxelVolumeSize.z - 1 && getVoxel(x, y, z + 1) > 0)) {
|
||||||
|
// this voxel has neighbors in every cardinal direction, so there's no need
|
||||||
|
// to include it in the collision hull.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<glm::vec3> pointsInPart;
|
||||||
|
|
||||||
|
float offL = -0.5f;
|
||||||
|
float offH = 0.5f;
|
||||||
|
if (_voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_EDGED_CUBIC) {
|
||||||
|
offL += 1.0f;
|
||||||
|
offH += 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 p000 = glm::vec3(vtoM * glm::vec4(x + offL, y + offL, z + offL, 1.0f));
|
||||||
|
glm::vec3 p001 = glm::vec3(vtoM * glm::vec4(x + offL, y + offL, z + offH, 1.0f));
|
||||||
|
glm::vec3 p010 = glm::vec3(vtoM * glm::vec4(x + offL, y + offH, z + offL, 1.0f));
|
||||||
|
glm::vec3 p011 = glm::vec3(vtoM * glm::vec4(x + offL, y + offH, z + offH, 1.0f));
|
||||||
|
glm::vec3 p100 = glm::vec3(vtoM * glm::vec4(x + offH, y + offL, z + offL, 1.0f));
|
||||||
|
glm::vec3 p101 = glm::vec3(vtoM * glm::vec4(x + offH, y + offL, z + offH, 1.0f));
|
||||||
|
glm::vec3 p110 = glm::vec3(vtoM * glm::vec4(x + offH, y + offH, z + offL, 1.0f));
|
||||||
|
glm::vec3 p111 = glm::vec3(vtoM * glm::vec4(x + offH, y + offH, z + offH, 1.0f));
|
||||||
|
|
||||||
|
box += p000;
|
||||||
|
box += p001;
|
||||||
|
box += p010;
|
||||||
|
box += p011;
|
||||||
|
box += p100;
|
||||||
|
box += p101;
|
||||||
|
box += p110;
|
||||||
|
box += p111;
|
||||||
|
|
||||||
|
pointsInPart << p000;
|
||||||
|
pointsInPart << p001;
|
||||||
|
pointsInPart << p010;
|
||||||
|
pointsInPart << p011;
|
||||||
|
pointsInPart << p100;
|
||||||
|
pointsInPart << p101;
|
||||||
|
pointsInPart << p110;
|
||||||
|
pointsInPart << p111;
|
||||||
|
|
||||||
|
// add next convex hull
|
||||||
|
QVector<glm::vec3> newMeshPoints;
|
||||||
|
_points << newMeshPoints;
|
||||||
|
// add points to the new convex hull
|
||||||
|
_points[i++] << pointsInPart;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -629,10 +778,15 @@ void RenderablePolyVoxEntityItem::setZTextureURL(QString zTextureURL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderablePolyVoxEntityItem::getModel() {
|
void RenderablePolyVoxEntityItem::getModel() {
|
||||||
|
#ifdef WANT_DEBUG
|
||||||
|
auto startTime = usecTimestampNow();
|
||||||
|
#endif
|
||||||
|
|
||||||
// A mesh object to hold the result of surface extraction
|
// A mesh object to hold the result of surface extraction
|
||||||
PolyVox::SurfaceMesh<PolyVox::PositionMaterialNormal> polyVoxMesh;
|
PolyVox::SurfaceMesh<PolyVox::PositionMaterialNormal> polyVoxMesh;
|
||||||
|
|
||||||
switch (_voxelSurfaceStyle) {
|
switch (_voxelSurfaceStyle) {
|
||||||
|
case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES:
|
||||||
case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: {
|
case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: {
|
||||||
PolyVox::MarchingCubesSurfaceExtractor<PolyVox::SimpleVolume<uint8_t>> surfaceExtractor
|
PolyVox::MarchingCubesSurfaceExtractor<PolyVox::SimpleVolume<uint8_t>> surfaceExtractor
|
||||||
(_volData, _volData->getEnclosingRegion(), &polyVoxMesh);
|
(_volData, _volData->getEnclosingRegion(), &polyVoxMesh);
|
||||||
|
@ -682,6 +836,10 @@ void RenderablePolyVoxEntityItem::getModel() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_needsModelReload = false;
|
_needsModelReload = false;
|
||||||
|
|
||||||
|
#ifdef WANT_DEBUG
|
||||||
|
qDebug() << "RenderablePolyVoxEntityItem::getModel" << (usecTimestampNow() - startTime) << getName();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
|
void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
|
||||||
|
@ -737,8 +895,6 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
|
||||||
_zTexture = DependencyManager::get<TextureCache>()->getTexture(_zTextureURL);
|
_zTexture = DependencyManager::get<TextureCache>()->getTexture(_zTextureURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
||||||
|
|
||||||
if (_xTexture) {
|
if (_xTexture) {
|
||||||
batch.setResourceTexture(0, _xTexture->getGPUTexture());
|
batch.setResourceTexture(0, _xTexture->getGPUTexture());
|
||||||
} else {
|
} else {
|
||||||
|
@ -802,3 +958,19 @@ namespace render {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToWorldCoords(glm::vec3& voxelCoords) const {
|
||||||
|
return glm::vec3(voxelToWorldMatrix() * glm::vec4(voxelCoords, 1.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 RenderablePolyVoxEntityItem::worldCoordsToVoxelCoords(glm::vec3& worldCoords) const {
|
||||||
|
return glm::vec3(worldToVoxelMatrix() * glm::vec4(worldCoords, 1.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToLocalCoords(glm::vec3& voxelCoords) const {
|
||||||
|
return glm::vec3(voxelToLocalMatrix() * glm::vec4(voxelCoords, 0.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 RenderablePolyVoxEntityItem::localCoordsToVoxelCoords(glm::vec3& localCoords) const {
|
||||||
|
return glm::vec3(localToVoxelMatrix() * glm::vec4(localCoords, 0.0f));
|
||||||
|
}
|
||||||
|
|
|
@ -54,9 +54,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual uint8_t getVoxel(int x, int y, int z);
|
virtual uint8_t getVoxel(int x, int y, int z);
|
||||||
virtual void setVoxel(int x, int y, int z, uint8_t toValue);
|
virtual bool setVoxel(int x, int y, int z, uint8_t toValue);
|
||||||
|
|
||||||
void updateOnCount(int x, int y, int z, uint8_t new_value);
|
bool updateOnCount(int x, int y, int z, uint8_t new_value);
|
||||||
|
|
||||||
void render(RenderArgs* args);
|
void render(RenderArgs* args);
|
||||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||||
|
@ -71,23 +71,26 @@ public:
|
||||||
virtual void setVoxelVolumeSize(glm::vec3 voxelVolumeSize);
|
virtual void setVoxelVolumeSize(glm::vec3 voxelVolumeSize);
|
||||||
glm::vec3 getSurfacePositionAdjustment() const;
|
glm::vec3 getSurfacePositionAdjustment() const;
|
||||||
glm::mat4 voxelToWorldMatrix() const;
|
glm::mat4 voxelToWorldMatrix() const;
|
||||||
glm::mat4 voxelToLocalMatrix() const;
|
|
||||||
glm::mat4 worldToVoxelMatrix() const;
|
glm::mat4 worldToVoxelMatrix() const;
|
||||||
|
glm::mat4 voxelToLocalMatrix() const;
|
||||||
|
glm::mat4 localToVoxelMatrix() const;
|
||||||
|
|
||||||
virtual ShapeType getShapeType() const;
|
virtual ShapeType getShapeType() const;
|
||||||
virtual bool isReadyToComputeShape();
|
virtual bool isReadyToComputeShape();
|
||||||
virtual void computeShapeInfo(ShapeInfo& info);
|
virtual void computeShapeInfo(ShapeInfo& info);
|
||||||
|
|
||||||
|
virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3& voxelCoords) const;
|
||||||
|
virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3& worldCoords) const;
|
||||||
|
virtual glm::vec3 voxelCoordsToLocalCoords(glm::vec3& voxelCoords) const;
|
||||||
|
virtual glm::vec3 localCoordsToVoxelCoords(glm::vec3& localCoords) const;
|
||||||
|
|
||||||
// coords are in voxel-volume space
|
// coords are in voxel-volume space
|
||||||
virtual void setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue);
|
virtual bool setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue);
|
||||||
|
virtual bool setVoxelInVolume(glm::vec3 position, uint8_t toValue);
|
||||||
|
|
||||||
// coords are in world-space
|
// coords are in world-space
|
||||||
virtual void setSphere(glm::vec3 center, float radius, uint8_t toValue);
|
virtual bool setSphere(glm::vec3 center, float radius, uint8_t toValue);
|
||||||
|
virtual bool setAll(uint8_t toValue);
|
||||||
virtual void setAll(uint8_t toValue);
|
|
||||||
|
|
||||||
virtual void setVoxelInVolume(glm::vec3 position, uint8_t toValue);
|
|
||||||
|
|
||||||
virtual void setXTextureURL(QString xTextureURL);
|
virtual void setXTextureURL(QString xTextureURL);
|
||||||
virtual void setYTextureURL(QString yTextureURL);
|
virtual void setYTextureURL(QString yTextureURL);
|
||||||
|
@ -107,10 +110,10 @@ private:
|
||||||
// The PolyVoxEntityItem class has _voxelData which contains dimensions and compressed voxel data. The dimensions
|
// The PolyVoxEntityItem class has _voxelData which contains dimensions and compressed voxel data. The dimensions
|
||||||
// may not match _voxelVolumeSize.
|
// may not match _voxelVolumeSize.
|
||||||
|
|
||||||
void setVoxelInternal(int x, int y, int z, uint8_t toValue);
|
bool setVoxelInternal(int x, int y, int z, uint8_t toValue);
|
||||||
void compressVolumeData();
|
void compressVolumeData();
|
||||||
void decompressVolumeData();
|
void decompressVolumeData();
|
||||||
|
void clearEdges();
|
||||||
|
|
||||||
PolyVox::SimpleVolume<uint8_t>* _volData = nullptr;
|
PolyVox::SimpleVolume<uint8_t>* _volData = nullptr;
|
||||||
model::Geometry _modelGeometry;
|
model::Geometry _modelGeometry;
|
||||||
|
|
|
@ -415,7 +415,7 @@ void RayToEntityIntersectionResultFromScriptValue(const QScriptValue& object, Ra
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityScriptingInterface::setVoxels(QUuid entityID,
|
bool EntityScriptingInterface::setVoxels(QUuid entityID,
|
||||||
std::function<void(PolyVoxEntityItem&)> actor) {
|
std::function<bool(PolyVoxEntityItem&)> actor) {
|
||||||
if (!_entityTree) {
|
if (!_entityTree) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -435,7 +435,7 @@ bool EntityScriptingInterface::setVoxels(QUuid entityID,
|
||||||
|
|
||||||
auto polyVoxEntity = std::dynamic_pointer_cast<PolyVoxEntityItem>(entity);
|
auto polyVoxEntity = std::dynamic_pointer_cast<PolyVoxEntityItem>(entity);
|
||||||
_entityTree->lockForWrite();
|
_entityTree->lockForWrite();
|
||||||
actor(*polyVoxEntity);
|
bool result = actor(*polyVoxEntity);
|
||||||
entity->setLastEdited(now);
|
entity->setLastEdited(now);
|
||||||
entity->setLastBroadcast(now);
|
entity->setLastBroadcast(now);
|
||||||
_entityTree->unlock();
|
_entityTree->unlock();
|
||||||
|
@ -448,42 +448,41 @@ bool EntityScriptingInterface::setVoxels(QUuid entityID,
|
||||||
properties.setLastEdited(now);
|
properties.setLastEdited(now);
|
||||||
|
|
||||||
queueEntityMessage(PacketType::EntityEdit, entityID, properties);
|
queueEntityMessage(PacketType::EntityEdit, entityID, properties);
|
||||||
return true;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityScriptingInterface::setPoints(QUuid entityID, std::function<bool(LineEntityItem&)> actor) {
|
bool EntityScriptingInterface::setPoints(QUuid entityID, std::function<bool(LineEntityItem&)> actor) {
|
||||||
if (!_entityTree) {
|
if (!_entityTree) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityItemPointer entity = static_cast<EntityItemPointer>(_entityTree->findEntityByEntityItemID(entityID));
|
EntityItemPointer entity = static_cast<EntityItemPointer>(_entityTree->findEntityByEntityItemID(entityID));
|
||||||
if (!entity) {
|
if (!entity) {
|
||||||
qCDebug(entities) << "EntityScriptingInterface::setPoints no entity with ID" << entityID;
|
qCDebug(entities) << "EntityScriptingInterface::setPoints no entity with ID" << entityID;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityTypes::EntityType entityType = entity->getType();
|
EntityTypes::EntityType entityType = entity->getType();
|
||||||
|
|
||||||
if (entityType != EntityTypes::Line) {
|
if (entityType != EntityTypes::Line) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto now = usecTimestampNow();
|
auto now = usecTimestampNow();
|
||||||
|
|
||||||
auto lineEntity = std::static_pointer_cast<LineEntityItem>(entity);
|
auto lineEntity = std::static_pointer_cast<LineEntityItem>(entity);
|
||||||
_entityTree->lockForWrite();
|
_entityTree->lockForWrite();
|
||||||
bool success = actor(*lineEntity);
|
bool success = actor(*lineEntity);
|
||||||
entity->setLastEdited(now);
|
entity->setLastEdited(now);
|
||||||
entity->setLastBroadcast(now);
|
entity->setLastBroadcast(now);
|
||||||
_entityTree->unlock();
|
_entityTree->unlock();
|
||||||
|
|
||||||
_entityTree->lockForRead();
|
_entityTree->lockForRead();
|
||||||
EntityItemProperties properties = entity->getProperties();
|
EntityItemProperties properties = entity->getProperties();
|
||||||
_entityTree->unlock();
|
_entityTree->unlock();
|
||||||
|
|
||||||
properties.setLinePointsDirty();
|
properties.setLinePointsDirty();
|
||||||
properties.setLastEdited(now);
|
properties.setLastEdited(now);
|
||||||
|
|
||||||
|
|
||||||
queueEntityMessage(PacketType::EntityEdit, entityID, properties);
|
queueEntityMessage(PacketType::EntityEdit, entityID, properties);
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
@ -491,19 +490,19 @@ bool EntityScriptingInterface::setPoints(QUuid entityID, std::function<bool(Line
|
||||||
|
|
||||||
bool EntityScriptingInterface::setVoxelSphere(QUuid entityID, const glm::vec3& center, float radius, int value) {
|
bool EntityScriptingInterface::setVoxelSphere(QUuid entityID, const glm::vec3& center, float radius, int value) {
|
||||||
return setVoxels(entityID, [center, radius, value](PolyVoxEntityItem& polyVoxEntity) {
|
return setVoxels(entityID, [center, radius, value](PolyVoxEntityItem& polyVoxEntity) {
|
||||||
polyVoxEntity.setSphere(center, radius, value);
|
return polyVoxEntity.setSphere(center, radius, value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityScriptingInterface::setVoxel(QUuid entityID, const glm::vec3& position, int value) {
|
bool EntityScriptingInterface::setVoxel(QUuid entityID, const glm::vec3& position, int value) {
|
||||||
return setVoxels(entityID, [position, value](PolyVoxEntityItem& polyVoxEntity) {
|
return setVoxels(entityID, [position, value](PolyVoxEntityItem& polyVoxEntity) {
|
||||||
polyVoxEntity.setVoxelInVolume(position, value);
|
return polyVoxEntity.setVoxelInVolume(position, value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityScriptingInterface::setAllVoxels(QUuid entityID, int value) {
|
bool EntityScriptingInterface::setAllVoxels(QUuid entityID, int value) {
|
||||||
return setVoxels(entityID, [value](PolyVoxEntityItem& polyVoxEntity) {
|
return setVoxels(entityID, [value](PolyVoxEntityItem& polyVoxEntity) {
|
||||||
polyVoxEntity.setAll(value);
|
return polyVoxEntity.setAll(value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,16 +511,16 @@ bool EntityScriptingInterface::setAllPoints(QUuid entityID, const QVector<glm::v
|
||||||
if (!entity) {
|
if (!entity) {
|
||||||
qCDebug(entities) << "EntityScriptingInterface::setPoints no entity with ID" << entityID;
|
qCDebug(entities) << "EntityScriptingInterface::setPoints no entity with ID" << entityID;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityTypes::EntityType entityType = entity->getType();
|
EntityTypes::EntityType entityType = entity->getType();
|
||||||
|
|
||||||
if (entityType == EntityTypes::Line) {
|
if (entityType == EntityTypes::Line) {
|
||||||
return setPoints(entityID, [points](LineEntityItem& lineEntity) -> bool
|
return setPoints(entityID, [points](LineEntityItem& lineEntity) -> bool
|
||||||
{
|
{
|
||||||
return (LineEntityItem*)lineEntity.setLinePoints(points);
|
return (LineEntityItem*)lineEntity.setLinePoints(points);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -658,3 +657,83 @@ QVariantMap EntityScriptingInterface::getActionArguments(const QUuid& entityID,
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec3 EntityScriptingInterface::voxelCoordsToWorldCoords(const QUuid& entityID, glm::vec3 voxelCoords) {
|
||||||
|
if (!_entityTree) {
|
||||||
|
return glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID);
|
||||||
|
if (!entity) {
|
||||||
|
qCDebug(entities) << "EntityScriptingInterface::voxelCoordsToWorldCoords no entity with ID" << entityID;
|
||||||
|
return glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityTypes::EntityType entityType = entity->getType();
|
||||||
|
if (entityType != EntityTypes::PolyVox) {
|
||||||
|
return glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto polyVoxEntity = std::dynamic_pointer_cast<PolyVoxEntityItem>(entity);
|
||||||
|
return polyVoxEntity->voxelCoordsToWorldCoords(voxelCoords);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 EntityScriptingInterface::worldCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 worldCoords) {
|
||||||
|
if (!_entityTree) {
|
||||||
|
return glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID);
|
||||||
|
if (!entity) {
|
||||||
|
qCDebug(entities) << "EntityScriptingInterface::worldCoordsToVoxelCoords no entity with ID" << entityID;
|
||||||
|
return glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityTypes::EntityType entityType = entity->getType();
|
||||||
|
if (entityType != EntityTypes::PolyVox) {
|
||||||
|
return glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto polyVoxEntity = std::dynamic_pointer_cast<PolyVoxEntityItem>(entity);
|
||||||
|
return polyVoxEntity->worldCoordsToVoxelCoords(worldCoords);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 EntityScriptingInterface::voxelCoordsToLocalCoords(const QUuid& entityID, glm::vec3 voxelCoords) {
|
||||||
|
if (!_entityTree) {
|
||||||
|
return glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID);
|
||||||
|
if (!entity) {
|
||||||
|
qCDebug(entities) << "EntityScriptingInterface::voxelCoordsToLocalCoords no entity with ID" << entityID;
|
||||||
|
return glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityTypes::EntityType entityType = entity->getType();
|
||||||
|
if (entityType != EntityTypes::PolyVox) {
|
||||||
|
return glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto polyVoxEntity = std::dynamic_pointer_cast<PolyVoxEntityItem>(entity);
|
||||||
|
return polyVoxEntity->voxelCoordsToLocalCoords(voxelCoords);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 EntityScriptingInterface::localCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 localCoords) {
|
||||||
|
if (!_entityTree) {
|
||||||
|
return glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID);
|
||||||
|
if (!entity) {
|
||||||
|
qCDebug(entities) << "EntityScriptingInterface::localCoordsToVoxelCoords no entity with ID" << entityID;
|
||||||
|
return glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityTypes::EntityType entityType = entity->getType();
|
||||||
|
if (entityType != EntityTypes::PolyVox) {
|
||||||
|
return glm::vec3(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto polyVoxEntity = std::dynamic_pointer_cast<PolyVoxEntityItem>(entity);
|
||||||
|
return polyVoxEntity->localCoordsToVoxelCoords(localCoords);
|
||||||
|
}
|
||||||
|
|
|
@ -134,6 +134,11 @@ public slots:
|
||||||
Q_INVOKABLE QVector<QUuid> getActionIDs(const QUuid& entityID);
|
Q_INVOKABLE QVector<QUuid> getActionIDs(const QUuid& entityID);
|
||||||
Q_INVOKABLE QVariantMap getActionArguments(const QUuid& entityID, const QUuid& actionID);
|
Q_INVOKABLE QVariantMap getActionArguments(const QUuid& entityID, const QUuid& actionID);
|
||||||
|
|
||||||
|
Q_INVOKABLE glm::vec3 voxelCoordsToWorldCoords(const QUuid& entityID, glm::vec3 voxelCoords);
|
||||||
|
Q_INVOKABLE glm::vec3 worldCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 worldCoords);
|
||||||
|
Q_INVOKABLE glm::vec3 voxelCoordsToLocalCoords(const QUuid& entityID, glm::vec3 voxelCoords);
|
||||||
|
Q_INVOKABLE glm::vec3 localCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 localCoords);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
|
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
|
||||||
void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
|
void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
|
||||||
|
@ -162,7 +167,7 @@ signals:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool actionWorker(const QUuid& entityID, std::function<bool(EntitySimulation*, EntityItemPointer)> actor);
|
bool actionWorker(const QUuid& entityID, std::function<bool(EntitySimulation*, EntityItemPointer)> actor);
|
||||||
bool setVoxels(QUuid entityID, std::function<void(PolyVoxEntityItem&)> actor);
|
bool setVoxels(QUuid entityID, std::function<bool(PolyVoxEntityItem&)> actor);
|
||||||
bool setPoints(QUuid entityID, std::function<bool(LineEntityItem&)> actor);
|
bool setPoints(QUuid entityID, std::function<bool(LineEntityItem&)> actor);
|
||||||
void queueEntityMessage(PacketType::Value packetType, EntityItemID entityID, const EntityItemProperties& properties);
|
void queueEntityMessage(PacketType::Value packetType, EntityItemID entityID, const EntityItemProperties& properties);
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
|
|
||||||
const glm::vec3 PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE = glm::vec3(32, 32, 32);
|
const glm::vec3 PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE = glm::vec3(32, 32, 32);
|
||||||
const float PolyVoxEntityItem::MAX_VOXEL_DIMENSION = 32.0f;
|
const float PolyVoxEntityItem::MAX_VOXEL_DIMENSION = 128.0f;
|
||||||
const QByteArray PolyVoxEntityItem::DEFAULT_VOXEL_DATA(PolyVoxEntityItem::makeEmptyVoxelData());
|
const QByteArray PolyVoxEntityItem::DEFAULT_VOXEL_DATA(PolyVoxEntityItem::makeEmptyVoxelData());
|
||||||
const PolyVoxEntityItem::PolyVoxSurfaceStyle PolyVoxEntityItem::DEFAULT_VOXEL_SURFACE_STYLE =
|
const PolyVoxEntityItem::PolyVoxSurfaceStyle PolyVoxEntityItem::DEFAULT_VOXEL_SURFACE_STYLE =
|
||||||
PolyVoxEntityItem::SURFACE_MARCHING_CUBES;
|
PolyVoxEntityItem::SURFACE_MARCHING_CUBES;
|
||||||
|
|
|
@ -58,7 +58,8 @@ class PolyVoxEntityItem : public EntityItem {
|
||||||
enum PolyVoxSurfaceStyle {
|
enum PolyVoxSurfaceStyle {
|
||||||
SURFACE_MARCHING_CUBES,
|
SURFACE_MARCHING_CUBES,
|
||||||
SURFACE_CUBIC,
|
SURFACE_CUBIC,
|
||||||
SURFACE_EDGED_CUBIC
|
SURFACE_EDGED_CUBIC,
|
||||||
|
SURFACE_EDGED_MARCHING_CUBES
|
||||||
};
|
};
|
||||||
|
|
||||||
void setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle);
|
void setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle);
|
||||||
|
@ -73,17 +74,20 @@ class PolyVoxEntityItem : public EntityItem {
|
||||||
static const PolyVoxSurfaceStyle DEFAULT_VOXEL_SURFACE_STYLE;
|
static const PolyVoxSurfaceStyle DEFAULT_VOXEL_SURFACE_STYLE;
|
||||||
|
|
||||||
// coords are in voxel-volume space
|
// coords are in voxel-volume space
|
||||||
virtual void setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) {}
|
virtual bool setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) { return false; }
|
||||||
|
virtual bool setVoxelInVolume(glm::vec3 position, uint8_t toValue) { return false; }
|
||||||
|
|
||||||
|
virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3& voxelCoords) const { return glm::vec3(0.0f); }
|
||||||
|
virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3& worldCoords) const { return glm::vec3(0.0f); }
|
||||||
|
virtual glm::vec3 voxelCoordsToLocalCoords(glm::vec3& voxelCoords) const { return glm::vec3(0.0f); }
|
||||||
|
virtual glm::vec3 localCoordsToVoxelCoords(glm::vec3& localCoords) const { return glm::vec3(0.0f); }
|
||||||
|
|
||||||
// coords are in world-space
|
// coords are in world-space
|
||||||
virtual void setSphere(glm::vec3 center, float radius, uint8_t toValue) {}
|
virtual bool setSphere(glm::vec3 center, float radius, uint8_t toValue) { return false; }
|
||||||
|
virtual bool setAll(uint8_t toValue) { return false; }
|
||||||
virtual void setAll(uint8_t toValue) {}
|
|
||||||
|
|
||||||
virtual void setVoxelInVolume(glm::vec3 position, uint8_t toValue) {}
|
|
||||||
|
|
||||||
virtual uint8_t getVoxel(int x, int y, int z) { return 0; }
|
virtual uint8_t getVoxel(int x, int y, int z) { return 0; }
|
||||||
virtual void setVoxel(int x, int y, int z, uint8_t toValue) {}
|
virtual bool setVoxel(int x, int y, int z, uint8_t toValue) { return false; }
|
||||||
|
|
||||||
static QByteArray makeEmptyVoxelData(quint16 voxelXSize = 16, quint16 voxelYSize = 16, quint16 voxelZSize = 16);
|
static QByteArray makeEmptyVoxelData(quint16 voxelXSize = 16, quint16 voxelYSize = 16, quint16 voxelZSize = 16);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue