Spaces:
Runtime error
Runtime error
| import pygame | |
| from pygame.locals import * | |
| from OpenGL.GL import * | |
| from OpenGL.GLU import * | |
| import numpy as np | |
| from scipy import ndimage | |
| import random | |
| # Simple 3D Earth Viewer with atmosphere, clouds, terrain, and stars | |
| # Uses PyOpenGL and pygame for rendering | |
| def create_sphere(radius, slices, stacks): | |
| vertices = [] | |
| normals = [] | |
| texcoords = [] | |
| indices = [] | |
| for i in range(stacks + 1): | |
| V = i / stacks | |
| phi = V * np.pi | |
| for j in range(slices + 1): | |
| U = j / slices | |
| theta = U * 2 * np.pi | |
| x = radius * np.sin(phi) * np.cos(theta) | |
| y = radius * np.cos(phi) | |
| z = radius * np.sin(phi) * np.sin(theta) | |
| vertices.append([x, y, z]) | |
| nx, ny, nz = x/radius, y/radius, z/radius | |
| normals.append([nx, ny, nz]) | |
| texcoords.append([U, V]) | |
| for i in range(stacks): | |
| for j in range(slices): | |
| first = i * (slices + 1) + j | |
| second = first + slices + 1 | |
| indices.append(first) | |
| indices.append(second) | |
| indices.append(first + 1) | |
| indices.append(second) | |
| indices.append(second + 1) | |
| indices.append(first + 1) | |
| return np.array(vertices), np.array(normals), np.array(texcoords), np.array(indices) | |
| def create_terrain_noise(resolution=64): | |
| # Generate procedural terrain (heightmap) | |
| noise = np.random.randn(resolution, resolution) * 0.01 | |
| noise = ndimage.gaussian_filter(noise, sigma=2) | |
| return noise | |
| def create_starfield(num_stars=1000): | |
| stars = [] | |
| for _ in range(num_stars): | |
| theta = np.random.uniform(0, 2*np.pi) | |
| phi = np.arccos(1 - np.random.uniform(0, 1)) | |
| r = 100 + np.random.uniform(0, 10) | |
| x = r * np.sin(phi) * np.cos(theta) | |
| y = r * np.cos(phi) | |
| z = r * np.sin(phi) * np.sin(theta) | |
| stars.append([x, y, z]) | |
| return np.array(stars) | |
| def load_texture_from_solid_color(color, width=64, height=64): | |
| texture_data = np.zeros((height, width, 3), dtype=np.uint8) | |
| texture_data[:, :] = color | |
| texture_data = texture_data.tobytes() | |
| texture_id = glGenTextures(1) | |
| glBindTexture(GL_TEXTURE_2D, texture_id) | |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) | |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) | |
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_data) | |
| return texture_id | |
| def load_simple_earth_texture(): | |
| # Create a simple blue marble-like texture | |
| width, height = 1024, 512 | |
| texture_data = np.zeros((height, width, 3), dtype=np.uint8) | |
| for y in range(height): | |
| for x in range(width): | |
| # Simple Earth approximation with blue oceans and green/brown continents | |
| u, v = x / width, y / height | |
| if np.sin(2*np.pi*u) * np.sin(np.pi*v) > 0.5 or (u-0.3)**2 + (v-0.5)**2 < 0.02: | |
| texture_data[y, x] = [30, 100, 200] # Ocean | |
| elif np.random.rand() < 0.3: | |
| texture_data[y, x] = [100, 180, 80] # Land | |
| else: | |
| texture_data[y, x] = [30, 100, 200] | |
| texture_data = texture_data.tobytes() | |
| texture_id = glGenTextures(1) | |
| glBindTexture(GL_TEXTURE_2D, texture_id) | |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) | |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) | |
| glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_data) | |
| return texture_id | |
| class Earth3DViewer: | |
| def __init__(self): | |
| pygame.init() | |
| self.display = (800, 600) | |
| pygame.display.set_mode(self.display, DOUBLEBUF | OPENGL) | |
| pygame.display.set_caption("3D Earth Viewer") | |
| gluPerspective(45, (self.display[0]/self.display[1]), 0.1, 100.0) | |
| glTranslatef(0.0, 0.0, -15) | |
| # Create Earth | |
| self.vertices, self.normals, self.texcoords, self.indices = create_sphere(6.0, 32, 32) | |
| self.cloud_vertices, _, _, _ = create_sphere(6.05, 32, 32) # Slightly bigger for cloud layer | |
| self.atmosphere_vertices, _, _, _ = create_sphere(6.2, 32, 32) # Atmosphere glow | |
| # Load textures | |
| self.earth_texture = load_simple_earth_texture() | |
| self.cloud_texture = load_texture_from_solid_color([200, 200, 255], 64, 64) | |
| self.atmosphere_texture = load_texture_from_solid_color([150, 200, 255, 100], 64, 64) | |
| # Create procedural terrain displacement (conceptual) | |
| self.terrain_noise = create_terrain_noise(32) | |
| # Stars | |
| self.stars = create_starfield(500) | |
| self.rotation = 0 | |
| self.cloud_rotation = 0 | |
| def draw_sphere(self, vertices, texture_id, blend=False, alpha=1.0): | |
| if blend: | |
| glEnable(GL_BLEND) | |
| glBlendFunc(GL_SRC_ALPHA, GL_ONE) | |
| glDepthMask(GL_FALSE) | |
| glBindTexture(GL_TEXTURE_2D, texture_id) | |
| glEnable(GL_TEXTURE_2D) | |
| glBegin(GL_TRIANGLES) | |
| for i in range(0, len(self.indices), 3): | |
| for j in range(3): | |
| idx = self.indices[i + j] | |
| glTexCoord2fv(self.texcoords[idx]) | |
| glVertex3fv(vertices[idx]) | |
| glEnd() | |
| glDisable(GL_TEXTURE_2D) | |
| if blend: | |
| glDisable(GL_BLEND) | |
| glDepthMask(GL_TRUE) | |
| def draw_stars(self): | |
| glEnable(GL_POINT_SMOOTH) | |
| glPointSize(1.0) | |
| glColor3f(1, 1, 1) | |
| glBegin(GL_POINTS) | |
| for star in self.stars: | |
| glVertex3fv(star) | |
| glEnd() | |
| def render(self): | |
| while True: | |
| for event in pygame.event.get(): | |
| if event.type == pygame.QUIT: | |
| pygame.quit() | |
| return | |
| # Handle rotation | |
| self.rotation += 0.5 | |
| self.cloud_rotation += 0.6 | |
| glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) | |
| glEnable(GL_DEPTH_TEST) | |
| # Draw stars (background) | |
| glPushMatrix() | |
| glRotatef(self.rotation * 0.01, 0, 1, 0) | |
| self.draw_stars() | |
| glPopMatrix() | |
| # Draw Earth | |
| glPushMatrix() | |
| glRotatef(self.rotation, 0, 1, 0) | |
| self.draw_sphere(self.vertices, self.earth_texture) | |
| glPopMatrix() | |
| # Draw clouds | |
| glPushMatrix() | |
| glRotatef(self.cloud_rotation, 0, 1, 0) | |
| self.draw_sphere(self.cloud_vertices, self.cloud_texture, blend=True, alpha=0.3) | |
| glPopMatrix() | |
| # Draw atmosphere glow | |
| glPushMatrix() | |
| glRotatef(self.rotation, 0, 1, 0) | |
| glColor4f(0.5, 0.8, 1.0, 0.1) | |
| self.draw_sphere(self.atmosphere_vertices, self.atmosphere_texture, blend=True, alpha=0.1) | |
| glPopMatrix() | |
| pygame.display.flip() | |
| pygame.time.wait(30) | |
| if __name__ == "__main__": | |
| app = Earth3DViewer() | |
| app.render() |