Troubleshooting a rendering performance problem with an object rendered using Three.js

Having an issue with animations slowing down over time when rendering an obj file from Blender using Three.js. Here's the code snippet I'm working with:

<script>

            var objcontainer, stats;

            var camera, scene, renderer;

            var mouseX = 0, mouseY = 0;

            var windowHalfX = window.innerWidth / 2;
            var windowHalfY = window.innerHeight / 2;

            init(); 
            animate();


            function init() {

                objcontainer = document.createElement( 'div' );
                document.body.appendChild( objcontainer );

                // scene
                scene = new THREE.Scene();

                camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 2000 );
                camera.position.z = 300;
                camera.position.x = 0;
                camera.position.y = 0;
                scene.add( camera );

                /*var ambient = new THREE.AmbientLight( 0x101030 );
                scene.add( ambient );*/

                var directionalLight = new THREE.DirectionalLight( 0xffffff );
                directionalLight.position.set( 1, 1, 1 ).normalize();
                scene.add( directionalLight );

                var loader = new THREE.OBJMTLLoader();
                loader.addEventListener( 'load', function ( event ) {
                    var object = event.content;

                    object.position.y = 20;
                    object.position.x = 0;
                    object.position.z = 0;
                    object.rotation.x = -(Math.PI / 2);
                    scene.add( object );
                }, false);
                loader.load('objects/coque.obj', 'objects/coque.mtl');
                loader.load('objects/ecran_int.obj', 'objects/ecran_int.mtl');
                loader.load('objects/ecran_tour.obj', 'objects/ecran_tour.mtl');
                loader.load('objects/app_photo.obj', 'objects/app_photo.mtl');


                renderer = new THREE.WebGLRenderer({
                    antialias       : true // to get smoother output
                });
                renderer.setClearColorHex( 0xe5e5e5, 1 );
                renderer.setSize( window.innerWidth, window.innerHeight );
                objcontainer.appendChild( renderer.domElement );            
            }

            $('#left').bind('mouseenter', function() {
                this.iid = setInterval(function() {
                camera.position.x = camera.position.x + 10;
                camera.lookAt( scene?.position );
                renderer.clear();
                renderer.render( scene, camera );                 
            }, 25);
            }).bind('mouseleave', function(){
                this.iid && clearInterval(this.iid);
            });


            $('#right').bind('mouseenter', function() {
                this.iid = setInterval(function() {
                camera.position.x = camera.position.x - 10;
                camera.lookAt( scene?.position );
                renderer.clear();
                renderer.render( scene, camera );              
            }, 25);
            }).bind('mouseleave', function(){
                this.iid && clearInterval(this.iid);
            });

            $('#up').bind('mouseenter', function() {
                this.iid = setInterval(function() {
                camera.position.y = camera.position.y - 10;
                camera.lookAt( scene?.position );
                renderer.clear();
                renderer.render( scene, camera );              
            }, 25);
            }).bind('mouseleave', function(){
                this.iid && clearInterval(this.iid);
            });

            $('#down').bind('mouseenter', function() {
                this.iid = setInterval(function() {
                camera.position.y = camera.position.y + 10;
                camera.lookAt( scene?.position );
                renderer.clear();
                renderer.render( scene, camera );              
            }, 25);
            }).bind('mouseleave', function(){
                this.iid && clearInterval(this.iid);
            });

            $('#zoom-in').bind('mouseenter', function() {
                this.iid = setInterval(function() {
                camera.position.z = camera.position.z - 10;
                camera.lookAt( scene?.position );
                renderer.clear();
                renderer.render( scene, camera );              
            }, 25);
            }).bind('mouseleave', function(){
                this.iid && clearInterval(this.iid);
            });

            $('#zoom-out').bind('mouseenter', function() {
                this.iid = setInterval(function() {
                camera.position.z = camera.position.z + 10;
                camera.lookAt( scene?.position );
                renderer.clear();
                renderer.render( scene, camera );              
            }, 25);
            }).bind('mouseleave', function(){
                this.iid && clearInterval(this.iid);
            });

            $('#init').bind('click', function() {
                camera.position.z = 300;
                camera.position.x = 0;
                camera.position.y = 20;
                camera.lookAt( scene?.position );
                renderer.clear();
                renderer.render( scene, camera );              
            });

            function animate() {

                requestAnimationFrame( animate );
                render();
            }

            function render() { 
                requestAnimationFrame(render); 
                renderer.render(scene, camera); 
            } 

        </script>

Noticing performance decrease slightly slower on Safari compared to Chrome. Any advice or help would be greatly appreciated :)

Geoffrey

Answer №1

A jsfiddle would be helpful for debugging purposes. It seems likely that the issue is arising from calling render() within your event handler setInterval functions unnecessarily. Your animate function already handles rendering each frame, so this additional call may be causing multiple renders per frame due to intervals not being cleared properly.

This repeated rendering could explain why the performance slows over time, as the number of redundant render() calls continues to increase...

You might want to try removing the following lines from your event handlers/setintervals:

            renderer.clear();
            renderer.render( scene, camera );    

Furthermore, consider reviewing how movement and animation are implemented in some control files like https://github.com/mrdoob/three.js/blob/master/examples/js/controls/FirstPersonControls.js). These files separate logic from events and only set variables like movingForward = true; in event handlers while actual movement occurs in a single update() loop. Adapting this approach may benefit your code as well.

Additionally, it appears that your main animation loop is configured incorrectly, leading to unnecessary render calls. Removing the requestAnimationFrame call from your render() function, since it is already included in the animate() function, could help address this issue.

        function animate() {
            requestAnimationFrame( animate );
            render();
        }

        function render() { 
            // requestAnimationFrame(render); <-- remove this
            renderer.render(scene, camera); 
        } 

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

"Troubleshooting a Node.js JWT issue in a React.js

I've been diving into backend development and recently created some small APIs. They all function perfectly in Postman, but I encountered an issue when attempting to execute this particular call const onSubmit = async () => { try { setIsL ...

The jQuery selector is unable to locate the IMG element using its unique ID

I'm experiencing an issue with a webpage that includes the following code snippet: <img class="img-qrcode" id="img_123.000.00.01" src="http://localhost:7777/data/code_img\123.000.00.01.png" alt="./data/code_img\123.000.00.01. ...

The error message "Evaluating this.props.navigation: undefined is not an object" indicates that there

In the navigation bar, I am trying to keep a touchable opacity at the top right. When this touchable opacity is pressed, I want to redirect the user to the home page. constructor(props) { super(props); this.state = { stAccntList: [], ...

Utilizing Page Objects to select dropdown list items in JavaScript for Protractor testing

I'm struggling with a particular issue during my testing process. The task requires selecting an item from a list as part of a form to create a new user. However, the test does not select an item from the list even though Protractor does not report an ...

When changing recipients in Firebase, the Javascript code fetches the same message multiple times even though there is only a single message stored in the database

In the process of developing a chat application using Firebase and JavaScript, I have come across an issue. Whenever I switch receivers multiple times, the message I send is fetched multiple times even though it is only sent once to the database. var selec ...

The Node.js promise failure can be unpredictable, despite being properly managed

In my journey to master MongoDB, I am currently exploring its capabilities by building a basic blog application. However, I have encountered an issue with the code responsible for saving blog posts - it seems to be inconsistent in its success rate, sometim ...

There seems to be a hiccup in the distribution build of Angular grunt, as it is unable to locate the

While testing the build, everything runs smoothly. However, when attempting to build the distribution, an error is encountered: An error occurred: Cannot find module '/Users/matt.sich/Documents/angularProjects/firstProject/node_modules/grunt-usemin/l ...

Angular checkboxes not triggering ng-click event

Within my Angular application, there is a form that includes checkbox inputs: <div ng-repeat="partner in type.partners"> <label class="checkbox-inline"> <input type="checkbox" value="partner" ng-checked="report.participa ...

Troubles with proper functionality of antd's DatePicker.RangePicker within a React Function Component

I am currently utilizing React and the antd library, attempting to incorporate the DatePicker.RangePicker into my project. Initially, when I directly embed the RangePicker within the component, everything works smoothly. However, for better code organizat ...

Vue.js is displaying the error message "Expected Object, got Array" when the length appears as undefined

I have an app where users input style codes into a field. I want to create a popup confirmation modal that displays a message with the number of style codes provided. The code I currently have is: <template> <h4>Style Number</h4> <For ...

Capturing click events on a stacked area chart with nvd3

Could someone assist me in capturing the click event on a nvd3 stacked area chart? I have successfully managed to capture tooltip show and hide events but am struggling with the click event. How can I obtain information about the clicked point? Please help ...

pure-react-carousel: every slide is in view

Issue I am encountering a problem where the non-active slides in my container are not being hidden properly. This results in all of the slides being visible when only one should be displayed. Additionally, some slides are rendering outside of the designate ...

Issue with ngStyle function in Internet Explorer

Within my Angular 4 application, I have defined styles as shown below: [ngStyle]="{'border': getInterleaveColor(i)}" The following function is also included: getInterleaveColor(auditNumber) { var borderProperties = '2px solid'; ...

Incorporate the previous page's location path into the next page using Props in Gatsby Link

My website has multiple pages with paginated lists of blog posts, each post generated from markdown using createPage(). Each page in the /posts directory displays 3 post previews and subsequent pages are numbered (e.g. /posts/2). I am trying to pass the p ...

Implementing the History API to dynamically load content into a div using Ajax

On my WordPress site, I have post content that loads into a div using AJAX when a user clicks on it. Now, I'd like to update the URL for the current post without using hashes. How can I achieve this with my JavaScript? JavaScript: jQuery(docum ...

Issue with Javascript/Jquery functionality within a PHP script

I have been attempting to incorporate a multi-select feature (view at http://jsfiddle.net/eUDRV/318/) into my PHP webpage. While I am able to display the table as desired, pressing the buttons to move elements from one side to another does not trigger any ...

What could be causing Ajax's html() function to create a loop that never ends?

Is there a way to incorporate an animation during the database operation and update the table content in the HTML document once the operation is completed? <script> var jobj = new Object(); jobj.uid = <?php echo "'".$_SESSION['user_ ...

What is the best way to save the toggleClass value of various selectors along with their corresponding classes in localStorage?

I've been attempting to preserve the toggled class of multiple elements using local storage or cookies in order to maintain the toggled class after a page refresh. Despite trying various solutions such as js cookie and other tutorials, I've had n ...

Learn how to seamlessly integrate React Hooks Form with the Select component from @Mui for a powerful

I am currently facing an issue while using react-hooks-form to manage forms in conjunction with the @Mui library. The specific problem I'm encountering is figuring out how to integrate the Select component from the @Mui library with react-hooks-form s ...

Tips for implementing JS function in Angular for a Collapsible Sidebar in your component.ts file

I am attempting to collapse a pre-existing Sidebar within an Angular project. The Sidebar is currently set up in the app.component.html file, but I want to transform it into its own component. My goal is to incorporate the following JS function into the s ...