diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index e6f0a32e75..967c8950ad 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -10,6 +10,7 @@ // #include +#include #include @@ -21,6 +22,8 @@ #include #include #include +#include +#include #include "model/Geometry.h" #include "gpu/GLBackend.h" @@ -50,22 +53,19 @@ void RenderablePolyVoxEntityItem::setVoxelVolumeSize(glm::vec3 voxelVolumeSize) _volData = new PolyVox::SimpleVolume(PolyVox::Region(lowCorner, highCorner)); } -glm::vec3 RenderablePolyVoxEntityItem::metersToVoxelCoordinates(glm::vec3 metersOffCenter) { - // convert a vector from the center of the entity with units of meters to a vector with units - // of index-into-volData. - glm::vec3 dimensions = getDimensions(); - glm::vec3 scale = dimensions / _voxelVolumeSize; // meters / voxel-units - glm::vec3 voxelCoords = metersOffCenter / scale; - // the voxel volume is entirely in positive space, but the voxel space is centered at the entity's coords, so: - return voxelCoords + _voxelVolumeSize / 2.0f; +glm::mat4 RenderablePolyVoxEntityItem::voxelToWorldMatrix() 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); + glm::mat4 rotation = glm::mat4_cast(_rotation); + glm::mat4 translation = glm::translate(getCenter()); + return translation * rotation * centerToCorner; } -glm::vec3 RenderablePolyVoxEntityItem::voxelCoordinatesToMeters(glm::vec3 voxelCoords) { - // convert a vector is voxel-space to an offset from the entity-center in meters - glm::vec3 dimensions = getDimensions(); - glm::vec3 scale = dimensions / _voxelVolumeSize; // meters / voxel-units - glm::vec3 centeredCoords = voxelCoords - _voxelVolumeSize / 2.0f; - return centeredCoords * scale; +glm::mat4 RenderablePolyVoxEntityItem::worldToVoxelMatrix() const { + glm::mat4 worldToModelMatrix = glm::inverse(voxelToWorldMatrix()); + return worldToModelMatrix; + } void RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) { @@ -91,13 +91,29 @@ void RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radi } } -void RenderablePolyVoxEntityItem::createSphereInVolume(glm::vec3 center, float radius) { - setSphereInVolume(center, radius, 255); +void RenderablePolyVoxEntityItem::createSphereInVolume(glm::vec3 centerVoxelCoords, float radiusVoxelCoords) { + setSphereInVolume(centerVoxelCoords, radiusVoxelCoords, 255); } +void RenderablePolyVoxEntityItem::eraseSphereInVolume(glm::vec3 centerVoxelCoords, float radiusVoxelCoords) { + setSphereInVolume(centerVoxelCoords, radiusVoxelCoords, 0); +} -void RenderablePolyVoxEntityItem::eraseSphereInVolume(glm::vec3 center, float radius) { - setSphereInVolume(center, radius, 0); +void RenderablePolyVoxEntityItem::setSphere(glm::vec3 centerWorldCoords, float radiusWorldCoords, uint8_t toValue) { + // glm::vec3 centerVoxelCoords = worldToVoxelCoordinates(centerWorldCoords); + glm::vec4 centerVoxelCoords = worldToVoxelMatrix() * glm::vec4(centerWorldCoords, 1.0f); + glm::vec3 scale = _dimensions / _voxelVolumeSize; // meters / voxel-units + float scaleY = scale[0]; + float radiusVoxelCoords = radiusWorldCoords / scaleY; + setSphereInVolume(glm::vec3(centerVoxelCoords), radiusVoxelCoords, toValue); +} + +void RenderablePolyVoxEntityItem::createSphere(glm::vec3 centerWorldCoords, float radiusWorldCoords) { + setSphere(centerWorldCoords, radiusWorldCoords, 255); +} + +void RenderablePolyVoxEntityItem::eraseSphere(glm::vec3 centerWorldCoords, float radiusWorldCoords) { + setSphere(centerWorldCoords, radiusWorldCoords, 0); } void RenderablePolyVoxEntityItem::getModel() { @@ -106,12 +122,19 @@ void RenderablePolyVoxEntityItem::getModel() { setVoxelVolumeSize(_voxelVolumeSize); } - glm::vec3 center(_volData->getDepth() / 2.0f, - _volData->getHeight() / 2.0f, - _volData->getWidth() / 2.0f); - createSphereInVolume(center, 15); - createSphereInVolume(center + glm::vec3(8.0f, 0.0f, 0.0f), 15); - eraseSphereInVolume(center + glm::vec3(4.0f, 0.0f, 4.0f), 15); + // glm::vec3 center(_volData->getDepth() / 2.0f, + // _volData->getHeight() / 2.0f, + // _volData->getWidth() / 2.0f); + // createSphereInVolume(center, 15); + // createSphereInVolume(center + glm::vec3(8.0f, 0.0f, 0.0f), 15); + // eraseSphereInVolume(center + glm::vec3(4.0f, 0.0f, 4.0f), 15); + + + glm::vec3 center = getCenter(); + createSphere(center, 4); + createSphere(center + glm::vec3(6.0f, 0.0f, 0.0f), 2); + // eraseSphere(center + glm::vec3(0.5f, 0.0f, 4.0f), 0.8); + // A mesh object to hold the result of surface extraction PolyVox::SurfaceMesh polyVoxMesh; @@ -153,7 +176,7 @@ void RenderablePolyVoxEntityItem::getModel() { gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW))); - qDebug() << "-------------XXXXXXXXXXXXXXXXXXXX-------------------"; + qDebug() << "-------------XXXXXXXXXXXXXXXXXXXX-------------------" << usecTimestampNow(); qDebug() << "---- vecIndices.size() =" << vecIndices.size(); qDebug() << "---- sizeof(vecIndices[0]) =" << sizeof(vecIndices[0]); qDebug() << "---- vecVertices.size() =" << vecVertices.size(); @@ -175,8 +198,6 @@ void RenderablePolyVoxEntityItem::getModel() { _needsModelReload = false; } - - void RenderablePolyVoxEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderablePolyVoxEntityItem::render"); assert(getType() == EntityTypes::PolyVox); @@ -214,3 +235,60 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { glPopMatrix(); RenderableDebugableEntityItem::render(this, args); } + +class RaycastFunctor +{ +public: + RaycastFunctor() : _result(glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)) { } + bool operator()(PolyVox::SimpleVolume::Sampler& sampler) + { + if (sampler.getVoxel() == 0) { + return true; // keep raycasting + } + PolyVox::Vector3DInt32 positionIndex = sampler.getPosition(); + _result = glm::vec4(positionIndex.getX(), positionIndex.getY(), positionIndex.getZ(), 1.0f); + return false; + } + glm::vec4 _result; +}; + +bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& origin, + const glm::vec3& direction, + bool& keepSearching, + OctreeElement*& element, + float& distance, BoxFace& face, + void** intersectedObject, + bool precisionPicking) const +{ + if (_needsModelReload || !precisionPicking) { + // just intersect with bounding box + return true; + } + + glm::mat4 wtvMatrix = worldToVoxelMatrix(); + glm::vec3 far = origin + direction; + glm::vec4 originInVoxel = wtvMatrix * glm::vec4(origin, 1.0f); + glm::vec4 farInVoxel = wtvMatrix * glm::vec4(far, 1.0f); + glm::vec4 directionInVoxel = farInVoxel - originInVoxel; + + PolyVox::Vector3DFloat start(originInVoxel[0], originInVoxel[1], originInVoxel[2]); + PolyVox::Vector3DFloat pvDirection(directionInVoxel[0], directionInVoxel[1], directionInVoxel[2]); + pvDirection.normalise(); + // pvDirection *= 1000.0f; // Casts ray of length 1000 + pvDirection *= 64.0f; // Casts ray of length 1000 + + PolyVox::RaycastResult raycastResult; + RaycastFunctor callback; + raycastResult = PolyVox::raycastWithDirection(_volData, start, pvDirection, callback); + + if (raycastResult == PolyVox::RaycastResults::Completed) // the ray completed its path -- nothing was hit. + return false; + + glm::vec4 intersectedWorldPosition = voxelToWorldMatrix() * callback._result; + + distance = glm::distance(glm::vec3(intersectedWorldPosition), origin); + + face = BoxFace::MIN_X_FACE; // XXX + + return true; +} diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 0c0cf82dad..4d414b4b7b 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -26,14 +26,30 @@ public: virtual ~RenderablePolyVoxEntityItem(); + virtual void somethingChangedNotification() { + // This gets called from EnityItem::readEntityDataFromBuffer every time a packet describing + // this entity comes from the entity-server. It gets called even if nothing has actually changed + // (see the comment in EntityItem.cpp). If that gets fixed, this could be used to know if we + // need to redo the voxel data. + // _needsModelReload = true; + } + + void render(RenderArgs* args); - virtual bool hasModel() const { return true; } + virtual bool supportsDetailedRayIntersection() const { return true; } + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject, bool precisionPicking) const; + void getModel(); virtual void setVoxelVolumeSize(glm::vec3 voxelVolumeSize); + glm::mat4 voxelToWorldMatrix() const; + glm::mat4 worldToVoxelMatrix() const; - glm::vec3 metersToVoxelCoordinates(glm::vec3 metersOffCenter); - glm::vec3 voxelCoordinatesToMeters(glm::vec3 voxelCoords); + void setSphere(glm::vec3 center, float radius, uint8_t toValue); + void createSphere(glm::vec3 centerWorldCoords, float radiusWorldCoords); + void eraseSphere(glm::vec3 centerWorldCoords, float radiusWorldCoords); void setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue); void createSphereInVolume(glm::vec3 center, float radius); diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 1c68947eef..ee728160f6 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -613,7 +613,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef // we want to extrapolate the motion forward to compensate for packet travel time, but // we don't want the side effect of flag setting. - // simulateKinematicMotion(skipTimeForward, false); + simulateKinematicMotion(skipTimeForward, false); } _lastSimulated = now; }