diff --git a/Source/ArkitCapture.h b/Source/ArkitCapture.h index 4ded8a1..b0c8ab2 100644 --- a/Source/ArkitCapture.h +++ b/Source/ArkitCapture.h @@ -17,6 +17,8 @@ namespace Arkit class TSessionCamera; // arkit session which reads a certain source class TCaptureParams; + class TGeometryCache; + namespace ArFrameSource { enum Type @@ -70,10 +72,24 @@ class Arkit::TCaptureParams bool mOutputSceneDepthSmooth = false; bool mVerboseDebug = false; // todo: colour format + bool mOutputAnchorGeometryStream = false; // output anchor geometry triangles as a float-image stream }; +class Arkit::TGeometryCache +{ +public: + std::string mUuid; + vec3f mBoundsCenter; + vec3f mBoundsSize; + size_t mPositionCount = 0; + SoyTime mTimestamp; + std::shared_ptr mTrianglePositionsPixels; // floats stored in a pixel buffer. done early to avoid a copy/alloc later + //Array mTrianglePositions; + BufferArray mLocalToWorld; +}; + class Arkit::TFrameDevice : public PopCameraDevice::TDevice { public: @@ -84,9 +100,15 @@ class Arkit::TFrameDevice : public PopCameraDevice::TDevice void PushFrame(ARDepthData* DepthData,SoyTime Timestamp,json11::Json::object& Meta,const char* StreamName); void PushFrame(ARFrame* Frame,ArFrameSource::Type Source); + void PushGeometryFrame(const TGeometryCache& Geometry); + void UpdateGeometry(const std::string& Uuid,std::function UpdateGeometry); // callback return true if data changed + SoyTime mPreviousDepthTime; SoyTime mPreviousFrameTime; TCaptureParams mParams; + + // we keep old geometry, so we can detect is if it's changed + Array> mGeometryCache; }; diff --git a/Source/ArkitCapture.mm b/Source/ArkitCapture.mm index ca44444..64e0acf 100644 --- a/Source/ArkitCapture.mm +++ b/Source/ArkitCapture.mm @@ -27,6 +27,7 @@ namespace Arkit { + const char* GeometryStreamName = "Geometry"; const char* GetColourStreamName(ArFrameSource::Type Source); }; @@ -646,9 +647,9 @@ void GetAnchorMeta(ARPlaneAnchor* Anchor, json11::Json::object& Meta,bool Includ json11::Json::array GeometryPositions; GetAnchorTriangles( Anchor.geometry, GeometryPositions ); Meta["Triangles"] = GeometryPositions; + } } } -} // return false to not report this anchor bool GetAnchorMeta(ARAnchor* Anchor, json11::Json::object& Meta,bool IncludeGeometry) @@ -692,6 +693,21 @@ bool GetAnchorMeta(ARAnchor* Anchor, json11::Json::object& Meta,bool IncludeGeom return true; } +void EnumGeometryAnchors(ARFrame* Frame,std::function Enum) +{ + auto EnumAnchor = [&](ARAnchor* Anchor) + { + if ( [Anchor isKindOfClass:[ARPlaneAnchor class]] ) + { + Enum( (ARPlaneAnchor*)Anchor, nullptr ); + } + if ( [Anchor isKindOfClass:[ARMeshAnchor class]] ) + { + Enum( nullptr, (ARMeshAnchor*)Anchor ); + } + }; + Platform::NSArray_ForEach(Frame.anchors,EnumAnchor); +} void Avf::GetMeta(ARFrame* Frame,json11::Json::object& Meta,Arkit::TCaptureParams& Params) { @@ -842,9 +858,54 @@ bool GetAnchorMeta(ARAnchor* Anchor, json11::Json::object& Meta,bool IncludeGeom // todo; get capabilities and reject params here } +bool UpdateGeomtetry(ARPlaneAnchor* Anchor,Arkit::TGeometryCache& Geometry) +{ + Geometry.mBoundsCenter = vec3f( Anchor.center.x, Anchor.center.y, Anchor.center.z ); + Geometry.mBoundsSize = vec3f( Anchor.extent.x, Anchor.extent.y, Anchor.extent.z ); + + if ( Anchor.geometry ) + { + auto TriangleCount = Anchor.geometry.triangleCount; + Geometry.mPositionCount = TriangleCount * 3; + + } + +} + +bool UpdateGeomtetry(ARMeshAnchor* Anchor,Arkit::TGeometryCache& Geometry) +{ + return false; +} void Arkit::TFrameDevice::PushFrame(ARFrame* Frame,ArFrameSource::Type Source) { + auto OnAnchor = [&](ARPlaneAnchor* PlaneAnchor,ARMeshAnchor* MeshAnchor) + { + auto* Anchor = PlaneAnchor ? PlaneAnchor : MeshAnchor; + if ( !Anchor ) + return; + + auto Uuid = Soy::NSStringToString(Anchor.identifier.UUIDString); + if ( PlaneAnchor ) + { + auto Update = [&](TGeometryCache& Geometry) + { + return UpdateGeomtetry( PlaneAnchor, Geometry ); + }; + this->UpdateGeometry( Uuid, Update ); + } + + if ( MeshAnchor ) + { + auto Update = [&](TGeometryCache& Geometry) + { + return UpdateGeomtetry( MeshAnchor, Geometry ); + }; + this->UpdateGeometry( Uuid, Update ); + } + }; + EnumGeometryAnchors(Frame); + auto* ColourStreamName = GetColourStreamName(Source); auto FrameTime = Soy::Platform::GetTime( Frame.timestamp ); auto CapDepthTime = Soy::Platform::GetTime( Frame.capturedDepthDataTimestamp ); @@ -949,6 +1010,24 @@ bool GetAnchorMeta(ARAnchor* Anchor, json11::Json::object& Meta,bool IncludeGeom } +void Arkit::TFrameDevice::PushGeometryFrame(const TGeometryCache& Geometry) +{ + Soy::TScopeTimerPrint Timer(__PRETTY_FUNCTION__,5); + + float3x3 Transform; + auto StreamName = GeometryStreamName; + std::shared_ptr Buffer( new TDumbSharedPixelBuffer( Geometry.mTrianglePositionsPixels, Transform ) ); + + json11::Json::object Meta; + Meta["StreamName"] = StreamName; + Meta["AnchorUuid"] = Geometry.mUuid; + Meta["PositionCount"] = Geometry.mPositionCount; + Meta["LocalToWorld"] = GetJsonArray(Geometry.mLocalToWorld); + + PopCameraDevice::TDevice::PushFrame( Buffer, Timestamp, Meta ); +} + +