A.A.
A.A.

Reputation: 21

3d to 2d Projection Algorithm (Perspective projection) - Javascript

I am looking for the algorithm that takes 3D coordinates and change them to 2D coordinates.

I tried the steps form this Wikipedia Page : https://en.wikipedia.org/wiki/3D_projection#Perspective_projection

and my code so far is this :

      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>

I want a function that can translate 3D to 2D depending on both position and rotation of the camera.

Upvotes: 2

Views: 4640

Answers (1)

LimeThaw
LimeThaw

Reputation: 11

Taking a look at the Wikipedia page you linked it appears that you have errors in your equations for D. It should be:

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);

Also I think you are using the wrong coordinates for E, which is "the viewer's position relative to the display surface" and should not depend on the coordinates of the point.

The y coordinate of your 2D position appears to contain an error too; you use Ez instead of Ey.

Additionally i can recommend this site. It is written for C++ and OpenGL, but it contains a lot of good explanations and diagrams to get a better understanding of what it is you are trying to do.

Upvotes: 1

Related Questions