Skip to content

Instantly share code, notes, and snippets.

@rikusalminen
Created January 19, 2018 08:05
Show Gist options
  • Save rikusalminen/adebf59e87fdbbc2e7daf0e4d821e0a4 to your computer and use it in GitHub Desktop.
Save rikusalminen/adebf59e87fdbbc2e7daf0e4d821e0a4 to your computer and use it in GitHub Desktop.
Triangle meshes with Python and pygame
import pygame
import pygame.freetype
import pygame.gfxdraw
quadrants = (
(( 0, 0), (+1, -1), (+1, +1)),
(( 0, 0), (+1, +1), (-1, +1)),
(( 0, 0), (-1, +1), (-1, -1)),
(( 0, 0), (-1, -1), (+1, -1)))
octants = (
((+1, 0), (+1, +1), ( 0, 0)),
(( 0, +1), ( 0, 0), (+1, +1)),
(( 0, +1), (-1, +1), ( 0, 0)),
((-1, 0), ( 0, 0), (-1, +1)),
((-1, 0), (-1, -1), ( 0, 0)),
(( 0, -1), ( 0, 0), (-1, -1)),
(( 0, -1), (+1, -1), ( 0, 0)),
((+1, 0), ( 0, 0), (+1, -1)))
def quad0(tri, vert):
return quadrants[tri][vert]
def octa0(tri, vert):
return octants[tri][vert]
def test_triangles():
print('\n'.join('\t'.join('%+d,%+d' % quad0(tri, vert) for vert in range(3)) for tri in range(4)))
print('\n')
print('\n'.join('\t'.join('%+d,%+d' % octa0(tri, vert) for vert in range(3)) for tri in range(8)))
def meshmake(lod, x, y):
triangles = [[((x+1.0)/2.0, (y+1.0)/2.0) for (x, y) in tri] for tri in quadrants[0:3]+octants[7:8]]
return triangles
def meshdraw(surface, size, mesh):
black = (0, 0, 0, 0)
white = (255, 255, 255, 255)
red = (255, 0, 0, 255)
def project(size, pos):
return (
int(float(size[0]-1) * pos[0]),
size[1]-int(float(size[1]-1) * pos[1])-1)
for triangle in mesh:
v0 = triangle[0]
v1 = triangle[1]
v2 = triangle[2]
x1 = (v1[0] - v0[0])
y1 = (v1[1] - v0[1])
x2 = (v2[0] - v0[0])
y2 = (v2[1] - v0[1])
cross = x1*y2 - x2*y1
# back facing = red
color = white if cross >= 0.0 else red
for i in range(3):
b = project(size, triangle[i])
e = project(size, triangle[(i+1)%3])
pygame.gfxdraw.line(surface, b[0], b[1], e[0], e[1], color)
if __name__ == '__main__':
test_triangles()
pygame.init()
surface = pygame.display.set_mode((1024,1024)) #, pygame.RESIZABLE)
size = surface.get_size()
font = pygame.freetype.Font(None, 18)
lod = 0
mouse_pos = (0, 0)
quit = False
while not quit:
event = pygame.event.wait()
if event.type == pygame.QUIT:
quit = True
elif event.type == pygame.MOUSEMOTION:
mouse_pos = event.pos
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_PLUS or event.key == pygame.K_KP_PLUS:
lod = lod + 1
elif event.key == pygame.K_MINUS or event.key == pygame.K_KP_MINUS:
lod = max(0, lod - 1)
elif event.type == pygame.VIDEORESIZE:
size = event.size
x = min(int((float(mouse_pos[0]) / float(size[0]))*(1 + (1 << lod))), (1<<lod))
y = min(int((1.0 - float(mouse_pos[1]) / float(size[1]))*(1 + (1 << lod))), (1<<lod))
mesh = meshmake(lod, x, y)
black = (0, 0, 0, 0)
white = (255, 255, 255, 255)
surface.fill(black)
screen_x = size[0] * x / (1 << lod)
screen_y = size[1] - size[1] * y / (1 << lod)
surface.fill(white, rect=(screen_x-2, screen_y-2, 5, 5))
meshdraw(surface, size, mesh)
status_text = 'lod: %d mouse_x: %d mouse_y: %d x: %d y: %d triangles: %d' % (lod, mouse_pos[0], mouse_pos[1], x, y, len(mesh))
font.render_to(surface, (0, 0), status_text, fgcolor=white)
pygame.display.flip()
pygame.display.quit()
pygame.quit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment