|
28 | 28 | #include "VROARAnchor.h" |
29 | 29 | #include "VROGeospatialAnchor.h" |
30 | 30 | #include "VROARHitTestResult.h" |
| 31 | +#include "VROTextureSubstrateOpenGL.h" |
| 32 | +#include "VRODriverOpenGL.h" |
31 | 33 | #include "VROARImageTargetAndroid.h" |
32 | 34 | #include "VROARPlaneAnchor.h" |
33 | 35 | #include "VROCameraTexture.h" |
@@ -61,11 +63,18 @@ VROARSessionARCore::VROARSessionARCore(std::shared_ptr<VRODriverOpenGL> driver) |
61 | 63 | _geospatialMode(arcore::GeospatialMode::Disabled), |
62 | 64 | _cameraTextureId(0), |
63 | 65 | _displayRotation(VROARDisplayRotation::R0), _rotatedImageDataLength(0), |
64 | | - _rotatedImageData(nullptr) { |
| 66 | + _rotatedImageData(nullptr), |
| 67 | + _driver(driver) { |
65 | 68 |
|
66 | 69 | _session = nullptr; |
67 | 70 | _frame = nullptr; |
68 | 71 | _frameCount = 0; |
| 72 | + |
| 73 | + // Sync occlusion mode with depth mode default |
| 74 | + // Since depth mode defaults to Automatic, enable occlusion by default |
| 75 | + if (_depthMode == arcore::DepthMode::Automatic) { |
| 76 | + VROARSession::setOcclusionMode(VROOcclusionMode::DepthBased); |
| 77 | + } |
69 | 78 | } |
70 | 79 |
|
71 | 80 | void VROARSessionARCore::setARCoreSession( |
@@ -717,7 +726,9 @@ std::unique_ptr<VROARFrame> &VROARSessionARCore::updateFrame() { |
717 | 726 | std::make_unique<VROARFrameARCore>(_frame, _viewport, shared_from_this()); |
718 | 727 |
|
719 | 728 | VROARFrameARCore *arFrame = (VROARFrameARCore *)_currentFrame.get(); |
| 729 | + arFrame->setDriver(_driver.lock()); |
720 | 730 | processUpdatedAnchors(arFrame); |
| 731 | + updateDepthTexture(); |
721 | 732 |
|
722 | 733 | return _currentFrame; |
723 | 734 | } |
@@ -1591,3 +1602,124 @@ void VROARSessionARCore::setSemanticModeEnabled(bool enabled) { |
1591 | 1602 | _semanticModeEnabled = false; |
1592 | 1603 | } |
1593 | 1604 | } |
| 1605 | + |
| 1606 | +void VROARSessionARCore::updateDepthTexture() { |
| 1607 | + // Limit log frequency to avoid spam |
| 1608 | + static int logCounter = 0; |
| 1609 | + if (logCounter++ % 60 == 0) { |
| 1610 | + pinfo("VROARSessionARCore::updateDepthTexture called (sampled)"); |
| 1611 | + } |
| 1612 | + |
| 1613 | + if (!isDepthModeEnabled()) { |
| 1614 | + // pinfo("VROARSessionARCore: Depth mode disabled, skipping update"); |
| 1615 | + return; |
| 1616 | + } |
| 1617 | + |
| 1618 | + // Acquire depth image from ARCore |
| 1619 | + arcore::Image *depthImage = nullptr; |
| 1620 | + arcore::ImageRetrievalStatus status = _frame->acquireDepthImage(&depthImage); |
| 1621 | + |
| 1622 | + if (status != arcore::ImageRetrievalStatus::Success || depthImage == nullptr) { |
| 1623 | + // pwarn("VROARSessionARCore: Failed to acquire depth image. Status: %d", (int)status); |
| 1624 | + return; |
| 1625 | + } |
| 1626 | + |
| 1627 | + int width = depthImage->getWidth(); |
| 1628 | + int height = depthImage->getHeight(); |
| 1629 | + |
| 1630 | + if (width <= 0 || height <= 0) { |
| 1631 | + pwarn("VROARSessionARCore: Invalid depth image dimensions: %d x %d", width, height); |
| 1632 | + delete depthImage; |
| 1633 | + return; |
| 1634 | + } |
| 1635 | + |
| 1636 | + // Get depth data (16-bit depth in millimeters) |
| 1637 | + const uint8_t *depthData = nullptr; |
| 1638 | + int depthDataLength = 0; |
| 1639 | + depthImage->getPlaneData(0, &depthData, &depthDataLength); |
| 1640 | + |
| 1641 | + int rowStride = depthImage->getPlaneRowStride(0); |
| 1642 | + |
| 1643 | + if (depthData == nullptr || depthDataLength <= 0) { |
| 1644 | + pwarn("VROARSessionARCore: Invalid depth data. Length: %d", depthDataLength); |
| 1645 | + delete depthImage; |
| 1646 | + return; |
| 1647 | + } |
| 1648 | + |
| 1649 | + // Convert to float buffer |
| 1650 | + int numPixels = width * height; |
| 1651 | + if (_depthFloatBuffer.size() != numPixels) { |
| 1652 | + _depthFloatBuffer.resize(numPixels); |
| 1653 | + } |
| 1654 | + |
| 1655 | + float *floatData = _depthFloatBuffer.data(); |
| 1656 | + |
| 1657 | + // Handle row stride (padding) |
| 1658 | + if (rowStride > 0 && rowStride != width * 2) { |
| 1659 | + for (int y = 0; y < height; y++) { |
| 1660 | + const uint16_t *rowStart = reinterpret_cast<const uint16_t*>(depthData + y * rowStride); |
| 1661 | + for (int x = 0; x < width; x++) { |
| 1662 | + floatData[y * width + x] = (float)rowStart[x] * 0.001f; |
| 1663 | + } |
| 1664 | + } |
| 1665 | + } else { |
| 1666 | + // Optimized loop: direct pointer access (packed) |
| 1667 | + const uint16_t *depthData16 = reinterpret_cast<const uint16_t*>(depthData); |
| 1668 | + for (int i = 0; i < numPixels; i++) { |
| 1669 | + floatData[i] = (float)depthData16[i] * 0.001f; // mm to meters |
| 1670 | + } |
| 1671 | + } |
| 1672 | + |
| 1673 | + // DEBUG: Log center depth value |
| 1674 | + if (numPixels > 0) { |
| 1675 | + int centerIdx = (height / 2) * width + (width / 2); |
| 1676 | + // pinfo("VROARSessionARCore: Depth update. Center val: %f, Width: %d, Height: %d", floatData[centerIdx], width, height); |
| 1677 | + } |
| 1678 | + |
| 1679 | + // If texture doesn't exist, create it |
| 1680 | + if (!_depthTexture || _depthTexture->getWidth() != width || _depthTexture->getHeight() != height) { |
| 1681 | + pinfo("VROARSessionARCore: Creating new depth texture (size %d x %d)", width, height); |
| 1682 | + std::shared_ptr<VROData> depthVROData = std::make_shared<VROData>( |
| 1683 | + (void *)floatData, numPixels * sizeof(float), VRODataOwnership::Copy); |
| 1684 | + std::vector<std::shared_ptr<VROData>> dataVec = { depthVROData }; |
| 1685 | + |
| 1686 | + _depthTexture = std::make_shared<VROTexture>(VROTextureType::Texture2D, |
| 1687 | + VROTextureFormat::R32F, |
| 1688 | + VROTextureInternalFormat::R32F, |
| 1689 | + false, |
| 1690 | + VROMipmapMode::None, |
| 1691 | + dataVec, |
| 1692 | + width, height, |
| 1693 | + std::vector<uint32_t>()); |
| 1694 | + |
| 1695 | + _depthTexture->setMinificationFilter(VROFilterMode::Nearest); |
| 1696 | + _depthTexture->setMagnificationFilter(VROFilterMode::Nearest); |
| 1697 | + // Use Clamp which maps to GL_CLAMP_TO_EDGE for OpenGL ES compatibility |
| 1698 | + _depthTexture->setWrapS(VROWrapMode::Clamp); |
| 1699 | + _depthTexture->setWrapT(VROWrapMode::Clamp); |
| 1700 | + } else { |
| 1701 | + // Update existing texture |
| 1702 | + std::shared_ptr<VRODriver> driver = _driver.lock(); |
| 1703 | + if (driver) { |
| 1704 | + VROTextureSubstrate *substrate = _depthTexture->getSubstrate(0, driver, true); |
| 1705 | + if (substrate) { |
| 1706 | + // We need to cast to OpenGL substrate to access GL ID, or use a generic update method if available. |
| 1707 | + // Since we are in VROARSessionARCore (Android specific), we can assume OpenGL. |
| 1708 | + VROTextureSubstrateOpenGL *glSubstrate = (VROTextureSubstrateOpenGL *)substrate; |
| 1709 | + std::pair<GLenum, GLuint> textureInfo = glSubstrate->getTexture(); |
| 1710 | + GLenum target = textureInfo.first; |
| 1711 | + GLuint texId = textureInfo.second; |
| 1712 | + |
| 1713 | + glBindTexture(target, texId); |
| 1714 | + glTexSubImage2D(target, 0, 0, 0, width, height, GL_RED, GL_FLOAT, floatData); |
| 1715 | + glBindTexture(target, 0); |
| 1716 | + } else { |
| 1717 | + pwarn("VROARSessionARCore: Failed to get substrate for depth texture update"); |
| 1718 | + } |
| 1719 | + } else { |
| 1720 | + pwarn("VROARSessionARCore: Driver expired, cannot update depth texture"); |
| 1721 | + } |
| 1722 | + } |
| 1723 | + |
| 1724 | + delete depthImage; |
| 1725 | +} |
0 commit comments