Earth / app.py
Tigasturned's picture
Upload app.py with huggingface_hub
2654bf7 verified
raw
history blame
7.1 kB
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()