What causes certain STL models to appear completely black in a three.js environment?

Screenshot 1

Screenshot 2

Some of my models(STL) have turned completely black while others receive color correctly from the lights.

In Screenshot 1 and 2, you can see that the fighter model has color but the miku model appears entirely black. It seems like there is no light illuminating her or she is behaving as if a black BasicMaterial has been applied to her.

Both models are applied with PhongMaterial. I have tried various combinations of lights with different positions, types, and parameters but nothing seems to work.

I am certain that the miku model is normal because I downloaded both the fighter and miku models from the same website where they were displayed with colors. There are other models in my scene that also turn pure black even though they are regular STL models.

There must be some errors in my scene configuration.

Here is the code snippet:

    <script>
    var renderer;
    function initThree() {
        width = document.getElementById('canvas-frame').clientWidth;
        height = document.getElementById('canvas-frame').clientHeight;
        renderer = new THREE.WebGLRenderer({
            antialias: true
        });
        renderer.setSize(width, height);
        document.getElementById('canvas-frame').appendChild(renderer.domElement);

    }

    var camera;
    function initCamera() {
        camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);
        camera.position.x = 50;
        camera.position.y = 0;
        camera.position.z = 0;
        camera.lookAt({
            x: 0,
            y: 0,
            z: 0
        });


    }


    var scene;
    function initScene() {
        scene = new THREE.Scene();


    }


    //Light source 1
    var light;
    function initLight() {
        light = new THREE.DirectionalLight(0xfefff7, 2.0, 0);
        light.position.set(0, 500, 0);
        scene.add(light);
    }
    //Light source 2
    var light2;
    function initLight2() {
        light2 = new THREE.DirectionalLight(0x414141, 1.0, 0);
        light2.position.set(0, -500, 0);
        scene.add(light2);
    }

    //Unused light source 3
    var light3;
    function initLight3() {
        light3 = new THREE.SpotLight(0xffffff, .7, 0);
        light3.spotLight = new THREE.SpotLight(0xffffff, .7, 0);
        light3.position.set(-700, 1000, 1000);
        light3.castShadow = true;
        scene.add(light3);
    }

    //Unused light source 4
    var light4;
    function initLight4() {
        light4 = new THREE.PointLight(0xffffff, 0.7, 0);
        light4.position.set(3200, -3900, 3500);
        light4.castShadow = true;
        scene.add(light4);


    }

    //Create Jupiter
    var sphere;
    function initSphere() {
        var bitmap = new Image();
        bitmap.src = 'img/jupiter.jpg';
        var texture = THREE.ImageUtils.loadTexture(bitmap.src);
        var material = new THREE.MeshPhongMaterial({
            map: texture
        });
        var geometry = new THREE.SphereGeometry(50, 64, 64);
        sphere = new THREE.Mesh(geometry, material);
        sphere.position.set(0, 17, -120);
        scene.add(sphere);
    }

    //Load model file
    var loader = new THREE.STLLoader();
    function initLoad() {
        loader.addEventListener('load', function (event) {

            var geometryOfFiles = event.content;
            var materialOfFiles = new THREE.MeshPhongMaterial({
                wrapAround: true,
                wrapRGB: new THREE.Vector3(0, 1, 1),
                color: 0xFFFFFF,
                specular: 0xFFFFFF,
                shading: THREE.SmoothShading,
                shininess: 630,
                fog: false,
                side: THREE.DoubleSide

            });
            var object = new THREE.Mesh(geometryOfFiles, materialOfFiles);

            object.position.set(0, 0, 0);
            object.rotation.set(-Math.PI / 2, 0, Math.PI / 111);
            object.scale.set(2, 2, 2);


            scene.add(object);


        });
        loader.load('miku.stl');
    }

    var loader1 = new THREE.STLLoader();
    function initLoad1() {
        loader1.addEventListener('load', function (event) {

            var geometryOfFiles = event.content;
            var materialOfFiles = new THREE.MeshPhongMaterial({
                wrapAround: true,
                wrapRGB: new THREE.Vector3(0, 1, 1),
                color: 0xFFFFFF,
                specular: 0xFFFFFF,
                shading: THREE.SmoothShading,
                shininess: 230,
                fog: false,
                side: THREE.DoubleSide

            });
            var object = new THREE.Mesh(geometryOfFiles, materialOfFiles);

            object.position.set(0, 20, 50);
            object.rotation.set(-Math.PI / 2, 0, Math.PI / 111);
            object.scale.set(0.5, 0.5, 0.5);


            scene.add(object);


        });
        loader1.load('f35.stl');
    }


    var controls;
    function setControl() {
        controls = new THREE.TrackballControls(camera);

        /*
         controls.rotateSpeed = 5.0;
         controls.zoomSpeed = 5;
         controls.panSpeed = 2;

         controls.noZoom = false;
         controls.noPan = false;

         controls.staticMoving = false;
         controls.dynamicDampingFactor = 0.3;*/
    }


    function animate() {
        controls.update();
        renderer.clear();
        renderer.render(scene, camera);
        requestAnimationFrame(animate);
        sphere.position.x -= 0.1;
        sphere.rotation.y += -0.005;
    }

    function threeStart() {
        initThree();
        initCamera();
        initScene();
        initLight3();
        initLight4();
        initSphere();
        setControl();
        animate();
        initLoad();
        initLoad1();


    }



</script>

Answer №1

Upon realizing that the addition of an AmbientLight has improved the situation, it is likely that the normals are being calculated incorrectly or missing altogether. It is recommended to check them here:

geometry.faces[0].normal;

To ensure accurate values are calculated, use the following command:

geometry.computeFaceNormals()

In response to how Thingiverse displays correct normals: upon examining their code, it was discovered that they do not directly utilize the STL files provided. Instead, they have a JSON file that is loaded from using THREE.JSONLoader.

These files contain correct normals (potentially through precalculations on user-uploaded files), but it is advised to verify the normals in the STL file independently.

The Miku JSON file can be accessed at .

Answer №2

Not sure if computeFaceNormals() is considered obsolete, but in my situation I found that I had to execute the following:

const objectGeometry = useLoader(STLLoader, ObjectFile)
objectGeometry.computeVertexNormals()

It works perfectly though 👍

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

Using JavaScript to extract information from a dropdown menu

Currently, I am working on a project that involves reading values from a dropdown box on a webpage and alerting the selected value. Below is the code I have written for this task. JavaScript function main(input) { value = getValue(); alert(value) ...

Nextjs style import function properly on the development server, but faces issues when deployed to production environments

import "../styles.css"; import styles from "react-responsive-carousel/lib/styles/carousel.min.css"; import "react-owl-carousel2/lib/styles.css"; import { Provider } from "react-redux"; import store from "../store/store" function App({ Component, pageProps ...

Accessing data attributes using jQuery and the class selector

I'm looking for a way to trigger an onClick event for an entire class of elements and access their individual data attributes within the function. Typically, I would use the following method: $(".classy").click(function(){ console.log("Replace th ...

acquire information using ajax in conjunction with jquery

I am currently working with the following code: <div data-role="content"> <div data-role="content"> <form id="registerForm" action="/register" method="post" data-ajax="false" class="ui-body ui-body-a ui-corner-al ...

Adding a new HTML element to each ng-repeat iteration in AngularJS

Can you help me find a solution for inserting a <p> tag in the DOM for each item in my ng-repeat loop? Here is the array of objects I am using for the ng-repeat: $scope.items = [ {name: "john", paragraph:"<p>hi, im john</p>"}, {nam ...

Node.js dynamically updates exports for efficient code execution

I am facing an issue with exporting and importing an object in my code. The object starts off empty but gets populated with keys and values when a button is clicked. However, when other files import this object, it still shows as empty. How can I dynamical ...

Utilize Ajax and PHP to transfer User ID to the Database

One issue I'm facing is that I have a page where my users' posts are displayed, and each post has a connect button in the form of form input. The poster's id is associated with each post. I want it so that when a user clicks on the connect b ...

Documents are not stored in cache

Using the cache.manifest file, I am able to view my project offline and everything works perfectly. However, the only issue I'm facing is that the libraries for my gallery slider are not being cached, and I'm not sure why. Can anyone lend me a ...

Declaring a Javascript variable within an if statement does not alter the value of the global variable

Currently, I am working on enhancing my HTML projects by using JavaScript to modify the video source. Below is the video element in question. <div> <video id="songVid" onmouseover="controlsVid()"> <source src=&qu ...

Enhance Website User Experience: Keeping Track of Scroll Position When Users Navigate Back in Browser

Have you ever experienced the frustration of scrolling through a page with infinite scroll, only to click on a link and then go back to find that you've lost your place in the scroll? You're scrolling down a lot, You click on a link from the i ...

Sails.js navigating through sessions

What is a rolling session in Sails.js? A rolling session is a session that expires after a set amount of time without user activity, except for websockets live updating data. If the user navigates to a different part of the site before the session expires, ...

Obtain keys from an object implemented with an interface in TypeScript

Is it possible to retrieve the actual keys of an object when utilizing an interface to define the object? For example: interface IPerson { name: string; } interface IAddress { [key: string]: IPerson; } const personInAddressObj: IAddress= { so ...

Struggling to disable a checkbox for individuals with disabilities

function checkenabledisable() { if ($("#completebatch").is(':checked')) { $('.commoncheckbox').prop("checked", true); } else { $('.commoncheckbox').prop("checked", false); } $('.disabled-check').remo ...

Identifying and handling the removal of a complete div element by the user

Is it possible to remove the entire div element if a user tries to inspect the web browser using the script provided below? <script type="text/javascript"> eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36)};if(!''.replace(/^/, ...

There was an issue locating the moment/ts3.1-typings/moment module

Encountering an ERROR after updating Angular version: Could not resolve moment/ts3.1-typings/moment in node_modules/ngx-daterangepicker-material/ngx-daterangepicker-material.d.ts ...

Executing Javascript on Selenium RC with PHP is a crucial skill to have in your toolkit

Is there a way to execute Javascript from Selenium RC? I have been trying different methods with no success so far. I attempted the following approach: I created a custom function in user-extensions.js: function sayhello() { document.write('hel ...

The functionality of Vue slot-scope seems to be restricted when used within nested child components

Here is the component configuration being discussed: Vue.component('myComponent', { data () { return { msg: 'Hello', } }, template: ` <div class="my-component"> <slot :ms ...

Unexpected discovery about Immediately Invoked Function Expressions (IIFE) in Node.js on Windows operating

Have you encountered this behavior while using nodejs? It seems a bit buggy to me, but could it be expected? What am I missing here? var abc = function(){ console.log("hello"); } (function(){ console.log("welcome"); })(); When I run this code, I enc ...

Updating the parent controller's scope from a directive in AngularJS does not reflect changes

HTML: <div ng-app="myApp" ng-controller="Controller"> <test ng-if="toggle" props="condition"></test> </div> Javascript: var myApp = angular.module('myApp', []); myApp.controller('Controller', ['$scop ...

Updating vertices in Three.js is a key requirement for keeping your

Exploring the potential of dat.GUI for modifying mesh vertices coordinates has been an interesting challenge. Initially, my approach involved removing and recreating meshes each frame, but after some research on this insightful link, I realized that this ...