Utilized OBJLoader to load an item successfully; now seeking guidance on calculating the coordinates of an element within (three.js)

I am utilizing three.js and OBJLoader to create a 3D human head representation:

let renderer, camera, scene, head, light, projectiles;

new THREE.OBJLoader().load(objUrl, initialize);

function initialize(obj) {
  renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight);

  scene = new THREE.Scene();

  head = obj.clone();
  head.children.forEach(child => child.material = new THREE.MeshPhongMaterial({ color: "#ffc700" }));
  head.position.y = -34;
  head.position.z = -110;
  scene.add(head);
  
  light = new THREE.SpotLight();
  light.target = head;
  scene.add(light);
  
  projectiles = [];

  window.addEventListener("mousedown", createProjectile, false);

  animate();
}

function animate() {
  head.rotation.y += THREE.Math.degToRad(1);

  projectiles.forEach(updateProjectile);

  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}

function createProjectile() {
  let projectile = new THREE.Mesh();
  projectile.material = new THREE.MeshToonMaterial({ color: "#ff0000" });
  projectile.geometry = new THREE.SphereGeometry(3, 20, 20);
  projectile.position.copy(getMouthPosition());
  scene.add(projectile);
  projectiles.push(projectile);
}

function updateProjectile(projectile) {
  // TODO: Move projectile in the direction the mouth was facing when projectile was first created.
  projectile.position.x += 2;
}

function getMouthPosition() {
  // TODO: Determine the world position of the mouth.
  let box = new THREE.Box3().setFromObject(head);
  return box.getCenter();
}
body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
}

canvas {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/86/three.js">
</script>

<script src="https://wzrd.in/standalone/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ccb8a4bea9a9e1a3aea6e1a0a3ada8a9be8cfde2fde2ff">[email protected]</a>">
</script>

<script>
  threeObjLoader(THREE);
  objUrl = "https://cdn.rawgit.com/mrdoob/three.js/f32fc45/examples/obj/walt/WaltHead.obj";
</script>

On mouse click, I aim to launch a bullet/projectile from the moving head's mouth. However, there are two functions that need implementation, as indicated by the TODO comments: getMouthPosition() and updateProjectile().

To determine the current mouth position for getMouthPosition(), I am looking to spawn the projectile slightly in front of the mouth.

Regarding updateProjectile(), the goal is to move the projectile based on the direction the head was facing at the moment of creation.

If anyone has insights or suggestions on how to tackle these functions, it would be highly appreciated. Thank you.

Answer №1

Listen up! At some point, you'll need to find the exact location of the mouth (the coordinates within the head group are approximately [0, 25, 20]). To pinpoint the position of the spinning head's mouth, utilize the .localToWorld(v) method in this manner:

head.localToWorld(mouthPosition.copy(spawnPoint.position));

The spawnPoint serves as a guiding object indicating our spawn point.

In addition, understanding the direction your head is facing is crucial. Retrieve this information using another method called .getWorldDirection() belonging to the head entity.

To sum it all up: armed with knowledge about the head's mouth position and its orientation, launching a projectile becomes feasible using those precise values.

let renderer, camera, scene, head, light, projectiles, spawnPoint, clock = new THREE.Clock(), delta = 0;

new THREE.OBJLoader().load(objUrl, initialize);

function initialize(obj) {
  renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight);

  scene = new THREE.Scene();

  head = obj.clone();
  head.children.forEach(child => child.material = new THREE.MeshPhongMaterial({ color: Math.random() * 0xffffff }));
  head.position.y = -34;
  head.position.z = -110;
  scene.add(head);
  
  light = new THREE.SpotLight();
  light.target = head;
  scene.add(light);
  
  spawnPoint = new THREE.Mesh(new THREE.SphereGeometry(1, 4, 2), new THREE.MeshBasicMaterial({color: "red", wireframe: true}));
  spawnPoint.position.set(0, 25, 20);
  head.add(spawnPoint);
  
  projectiles = [];

  window.addEventListener("mousedown", event => { createProjectile(); }, false);
  
  animate();
}

function animate() {
  delta = clock.getDelta();
  
  requestAnimationFrame(animate);
  
  head.rotation.y += THREE.Math.degToRad(20) * delta;

  projectiles.forEach(p => {
    p.position.addScaledVector(p.userData.direction, p.userData.speed * delta);
  });

  renderer.render(scene, camera);
}

function createProjectile() {
  let projectile = new THREE.Mesh();
  projectile.material = new THREE.MeshToonMaterial({ color: 0xff0000 });
  projectile.geometry = new THREE.SphereGeometry(3, 16, 12);
  let pos = getMouthPosition();
  console.log("pos", pos);
  projectile.position.copy(pos);
  projectile.userData.direction = new THREE.Vector3().copy(head.getWorldDirection().normalize());
  console.log(projectile.userData.direction);
  projectile.userData.speed = 50;
  scene.add(projectile);
  projectiles.push(projectile);
  console.log(projectiles);
}

function getMouthPosition() {
  let mouthPosition = new THREE.Vector3();
  console.log("spawnPoint", spawnPoint);
  head.localToWorld(mouthPosition.copy(spawnPoint.position));
  console.log("mouthPosition", mouthPosition);
  return mouthPosition;
}
body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
}

canvas {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/86/three.js">
</script>

<script src="https://wzrd.in/standalone/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="defab6acbbbbf3b1bcb4f3b2b1bfbabbac9eeff0eff0ed">[email protected]</a>">
</script>

<script>
  threeObjLoader(THREE);
  objUrl = "https://cdn.rawgit.com/mrdoob/three.js/f32fc45/examples/obj/walt/WaltHead.obj";
</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

DOMException: Access to property "apply" on a cross-origin object has been denied

Over the last day, I've been tackling the FreeCodeCamp assignment "quote machine". Everything is working fine except for the tweet button. You can tweet as many times as you like for one single quote, but not for multiple quotes (once you tweet one, y ...

odd appearance when objects make contact with one another

I am encountering a peculiar issue with my threejs objects in a scene. Whenever they get near each other or touch, I notice strange triangular artifacts forming at the borders of the objects, as shown in the image below. The renderer being used is THREE.W ...

Unable to Deselect Checkbox (HTML)

Currently, I am tackling the challenge of implementing an autocomplete feature using JavaScript for a form. However, I have encountered an issue with a checkbox in my HTML code. The concept is simple - users should be able to enter their shipping name and ...

What is the proper way to retrieve the correct value in JavaScript?

I'm currently working on an Angular program but I'm having trouble returning the correct value: function facilityChecked(facility, search) { var result; search.filter( function (v) { var rtn = (v["facility_Item"]["te ...

What is the method to change the state of Bootstrap 4 buttons in a mobile view without using CSS classes as a reference?

I have a simple example featuring a few buttons displayed in a basic modular popup. I am curious about how the state changes from active to inactive as I don't see any visible change in my code. Initially, I attempted to use custom JS to add an "acti ...

Creating an eternal loop within the useEffect hook in order to monitor the presence of a specific property within the window object

Upon loading, I need to verify if the window object has the property VL.refCode. My website utilizes viral loops, and the VL object is populated with the refCode property when a user registers. Initially, I used a for loop within a useEffect hook to deter ...

What could be the reason my code isn't successfully performing addition within the input field?

As a novice, I am practicing by attempting to retrieve a number from a text field, prompting the user to click a button that adds 2 to that number, and then displaying the result through HTML. However, I keep encountering an issue where NaN is returned whe ...

Trouble with Mongoose save() function failing to update data

I am currently working on enhancing a fully functioning CRUD app by adding a new feature that allows users to update a list of vendors. They have the ability to add new vendors, update existing ones, and delete vendors. While the add and delete functions a ...

Tips on working with an array received from a PHP script through AJAX

I've been stuck with this issue for the past few hours and I'm hoping to find a solution here. What I'm attempting to do is something like the following: PHP: $errorIds = array(); if(error happens){ array_push($errorIds, $user['user ...

When React JS and PHP(Mysql) combine, the error message "records.map is not a function" may appear

What problem am I facing with my code? The issue lies in my JavaScript code while trying to display the JSON array fetched correctly by the PHP file. The JavaScript implementation of JSON in the state is accurate, but an error occurs when attempting to us ...

What is the best way to manage a multi-select dropdown with checkboxes in Selenium Webdriver?

Below is a snapshot of the drop-down I am working with. In order to handle multiple selections, I currently have code that clicks on the arrow in the drop-down and then selects the corresponding checkbox. However, I would like a more efficient solution fo ...

Dividing a string using regex to deal with numerical issues

My task involves processing a list of strings that look like this: Client Potential XSS2Medium Client HTML5 Insecure Storage41Medium Client Potential DOM Open Redirect12Low The goal is to split each string into three parts, like so: ["Client Potential X ...

Event delegation will be ineffective when the target element is nested within another element

After receiving a recommendation from my colleagues on Stackoverflow (mplungjan, Michel), I implemented the event delegation pattern for a comment list. It has been working well and I am quite excited about this approach. However, I have encountered an iss ...

Ways to pause for the completion of multiple HTTP promises and display a modal exclusively when all promises result in failure

There are two separate HTTP calls on a page that need to be handled independently. vm.$onInit = function() { .... .... //Retrieve all items during initialization ds.getAllItems().then(function(result){ vm.items = result; },funct ...

Using a parameter as a key index in JavaScript

Here's the structure of my Object festivals: Object {friday: Object} friday: Object amazon: Object band: Object Next, I've created a function called`newAct`: function newAct(band, date, startTime, endTime, stage){ var ...

Tips for reversing a sketch: Creating a timer where the text continuously refreshes causing it to intersect

Currently, I am working on developing a stopwatch that is functional. However, I am facing an issue where the text overlaps itself when it changes due to repetitive drawing. Removing the strokeText and fillText from the interval prevents it from changing a ...

What is the process for incorporating the 'url-regex' npm package into an Angular(2/4) project?

I'm currently working on a project with Angular 4 and I've run into some issues while trying to use the url-regex package within my Component. After some troubleshooting, I discovered that this approach seems to work: import * as urlRegex from ...

Instructions for attaching an event listener to a Threejs Mesh Object with the help of threex dom events

var domEvents = new THREEx.DomEvents(camera, view.domElement); var div = document.createElement( 'div' ); div.setAttribute('data-remove','mesh1'); div.className = 'close-me'; var label = new THREE.CSS2DObje ...

Searching for matching strings in jQuery and eliminating the parent div element

Here's an HTML snippet: <div id="keywords"> <div id="container0"> <span id="term010"> this</span> <span id="term111"> is</span> <span id="term212"> a</span> <span ...

Failed to transfer CryptoKey to Express server

When I generate a CryptoKeyPair object on the client using the WebCrypto API, and try to send it to my express server using the fetch API, the req.body on the server side ends up being an empty object. What could be causing this issue? This is how I am ge ...