mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 13:43:49 +02:00
basic collisions with cubic polyvoxes
This commit is contained in:
parent
a96520ca74
commit
96a40bd673
8 changed files with 201 additions and 25 deletions
|
@ -15,9 +15,9 @@ function mousePressEvent(event) {
|
|||
for (var i = 0; i < ids.length; i++) {
|
||||
var id = ids[i];
|
||||
if (controlHeld) {
|
||||
Entities.setVoxelSphere(id, intersection.intersection, 1.2, 0);
|
||||
Entities.setVoxelSphere(id, intersection.intersection, 0.5, 0);
|
||||
} else {
|
||||
Entities.setVoxelSphere(id, intersection.intersection, 1.2, 255);
|
||||
Entities.setVoxelSphere(id, intersection.intersection, 0.5, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,12 +38,22 @@ EntityItemPointer RenderablePolyVoxEntityItem::factory(const EntityItemID& entit
|
|||
return EntityItemPointer(new RenderablePolyVoxEntityItem(entityID, properties));
|
||||
}
|
||||
|
||||
RenderablePolyVoxEntityItem::RenderablePolyVoxEntityItem(const EntityItemID& entityItemID,
|
||||
const EntityItemProperties& properties) :
|
||||
PolyVoxEntityItem(entityItemID, properties) {
|
||||
setVoxelVolumeSize(_voxelVolumeSize);
|
||||
|
||||
model::Mesh* mesh = new model::Mesh();
|
||||
model::MeshPointer meshPtr(mesh);
|
||||
_modelGeometry.setMesh(meshPtr);
|
||||
}
|
||||
|
||||
|
||||
RenderablePolyVoxEntityItem::~RenderablePolyVoxEntityItem() {
|
||||
delete _volData;
|
||||
}
|
||||
|
||||
void RenderablePolyVoxEntityItem::setVoxelVolumeSize(glm::vec3 voxelVolumeSize) {
|
||||
|
||||
if (_volData && voxelVolumeSize == _voxelVolumeSize) {
|
||||
return;
|
||||
}
|
||||
|
@ -83,12 +93,32 @@ glm::mat4 RenderablePolyVoxEntityItem::voxelToWorldMatrix() const {
|
|||
return translation * rotation * centerToCorner;
|
||||
}
|
||||
|
||||
|
||||
glm::mat4 RenderablePolyVoxEntityItem::voxelToLocalMatrix() const {
|
||||
glm::vec3 scale = _dimensions / _voxelVolumeSize; // meters / voxel-units
|
||||
glm::mat4 scaled = glm::scale(glm::mat4(), scale);
|
||||
glm::mat4 centerToCorner = glm::translate(scaled, _voxelVolumeSize / -2.0f);
|
||||
return centerToCorner;
|
||||
}
|
||||
|
||||
glm::mat4 RenderablePolyVoxEntityItem::worldToVoxelMatrix() const {
|
||||
glm::mat4 worldToModelMatrix = glm::inverse(voxelToWorldMatrix());
|
||||
return worldToModelMatrix;
|
||||
|
||||
}
|
||||
|
||||
void RenderablePolyVoxEntityItem::setAll(uint8_t toValue) {
|
||||
// XXX a volume that is all "on" has no mesh. make a different call for this nearly-all code:
|
||||
for (int z = 1; z < _volData->getDepth() - 1; z++) {
|
||||
for (int y = 1; y < _volData->getHeight() - 1; y++) {
|
||||
for (int x = 1; x < _volData->getWidth() - 1; x++) {
|
||||
_volData->setVoxelAt(x, y, z, toValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
compressVolumeData();
|
||||
}
|
||||
|
||||
void RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) {
|
||||
// This three-level for loop iterates over every voxel in the volume
|
||||
for (int z = 0; z < _volData->getDepth(); z++) {
|
||||
|
@ -106,7 +136,6 @@ void RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radi
|
|||
}
|
||||
}
|
||||
compressVolumeData();
|
||||
_needsModelReload = true;
|
||||
}
|
||||
|
||||
void RenderablePolyVoxEntityItem::setSphere(glm::vec3 centerWorldCoords, float radiusWorldCoords, uint8_t toValue) {
|
||||
|
@ -119,11 +148,6 @@ void RenderablePolyVoxEntityItem::setSphere(glm::vec3 centerWorldCoords, float r
|
|||
}
|
||||
|
||||
void RenderablePolyVoxEntityItem::getModel() {
|
||||
if (!_volData) {
|
||||
// this will cause the allocation of _volData
|
||||
setVoxelVolumeSize(_voxelVolumeSize);
|
||||
}
|
||||
|
||||
// A mesh object to hold the result of surface extraction
|
||||
PolyVox::SurfaceMesh<PolyVox::PositionMaterialNormal> polyVoxMesh;
|
||||
|
||||
|
@ -143,24 +167,25 @@ void RenderablePolyVoxEntityItem::getModel() {
|
|||
}
|
||||
|
||||
// convert PolyVox mesh to a Sam mesh
|
||||
model::Mesh* mesh = new model::Mesh();
|
||||
model::MeshPointer meshPtr(mesh);
|
||||
auto mesh = _modelGeometry.getMesh();
|
||||
|
||||
const std::vector<uint32_t>& vecIndices = polyVoxMesh.getIndices();
|
||||
auto indexBuffer = new gpu::Buffer(vecIndices.size() * sizeof(uint32_t), (gpu::Byte*)vecIndices.data());
|
||||
auto indexBufferPtr = gpu::BufferPointer(indexBuffer);
|
||||
mesh->setIndexBuffer(gpu::BufferView(indexBufferPtr, gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::RAW)));
|
||||
auto indexBufferView = new gpu::BufferView(indexBufferPtr, gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::RAW));
|
||||
mesh->setIndexBuffer(*indexBufferView);
|
||||
|
||||
|
||||
const std::vector<PolyVox::PositionMaterialNormal>& vecVertices = polyVoxMesh.getVertices();
|
||||
auto vertexBuffer = new gpu::Buffer(vecVertices.size() * sizeof(PolyVox::PositionMaterialNormal),
|
||||
(gpu::Byte*)vecVertices.data());
|
||||
auto vertexBufferPtr = gpu::BufferPointer(vertexBuffer);
|
||||
mesh->setVertexBuffer(gpu::BufferView(vertexBufferPtr,
|
||||
0,
|
||||
vertexBufferPtr->getSize() - sizeof(float) * 3,
|
||||
sizeof(PolyVox::PositionMaterialNormal),
|
||||
gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW)));
|
||||
auto vertexBufferView = new gpu::BufferView(vertexBufferPtr,
|
||||
0,
|
||||
vertexBufferPtr->getSize() - sizeof(float) * 3,
|
||||
sizeof(PolyVox::PositionMaterialNormal),
|
||||
gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW));
|
||||
mesh->setVertexBuffer(*vertexBufferView);
|
||||
mesh->addAttribute(gpu::Stream::NORMAL,
|
||||
gpu::BufferView(vertexBufferPtr,
|
||||
sizeof(float) * 3,
|
||||
|
@ -176,7 +201,6 @@ void RenderablePolyVoxEntityItem::getModel() {
|
|||
qDebug() << "---- vecIndices.size() =" << vecIndices.size();
|
||||
qDebug() << "---- vecVertices.size() =" << vecVertices.size();
|
||||
|
||||
_modelGeometry.setMesh(meshPtr);
|
||||
_needsModelReload = false;
|
||||
}
|
||||
|
||||
|
@ -310,6 +334,9 @@ void RenderablePolyVoxEntityItem::compressVolumeData() {
|
|||
// revert
|
||||
decompressVolumeData();
|
||||
}
|
||||
|
||||
_dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS;
|
||||
_needsModelReload = true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -329,8 +356,104 @@ void RenderablePolyVoxEntityItem::decompressVolumeData() {
|
|||
}
|
||||
}
|
||||
|
||||
_needsModelReload = true;
|
||||
|
||||
qDebug() << "--------------- voxel decompress ---------------";
|
||||
qDebug() << "raw-size =" << rawSize << " compressed-size =" << _voxelData.size();
|
||||
|
||||
_dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS;
|
||||
_needsModelReload = true;
|
||||
getModel();
|
||||
}
|
||||
|
||||
bool RenderablePolyVoxEntityItem::isReadyToComputeShape() {
|
||||
qDebug() << "RenderablePolyVoxEntityItem::isReadyToComputeShape" << (!_needsModelReload);
|
||||
|
||||
if (_needsModelReload) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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 (_volData->getVoxelAt(x, y, z) > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) {
|
||||
qDebug() << "RenderablePolyVoxEntityItem::computeShapeInfo";
|
||||
ShapeType type = getShapeType();
|
||||
if (type != SHAPE_TYPE_COMPOUND) {
|
||||
qDebug() << "RenderablePolyVoxEntityItem::computeShapeInfo NOT COMPOUND";
|
||||
PolyVoxEntityItem::computeShapeInfo(info);
|
||||
info.setParams(type, 0.5f * getDimensions());
|
||||
} else {
|
||||
_points.clear();
|
||||
unsigned int i = 0;
|
||||
|
||||
glm::mat4 wToM = voxelToLocalMatrix();
|
||||
|
||||
AABox box;
|
||||
|
||||
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 (_volData->getVoxelAt(x, y, z) > 0) {
|
||||
QVector<glm::vec3> pointsInPart;
|
||||
|
||||
float offL = -0.5f;
|
||||
float offH = 0.5f;
|
||||
|
||||
// XXX I don't really understand why this make it line up.
|
||||
// float offL = -1.0f;
|
||||
// float offH = 0.0f;
|
||||
|
||||
|
||||
glm::vec3 p000 = glm::vec3(wToM * glm::vec4(x + offL, y + offL, z + offL, 1.0f));
|
||||
glm::vec3 p001 = glm::vec3(wToM * glm::vec4(x + offL, y + offL, z + offH, 1.0f));
|
||||
glm::vec3 p010 = glm::vec3(wToM * glm::vec4(x + offL, y + offH, z + offL, 1.0f));
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
glm::vec3 collisionModelDimensions = box.getDimensions();
|
||||
QByteArray b64 = _voxelData.toBase64();
|
||||
info.setParams(type, collisionModelDimensions, QString(b64));
|
||||
info.setConvexHulls(_points);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,7 @@ class RenderablePolyVoxEntityItem : public PolyVoxEntityItem {
|
|||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
RenderablePolyVoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
PolyVoxEntityItem(entityItemID, properties) { }
|
||||
RenderablePolyVoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||
|
||||
virtual ~RenderablePolyVoxEntityItem();
|
||||
|
||||
|
@ -47,14 +46,22 @@ public:
|
|||
|
||||
virtual void setVoxelVolumeSize(glm::vec3 voxelVolumeSize);
|
||||
glm::mat4 voxelToWorldMatrix() const;
|
||||
glm::mat4 voxelToLocalMatrix() const;
|
||||
glm::mat4 worldToVoxelMatrix() const;
|
||||
|
||||
|
||||
virtual bool isReadyToComputeShape();
|
||||
virtual void computeShapeInfo(ShapeInfo& info);
|
||||
|
||||
|
||||
// coords are in voxel-volume space
|
||||
virtual void setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue);
|
||||
|
||||
// coords are in world-space
|
||||
virtual void setSphere(glm::vec3 center, float radius, uint8_t toValue);
|
||||
|
||||
virtual void setAll(uint8_t toValue);
|
||||
|
||||
private:
|
||||
void compressVolumeData();
|
||||
void decompressVolumeData();
|
||||
|
@ -62,6 +69,8 @@ private:
|
|||
PolyVox::SimpleVolume<uint8_t>* _volData = nullptr;
|
||||
model::Geometry _modelGeometry;
|
||||
bool _needsModelReload = true;
|
||||
|
||||
QVector<QVector<glm::vec3>> _points; // XXX
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -420,3 +420,40 @@ bool EntityScriptingInterface::setVoxelSphere(QUuid entityID, const glm::vec3& c
|
|||
queueEntityMessage(PacketTypeEntityEdit, entityID, properties);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool EntityScriptingInterface::setAllVoxels(QUuid entityID, int value) {
|
||||
if (!_entityTree) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EntityItemPointer entity = static_cast<EntityItemPointer>(_entityTree->findEntityByEntityItemID(entityID));
|
||||
if (!entity) {
|
||||
qCDebug(entities) << "EntityScriptingInterface::setVoxelSphere no entity with ID" << entityID;
|
||||
return false;
|
||||
}
|
||||
|
||||
EntityTypes::EntityType entityType = entity->getType();
|
||||
if (entityType != EntityTypes::PolyVox) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto now = usecTimestampNow();
|
||||
|
||||
PolyVoxEntityItem* polyVoxEntity = static_cast<PolyVoxEntityItem*>(entity.get());
|
||||
_entityTree->lockForWrite();
|
||||
polyVoxEntity->setAll(value);
|
||||
entity->setLastEdited(now);
|
||||
entity->setLastBroadcast(now);
|
||||
_entityTree->unlock();
|
||||
|
||||
_entityTree->lockForRead();
|
||||
EntityItemProperties properties = entity->getProperties();
|
||||
_entityTree->unlock();
|
||||
|
||||
properties.setVoxelDataDirty();
|
||||
properties.setLastEdited(now);
|
||||
|
||||
queueEntityMessage(PacketTypeEntityEdit, entityID, properties);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -118,6 +118,7 @@ public slots:
|
|||
Q_INVOKABLE bool getSendPhysicsUpdates() const;
|
||||
|
||||
Q_INVOKABLE bool setVoxelSphere(QUuid entityID, const glm::vec3& center, float radius, int value);
|
||||
Q_INVOKABLE bool setAllVoxels(QUuid entityID, int value);
|
||||
|
||||
Q_INVOKABLE void dumpTree() const;
|
||||
|
||||
|
|
|
@ -115,3 +115,8 @@ void PolyVoxEntityItem::debugDump() const {
|
|||
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||
}
|
||||
|
||||
|
||||
// virtual
|
||||
ShapeType PolyVoxEntityItem::getShapeType() const {
|
||||
return SHAPE_TYPE_COMPOUND;
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ class PolyVoxEntityItem : public EntityItem {
|
|||
_color[BLUE_INDEX] = value.blue;
|
||||
}
|
||||
|
||||
virtual ShapeType getShapeType() const { return SHAPE_TYPE_POLYVOX; }
|
||||
virtual ShapeType getShapeType() const;
|
||||
|
||||
// never have a ray intersection pick a PolyVoxEntityItem.
|
||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||
|
@ -88,6 +88,8 @@ class PolyVoxEntityItem : public EntityItem {
|
|||
// coords are in world-space
|
||||
virtual void setSphere(glm::vec3 center, float radius, uint8_t toValue) {}
|
||||
|
||||
virtual void setAll(uint8_t toValue) {}
|
||||
|
||||
protected:
|
||||
rgbColor _color;
|
||||
glm::vec3 _voxelVolumeSize; // this is always 3 bytes
|
||||
|
|
|
@ -35,8 +35,7 @@ enum ShapeType {
|
|||
SHAPE_TYPE_CYLINDER_X,
|
||||
SHAPE_TYPE_CYLINDER_Y,
|
||||
SHAPE_TYPE_CYLINDER_Z,
|
||||
SHAPE_TYPE_LINE,
|
||||
SHAPE_TYPE_POLYVOX
|
||||
SHAPE_TYPE_LINE
|
||||
};
|
||||
|
||||
class ShapeInfo {
|
||||
|
|
Loading…
Reference in a new issue