How to correctly position an object upright on a wall in Three.js WebXR(AR) and rotate it effectively

I'm currently facing a challenge trying to position an object vertically on a wall with the correct rotation. For illustration purposes, I've replaced the object with a reticle in the images provided. As shown in the last two pictures, the reticle appears twisted when placed on the wall.

My objective is to ensure that the local x-axis remains parallel to the floor and the local z-axis points downward.

Could this issue be related to the fact that the z-axis of the reticle always faces the camera when focused on the floor?

I attempted to rectify the undesired rotation by reversing the rotation and adjusting the Euler order, yet it seems to be a more general problem. Does anyone have any suggestions on how to resolve this? I am unable to find a suitable solution and would appreciate any assistance.

The main code source can be found here: https://github.com/mrdoob/three.js/blob/master/examples/webxr_ar_hittest.html

import * as THREE from 'three'
import { ARButton } from 'three/examples/jsm/webxr/ARButton'

var camera
var scene 
var renderer
var arbutton
var controller
var reticle

var hitTestSource = null
var hitTestSourceRequested = false

init()
renderer.setAnimationLoop(render);

function init() {
    renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.xr.enabled = true;

    arbutton = ARButton.createButton(renderer, { 
        requiredFeatures: ['hit-test'],
        optionalFeatures: ['dom-overlay'],
        domOverlay: { root: document.getElementById('arOverlay') } 
    })
    document.body.appendChild(arbutton);

    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 20);

    var light = new THREE.HemisphereLight(0xffffff, 0xbbbbff, 1);
    light.position.set(0.5, 1, 0.25);
    scene.add(light);

    reticle = new THREE.Mesh(new THREE.RingBufferGeometry(0.15, 0.2, 32).rotateX(-Math.PI/2), new THREE.MeshBasicMaterial());
    reticle.matrixAutoUpdate = false;
    reticle.visible = false;
    scene.add(reticle);
    reticle.add(new THREE.AxesHelper(0.5));
    reticle.add(new THREE.Mesh(new THREE.PlaneBufferGeometry(0.1, 0.1), new THREE.MeshBasicMaterial()))

    controller = renderer.xr.getController(0);
    scene.add(controller);

    scene.add(new THREE.AxesHelper(1));
}

function render(timestamp, frame) {
    if(frame){
        var referenceSpace = renderer.xr.getReferenceSpace();
        var session = renderer.xr.getSession();

        if (hitTestSourceRequested === false) {
            session.requestReferenceSpace('viewer').then(function (referenceSpace) {
                session.requestHitTestSource({ space: referenceSpace }).then(function (source) {
                    hitTestSource = source;
                });
            });
            session.addEventListener('end', function () {
                hitTestSourceRequested = false;
                hitTestSource = null;
            });
            hitTestSourceRequested = true;
        }

        if (hitTestSource) {
            var hitTestResults = frame.getHitTestResults(hitTestSource);
            if (hitTestResults.length) {
                var hit = hitTestResults[0];
                reticle.visible = true;
                reticle.matrix.fromArray(hit.getPose(referenceSpace).transform.matrix);

                // TODO apply some additional rotation here

            } else {
                reticle.visible = false;
            }
        }
    
    }
    renderer.render(scene, camera);
}


https://i.sstatic.net/619b0m.jpg https://i.sstatic.net/wDEofm.jpg https://i.sstatic.net/T0EVxm.jpg https://i.sstatic.net/np3V7m.jpg

Answer №1

My solution involved rotating the reticle around the y-axis based on its angle relative to the xz plane.

const xAxis = new Vector3()
reticle.matrix.extractBasis(xAxis, new Vector(), new Vector())

const yAxis = new Vector3(0, 1, 0)
const angle = Math.asin(xAxis.dot(yAxis)) 

const rotationMatrix = new Matrix4()
rotationMatrix.makeRotationY(Math.PI + angle)

reticle.matrix.multiply(rotationMatrix)                    

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Filtering Database Tables

UPDATE: Apologies for my lack of familiarity with the guidelines as a newcomer here. Here is my progress so far: <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title>AJAX filter demo</title> </head> < ...

What is the reason behind Selenium not utilizing JavaScript?

I've been a beginner in the world of Javascript for a while now, with my main goal being to use it for creating Selenium automations as part of my journey into QA automation. However, I find myself quite perplexed when it comes to the language. In al ...

"Using SetState frequently results in multiple rerenders of the component

Currently, I am developing a messenger application with a main screen component that displays all messages. My goal is to make sure that whenever a user sends or receives a message, the component updates the Flatlist to show the latest sent message. To ach ...

Tips for transferring POST body data to a different route without losing any information

Assuming I have the following route: app.post('/category',function(req,res){ res.redirect('/category/item'); }) In this scenario, the user will submit data to the '/category' route and then automatically be redirected ...

What's causing the text texture in three.js to appear so dismal?

Struggling to add a texture to 3D text, I can't help but notice it doesn't look quite right. The texture only appears on the letters' faces, while the sides just show stripes. It seems like I must be missing something or there might be a bet ...

React - Parent Component not successfully passing Ajax data to Child Component

I have a parent component and a child component. I am using the fetch method within the componentDidMount() callback to retrieve data from an API and then set the state with key items to that data. The intention is for this data to be passed down to the ch ...

Lazy Load immediately loads images that are visible on the screen without needing a click

I am facing an issue with Lazy Load on my image-heavy website. I want the images to load only when a button is clicked, but currently, it only partially works. Images below the fold follow the desired behavior of loading on click, but those above the fold ...

Download button on Rshiny platform for collecting numerous files from different sources

I am on a quest for knowledge regarding the inclusion of a download button in my application that consolidates various files into a zip archive. Within my application, there are a timeline and a datatable, with files linked to entries on the datatable. Th ...

Using JavaScript to replace a radio button with the term "selected"

I am currently in the process of developing a quiz that is powered by jQuery and possibly JSON, with data being stored in a database. Everything is functioning correctly at this point, but I would like to enhance the user interface by hiding the radio butt ...

Problem with modals not triggering within the iDangero.us swiper

I am encountering an issue with the iDangerous.us Swiper where I cannot activate any events within the swiper-wrapper. I am attempting to trigger a modal on each slide but nothing is happening. Any Modal placed inside the swiper-wrapper does not work. I a ...

Synchronous loop in Javascript

Is there a method to execute codes asynchronously within a for loop? In this scenario, events ranging from day x to y need to be inserted into the calendar using a for loop. However, the current loop is taking too long, as it has to cover all the days fro ...

Implementing file uploads using AJAX in CodeIgniter will continue to run, even if the value is null or undefined

I need to trigger another ajax request if the file has not been input yet. However, it is currently still carrying out the form action. Below is my view code: <form method="POST" id="quiz_file" action="<?php echo site_url('home/upload_quiz/&ap ...

What are the steps for implementing webpack 5 configurations in Next.js?

I can't seem to figure out how to properly add experiments to my webpack config. Here is my current environment: [email protected] [email protected] To set up, I started a new Next.js app using the command npx create-next-app blog Accord ...

sequentially animating elements using animate css in a choreographed manner

I have created a unique jsfiddle with 20 boxes that I am trying to animate using the Animate.css plugin. The plugin can be found at daneden.me/animate. My goal is to animate each box one after the other in a sequential manner, but I seem to be having trou ...

Tips for sending query string parameters to an AJAX request using data

Currently, I am making an ajax call to hit the API and I need to include a query parameter. How can I accomplish this with my ajax call? Below is the code snippet that I am using. Any assistance on this matter would be greatly appreciated. Thank you. ...

The functionality of Jquery UI is not compatible with version 1.12

Incorporating jQuery UI into my current project has presented some challenges. Both the jquery-ui.min.css and jquery-ui.min.js files are version 1.12, so I opted for the latest jQuery version, jquery-3.2.1.min.js. Specifically, I decided to test the datep ...

Obtaining a list of dates for a particular week using React DayPicker

I'm seeking the ability to click on a specific week number within the react DayPicker and receive an array of all dates within that week. The DayPicker package I am using can be found here: I've copied the example code from react DayPicker to e ...

Unusual behavior exhibited by AngularJS when working with Float32Arrays

After working with Float32Array values in AngularJS, I have noticed some unexpected behavior. During my testing, I encountered the following scenarios: angular.module("myApp", []).controller("myCtrl", function($scope) { $scope.n = 0.2; // Displays as 0 ...

Create and export a React component with dual properties

Currently, I am utilizing MaterialUI in my project and exporting components in the following manner: import withStyles, { WithStyles } from "@material-ui/core/styles/withStyles"; ... export default withStyles(styles)(Users); Recently, I have integrated ...

Show a visual content in Grails Server Pages created through a specific class

In my class file, I have the image path displayed as shown below: String val; val+= "<img src=/"PATH_TO_FILE/" alt=/"sometext/">" Now, I am attempting to load the image in a gsp view within a div using jQuery from the val variable. The image is be ...