in edged mode, make sure border voxels are zeroed out. expose some more voxel matrix math to javascript

This commit is contained in:
Seth Alves 2015-08-16 09:36:54 -07:00
parent 6db115bed5
commit b129c2a933
5 changed files with 117 additions and 18 deletions

View file

@ -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__)
@ -67,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:
@ -206,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());
@ -252,13 +258,32 @@ bool RenderablePolyVoxEntityItem::setVoxelInternal(int x, int y, int z, uint8_t
return result; return result;
} }
void RenderablePolyVoxEntityItem::clearEdges() {
// if we are in an edged mode, make sure the outside surfaces are zeroed out.
if (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC || _voxelSurfaceStyle == SURFACE_EDGED_MARCHING_CUBES) {
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);
}
}
}
}
}
}
bool RenderablePolyVoxEntityItem::setVoxel(int x, int y, int z, uint8_t toValue) { bool RenderablePolyVoxEntityItem::setVoxel(int x, int y, int z, uint8_t toValue) {
if (_locked) { if (_locked) {
return false; return false;
} }
bool result = setVoxelInternal(x, y, z, toValue); bool result = setVoxelInternal(x, y, z, toValue);
compressVolumeData(); if (result) {
compressVolumeData();
}
return result; return result;
} }
@ -298,7 +323,9 @@ bool RenderablePolyVoxEntityItem::setAll(uint8_t toValue) {
} }
} }
} }
compressVolumeData(); if (result) {
compressVolumeData();
}
return result; return result;
} }
@ -308,7 +335,7 @@ bool RenderablePolyVoxEntityItem::setVoxelInVolume(glm::vec3 position, uint8_t t
} }
// same as setVoxel but takes a vector rather than 3 floats. // same as setVoxel but takes a vector rather than 3 floats.
return setVoxel((int)position.x, (int)position.y, (int)position.z, toValue); return setVoxel(roundf(position.x), roundf(position.y), roundf(position.z), toValue);
} }
bool RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) { bool RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) {
@ -332,7 +359,9 @@ bool RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radi
} }
} }
} }
compressVolumeData(); if (result) {
compressVolumeData();
}
return result; return result;
} }
@ -354,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;
@ -365,8 +395,9 @@ public:
if (sampler.getVoxel() == 0) { if (sampler.getVoxel() == 0) {
return true; // keep raycasting return true; // keep raycasting
} }
PolyVox::Vector3DInt32 positionIndex = sampler.getPosition(); // qDebug() << "RaycastFunctor hit" << x << y << z;
_result = glm::vec4(positionIndex.getX(), positionIndex.getY(), positionIndex.getZ(), 1.0f); // add {0.5, 0.5, 0.5} to result so it's centered on the voxel
_result = glm::vec4((float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f, 1.0f);
return false; return false;
} }
glm::vec4 _result; glm::vec4 _result;
@ -386,7 +417,6 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o
return true; return true;
} }
// the PolyVox ray intersection code requires a near and far point.
glm::mat4 wtvMatrix = worldToVoxelMatrix(); glm::mat4 wtvMatrix = worldToVoxelMatrix();
glm::vec3 normDirection = glm::normalize(direction); glm::vec3 normDirection = glm::normalize(direction);
@ -411,23 +441,29 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o
} }
glm::vec4 result = callback._result; glm::vec4 result = callback._result;
switch (_voxelSurfaceStyle) { switch (_voxelSurfaceStyle) {
case PolyVoxEntityItem::SURFACE_EDGED_CUBIC: case PolyVoxEntityItem::SURFACE_EDGED_CUBIC:
case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES: case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES:
result -= glm::vec4(1, 1, 1, 0); // compensate for the extra voxel border result -= glm::vec4(1.0f, 1.0f, 1.0f, 0.0f); // compensate for the extra voxel border
break; break;
case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: case PolyVoxEntityItem::SURFACE_MARCHING_CUBES:
case PolyVoxEntityItem::SURFACE_CUBIC: case PolyVoxEntityItem::SURFACE_CUBIC:
break; break;
} }
result -= glm::vec4(0.5f, 0.5f, 0.5f, 0.0f); // result -= glm::vec4(0.5f, 0.5f, 0.5f, 0.0f);
glm::vec4 intersectedWorldPosition = voxelToWorldMatrix() * result; glm::vec4 intersectedWorldPosition = voxelToWorldMatrix() * result;
distance = glm::distance(glm::vec3(intersectedWorldPosition), origin); // TODO: use this to find the actual point of intersection rather than using the center of the voxel
// GeometryUtil.h
// bool findRayRectangleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::quat& rotation,
// const glm::vec3& position, const glm::vec2& dimensions, float& distance);;
face = BoxFace::MIN_X_FACE; // XXX face = BoxFace::MIN_X_FACE;
distance = glm::distance(glm::vec3(intersectedWorldPosition), origin);
return true; return true;
} }
@ -436,6 +472,8 @@ 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() {
auto startTime = usecTimestampNow();
quint16 voxelXSize = _voxelVolumeSize.x; quint16 voxelXSize = _voxelVolumeSize.x;
quint16 voxelYSize = _voxelVolumeSize.y; quint16 voxelYSize = _voxelVolumeSize.y;
quint16 voxelZSize = _voxelVolumeSize.z; quint16 voxelZSize = _voxelVolumeSize.z;
@ -486,6 +524,8 @@ void RenderablePolyVoxEntityItem::compressVolumeData() {
_dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS; _dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS;
_needsModelReload = true; _needsModelReload = true;
qDebug() << "RenderablePolyVoxEntityItem::compressVolumeData" << (usecTimestampNow() - startTime) << getName();
} }
@ -525,6 +565,7 @@ void RenderablePolyVoxEntityItem::decompressVolumeData() {
} }
} }
} }
clearEdges();
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qDebug() << "--------------- voxel decompress ---------------"; qDebug() << "--------------- voxel decompress ---------------";
@ -628,7 +669,6 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) {
offH += 1.0f; offH += 1.0f;
} }
glm::vec3 p000 = glm::vec3(vtoM * glm::vec4(x + offL, y + offL, z + offL, 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 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 p010 = glm::vec3(vtoM * glm::vec4(x + offL, y + offH, z + offL, 1.0f));
@ -691,6 +731,8 @@ void RenderablePolyVoxEntityItem::setZTextureURL(QString zTextureURL) {
} }
void RenderablePolyVoxEntityItem::getModel() { void RenderablePolyVoxEntityItem::getModel() {
auto startTime = usecTimestampNow();
// 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;
@ -745,6 +787,8 @@ void RenderablePolyVoxEntityItem::getModel() {
#endif #endif
_needsModelReload = false; _needsModelReload = false;
qDebug() << "RenderablePolyVoxEntityItem::getModel" << (usecTimestampNow() - startTime) << getName();
} }
void RenderablePolyVoxEntityItem::render(RenderArgs* args) { void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
@ -871,3 +915,11 @@ glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToWorldCoords(glm::vec3 voxelC
glm::vec3 RenderablePolyVoxEntityItem::worldCoordsToVoxelCoords(glm::vec3 worldCoords) { glm::vec3 RenderablePolyVoxEntityItem::worldCoordsToVoxelCoords(glm::vec3 worldCoords) {
return glm::vec3(worldToVoxelMatrix() * glm::vec4(worldCoords, 1.0f)); return glm::vec3(worldToVoxelMatrix() * glm::vec4(worldCoords, 1.0f));
} }
glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToLocalCoords(glm::vec3 voxelCoords) {
return glm::vec3(voxelToLocalMatrix() * glm::vec4(voxelCoords, 1.0f));
}
glm::vec3 RenderablePolyVoxEntityItem::localCoordsToVoxelCoords(glm::vec3 localCoords) {
return glm::vec3(localToVoxelMatrix() * glm::vec4(localCoords, 1.0f));
}

View file

@ -71,8 +71,9 @@ 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();
@ -80,6 +81,8 @@ public:
virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3 voxelCoords); virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3 voxelCoords);
virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3 worldCoords); virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3 worldCoords);
virtual glm::vec3 voxelCoordsToLocalCoords(glm::vec3 voxelCoords);
virtual glm::vec3 localCoordsToVoxelCoords(glm::vec3 localCoords);
// coords are in voxel-volume space // coords are in voxel-volume space
virtual bool setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue); virtual bool setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue);
@ -110,7 +113,7 @@ private:
bool 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;

View file

@ -697,3 +697,43 @@ glm::vec3 EntityScriptingInterface::worldCoordsToVoxelCoords(const QUuid& entity
auto polyVoxEntity = std::dynamic_pointer_cast<PolyVoxEntityItem>(entity); auto polyVoxEntity = std::dynamic_pointer_cast<PolyVoxEntityItem>(entity);
return polyVoxEntity->worldCoordsToVoxelCoords(worldCoords); 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);
}

View file

@ -136,6 +136,8 @@ public slots:
Q_INVOKABLE glm::vec3 voxelCoordsToWorldCoords(const QUuid& entityID, glm::vec3 voxelCoords); 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 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);

View file

@ -79,6 +79,8 @@ class PolyVoxEntityItem : public EntityItem {
virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3 voxelCoords) { return glm::vec3(0.0f); } virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3 voxelCoords) { return glm::vec3(0.0f); }
virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3 worldCoords) { return glm::vec3(0.0f); } virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3 worldCoords) { return glm::vec3(0.0f); }
virtual glm::vec3 voxelCoordsToLocalCoords(glm::vec3 voxelCoords) { return glm::vec3(0.0f); }
virtual glm::vec3 localCoordsToVoxelCoords(glm::vec3 localCoords) { return glm::vec3(0.0f); }
// coords are in world-space // coords are in world-space
virtual bool setSphere(glm::vec3 center, float radius, uint8_t toValue) { return false; } virtual bool setSphere(glm::vec3 center, float radius, uint8_t toValue) { return false; }