Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/457.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使用Matrix4.setLookAt在场景中移动摄影机_Javascript_Webgl - Fatal编程技术网

Javascript 如何使用Matrix4.setLookAt在场景中移动摄影机

Javascript 如何使用Matrix4.setLookAt在场景中移动摄影机,javascript,webgl,Javascript,Webgl,正在尝试在webGL中制作第一人称摄影机控制器。我试图使用Matrix4.setLookAt()函数来实现这一点,但我不确定如何计算(坦率地说,有点不确定需要修改哪些参数以及何时修改)如何移动。我目前实现的“向左看”和“向右看”的方式最初似乎可以正常工作,但一旦g_eyeX值接近1.0或-1.0,它就会开始将摄影机从场景中的立方体移开(在负x方向移开)。我找不到太多关于如何利用此函数在场景中移动“摄影机”的文档,因为其中大部分引用了three.js(我正在尝试了解它的工作原理,不想使用库)。谁能

正在尝试在webGL中制作第一人称摄影机控制器。我试图使用Matrix4.setLookAt()函数来实现这一点,但我不确定如何计算(坦率地说,有点不确定需要修改哪些参数以及何时修改)如何移动。我目前实现的“向左看”和“向右看”的方式最初似乎可以正常工作,但一旦g_eyeX值接近1.0或-1.0,它就会开始将摄影机从场景中的立方体移开(在负x方向移开)。我找不到太多关于如何利用此函数在场景中移动“摄影机”的文档,因为其中大部分引用了three.js(我正在尝试了解它的工作原理,不想使用库)。谁能给我一些帮助或者给我指出正确的方向?我们将不胜感激

下面列出了我的代码,下面是setLookAt函数的参数 矩阵4.setLookAt(eyeX,eyeY,eyeZ,atX,atY,atZ,upX,upY,upZ)

“眼X,Y,Z”-指定眼点的位置 “atX、atY、atZ”-指定注视点的位置 “upX,upY,upZ”-指定场景中的向上方向

JS:

//sceneWalker.js
//修改自RotatingTriangle.js(c)2012 matsuda
//使用非索引立方体-每边2个三角形-36个顶点
//顶点着色器程序
var-VSHADER_源=
'属性向量4 a_位置\不+
'统一mat4 u_视图矩阵\不+
'统一mat4 u_模型矩阵\不+
“一致mat4 u_ProjMatrix\不+
'void main(){\n'+
'gl_Position=u_ProjMatrix*u_ViewMatrix*u_ModelMatrix*a_Position;\n'+
'}\n';
//片段着色器程序
var FSHADER_源=
'void main(){\n'+
'gl_FragColor=vec4(1.0,0.0,0.0,1.0);\n'+
'}\n';
//旋转角度(度/秒)
var角_阶跃=0.0;
var移动金额=0.0;
var g_eyeX=0.0,g_eyeY=0.0,g_eyeZ=0.25;//眼睛位置
var g_curX=0.0,g_curZ=-3.0;
函数main(){
//检索元素
var canvas=document.getElementById('webgl');
//获取WebGL的渲染上下文
var gl=getWebGLContext(画布);
如果(!gl){
log('未能获取WebGL的呈现上下文');
返回;
}
//初始化着色器
if(!initShaders(gl、VSHADER_源、FSHADER_源)){
log('初始化着色器失败');
返回;
}
//将顶点的位置写入顶点着色器
var n=initVertexBuffers(gl);
if(n<0){
console.log('未能设置顶点的位置');
返回;
}
//指定要清除的颜色
gl.clearColor(0.0,0.0,0.0,1.0);
//获取u_ViewMatrix的存储位置
var u_ViewMatrix=gl.getUniformLocation(gl.program,“u_ViewMatrix”);
如果(!u_ViewMatrix){
console.log('无法获取u_ViewMatrix的存储位置');
返回;
}
var u_ModelMatrix=gl.getUniformLocation(gl.program,“u_ModelMatrix”);
如果(!u_ModelMatrix){
console.log('未能获取u_ModelMatrix的存储位置');
返回;
}
var u_ProjMatrix=gl.getUniformLocation(gl.program,“u_ProjMatrix”);
如果(!u_ModelMatrix){
console.log('未能获取u_ProjMatrix的存储位置');
返回;
}   
//当前旋转角度
var currentAngle=0.0;
//模型矩阵
var modelMatrix=new Matrix4();
var viewMatrix=新矩阵4();
var projMatrix=新矩阵4();
modelMatrix.setTranslate(0,0100);
setLookAt(g_-eyeX,g_-eyeY,g_-eyeZ,0,0,0,1,0);
projMatrix.setPerspective(45,(canvas.width)/(canvas.height),0.1100000);
gl.uniformMatrix4fv(u_ModelMatrix,false,ModelMatrix.elements);
gl.uniformMatrix4fv(u_ViewMatrix,false,ViewMatrix.elements);
gl.uniformMatrix4fv(u_ProjMatrix,false,ProjMatrix.elements);
document.onkeydown=函数(ev){keydown(ev,gl,n,u_ViewMatrix,ViewMatrix);};
//开始绘图
var tick=函数(){
//currentAngle=动画(currentAngle);//更新旋转角度
绘制(gl,n,currentAngle,modelMatrix,viewMatrix,u_modelMatrix,u_viewMatrix);//绘制三角形
requestAnimationFrame(勾号,画布);//请求浏览器调用勾号
};
勾选();
}
功能键控(ev、gl、n、u_ViewMatrix、ViewMatrix){
控制台日志(ev.keyCode);
如果(ev.keyCode==39){//按下右箭头键
g_eyeX-=0.01;
控制台日志(g_eyeX);
}否则
如果(ev.keyCode==37){//按下左箭头键
g_eyeX+=0.01;
控制台日志(g_eyeX);
}
如果(ev.keyCode==38){
g_eyeY+=0.01;
}
如果(ev.keyCode==40){
g_eyeY-=0.01;
}
如果(ev.keyCode==68){
g_curX-=0.01;
}
如果(ev.keyCode==65){
g_curX+=0.01;
}
如果(ev.keyCode==87){
g_curZ+=0.01;
}
如果(ev.keyCode==83){
g_curZ-=0.01;
}
else{return;}
}
函数initVertexBuffers(gl){
var顶点=新数组([
-0.5, 0.5, 0.5,
-0.5, -0.5, 0.5,
0.5, -0.5, 0.5,
-0.5, 0.5, 0.5,
0.5, -0.5, 0.5,
0.5, 0.5, 0.5,
0.5, 0.5, 0.5,
0.5, -0.5, 0.5,
0.5, -0.5, -0.5,
0.5, 0.5, 0.5,
0.5, -0.5, -0.5,
0.5, 0.5, -0.5,
0.5, -0.5, 0.5,
-0.5, -0.5, 0.5,
-0.5, -0.5, -0.5,
0.5, -0.5, 0.5,
-0.5, -0.5, -0.5,
0.5, -0.5, -0.5,
0.5, 0.5, -0.5,
-0.5, 0.5, -0.5,
-0.5, 0.5, 0.5,
0.5, 0.5, -0.5,
-0.5, 0.5, 0.5,
0.5, 0.
 // sceneWalker.js
    // modified from RotatingTriangle.js (c) 2012 matsuda
    // uses a non-indexed cube - 2 triangles per side - 36 vertices
    // Vertex shader program
    var VSHADER_SOURCE =
      'attribute vec4 a_Position;\n' +
      'uniform mat4 u_ViewMatrix;\n' +
      'uniform mat4 u_ModelMatrix;\n' +
      'uniform mat4 u_ProjMatrix;\n' +
      'void main() {\n' +
      '  gl_Position = u_ProjMatrix * u_ViewMatrix * u_ModelMatrix * a_Position;\n' +
      '}\n';

    // Fragment shader program
    var FSHADER_SOURCE =
      'void main() {\n' +
      '  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
      '}\n';

    // Rotation angle (degrees/second)
    var ANGLE_STEP = 0.0;
    var MOVE_AMOUNT = 0.0;
    var g_eyeX = 0.0, g_eyeY = 0.0, g_eyeZ = 0.25; // Eye position
    var g_curX = 0.0, g_curZ = -3.0;

    function main() {
      // Retrieve <canvas> element
      var canvas = document.getElementById('webgl');

      // Get the rendering context for WebGL
      var gl = getWebGLContext(canvas);
      if (!gl) {
        console.log('Failed to get the rendering context for WebGL');
        return;
      }

      // Initialize shaders
      if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
        console.log('Failed to intialize shaders.');
        return;
      }

      // Write the positions of vertices to a vertex shader
      var n = initVertexBuffers(gl);
      if (n < 0) {
        console.log('Failed to set the positions of the vertices');
        return;
      }

      // Specify the color for clearing <canvas>
      gl.clearColor(0.0, 0.0, 0.0, 1.0);

      // Get storage location of u_ViewMatrix
      var u_ViewMatrix = gl.getUniformLocation(gl.program, 'u_ViewMatrix');
      if (!u_ViewMatrix) { 
        console.log('Failed to get the storage location of u_ViewMatrix');
        return;
      }

      var u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix');
      if (!u_ModelMatrix) { 
        console.log('Failed to get the storage location of u_ModelMatrix');
        return;
      }

      var u_ProjMatrix = gl.getUniformLocation(gl.program, 'u_ProjMatrix');
        if (!u_ModelMatrix) { 
            console.log('Failed to get the storage location of u_ProjMatrix');
            return;
        }   
      // Current rotation angle
      var currentAngle = 0.0;
      // Model matrix
      var modelMatrix = new Matrix4();
      var viewMatrix = new Matrix4();
      var projMatrix = new Matrix4();
      modelMatrix.setTranslate(0, 0, 100);
      viewMatrix.setLookAt(g_eyeX, g_eyeY, g_eyeZ, 0, 0, 0, 0, 1, 0);
      projMatrix.setPerspective(45, (canvas.width)/(canvas.height), 0.1, 10000000);
      gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);
      gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix.elements);
      gl.uniformMatrix4fv(u_ProjMatrix, false, projMatrix.elements);

      document.onkeydown = function(ev){ keydown(ev, gl, n, u_ViewMatrix, viewMatrix); };
      // Start drawing
      var tick = function() {
        //currentAngle = animate(currentAngle);  // Update the rotation angle
        draw(gl, n, currentAngle, modelMatrix, viewMatrix, u_ModelMatrix, u_ViewMatrix);   // Draw the triangle
        requestAnimationFrame(tick, canvas); // Request that the browser calls tick
      };
      tick();
    }

    function keydown(ev, gl, n, u_ViewMatrix, viewMatrix) {
    console.log(ev.keyCode);
        if(ev.keyCode == 39) { // The right arrow key was pressed
          g_eyeX -= 0.01;
          console.log(g_eyeX);
        } else 
        if (ev.keyCode == 37) { // The left arrow key was pressed
          g_eyeX += 0.01;
          console.log(g_eyeX);
        }
        if(ev.keyCode == 38){
            g_eyeY += 0.01;
        }
        if(ev.keyCode == 40){
            g_eyeY -= 0.01;
        }
        if(ev.keyCode == 68){
            g_curX -= 0.01;
        }
        if(ev.keyCode == 65){
            g_curX += 0.01;
        }
        if(ev.keyCode == 87){
            g_curZ += 0.01;
        }
        if(ev.keyCode == 83){
            g_curZ -= 0.01;
        }
        else { return; }   
    }


    function initVertexBuffers(gl) {
      var vertices = new Float32Array ([
        -0.5, 0.5, 0.5,
        -0.5, -0.5, 0.5,
        0.5, -0.5, 0.5,
        -0.5, 0.5, 0.5,
        0.5, -0.5, 0.5,
        0.5, 0.5, 0.5,
        0.5, 0.5, 0.5,
        0.5, -0.5, 0.5,
        0.5, -0.5, -0.5,
        0.5, 0.5, 0.5,
        0.5, -0.5, -0.5,
        0.5, 0.5, -0.5,
        0.5, -0.5, 0.5,
        -0.5, -0.5, 0.5,
        -0.5, -0.5, -0.5,
        0.5, -0.5, 0.5,
        -0.5, -0.5, -0.5,
        0.5, -0.5, -0.5,
        0.5, 0.5, -0.5,
        -0.5, 0.5, -0.5,
        -0.5, 0.5, 0.5,
        0.5, 0.5, -0.5,
        -0.5, 0.5, 0.5,
        0.5, 0.5, 0.5,
        -0.5, -0.5, -0.5,
        -0.5, 0.5, -0.5,
        0.5, 0.5, -0.5,
        -0.5, -0.5, -0.5,
        0.5, 0.5, -0.5,
        0.5, -0.5, -0.5,
        -0.5, 0.5, -0.5,
        -0.5, -0.5, -0.5,
        -0.5, -0.5, 0.5,
        -0.5, 0.5, -0.5,
        -0.5, -0.5, 0.5,
        -0.5, 0.5, 0.5
      ]);
      var n = 36;   // The number of vertices

      // Create a buffer object
      var vertexBuffer = gl.createBuffer();
      if (!vertexBuffer) {
        console.log('Failed to create the buffer object');
        return -1;
      }

      // Bind the buffer object to target
      gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
      // Write date into the buffer object
      gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

      // Assign the buffer object to a_Position variable
      var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
      if(a_Position < 0) {
        console.log('Failed to get the storage location of a_Position');
        return -1;
      }
      gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, 0, 0);

      // Enable the assignment to a_Position variable
      gl.enableVertexAttribArray(a_Position);

      return n;
    }

    function draw(gl, n, currentAngle, modelMatrix, viewMatrix, u_ModelMatrix, u_ViewMatrix) {
      // Set the rotation matrix
      modelMatrix.setRotate(currentAngle, 1, 1, 1); 
      modelMatrix.setTranslate(g_curX, 0, g_curZ);

      viewMatrix.setLookAt(g_eyeX, g_eyeY, g_eyeZ, 0, 0, 0, 0, 1, 0);
      // Pass the rotation matrix to the vertex shader
      gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix.elements);
      gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);

      // Clear <canvas>
      gl.clear(gl.COLOR_BUFFER_BIT);

      // Draw the rectangle
      gl.drawArrays(gl.TRIANGLES, 0, n);
    }

    // Last time that this function was called
    var g_last = Date.now();
    function animate(angle) {
      // Calculate the elapsed time
      var now = Date.now();
      var elapsed = now - g_last;
      g_last = now;
      // Update the current rotation angle (adjusted by the elapsed time)
      var newAngle = angle + (ANGLE_STEP * elapsed) / 1000.0;
      return newAngle %= 360;
    }
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Cube</title>
  </head>

  <body onload="main()">
    <canvas id="webgl" width="400" height="400">
    Please use a browser that supports "canvas"
    </canvas>

    <script src="../lib/webgl-utils.js"></script>
    <script src="../lib/webgl-debug.js"></script>
    <script src="../lib/cuon-utils.js"></script>
    <script src="../lib/cuon-matrix.js"></script>
    <script src="sceneWalker.js"></script>
  </body>
</html>
/** @constructor */
function FPSCamera(){
    this.pos = [0.0, 0.0, 0.0];

    this.dir = [0.0, 0.0, -1.0]; // or forward
    this.up = [0.0, 1.0, 0.0];
    this.side = [1.0, 0.0, 0.0]; // or right
}

FPSCamera.prototype.forward = function(dist){
    this.pos[0] += this.dir[0] * dist;
    this.pos[1] += this.dir[1] * dist;
    this.pos[2] += this.dir[2] * dist;
};
// do the same for other 2 directions, strife and fly

// looks to left/right
FPSCamera.prototype.yaw = function(radians){
    var orientationChange = ORIENTATION.fromAxisAngle(this.up, radians);
    this.dir = VEC3.rotatedByOrientation(this.dir, orientationChange);
    this.side = VEC3.cross(this.dir, this.up);
    this.side = VEC3.normalize(this.side);
};

// same for pitch... except the rotation axis is this.side and you need to ensure the pitch is within +/- 90 degrees

FPSCamera.prototype.getViewMatrix = function(){
    // matrix can be extracted from the 3 direction vectors, but lets use lookAt here;
    return MAT4.lookAt(this.pos, VEC3.plus(this.pos, this.dir), this.up);
};