hook up a way to get mesh out of polyvox

This commit is contained in:
Seth Alves 2017-01-28 20:42:14 -08:00
parent d6b2216448
commit d158f6afd1
8 changed files with 60 additions and 30 deletions

View file

@ -14,6 +14,7 @@
#include <QByteArray>
#include <QtConcurrent/QtConcurrentRun>
#include <glm/gtx/transform.hpp>
#include "ModelScriptingInterface.h"
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
@ -73,7 +74,7 @@ const float MARCHING_CUBE_COLLISION_HULL_OFFSET = 0.5;
_meshDirty
In RenderablePolyVoxEntityItem::render, these flags are checked and changes are propagated along the chain.
decompressVolumeData() is called to decompress _voxelData into _volData. getMesh() is called to invoke the
decompressVolumeData() is called to decompress _voxelData into _volData. recomputeMesh() is called to invoke the
polyVox surface extractor to create _mesh (as well as set Simulation _dirtyFlags). Because Simulation::DIRTY_SHAPE
is set, isReadyToComputeShape() gets called and _shape is created either from _volData or _shape, depending on
the surface style.
@ -81,7 +82,7 @@ const float MARCHING_CUBE_COLLISION_HULL_OFFSET = 0.5;
When a script changes _volData, compressVolumeDataAndSendEditPacket is called to update _voxelData and to
send a packet to the entity-server.
decompressVolumeData, getMesh, computeShapeInfoWorker, and compressVolumeDataAndSendEditPacket are too expensive
decompressVolumeData, recomputeMesh, computeShapeInfoWorker, and compressVolumeDataAndSendEditPacket are too expensive
to run on a thread that has other things to do. These use QtConcurrent::run to spawn a thread. As each thread
finishes, it adjusts the dirty flags so that the next call to render() will kick off the next step.
@ -570,7 +571,7 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
if (voxelDataDirty) {
decompressVolumeData();
} else if (volDataDirty) {
getMesh();
recomputeMesh();
}
model::MeshPointer mesh;
@ -1096,7 +1097,7 @@ void RenderablePolyVoxEntityItem::copyUpperEdgesFromNeighbors() {
}
}
void RenderablePolyVoxEntityItem::getMesh() {
void RenderablePolyVoxEntityItem::recomputeMesh() {
// use _volData to make a renderable mesh
PolyVoxSurfaceStyle voxelSurfaceStyle;
withReadLock([&] {
@ -1171,7 +1172,7 @@ void RenderablePolyVoxEntityItem::getMesh() {
}
void RenderablePolyVoxEntityItem::setMesh(model::MeshPointer mesh) {
// this catches the payload from getMesh
// this catches the payload from recomputeMesh
bool neighborsNeedUpdate;
withWriteLock([&] {
_dirtyFlags |= Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS;
@ -1426,7 +1427,6 @@ std::shared_ptr<RenderablePolyVoxEntityItem> RenderablePolyVoxEntityItem::getZPN
return std::dynamic_pointer_cast<RenderablePolyVoxEntityItem>(_zPNeighbor.lock());
}
void RenderablePolyVoxEntityItem::bonkNeighbors() {
// flag neighbors to the negative of this entity as needing to rebake their meshes.
cacheNeighbors();
@ -1446,7 +1446,6 @@ void RenderablePolyVoxEntityItem::bonkNeighbors() {
}
}
void RenderablePolyVoxEntityItem::locationChanged(bool tellPhysics) {
EntityItem::locationChanged(tellPhysics);
if (!_pipeline || !render::Item::isValidID(_myItem)) {
@ -1458,3 +1457,17 @@ void RenderablePolyVoxEntityItem::locationChanged(bool tellPhysics) {
scene->enqueuePendingChanges(pendingChanges);
}
bool RenderablePolyVoxEntityItem::getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) const {
bool success = false;
MeshProxy* meshProxy = nullptr;
model::MeshPointer mesh = nullptr;
withReadLock([&] {
if (_meshInitialized) {
success = true;
meshProxy = new MeshProxy(_mesh);
}
});
result = meshToScriptValue(engine, meshProxy);
return success;
}

View file

@ -130,6 +130,7 @@ public:
std::function<void(int, int, int, uint8_t)> thunk);
void setMesh(model::MeshPointer mesh);
bool getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) const override;
void setCollisionPoints(ShapeInfo::PointCollection points, AABox box);
PolyVox::SimpleVolume<uint8_t>* getVolData() { return _volData; }
@ -164,7 +165,7 @@ private:
ShapeInfo _shapeInfo;
PolyVox::SimpleVolume<uint8_t>* _volData = nullptr;
bool _volDataDirty = false; // does getMesh need to be called?
bool _volDataDirty = false; // does recomputeMesh need to be called?
int _onCount; // how many non-zero voxels are in _volData
bool _neighborsNeedUpdate { false };
@ -175,7 +176,7 @@ private:
// these are run off the main thread
void decompressVolumeData();
void compressVolumeDataAndSendEditPacket();
virtual void getMesh() override; // recompute mesh
virtual void recomputeMesh() override; // recompute mesh
void computeShapeInfoWorker();
// these are cached lookups of _xNNeighborID, _yNNeighborID, _zNNeighborID, _xPNeighborID, _yPNeighborID, _zPNeighborID

View file

@ -822,8 +822,7 @@ void RayToEntityIntersectionResultFromScriptValue(const QScriptValue& object, Ra
}
}
bool EntityScriptingInterface::setVoxels(QUuid entityID,
std::function<bool(PolyVoxEntityItem&)> actor) {
bool EntityScriptingInterface::polyVoxWorker(QUuid entityID, std::function<bool(PolyVoxEntityItem&)> actor) {
if (!_entityTree) {
return false;
}
@ -887,32 +886,38 @@ bool EntityScriptingInterface::setPoints(QUuid entityID, std::function<bool(Line
bool EntityScriptingInterface::setVoxelSphere(QUuid entityID, const glm::vec3& center, float radius, int value) {
return setVoxels(entityID, [center, radius, value](PolyVoxEntityItem& polyVoxEntity) {
return polyVoxEntity.setSphere(center, radius, value);
});
return polyVoxWorker(entityID, [center, radius, value](PolyVoxEntityItem& polyVoxEntity) {
return polyVoxEntity.setSphere(center, radius, value);
});
}
bool EntityScriptingInterface::setVoxel(QUuid entityID, const glm::vec3& position, int value) {
return setVoxels(entityID, [position, value](PolyVoxEntityItem& polyVoxEntity) {
return polyVoxEntity.setVoxelInVolume(position, value);
});
return polyVoxWorker(entityID, [position, value](PolyVoxEntityItem& polyVoxEntity) {
return polyVoxEntity.setVoxelInVolume(position, value);
});
}
bool EntityScriptingInterface::setAllVoxels(QUuid entityID, int value) {
return setVoxels(entityID, [value](PolyVoxEntityItem& polyVoxEntity) {
return polyVoxEntity.setAll(value);
});
return polyVoxWorker(entityID, [value](PolyVoxEntityItem& polyVoxEntity) {
return polyVoxEntity.setAll(value);
});
}
bool EntityScriptingInterface::setVoxelsInCuboid(QUuid entityID, const glm::vec3& lowPosition,
const glm::vec3& cuboidSize, int value) {
return setVoxels(entityID, [lowPosition, cuboidSize, value](PolyVoxEntityItem& polyVoxEntity) {
return polyVoxEntity.setCuboid(lowPosition, cuboidSize, value);
});
return polyVoxWorker(entityID, [lowPosition, cuboidSize, value](PolyVoxEntityItem& polyVoxEntity) {
return polyVoxEntity.setCuboid(lowPosition, cuboidSize, value);
});
}
MeshProxy* EntityScriptingInterface::voxelsToMesh(QUuid entityID) {
return nullptr;
void EntityScriptingInterface::voxelsToMesh(QUuid entityID, QScriptValue callback) {
polyVoxWorker(entityID, [callback](PolyVoxEntityItem& polyVoxEntity) mutable {
QScriptValue mesh;
polyVoxEntity.getMeshAsScriptValue(callback.engine(), mesh);
QScriptValueList args { mesh };
callback.call(QScriptValue(), args);
return true;
});
}
bool EntityScriptingInterface::setAllPoints(QUuid entityID, const QVector<glm::vec3>& points) {

View file

@ -228,7 +228,7 @@ public slots:
Q_INVOKABLE bool setAllVoxels(QUuid entityID, int value);
Q_INVOKABLE bool setVoxelsInCuboid(QUuid entityID, const glm::vec3& lowPosition,
const glm::vec3& cuboidSize, int value);
Q_INVOKABLE MeshProxy* voxelsToMesh(QUuid entityID);
Q_INVOKABLE void voxelsToMesh(QUuid entityID, QScriptValue callback);
Q_INVOKABLE bool setAllPoints(QUuid entityID, const QVector<glm::vec3>& points);
Q_INVOKABLE bool appendPoint(QUuid entityID, const glm::vec3& point);
@ -321,7 +321,7 @@ signals:
private:
bool actionWorker(const QUuid& entityID, std::function<bool(EntitySimulationPointer, EntityItemPointer)> actor);
bool setVoxels(QUuid entityID, std::function<bool(PolyVoxEntityItem&)> actor);
bool polyVoxWorker(QUuid entityID, std::function<bool(PolyVoxEntityItem&)> actor);
bool setPoints(QUuid entityID, std::function<bool(LineEntityItem&)> actor);
void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties);

View file

@ -242,3 +242,7 @@ const QByteArray PolyVoxEntityItem::getVoxelData() const {
});
return voxelDataCopy;
}
bool PolyVoxEntityItem::getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) const {
return false;
}

View file

@ -129,7 +129,9 @@ class PolyVoxEntityItem : public EntityItem {
virtual void rebakeMesh() {};
void setVoxelDataDirty(bool value) { withWriteLock([&] { _voxelDataDirty = value; }); }
virtual void getMesh() {}; // recompute mesh
virtual void recomputeMesh() {};
virtual bool getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) const;
protected:
glm::vec3 _voxelVolumeSize; // this is always 3 bytes

View file

@ -9,6 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QScriptEngine>
#include <QtScript/QScriptValue>
#include "ModelScriptingInterface.h"
ModelScriptingInterface::ModelScriptingInterface(QObject* parent) : QObject(parent) {
@ -23,9 +25,10 @@ MeshProxy::~MeshProxy() {
QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in) {
QScriptValue obj("something");
return obj;
return engine->newQObject(in, QScriptEngine::QtOwnership,
QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects);
}
void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out) {
out = qobject_cast<MeshProxy*>(value.toQObject());
}

View file

@ -37,6 +37,8 @@ public:
MeshPointer getMeshPointer() const { return _mesh; }
Q_INVOKABLE int getNumVertices() const { return _mesh->getNumVertices(); }
protected:
MeshPointer _mesh;
};