为什么这组F在这个轨迹旋转

Why is this set of F rotating in this locus

在这段代码中,我无法理解为什么旋转不是在圆形轨迹中。这可能是这背后的基本逻辑,但我不明白为什么这个轨迹如此随机。

我在轨道运动中旋转相机,但它没有跟随它。

据我所知,我创建了一个轨道运动相机,它的逆矩阵是视图矩阵。所以,视图矩阵将改变世界 space 为此 result.Is 我的思维过程有什么错误吗?

"use strict";

const vertexShader = `#version 300 es

    in vec4 a_position;
    in vec4 a_color;

    out vec4 v_color;

    uniform mat4 u_matrix;

    void main(){
        gl_Position = u_matrix*a_position;
        v_color = a_color;
    }
`;


const fragShader = `#version 300 es

    precision highp float;

        in vec4 v_color;
        out vec4 frag_color;

        void main(){
            frag_color = v_color;
        }
`;

var cameraAngleDegree = 0;
var  cameraAngle = 0;
const radius = 100;
var increment = 1;
var numFs = 5;
function main() {

    var canvas = document.querySelector("#canvas");
    var gl = canvas.getContext("webgl2");
    if (!gl) {
        return;
    }
    requestAnimationFrame(function() {
        init(gl);
    });
}

function init(gl) {


    const program = webglUtils.createProgramFromSources(gl, [vertexShader, fragShader]);

    const apositionLoc = gl.getAttribLocation(program, 'a_position');
    const acolorLoc = gl.getAttribLocation(program, 'a_color');
    const umatrixLoc = gl.getUniformLocation(program, 'u_matrix');

    let vao = gl.createVertexArray();
    gl.bindVertexArray(vao);

    let positionBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
    setGeometry(gl);
    gl.enableVertexAttribArray(apositionLoc);

    let size = 3;
    let type = gl.FLOAT;
    let normalize = false;
    let stride = 0;
    let offset = 0;
    gl.vertexAttribPointer(apositionLoc, size, type, normalize, stride, offset);

    let colorBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
    setColor(gl);
    gl.enableVertexAttribArray(acolorLoc);

    size = 3;
    type = gl.UNSIGNED_BYTE;
    normalize = true;
    stride = 0;
    offset = 0;
    gl.vertexAttribPointer(acolorLoc, size, type, normalize, stride, offset);

    let fov = degreeToRadian(60);
    cameraAngle = degreeToRadian(cameraAngleDegree);

    function degreeToRadian(deg) {
        return deg * Math.PI / 180;
    }

    function radToDegree(rad) {
        return rad * (180) / Math.PI;
    }

    drawScene();

    // webglLessonsUI.setupSlider("#cameraAngle", { value: radToDegree(cameraAngle), slide: updateCameraAngle, min: -360, max: 360 });

    // function updateCameraAngle(event, ui) {
    //     cameraAngle = degreeToRadian(ui.value);
    //     drawScene();
    // }


    function drawScene() {

        webglUtils.resizeCanvasToDisplaySize(gl.canvas);

        gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

        gl.enable(gl.CULL_FACE);

        gl.enable(gl.DEPTH_TEST);

        gl.useProgram(program);

        let aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;

        let projection = m4.perspective(fov, aspect, 1, 1000);

        const fPosition = [radius, 0, 0];

        cameraAngleDegree += increment;

        cameraAngle =degreeToRadian(cameraAngleDegree);
        
        let camera = m4.yRotation(cameraAngle);
        camera = m4.translate(camera, 0, 100, 300);

        let cameraPosition = [camera[12], camera[13], camera[14]];

        // let up = [0, 1, 0];

        // camera = m4.lookAt(cameraPosition, fPosition, up);

        let viewMatrix = m4.inverse(camera);

        let viewProjection = m4.multiply(projection, viewMatrix);

        for (var ii = 0; ii < numFs; ++ii) {
            var angle = ii * Math.PI * 2 / numFs;

            var x = Math.cos(angle) * radius;
            var z = Math.sin(angle) * radius;
            var matrix = m4.translate(viewProjection, x, 0, z);

            // Set the matrix.
            gl.uniformMatrix4fv(umatrixLoc, false, matrix);

            // Draw the geometry.
            var primitiveType = gl.TRIANGLES;
            var offset = 0;
            var count = 16 * 6;
            gl.drawArrays(primitiveType, offset, count);
        }
        //     gl.uniformMatrix4fv(umatrixLoc, false, viewProjection);

        //     var primitives = gl.TRIANGLES;
        //     var count = 16 * 6;
        //     var offset = 0;
        //     gl.drawArrays(primitives, offset, count);

        // }

        requestAnimationFrame(function() {
            init(gl)
        });

    }
}

function setGeometry(gl) {

    let positions = new Float32Array([

        0, 0, 0,
        0, 150, 0,
        30, 0, 0,
        0, 150, 0,
        30, 150, 0,
        30, 0, 0,

        // top rung front
        30, 0, 0,
        30, 30, 0,
        100, 0, 0,
        30, 30, 0,
        100, 30, 0,
        100, 0, 0,

        // middle rung front
        30, 60, 0,
        30, 90, 0,
        67, 60, 0,
        30, 90, 0,
        67, 90, 0,
        67, 60, 0,

        // left column back
        0, 0, 30,
        30, 0, 30,
        0, 150, 30,
        0, 150, 30,
        30, 0, 30,
        30, 150, 30,

        // top rung back
        30, 0, 30,
        100, 0, 30,
        30, 30, 30,
        30, 30, 30,
        100, 0, 30,
        100, 30, 30,

        // middle rung back
        30, 60, 30,
        67, 60, 30,
        30, 90, 30,
        30, 90, 30,
        67, 60, 30,
        67, 90, 30,

        // top
        0, 0, 0,
        100, 0, 0,
        100, 0, 30,
        0, 0, 0,
        100, 0, 30,
        0, 0, 30,

        // top rung right
        100, 0, 0,
        100, 30, 0,
        100, 30, 30,
        100, 0, 0,
        100, 30, 30,
        100, 0, 30,

        // under top rung
        30, 30, 0,
        30, 30, 30,
        100, 30, 30,
        30, 30, 0,
        100, 30, 30,
        100, 30, 0,

        // between top rung and middle
        30, 30, 0,
        30, 60, 30,
        30, 30, 30,
        30, 30, 0,
        30, 60, 0,
        30, 60, 30,

        // top of middle rung
        30, 60, 0,
        67, 60, 30,
        30, 60, 30,
        30, 60, 0,
        67, 60, 0,
        67, 60, 30,

        // right of middle rung
        67, 60, 0,
        67, 90, 30,
        67, 60, 30,
        67, 60, 0,
        67, 90, 0,
        67, 90, 30,

        // bottom of middle rung.
        30, 90, 0,
        30, 90, 30,
        67, 90, 30,
        30, 90, 0,
        67, 90, 30,
        67, 90, 0,

        // right of bottom
        30, 90, 0,
        30, 150, 30,
        30, 90, 30,
        30, 90, 0,
        30, 150, 0,
        30, 150, 30,

        // bottom
        0, 150, 0,
        0, 150, 30,
        30, 150, 30,
        0, 150, 0,
        30, 150, 30,
        30, 150, 0,

        // left side
        0, 0, 0,
        0, 0, 30,
        0, 150, 30,
        0, 0, 0,
        0, 150, 30,
        0, 150, 0,

    ]);

    gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW)
}

function setColor(gl) {
    gl.bufferData(
        gl.ARRAY_BUFFER,
        new Uint8Array([
            // left column front
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,

            // top rung front
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,

            // middle rung front
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,

            // left column back
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,

            // top rung back
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,

            // middle rung back
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,

            // top
            70, 200, 210,
            70, 200, 210,
            70, 200, 210,
            70, 200, 210,
            70, 200, 210,
            70, 200, 210,

            // top rung right
            200, 200, 70,
            200, 200, 70,
            200, 200, 70,
            200, 200, 70,
            200, 200, 70,
            200, 200, 70,

            // under top rung
            210, 100, 70,
            210, 100, 70,
            210, 100, 70,
            210, 100, 70,
            210, 100, 70,
            210, 100, 70,

            // between top rung and middle
            210, 160, 70,
            210, 160, 70,
            210, 160, 70,
            210, 160, 70,
            210, 160, 70,
            210, 160, 70,

            // top of middle rung
            70, 180, 210,
            70, 180, 210,
            70, 180, 210,
            70, 180, 210,
            70, 180, 210,
            70, 180, 210,

            // right of middle rung
            100, 70, 210,
            100, 70, 210,
            100, 70, 210,
            100, 70, 210,
            100, 70, 210,
            100, 70, 210,

            // bottom of middle rung.
            76, 210, 100,
            76, 210, 100,
            76, 210, 100,
            76, 210, 100,
            76, 210, 100,
            76, 210, 100,

            // right of bottom
            140, 210, 80,
            140, 210, 80,
            140, 210, 80,
            140, 210, 80,
            140, 210, 80,
            140, 210, 80,

            // bottom
            90, 130, 110,
            90, 130, 110,
            90, 130, 110,
            90, 130, 110,
            90, 130, 110,
            90, 130, 110,

            // left side
            160, 160, 220,
            160, 160, 220,
            160, 160, 220,
            160, 160, 220,
            160, 160, 220,
            160, 160, 220,
        ]),
        gl.STATIC_DRAW);
}

main();
<!DOCTYPE html>
<html>

<head>
    <title>Traingle Webgl 2</title>
    <style type="text/css">
    @import url("https://webglfundamentals.org/webgl/resources/webgl-tutorials.css");

    body {
        margin: 0;
    }

    button {
        position: absolute;
    }

    canvas {
        width: 100vw;
        height: 100vh;
        display: block;
    }
    </style>
</head>

<body>
    <canvas id="canvas"></canvas>
    <div id="uiContainer">
        <div id="ui">
            <div id="cameraAngle"></div>
        </div>
    </div>
    <!--
for most samples webgl-utils only provides shader compiling/linking and
canvas resizing because why clutter the examples with code that's the same in every sample.
See https://webglfundamentals.org/webgl/lessons/webgl-boilerplate.html
and https://webglfundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html
for webgl-utils, m3, m4, and webgl-lessons-ui.
-->
    <script src="https://webglfundamentals.org/webgl/resources/webgl-utils.js"></script>
    <script src="https://webglfundamentals.org/webgl/resources/webgl-lessons-ui.js"></script>
    <script src="https://webglfundamentals.org/webgl/resources/m4.js"></script>
    <script src="https://greggman.github.io/webgl-helpers/webgl-gl-error-check.js"></script>
    <script type="text/javascript" src="js/lookat.js"></script>
    <!-- <script type="text/javascript" src="js/camera.js"></script> -->
</body>

</html>

如果我理解你的问题,你看到的问题是看起来相机离 Fs 越来越近和越来越远

问题是 Fs 的顶点数据是这样构建的,所以左上角前角位于 0,0,0,从那里他们去 +X 100 个单位(所以 100 个单位宽),+Y 150 个单位(所以 100 个单位高),+Z 30 个单位所以 30 个单位深

那么,当您围绕 100 个单位的圆绘制它们时,它们的原点就是您要定位的部分,您会得到这个

图像是自上而下的,所以 Fs 只是一个矩形。绿色圆圈是每个 F 的局部原点,即局部 0,0,0。 F 的其他顶点相对于该局部原点,因此它们在一侧更靠近外圆(相机的轨道),而在另一侧更远

您可以通过将 Fs 在 X 方向移动 -50 和在 Z 方向移动 -15 来修复它。换句话说

            var angle = ii * Math.PI * 2 / numFs;

            var x = Math.cos(angle) * radius - 50;
            var z = Math.sin(angle) * radius - 15;

这给了你这种情况

每个F的本地原点不再在圆上。​​

您也可以通过将 F 顶点数据居中来修复它,遍历所有顶点并从 X 中减去 50,从 Z 中减去 15。这会给您带来这种情况

现在每个F的原点都居中,局部原点在圆上。

另一种解决方法是计算 F 组的范围,计算范围的中心,将相机轨道的中心移动到那里,这就是这种情况