mirror of
https://github.com/overte-org/overte.git
synced 2025-08-03 22:43:15 +02:00
hook up a way to get mesh out of polyvox
This commit is contained in:
parent
d6b2216448
commit
d158f6afd1
8 changed files with 60 additions and 30 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -242,3 +242,7 @@ const QByteArray PolyVoxEntityItem::getVoxelData() const {
|
|||
});
|
||||
return voxelDataCopy;
|
||||
}
|
||||
|
||||
bool PolyVoxEntityItem::getMeshAsScriptValue(QScriptEngine *engine, QScriptValue& result) const {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@ public:
|
|||
|
||||
MeshPointer getMeshPointer() const { return _mesh; }
|
||||
|
||||
Q_INVOKABLE int getNumVertices() const { return _mesh->getNumVertices(); }
|
||||
|
||||
protected:
|
||||
MeshPointer _mesh;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue