Advertisement
jargon

3dRenderClass.js

Jun 16th, 2024
679
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. class Construct {
  2.     constructor() {
  3.         // Define constants for key codes
  4.         this.Ci_Esc = 'Escape'; // Key code for Escape key
  5.         this.Ci_Up_ArrowPad = 'ArrowUp'; // Key code for Up Arrow key
  6.         this.Ci_Down_ArrowPad = 'ArrowDown'; // Key code for Down Arrow key
  7.  
  8.         // Define constants for success and failure states
  9.         this.Ct_Success = 1; // Success constant
  10.         this.Ct_Failure = 0; // Failure constant
  11.  
  12.         // Set screen size
  13.         this.p3d_screensizex = 640; // Screen width
  14.         this.p3d_screensizey = 480; // Screen height
  15.  
  16.         // Calculate screen center coordinates
  17.         this.p3d_screencenterx = this.p3d_screensizex / 2.0; // Screen center x-coordinate
  18.         this.p3d_screencentery = this.p3d_screensizey / 2.0; // Screen center y-coordinate
  19.  
  20.         // Create a canvas element and append it to the document body
  21.         this.canvas = document.createElement('canvas'); // Create a canvas element
  22.         document.body.appendChild(this.canvas); // Append the canvas to the document body
  23.         this.ctx = this.canvas.getContext('2d'); // Get the 2D rendering context for the canvas
  24.         this.canvas.width = this.p3d_screensizex; // Set canvas width
  25.         this.canvas.height = this.p3d_screensizey; // Set canvas height
  26.  
  27.         // Initialize 3D projection variables
  28.         this.p3d_ex = 0.0; // Eye x-coordinate
  29.         this.p3d_ey = 0.0; // Eye y-coordinate
  30.         this.p3d_ez = 0.0; // Eye z-coordinate
  31.  
  32.         this.p3d_wx = 0.0; // World x-coordinate
  33.         this.p3d_wy = 0.0; // World y-coordinate
  34.         this.p3d_wz = 0.0; // World z-coordinate
  35.  
  36.         this.p3d_sx = 0.0; // Screen x-coordinate
  37.         this.p3d_sy = 0.0; // Screen y-coordinate
  38.  
  39.         // Define eye positions for 3D projection
  40.         this.eye = [
  41.             [0, 0, 0],    // Origin
  42.             [0, 0, 100],  // Forward direction
  43.             [0, 70, 0]    // Up direction
  44.         ];
  45.  
  46.         // Initialize pt array for storing point data
  47.         this.pt = [
  48.             [], // pt[0] is an empty array
  49.             [], // pt[1] is an empty array
  50.             []  // pt[2] is an empty array
  51.         ];
  52.  
  53.         // Initialize pt[2] with empty arrays
  54.         for (let i = 0; i <= 8; i++) {
  55.             this.pt[2][i] = [0, 0, 0]; // Initialize each element in pt[2] with [0, 0, 0]
  56.         }
  57.  
  58.         // Set screen size variables
  59.         this.screensizex = this.p3d_screensizex; // Screen width
  60.         this.screensizey = this.p3d_screensizey; // Screen height
  61.  
  62.         // Calculate screen center coordinates
  63.         this.screencenterx = this.screensizex / 2; // Screen center x-coordinate
  64.         this.screencentery = this.screensizey / 2; // Screen center y-coordinate
  65.  
  66.         // Initialize input handling variables
  67.         this.keys = {}; // Object to store key states
  68.         this.mouseX = 0; // Mouse x-coordinate
  69.         this.mouseY = 0; // Mouse y-coordinate
  70.         this.running = true; // Running state of the application
  71.  
  72.         // Add event listeners for key and mouse events
  73.         document.addEventListener('keydown', (event) => this.keys[event.code] = true); // Set key state to true on keydown
  74.         document.addEventListener('keyup', (event) => this.keys[event.code] = false); // Set key state to false on keyup
  75.         document.addEventListener('mousemove', (event) => {
  76.             this.mouseX = event.clientX; // Update mouseX on mouse move
  77.             this.mouseY = event.clientY; // Update mouseY on mouse move
  78.         });
  79.  
  80.         // Start the update loop
  81.         requestAnimationFrame(() => this.update()); // Call the update method on the next animation frame
  82.     }
  83.  
  84.     // Method to clear the screen
  85.     clearScreen() {
  86.         this.ctx.fillStyle = 'blue'; // Set fill color to blue
  87.         this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); // Fill the entire canvas with blue color
  88.     }
  89.  
  90.     // Method to draw a line on the canvas
  91.     // x1, y1: Starting coordinates of the line
  92.     // x2, y2: Ending coordinates of the line
  93.     // color: Color of the line (default is 'yellow')
  94.     drawLine(x1, y1, x2, y2, color = 'yellow') {
  95.         this.ctx.strokeStyle = color; // Set stroke color
  96.         this.ctx.beginPath(); // Begin a new path
  97.         this.ctx.moveTo(x1, y1); // Move to the starting point
  98.         this.ctx.lineTo(x2, y2); // Draw a line to the ending point
  99.         this.ctx.stroke(); // Stroke the path
  100.     }
  101.  
  102.     // Method to calculate a segment index
  103.     // X, Y, Z: Coordinates used to calculate the index
  104.     segindex(X, Y, Z) {
  105.         return X + Y * 2 + Z * 4 + 1; // Calculate and return the segment index
  106.     }
  107.  
  108.     // Method to render a segment between two points
  109.     // P1, P2: Indices of the points to render the segment between
  110.     renderseg(P1, P2) {
  111.         // Render a line between the 2D projections of points P1 and P2
  112.         return this.renderline(this.pt[2][P1][0], this.pt[2][P1][1], this.pt[2][P2][0], this.pt[2][P2][1], this.pt[2][P1][2], this.pt[2][P2][2]);
  113.     }
  114.  
  115.     // Method to render a line between two points
  116.     // x1, y1: Starting coordinates of the line
  117.     // x2, y2: Ending coordinates of the line
  118.     // z1, z2: Z-coordinates used to determine if the line should be rendered
  119.     renderline(x1, y1, x2, y2, z1, z2) {
  120.         if (z1 === this.Ct_Failure || z2 === this.Ct_Failure) return this.Ct_Failure; // If either z-coordinate is failure, return failure
  121.         this.drawLine(x1 + this.screencenterx, this.screencentery - y1, x2 + this.screencenterx, this.screencentery - y2); // Draw the line adjusted for screen center
  122.         return this.Ct_Success; // Return success
  123.     }
  124.  
  125.     // Method to synchronize 3D points
  126.     // P: Index of the point to synchronize
  127.     sync3ds(P) {
  128.         this.pt[2][P][0] = this.p3d_sx; // Sync screen x-coordinate
  129.         this.pt[2][P][1] = this.p3d_sy; // Sync screen y-coordinate
  130.         return this.Ct_Success; // Return success
  131.     }
  132.  
  133.     // Method for 3D projection calculations
  134.     // ex, ey, ez: Eye coordinates
  135.     // wx, wy, wz: World coordinates
  136.     // sx, sy: Screen coordinates
  137.     // fwx, fwy, fwz: Flags for world coordinates
  138.     // fsx, fsy: Flags for screen coordinates
  139.     Projection3d(ex, ey, ez, wx, wy, wz, sx, sy, fwx, fwy, fwz, fsx, fsy) {
  140.         this.p3d_ex = ex; // Set eye x-coordinate
  141.         this.p3d_ey = ey; // Set eye y-coordinate
  142.         this.p3d_ez = ez; // Set eye z-coordinate
  143.  
  144.         this.p3d_wx = wx; // Set world x-coordinate
  145.         this.p3d_wy = wy; // Set world y-coordinate
  146.         this.p3d_wz = wz; // Set world z-coordinate
  147.  
  148.         this.p3d_sx = sx; // Set screen x-coordinate
  149.         this.p3d_sy = sy; // Set screen y-coordinate
  150.  
  151.         let tmp_PZ = 0; // Temporary projection factor
  152.         let tmp_PF = 0; // Temporary projection flag
  153.         let tmp_Flags = 0; // Temporary flags
  154.  
  155.         // Calculate flags based on non-zero values
  156.         if (fwx !== 0) tmp_Flags |= 1; // If fwx is non-zero, set flag bit 1
  157.         if (fwy !== 0) tmp_Flags |= 2; // If fwy is non-zero, set flag bit 2
  158.         if (fwz !== 0) tmp_Flags |= 4; // If fwz is non-zero, set flag bit 4
  159.         if (fsx !== 0) tmp_Flags |= 8; // If fsx is non-zero, set flag bit 8
  160.         if (fsy !== 0) tmp_Flags |= 16; // If fsy is non-zero, set flag bit 16
  161.  
  162.         if (tmp_Flags > 0) { // If any flag is set
  163.             // Determine the primary projection factor
  164.             if ((wx !== 0) && (!((fsx !== 0) || (fwx !== 0)))) {
  165.                 tmp_PF = 1; // Set primary factor to 1 if wx is non-zero and neither fsx nor fwx are non-zero
  166.             } else if ((wy !== 0) && (!((fwy !== 0) || (fsx !== 0)))) {
  167.                 tmp_PF = 2; // Set primary factor to 2 if wy is non-zero and neither fwy nor fsx are non-zero
  168.             } else if ((wz + ez > 0) && (!(fwz !== 0))) {
  169.                 tmp_PF = 4; // Set primary factor to 4 if wz + ez is positive and fwz is zero
  170.             } else {
  171.                 tmp_PF = 0; // Set primary factor to 0 otherwise
  172.             }
  173.  
  174.             if (tmp_PF === 0) return this.Ct_Failure; // Return failure if primary factor is 0
  175.  
  176.             // Calculate projection based on the primary factor
  177.             if (tmp_PF & 1) {
  178.                 tmp_PZ = wx; // Set temporary projection factor to wx if primary factor bit 1 is set
  179.             } else if (tmp_PF & 2) {
  180.                 tmp_PZ = wy; // Set temporary projection factor to wy if primary factor bit 2 is set
  181.             } else if (tmp_PF & 4) {
  182.                 tmp_PZ = wz + ez; // Set temporary projection factor to wz + ez if primary factor bit 4 is set
  183.             } else {
  184.                 tmp_PZ = 0; // Set temporary projection factor to 0 otherwise
  185.             }
  186.  
  187.             if (tmp_PZ === 0) return this.Ct_Failure; // Return failure if temporary projection factor is 0
  188.  
  189.             if (tmp_PF & 1) {
  190.                 tmp_PZ = (sx - ex) / tmp_PZ; // Calculate projection factor for sx
  191.             } else if (tmp_PF & 2) {
  192.                 tmp_PZ = (sy - ey) / tmp_PZ; // Calculate projection factor for sy
  193.             } else if (tmp_PF & 4) {
  194.                 tmp_PZ = ez / tmp_PZ; // Calculate projection factor for ez
  195.             } else {
  196.                 tmp_PZ = 0; // Set temporary projection factor to 0 otherwise
  197.             }
  198.  
  199.             if ((tmp_Flags & 7) > 0 && tmp_PZ === 0) return this.Ct_Failure; // Return failure if any of the lower 3 bits of tmp_Flags are set and tmp_PZ is 0
  200.  
  201.             // Adjust wx, wy, and wz based on projection
  202.             if (fwx !== 0 && fsx === 0) {
  203.                 wx = (sx - ex) / tmp_PZ; // Calculate wx if fwx is non-zero and fsx is zero
  204.                 tmp_Flags &= 30; // Clear the lowest bit of tmp_Flags
  205.             }
  206.             if (fwy !== 0 && fsy === 0) {
  207.                 wy = (sy - ey) / tmp_PZ; // Calculate wy if fwy is non-zero and fsy is zero
  208.                 tmp_Flags &= 29; // Clear the second bit of tmp_Flags
  209.             }
  210.             if (fwz !== 0) {
  211.                 wz = (ez / tmp_PZ) - ez; // Calculate wz if fwz is non-zero
  212.                 tmp_Flags &= 27; // Clear the third bit of tmp_Flags
  213.             }
  214.             if (fsx !== 0 && fwx === 0) {
  215.                 sx = ex + wx * tmp_PZ; // Calculate sx if fsx is non-zero and fwx is zero
  216.                 tmp_Flags &= 23; // Clear the fourth bit of tmp_Flags
  217.             }
  218.             if (fsy !== 0 && fwy === 0) {
  219.                 sy = ey - wy * tmp_PZ; // Calculate sy if fsy is non-zero and fwy is zero
  220.                 tmp_Flags &= 15; // Clear the fifth bit of tmp_Flags
  221.             }
  222.  
  223.             if (tmp_Flags > 0) return this.Ct_Failure; // Return failure if any flag is still set
  224.         }
  225.  
  226.         return this.Ct_Success; // Return success
  227.     }
  228.  
  229.     // Method for scaling 3D projections
  230.     // arg_EX, arg_EY, arg_EZ: Eye coordinates
  231.     // arg_UnitX, arg_UnitY: Unit coordinates for scaling
  232.     // arg_WZ: World Z coordinate
  233.     Projection3d_Scale(arg_EX, arg_EY, arg_EZ, arg_UnitX, arg_UnitY, arg_WZ) {
  234.         const tmp_Success = this.Projection3d(arg_EX, arg_EY, arg_EZ, arg_UnitX, arg_UnitY, arg_WZ, 0.0, 0.0, 0, 0, 0, 1, 1); // Call Projection3d method with scaling arguments
  235.         if (tmp_Success === this.Ct_Failure) return this.Ct_Failure; // Return failure if Projection3d failed
  236.         this.p3d_sx = Math.abs(this.p3d_sx); // Take absolute value of screen x-coordinate
  237.         this.p3d_sy = Math.abs(this.p3d_sy); // Take absolute value of screen y-coordinate
  238.         return this.Ct_Success; // Return success
  239.     }
  240.  
  241.     // Method to update the canvas
  242.     update() {
  243.         // Stop running if Escape key is pressed
  244.         if (this.keys[this.Ci_Esc]) {
  245.             this.running = false; // Set running to false
  246.             return; // Exit the method
  247.         }
  248.  
  249.         // Adjust eye position based on key input
  250.         if (this.keys[this.Ci_Up_ArrowPad]) this.eye[2][2] += 1.0; // Move eye forward if Up Arrow is pressed
  251.         if (this.keys[this.Ci_Down_ArrowPad]) this.eye[2][2] -= 1.0; // Move eye backward if Down Arrow is pressed
  252.  
  253.         // Update eye position based on mouse position
  254.         this.eye[2][0] = this.mouseX - this.screencenterx; // Set eye x-coordinate based on mouse x
  255.         this.eye[2][1] = this.mouseY - this.screencentery; // Set eye y-coordinate based on mouse y
  256.  
  257.         // Clear the screen
  258.         this.clearScreen(); // Clear the canvas
  259.  
  260.         // Loop through grid points and project them
  261.         for (let Z1 = 0; Z1 <= 0; Z1++) { // Loop for Z1
  262.             for (let Y1 = -3; Y1 <= 3; Y1++) { // Loop for Y1
  263.                 for (let X1 = -3; X1 <= 3; X1++) { // Loop for X1
  264.                     for (let Z = 0; Z <= 1; Z++) { // Loop for Z
  265.                         for (let Y = 0; Y <= 1; Y++) { // Loop for Y
  266.                             for (let X = 0; X <= 1; X++) { // Loop for X
  267.                                 this.pt[1][this.segindex(X, Y, Z)] = [
  268.                                     (X + X1 - 0.5) * 50.0, // Set point x-coordinate
  269.                                     (Y + Y1 - 0.5) * 50.0, // Set point y-coordinate
  270.                                     (Z + Z1 - 0.5) * 50.0  // Set point z-coordinate
  271.                                 ];
  272.                             }
  273.                         }
  274.                     }
  275.  
  276.                     // Project points and synchronize them
  277.                     for (let T = 1; T <= 8; T++) { // Loop for T (point indices)
  278.                         this.pt[2][T] = [0, 0, this.Projection3d(this.eye[1][0], this.eye[1][1], this.eye[1][2], this.pt[1][T][0] - this.eye[2][0], this.pt[1][T][1] - this.eye[2][1], this.pt[1][T][2] - this.eye[2][2], this.pt[2][T][0], this.pt[2][T][1], 0, 0, 0, 1, 1)]; // Project the point
  279.                         this.sync3ds(T); // Synchronize the projected point
  280.                     }
  281.  
  282.                     // Render segments between points
  283.                     this.renderseg(this.segindex(0, 0, 0), this.segindex(1, 0, 0)); // Render segment between (0, 0, 0) and (1, 0, 0)
  284.                     this.renderseg(this.segindex(0, 0, 0), this.segindex(0, 1, 0)); // Render segment between (0, 0, 0) and (0, 1, 0)
  285.                     this.renderseg(this.segindex(0, 0, 0), this.segindex(0, 0, 1)); // Render segment between (0, 0, 0) and (0, 0, 1)
  286.  
  287.                     this.renderseg(this.segindex(1, 1, 1), this.segindex(1, 1, 0)); // Render segment between (1, 1, 1) and (1, 1, 0)
  288.                     this.renderseg(this.segindex(1, 1, 1), this.segindex(1, 0, 1)); // Render segment between (1, 1, 1) and (1, 0, 1)
  289.                     this.renderseg(this.segindex(1, 1, 1), this.segindex(0, 1, 1)); // Render segment between (1, 1, 1) and (0, 1, 1)
  290.  
  291.                     this.renderseg(this.segindex(1, 0, 0), this.segindex(1, 1, 0)); // Render segment between (1, 0, 0) and (1, 1, 0)
  292.                     this.renderseg(this.segindex(1, 0, 0), this.segindex(1, 0, 1)); // Render segment between (1, 0, 0) and (1, 0, 1)
  293.  
  294.                     this.renderseg(this.segindex(0, 1, 0), this.segindex(1, 1, 0)); // Render segment between (0, 1, 0) and (1, 1, 0)
  295.                     this.renderseg(this.segindex(0, 1, 0), this.segindex(0, 1, 1)); // Render segment between (0, 1, 0) and (0, 1, 1)
  296.  
  297.                     this.renderseg(this.segindex(0, 0, 1), this.segindex(1, 0, 1)); // Render segment between (0, 0, 1) and (1, 0, 1)
  298.                     this.renderseg(this.segindex(0, 0, 1), this.segindex(0, 1, 1)); // Render segment between (0, 0, 1) and (0, 1, 1)
  299.                 }
  300.             }
  301.         }
  302.  
  303.         // Continue the update loop if running
  304.         if (this.running) {
  305.             requestAnimationFrame(() => this.update()); // Call the update method on the next animation frame
  306.         }
  307.     }
  308. }
  309.  
  310. // Create an instance of the Construct class
  311. const app = new Construct(); // Instantiate the Construct class
  312.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement