Encountering issues with parsing normals in THREE.js json mesh format

UPDATE: The demo is finally live! Check it out here: . Use the dropdown menu to switch between torus models and see the issue in action. Please note that WebGL MRT extensions are required for this demo.

I have been working on developing my own WebGL deferred rendering engine for some time now, and I have successfully created a prototype using GBuffers and MRT extensions that effectively renders teapots. This project was started from scratch as a way for me to learn WebGL thoroughly without relying on any frameworks, while gaining a deep understanding of deferred rendering. For those interested, the source code can be found on GitHub at: https://github.com/bharling/webgl-defer

After getting tired of only seeing teapots, I attempted to implement a loader for models in THREE.js JSON format. While I managed to load meshes with accurate vertices and index buffers, the normals did not render correctly. I chose to support indexed geometry with vertex UVs, vertex normals, and a single material for now (with plans to move towards PBR). Any other data in the JSON file is ignored, and only supported data is written directly to Float32Arrays, among others. Below is the code snippet for importing the model, along with a screenshot showing the abnormal normals being encountered:


// Importing a ThreeJS model
parseThreeJSModel: (data) => {
    // Parsing logic goes here...
}

The screenshot above showcases the world-space normals gbuffer which displays the issue.

One major divergence in my engine is that I do not store face information in classes like `THREE.Face3`, but instead write the data directly into buffer attributes, similar to `THREE.BufferGeometry`.

So far, I had been using the Utah Teapot model from the 'Learning WebGL' course, specifically from this link: . This model works perfectly fine in my engine and supposedly follows an early version of the THREE JSON format. However, even a simple cube exported from the latest Blender exporter does not perform as expected.

Any suggestions or insights would be greatly appreciated. Thank you!

UPDATE: Here is a screenshot showing the normal pass using the teapot model from the WebGL tutorials. Note: I am not implying that the THREE.js exporter is faulty; rather, it seems there might be an issue with my parsing code. After extensively reviewing the GBuffer implementation in this engine over the past year, I am confident it is correct now. I just seem to be struggling with understanding the THREE.js JSON model format.

https://i.sstatic.net/QsoBK.png

Answer №1

Unsure if the translation of Three.Face3 to buffers is accurate. Here is a custom Three Json parser that I utilize for loading animated skinned mesh from blender, which could offer some assistance. Note that only partial features are supported, and it generates indexed buffers for use with .drawElements instead of .drawArrays.

function parsePackedArrayHelper(outArray, index, dataArray, componentSize){
    for (var c = 0; c<componentSize; c++){
        outArray.push(dataArray[index*componentSize + c]);
    }
}

function parseThreeJson(geometry){
    if (isString(geometry)){
        geometry = JSON.parse(geometry);
    }

    var faces = geometry["faces"];
    faces = convertQuadToTrig(faces); // recommend using the triangulate modifer in blender
    // and other data manipulations...

    var seenVertices = new Map();
    var currentIndex = 0;
    var maxIndex = 0;

    var c = 0; // current index into the .faces array
    while (c < faces.length){
        var bitInfo = faces[c];
        var hasMaterials = (bitInfo &(1<<1)) !== 0;
        var hasVertexUvs = (bitInfo &(1<<3)) !== 0;
        var hasVertexNormals = (bitInfo &(1<<5)) !== 0;
        var faceIndex = c+1;

        c += (
            4 + //1 for the bitflag and 3 for vertex positions
            (hasMaterials? 1: 0) +
            (hasVertexUvs? 3: 0) +
            (hasVertexNormals ? 3: 0)
        );

        for (var v = 0;v<3;v++){
            var s = 0; 
            var vertIndex = faces[faceIndex+v];
            var uvIndex = -1;
            var normalIndex = -1;
            var materialIndex = -1;
            if (hasMaterials){
                s += 1;
                materialIndex = faces[faceIndex+3];
            }
            if (hasVertexUvs){
                s += 3;
                uvIndex = faces[faceIndex+s+v];
            }
            if (hasVertexNormals){
                s += 3;
                normalIndex = faces[faceIndex+s+v];
            }

            var hash = ""+vertIndex+","+uvIndex+","+normalIndex;
            if (seenVertices.has(hash)){
                indices[currentIndex++] = seenVertices.get(hash);
            } else {
                seenVertices.set(hash, maxIndex);
                indices[currentIndex++] = maxIndex++;
                parsePackedArrayHelper(verticesOut, vertIndex, verticesData, 3);
                if (boneInfluences > 1){
                    // skipping skinning data
                }
                if (hasVertexUvs){
                    parsePackedArrayHelper(uvsOut, uvIndex, uvsData[0], 2);

                    // flip uv vertically; may or may not be needed
                    var lastV = uvsOut[uvsOut.length-1];
                    uvsOut[uvsOut.length-1] = 1.0 - lastV;

                }
                if (hasVertexNormals){
                    parsePackedArrayHelper(normalsOut, normalIndex, normalsData, 3);
                }

                if (hasMaterials){
                    materialIndexOut.push(materialIndex);
                }
            }
        }
    }
}

Answer №2

While this may not be the exact answer you're looking for, it could still provide some useful information.

In situations where you are dealing with basic shapes like the boxes shown in the example, you have the option to utilize THREE.FlatShading instead of manually setting normals. This may prove to be a simpler approach in certain scenarios:

var material = new THREE.???Material({ shading: THREE.FlatShading });

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

What is the best way to utilize AJAX in sending chosen files to a PHP script?

I currently have two forms set up. Form A includes fields for name, age, address, email, and a hidden text field that holds the names of images to be uploaded in form B. Form B allows users to browse and select their photos using an input type File. ...

Finding Node.js modules with a specific field: A comprehensive guide

Inquiry: What is the method to import modules that contain the example field in their package.json? Illustrative instance: const path = require( "path" ); const glob = require( "glob" ); const modules = glob.sync( './node_modules/*' ); for ( ...

"Enhance the user experience by enabling clickable preview files in dropzone

After working on my Django project, I have implemented the following: <link href="{% static 'media/dropzone/dist/min/dropzone.min.css' %}" type="text/css" rel="stylesheet" /> <form class="dropzone" id="my-media-dropzone" action="/some/u ...

What is the process for accessing extra scope information with next-auth?

I have integrated next-auth with Discord authentication and included guilds in my scope, but I am unable to retrieve the guild data. How can this issue be resolved? const options = { providers: [ Providers.Discord({ clientId: process.env.DISC ...

Discover how to achieve the detail page view in Vue Js by clicking on an input field

I'm a beginner with Vuejs and I'm trying to display the detail page view when I click on an input field. <div class="form-group row"> <label for="name" class="col-sm-2 col-form-label">Name</label> ...

What is the most efficient way to transfer form data from one JSP page to another?

I need to transfer information from one webpage (1.jsp) to another webpage (2.jsp). The data that needs to be transferred includes checkboxes, radio buttons, and drop downs. This data will be used in 2.jsp to generate the appropriate page. Is there a way ...

What are the steps to integrate TypeScript into JavaScript code?

How can I import a TypeScript class in a Node CommonJS JavaScript file? When using mongoose in my TypeScript code, I typically do the following: // user.model.ts export const UserModel = model<User>('User', schema); In my JavaScript code: ...

Are there alternative methods for handling routes in React, other than using the react-router-dom@latest library?

Currently, I am focused on a frontend project. One of the tasks at hand is to configure the network of routes. During my research, I came across react-router-dom@latest as a potential solution. However, I am curious to explore alternative options availa ...

403 Error Code - Access Denied when trying to access Cowin Setu APIs

While attempting to create a covid vaccine alert using the Cowin Setu API (India) in nodejs, I encountered a strange issue. Every time I send a get request, I receive a 403 response code from cloudfront stating 'Request Blocked', although it work ...

The AngularJS directive is being triggered before the Jquery AJAX request is completed

I am currently facing an issue where the chart in my AngularJS application (using NVD3.org) is loading before the AJAX call completes and data is fetched. How can I ensure that the chart waits for the AJAX call to finish? <script> var dataxx= ...

Is there a way to keep the node text in place and prevent overlapping in my D3.js tree?

I'm facing an issue with long text strings in my D3 tree. The nodes move according to the tree structure, but how can I handle excessively long node-text? For instance, if the label "T-ALL" had a longer name, it could overlap with the neighboring nod ...

The Node.js application successfully receives an emit event from the browser, however, the browser does not receive any emit

I'm having trouble understanding why the node.js server can connect and receive an emit() from the browser, but when I try to emit() back from node.js it doesn't reach the browser. Am I overlooking something here? The console log displays "Test ...

What is the best way to center text on an HTML canvas?

Is it possible to center an h1 tag in the middle of an HTML canvas using either JavaScript or HTML? I already have a CSS file for canvas styles. HTML <body> <canvas id="myCanvas"></canvas> <script src="canvas.js"></scri ...

Highlighting JavaScript code with React Syntax Highlighter exclusively

I've been struggling to highlight Ruby code, but it seems like no matter what I do, it keeps highlighting JavaScript instead. It's frustrating because I can't seem to get it right. import React from "react"; import atom from "node_module ...

Achieve horizontal bar movement by utilizing google.visualization.DataTable in a left-to-right motion

I am exploring the possibility of reversing the direction of a chart(bar) using google.visualization.DataTable. In the current setup, the bar progresses from left to right, but I wish for it to move from right to left instead. Below is what I have attempte ...

Tips for applying a texture to only one side of a cube without using THREE.MultiMaterial to lower draw calls

Imagine a scenario where there is a cube featuring 2 different materials. While I am utilizing MultiMaterial, I have noticed that it results in 6 draw calls instead of just 2. This concerns me in terms of performance, especially if the project is scaled up ...

How to Improve Performance for 15,000 Socket.io Users

I am facing an issue with my chat application that has large chatrooms, with 15,000 users connected to a single room. Only a few have the privilege to write messages, so in theory, there should not be a significant load on the server. However, I have obser ...

Use Google Maps and MySql to retrieve specific markers within a designated radius using unique latitude and longitude coordinates

Can the latitude and longitude of specific coordinates within a certain radius be retrieved from a database? ...

Ways to track all requests completed in Nuxt 3

I am looking to create a unique loading page that conceals itself once all requests and static data have been loaded, including static images and libraries. How can I determine when all requests and static data have finished loading? I have attempted the ...

What is the best method for conducting comprehensive testing of all projects and libraries within NestJS (nx)?

Our NestJS project has been established with multiple libraries through Nx. We have successfully run tests on individual projects/libraries using the following command: npx nx test lib1 --coverage While this method works well, we are faced with numerous l ...