Skip to content

Commit c58a975

Browse files
feat: add depth mesh generation, fix android semantics
1 parent 2e54459 commit c58a975

26 files changed

Lines changed: 2035 additions & 42 deletions

ViroRenderer/VROARDepthMesh.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//
2+
// VROARDepthMesh.cpp
3+
// ViroRenderer
4+
//
5+
// Copyright © 2024 Viro Media. All rights reserved.
6+
//
7+
// Permission is hereby granted, free of charge, to any person obtaining
8+
// a copy of this software and associated documentation files (the
9+
// "Software"), to deal in the Software without restriction, including
10+
// without limitation the rights to use, copy, modify, merge, publish,
11+
// distribute, sublicense, and/or sell copies of the Software, and to
12+
// permit persons to whom the Software is furnished to do so, subject to
13+
// the following conditions:
14+
//
15+
// The above copyright notice and this permission notice shall be included
16+
// in all copies or substantial portions of the Software.
17+
//
18+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21+
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22+
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23+
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24+
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25+
26+
#include "VROARDepthMesh.h"
27+
#include <numeric>
28+
29+
VROARDepthMesh::VROARDepthMesh() {}
30+
31+
VROARDepthMesh::VROARDepthMesh(std::vector<VROVector3f> vertices,
32+
std::vector<int> indices,
33+
std::vector<float> confidences)
34+
: _vertices(std::move(vertices)),
35+
_indices(std::move(indices)),
36+
_confidences(std::move(confidences)) {
37+
}
38+
39+
VROARDepthMesh::~VROARDepthMesh() {}
40+
41+
float VROARDepthMesh::getAverageConfidence() const {
42+
if (_confidences.empty()) {
43+
return 0.0f;
44+
}
45+
float sum = std::accumulate(_confidences.begin(), _confidences.end(), 0.0f);
46+
return sum / static_cast<float>(_confidences.size());
47+
}
48+
49+
bool VROARDepthMesh::isValid() const {
50+
return !_vertices.empty() &&
51+
!_indices.empty() &&
52+
_indices.size() % 3 == 0;
53+
}

ViroRenderer/VROARDepthMesh.h

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
//
2+
// VROARDepthMesh.h
3+
// ViroRenderer
4+
//
5+
// Copyright © 2024 Viro Media. All rights reserved.
6+
//
7+
// Permission is hereby granted, free of charge, to any person obtaining
8+
// a copy of this software and associated documentation files (the
9+
// "Software"), to deal in the Software without restriction, including
10+
// without limitation the rights to use, copy, modify, merge, publish,
11+
// distribute, sublicense, and/or sell copies of the Software, and to
12+
// permit persons to whom the Software is furnished to do so, subject to
13+
// the following conditions:
14+
//
15+
// The above copyright notice and this permission notice shall be included
16+
// in all copies or substantial portions of the Software.
17+
//
18+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21+
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22+
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23+
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24+
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25+
26+
#ifndef VROARDepthMesh_h
27+
#define VROARDepthMesh_h
28+
29+
#include <vector>
30+
#include <memory>
31+
#include "VROVector3f.h"
32+
33+
/**
34+
* Represents a triangulated mesh generated from AR depth data.
35+
* Used for physics collision and hit testing against real-world surfaces.
36+
*
37+
* The mesh is generated by sampling the depth image at regular intervals
38+
* (controlled by stride) and connecting adjacent valid depth samples into
39+
* triangles. Depth discontinuities are detected to avoid connecting
40+
* surfaces that are far apart in depth (e.g., a table edge and the floor).
41+
*/
42+
class VROARDepthMesh {
43+
public:
44+
VROARDepthMesh();
45+
46+
/**
47+
* Construct a depth mesh from vertex and index data.
48+
*
49+
* @param vertices Array of 3D vertex positions in world space
50+
* @param indices Triangle indices (every 3 values form a triangle)
51+
* @param confidences Per-vertex confidence values (0.0-1.0)
52+
*/
53+
VROARDepthMesh(std::vector<VROVector3f> vertices,
54+
std::vector<int> indices,
55+
std::vector<float> confidences);
56+
57+
~VROARDepthMesh();
58+
59+
/**
60+
* Get the vertex positions in world space.
61+
*/
62+
const std::vector<VROVector3f>& getVertices() const { return _vertices; }
63+
64+
/**
65+
* Get the triangle indices. Every 3 values form a triangle.
66+
*/
67+
const std::vector<int>& getIndices() const { return _indices; }
68+
69+
/**
70+
* Get the per-vertex confidence values (0.0-1.0).
71+
*/
72+
const std::vector<float>& getConfidences() const { return _confidences; }
73+
74+
/**
75+
* Get the number of vertices in the mesh.
76+
*/
77+
int getVertexCount() const { return static_cast<int>(_vertices.size()); }
78+
79+
/**
80+
* Get the number of triangles in the mesh.
81+
*/
82+
int getTriangleCount() const { return static_cast<int>(_indices.size() / 3); }
83+
84+
/**
85+
* Get the average confidence across all vertices.
86+
*/
87+
float getAverageConfidence() const;
88+
89+
/**
90+
* Check if the mesh is valid (has vertices and valid triangle indices).
91+
*/
92+
bool isValid() const;
93+
94+
private:
95+
std::vector<VROVector3f> _vertices;
96+
std::vector<int> _indices;
97+
std::vector<float> _confidences;
98+
};
99+
100+
#endif /* VROARDepthMesh_h */

ViroRenderer/VROARDepthMesh.mm

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//
2+
// VROARDepthMesh.cpp
3+
// ViroRenderer
4+
//
5+
// Copyright © 2024 Viro Media. All rights reserved.
6+
//
7+
// Permission is hereby granted, free of charge, to any person obtaining
8+
// a copy of this software and associated documentation files (the
9+
// "Software"), to deal in the Software without restriction, including
10+
// without limitation the rights to use, copy, modify, merge, publish,
11+
// distribute, sublicense, and/or sell copies of the Software, and to
12+
// permit persons to whom the Software is furnished to do so, subject to
13+
// the following conditions:
14+
//
15+
// The above copyright notice and this permission notice shall be included
16+
// in all copies or substantial portions of the Software.
17+
//
18+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21+
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22+
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23+
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24+
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25+
26+
#include "VROARDepthMesh.h"
27+
#include <numeric>
28+
29+
VROARDepthMesh::VROARDepthMesh() {}
30+
31+
VROARDepthMesh::VROARDepthMesh(std::vector<VROVector3f> vertices,
32+
std::vector<int> indices,
33+
std::vector<float> confidences)
34+
: _vertices(std::move(vertices)),
35+
_indices(std::move(indices)),
36+
_confidences(std::move(confidences)) {
37+
}
38+
39+
VROARDepthMesh::~VROARDepthMesh() {}
40+
41+
float VROARDepthMesh::getAverageConfidence() const {
42+
if (_confidences.empty()) {
43+
return 0.0f;
44+
}
45+
float sum = std::accumulate(_confidences.begin(), _confidences.end(), 0.0f);
46+
return sum / static_cast<float>(_confidences.size());
47+
}
48+
49+
bool VROARDepthMesh::isValid() const {
50+
return !_vertices.empty() &&
51+
!_indices.empty() &&
52+
_indices.size() % 3 == 0;
53+
}

ViroRenderer/VROARFrame.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
class VROARCamera;
4040
class VROARAnchor;
4141
class VROARHitTestResult;
42+
class VROARDepthMesh;
4243
class VROTexture;
4344
enum class VROARHitTestResultType;
4445
enum class VROCameraOrientation;
@@ -148,6 +149,22 @@ class VROARFrame {
148149
*/
149150
virtual int getDepthImageHeight() const { return 0; }
150151

152+
/**
153+
* Generate a triangulated mesh from depth data for physics collision.
154+
* The mesh vertices are in world space coordinates.
155+
*
156+
* @param stride Sample every Nth pixel (1=full resolution, 4=recommended for performance)
157+
* @param minConfidence Skip pixels with confidence below this threshold (0.0-1.0)
158+
* @param maxDepth Skip pixels with depth beyond this distance in meters
159+
* @return Shared pointer to depth mesh, or nullptr if depth data is unavailable
160+
*/
161+
virtual std::shared_ptr<VROARDepthMesh> generateDepthMesh(
162+
int stride = 4,
163+
float minConfidence = 0.3f,
164+
float maxDepth = 5.0f) {
165+
return nullptr;
166+
}
167+
151168
/*
152169
Returns the transform matrix to convert from camera texture coordinates
153170
to depth texture coordinates. The depth map may have a different

ViroRenderer/VROARPointCloud.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828

2929
#include <cstdint>
3030
#include <vector>
31+
#include "VROVector4f.h"
3132

32-
class VROVector4f;
3333
class VROMatrix3f;
3434

3535
// TODO: possible need to guard uint64_t usage with #ifdef UINT64_MAX, seems fine on iOS/Android

ViroRenderer/VROARScene.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "VROMaterial.h"
3838
#include "VROImageUtil.h"
3939
#include "VROARCamera.h"
40+
#include "VROPencil.h"
4041

4142
VROARScene::~VROARScene() {
4243
// no-op, we define this here vs in header because for some reason if you want
@@ -137,6 +138,7 @@ void VROARScene::setDriver(std::shared_ptr<VRODriver> driver) {
137138

138139
void VROARScene::updateParticles(const VRORenderContext &context) {
139140
updatePointCloud();
141+
updateWorldMesh();
140142
VROScene::updateParticles(context);
141143
}
142144

@@ -279,3 +281,81 @@ void VROARScene::willDisappear() {
279281
_declarativeSession->sceneWillDisappear();
280282
}
281283
}
284+
285+
#pragma mark - World Mesh
286+
287+
void VROARScene::setWorldMeshEnabled(bool enabled) {
288+
_worldMeshEnabled = enabled;
289+
290+
if (enabled && !_worldMesh) {
291+
// Create world mesh manager with our physics world
292+
_worldMesh = std::make_shared<VROARWorldMesh>(getPhysicsWorld());
293+
_worldMesh->setConfig(_worldMeshConfig);
294+
295+
// Set up callback to notify delegate
296+
std::weak_ptr<VROARSceneDelegate> weakDelegate = _delegate;
297+
_worldMesh->setUpdateCallback([weakDelegate](const VROWorldMeshStats& stats) {
298+
std::shared_ptr<VROARSceneDelegate> delegate = weakDelegate.lock();
299+
if (delegate) {
300+
delegate->onWorldMeshUpdated(stats);
301+
}
302+
});
303+
}
304+
305+
if (_worldMesh) {
306+
_worldMesh->setEnabled(enabled);
307+
}
308+
309+
pinfo("VROARScene: World mesh %s", enabled ? "enabled" : "disabled");
310+
}
311+
312+
bool VROARScene::isWorldMeshEnabled() const {
313+
return _worldMeshEnabled;
314+
}
315+
316+
void VROARScene::setWorldMeshConfig(const VROWorldMeshConfig& config) {
317+
_worldMeshConfig = config;
318+
319+
if (_worldMesh) {
320+
_worldMesh->setConfig(config);
321+
}
322+
}
323+
324+
VROWorldMeshStats VROARScene::getWorldMeshStats() const {
325+
if (_worldMesh) {
326+
return _worldMesh->getStats();
327+
}
328+
return VROWorldMeshStats();
329+
}
330+
331+
void VROARScene::updateWorldMesh() {
332+
if (!_worldMesh || !_worldMeshEnabled) {
333+
return;
334+
}
335+
336+
std::shared_ptr<VROARSession> arSession = _arSession.lock();
337+
if (!arSession) {
338+
return;
339+
}
340+
341+
std::unique_ptr<VROARFrame> &frame = arSession->getLastFrame();
342+
if (!frame) {
343+
return;
344+
}
345+
346+
_worldMesh->updateFromFrame(frame);
347+
}
348+
349+
void VROARScene::computePhysics(const VRORenderContext &context) {
350+
// Call base class physics computation
351+
VROScene::computePhysics(context);
352+
353+
// Draw world mesh wireframe if enabled
354+
debugDrawWorldMesh(context);
355+
}
356+
357+
void VROARScene::debugDrawWorldMesh(const VRORenderContext &context) {
358+
if (_worldMesh && _worldMeshEnabled) {
359+
_worldMesh->debugDraw(context.getPencil());
360+
}
361+
}

0 commit comments

Comments
 (0)