What's causing the unexpected rendering outcome in Three.js?

Here is a mesh created in Blender: https://i.sstatic.net/KBGM5.jpg

Upon loading it into Three.js, I am seeing this result: https://i.sstatic.net/PCNQ8.jpg

I have exported it to .obj format and ensured all faces are triangulated. I am not sure why this issue is occurring. Below is the Three.js code I am using to render the mesh. The same code works fine with other meshes, so I suspect there might be something specific about this mesh that Three.js does not like?

<!DOCTYPE html>

<html>

<head>
    <title></title>
    <script type="text/javascript" src="/js/three.js"></script>
    <script type="text/javascript" src="/js/DDSLoader.js"></script>
    <script type="text/javascript" src="/js/MTLLoader.js"></script>
    <script type="text/javascript" src="/js/OBJLoader.js"></script>
    <script type="text/javascript" src="/js/OrbitControls.js"></script>



    <script type="text/javascript" src="/js/stats.js"></script>
    <script type="text/javascript" src="/js/dat.gui.js"></script>
    <style>
        body {
            /* set margin to 0 and overflow to hidden, to go fullscreen */
            margin: 0;
            overflow: hidden;
        }
    </style>
</head>
<body>

<div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">

    function init() {
        var stats = initStats();

        var scene = new THREE.Scene();

        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
        camera.position.x = 130;
        camera.position.y = 40;
        camera.position.z = 50;
        camera.lookAt(scene.position);
        scene.add(camera);


        // create a render and set the size
        var webGLRenderer = new THREE.WebGLRenderer();
        //webGLRenderer.setPixelRatio( window.devicePixelRatio );
        webGLRenderer.setClearColor(new THREE.Color(0xffffff, 1.0));
        webGLRenderer.setSize(window.innerWidth, window.innerHeight);
        webGLRenderer.shadowMapEnabled = true;


        var ambient = new THREE.AmbientLight( 0x444444 );
        ambient.intensity = 5;
        scene.add( ambient );


        if('stiletto_switchblade_knife.mtl' !== ''){

            THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() );

            var mtlLoader = new THREE.MTLLoader();
            mtlLoader.setBaseUrl( '/assets/download/mesh/18/' );
            mtlLoader.setPath( '/assets/download/mesh/18/' );
            mtlLoader.load( 'stiletto_switchblade_knife.mtl', function( materials ) {
                materials.preload();

                var objLoader = new THREE.OBJLoader();
                objLoader.setMaterials( materials );
                objLoader.setPath( '/assets/download/mesh/18/' );
                objLoader.load( 'stiletto_switchblade_knife.obj', function ( object ) {
                    //object.scale.set(100, 100, 100);
                    //object.rotation.x = -0.3;
                    scene.add( object );
                });

            });

        } else {

            var objLoader = new THREE.OBJLoader();
            objLoader.setPath( '/assets/download/mesh/18/' );
            objLoader.load( 'stiletto_switchblade_knife.obj', function ( object ) {
                object.material = new THREE.MeshLambertMaterial({color: 0xFFFFFF});
                //object.scale.set(100, 100, 100);
                //object.rotation.x = -0.3;
                scene.add( object );
            });

        }


        // add the output of the renderer to the html element
        document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);


        var controls = new THREE.OrbitControls(camera, webGLRenderer.domElement );
        render();


        // simple render
        function render() {
            stats.update();
            controls.update();
            requestAnimationFrame(render);
            webGLRenderer.render(scene, camera);
        }

        function initStats() {

            var stats = new Stats();
            stats.setMode(0); // 0: fps, 1: ms

            // Align top-left
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';

            document.getElementById("Stats-output").appendChild(stats.domElement);

            return stats;
        }
    }
    window.onload = init;
</script>
</body>
</html>

EDIT Are watertight meshes required in Three.js? There are areas in this mesh that are not completely closed, could that be causing the issue? This is the only difference I can think of compared to other meshes that render correctly.

Answer №1

When using OBJ models in three.js R76, I discovered that renders were being impacted by stray "l" (line) elements within certain objects. To address this issue, I searched the ASCII OBJ file for instances of "l ", removed the offending elements by hiding all faces associated with them, and then addressed any remaining issues.

Answer №2

After some investigation, it became clear that a few hidden faces were causing the unexpected behavior within the mesh. To resolve this issue, I employed an intriguing debugging technique by systematically removing vertices and testing with threejs until pinpointing the problematic section.

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

Selenium2: Exploring ways to retrieve error specifics after executeScript() encounters a failure

While facing certain idiosyncrasies with browsers, I often have to execute JavaScript commands during testing. Every now and then, Selenium returns an error stating that there was a JavaScript error without providing any specifics. Is there a method to re ...

Webstorm seems to be having trouble identifying Next.js

When I create a Next.js app using the command npx create-next-app my-app --use-npm Everything is successfully installed, but when using WebStorm, I noticed that it does not auto import the <Link> component from Next.js. I have to manually import it ...

Displaying MySQL information on an EJS document including references to other tables

Check out the project on GitHub I am currently working on retrieving quiz answers from a MySQL database and displaying them in a form using EJS templating within a node.js/express application. However, I am facing challenges with correctly mapping answers ...

Changing the color of the timePicker clock in material-ui: a step-by-step guide

I have been attempting to update the color of the time clock in my timeInput component (material-ui-time-picker) for material-ui, but unfortunately, it is not reflecting the change. Here is the code I am using: <TimeInput style ={heure} ...

Tips for bringing a 3D model to life in three.js

I'm currently in the process of working on a project that involves showcasing 3D models on the frontend. As you scroll, the next models are displayed. I'm utilizing gsap for scrolling, and three-fiber within the React framework for this purpose. ...

Crafting personalized objects from an array

In the process of creating an object from an array, I am faced with a dilemma. The elements in the array are as follows: var arr = [ 'find({ qty: { $lt: 20 } } )', 'limit(5)', 'skip(0)' ] Despite my efforts, my code is ...

In production mode, the Angular/JS Express app is stuck in an endless routing loop, while it functions perfectly in development mode

My webapp is constructed using generator-angular-fullstack. While it functions properly in development mode (grunt serve), I encounter a problem with what appears to be an endless routing loop when switching to production mode (grunt serve:dist). The outp ...

Can anyone identify the result produced by this line of code? Utilizing the $.get method to access "http://192.168.4.1:80/" with the parameter {pin:p}

Can anyone explain the output of this line of code? $.get("http://192.168.4.1:80/", {pin:p}); I understand that it is an Ajax code that sends data through a GET request, but I am trying to manually send the same data like this ".../pin:13" or "", however ...

Clicking the mouse within three.js

I'm facing an issue with my webpage that features a three.js (webgl) graphic created using a .dae file imported from Blender. My goal is to draw a square or mark wherever the mouse is clicked, but for some reason, the square appears in a different loc ...

How the React Component Class Executes OnChange Event in a Closure

When working on my React code, I found myself creating a closure by calling "onChange." class CityInput extends React.Component { constructor( props ){ super( props ); this.state = { city : "", country : "" ...

What is the best way to fill a list-group using JavaScript?

Fetching ticket data from a controller is done using the code snippet below: $.ajax({ type: "GET", url: "/Tickets/List/", data: param = "", contentType: "application/ ...

Neither req.body nor req.file contain any data

Hey everyone, I'm new to coding and currently working on creating a basic markdown blog. However, I'm facing an issue where req.body doesn't contain my markdown field and req.file is undefined when trying to upload an article. I'm unsur ...

Encountered an error when attempting to submit with Node.js and Express.js connected to MySql - "Cannot POST /login

I am currently working on creating a basic login page using node.js with the express.js and mysql packages. The goal is to redirect users to the layout.html page if their username and password exist in the mysql database. For this project, I have set up a ...

Positioning an Element on a Web Page in Real-Time

Trying to implement an Emoji picker in my React application, I have two toggle buttons on the page to show the picker. I want it to appear where the Toggle button is clicked - whether at the top or bottom of the page. The challenge is to ensure that the pi ...

Error: The property 'scrollIntoView' cannot be read because it is null

class MessageApp extends Component { constructor(props) { super(props) this.state = { text: "", messages: [] } } componentDidMount() { const config = { apiKey: "<api-key>", authDomain: "<projec ...

Is it possible to adjust the width of the comment box on the Facebook "Like" button?

Is there a way to set the width of the comment box that appears after clicking the Facebook "Like" button? I know how to adjust the width of the button itself and related content, but can't find any options for the comment box: I've tried overri ...

How can you retrieve the <head> content from a remote website without being able to make any changes to that site?

Imagine I need to access the <head> tag of a remote website like YouTube. Whenever I attempt this, I encounter an error message: Access to XMLHttpRequest at ‘Website I am trying to access for the head section’ from origin ‘My Website’ has b ...

Launching the webpage with Next.js version 13

Hey there! I'm currently working on implementing a loading screen for my website to enhance the user experience. Since it's quite a large site, I believe a loading screen would be beneficial. However, I'm having trouble getting it to work on ...

What steps can I take to resolve the CSP errors I am experiencing?

I am currently working with NextJs@12 and I am attempting to set up CSP for my application. Unfortunately, I keep encountering errors in my console and I cannot figure out where I am going wrong. Below is the current policy that I have in my next.config fi ...

React - what propType should be used for the Material UI icon?

I am planning to send a Material-UI icon to the Test component and I need to define the correct proptype for it. App.js import "./styles.css"; import VisibilityIcon from "@material-ui/icons/Visibility"; import Test from "./Test&q ...