Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class Construct {
- constructor() {
- // Define constants for key codes
- this.Ci_Esc = 'Escape'; // Key code for Escape key
- this.Ci_Up_ArrowPad = 'ArrowUp'; // Key code for Up Arrow key
- this.Ci_Down_ArrowPad = 'ArrowDown'; // Key code for Down Arrow key
- // Define constants for success and failure states
- this.Ct_Success = 1; // Success constant
- this.Ct_Failure = 0; // Failure constant
- // Set screen size
- this.p3d_screensizex = 640; // Screen width
- this.p3d_screensizey = 480; // Screen height
- // Calculate screen center coordinates
- this.p3d_screencenterx = this.p3d_screensizex / 2.0; // Screen center x-coordinate
- this.p3d_screencentery = this.p3d_screensizey / 2.0; // Screen center y-coordinate
- // Create a canvas element and append it to the document body
- this.canvas = document.createElement('canvas'); // Create a canvas element
- document.body.appendChild(this.canvas); // Append the canvas to the document body
- this.ctx = this.canvas.getContext('2d'); // Get the 2D rendering context for the canvas
- this.canvas.width = this.p3d_screensizex; // Set canvas width
- this.canvas.height = this.p3d_screensizey; // Set canvas height
- // Initialize 3D projection variables
- this.p3d_ex = 0.0; // Eye x-coordinate
- this.p3d_ey = 0.0; // Eye y-coordinate
- this.p3d_ez = 0.0; // Eye z-coordinate
- this.p3d_wx = 0.0; // World x-coordinate
- this.p3d_wy = 0.0; // World y-coordinate
- this.p3d_wz = 0.0; // World z-coordinate
- this.p3d_sx = 0.0; // Screen x-coordinate
- this.p3d_sy = 0.0; // Screen y-coordinate
- // Define eye positions for 3D projection
- this.eye = [
- [0, 0, 0], // Origin
- [0, 0, 100], // Forward direction
- [0, 70, 0] // Up direction
- ];
- // Initialize pt array for storing point data
- this.pt = [
- [], // pt[0] is an empty array
- [], // pt[1] is an empty array
- [] // pt[2] is an empty array
- ];
- // Initialize pt[2] with empty arrays
- for (let i = 0; i <= 8; i++) {
- this.pt[2][i] = [0, 0, 0]; // Initialize each element in pt[2] with [0, 0, 0]
- }
- // Set screen size variables
- this.screensizex = this.p3d_screensizex; // Screen width
- this.screensizey = this.p3d_screensizey; // Screen height
- // Calculate screen center coordinates
- this.screencenterx = this.screensizex / 2; // Screen center x-coordinate
- this.screencentery = this.screensizey / 2; // Screen center y-coordinate
- // Initialize input handling variables
- this.keys = {}; // Object to store key states
- this.mouseX = 0; // Mouse x-coordinate
- this.mouseY = 0; // Mouse y-coordinate
- this.running = true; // Running state of the application
- // Add event listeners for key and mouse events
- document.addEventListener('keydown', (event) => this.keys[event.code] = true); // Set key state to true on keydown
- document.addEventListener('keyup', (event) => this.keys[event.code] = false); // Set key state to false on keyup
- document.addEventListener('mousemove', (event) => {
- this.mouseX = event.clientX; // Update mouseX on mouse move
- this.mouseY = event.clientY; // Update mouseY on mouse move
- });
- // Start the update loop
- requestAnimationFrame(() => this.update()); // Call the update method on the next animation frame
- }
- // Method to clear the screen
- clearScreen() {
- this.ctx.fillStyle = 'blue'; // Set fill color to blue
- this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); // Fill the entire canvas with blue color
- }
- // Method to draw a line on the canvas
- // x1, y1: Starting coordinates of the line
- // x2, y2: Ending coordinates of the line
- // color: Color of the line (default is 'yellow')
- drawLine(x1, y1, x2, y2, color = 'yellow') {
- this.ctx.strokeStyle = color; // Set stroke color
- this.ctx.beginPath(); // Begin a new path
- this.ctx.moveTo(x1, y1); // Move to the starting point
- this.ctx.lineTo(x2, y2); // Draw a line to the ending point
- this.ctx.stroke(); // Stroke the path
- }
- // Method to calculate a segment index
- // X, Y, Z: Coordinates used to calculate the index
- segindex(X, Y, Z) {
- return X + Y * 2 + Z * 4 + 1; // Calculate and return the segment index
- }
- // Method to render a segment between two points
- // P1, P2: Indices of the points to render the segment between
- renderseg(P1, P2) {
- // Render a line between the 2D projections of points P1 and P2
- 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]);
- }
- // Method to render a line between two points
- // x1, y1: Starting coordinates of the line
- // x2, y2: Ending coordinates of the line
- // z1, z2: Z-coordinates used to determine if the line should be rendered
- renderline(x1, y1, x2, y2, z1, z2) {
- if (z1 === this.Ct_Failure || z2 === this.Ct_Failure) return this.Ct_Failure; // If either z-coordinate is failure, return failure
- this.drawLine(x1 + this.screencenterx, this.screencentery - y1, x2 + this.screencenterx, this.screencentery - y2); // Draw the line adjusted for screen center
- return this.Ct_Success; // Return success
- }
- // Method to synchronize 3D points
- // P: Index of the point to synchronize
- sync3ds(P) {
- this.pt[2][P][0] = this.p3d_sx; // Sync screen x-coordinate
- this.pt[2][P][1] = this.p3d_sy; // Sync screen y-coordinate
- return this.Ct_Success; // Return success
- }
- // Method for 3D projection calculations
- // ex, ey, ez: Eye coordinates
- // wx, wy, wz: World coordinates
- // sx, sy: Screen coordinates
- // fwx, fwy, fwz: Flags for world coordinates
- // fsx, fsy: Flags for screen coordinates
- Projection3d(ex, ey, ez, wx, wy, wz, sx, sy, fwx, fwy, fwz, fsx, fsy) {
- this.p3d_ex = ex; // Set eye x-coordinate
- this.p3d_ey = ey; // Set eye y-coordinate
- this.p3d_ez = ez; // Set eye z-coordinate
- this.p3d_wx = wx; // Set world x-coordinate
- this.p3d_wy = wy; // Set world y-coordinate
- this.p3d_wz = wz; // Set world z-coordinate
- this.p3d_sx = sx; // Set screen x-coordinate
- this.p3d_sy = sy; // Set screen y-coordinate
- let tmp_PZ = 0; // Temporary projection factor
- let tmp_PF = 0; // Temporary projection flag
- let tmp_Flags = 0; // Temporary flags
- // Calculate flags based on non-zero values
- if (fwx !== 0) tmp_Flags |= 1; // If fwx is non-zero, set flag bit 1
- if (fwy !== 0) tmp_Flags |= 2; // If fwy is non-zero, set flag bit 2
- if (fwz !== 0) tmp_Flags |= 4; // If fwz is non-zero, set flag bit 4
- if (fsx !== 0) tmp_Flags |= 8; // If fsx is non-zero, set flag bit 8
- if (fsy !== 0) tmp_Flags |= 16; // If fsy is non-zero, set flag bit 16
- if (tmp_Flags > 0) { // If any flag is set
- // Determine the primary projection factor
- if ((wx !== 0) && (!((fsx !== 0) || (fwx !== 0)))) {
- tmp_PF = 1; // Set primary factor to 1 if wx is non-zero and neither fsx nor fwx are non-zero
- } else if ((wy !== 0) && (!((fwy !== 0) || (fsx !== 0)))) {
- tmp_PF = 2; // Set primary factor to 2 if wy is non-zero and neither fwy nor fsx are non-zero
- } else if ((wz + ez > 0) && (!(fwz !== 0))) {
- tmp_PF = 4; // Set primary factor to 4 if wz + ez is positive and fwz is zero
- } else {
- tmp_PF = 0; // Set primary factor to 0 otherwise
- }
- if (tmp_PF === 0) return this.Ct_Failure; // Return failure if primary factor is 0
- // Calculate projection based on the primary factor
- if (tmp_PF & 1) {
- tmp_PZ = wx; // Set temporary projection factor to wx if primary factor bit 1 is set
- } else if (tmp_PF & 2) {
- tmp_PZ = wy; // Set temporary projection factor to wy if primary factor bit 2 is set
- } else if (tmp_PF & 4) {
- tmp_PZ = wz + ez; // Set temporary projection factor to wz + ez if primary factor bit 4 is set
- } else {
- tmp_PZ = 0; // Set temporary projection factor to 0 otherwise
- }
- if (tmp_PZ === 0) return this.Ct_Failure; // Return failure if temporary projection factor is 0
- if (tmp_PF & 1) {
- tmp_PZ = (sx - ex) / tmp_PZ; // Calculate projection factor for sx
- } else if (tmp_PF & 2) {
- tmp_PZ = (sy - ey) / tmp_PZ; // Calculate projection factor for sy
- } else if (tmp_PF & 4) {
- tmp_PZ = ez / tmp_PZ; // Calculate projection factor for ez
- } else {
- tmp_PZ = 0; // Set temporary projection factor to 0 otherwise
- }
- 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
- // Adjust wx, wy, and wz based on projection
- if (fwx !== 0 && fsx === 0) {
- wx = (sx - ex) / tmp_PZ; // Calculate wx if fwx is non-zero and fsx is zero
- tmp_Flags &= 30; // Clear the lowest bit of tmp_Flags
- }
- if (fwy !== 0 && fsy === 0) {
- wy = (sy - ey) / tmp_PZ; // Calculate wy if fwy is non-zero and fsy is zero
- tmp_Flags &= 29; // Clear the second bit of tmp_Flags
- }
- if (fwz !== 0) {
- wz = (ez / tmp_PZ) - ez; // Calculate wz if fwz is non-zero
- tmp_Flags &= 27; // Clear the third bit of tmp_Flags
- }
- if (fsx !== 0 && fwx === 0) {
- sx = ex + wx * tmp_PZ; // Calculate sx if fsx is non-zero and fwx is zero
- tmp_Flags &= 23; // Clear the fourth bit of tmp_Flags
- }
- if (fsy !== 0 && fwy === 0) {
- sy = ey - wy * tmp_PZ; // Calculate sy if fsy is non-zero and fwy is zero
- tmp_Flags &= 15; // Clear the fifth bit of tmp_Flags
- }
- if (tmp_Flags > 0) return this.Ct_Failure; // Return failure if any flag is still set
- }
- return this.Ct_Success; // Return success
- }
- // Method for scaling 3D projections
- // arg_EX, arg_EY, arg_EZ: Eye coordinates
- // arg_UnitX, arg_UnitY: Unit coordinates for scaling
- // arg_WZ: World Z coordinate
- Projection3d_Scale(arg_EX, arg_EY, arg_EZ, arg_UnitX, arg_UnitY, arg_WZ) {
- 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
- if (tmp_Success === this.Ct_Failure) return this.Ct_Failure; // Return failure if Projection3d failed
- this.p3d_sx = Math.abs(this.p3d_sx); // Take absolute value of screen x-coordinate
- this.p3d_sy = Math.abs(this.p3d_sy); // Take absolute value of screen y-coordinate
- return this.Ct_Success; // Return success
- }
- // Method to update the canvas
- update() {
- // Stop running if Escape key is pressed
- if (this.keys[this.Ci_Esc]) {
- this.running = false; // Set running to false
- return; // Exit the method
- }
- // Adjust eye position based on key input
- if (this.keys[this.Ci_Up_ArrowPad]) this.eye[2][2] += 1.0; // Move eye forward if Up Arrow is pressed
- if (this.keys[this.Ci_Down_ArrowPad]) this.eye[2][2] -= 1.0; // Move eye backward if Down Arrow is pressed
- // Update eye position based on mouse position
- this.eye[2][0] = this.mouseX - this.screencenterx; // Set eye x-coordinate based on mouse x
- this.eye[2][1] = this.mouseY - this.screencentery; // Set eye y-coordinate based on mouse y
- // Clear the screen
- this.clearScreen(); // Clear the canvas
- // Loop through grid points and project them
- for (let Z1 = 0; Z1 <= 0; Z1++) { // Loop for Z1
- for (let Y1 = -3; Y1 <= 3; Y1++) { // Loop for Y1
- for (let X1 = -3; X1 <= 3; X1++) { // Loop for X1
- for (let Z = 0; Z <= 1; Z++) { // Loop for Z
- for (let Y = 0; Y <= 1; Y++) { // Loop for Y
- for (let X = 0; X <= 1; X++) { // Loop for X
- this.pt[1][this.segindex(X, Y, Z)] = [
- (X + X1 - 0.5) * 50.0, // Set point x-coordinate
- (Y + Y1 - 0.5) * 50.0, // Set point y-coordinate
- (Z + Z1 - 0.5) * 50.0 // Set point z-coordinate
- ];
- }
- }
- }
- // Project points and synchronize them
- for (let T = 1; T <= 8; T++) { // Loop for T (point indices)
- 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
- this.sync3ds(T); // Synchronize the projected point
- }
- // Render segments between points
- this.renderseg(this.segindex(0, 0, 0), this.segindex(1, 0, 0)); // Render segment between (0, 0, 0) and (1, 0, 0)
- this.renderseg(this.segindex(0, 0, 0), this.segindex(0, 1, 0)); // Render segment between (0, 0, 0) and (0, 1, 0)
- this.renderseg(this.segindex(0, 0, 0), this.segindex(0, 0, 1)); // Render segment between (0, 0, 0) and (0, 0, 1)
- this.renderseg(this.segindex(1, 1, 1), this.segindex(1, 1, 0)); // Render segment between (1, 1, 1) and (1, 1, 0)
- this.renderseg(this.segindex(1, 1, 1), this.segindex(1, 0, 1)); // Render segment between (1, 1, 1) and (1, 0, 1)
- this.renderseg(this.segindex(1, 1, 1), this.segindex(0, 1, 1)); // Render segment between (1, 1, 1) and (0, 1, 1)
- this.renderseg(this.segindex(1, 0, 0), this.segindex(1, 1, 0)); // Render segment between (1, 0, 0) and (1, 1, 0)
- this.renderseg(this.segindex(1, 0, 0), this.segindex(1, 0, 1)); // Render segment between (1, 0, 0) and (1, 0, 1)
- this.renderseg(this.segindex(0, 1, 0), this.segindex(1, 1, 0)); // Render segment between (0, 1, 0) and (1, 1, 0)
- this.renderseg(this.segindex(0, 1, 0), this.segindex(0, 1, 1)); // Render segment between (0, 1, 0) and (0, 1, 1)
- this.renderseg(this.segindex(0, 0, 1), this.segindex(1, 0, 1)); // Render segment between (0, 0, 1) and (1, 0, 1)
- this.renderseg(this.segindex(0, 0, 1), this.segindex(0, 1, 1)); // Render segment between (0, 0, 1) and (0, 1, 1)
- }
- }
- }
- // Continue the update loop if running
- if (this.running) {
- requestAnimationFrame(() => this.update()); // Call the update method on the next animation frame
- }
- }
- }
- // Create an instance of the Construct class
- const app = new Construct(); // Instantiate the Construct class
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement