OBJ 模型未显示 WebGL

问题描述 投票:0回答:1

我正在使用 WebGL 开发一个项目,并且尝试显示一个简单的 OBJ,但是没有显示任何内容。这就是控制台显示的原因:

Unhandled Model Keyword: mtllib at line 1 loadModel.js:85:21
Unhandled Model Keyword: o at line 2 loadModel.js:85:21
Unhandled Model Keyword: usemtl at line 37 loadModel.js:85:21
Unhandled Model Keyword: s at line 38 loadModel.js:85:21
<empty string> app.js:68:13
<empty string> app.js:74:13
WebGL warning: drawArraysInstanced: Vertex fetch requires 36, but attribs only supply 26. 32
After reporting 32, no further warnings will be reported for this WebGL context.

这是我的代码:

index.html:

<!DOCTYPE html>

<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
    <link href="index.css" rel="stylesheet">
    <link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Source+Sans+Pro&display=swap" rel="stylesheet">
    
    <script src="gl-matrix-min.js" defer></script>
    <script type="module" src="app.js" defer></script>
</head>
<body>
    <canvas></canvas>
    <script>
        const c = document.getElementsByTagName("canvas")[0];
        c.width = window.innerWidth;
        c.height = window.innerHeight;
    </script>
</body>
</html>

App.js:

import "./gl-matrix-min.js";
const { mat2, mat2d, mat4, mat3, quat, quat2, vec2, vec3, vec4 } = glMatrix;

import { loadTexture } from "./loadTexture.js"
import { parseOBJ } from "./loadModel.js";
import { loadTextResource, repeat } from "./util.js";

window.onload = function (){
    loadTextResource('/Shaders/shader.vs.glsl', function(vsErr, vsText){
        if(vsErr){
            alert("Error getting vertex shader (check console for more info)");
            console.error(vsErr);
        }else{
            loadTextResource('/Shaders/shader.fs.glsl', function(fsErr, fsText){
                if(fsErr){
                    alert("Error getting fragment shader (check console for more info)");
                    console.error(fsErr);
                }else{
                    RunScene(vsText, fsText);
                }
            });
        }
    });
}
async function RunScene(vsText, fsText){
    const canvas = document.querySelector('canvas');
    const gl = canvas.getContext('webgl');

    if(!gl){
        console.error("WebGL not supported on this browser!");
    }

    const response = await fetch('Models/test.obj');
    const text = await response.text();
    const data = parseOBJ(text);

    //Vertex Data
    const vertexData = data.positions;

    // Image UV Data
    const uvData = data.texCoords;

    // F|L|B|R|T|U
    const normalData = data.normals;

//    console.log(normalData);

    const positionBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexData), gl.STATIC_DRAW);

    const uvBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(uvData), gl.STATIC_DRAW);

    const normalBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normalData), gl.STATIC_DRAW);

    const picture = loadTexture(gl, `Textures/Pablo.png`);

    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, picture);

    const vertexShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertexShader, vsText);
    gl.compileShader(vertexShader);
    console.log(gl.getShaderInfoLog(vertexShader));


    const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragmentShader, fsText);
    gl.compileShader(fragmentShader);
    console.log(gl.getShaderInfoLog(fragmentShader));

    const program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);

    const positionLocation = gl.getAttribLocation(program, 'position');
    gl.enableVertexAttribArray(positionLocation);
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
    gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);

    const uvLocation = gl.getAttribLocation(program, 'uv');
    gl.enableVertexAttribArray(uvLocation);
    gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer);
    gl.vertexAttribPointer(uvLocation, 2, gl.FLOAT, false, 0, 0);

    const normalLocation = gl.getAttribLocation(program, 'normal');
    gl.enableVertexAttribArray(normalLocation);
    gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
    gl.vertexAttribPointer(normalLocation, 3, gl.FLOAT, false, 0, 0);

    gl.useProgram(program);
    gl.enable(gl.DEPTH_TEST);

    const uniformLocations = {
        matrix: gl.getUniformLocation(program, 'matrix'),
        normalMatrix: gl.getUniformLocation(program, 'normalMatrix'),
        textureLocation: gl.getUniformLocation(program, 'textureID'),
    };


    const modelMatrix = mat4.create();
    const viewMatrix = mat4.create();
    const projectionMatrix = mat4.create();
    mat4.perspective(projectionMatrix, 75 * Math.PI/180, canvas.width/canvas.height, 1e-4, 1e4);

    const mvMatrix = mat4.create();
    const mvpMatrix = mat4.create();

    const normalMatrix = mat4.create();

    mat4.translate(viewMatrix, viewMatrix, [0, 0.01, 2]);
    mat4.invert(viewMatrix, viewMatrix);

    gl.uniform1i(uniformLocations.textureLocation, 0);

    function animate(){
        requestAnimationFrame(animate);

        mat4.rotateX(modelMatrix, modelMatrix, Math.PI/100);
        mat4.rotateY(modelMatrix, modelMatrix, Math.PI/200);

        mat4.multiply(mvMatrix, viewMatrix, modelMatrix);
        mat4.multiply(mvpMatrix, projectionMatrix, mvMatrix);
        
        mat4.invert(normalMatrix, mvMatrix);
        mat4.transpose(normalMatrix, normalMatrix);
        
        gl.uniformMatrix4fv(uniformLocations.matrix, false, mvpMatrix);
        gl.uniformMatrix4fv(uniformLocations.normalMatrix, false, normalMatrix);

        gl.drawArrays(gl.TRIANGLES, 0, vertexData.length/3);
    }

    animate();
}

loadModel.js:

export function parseOBJ(text){
    const objPositions = [[0, 0, 0]];
    const objTexCoords = [[0, 0]];
    const objNormals = [[0, 0, 0]];

    const objVertexData = [
        objPositions,
        objTexCoords,
        objNormals,
    ];
    
    let webglVertexData = [
        [], //Verts
        [], //UV
        [], //Normals
    ];

    function addVertex(vert) {
        const ptn = vert.split('/');
        ptn.forEach((objIndexStr, i) => {
            if (!objIndexStr) {
                return;
            }
            const objIndex = parseInt(objIndexStr);
            const dataArray = objVertexData[i];
    
            if (dataArray && dataArray.length > 0) {
                let index = objIndex > 0 ? objIndex - 1 : dataArray.length + objIndex;
                
                // Ensure the index is within bounds
                index = Math.max(0, Math.min(index, dataArray.length - 1));
    
                const data = dataArray[index];
                if (data !== undefined) {
                    webglVertexData[i].push(...dataArray[index]);
                } else {
                    console.error(`Error: Undefined data at index ${index} for objVertexData[${i}]`);
                }
            } else {
                console.error(`Error: No data found for objVertexData[${i}]`);
            }
        });
    }
    
    
    

    const keywords = {
        v(parts){
            objPositions.push(parts.map(parseFloat));
        },
        vn(parts){
            objTexCoords.push(parts.map(parseFloat));
        },
        vt(parts){
            objNormals.push(parts.map(parseFloat));
        },
        f(parts){
            const numTriangles = parts.length - 2;
            for(let tri = 0; tri < numTriangles; ++tri){
                addVertex(parts[0]);
                addVertex(parts[tri + 1]);
                addVertex(parts[tri + 2]);
            }
        }
    };

    const keywordRE = /(\w*)(?: )*(.*)/;
    const lines = text.split('\n');
    for(let lineNum = 0; lineNum < lines.length; ++lineNum){
        const line = lines[lineNum].trim();
        if(line === '' || line.startsWith('#')){
            continue;
        }

        const m = keywordRE.exec(line);
        if(!m){
            continue;
        }
        
        const [, keyword, unparsedArgs] = m;
        const parts = line.split(/\s+/).slice(1);
        const handler = keywords[keyword];
        if(!handler){
            console.warn('Unhandled Model Keyword:', keyword, 'at line', lineNum + 1);
            continue;
        }
        handler(parts, unparsedArgs);
    }

    return {
        positions: webglVertexData[0],
        texCoords: webglVertexData[1],
        normals: webglVertexData[2]
    };
}

我相信某些顶点没有提供给 WebGL,但是,当我打印出顶点时,它显示长度为 36 并且顶点本身与 OBJ 文件的顶点匹配。

javascript webgl
1个回答
0
投票

检查您的 OBJ 文件。您报告的错误通常意味着您没有正确定义 OBJ 文件。它们应该看起来像这样:

# Blender v2.80 (sub 74) OBJ File: ''
# www.blender.org
mtllib test_with_texture.mtl
o Cube
v 1.000000 1.000000 -1.000000
...
...
...
v -1.000000 -1.000000 -1.000000

注意

mtllib
o cube
。可能意味着您没有正确定义 OBJ 纹理。

未处理的模型关键字:第 1 行的 mtllib loadModel.js:85:21 未处理的模型关键字:o 在第 2 行 loadModel.js:85:21

请参阅此答案了解更多信息。

© www.soinside.com 2019 - 2024. All rights reserved.