"Implementing a fixed target in ThreeJS orbit controls without using the lookAt

I'm currently working on developing a 3D viewer for building models. After successfully loading the model, my team and I are now focused on implementing interactive features with the model using OrbiControls for rotation, panning, and zooming.

Our goal is to allow users to click and drag to rotate the model, with the rotation center being set at the point where the user clicks on the building.

In an attempt to achieve this behavior, I started by updating the target of the OrbitControl:

control.target.set(newX, newY, newZ);

However, upon further investigation into the source code of OrbitControl.js, I discovered that when the control updates, the function camera.lookAt() is invoked, causing the camera to abruptly shift to a new position.

Is there a workaround for this issue? I've spent several hours experimenting with different solutions but haven't had any success yet. I've tried modifying target0 and then resetting the control, as well as reverting the camera back to its original position (although I may not have executed this properly).

Answer №1

Can this situation be bypassed?

The quick answer is "Yes, but not with the standard version of OrbitControls.js".

Let's delve into my detailed explanation...

I recently delved into the source code of OrbitControls.js (r87) with the intention of adding a feature that would allow for an optional second point as the camera target.

However, upon examining the code, I've concluded that incorporating this feature into the public version might not be ideal. Several aspects of OrbitControls, such as limiting viewing angles, minimum and maximum rotation, and dolly distance, rely on the assumption that the camera and orbit center are the same. Introducing a secondary camera target would necessitate significant modifications to accommodate both options, potentially complicating the codebase unnecessarily for a specialized function.

Therefore, the solution:

Given your focus on technical functionality over limitations like viewing angles or rotations, my suggestion would be to duplicate OrbitControls.js in your project, rename it to OrbitControls_customised.js, and make the necessary alterations:

Introduce two new parameters after this.target titled this.cameraTarget and this.coupleCenters

// "target" sets the location of focus, where the object orbits around
this.target = new THREE.Vector3();

// "cameraTarget" defines where the camera is looking (initially same as target)
this.cameraTarget = new THREE.Vector3();

// Indicates if the camera should align with the orbit center
this.coupleCenters = true;

In the section where the camera looks at the center...

scope.object.lookAt( scope.target );

...adjust it to update the camera only when coupleCenters is true...

if( scope.coupleCenters ){
    scope.cameraTarget = scope.target;
}
scope.object.lookAt( scope.cameraTarget );

With these adjustments, you can implement an onMouseDown event utilizing RayCasting to identify a point on your object, set controls.decoupleCenters to false, and establish controls.target as the intersecting point. Similarly, use an onMouseUp event to reset controls.target to controls.cameraTarget to restore normal behavior.

I trust this provides clarity on your query and points you towards a potential solution.

Answer №2

Give this a try:

Start by adjusting the control's position to:

control.center.set(0, 0, 0);

Next, follow these steps:

camera.position.copy(control.center).add(new THREE.Vector3(a, b, c+15));

where a, b, and c represent the coordinates of your structure model.

Note the addition of +15 to c, positioning the camera in front of the model. Modify this value for different distances from the model.

Answer №3

Showing gratitude to Martin Joiner, his solution has been applied in the following codepen:

Edit line 45 as follows:

controls.coupleCenters = true;

Initial behavior described by Wouter Coebergh can be observed by pressing any key or clicking the mouse before implementing Martin's recommended logic into the customized orbital controls.

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

Unable to retrieve the most recent global variable value within the confirmation box

<script type="text/javascript"> var customDiv ="hello"; $(function () { var $form = $("#authNotificationForm"); var startItems = $form.serializeArray(); startItems = convertSerializedArrayToHash(startItems); $("#authNoti ...

javascript ajax if statement is returning a false value erroneously

Upon successfully connecting and receiving data from PHP using AJAX, I encountered an issue with my if statement returning false inexplicably... Javascript: var xhr = new XMLHttpRequest(); xhr.open('POST', action, true); xhr.setRequestHeader(&a ...

Using HTML5 chunks and web workers will not involve any uploading of files

I encountered an issue while working with html5 slice and webworker. It seems that when I try to upload a file using the uploadFile function, nothing is happening and the file is not being uploaded. <html> <head> <title>Uploa ...

Issue with retrieving objects from Three.js functions

Let's take a look at the function I've created. function Planet(radius, c) { var sphere = new THREE.Mesh( new THREE.SphereGeometry(radius, 64, 64), new THREE.MeshLambertMaterial({ color: c }) ); } Using this function, ...

Is it a guarantee that a function called in the head section of a JavaScript for-of loop will only be executed once?

In both Firefox and Chrome, I tested the code snippet below: function test() { console.log("***") return [1,2,3] } for (const t of test()) { console.log(t) } After running this code, I noticed that the test function was only called once. T ...

Utilizing JavaScript to showcase information retrieved from the database

After implementing this code example for a cascaded drop-down menu, I would like to incorporate the names of individuals residing in a specific city. How can I achieve this functionality once a city is selected? Demo link: Complete code snippet below: ...

I am encountering an issue where the nested loop in Angular TypeScript is failing to return

I am facing an issue with my nested loop inside a function. The problem is that it is only returning the default value of false, instead of the value calculated within the loop. Can someone please point out what I might be doing incorrectly? Provided belo ...

Troubleshooting the non-functional asynchronous function

After starting to use redis with node (specifically the node_redis module), I decided to wrap my retrieval code for debugging and DRY principles. However, I encountered an issue where my new function wasn't working as expected. As someone who is stil ...

What is the best way to pass the first of two values from Angular to Node.js?

Press the button to retrieve two folderid values. Is there a way to only send the first folderid to the service? Refer to the screenshot below - when clicking on folder-1 (folderid 1230), it opens to reveal four folders. Then, clicking on folder-1-1 (fold ...

Bring in a collection of classes of various types from one TypeScript file to another

In my code file exampleA.ts, I define an object as follows: import { ExampleClass } from 'example.ts'; export const dynamicImportations = { ExampleClass }; Later, in another file named exampleB.ts, I import an array that includes class types and ...

What is the process of converting Luxon DateTime format into a string or numerical representation?

After setting up a Luxon clock for my project, I am facing an issue while using a component to define the month number of the current date. import { DateTime } from 'luxon'; import React, { useEffect, useState } from 'react'; interface ...

I attempted an AJAX script, but unfortunately, it was unsuccessful. Upon submitting the form, I received a success alert, but no data was sent to

I have been struggling with an Ajax script that doesn't seem to be working as expected. When I submit the form, I receive a success alert but nothing is being sent to the database. Here is my HTML form: <form action="account_info.php" enctype="mu ...

Vue - a guide on customizing a prop in a parent component

I have implemented a wrapper component that encapsulates a Quasar q-select element in the following manner: <template lang="pug"> q-select( :options="organisations" option-value="id" v-bind="$attrs&quo ...

Cakephp routing issue preventing jQuery autocomplete from displaying values

I am currently working on implementing jQuery autocomplete to display data from my table in Cakephp. While I have successfully set up the autocomplete feature with tags, I am facing difficulty in fetching and displaying data from my table. The search funct ...

End the connection to mysql once several queries have been executed

I am currently working on a project that involves fetching data from an API using node.js and running multiple mysql queries in a loop to update rows. However, I am facing an issue where the script keeps running until I manually terminate the mysql connect ...

Set the cookie to expire in 5 minutes using PHP, JavaScript, or jQuery

Is there a way to set a cookie in PHP that expires in 5 minutes? I am comfortable with the setcookie() function, but unsure about how to set the expiration time. Any explanation would be greatly appreciated. Could someone please guide me on how to achieve ...

Is there a method available to retrieve the data values stored within these objects?

Looking at the image below, I have data that includes a Data array in JSON format. https://i.sstatic.net/WHdUw.png The Data array contains key values such as condition_type and other related values. In order to extract individual values, I am using the ...

Form serialization causes text inputs to be left blank

I am currently using an ajax/php file uploader that includes additional form fields. The hidden form fields with preset values are being passed without any issues, however, the text fields with user-inputted values are coming up empty. Upon checking with h ...

Consistent height for h2 containers across all CSS grid columns

Is there a way to ensure all h2 containers have the same height, both with JavaScript and without it? The h2 titles are dynamic and can vary in length, but I want to maximize the space for all containers. img { max-width: 100%; height: auto; } .gri ...

What are the steps involved in transferring information from a website to an API?

Can someone help me with this question? I am having trouble understanding it. This is what I have: <a @click.prevent="Submit(0)" href="#">NO</a> <a @click.prevent="Submit(1)" href="#">OK</a> In my vue method submit, I want to se ...