Showing the changes to interface/src/MetavoxelSystem.cpp (1 of 4 files). Show all
Unified · Split
| @@ -328,6 +328,50 @@ bool MetavoxelSystem::findFirstRayHeightfieldIntersection(const glm::vec3& origi · 327 unmodified lines | ||
| 328 | 328 | return true; |
| 329 | 329 | } |
| 330 | 330 | |
| 331 | +class RayVoxelIntersectionVisitor : public RayIntersectionVisitor { | |
| 332 | +public: | |
| 333 | + | |
| 334 | + float intersectionDistance; | |
| 335 | + | |
| 336 | + RayVoxelIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction, const MetavoxelLOD& lod); | |
| 337 | + | |
| 338 | + virtual int visit(MetavoxelInfo& info, float distance); | |
| 339 | +}; | |
| 340 | + | |
| 341 | +RayVoxelIntersectionVisitor::RayVoxelIntersectionVisitor(const glm::vec3& origin, | |
| 342 | + const glm::vec3& direction, const MetavoxelLOD& lod) : | |
| 343 | + RayIntersectionVisitor(origin, direction, QVector<AttributePointer>() << | |
| 344 | + Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute(), QVector<AttributePointer>(), lod), | |
| 345 | + intersectionDistance(FLT_MAX) { | |
| 346 | +} | |
| 347 | + | |
| 348 | +int RayVoxelIntersectionVisitor::visit(MetavoxelInfo& info, float distance) { | |
| 349 | + if (!info.isLeaf) { | |
| 350 | + return _order; | |
| 351 | + } | |
| 352 | + const VoxelBuffer* buffer = static_cast<VoxelBuffer*>( | |
| 353 | + info.inputValues.at(0).getInlineValue<BufferDataPointer>().data()); | |
| 354 | + if (!buffer) { | |
| 355 | + return STOP_RECURSION; | |
| 356 | + } | |
| 357 | + glm::vec3 origin = ((_origin + distance * _direction) - info.minimum) / info.size; | |
| 358 | + if (buffer->findFirstRayIntersection(origin, _direction, intersectionDistance)) { | |
| 359 | + intersectionDistance = intersectionDistance * info.size + distance; | |
| 360 | + return SHORT_CIRCUIT; | |
| 361 | + } | |
| 362 | + return STOP_RECURSION; | |
| 363 | +} | |
| 364 | + | |
| 365 | +bool MetavoxelSystem::findFirstRayVoxelIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) { | |
| 366 | + RayVoxelIntersectionVisitor visitor(origin, direction, getLOD()); | |
| 367 | + guideToAugmented(visitor); | |
| 368 | + if (visitor.intersectionDistance == FLT_MAX) { | |
| 369 | + return false; | |
| 370 | + } | |
| 371 | + distance = visitor.intersectionDistance; | |
| 372 | + return true; | |
| 373 | +} | |
| 374 | + | |
| 331 | 375 | class HeightfieldHeightVisitor : public MetavoxelVisitor { |
| 332 | 376 | public: |
| 333 | 377 | |
| @@ -991,10 +1035,12 @@ void VoxelPoint::setNormal(const glm::vec3& normal) { · 657 unmodified lines | ||
| 991 | 1035 | } |
| 992 | 1036 | |
| 993 | 1037 | VoxelBuffer::VoxelBuffer(const QVector<VoxelPoint>& vertices, const QVector<int>& indices, const QVector<glm::vec3>& hermite, |
| 994 | − const QVector<SharedObjectPointer>& materials) : | |
| 1038 | + const QHash<QRgb, glm::vec3>& points, int size, const QVector<SharedObjectPointer>& materials) : | |
| 995 | 1039 | _vertices(vertices), |
| 996 | 1040 | _indices(indices), |
| 997 | 1041 | _hermite(hermite), |
| 1042 | + _points(points), | |
| 1043 | + _size(size), | |
| 998 | 1044 | _vertexCount(vertices.size()), |
| 999 | 1045 | _indexCount(indices.size()), |
| 1000 | 1046 | _hermiteCount(hermite.size()), |
| @@ -1002,6 +1048,68 @@ VoxelBuffer::VoxelBuffer(const QVector<VoxelPoint>& vertices, const QVector<int> · 1 unmodified line | ||
| 1002 | 1048 | _materials(materials) { |
| 1003 | 1049 | } |
| 1004 | 1050 | |
| 1051 | +bool VoxelBuffer::findFirstRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { | |
| 1052 | + float highest = _size - 1.0f; | |
| 1053 | + glm::vec3 position = origin * highest; | |
| 1054 | + glm::vec3 floors = glm::floor(position); | |
| 1055 | + int max = _size - 2; | |
| 1056 | + int x = qMin((int)floors.x, max), y = qMin((int)floors.y, max), z = qMin((int)floors.z, max); | |
| 1057 | + float combinedDistance = 0.0f; | |
| 1058 | + forever { | |
| 1059 | + if (_points.contains(qRgb(x + 1, y + 1, z + 1))) { | |
| 1060 | + distance = combinedDistance / highest; | |
| 1061 | + return true; | |
| 1062 | + } | |
| 1063 | + float xDistance = FLT_MAX, yDistance = FLT_MAX, zDistance = FLT_MAX; | |
| 1064 | + if (direction.x > 0.0f) { | |
| 1065 | + xDistance = (x + 1.0f - position.x) / direction.x; | |
| 1066 | + } else if (direction.x < 0.0f) { | |
| 1067 | + xDistance = (x - position.x) / direction.x; | |
| 1068 | + } | |
| 1069 | + if (direction.y > 0.0f) { | |
| 1070 | + yDistance = (y + 1.0f - position.y) / direction.y; | |
| 1071 | + } else if (direction.y < 0.0f) { | |
| 1072 | + yDistance = (y - position.y) / direction.y; | |
| 1073 | + } | |
| 1074 | + if (direction.z > 0.0f) { | |
| 1075 | + zDistance = (z + 1.0f - position.z) / direction.z; | |
| 1076 | + } else if (direction.z < 0.0f) { | |
| 1077 | + zDistance = (z - position.z) / direction.z; | |
| 1078 | + } | |
| 1079 | + float minimumDistance = qMin(xDistance, qMin(yDistance, zDistance)); | |
| 1080 | + if (minimumDistance == xDistance) { | |
| 1081 | + if (direction.x > 0.0f) { | |
| 1082 | + if (x++ == max) { | |
| 1083 | + return false; | |
| 1084 | + } | |
| 1085 | + } else if (x-- == 0) { | |
| 1086 | + return false; | |
| 1087 | + } | |
| 1088 | + } | |
| 1089 | + if (minimumDistance == yDistance) { | |
| 1090 | + if (direction.y > 0.0f) { | |
| 1091 | + if (y++ == max) { | |
| 1092 | + return false; | |
| 1093 | + } | |
| 1094 | + } else if (y-- == 0) { | |
| 1095 | + return false; | |
| 1096 | + } | |
| 1097 | + } | |
| 1098 | + if (minimumDistance == zDistance) { | |
| 1099 | + if (direction.z > 0.0f) { | |
| 1100 | + if (z++ == max) { | |
| 1101 | + return false; | |
| 1102 | + } | |
| 1103 | + } else if (z-- == 0) { | |
| 1104 | + return false; | |
| 1105 | + } | |
| 1106 | + } | |
| 1107 | + position += direction * minimumDistance; | |
| 1108 | + combinedDistance += minimumDistance; | |
| 1109 | + } | |
| 1110 | + return false; | |
| 1111 | +} | |
| 1112 | + | |
| 1005 | 1113 | void VoxelBuffer::render(bool cursor) { |
| 1006 | 1114 | if (!_vertexBuffer.isCreated()) { |
| 1007 | 1115 | _vertexBuffer.create(); |
| @@ -1627,6 +1735,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 619 unmodified lines | ||
| 1627 | 1735 | QVector<VoxelPoint> vertices; |
| 1628 | 1736 | QVector<int> indices; |
| 1629 | 1737 | QVector<glm::vec3> hermiteSegments; |
| 1738 | + QHash<QRgb, glm::vec3> points; | |
| 1630 | 1739 | |
| 1631 | 1740 | // see http://www.frankpetterson.com/publications/dualcontour/dualcontour.pdf for a description of the |
| 1632 | 1741 | // dual contour algorithm for generating meshes from voxel data using Hermite-tagged edges |
| @@ -2033,6 +2142,8 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 400 unmodified lines | ||
| 2033 | 2142 | { (quint8)materialWeights[0], (quint8)materialWeights[1], (quint8)materialWeights[2], |
| 2034 | 2143 | (quint8)materialWeights[3] } }; |
| 2035 | 2144 | |
| 2145 | + points.insert(qRgb(x + 1, y + 1, z + 1), (glm::vec3(clampedX, clampedY, clampedZ) + center) / highest); | |
| 2146 | + | |
| 2036 | 2147 | // determine whether we must "crease" by generating directional normals |
| 2037 | 2148 | const float CREASE_COS_NORMAL = glm::cos(glm::radians(40.0f)); |
| 2038 | 2149 | AxisIndex index(vertices.size(), vertices.size(), vertices.size()); |
| @@ -2158,7 +2269,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { · 119 unmodified lines | ||
| 2158 | 2269 | colorZ += area; |
| 2159 | 2270 | } |
| 2160 | 2271 | } |
| 2161 | − buffer = new VoxelBuffer(vertices, indices, hermiteSegments, | |
| 2272 | + buffer = new VoxelBuffer(vertices, indices, hermiteSegments, points, size, | |
| 2162 | 2273 | material ? material->getMaterials() : QVector<SharedObjectPointer>()); |
| 2163 | 2274 | } |
| 2164 | 2275 | BufferDataPointer pointer(buffer); |