Utilizing a raycasting technique in conjunction with the camera to achieve a dynamic crosshair effect reminiscent of Google Cardboard

I'm looking for a way to implement the Google Cardboard crosshair effect in my three.js scene. Essentially, I want to create a dot or crosshair in the center of the screen for VR navigation. How can I achieve this and use a raycaster to interact with objects in the virtual reality environment?

One suggestion I found involves faking an X and Y position of the mouse by adding an event listener to the mousemove event. However, this method is more suited for desktop usage and I am interested in making this work on mobile devices as well. Any suggestions on the best approach to take in this situation?

Answer №1

To construct your own gaze cursor, you will need the following key components:

  1. A designated object to act as the cursor for user feedback
  2. An array of objects that the cursor will interact with
  3. A loop to iterate through the array of interactive objects to determine if the cursor is targeting them

Below is a sample implementation to help you better understand the process.

Cursor Design

Utilizing a ring design allows for animation, which provides users with feedback before triggering an interaction.

const cursor = new THREE.Mesh(
  new THREE.RingBufferGeometry(0.1, 0.15),
  new THREE.MeshBasicMaterial({ color: "white" })
);

Interactive Elements

Maintain a list of objects that should be interactive and define the actions they should perform when interacted with.

const selectable = [];

const cube = new THREE.Mesh(
  new THREE.BoxBufferGeometry(1, 1, 1),
  new THREE.MeshNormalMaterial()
);

selectable.push({
  object: cube,
  action() {
    console.log("Cube selected");
  },
});

Interactivity Validation

Regularly check for interactions and execute the corresponding actions.

const raycaster = new THREE.Raycaster();

(function animate() {
  for (let i = 0, length = selectable.length; i < length; i++) {
    const camPosition = camera.position.clone();
    const objectPosition = selectable[i].object.position.clone();

    raycaster.set(camPosition, camera.getWorldDirection(objectPosition));

    const intersects = raycaster.intersectObject(selectable[i].object);
    const selected = intersects.length > 0;

    // Change cursor color to indicate selection
    cursor.material.color.set(selected ? "crimson" : "white");

    // Execute object action only once
    if (selected && !selectable[i].selected) {
      selectable[i].action();
    }
    selectable[i].selected = selected;
  }
})();

View the demonstration below to see this concept in practice:

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

canvas {
  display: block;
}
<script type="module">
  import * as THREE from "https://cdn.jsdelivr.net/npm/three@latest/build/three.module.js";
  import { OrbitControls } from "https://cdn.jsdelivr.net/npm/three@latest/examples/jsm/controls/OrbitControls.js";

  // Code for setting up the environment and implementing the gaze cursor
</script>

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

The jQuery selector fails to refresh after the dynamic insertion of new elements

My selector is: $('section#attendance input:last') However, I add another input to section#attendance. I want the selector to target that new element since it should select the last element due to :last. However, for unknown reasons, it does no ...

Guide on implementing a globalThis polyfill within a NextJS application

Having some trouble with the Mantine react component library on older iOS versions. It's throwing a ReferenceError: Can't find variable: globalThis I've looked into polyfills, but I'm struggling to figure out how to integrate it into ...

Trouble looping through Javascript

Hello, I am encountering a problem with some JavaScript code that I am trying to implement. The functions in question are as follows: var changing_thumbs = new Array(); function changeThumb(index, i, thumb_count, path) { if (changing_thumbs[index]) { ...

A method for dynamically enlarging a parent node within a dhtmlx tree using JSON data

As I was browsing through the dhtmlx documentation, I came across this particular method: This method determines how the server-side URL is constructed when making dynamic loading calls: <script> tree.setXMLAutoLoadingBehaviour(mode); </s ...

Error message: "An issue occurred: Unable to access undefined properties (specifically, borderRadius) in MUI react."

I recently created a navigation bar with an integrated search bar component. The styling for my search component was done using MUI styled from @emotion/styled in MUI library, where I applied a borderRadius: theme.shape.borderRadius. However, I encountere ...

Searching for particular information within an array of objects

Seeking guidance as a newbie on how to extract a specific object from an array. Here is an example of the Array I am dealing with: data { "orderid": 5, "orderdate": "testurl.com", "username": "chris", "email": "", "userinfo": [ ...

Tips for scaling and compressing a canvas image using only pure javascript and HTML5 techniques

I am currently working on resizing and rotating a camera picture on the client side without using any special libraries. I have successfully completed most of the task, but I encounter an offset of 320 pixels when rotating the image. The source of this off ...

Set up Node to utilize Object.assign

Currently, I am experimenting with Object.assign functionality in IO.js and Node.JS, but encountering an unexpected error. /Users/lp/.nvm/versions/io.js/v2.4.0/bin/iojs --debug-brk=59842 --nolazy mixin.js Debugger listening on port 59842 /Users/lp/Documen ...

One limitation is that you cannot use JQuery to make multiple rows editable simultaneously

I have a unique challenge with implementing an edit button on each row of a dynamic Bootstrap table. I am attempting to toggle the button's icons and, depending on its current state, enable the corresponding row for editing. <td><button typ ...

"Fill the designated area on the webpage with data retrieved from an external script

In my current project, I am utilizing Angular and JQuery to enhance re-usability by setting the header and footer as partials. However, I encountered an issue where I needed certain javascript functions to be executed within the footer upon loading - a tas ...

Cancel your subscription to a PubNub channel when the unload event occurs

Currently, I am developing a multiplayer game in Angular utilizing the PubNub service along with the presence add-on. One of the challenges I am facing is detecting when a player unexpectedly leaves the game. This is crucial for sending notifications to o ...

Is there a way to reverse the animation playback in Angular?

I am working on an animation that involves a box fading from its original color to yellow. However, I would like to achieve the opposite effect: when the page loads, I want the box to start off as yellow and then fade back to its original color. The challe ...

The pagination feature is malfunctioning and is displaying all elements on every page instead of correctly displaying a

I am currently working with BootstrapVue 3 to create a component that uses a b-table. The issue I am facing is with the pagination functionality using b-pagination. My intention was to display only 2 objects per page, but instead of that, all objects are ...

Is there a way to prompt WebAPI to receive a complicated object as its argument for a DELETE HTTP request without relying on C# attributes?

Currently, my server is utilizing C#/WebAPI while the client side is using AngularJS. I am faced with a dilemma when it comes to formatting an HTTP DELETE request without specifying attributes in C#. Specifically, I am struggling with how to handle a meth ...

What is the best way to establish a connection between a client and MongoDB

My attempt to connect my client with MongoDB resulted in an error message: MongoParseError: option useunifedtopology is not supported. I am unsure of the reason behind this issue and would greatly appreciate your assistance. Below is the snippet of code ...

The CustomValidator ClientValidationFunction will only activate on the second or subsequent submission if CheckBoxList is checked

I am encountering an issue with a user control that is dynamically added to pages on DNN. The user control is built on a customized version of CheckBoxList and includes a CustomValidator with ClientValidationFunction set to a javascript function. It works ...

Paragraph Separated by Bullets Without Bullets At End of Line

I need assistance in creating a unique type of list that I call a "bullet separated paragraph list" by using a javascript array of strings. For example: item • item • item • item • item     item • item • item • item item • ...

Is there a way for me to redirect back to the original path?

Whenever I utilize <Redirect to="<same_path>" />, a warning pops up: Warning: You tried to redirect to the same route you're currently on: "<path>". In one of my Components, I trigger another Component that prompts for either submis ...

Waiting for a response from an API with the help of nodejs

I'm new to exploring Node.js and I'm interested in making API calls where the result is awaited before proceeding with any further actions. // defining endpoint function function getListMarket() { var deferred = Q.defer(); deferred.resolve(Q ...

Display/Modify HTML form

Looking for advice on how to create an interactive HTML form that displays data and allows users to edit it by clicking 'Edit' before submitting changes. Any suggestions on how to implement this functionality? ...