3d_box_v1
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revision | |||
3d_box_v1 [2024/09/20 00:54] – appledog | 3d_box_v1 [2024/09/21 01:13] (current) – appledog | ||
---|---|---|---|
Line 4: | Line 4: | ||
The code will be presented as a monolithic file but it is intended that it be split into many files such as putting Object3d into it's own file, and then moving functions like rotate_x into there (maybe using staticmethod) or into their own library class. Object data could also stand to be moved out, maybe into an objects.py sort of class, or into files like cube.obj (i.e. cube.txt) which could be read in at runtime. | The code will be presented as a monolithic file but it is intended that it be split into many files such as putting Object3d into it's own file, and then moving functions like rotate_x into there (maybe using staticmethod) or into their own library class. Object data could also stand to be moved out, maybe into an objects.py sort of class, or into files like cube.obj (i.e. cube.txt) which could be read in at runtime. | ||
- | == The Code | + | == The Code (Wireframe) |
+ | < | ||
+ | import pygame | ||
+ | import sys | ||
+ | import math | ||
+ | |||
+ | # Initialize Pygame | ||
+ | pygame.init() | ||
+ | |||
+ | # Constants | ||
+ | WIDTH, HEIGHT = 800, 600 | ||
+ | FOV = 256 # Field of view | ||
+ | CAMERA_Z = 4 # Camera distance from the object | ||
+ | SQUARE_SIZE = 1 # Half the size of the square for vertex calculations | ||
+ | rotation_angles = [0, 0, 0] # Rotation angles for x, y, z | ||
+ | |||
+ | # Set up the display | ||
+ | screen = pygame.display.set_mode((WIDTH, | ||
+ | pygame.display.set_caption(" | ||
+ | |||
+ | # Square | ||
+ | square_obj = [ | ||
+ | [ # Back face | ||
+ | [-SQUARE_SIZE, | ||
+ | [SQUARE_SIZE, | ||
+ | [SQUARE_SIZE, | ||
+ | [-SQUARE_SIZE, | ||
+ | ] | ||
+ | ] | ||
+ | |||
+ | # Define the vertices of a 3D cube | ||
+ | cube_obj = [ | ||
+ | [ # Back face | ||
+ | (-SQUARE_SIZE, | ||
+ | (SQUARE_SIZE, | ||
+ | (SQUARE_SIZE, | ||
+ | (-SQUARE_SIZE, | ||
+ | ], | ||
+ | [ # Front face | ||
+ | (-SQUARE_SIZE, | ||
+ | (SQUARE_SIZE, | ||
+ | (SQUARE_SIZE, | ||
+ | (-SQUARE_SIZE, | ||
+ | ], | ||
+ | [ # Left face | ||
+ | (-SQUARE_SIZE, | ||
+ | (-SQUARE_SIZE, | ||
+ | (-SQUARE_SIZE, | ||
+ | (-SQUARE_SIZE, | ||
+ | ], | ||
+ | [ # Right face | ||
+ | (SQUARE_SIZE, | ||
+ | (SQUARE_SIZE, | ||
+ | (SQUARE_SIZE, | ||
+ | (SQUARE_SIZE, | ||
+ | ], | ||
+ | [ # Top face | ||
+ | (-SQUARE_SIZE, | ||
+ | (SQUARE_SIZE, | ||
+ | (SQUARE_SIZE, | ||
+ | (-SQUARE_SIZE, | ||
+ | ], | ||
+ | [ # Bottom face | ||
+ | (-SQUARE_SIZE, | ||
+ | (SQUARE_SIZE, | ||
+ | (SQUARE_SIZE, | ||
+ | (-SQUARE_SIZE, | ||
+ | ] | ||
+ | ] | ||
+ | |||
+ | |||
+ | # Function to project 3D points to 2D | ||
+ | def project(point): | ||
+ | x, y, z = point | ||
+ | scale = FOV / (CAMERA_Z + z) | ||
+ | x_proj = int(x * scale + WIDTH // 2) | ||
+ | y_proj = int(-y * scale + HEIGHT // 2) | ||
+ | return (x_proj, y_proj) | ||
+ | |||
+ | |||
+ | # Functions for rotating points | ||
+ | def rotate_x(point, | ||
+ | rad = math.radians(angle) | ||
+ | cos_angle = math.cos(rad) | ||
+ | sin_angle = math.sin(rad) | ||
+ | x, y, z = point | ||
+ | y_rotated = y * cos_angle - z * sin_angle | ||
+ | z_rotated = y * sin_angle + z * cos_angle | ||
+ | return (x, y_rotated, z_rotated) | ||
+ | |||
+ | |||
+ | def rotate_y(point, | ||
+ | rad = math.radians(angle) | ||
+ | cos_angle = math.cos(rad) | ||
+ | sin_angle = math.sin(rad) | ||
+ | x, y, z = point | ||
+ | x_rotated = z * sin_angle + x * cos_angle | ||
+ | z_rotated = z * cos_angle - x * sin_angle | ||
+ | return (x_rotated, y, z_rotated) | ||
+ | |||
+ | |||
+ | def rotate_z(point, | ||
+ | rad = math.radians(angle) | ||
+ | cos_angle = math.cos(rad) | ||
+ | sin_angle = math.sin(rad) | ||
+ | x, y, z = point | ||
+ | x_rotated = x * cos_angle - y * sin_angle | ||
+ | y_rotated = x * sin_angle + y * cos_angle | ||
+ | return (x_rotated, y_rotated, z) | ||
+ | |||
+ | |||
+ | # Function to draw the cube using faces | ||
+ | def draw_obj(position, | ||
+ | face_data = [] | ||
+ | |||
+ | for index, face in enumerate(faces): | ||
+ | transformed_vertices = [] | ||
+ | |||
+ | # Transform each vertex | ||
+ | for vertex in face: | ||
+ | # Rotate the vertex around the Z-axis | ||
+ | vertex = rotate_z(vertex, | ||
+ | # Rotate the result around the Y-axis | ||
+ | vertex = rotate_y(vertex, | ||
+ | # Rotate the result around the X-axis | ||
+ | vertex = rotate_x(vertex, | ||
+ | # Append the transformed vertex | ||
+ | transformed_vertices.append(vertex) | ||
+ | |||
+ | projected_vertices = [] | ||
+ | |||
+ | # Project each transformed vertex to 2D | ||
+ | for vertex in transformed_vertices: | ||
+ | projected_vertex = project((vertex[0] + position[0], | ||
+ | projected_vertices.append(projected_vertex) | ||
+ | |||
+ | pygame.draw.polygon(screen, | ||
+ | |||
+ | |||
+ | def draw_obj(position, | ||
+ | for face in faces: | ||
+ | transformed_vertices = [ | ||
+ | rotate_x(rotate_y(rotate_z(vertex, | ||
+ | for vertex in face | ||
+ | ] | ||
+ | projected_vertices = [project((x + position[0], | ||
+ | transformed_vertices] | ||
+ | |||
+ | # Draw the polygon face | ||
+ | pygame.draw.polygon(screen, | ||
+ | |||
+ | |||
+ | # Main loop | ||
+ | def main(): | ||
+ | clock = pygame.time.Clock() | ||
+ | position = [0, 0, 0] # Initial position of the cube | ||
+ | |||
+ | while True: | ||
+ | for event in pygame.event.get(): | ||
+ | if event.type == pygame.QUIT: | ||
+ | pygame.quit() | ||
+ | sys.exit() | ||
+ | |||
+ | keys = pygame.key.get_pressed() | ||
+ | |||
+ | # Movement controls | ||
+ | if keys[pygame.K_UP]: | ||
+ | position[2] += 0.1 | ||
+ | if keys[pygame.K_DOWN]: | ||
+ | position[2] -= 0.1 | ||
+ | if keys[pygame.K_a]: | ||
+ | position[0] -= 0.1 | ||
+ | if keys[pygame.K_d]: | ||
+ | position[0] += 0.1 | ||
+ | if keys[pygame.K_w]: | ||
+ | position[1] += 0.1 | ||
+ | if keys[pygame.K_s]: | ||
+ | position[1] -= 0.1 | ||
+ | |||
+ | # Rotation controls | ||
+ | if keys[pygame.K_1]: | ||
+ | rotation_angles[0] += 1 | ||
+ | if keys[pygame.K_2]: | ||
+ | rotation_angles[0] -= 1 | ||
+ | if keys[pygame.K_3]: | ||
+ | rotation_angles[1] += 1 | ||
+ | if keys[pygame.K_4]: | ||
+ | rotation_angles[1] -= 1 | ||
+ | if keys[pygame.K_5]: | ||
+ | rotation_angles[2] += 1 | ||
+ | if keys[pygame.K_6]: | ||
+ | rotation_angles[2] -= 1 | ||
+ | |||
+ | # Fill the screen with black | ||
+ | screen.fill((0, | ||
+ | |||
+ | # Draw the cube using polygons | ||
+ | draw_obj(position, | ||
+ | |||
+ | # Draw the bounding box (optional) | ||
+ | pygame.draw.rect(screen, | ||
+ | |||
+ | # Update the display | ||
+ | pygame.display.flip() | ||
+ | clock.tick(60) | ||
+ | |||
+ | |||
+ | if __name__ == " | ||
+ | main() | ||
+ | |||
+ | </ | ||
+ | |||
+ | == The Code (with Simple Z-avg and fill) | ||
< | < | ||
import pygame | import pygame |
3d_box_v1.1726793643.txt.gz · Last modified: 2024/09/20 00:54 by appledog