javascript - 3d 到 2d 投影算法(透视投影)- Javascript

标签 javascript projection perspective

我正在寻找采用 3D 坐标并将其更改为 2D 坐标的算法。

我尝试了此维基百科页面中的步骤:https://en.wikipedia.org/wiki/3D_projection#Perspective_projection

到目前为止我的代码是这样的:

      var WIDTH = 1280/2;
      var HEIGHT = 720/2;
      // Distance from center of Canvas (Camera) with a Field of View of 90 digress, to the Canvas
      var disToCanvas = Math.tan(45) * WIDTH/2;
      
      var canvas = document.createElement('canvas');
      canvas.width = WIDTH;
      canvas.height = HEIGHT;
      
      document.body.appendChild(canvas);
      
      var ctx = canvas.getContext('2d');
      
      var Player = function (){ // Camera
      // Camera Coordinates
      	this.x = 0;
        this.y = 0;
        this.z = 0;
      // Camera Rotation (Angle)
        this.rx = 0;
        this.ry = 90;
        this.rz = 0;
      };
      var player = new Player();
      
      var Point = function (x, y ,z){
      // Point 3D Coordinates
      	this.x = x;
        this.y = y;
        this.z = z;
      // Point 2D Coordinates
        this.X2d = 0;
        this.Y2d = 0;
        
      // The function that changes 3D coordinates to 2D
        this.update = function (){
          var X = (player.x - this.x);
          var Y = (player.y - this.y);
          var Z = (player.z - this.z);
          
          var Cx = Math.cos(player.rx); // cos(θx)
          var Cy = Math.cos(player.ry); // cos(θy)
          var Cz = Math.cos(player.rz); // cos(θz)
          
          var Sx = Math.sin(player.rx); // sin(θx)
          var Sy = Math.sin(player.ry); // sin(θy)
          var Sz = Math.sin(player.rz); // sin(θz)
          
          var Dx = Cy * (Sy*Y + Cz*X) - Sy*Z;
          var Dy = Sx * (Cy*Z + Sy * (Sz*Y + Cz*X)) + Cx * (Cy*Y + Sz*X);
          var Dz = Cx * (Cy*Z + Sy * (Sz*Y + Cz*X)) - Sx * (Cy*Y + Sz*X);
          
          var Ex = this.x / this.z * disToCanvas; // This isn't 100% correct
          var Ey = this.y / this.z * disToCanvas; // This isn't 100% correct
          var Ez = disToCanvas;                   // This isn't 100% correct
          
          this.X2d = Ez/Dz * Dx - Ex + WIDTH/2;  // Adding WIDTH/2 to center the camera
          this.Y2d = Ez/Dz * Dy - Ez + HEIGHT/2; // Adding HEIGHT/2 to center the camera
        }
      }
      // CREATING, UPDATING AND RENDERING A SQUARE
      var point = [];
      point[0] = new Point(10, 10, 10);
      point[1] = new Point(20, 10, 10);
      point[2] = new Point(20, 20, 10);
      point[3] = new Point(10, 20, 10);
      
      var run = setInterval(function (){
      	for (key in point){
        	point[key].update();
        }
        
        ctx.beginPath();
        ctx.moveTo(point[0].X2d, point[0].Y2d);
        ctx.lineTo(point[1].X2d, point[1].Y2d);
        ctx.lineTo(point[2].X2d, point[2].Y2d);
        ctx.lineTo(point[3].X2d, point[3].Y2d);
        ctx.lineTo(point[0].X2d, point[0].Y2d);
        
      }, 1000/30);
html, body {
      	width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
        
        background: rgba(73,72,62,.99);
      }
      canvas {
      	position: absolute;
        margin: auto;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        
        outline: 1px solid white;
      }
<html>
  <head>
  </head>
  <body>
  </body>
</html>

我想要一个可以根据相机的位置和旋转将 3D 转换为 2D 的函数。

最佳答案

查看您链接的维基百科页面,您的 D 方程似乎有错误。它应该是:

var Dx = Cy * (Sz*Y + Cz*X) - Sy*Z;
var Dy = Sx * (Cy*Z + Sy * (Sz*Y + Cz*X)) + Cx * (Cz*Y + Sz*X);
var Dz = Cx * (Cy*Z + Sy * (Sz*Y + Cz*X)) - Sx * (Cz*Y + Sz*X);

此外,我认为您使用了错误的 E 坐标,它是“观看者相对于显示表面的位置”,不应该依赖于该点的坐标。

您的 2D 位置的 y 坐标似乎也包含错误;您使用 Ez 而不是 Ey。

另外我可以推荐this site 。它是为 C++ 和 OpenGL 编写的,但它包含许多很好的解释和图表,可以帮助您更好地理解您正在尝试执行的操作。

关于javascript - 3d 到 2d 投影算法(透视投影)- Javascript,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47394970/

相关文章:

javascript - 如何在javascript中添加 'delete all button'

java - 没有 createQuery() 的 Hibernate 连接

html - 为什么更新某些样式时透视图没有给出相同的结果?

css - Android 版 Chrome 上的纯 CSS 视差滚动效果

javascript - 如何仅在正文(而不是页眉和页脚)上启用反弹过度滚动?

javascript - PHP include != JS 加载

javascript - 单击 React 在新窗口中打开组件

sql - 这个投影会返回什么?

c++ - 使用 GDAL/OGR 库从二维地理引用栅格数据阵列重新投影栅格数据

python - 透视变换在 PIL 中是如何工作的?