<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Shiru99 on Medium]]></title>
        <description><![CDATA[Stories by Shiru99 on Medium]]></description>
        <link>https://medium.com/@shiru99?source=rss-a19e9a6bab29------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*KE1s_veWShpwhl0VGcizXQ.png</url>
            <title>Stories by Shiru99 on Medium</title>
            <link>https://medium.com/@shiru99?source=rss-a19e9a6bab29------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 02:26:23 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@shiru99/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Eye Tracking with ARKit (iOS)- Part II]]></title>
            <link>https://shiru99.medium.com/eye-tracking-with-arkit-ios-part-ii-2723f9bfe04e?source=rss-a19e9a6bab29------2</link>
            <guid isPermaLink="false">https://medium.com/p/2723f9bfe04e</guid>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[lookatpoint]]></category>
            <category><![CDATA[augmented-reality]]></category>
            <category><![CDATA[arkit]]></category>
            <category><![CDATA[eye-tracking]]></category>
            <dc:creator><![CDATA[Shiru99]]></dc:creator>
            <pubDate>Tue, 09 Jan 2024 07:42:53 GMT</pubDate>
            <atom:updated>2024-01-09T07:42:53.249Z</atom:updated>
            <content:encoded><![CDATA[<p><em>Utilizing LookAtPoint for Pinpointing User’s Gaze onto the Mobile Screen Plane</em></p><p>In this article, we’ll explore the practical application of eye gaze tracking on a mobile screen. Leveraging the power of ARKit’s <strong>ARFaceAnchor</strong> and the dynamic <strong>lookAtPoint</strong> property, this project allows us to precisely determine where a user is looking on their device.</p><p>The code and resources you need are conveniently hosted in the <a href="https://github.com/Shiru99/AR-Eye-Tracker">GitHub repository</a>. Basics about ARKit, ARFaceAnchor, BlendShapeLocations, and LookAtPoint covered in <a href="https://shiru99.medium.com/eye-tracking-with-arkit-ios-part-i-ad42cd21301d">1st part</a>.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FTX9qSaGXFyg%3Fstart%3D34%26feature%3Doembed%26start%3D34&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DTX9qSaGXFyg&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FTX9qSaGXFyg%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/d6bbcbaa1480d11a161420ff3a57a257/href">https://medium.com/media/d6bbcbaa1480d11a161420ff3a57a257/href</a></iframe><blockquote>In a recent Apple event, the frontier of eye tracking technology was pushed further with the Vision Pro mixed-reality headset, showcasing a future where users can interact with applications using just their eyes</blockquote><h3>Local Coordinate Space Vs World Coordinate System</h3><h4>Local Coordinate Space:</h4><p>Imagine the local coordinate space of the ARFaceAnchor as a 3D grid centered on the face. The origin of this grid is at the center of the face, and positions and rotations are defined relative to this origin. The lookAtPoint is a coordinate in this local space and indicates the direction the user is looking concerning their own face.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*BRgHrrtu4gquKP_Z.png" /><figcaption>ARFaceAnchor</figcaption></figure><h4>World Coordinate System:</h4><p>Now, let’s expand this view to the world coordinate system. In the broader world space (the entire environment captured by the camera), every object, including the face anchor, has its own position and orientation. The world coordinate system provides a global reference frame for all these objects.</p><p>The lookAtPoint is a point expressed in the local coordinate space of the face anchor. To convert it into a meaningful global position, you need to consider the anchor&#39;s own position and orientation in the world coordinate system.</p><blockquote><strong>Simplified Explanation: </strong>Local Coordinate Space <strong><em>Vs</em></strong> World Coordinate System and their relation with lookAtPoint &amp; <em>ARFaceAnchor :</em></blockquote><blockquote>Think of the ARFaceAnchor as the center of a little world on your face. This is the Local Coordinate Space. In this space, everything is measured from the center of your face, like how you might give directions using your own body as a reference point (raise your right hand).</blockquote><blockquote>Now, imagine you’re in a larger world, like a room. This is the World Coordinate System. In this big world, there are not only things on your face (like the ARFaceAnchor or where you’re looking), but also everything else around you, including the device’s camera capturing your face.</blockquote><blockquote>So, when we talk about where you’re looking (lookAtPoint), we first figure it out in the little world on your face (Local Coordinate Space with the ARFaceAnchor as the center). Then, we take that information and translate it to make sense in the bigger world around you (World Coordinate System), where there’s more than just your face — there’s the whole environment captured by the camera. It’s like saying, “I’m pointing to my nose in my personal space, and now let’s find where that is in the entire room.”</blockquote><h3>lookAtPoint w.r.t. the world coordinate system</h3><p>To convert the lookAtPoint from the local coordinate space of the ARFaceAnchor to the world coordinate system, we can use matrix multiplication. The process involves applying the transformation matrix of the ARFaceAnchor to the lookAtPoint. This will bring the point from the local coordinate space of the face anchor to the world coordinate system.</p><pre>let lookAtPointInWorld = faceAnchor.transform * simd_float4(lookAtPoint, 1)</pre><p>In this line, faceAnchor.transform represents the transformation matrix of the ARFaceAnchor, and lookAtPoint is extended to a simd_float4 to facilitate matrix multiplication. The multiplication operation combines the transformation matrix and the point, resulting in a new point that is now in the world coordinate system.</p><p>After this transformation, lookAtPointInWorld contains the coordinates of the lookAtPoint with respect to the world coordinate system.</p><h3>Camera Transformations</h3><p>The camera is a crucial component in AR, responsible for capturing the real-world environment and providing the necessary data for rendering virtual objects in the correct perspective.</p><p>In ARKit, the camera.transform represents the transformation matrix of the device&#39;s camera. The transformation matrix is a mathematical construct that encapsulates translation, rotation, and scaling operations in 3D space. Essentially, it contains information about how the camera is positioned and oriented relative to the <strong>world coordinate system</strong>.</p><pre>cameraTransform = session.currentFrame?.camera.transform</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/375/1*XBu3mS4pcm1NFIR3Ku2A3Q.png" /></figure><p>Breakdown of what the camera.transform includes:</p><ul><li>Translation (Position): Specifies the location of the camera in 3D space (X, Y, Z coordinates).</li><li>Rotation: Describes the orientation of the camera. This can include rotations around the X, Y, and Z axes.</li><li>Scaling: Defines any scaling factors applied to the camera.</li></ul><p>camera.transform is useful to transform the lookAtPoint (gaze direction) from the local coordinate space of the ARFaceAnchor to the world coordinate system.</p><p>In summary, the camera.transform provides a comprehensive representation of how the device&#39;s camera is positioned and oriented in 3D space, enabling accurate transformations between the real world and the virtual world in AR applications.</p><h3>lookAtPoint onto the mobile screen</h3><p>To find the reflection of a point in the XY plane (phone screen plane) of a given camera transform, you can follow these steps:</p><ol><li><strong>Transform the LookAtPoint to Camera Coordinates:</strong></li></ol><ul><li>We have the lookAtPointInWorld in global coordinates (world coordinate system).</li><li>Use the inverse of the camera transform to convert it to camera coordinates. This new point is referred to as lookAtPointInCamera.</li></ul><pre>let lookAtPointInCamera = simd_mul(simd_inverse(cameraTransform), lookAtPointInWorld)</pre><p><strong>2. Reflection in the XY Plane </strong>(Phone screen plane<strong>):</strong></p><ul><li>To reflect a point in the XY plane, we can neglect its z-coordinate since lookAtPointInCamera is relative to camera coordinates.</li><li>Coordinates — (transformedLookAtPoint.x, transformedLookAtPoint.y)</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/691/0*ExmMk7oTbqRzA08q" /><figcaption>(transformedLookAtPoint.x, transformedLookAtPoint.y)</figcaption></figure><p>In conclusion, by transforming the lookAtPoint from global coordinates to camera coordinates and reflecting it in the XY plane, we successfully obtained the user’s gaze point coordinates in the camera coordinates system.</p><h3>FocusPoint on Mobile Screen</h3><p>After obtaining the user’s gaze point coordinates in the camera coordinates system, the next step is to project this point onto the mobile screen. The process involves several key calculations:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Ftenor.com%2Fembed%2F3654754744145897317&amp;display_name=Tenor&amp;url=https%3A%2F%2Ftenor.com%2Fview%2Fdungeong-gif-3654754744145897317&amp;image=https%3A%2F%2Fmedia.tenor.com%2FMrhME3n9Z2UAAAAN%2Fdungeong.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=tenor" width="600" height="400" frameborder="0" scrolling="no"><a href="https://medium.com/media/e4a2e602e6226f5e57e291c28fdd1b3b/href">https://medium.com/media/e4a2e602e6226f5e57e291c28fdd1b3b/href</a></iframe><pre>let screenX = transformedLookAtPoint.y / (Float(Device.screenSize.width) / 2) * Float(Device.frameSize.width)<br>let screenY = transformedLookAtPoint.x / (Float(Device.screenSize.height) / 2) * Float(Device.frameSize.height)<br>        <br>let focusPoint = CGPoint(<br>    x: CGFloat(screenX).clamped(to: Ranges.widthRange),<br>    y: CGFloat(screenY).clamped(to: Ranges.heightRange)<br>)</pre><p><strong>Normalization:</strong></p><ul><li>transformedLookAtPoint.y / (Float(Device.screenSize.width) / 2): This step normalizes the y-coordinate of the gaze point relative to half of the screen width, resulting in a value between -1 and 1.</li><li>transformedLookAtPoint.x / (Float(Device.screenSize.height) / 2): Similarly, the x-coordinate is normalized relative to half of the screen height.</li></ul><p><strong>Scaling to Screen Size:</strong></p><ul><li>* Float(Device.frameSize.width): The normalized x-coordinate is then scaled to the full width of the screen.</li><li>* Float(Device.frameSize.height): Likewise, the normalized y-coordinate is scaled to the full height of the screen.</li></ul><p><strong>Creating a CGPoint:</strong></p><ul><li>let focusPoint = CGPoint(...): The scaled coordinates are then used to create a CGPoint, representing the user&#39;s focus point on the mobile screen.</li></ul><p><strong>Clamping to Screen Boundaries:</strong></p><ul><li>clamped(to: Ranges.widthRange) and clamped(to: Ranges.heightRange): To ensure the focus point stays within the screen boundaries, these clamping operations restrict the coordinates to valid ranges.</li></ul><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FcjR-mREOJCQ%3Fstart%3D26%26feature%3Doembed%26start%3D26&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DcjR-mREOJCQ&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FcjR-mREOJCQ%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/7d965994a4d06d1fcdb5a3a27ca2f194/href">https://medium.com/media/7d965994a4d06d1fcdb5a3a27ca2f194/href</a></iframe><h3>limitations of eye tracking with ARKit</h3><ul><li>Head movement: Head movement can affect the accuracy of eye tracking, especially if the user is moving their head quickly.</li><li>Blinking: Blinking can also affect the accuracy of eye tracking, as the camera may not be able to track the user’s eyes during a blink.</li><li>Ambient lighting: Ambient lighting can also affect the accuracy of eye tracking, as the camera may not be able to see the user’s eyes properly if the lighting is too bright or too dark.</li><li>Other Factors: Glasses and accessories, Eyelid occlusion, Eye conditions, Distance and angle, Limited field of view:, Environmental factors, Hardware limitations</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2723f9bfe04e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Eye Tracking with ARKit (iOS)- Part I]]></title>
            <link>https://shiru99.medium.com/eye-tracking-with-arkit-ios-part-i-ad42cd21301d?source=rss-a19e9a6bab29------2</link>
            <guid isPermaLink="false">https://medium.com/p/ad42cd21301d</guid>
            <category><![CDATA[arfaceanchor]]></category>
            <category><![CDATA[arkit]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[lookatpoint]]></category>
            <category><![CDATA[eye-tracking]]></category>
            <dc:creator><![CDATA[Shiru99]]></dc:creator>
            <pubDate>Mon, 08 Jan 2024 18:31:44 GMT</pubDate>
            <atom:updated>2024-01-08T19:03:51.494Z</atom:updated>
            <content:encoded><![CDATA[<p><em>Exploring ARKit, ARFaceAnchor, BlendShapeLocations, and LookAtPoint</em></p><p>Eye tracking technology can be a game-changer, unlocking new dimensions of user interaction and immersion. an AR experience that responds to the movement of your eyes, providing a level of engagement and personalization previously unattainable. <em>Imagine scrolling Instagram or X with eyebrow movement.</em></p><p>In this article, we’ll work on eye tracking with a specific focus on implementing it using ARKit, Apple’s powerful augmented reality framework. The code and resources you need are conveniently hosted in the <a href="https://github.com/Shiru99/AR-Eye-Tracker">GitHub repository</a>.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FcjR-mREOJCQ%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DcjR-mREOJCQ&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FcjR-mREOJCQ%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/986c638c52e7b424db85dc6bf296122f/href">https://medium.com/media/986c638c52e7b424db85dc6bf296122f/href</a></iframe><p>Eye tracking utilizes the front camera to monitor and track the gaze and movements of a user’s eyes. This technology enables AR applications to precisely discern the user’s point of focus, facilitating dynamic adjustments in the presentation of digital content based on their gaze direction.</p><h3>ARKit &amp; ARFaceAnchor</h3><p><a href="https://developer.apple.com/documentation/arkit">ARKit</a> is Apple’s augmented reality (AR) framework that empowers developers to integrate AR experiences seamlessly into iOS applications. One crucial aspect of ARKit is its ability to track and analyze facial expressions using the <a href="https://developer.apple.com/documentation/arkit/arfaceanchor">ARFaceAnchor</a> class.</p><h4>ARFaceAnchor:</h4><p>ARFaceAnchor is a class in ARKit that represents the face geometry tracked in an AR session. It provides information about the user’s facial features, such as the position and orientation of the face, as well as details about facial expressions through the use of blend shapes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*OUTqB67VgWE4y8PT.png" /><figcaption><em>ARFaceAnchor</em></figcaption></figure><p>Blend Shape Locations:</p><p>Blend shapes, in the context of ARFaceAnchor, refer to specific facial muscle movements or expressions that ARKit can identify and track. BlendShapeLocation is an enumeration in ARKit that defines various regions of the face, each corresponding to a specific facial feature or expression.</p><p>Some common BlendShapeLocations include:</p><ul><li>.mouthSmileLeft and .mouthSmileRight: Indicates a smile on the left or right side of the mouth.</li><li>.eyeBlinkLeft and .eyeBlinkRight: Represents a blink in the left or right eye.</li><li>.browDownLeft and .browDownRight: Signifies a downward movement of the left or right eyebrow.</li><li>.mouthPucker: Indicates a puckering or tightening of the mouth.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*GPiDDnLkyFn2OM4Q.png" /><figcaption>eyeBlinkLeft</figcaption></figure><blockquote><strong>Use Case: Interactive Gaming</strong></blockquote><blockquote>In gaming applications, facial expressions can be harnessed as input for character control or to trigger in-game events. Imagine building a game similar to Flappy Bird, but with a unique twist — this time, the bird takes flight with a simple blink of the eye. By utilizing blend shapes and ARFaceAnchor in ARKit, developers can introduce an entirely new level of interactivity, making gaming experiences more immersive and responsive to the player’s facial expressions.</blockquote><blockquote>Extending this concept to other applications, similar functionality can be implemented in social media apps, allowing users to scroll through content without physically touching the screen. This innovative use of facial expressions can redefine how users interact with digital environments, making the experience more intuitive and engaging.</blockquote><h3>ARFaceAnchor.LookAtPoint</h3><p>The <a href="https://developer.apple.com/documentation/arkit/arfaceanchor/2968192-lookatpoint">lookAtPoint</a> property in ARFaceAnchor plays a crucial role in eye tracking by providing information about the point in 3D space where the user is looking. When a user&#39;s gaze is directed at a specific point, this property holds the coordinates of that point in the AR world.</p><p>How it works:</p><ol><li><strong>Gaze Tracking</strong>: ARKit meticulously tracks the position of a user’s eyes by utilizing information from leftEyeTransform and rightEyeTransform.</li><li><strong>3D Coordinate Calculation</strong>: Leveraging the detected eye transforms, ARKit performs calculations to pinpoint the user’s current gaze in the 3D space. This calculated point is then represented by the lookAtPoint.</li><li><strong>Real-time Updates</strong>: The lookAtPoint property stays dynamically updated in real-time, continuously reflecting changes in the user’s gaze. This provides developers with up-to-the-moment information about the focal point in the AR environment.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hHnHUBl9H0jHUHMv8GPjlg.png" /><figcaption>rightEyeTransform</figcaption></figure><p>The lookAtPoint property is a valuable tool for developers implementing eye tracking features. It provides a dynamic and accurate representation of a user&#39;s gaze point in 3D space, opening up possibilities for creating immersive and responsive AR applications.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ad42cd21301d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AR Persistence with ARKit & RealityKit [in Details]: AR with iOS (Part-VIII)]]></title>
            <link>https://shiru99.medium.com/ar-persistence-with-arkit-realitykit-in-details-ar-with-ios-part-viii-28911d5cac5b?source=rss-a19e9a6bab29------2</link>
            <guid isPermaLink="false">https://medium.com/p/28911d5cac5b</guid>
            <category><![CDATA[augmented-reality]]></category>
            <category><![CDATA[arpersistence]]></category>
            <category><![CDATA[realitykit]]></category>
            <category><![CDATA[arkit]]></category>
            <category><![CDATA[persistence]]></category>
            <dc:creator><![CDATA[Shiru99]]></dc:creator>
            <pubDate>Thu, 22 Jun 2023 12:51:22 GMT</pubDate>
            <atom:updated>2023-06-22T12:51:22.672Z</atom:updated>
            <content:encoded><![CDATA[<p>Refer <a href="https://shiru99.medium.com/ar-persistence-with-arkit-realitykit-ar-with-ios-part-vii-2dfd4fda446c">Part VII </a>for intro of AR Persistence &amp; ARWorldMap. We’ll explore functionalities of ARPersistence package here.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nQBZKn5GEwTR71aNBTp4kg.png" /><figcaption>AR Persistence</figcaption></figure><h3>Save AR Functionality</h3><pre>public func save(_ uiView: ARView) {<br>    var modelEntityDetailsDict: [String: [String]] = [:]<br>    <br>    // Iterate through AR anchors<br>    if let arAnchors = uiView.session.currentFrame?.anchors {<br>        for arAnchor in arAnchors {<br>            if let modelName = arAnchor.name,<br>               let identifier = arAnchor.identifier {<br>                <br>                // Retrieve model entity and transform details<br>                if let anchorEntity = uiView.scene.findEntity(named: identifier) as? AnchorEntity,<br>                   let modelEntity = anchorEntity.children.first as? ModelEntity {<br>                    let transformDetails = [<br>                        modelEntity.transform.translation.debugDescription,<br>                        modelEntity.transform.rotation.debugDescription,<br>                        modelEntity.transform.scale.debugDescription<br>                    ]<br>                    modelEntityDetailsDict[&quot;\(modelName)@\(identifier.uuidString)&quot;] = transformDetails<br>                }<br>            }<br>        }<br>    }<br>    <br>    // Save AR Anchors as WorldMap<br>    let anchorDataURL = self.worldMapDir.appendingPathComponent(&quot;ARExperience.map&quot;)<br>    uiView.session.getCurrentWorldMap { worldMap, error in<br>        guard let worldMap = worldMap else { return }<br>        do {<br>            let anchorData = try NSKeyedArchiver.archivedData(withRootObject: worldMap, requiringSecureCoding: true)<br>            try anchorData.write(to: anchorDataURL, options: [.atomic])<br>        } catch {<br>            fatalError(&quot;Debug: Can&#39;t save map: \(error.localizedDescription)&quot;)<br>        }<br>    }<br>    <br>    // Save modelEntity transforms as JSON<br>    let modelEntityDataURL = self.worldMapDir.appendingPathComponent(&quot;ARExperience.json&quot;)<br>    do {<br>        let jsonData = try JSONSerialization.data(withJSONObject: modelEntityDetailsDict, options: [])<br>        try jsonData.write(to: modelEntityDataURL)<br>    } catch {<br>        print(&quot;Debug: \(error.localizedDescription)&quot;)<br>    }<br>}</pre><p><strong>Summary: </strong>The save method is responsible for saving the AR anchors and model entity transforms for AR persistence. It iterates through the AR anchors, retrieves the model entity and its transform details, and stores them in a dictionary. Then, it saves the AR anchors as a WorldMap using the getCurrentWorldMap method. Finally, it saves the model entity transforms as JSON. This method allows the user to save the positions and transformations of virtual objects placed in the scene for future retrieval and AR experiences.</p><h4><strong>Detailed Explanation:</strong></h4><p>Let’s go through the save function step by step:</p><ol><li>Create a dictionary modelEntityDetailsDict to store the details of the model entities&#39; transformations. The keys of the dictionary will be a combination of the model name and the anchor identifier.</li><li>Iterate through the AR anchors present in the current AR frame.</li><li>For each anchor, check if it has a name and an identifier. If both are available, proceed to retrieve the model entity and its transformation details.</li><li>Using the anchor’s identifier, find the corresponding AnchorEntity in the AR scene using the findEntity(named:) method. Then, access the first child of the AnchorEntity, assuming it is the model entity.</li><li>Retrieve the translation, rotation, and scale values of the model entity’s transformation and store them as an array of strings in the transformDetails variable.</li><li>Add an entry to the modelEntityDetailsDict dictionary using the combination of the model name and the anchor identifier as the key and the transformDetails as the value.</li><li>Define the URL for storing the AR anchors as a World Map. The file will be named “ARExperience.map” and stored in the worldMapDir directory.</li><li>Call getCurrentWorldMap on the AR session to obtain the current world map.</li><li>Inside the completion block, check if the worldMap is not nil. If it exists, archive the world map data using NSKeyedArchiver and write it to the anchorDataURL.</li><li>If an error occurs during the archiving and writing process, handle it by reporting a fatal error.</li><li>Define the URL for storing the model entity transforms as JSON. The file will be named “ARExperience.json” and stored in the worldMapDir directory.</li><li>Serialize the modelEntityDetailsDict dictionary into JSON data using JSONSerialization.data(withJSONObject:options:).</li><li>Write the JSON data to the modelEntityDataURL.</li><li>If an error occurs during the serialization and writing process, print the error description for debugging purposes.</li></ol><p>In summary, the save function iterates through the AR anchors in the current frame, retrieves the transformation details of the associated model entities, and stores both the AR anchors as a World Map and the model entity transforms as a JSON file. This enables saving the state of the AR experience, allowing it to be reloaded and restored at a later time with the same spatial alignment and placed virtual objects.</p><h4>Load AR Functionality</h4><pre>public func load(_ uiView: ARView) {<br>    // Load AR Anchors<br>    let anchorDataURL = self.worldMapDir.appendingPathComponent(&quot;ARExperience.map&quot;)<br>    <br>    do {<br>        let anchorData = try Data(contentsOf: anchorDataURL)<br>        if let worldMap = try NSKeyedUnarchiver.unarchivedObject(ofClass: ARWorldMap.self, from: anchorData) {<br>            let configuration = ARWorldTrackingConfiguration()<br>            configuration.initialWorldMap = worldMap<br>            uiView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])<br>        }<br>    } catch {<br>        print(&quot;Debug: Can&#39;t load map: \(error.localizedDescription)&quot;)<br>    }<br>    <br>    // Load modelEntity transforms<br>    let modelEntityDataURL = self.worldMapDir.appendingPathComponent(&quot;ARExperience.json&quot;)<br>    <br>    do {<br>        let jsonData = try Data(contentsOf: modelEntityDataURL)<br>        if let modelEntityDetailsDict = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: [String]] {<br>            for (key, transformDetails) in modelEntityDetailsDict {<br>                let components = key.components(separatedBy: &quot;@&quot;)<br>                guard components.count == 2 else { continue }<br>                <br>                let modelName = components[0]<br>                let identifier = components[1]<br>                <br>                let anchorEntity = AnchorEntity()<br>                anchorEntity.name = identifier<br>                uiView.scene.addAnchor(anchorEntity)<br>                <br>                let modelEntity = try ModelEntity.loadModel(named: modelName + &quot;.usdz&quot;)<br>                modelEntity.transform.translation = parseVector3(transformDetails[0])<br>                modelEntity.transform.rotation = parseQuaternion(transformDetails[1])<br>                modelEntity.transform.scale = parseVector3(transformDetails[2])<br>                anchorEntity.addChild(modelEntity)<br>                <br>                for animation in modelEntity.availableAnimations {<br>                    modelEntity.playAnimation(animation.repeat())<br>                }<br>            }<br>        } else {<br>            print(&quot;Debug: Can&#39;t load map&quot;)<br>        }<br>    } catch {<br>        print(&quot;Debug: \(error.localizedDescription)&quot;)<br>    }<br>}</pre><p><strong>Summary: </strong>The load method in the AR persistence code loads saved AR anchors and model entity transforms. It retrieves the ARWorldMap from the saved data and uses it to initialize the ARWorldTrackingConfiguration, which is then used to run the AR session. It also retrieves the model entity transform details from the JSON data and creates corresponding anchor entities with model entities in the AR scene. The method enables animations for the loaded model entities.</p><h4><strong>Detailed Explanation:</strong></h4><p>Let’s break down the load functionality in detail:</p><ol><li>Define the URL for the stored AR anchors as a World Map. The file is named “ARExperience.map” and located in the worldMapDir directory.</li><li>Attempt to read the data from the anchorDataURL using Data(contentsOf:).</li><li>If the data is successfully loaded, try to unarchive it using NSKeyedUnarchiver.unarchivedObject(ofClass:from:) as an instance of ARWorldMap.</li><li>If the unarchiving is successful and the worldMap exists, create a new ARWorldTrackingConfiguration and set its initialWorldMap property to the loaded worldMap.</li><li>Run the AR session with the new configuration, specifying options to reset the tracking and remove any existing anchors.</li><li>If an error occurs during the loading process, print the error description for debugging purposes.</li><li>Define the URL for the stored model entity transforms as a JSON file. The file is named “ARExperience.json” and located in the worldMapDir directory.</li><li>Attempt to read the data from the modelEntityDataURL using Data(contentsOf:).</li><li>If the data is successfully loaded, try to deserialize it using JSONSerialization.jsonObject(with:options:) as a dictionary with string keys and array values.</li><li>If the deserialization is successful and the modelEntityDetailsDict exists, iterate through its key-value pairs.</li><li>Split each key into components using the “@” separator. Ensure that there are exactly two components; otherwise, skip the current iteration.</li><li>Extract the model name and identifier from the components.</li><li>Create a new AnchorEntity and set its name to the identifier.</li><li>Add the AnchorEntity to the AR scene using uiView.scene.addAnchor(_:).</li><li>Load the model entity using ModelEntity.loadModel(named:), appending the model name with the &quot;.usdz&quot; extension.</li><li>Set the translation, rotation, and scale of the model entity’s transformation using the parsed vector and quaternion values from the transformDetails array.</li><li>Add the model entity as a child of the AnchorEntity.</li><li>Play all available animations of the model entity in a repeating manner.</li><li>If the JSON deserialization fails or the modelEntityDetailsDict does not exist, print a debug message indicating the failure.</li><li>If an error occurs during the loading process, print the error description for debugging purposes.</li></ol><p>In summary, the load function loads the previously saved AR anchors from a World Map file and restores the corresponding model entity transforms from a JSON file. It sets up the AR session with the loaded world map, creates anchor entities, loads model entities, applies their transformations, and plays animations if available.</p><h3>Share AR Experience</h3><p>To share the AR experience with others, the generated .map and .json files can be shared. These files contain the necessary information to recreate the saved AR anchors and model entity transforms. By sharing these files, other users can load the same AR scene with the exact positions and transformations of virtual objects. This allows for a consistent and synchronized AR experience across multiple devices, enabling users to collaborate, explore, and interact with the same augmented environment. Whether it&#39;s for educational purposes, gaming, or remote assistance, sharing these files empowers users to share their AR creations and immerse others in their augmented reality world.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FRbT2sJ1q-Mc%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DRbT2sJ1q-Mc&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FRbT2sJ1q-Mc%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/9aeef66f34c032a083af1e9f8171c18d/href">https://medium.com/media/9aeef66f34c032a083af1e9f8171c18d/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=28911d5cac5b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AR Persistence with ARKit & RealityKit: AR with iOS (Part-VII)]]></title>
            <link>https://shiru99.medium.com/ar-persistence-with-arkit-realitykit-ar-with-ios-part-vii-2dfd4fda446c?source=rss-a19e9a6bab29------2</link>
            <guid isPermaLink="false">https://medium.com/p/2dfd4fda446c</guid>
            <category><![CDATA[realitykit]]></category>
            <category><![CDATA[arpersistence]]></category>
            <category><![CDATA[arkit]]></category>
            <category><![CDATA[persistence]]></category>
            <category><![CDATA[augmented-reality]]></category>
            <dc:creator><![CDATA[Shiru99]]></dc:creator>
            <pubDate>Thu, 22 Jun 2023 12:10:58 GMT</pubDate>
            <atom:updated>2023-06-22T12:27:03.338Z</atom:updated>
            <content:encoded><![CDATA[<p>AR persistence is a powerful feature that allows us to save and share augmented reality experiences in iOS applications. By leveraging ARKit and RealityKit, developers can create immersive AR content that persists across multiple sessions, enabling users to revisit their augmented experiences and share them with others. In this article, we will explore the concept of AR persistence, its benefits, and how to implement it in iOS apps. Discover the potential of AR persistence and unlock new possibilities for interactive and collaborative augmented reality.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FRbT2sJ1q-Mc%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DRbT2sJ1q-Mc&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FRbT2sJ1q-Mc%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/9aeef66f34c032a083af1e9f8171c18d/href">https://medium.com/media/9aeef66f34c032a083af1e9f8171c18d/href</a></iframe><h3>AR Persistence</h3><p>AR Persistence refers to the ability of an augmented reality (AR) application to save and retrieve virtual content in real-world locations across multiple sessions. It allows users to place virtual objects, annotations, or effects in the physical environment and have them remain in their designated positions when they return to the app later. This means that the virtual content becomes persistent and retains its spatial context, enabling users to interact with and share their augmented reality experiences over time. AR Persistence leverages technologies such as ARKit and RealityKit to accurately track and anchor virtual content in the real world, providing a seamless and continuous AR experience.</p><h4>ARWorldMap</h4><p>The ARWorldMap in ARKit represents a serialized representation of the AR session’s spatial mapping and anchor data. It captures the geometric and semantic information of the real-world environment, including detected surfaces, images, and the positions and orientations of ARAnchors.</p><p>The WorldMap is used for persistence, allowing you to save the state of an AR session and later load it to restore the previously mapped environment and placed ARAnchors. By saving and loading WorldMaps, you can preserve the spatial understanding of the scene and the positions of virtual objects, enabling a consistent AR experience across different sessions or devices.</p><p>While the WorldMap itself does not directly store the specifics of model entities or their properties, it provides the foundation for reconstructing the AR scene and can serve as a basis for loading and placing virtual content based on the stored anchor data.</p><p>In summary, the WorldMap is a crucial component in ARKit and RealityKit that allows for persistence by capturing the spatial mapping and anchor data of an AR session, facilitating the restoration of the environment and virtual content placement.</p><h3>ARPersistence Package</h3><pre>import SwiftUI<br>import RealityKit<br>import ARKit<br>import ARPersistence<br><br><br>struct ARViewContainer: UIViewRepresentable {<br>    @Binding var modelName: String?<br>    @Binding var isResetOn: Bool<br>    @Binding var isSaveOn: Bool<br>    @Binding var loadSaved: Bool<br>    <br>    func makeUIView(context: Context) -&gt; ARView {<br>        let arView = ARView(frame: UIScreen.main.bounds)<br>        arView.debugOptions.insert([.showWorldOrigin])<br>        return arView<br>    }<br>    <br>    <br>    func setPropertiesToModelEntity(_ uiView: ARView, _ modelEntity: ModelEntity) {<br>        modelEntity.transform.translation.x = 0<br>        <br>        modelEntity.generateCollisionShapes(recursive: false)<br>        uiView.installGestures([.rotation, .translation, .scale], for: modelEntity)<br>    }<br>    <br>    <br>    func place3DModel(_ uiView: ARView) {<br>        <br>        guard let modelName = modelName else {<br>            return<br>        }<br>        <br>        // AR Anchor<br>        let arAnchor = ARAnchor(name: modelName, transform: matrix_identity_float4x4)<br>        uiView.session.add(anchor: arAnchor)<br>        <br>        <br>        // Anchor Entitty<br>        let anchorEntity = AnchorEntity(anchor: arAnchor)<br>        anchorEntity.name = arAnchor.identifier.uuidString      // MUST<br>        uiView.scene.addAnchor(anchorEntity)<br>        <br>        <br>        // Model Entity<br>        let modelEntity: ModelEntity = try! ModelEntity.loadModel(named: modelName + &quot;.usdz&quot;)<br>        setPropertiesToModelEntity(uiView, modelEntity)<br>        anchorEntity.addChild(modelEntity)<br>    }<br><br>    <br>    func updateUIView(_ uiView: ARView, context: Context) {<br><br>        if(loadSaved){<br>            uiView.scene.anchors.removeAll()<br>            ARPersistence.shared.load(uiView)<br>            loadSaved.toggle()<br>            return<br>        }<br>        <br>        if(isSaveOn){<br>            ARPersistence.shared.save(uiView)<br>            isSaveOn.toggle()<br>            return<br>        }<br>        <br>        if(isResetOn){<br>            uiView.scene.anchors.removeAll()<br>            isResetOn.toggle()<br>            return<br>        }<br>        <br>        place3DModel(uiView)<br>    }<br>}</pre><p><strong>In summary</strong>, the code allows users to store AR anchors and model entity transformations in .map and .json files using ARPersistence package, enabling them to retrieve and load the saved state in future sessions. This provides persistence and continuity to the AR experience, allowing users to resume their augmented reality environment with the previously placed 3D models.</p><h4><strong>Explanation</strong></h4><p>Code demonstrates an AR experience using SwiftUI, RealityKit, ARKit, and ARPersistence. It allows users to place 3D models in the AR scene, reset the scene, save the current state, and load a previously saved state.</p><p>The ARViewContainer struct represents the AR view and conforms to UIViewRepresentable. It sets up the ARView and handles the placement of 3D models, resetting the scene, saving the state, and loading a saved state using the ARPersistence library.</p><p>The saveState function saves the current AR anchors and model entity transformations by calling the save method from the ARPersistence library, which stores the data in .map and .json files.</p><p>The loadState function retrieves the previously saved AR anchors and model entity transformations by calling the load method from the ARPersistence library, which loads the data from the .map and .json files and applies it to the AR scene.</p><p>The updateUIView function is responsible for the main functionality. It checks the state of the isSaveOn, isResetOn, and loadSaved flags to determine whether to save the state, reset the scene, or load a saved state. If none of these flags are active, it calls the place3DModel function to place the selected 3D model in the AR scene.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oXdxGILCwARrnAGKW4PP7A.jpeg" /></figure><p><em>More Details about package</em> — <a href="https://iosexample.com/ar-persistence-with-arkit-and-realitykit/">ARPersistence</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2dfd4fda446c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Occlusion, Material with ARKit & RealityKit: AR with iOS (Part-VI)]]></title>
            <link>https://shiru99.medium.com/occlusion-material-with-arkit-realitykit-ar-with-ios-part-vi-a1d92c03cc82?source=rss-a19e9a6bab29------2</link>
            <guid isPermaLink="false">https://medium.com/p/a1d92c03cc82</guid>
            <category><![CDATA[ar]]></category>
            <category><![CDATA[materials]]></category>
            <category><![CDATA[realitykit]]></category>
            <category><![CDATA[occlusions]]></category>
            <category><![CDATA[arkit]]></category>
            <dc:creator><![CDATA[Shiru99]]></dc:creator>
            <pubDate>Wed, 21 Jun 2023 18:32:09 GMT</pubDate>
            <atom:updated>2023-06-21T18:32:09.331Z</atom:updated>
            <content:encoded><![CDATA[<p>In this article, we will explore how to implement occlusion and material in AR using SwiftUI and RealityKit, two powerful and user-friendly frameworks provided by Apple. We will start with a brief introduction to the main concepts and tools, and then we will dive into the code and build a simple AR app that showcases the capabilities of occlusion and material. So let’s get started and unleash the full potential of AR!</p><h3>Occlusion</h3><p>Occlusion refers to the ability of virtual objects to hide behind real-world objects in the scene, as if they were behind a physical barrier. Occlusion helps to create a sense of depth and realism, and it requires precise tracking and depth sensing, as well as accurate geometry and lighting of the virtual content.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/941/1*DBvThQCv48nTO638CKAk-w.png" /><figcaption>Occlusion</figcaption></figure><pre>// occlusion<br>self.environment.sceneUnderstanding.options.insert(.occlusion) </pre><pre>import SwiftUI<br>import RealityKit<br>import ARKit<br>import FocusEntity<br>import Combine<br><br>struct ContentView: View {<br>    <br>    var body: some View {<br>        ZStack(alignment: .bottom) {<br>            CustomARViewContainer()<br>            <br>            Button(action: {<br>                ActionManager.shared.actionStream.send(.place3DModel)<br>            }, label: {<br>                Text(&quot;Place 3D Model&quot;)<br>                    .font(.headline)<br>                    .foregroundColor(.white)<br>                    .padding()<br>                    .background(Color.blue)<br>                    .cornerRadius(10)<br>            })<br>            .padding(.bottom, 50)<br>        }<br>    }<br>}<br><br>struct CustomARViewContainer: UIViewRepresentable {<br>    <br>    func makeUIView(context: Context) -&gt; CustomARView {<br>        return CustomARView()<br>    }<br>    <br>    func updateUIView(_ uiView: CustomARView, context: Context) {}<br>}<br><br><br><br>class CustomARView: ARView {<br>    <br>    var focusEntity: FocusEntity?<br>    var cancellables: Set&lt;AnyCancellable&gt; = []<br>    <br>    init() {<br>        super.init(frame: .zero)<br>        <br>        // ActionStrean<br>        subscribeToActionStream()<br>        <br>        // FocusEntity<br>        self.focusEntity = FocusEntity(on: self, style: .classic(color: .yellow))<br>        <br>        // Configuration<br>        let config = ARWorldTrackingConfiguration()<br>        config.planeDetection = [.horizontal]<br>        config.environmentTexturing = .automatic<br>        <br>        if ARWorldTrackingConfiguration.supportsSceneReconstruction(.meshWithClassification) {<br>            config.sceneReconstruction = .meshWithClassification<br>        }<br>        <br>        // occlusion<br>        self.environment.sceneUnderstanding.options.insert(.occlusion)<br>        <br>        self.session.run(config)<br>    }<br><br>    <br>    func place3DModel() {<br>        guard let focusEntity = self.focusEntity else { return }<br><br>        let modelEntity = try! ModelEntity.load(named: &quot;toy_car.usdz&quot;)<br>        let anchorEntity = AnchorEntity(world: focusEntity.position)<br>        anchorEntity.addChild(modelEntity)<br>        self.scene.addAnchor(anchorEntity)<br>    }<br>    <br>    <br>    func subscribeToActionStream() {<br>        ActionManager.shared<br>            .actionStream<br>            .sink { [weak self] action in<br>                <br>                switch action {<br>                    <br>                case .place3DModel:<br>                    self?.place3DModel()<br>                    <br>                case .remove3DModel:<br>                    print(&quot;Removeing 3D model: has not been implemented&quot;)<br>                }<br>            }<br>            .store(in: &amp;cancellables)<br>    }<br>    <br>    @MainActor required dynamic init?(coder decoder: NSCoder) {<br>        fatalError(&quot;init(coder:) has not been implemented&quot;)<br>    }<br>    <br>    @MainActor required dynamic init(frame frameRect: CGRect) {<br>        fatalError(&quot;init(frame:) has not been implemented&quot;)<br>    }<br>}<br><br>enum Actions {<br>    case place3DModel<br>    case remove3DModel<br>}<br><br>class ActionManager {<br>    static let shared = ActionManager()<br>    <br>    private init() { }<br>    <br>    var actionStream = PassthroughSubject&lt;Actions, Never&gt;()<br>}</pre><p><strong>Functionality</strong>: This code sets up an AR view using SwiftUI and RealityKit that allows the user to place a 3D model in their real-world environment. The CustomARView class is a subclass of ARView that sets up the AR session and adds a yellow focus indicator for the user to interact with. When the user taps the &quot;Place 3D Model&quot; button, it triggers the place3DModel() function which loads a 3D model of a toy car and places it in the real-world environment at the position of the focus indicator.</p><p>The occlusion feature is implemented by adding the .occlusion option to the sceneUnderstanding.options of the CustomARView. This tells the ARKit to recognize and track the depth of the real-world objects and use that information to hide the virtual objects. The end result is a more realistic augmented reality experience where virtual objects interact seamlessly with the real world.</p><p>The ActionManager class is used to manage the user&#39;s actions and communicates them between different parts of the code. It uses a PassthroughSubject to send and receive actions. The subscribeToActionStream() function is called to listen for new actions being sent and performs the appropriate action, either placing or removing a 3D model.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/740/1*xMAdzlSfQtBWl5HXvKvy6A.jpeg" /><figcaption>Occlusion</figcaption></figure><h3>Material</h3><p>Material refers to the appearance and properties of the virtual objects, such as their color, texture, reflectivity, and transparency. Material is crucial for making the virtual content blend seamlessly with the real-world environment, and it can also convey meaning and emotion through visual cues.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Lm6ZpaVbddMeE2z90iitBg.png" /><figcaption>Metallic Material</figcaption></figure><pre>    func place3DModel() {<br>        guard let focusEntity = self.focusEntity else { return }<br><br>        let modelEntity = try! ModelEntity.load(named: &quot;toy_drummer_idle.usdz&quot;)<br>        <br>        // adding material<br>        var metal = SimpleMaterial(color: .clear, isMetallic: true)<br>        metal.metallic = 1.0<br>        modelEntity.model?.materials.append(metal)<br><br>        let anchorEntity = AnchorEntity(world: focusEntity.position)<br>        anchorEntity.addChild(modelEntity)<br>        self.scene.addAnchor(anchorEntity)<br>    }</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ccO-_p-z_pQWepWpBquWKQ.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a1d92c03cc82" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AR with iOS — SwiftUI, ARKit & RealityKit (Part-V)]]></title>
            <link>https://shiru99.medium.com/ar-with-ios-swiftui-arkit-realitykit-part-v-c3c89ad95b38?source=rss-a19e9a6bab29------2</link>
            <guid isPermaLink="false">https://medium.com/p/c3c89ad95b38</guid>
            <category><![CDATA[ar]]></category>
            <category><![CDATA[focusentity]]></category>
            <category><![CDATA[arkit]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[plane-detection]]></category>
            <dc:creator><![CDATA[Shiru99]]></dc:creator>
            <pubDate>Sat, 29 Apr 2023 18:28:30 GMT</pubDate>
            <atom:updated>2023-06-21T13:31:41.344Z</atom:updated>
            <content:encoded><![CDATA[<h3>Plane Detection, 3D model placement &amp; FocusEntity with ARKit &amp; RealityKit: AR with iOS (Part-V)</h3><p>Let’s get started with placing a 3D object on a horizontal or vertical plane using ARKit. With ARKit, we can detect the plane and add different user interactions to the 3D object. We can also explore the 3D model properties like animations or audio/video associated with them.</p><h3>Plane Detection</h3><p>When we use an AR app, we want to make sure that the virtual objects we place in the real world stay in place and move realistically as we move around them. The way we do this is by using something called “world tracking”.</p><p>World tracking configuration is like a tool that helps our app to understand and interact with the world around it. One of the things it can do is to detect flat surfaces in the real world, like a table or a floor. It does this by using the camera on our device to create a map of the area and then looking for places where the map is flat.</p><p>Once it detects a flat surface, it can add a virtual object on top of it, making it look like the object is sitting right there in the real world</p><blockquote>ARWorldTrackingConfiguration is a class provided by ARKit framework that specifies the configuration and options for an AR session that uses the device’s motion and camera to track the device’s position and orientation relative to the world around it. It allows for high-quality AR experiences, as it uses 6DoF (six degrees of freedom) tracking to track the device’s position and orientation in 3D space.</blockquote><pre>import SwiftUI<br>import RealityKit<br>import ARKit<br><br>struct ContentView : View {<br>    <br>    var body: some View {<br>        CustomARViewContainer()<br>    }<br>}<br><br>struct CustomARViewContainer: UIViewRepresentable {<br>    <br>    func makeUIView(context: Context) -&gt; CustomARView {<br>        return CustomARView()<br>    }<br>    <br>    func updateUIView(_ uiView: CustomARView, context: Context) { }<br>}<br><br><br>class CustomARView: ARView {<br>    <br>    init() {<br>        super.init(frame: .zero)<br><br>        let config = ARWorldTrackingConfiguration()<br>        config.planeDetection = [.horizontal]<br>        config.environmentTexturing = .automatic<br><br>        if ARWorldTrackingConfiguration.supportsSceneReconstruction(.meshWithClassification) {<br>            config.sceneReconstruction = .meshWithClassification<br>        }<br><br>        self.session.run(config)<br>    }<br>}</pre><p>In this part of the code, we create a configuration object for ARKit’s world tracking system. The ARWorldTrackingConfiguration is a class that encapsulates various settings for ARKit&#39;s tracking capabilities, such as the types of features to detect and track, the environment texture mapping, and scene reconstruction.</p><p>Here, we set the planeDetection property to [.horizontal], which means that we want ARKit to detect horizontal planes such as tables, floors, and other flat surfaces in the environment. The environmentTexturing property is set to .automatic, which means that ARKit will automatically create an environment map to blend virtual objects with the real-world environment.</p><p>Next, we check if the device supports scene reconstruction with the depth information from a LiDAR sensor. The LiDAR sensor can measure the distance between the device and objects in the environment with high accuracy and speed, allowing ARKit to reconstruct a detailed 3D mesh of the environment. If the device supports this feature, we set the sceneReconstruction property of the configuration to .meshWithClassification, which means that ARKit will generate a mesh with classification information, allowing us to place virtual objects on surfaces with more accuracy.</p><p>It’s worth noting that not all iPhones have LiDAR sensors, which means that some devices may not support the scene reconstruction feature with depth information. In such cases, ARKit will still work but with lower accuracy and precision.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Kb3mhfdloEHBuFmNRD7OBw.png" /><figcaption>Plane detection &amp; Scene reconstruction</figcaption></figure><h3><strong>FocusEntity</strong></h3><p>Once we detect a plane in the AR scene, the FocusEntity helps to guide the user’s attention to the detected plane by displaying a visual cue, such as a crosshair or a circle, on the detected plane. This visual cue helps to inform the user that they can interact with the AR content on the detected plane.</p><p>Additionally, the FocusEntity provides functionality for adding AR content onto the detected plane. For example, if we want to place a 3D model onto the detected plane, we can use the FocusEntity to ensure that the 3D model is placed correctly on the plane and also provide visual feedback to the user as they move the 3D model around on the plane.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/768/1*mt_aiJgVgrAWYxSPoFw3Eg.gif" /><figcaption>FocusEntity (<a href="https://github.com/maxxfrazer/FocusEntity">https://github.com/maxxfrazer/FocusEntity</a>)</figcaption></figure><p>Here are the steps you can follow to ensure that the FocusEntity package is properly integrated in your Xcode project:</p><ol><li>Add FocusEntity package to project. To do this, go to File -&gt; Swift Packages -&gt; Add Package Dependency and enter the package repository URL: <a href="https://github.com/maxxfrazer/FocusEntity">https://github.com/maxxfrazer/FocusEntity</a>.</li><li>Check if the package is listed under your project’s dependencies in the Project navigator. If it’s not there, try adding it again.</li></ol><pre>import SwiftUI<br>import RealityKit<br>import ARKit<br>import FocusEntity<br><br>struct ContentView : View {<br>    <br>    var body: some View {<br>        CustomARViewContainer()<br>    }<br>}<br><br>struct CustomARViewContainer: UIViewRepresentable {<br>    <br>    func makeUIView(context: Context) -&gt; CustomARView {<br>        return CustomARView()<br>    }<br>    <br>    func updateUIView(_ uiView: CustomARView, context: Context) { }<br>}<br><br><br>class CustomARView: ARView {<br>    <br>    var focusEntity: FocusEntity?<br>    <br>    init() {<br>        super.init(frame: .zero)<br>        <br>        self.setUpFocusEntity()<br>        self.setUpARView()<br>    }<br>    <br>    func setUpFocusEntity() {<br>        self.focusEntity = FocusEntity(on: self, style: .classic(color: .yellow))<br>    }<br>    <br>    func setUpARView() {<br>        let config = ARWorldTrackingConfiguration()<br>        config.planeDetection = [.horizontal]<br>        config.environmentTexturing = .automatic<br>        <br>        if ARWorldTrackingConfiguration.supportsSceneReconstruction(.meshWithClassification) {<br>            config.sceneReconstruction = .meshWithClassification<br>        }<br><br>        self.session.run(config)<br>    }<br>}</pre><p>The FocusEntity package provides a lot of customization options that can be used to change the appearance and behavior of the focus square in your AR app. For example, you can change the color of the focus square, adjust its size and animation, and even add 3D objects to it. More Details - <a href="https://github.com/maxxfrazer/FocusEntity">GitHub</a></p><h3>Placing 3D model on plane</h3><pre>import SwiftUI<br>import RealityKit<br>import ARKit<br>import FocusEntity<br>import Combine<br><br>struct ContentView: View {<br>    <br>    var body: some View {<br>        ZStack(alignment: .bottom) {<br>            CustomARViewContainer()<br>            <br>            Button(action: {<br>                ActionManager.shared.actionStream.send(.place3DModel)<br>            }, label: {<br>                Text(&quot;Place 3D Model&quot;)<br>                    .font(.headline)<br>                    .foregroundColor(.white)<br>                    .padding()<br>                    .background(Color.blue)<br>                    .cornerRadius(10)<br>            })<br>            .padding(.bottom, 50)<br>        }<br>    }<br>}<br><br>struct CustomARViewContainer: UIViewRepresentable {<br>    <br>    func makeUIView(context: Context) -&gt; CustomARView {<br>        return CustomARView()<br>    }<br>    <br>    func updateUIView(_ uiView: CustomARView, context: Context) {}<br>}<br><br><br><br>class CustomARView: ARView {<br>    <br>    var focusEntity: FocusEntity?<br>    var cancellables: Set&lt;AnyCancellable&gt; = []<br>    <br>    init() {<br>        super.init(frame: .zero)<br>        <br>        // ActionStrean<br>        subscribeToActionStream()<br>        <br>        // FocusEntity<br>        self.focusEntity = FocusEntity(on: self, style: .classic(color: .yellow))<br>        <br>        // Configuration<br>        let config = ARWorldTrackingConfiguration()<br>        config.planeDetection = [.horizontal]<br>        config.environmentTexturing = .automatic<br>        <br>        if ARWorldTrackingConfiguration.supportsSceneReconstruction(.meshWithClassification) {<br>            config.sceneReconstruction = .meshWithClassification<br>        }<br>        <br>        self.session.run(config)<br>    }<br><br>    <br>    func place3DModel() {<br>        guard let focusEntity = self.focusEntity else { return }<br><br>        let modelEntity = try! ModelEntity.load(named: &quot;toy_car.usdz&quot;)<br>        let anchorEntity = AnchorEntity(world: focusEntity.position)<br>        anchorEntity.addChild(modelEntity)<br>        self.scene.addAnchor(anchorEntity)<br>    }<br>    <br>    <br>    func subscribeToActionStream() {<br>        ActionManager.shared<br>            .actionStream<br>            .sink { [weak self] action in<br>                <br>                switch action {<br>                    <br>                case .place3DModel:<br>                    self?.place3DModel()<br>                    <br>                case .remove3DModel:<br>                    print(&quot;Removeing 3D model: has not been implemented&quot;)<br>                }<br>            }<br>            .store(in: &amp;cancellables)<br>    }<br>    <br>    @MainActor required dynamic init?(coder decoder: NSCoder) {<br>        fatalError(&quot;init(coder:) has not been implemented&quot;)<br>    }<br>    <br>    @MainActor required dynamic init(frame frameRect: CGRect) {<br>        fatalError(&quot;init(frame:) has not been implemented&quot;)<br>    }<br>}<br><br>enum Actions {<br>    case place3DModel<br>    case remove3DModel<br>}<br><br>class ActionManager {<br>    static let shared = ActionManager()<br>    <br>    private init() { }<br>    <br>    var actionStream = PassthroughSubject&lt;Actions, Never&gt;()<br>}</pre><p><strong>Functionality</strong>: When the user taps on the Button, the place3DModel function is called and a ModelEntity of a toy car is loaded and placed at the position of the FocusEntity.</p><p><em>You can ignore the functionality of </em><em>ActionManager it simply let the button action call </em><em>place3DModel directly.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NQ7YU6dU24bNp8fUP4NkdA.png" /><figcaption>Placing 3D on plane (IKEA Place)</figcaption></figure><h4>Tap Gesture Code Explanation:</h4><p>This code defines a SwiftUI ContentView that contains an AR view and a button labeled “Place 3D Model”. Tapping the button sends a message to the ActionManager’s shared PassthroughSubject, which is subscribed to by the CustomARView. When the action stream sends the “place3DModel” action, the CustomARView creates a ModelEntity from a 3D model file, creates an AnchorEntity at the position of the FocusEntity (a component for ARKit that helps with positioning objects in AR), adds the ModelEntity as a child of the AnchorEntity, and adds the AnchorEntity to the scene. The CustomARView also sets up an AR session with plane detection and environment texturing, and subscribes to the action stream to handle the “place3DModel” action.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c3c89ad95b38" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AR with iOS — SwiftUI, ARKit & RealityKit (Part-IV)]]></title>
            <link>https://shiru99.medium.com/ar-with-ios-swiftui-arkit-realitykit-part-iv-d05b0f23dc6c?source=rss-a19e9a6bab29------2</link>
            <guid isPermaLink="false">https://medium.com/p/d05b0f23dc6c</guid>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[gestures]]></category>
            <category><![CDATA[arkit]]></category>
            <category><![CDATA[ar]]></category>
            <dc:creator><![CDATA[Shiru99]]></dc:creator>
            <pubDate>Sat, 29 Apr 2023 18:27:08 GMT</pubDate>
            <atom:updated>2023-06-21T13:29:56.893Z</atom:updated>
            <content:encoded><![CDATA[<h3>AR gestures with ARKit &amp; RealityKit: AR with iOS (Part-IV)</h3><h3>AR gestures</h3><p>AR gestures are interactions and movements made by users in an Augmented Reality (AR) environment to manipulate AR objects or interact with AR content.</p><p>In the context of AR with iOS, AR gestures can be used to enable users to interact with virtual objects overlaid on the real world through intuitive gestures.</p><p>Some common AR gestures</p><ol><li><strong>Tap Gesture</strong>: Users can tap on virtual objects to select or interact with them. For example, tapping on a virtual button to trigger an action, or tapping on a virtual object to rotate or scale it.</li><li><strong>Pan Gesture</strong>: Users can use a pan gesture to move virtual objects in the AR environment. For example, dragging a virtual object to reposition it in the real world.</li><li><strong>Pinch Gesture</strong>: Users can use a pinch gesture to scale virtual objects. For example, pinching on a virtual object to resize it or zoom in/out.</li><li><strong>Rotation Gesture</strong>: Users can use a rotation gesture to rotate virtual objects. For example, rotating a virtual object with two fingers to change its orientation or alignment.</li><li><strong>Long-Press Gesture</strong>: Users can use a long-press gesture to trigger actions or interactions with virtual objects. For example, long-pressing on a virtual button to reveal additional options or information.</li><li><strong>Swipe Gesture</strong>: Users can use swipe gestures to trigger specific actions or interactions with virtual objects. For example, swiping left or right on a virtual object to get different colour variant of virtual object.</li></ol><p>The implementation of AR gestures may require handling touch events, gesture recognizers, or other APIs provided by ARKit and RealityKit frameworks</p><h3>AR gestures on ARViewContainer</h3><pre>import SwiftUI<br>import RealityKit<br><br>struct ContentView : View {<br>    <br>    var body: some View {<br>        ARViewContainer()<br>            .gesture(TapGesture().onEnded {<br>                // Handle tap gesture here<br>                print(&quot;Tap gesture detected&quot;)<br>            })<br>            .gesture(DragGesture().onChanged { value in<br>                // Handle drag gesture here<br>                print(&quot;Drag gesture detected: \(value.translation)&quot;)<br>            })<br>            .gesture(MagnificationGesture().onChanged { value in<br>                // Handle pinch gesture here<br>                print(&quot;Pinch gesture detected: \(value.magnitude)&quot;)<br>            })<br>            .gesture(RotationGesture().onChanged { value in<br>                // Handle rotation gesture here<br>                print(&quot;Rotation gesture detected: \(value.degrees)&quot;)<br>            })<br>    }<br>}<br><br>struct ARViewContainer: UIViewRepresentable {<br>    <br>    func makeUIView(context: Context) -&gt; ARView {<br>        let arView = ARView(frame: .zero)<br>        <br>        // Load the model from the app&#39;s asset catalog<br>        let modelEntity = try! ModelEntity.load(named: &quot;toy_car.usdz&quot;)<br>        <br>        // Create an anchor entity and add the model to it<br>        let anchorEntity = AnchorEntity()<br>        anchorEntity.addChild(modelEntity)<br>        <br>        // Set the position of the anchor entity to 1 meter in front of the camera<br>        anchorEntity.position = [0, 0, -1]<br>        <br>        // Add the anchor entity to the scene<br>        arView.scene.addAnchor(anchorEntity)<br>        <br>        return arView<br>    }<br>    <br>    func updateUIView(_ uiView: ARView, context: Context) { }<br>}</pre><p><strong>Code Explanation</strong></p><p>The code provided demonstrates how to implement AR gestures (tap, drag, pinch, and rotation) on an AR view in SwiftUI using RealityKit.</p><ol><li>ARViewContainer is a UIViewRepresentable that creates an ARView and loads a 3D model (in this case, &quot;toy_car.usdz&quot;) from the app&#39;s asset catalog. It creates an anchor entity, adds the model as its child, sets the position of the anchor entity to 1 meter in front of the camera, and adds the anchor entity to the AR scene.</li><li>In ContentView, an instance of ARViewContainer is added as a subview. Then, gesture recognizers (TapGesture, DragGesture, MagnificationGesture, and RotationGesture) are attached to the AR view using SwiftUI&#39;s .gesture() modifier.</li><li>The .onEnded and .onChanged closures within each gesture recognizer handle the corresponding gestures. For example, when a tap gesture is detected, it prints a message &quot;Tap gesture detected&quot;. When a drag gesture is detected, it prints the translation of the drag. When a pinch gesture is detected, it prints the magnitude of the pinch. When a rotation gesture is detected, it prints the degrees of rotation.</li></ol><h3>Issue with gestures on ARViewContainer</h3><pre>.gesture(DragGesture().onChanged { value in<br>    // Update the position of the modelEntity based on the translation value<br>    modelEntity.position += SIMD3&lt;Float&gt;(value.translation.width, value.translation.height, 0)<br>})</pre><p>This code adds a DragGesture to an ARViewContainer screen in a SwiftUI app. The position of a modelEntity is updated based on the horizontal and vertical translation values of the drag gesture. The modelEntity.position is updated by adding the translation values to its current position using the += operator, resulting in interactive manipulation of the model&#39;s position in the scene based on the user&#39;s pan gesture.</p><p>The issue is that if you drag on any part of the ARViewContainer where the modelEntity is not even available, the modelEntity will be updated, and the position of modelEntity will change accordingly.</p><p><em>What will happen if we get multiple modelEntities placed in ARView? </em><strong>gestures on modelEntity</strong></p><h3>Gestures on modelEntity</h3><p>This allows the user to interact with the model by performing gestures such as rotation, translation (pan), and scaling (pinch) using touch or other input methods.</p><pre>import SwiftUI<br>import RealityKit<br><br><br>struct ContentView : View {<br>    <br>    var body: some View {<br>        ARViewContainer()<br>    }<br>}<br><br>struct ARViewContainer: UIViewRepresentable {<br>    <br>    func makeUIView(context: Context) -&gt; ARView {<br>        let arView = ARView(frame: .zero)<br>        <br>        // Load the model from the app&#39;s asset catalog<br>        let modelEntity = try! ModelEntity.load(named: &quot;toy_car.usdz&quot;)<br>        <br>        // Create an anchor entity and add the model to it<br>        let anchorEntity = AnchorEntity()<br>        anchorEntity.addChild(modelEntity)<br>        <br>        // Set the position of the anchor entity to 1 meter in front of the camera<br>        anchorEntity.position = [0, 0, -1]<br>        <br>        // Add the anchor entity to the scene<br>        arView.scene.addAnchor(anchorEntity)<br>        <br>        // Install gestures on the modelEntity<br>        arView.installGestures([.rotation, .translation, .scale], for: modelEntity as! HasCollision)<br>        <br>        return arView<br>    }<br>    <br>    func updateUIView(_ uiView: ARView, context: Context) { }<br>}</pre><p>Overall, this code sets up an AR scene with a 3D model of a toy car and enables user interaction with the model through gestures in the ARView.</p><p>With Gestures on modelEntity, even if you place multiple 3D models, the user interaction with the models will be smooth.</p><h3>Custom Gestures within CustomARView</h3><p>[Note: same can be achieved with AR gestures on ARViewContainer]</p><pre>import SwiftUI<br>import RealityKit<br><br>struct ContentView : View {<br>    <br>    var body: some View {<br>        CustomARViewContainer()<br>    }<br>}<br><br>struct CustomARViewContainer: UIViewRepresentable {<br>    <br>    func makeUIView(context: Context) -&gt; CustomARView {<br>        return CustomARView()<br>    }<br>    <br>    func updateUIView(_ uiView: CustomARView, context: Context) { }<br>}<br><br><br>class CustomARView: ARView {<br>    <br>    init() {<br>        super.init(frame: .zero)<br><br>        let modelEntity = try! ModelEntity.loadModel(named: &quot;toy_car.usdz&quot;)<br><br>        let anchorEntity = AnchorEntity()<br>        anchorEntity.addChild(modelEntity)<br>        <br>        anchorEntity.position = [0, 0, -1]<br><br>        self.scene.addAnchor(anchorEntity)<br>        <br>        self.installGestures([.rotation, .translation, .scale], for: modelEntity as! HasCollision)<br>        <br>        let longpress = UILongPressGestureRecognizer(target: self, action: #selector(self.handleLongPress(_:)))<br>        self.addGestureRecognizer(longpress)<br>    }<br>    <br>    <br>    @objc func handleLongPress(_ recognizer: UITapGestureRecognizer? = nil) {<br><br>        guard let touchInView = recognizer?.location(in: self) else {<br>            return<br>        }<br><br>        guard let modelEntity = self.entity(at: touchInView) as? ModelEntity else {<br>            print(&quot;modelEntity not found&quot;)<br>            return<br>        }<br>        <br>        print(&quot;Long press detected on - \(modelEntity.name)&quot;)<br>        <br>    }<br>}</pre><p>Explanation : In this code, the long press gesture is set up to recognize when the user long presses on a 3D model loaded into the ARView. When a long press is detected, the code uses the entity(at: ) method to get the 3D entity (ModelEntity) at the location where the user long pressed on the screen. If the entity exists, the code prints out the name of the 3D model that was long pressed.</p><p>This code is useful when you want to perform an action when the user interacts with a 3D object in your AR app. For example, you could use this code to detect when the user selects a 3D object and display additional information or trigger an animation.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d05b0f23dc6c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AR with iOS — SwiftUI, ARKit & RealityKit (Part-III)]]></title>
            <link>https://shiru99.medium.com/ar-with-ios-swiftui-arkit-realitykit-part-iii-a7dd8abe64c?source=rss-a19e9a6bab29------2</link>
            <guid isPermaLink="false">https://medium.com/p/a7dd8abe64c</guid>
            <category><![CDATA[usdz]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[arkit]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[ar]]></category>
            <dc:creator><![CDATA[Shiru99]]></dc:creator>
            <pubDate>Sat, 29 Apr 2023 18:26:00 GMT</pubDate>
            <atom:updated>2023-06-21T13:28:46.056Z</atom:updated>
            <content:encoded><![CDATA[<h3>3D USDZ Models with ARKit &amp; RealityKit : AR with iOS (Part-III)</h3><h3>3D USDZ Models</h3><blockquote>what is usdz : USDZ is a file format developed by Pixar and Apple for sharing and displaying 3D content in AR and VR environments. It’s based on Pixar’s Universal Scene Description (USD), and is designed to be lightweight and efficient. USDZ files can contain 3D models, textures, animations, and other assets needed to render a complete 3D scene.</blockquote><blockquote>ARKit is a framework developed by Apple for building AR apps on iOS devices. While USDZ is the recommended format for creating and sharing 3D models in ARKit, the framework also supports other common 3D file formats such as OBJ, Collada (DAE), and Alembic (ABC).</blockquote><blockquote>Using USDZ format can have advantages over other formats, such as improved performance, better support for materials and lighting, and easier integration with Apple’s Quick Look and Reality Composer tools. Additionally, USDZ models can be easily previewed in AR using the Quick Look feature on iOS devices.</blockquote><h4>Some Resources for free USDZ models</h4><ol><li>Apple’s USDZ Sample Gallery: <a href="https://developer.apple.com/augmented-reality/quick-look/">https://developer.apple.com/augmented-reality/quick-look/</a></li><li>Sketchfab: <a href="https://sketchfab.com/">https://sketchfab.com/</a></li><li>TurboSquid: <a href="https://www.turbosquid.com/">https://www.turbosquid.com/</a></li><li>CGTrader: <a href="https://www.cgtrader.com/">https://www.cgtrader.com/</a></li><li>Free3D: <a href="https://free3d.com/">https://free3d.com/</a></li><li>Or one can convert other 3D model formats to USDZ using <a href="https://developer.apple.com/news/?id=01132020a">Reality Converter</a></li></ol><h3>Adding 3D Model in project</h3><ol><li>First create Assets folder in project</li><li>Download add few USDZ models from <a href="https://developer.apple.com/augmented-reality/quick-look/">Apple’s official site</a> or any other source</li><li>Add these USDZ models in Assets with “File” &gt; “Add Files to …” &gt; select USDZ files &gt; “Add”</li><li>Similarly, we can add images in Assests.xcassets as icons for these USDZ models</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*i3DDqvYmIhyGilz8YwhRnQ.png" /></figure><h3>Few AR Concepts</h3><ul><li>ARViewContainer: This is a UIViewRepresentable that wraps the ARView from the RealityKit framework. The ARView is the main view for displaying augmented reality content, and the ARViewContainer is responsible for managing the creation and updating of the view.</li><li>ModelEntity: This is a type from the RealityKit framework that represents a 3D model that can be added to the augmented reality scene. It is loaded from a file using the load(named:) method.</li><li>AnchorEntity: This is a type from the RealityKit framework that represents a position and orientation in the augmented reality scene. A ModelEntity can be added as a child of an AnchorEntity to place it in the scene. The AnchorEntity is added to the ARView&#39;s scene using the addAnchor(_:) method.</li></ul><h3>Code Explanation</h3><h4>overview</h4><p>When the user selects a model, the corresponding 3D model is loaded using ModelEntity and added to an AnchorEntity. The AnchorEntity is then positioned 1 meter in front of the camera and added to the AR view scene.</p><pre>import SwiftUI<br>import RealityKit<br><br>struct ContentView : View {<br>    <br>    let modelNames = [&quot;toy_car&quot;, &quot;robot_walk_idle&quot;, &quot;toy_biplane_idle&quot;, &quot;toy_drummer_idle&quot;]<br>    <br>    // State variable for selected model index<br>    @State private var selectedModelIndex = 0<br>    <br>    var body: some View {<br>        VStack {<br>            // AR view container with selected model<br>            ARViewContainer(modelName: modelNames[selectedModelIndex])<br>                .frame(height: 400)<br>            <br>            // Picker for selecting the model<br>            Picker(&quot;Select Model&quot;, selection: $selectedModelIndex) {<br>                ForEach(0 ..&lt; modelNames.count) { index in<br>                    Image(modelNames[index])<br>                        .resizable()<br>                        .frame(width: 50, height: 50)<br>                        .tag(index)<br>                }<br>            }<br>            .pickerStyle(SegmentedPickerStyle())<br>        }<br>    }<br>}<br><br>struct ARViewContainer: UIViewRepresentable {<br>    let modelName: String<br>    <br>    func makeUIView(context: Context) -&gt; ARView {<br>        let arView = ARView(frame: .zero)<br>        return arView<br>    }<br>    <br>    func updateUIView(_ uiView: ARView, context: Context) {<br>        // Remove any existing anchor entities from the scene<br>        uiView.scene.anchors.removeAll()<br>        <br>        // Load the model from the app&#39;s asset catalog<br>        let modelEntity = try! ModelEntity.load(named: modelName + &quot;.usdz&quot;)<br>        <br>        // Create an anchor entity and add the model to it<br>        let anchorEntity = AnchorEntity()<br>        anchorEntity.addChild(modelEntity)<br>        <br>        // Set the position of the anchor entity to 1 meter in front of the camera<br>        anchorEntity.position = [0, 0, -1]<br>        <br>        // Add the anchor entity to the scene<br>        uiView.scene.addAnchor(anchorEntity)<br>    }<br>}</pre><p>The ARView is initially empty when the app is launched, and the user needs to select a model from the Picker for it to be displayed in the ARView. The selected model is displayed at the position of the AnchorEntity which is 1 meter in front of the camera, and the user can move the camera to view the model from different angles and distances.</p><p>The ARViewContainer struct creates an instance of ARView, which is a UIView subclass provided by RealityKit. The makeUIView method returns the ARView instance when the view is created, and the updateUIView method is called to update the view. This method removes any existing anchor entities from the scene, loads the model from the app’s asset catalog, creates an anchor entity, adds the model to the anchor entity, sets the position of the anchor entity to 1 meter in front of the camera, and adds the anchor entity to the scene.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a7dd8abe64c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AR with iOS — SwiftUI, ARKit & RealityKit (Part-II)]]></title>
            <link>https://shiru99.medium.com/ar-with-ios-swiftui-arkit-realitykit-part-ii-b7f88f2c14b?source=rss-a19e9a6bab29------2</link>
            <guid isPermaLink="false">https://medium.com/p/b7f88f2c14b</guid>
            <category><![CDATA[realitykit]]></category>
            <category><![CDATA[ar]]></category>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[arkit]]></category>
            <dc:creator><![CDATA[Shiru99]]></dc:creator>
            <pubDate>Sat, 29 Apr 2023 18:25:09 GMT</pubDate>
            <atom:updated>2023-06-21T13:26:16.325Z</atom:updated>
            <content:encoded><![CDATA[<h3>ARKit &amp; RealityKit with SwiftUI : AR with iOS (Part-II)</h3><p>Augmented Reality (AR) is a technology that blends virtual objects and information with the real-world environment, enhancing the user experience. With the launch of ARKit and RealityKit, Apple has made it easier for iOS developers to create AR apps that can transform how we interact with the world. SwiftUI, Apple’s modern declarative UI framework, can be used to build the user interface for AR apps, making it easier to create engaging AR experiences. In this article, we will explore how to use SwiftUI, ARKit, and RealityKit to create AR apps for iOS devices.</p><h3><strong>Initial Setup</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qTsynRYHRrP5TldqYhPyRQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Y41Lb-JM5i1dtMVm86GeoA.png" /></figure><ol><li>Open Xcode: Launch Xcode from the Applications folder or by searching for it in Spotlight.</li><li>Create a new project: Click on “Create a new Xcode project” on the welcome screen or go to “File” &gt; “New” &gt; “Project” from the menu bar.</li><li>Choose a template: Choose the template that best matches your project needs, such as “iOS App” &gt; “Augmented Reality App” &gt; Next</li><li>Configure the project: Provide a name for your project, choose a team, and select a location to save the project.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OgCA0y77kFpFeCIAIQKLnA.png" /><figcaption>Initial Code Template</figcaption></figure><h3>Default Code Explanation</h3><pre>import SwiftUI<br>import RealityKit<br><br>struct ContentView : View {<br>    var body: some View {<br>        ARViewContainer().edgesIgnoringSafeArea(.all)<br>    }<br>}<br><br>struct ARViewContainer: UIViewRepresentable {<br>    <br>    func makeUIView(context: Context) -&gt; ARView {<br>        <br>        let arView = ARView(frame: .zero)<br>        <br>        // Load the &quot;Box&quot; scene from the &quot;Experience&quot; Reality File<br>        let boxAnchor = try! Experience.loadBox()<br>        <br>        // Add the box anchor to the scene<br>        arView.scene.anchors.append(boxAnchor)<br>        <br>        return arView<br>        <br>    }<br>    <br>    func updateUIView(_ uiView: ARView, context: Context) {}<br>    <br>}<br><br>#if DEBUG<br>struct ContentView_Previews : PreviewProvider {<br>    static var previews: some View {<br>        ContentView()<br>    }<br>}<br>#endif</pre><p>ARViewContainer is a UIViewRepresentable struct that is used to create and manage an ARView instance. UIViewRepresentable is a protocol that allows SwiftUI to interoperate with UIKit views and controls. ARViewContainer acts as a bridge between the SwiftUI framework and the RealityKit framework, allowing you to create 3D AR experiences in your SwiftUI app.</p><p>makeUIView is a required method of the UIViewRepresentable protocol. It&#39;s called when the SwiftUI view is being created for the first time. In this method, you create and configure your ARView instance, load any 3D models or assets you need, and add them to the scene. Finally, you return the ARView instance you created.</p><p>updateUIView is another required method of the UIViewRepresentable protocol. It&#39;s called whenever the SwiftUI view needs to be updated based on changes to its state or environment. In this method, you update the ARView instance to reflect any changes in the state of your SwiftUI view.</p><h4>More about updateUIView</h4><pre>struct ARViewContainer: UIViewRepresentable {<br>    @Binding var isModelDisplayed: Bool<br>    <br>    func makeUIView(context: Context) -&gt; ARView {<br>        let arView = ARView(frame: .zero)<br>        return arView<br>    }<br>    <br>    func updateUIView(_ uiView: ARView, context: Context) {<br>        if isModelDisplayed {<br>            // Load and add the 3D model to the AR scene<br>            let boxAnchor = try! Experience.loadBox()<br>        <br>            // Add the box anchor to the scene<br>            uiView.scene.anchors.append(boxAnchor)<br>        } else {<br>            // Remove the 3D model from the AR scene<br>            uiView.scene.anchors.removeAll()<br>        }<br>    }<br>}</pre><p>In this example, updateUIView is used to add or remove a 3D model from the AR scene based on the value of the isModelDisplayed Boolean state variable. If the value of isModelDisplayed is true, the method loads and adds a 3D box model to the AR scene. Otherwise, it removes all anchors (including the 3D model) from the AR scene.</p><p>This method is called whenever the value of the isModelDisplayed state variable is changed, and it allows the ARView instance to be updated accordingly. However, if you don’t do anything in the updateUIView method to respond to changes in that state variable, the ARViewContainer view won&#39;t be affected.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b7f88f2c14b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AR with iOS — AR, VR & MR Basics (Part-I)]]></title>
            <link>https://shiru99.medium.com/ar-with-ios-ar-vr-mr-basics-part-i-236679a2af93?source=rss-a19e9a6bab29------2</link>
            <guid isPermaLink="false">https://medium.com/p/236679a2af93</guid>
            <category><![CDATA[arkit]]></category>
            <category><![CDATA[ar]]></category>
            <category><![CDATA[vr]]></category>
            <category><![CDATA[mr]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Shiru99]]></dc:creator>
            <pubDate>Sat, 29 Apr 2023 18:23:19 GMT</pubDate>
            <atom:updated>2023-06-21T13:27:20.821Z</atom:updated>
            <content:encoded><![CDATA[<h3>AR, VR &amp; MR Basics: AR with iOS (Part-I)</h3><h3>Augmented Reality (AR)</h3><p>AR (Augmented Reality) overlays virtual content on the real world, allowing users to interact with virtual objects in their real environment.</p><p>Examples</p><ol><li>Snapchat filters</li><li>Ikea Place</li><li>Pokémon GO</li><li><a href="https://www.lamborghini.com/en-en/history/huracan-evo-rwd#ar">Lamborghini</a></li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kYqnwKzZSnPPPXS5uSBslw.png" /><figcaption>Pokémon GO AR</figcaption></figure><h3><strong>Virtual Reality (VR)</strong></h3><p>VR (Virtual Reality) creates a fully immersive digital environment, where users are transported to a virtual world and can interact with objects and environments that are entirely computer-generated.</p><p>Examples</p><ol><li>Oculus Rift</li><li>PlayStation VR</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*x0KyXtm_AbZcz4CqGPmJew.jpeg" /><figcaption>VR for F1 training</figcaption></figure><h3>Mixed Reality (MR)</h3><p>MR (Mixed Reality) combines elements of both AR and VR, allowing virtual objects to interact with and appear as if they are part of the real world. Users can interact with virtual objects while still being aware of and able to see their real environment.</p><p>Examples</p><ol><li>Microsoft <a href="https://www.microsoft.com/en-us/hololens">HoloLens</a></li><li>Magic Leap</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6KrEKf6AFTlcECiJSH06bg.png" /><figcaption>Hololens</figcaption></figure><h3>Difference between AR &amp; MR</h3><p>The main difference between AR (Augmented Reality) and MR (Mixed Reality) lies in the level of virtual object integration with the real world.</p><p>In AR, virtual content is overlaid onto the real world, allowing users to see and interact with virtual objects in their real environment. However, the virtual objects do not typically interact with the real world in a physically realistic way. They may appear as if they are floating or hovering above the real world, but they do not have a tangible connection to the physical environment.</p><p>On the other hand, in MR, virtual objects are integrated into the real world in a more realistic and seamless manner. They can interact with the real world objects and environments in a way that appears natural, creating a more immersive experience. MR often involves real-time tracking and mapping of the physical environment, allowing virtual objects to respond to and interact with the real world in a dynamic and interactive way.</p><p>In summary, while both AR and MR involve overlaying virtual content onto the real world, MR takes it a step further by integrating virtual objects into the real world in a more realistic and interactive manner.</p><p>Example, <a href="https://www.lamborghini.com/en-en/history/huracan-evo-rwd#ar">Lamborghini</a> VS Microsoft <a href="https://www.microsoft.com/en-us/hololens">HoloLens</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=236679a2af93" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>