【问题标题】:3d to 2d Projection Algorithm (Perspective projection) - Javascript3d 到 2d 投影算法(透视投影) - Javascript
【发布时间】:2018-05-03 20:19:15
【问题描述】:

我正在寻找采用 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 的函数。

【问题讨论】:

  • 你找到这个了吗?我尝试使用建议的修复方法重现您的实验,但无济于事。

标签: javascript projection perspective


【解决方案1】:

查看您链接的维基百科页面,您的 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 编写的,但它包含许多很好的解释和图表,以便更好地理解您正在尝试做什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-12
    相关资源
    最近更新 更多