Pour générer le tampon d'index souhaité, vous pouvez procéder comme suit. Penser en 2D avec le visage en question comme un carré avec des sommets (& plusmn; 1, & plusmn; 1), et le trou comme un cercle au milieu.
- Vous marchez le long du bord du cercle, en le divisant en un certain nombre de segments.
- Pour chaque sommet, vous le projetez sur le carré environnant avec
(x/M,y/M)
, où M
est max(abs(x),abs(y))
. M
est la valeur absolue de la plus grande coordonnée, donc cette échelle sera (x,y)
de sorte que la plus grande coordonnée est & plusmn; 1.
- Cette ligne vous divisez également en un certain nombre de segments.
- Les segments de deux lignes successives que vous rejoignez par paires en tant que faces.
Ceci est un exemple, subdivisant le cercle en 64 segments, et chaque rayon en 8 segments. Vous pouvez choisir les numéros correspondant à vos besoins.
alt text http://pici.se/pictures/AVhcssRRz.gif
Voici un code Python qui illustre ceci:
from math import sin, cos, pi
from itertools import izip
def pairs(iterable):
"""Yields the previous and the current item on each iteration.
"""
last = None
for item in iterable:
if last is not None:
yield last, item
last = item
def circle(radius, subdiv):
"""Yields coordinates of a circle.
"""
for angle in xrange(0,subdiv+1):
x = radius * cos(angle * 2 * pi/subdiv)
y = radius * sin(angle * 2 * pi/subdiv)
yield x, y
def line(x0,y0,x1,y1,subdiv):
"""Yields coordinates of a line.
"""
for t in xrange(subdiv+1):
x = (subdiv - t)*x0 + t*x1
y = (subdiv - t)*y0 + t*y1
yield x/subdiv, y/subdiv
def tesselate_square_with_hole((x,y),(w,h), radius=0.5, subdiv_circle=64, subdiv_ray=8):
"""Yields quads of a tesselated square with a circluar hole.
"""
for (x0,y0),(x1,y1) in pairs(circle(radius,subdiv_circle)):
M0 = max(abs(x0),abs(y0))
xM0, yM0 = x0/M0, y0/M0
M1 = max(abs(x1),abs(y1))
xM1, yM1 = x1/M1, y1/M1
L1 = line(x0,y0,xM0,yM0,subdiv_ray)
L2 = line(x1,y1,xM1,yM1,subdiv_ray)
for ((xa,ya),(xb,yb)),((xc,yc),(xd,yd)) in pairs(izip(L1,L2)):
yield ((x+xa*w/2,y+ya*h/2),
(x+xb*w/2,y+yb*h/2),
(x+xc*w/2,y+yc*h/2),
(x+xd*w/2,y+yd*h/2))
import pygame
def main():
"""Simple pygame program that displays the tesselated figure.
"""
print('Calculating faces...')
faces = list(tesselate_square_with_hole((150,150),(200,200),0.5,64,8))
print('done')
pygame.init()
pygame.display.set_mode((300,300))
surf = pygame.display.get_surface()
running = True
while running:
need_repaint = False
for event in pygame.event.get() or [pygame.event.wait()]:
if event.type == pygame.QUIT:
running = False
elif event.type in (pygame.VIDEOEXPOSE, pygame.VIDEORESIZE):
need_repaint = True
if need_repaint:
print('Repaint')
surf.fill((255,255,255))
for pa,pb,pc,pd in faces:
# draw a single quad with corners (pa,pb,pd,pc)
pygame.draw.aalines(surf,(0,0,0),True,(pa,pb,pd,pc),1)
pygame.display.flip()
try:
main()
finally:
pygame.quit()
Bonne idée! Mais dans mon cas, les choses sont un peu plus compliquées et je vais devoir utiliser un maillage. –