version Python du programme en c++ de la page:
http://www.cppfrance.com/codes/PICKING-OPENGL-GLUT-INTERPOLATION-BEZIER-SPLINE-CATMULROM_33230.aspx#addcomment
Opengl (GLUT) et picking avec tracé de courbe de bezier, spline et catmulrom.
Source / Exemple :
# Code initialement en c++ écrit par luhtor :
#http://www.cppfrance.com/codes/PICKING-OPENGL-GLUT-INTERPOLATION-BEZIER-SPLINE-CATMULROM_33230.aspx#addcomment
# converti en python par nahiene
from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.GL import *
from numpy import floor, ceil
BUFFER_SIZE =128
DEFAULT_PRECISION =40
SCR_X =640
SCR_Y =480
class point:
def __init__ (self,_x=0.0,_y=0.0,_r=0.0,_g=0.0,_b=1.0):
self.x = _x
self.y = _y
self.r = _r
self.g = _g
self.b = _b
def draw_point(self):
glColor3f(self.r,self.g,self.b)
glBegin(GL_POINTS)
glVertex2f(self.x,self.y)
glEnd()
def move(self, mx, my):
self.x += mx
self.y += my
def set_color(self, _r, _g, _b):
self.r = _r
self.g = _g
self.b = _b
#==================================================================================================
class selection:
def __init__(self,newlist=[]):
self.mylist=newlist
def add_point(self,mypoint):
if mypoint in self.mylist: return
self.mylist.append(mypoint)
mypoint.set_color(1.0,0.0,0.0)
def remove_point(self,mypoint):
self.mylist.remove(mypoint)
mypoint.set_color(0.0,0.0,1.0)
def find(self,mypoint):
if mypoint in self.mylist: return True
return False
def clear(self):
for mypoint in self.mylist:
mypoint.set_color(0.0,0.0,1.0)
self.mylist=[]
def move(self, mx, my):
for mypoint in self.mylist:
mypoint.move(mx,my)
def add_selection (self, myselection):
for mypoint in myselection.mylist:
self.add_point(mypoint)
myselection.mylist=[]
#==================================================================================================
class point_list:
def __init__(self, newlist=[]):
self.mylist=newlist
def draw_all_point(self, mod=GL_RENDER ):
for index, mypoint in enumerate(self.mylist):
if(mod==GL_SELECT): glLoadName(index)
mypoint.draw_point()
def draw_point(self,which): #il a l'air inutilisé
self.mylist[wich].draw_point()
def get_point(self,which):# on devrait s'en passer mais on méditera sur l'optimisation du code plus tard
return self.mylist[which]
def add_point(self,mypoint):
self.mylist.append(mypoint)
#==================================================================================================
# COURBE Catmul-rom
#==================================================================================================
#P est un point du plan. Et Px le point de controle d'indice x.
#P(t) = 1/2 * [ t^3,t^2,t,1 ] * [ -1 3 -3 1 ] * [ Pi-3 ]
# [ 2 -5 4 -1 ] [ Pi-2 ]
# [ -1 0 1 0 ] [ Pi-1 ]
# [ 0 2 0 0 ] [ Pi ]
class cat_curve:
def __init__(self, which=point_list()):
self.plist = which
self.curve_point = []
self.nb_curve_point = 0
self.nb_point = len(self.plist.mylist)
self.precision = DEFAULT_PRECISION
self.draw_number = True
def compute(self):
if (self.curve_point != []): self.curve_point=[]
self.nb_curve_point = self.precision+1
t=1.0
p = float(self.nb_point-3.0)/float(self.precision)
for k in range(self.nb_curve_point):
self.curve_point.append(point())
i = int(floor(t))
ti = float(i)
if (i!= self.nb_point-2):
self.curve_point[k].x = (3.0*self.plist.mylist[i].x-3.0*self.plist.mylist[i+1].x+self.plist.mylist[i+2].x-self.plist.mylist[i-1].x)*pow(t-ti,3)/2.0+( 2.0*self.plist.mylist[i-1].x - 5.0*self.plist.mylist[i].x + 4.0*self.plist.mylist[i+1].x - self.plist.mylist[i+2].x)*pow(t-ti,2)/2.0+( self.plist.mylist[i+1].x - self.plist.mylist[i-1].x ) *(t-ti)/2.0 + self.plist.mylist[i].x
self.curve_point[k].y = (3.0*self.plist.mylist[i].y-3.0*self.plist.mylist[i+1].y+self.plist.mylist[i+2].y-self.plist.mylist[i-1].y)*pow(t-ti,3)/2.0+( 2.0*self.plist.mylist[i-1].y - 5.0*self.plist.mylist[i].y + 4.0*self.plist.mylist[i+1].y - self.plist.mylist[i+2].y)*pow(t-ti,2)/2.0+( self.plist.mylist[i+1].y - self.plist.mylist[i-1].y ) *(t-ti)/2.0 + self.plist.mylist[i].y
else:
self.curve_point[k].x = self.plist.mylist[i].x
self.curve_point[k].y = self.plist.mylist[i].y
t += p
def draw(self):
glColor3f(0.8,0.6,0.0)
glBegin(GL_LINE_STRIP)
for i in range(self.nb_curve_point) :
glVertex2f(self.curve_point[i].x, self.curve_point[i].y)
glEnd()
if (self.draw_number):
glColor3f(0.0,0.0,0.0)
for i in range(self.nb_point):
glRasterPos2f(self.plist.mylist[i].x - 8.0, self.plist.mylist[i].y + 8.0)
ch=repr(int(i))
drawString(ch)
def Inc_Precision(self) : self.precision *= 2.0
def Dec_Precision(self) : self.precision = int(ceil(float(self.precision/2.0)))
def Toggle_Number(self):
self.draw_number = not self.draw_number
return self.draw_number
#==================================================================================================
# COURBE B Spline uniforme
# Fonction de pondération pour les B splines uniformes
def spline_uniform( t, x): # fonction allure Gauss, maximum en x = t
t -= float(2.0)
if ((x < t+1.0) and (x >= t)):
return pow(x - t,3)/6.0
elif ((x < t+2.0) and (x >= t+1.0)) :
return 1.0/6.0 * (3.0*t*t*t-3.0*t*t*(3.0*x-4.0)+3.0*t*(3.0*x*x-8.0*x+4.0)-3.0*x*x*x+12.0*x*(x-1.0)+4.0)
elif ((x < t+3.0) and (x >= t+2.0)) :
return -1.0/6.0 * (3.0*t*t*t-3.0*t*t*(3.0*x-8.0)+3.0*t*(3.0*x*x-16.0*x+20.0)-3.0*x*x*x+24.0*x*x-60.0*x+44.0)
elif ((x < t+4.0) and (x >= t+3.0)) :
return 1.0/6.0 * (t*t*t - 3.0*t*t*(x-4.0)+3.0*t*(x*x-8.0*x+16.0)-x*x*x+12.0*x*x-48.0*x+64.0)
else:
return 0.0
class spline_curve:
def __init__ (self, which=point_list()):
self.plist = which
self.curve_point = []
self.nb_curve_point = 0
self.nb_point = len(self.plist.mylist)
self.precision = DEFAULT_PRECISION
self.draw_number = True
self.draw_rep = True
self.rep_point = []
def compute(self):
if (self.curve_point != []) : self.curve_point=[]
if (self.rep_point != []) : self.rep_point=[]
self.nb_curve_point = self.precision+1
u=1.0
p = (float(self.nb_point-3.0))/float(self.precision)
for i in range(self.nb_curve_point):
self.curve_point.append(point()) #en remplacement de la fonction new
tx = 0.0
ty = 0.0
for j in range(1,self.nb_point+1):
tb = spline_uniform(j-1,u)
tx += tb*self.plist.mylist[j-1].x
ty += tb*self.plist.mylist[j-1].y
tb = 0
u += p
self.curve_point[i].x = tx
self.curve_point[i].y = ty
u=1.0
for i in range(self.nb_point-2):
self.rep_point.append(point()) #en remplacement de la fonction new
tx = 0.0
ty = 0.0
tb = 0.00
for j in range(1,self.nb_point+1):
tb = spline_uniform(j-1,u)
tx += tb*self.plist.mylist[j-1].x
ty += tb*self.plist.mylist[j-1].y
tb = 0.0
u += 1.0
self.rep_point[i].x = tx
self.rep_point[i].y = ty
def draw(self):
glColor3f(0.0,0.0,1.0)
glBegin(GL_LINE_STRIP)
for i in range(self.nb_curve_point):
glVertex2f(self.curve_point[i].x, self.curve_point[i].y)
glEnd()
if (self.draw_number):
glColor3f(0.0,0.0,0.0)
for i in range(self.nb_point):
glRasterPos2f(self.plist.mylist[i].x - 8.0, self.plist.mylist[i].y + 8.0)
ch=repr(int(i))
drawString(ch)
if (self.draw_rep):
glColor3f(1.0,0.0,0.0)
glPointSize(3.0)
glBegin(GL_POINTS)
for i in range(self.nb_point-2): glVertex2f(self.rep_point[i].x, self.rep_point[i].y)
glEnd()
glPointSize(4.0)
def Inc_Precision(self): self.precision *= 2.0
def Dec_Precision(self): self.precision = int(ceil(float(self.precision/2.0)))
def Toggle_Number(self):
self.draw_number = not self.draw_number
return self.draw_number
def Toggle_Rep(self):
self.draw_rep = not self.draw_rep
return self.draw_rep
#==================================================================================================
# COURBE de Bézier
def factoriel(x): # no comment
r = 1
for i in range(2, x+1): r*=i
return r
def Berstein(i, n, u): # i ème polynome de Berstein d'ordre n+1 évalué en u (appartenant à 0..1)
iu = 1.0-u
return factoriel(n)/(factoriel(i)*factoriel(n-i))*pow(u,i)*pow(iu,n-i) # tres lourd en calcul, mais c'est suffisant, et ca reste lisible
class bezier_curve:
def __init__(self , which=point_list()):
self.plist = which
self.curve_point = []
self.nb_curve_point = 0
self.nb_point = len(self.plist.mylist)
self.precision = DEFAULT_PRECISION
self.draw_tangeante = True
self.draw_number = True
def compute(self):
if (self.curve_point != []) :self.curve_point=[]
self.nb_curve_point = self.precision+1
u=0.0
p = 1.0/float(self.precision)
for i in range(self.nb_curve_point):
self.curve_point.append(point()) #en remplacement de new en C++
tx = 0
ty = 0
tb = 0
for j in range(self.nb_point):
tb = Berstein(j, self.nb_point-1, u)
tx += tb * self.plist.mylist[j].x
ty += tb * self.plist.mylist[j].y
u += p
self.curve_point[i].x = tx
self.curve_point[i].y = ty
def draw(self):
glColor3f(0.0,1.0,0.0)
glBegin(GL_LINE_STRIP)
for i in range(self.nb_curve_point): glVertex2f(self.curve_point[i].x, self.curve_point[i].y)
glEnd()
if (self.draw_tangeante):
glColor3f(1.0,0.0,0.0)
glBegin(GL_LINES)
glVertex2f(self.plist.mylist[0].x, self.plist.mylist[0].y)
glVertex2f(self.plist.mylist[1].x, self.plist.mylist[1].y)
glVertex2f(self.plist.mylist[self.nb_point-1].x, self.plist.mylist[self.nb_point-1].y)
glVertex2f(self.plist.mylist[self.nb_point-2].x, self.plist.mylist[self.nb_point-2].y)
glEnd()
if (self.draw_number):
glColor3f(0.0,0.0,0.0)
for i in range(self.nb_point):
glRasterPos2f(self.plist.mylist[i].x - 8.0, self.plist.mylist[i].y + 8.0)
ch=repr(int(i))
drawString(ch)
def Inc_Precision(self) : self.precision *= 2
def Dec_Precision(self) : self.precision = int(ceil(float(self.precision/2.0)))
def Toggle_Tangeante(self):
self.draw_tangeante = not self.draw_tangeante
return self.draw_tangeante
def Toggle_Number(self):
self.draw_number = not self.draw_number
return self.draw_number
#==============================================================================
# Déclaration des variables globales
# Avec Glut, on a pas trop le choix
pt_list= point_list()
sl_list=selection()
sweep_list=selection()
mouse_x=100
mouse_y=100
show_bezier = False
show_spline = False
show_cat = False
b_curve = bezier_curve(point_list())
s_curve = spline_curve(point_list())
c_curve = cat_curve(point_list())
last_point_added = -1
# booléens qui servent pour la gestion de la sélection
left_button_pressed = False
something_clicked = False # un point a été sélectionné
point_has_moved = False # des pts ont été déplacé
ctrl_pressed = False
shift_pressed = False
selected = False # il y a t il une sélection par glissement en cours
sl_x1 = 0.0
sl_y1 = 0.0
def drawString (s):
for i in s:
glutBitmapCharacter (GLUT_BITMAP_HELVETICA_10, ord(i)) # encore une difference avec le c++, en python il demande le numéro unicode du charactere
def reshape( w, h):
glViewport(0, 0, w, h)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluOrtho2D(0.0, w, 0.0, h)
glMatrixMode(GL_MODELVIEW)
def display():
glClear(GL_COLOR_BUFFER_BIT)
pt_list.draw_all_point()
if (show_bezier) :b_curve.draw()
if (show_spline): s_curve.draw()
if (show_cat) :c_curve.draw()
viewport=glGetIntegerv (GL_VIEWPORT)
if (selected) :# affichage de la sélection par glissement
glBegin(GL_QUADS)
glColor4f(0.0,0.0,1.0,0.4)
glVertex2f(sl_x1,sl_y1)
glVertex2f(mouse_x,sl_y1)
glColor4f(0.0,0.0,1.0,0.2)
glVertex2f(mouse_x,viewport[3] - mouse_y)
glVertex2f(sl_x1,viewport[3] - mouse_y)
glEnd()
glColor4f(0.0,0.0,1.0,0.8)
glBegin(GL_LINE_LOOP)
glVertex2f(sl_x1,sl_y1)
glVertex2f(mouse_x,sl_y1)
glVertex2f(mouse_x,viewport[3] - mouse_y)
glVertex2f(sl_x1,viewport[3] - mouse_y)
glEnd()
glColor4f(0.0,0.0,1.0,1.0)
glColor3f(0.0, 0.0, 0.0)
glRasterPos2i(5, viewport[3] - 10)
pos=repr(mouse_x)
drawString(pos)
glRasterPos2i(5, viewport[3] - 20)
pos=repr(mouse_y)
drawString(pos)
glutSwapBuffers()
glFlush()
def Mouse( button, state, x, y):
global pt_list
global sl_list
global sweep_list
global mouse_x
global mouse_y
global show_bezier
global show_spline
global show_cat
global b_curve
global s_curve
global c_curve
global last_point_added
# booléens qui servent pour la gestion de la sélection
global left_button_pressed
global something_clicked
global point_has_moved
global ctrl_pressed
global shift_pressed
global selected
global sl_x1
global sl_y1
mouse_x = x
mouse_y = y
shift_pressed = False
ctrl_pressed = False
if glutGetModifiers()==GLUT_ACTIVE_SHIFT: # on détect l'appuis sur SHIFT ou CTRL
shift_pressed = True
elif glutGetModifiers()==GLUT_ACTIVE_CTRL:
ctrl_pressed = True
# picking standard d'openGL
viewport=glGetIntegerv (GL_VIEWPORT)
glSelectBuffer(BUFFER_SIZE) # on définit la taille du tampon
glRenderMode(GL_SELECT) # on passe en mode sélection
glInitNames() # on reset le tampon
glPushName(10000) # on y insère un premier élément pour pouvoir utiliser la fonction glLoadName par la suite. Un élément qui n'existe pas.
# on aura pas 10000 point a l'écran avec ce programme.
glMatrixMode(GL_PROJECTION)
glPushMatrix() # on sauvergarde la matrice courante de projection
glLoadIdentity()
gluPickMatrix(x, (viewport[3] - y), 5.0, 5.0, viewport) # On définit une matrice de picking. Cad on réduit la fenetre a un carré de 5x5 pixel centré sur la souris.
gluOrtho2D(0.0, viewport[2], 0.0, viewport[3]) # matrice de projection 2D
pt_list.draw_all_point(GL_SELECT) # on réaffiche tous les points en mode sélection, tous les éléments qui y apparaissent, provoque un hit, et 4 informations par primitives sont placées dans le tampon définie précédemment pas glSelectBuffer.
# Ici, on ne peut pas sélectionner de segment, donc inutile des les afficher. Seul les points nous intéressent.
# je me sers de la 4ème information qui correspond au numéro du point, numéro qui est affiché à l'écran losrque l'option est activé.
# Voir des sites de picking, ou le redbook d'openGL pour d'avantage d'info, sur le tampon.
glMatrixMode(GL_PROJECTION)
glPopMatrix()
glFlush()
tampon = glRenderMode(GL_RENDER) # on récupère le tampon. ATTENTION!! on est différent du C++ sur cette ligne
nb_int= len(tampon)
if nb_int==0:
name=[]
else:
zmin, zmax, name=tampon[0]
#print zmin, zmax, tampon,nb_int,len(tampon), len(tampon_provisoire)
something_clicked = False
sl_x1 = mouse_x
sl_y1 = float(viewport[3] - mouse_y) # toutes les opérations viewport[3] - x sont dues a l'inversion des coordonnées glut de openGL
# toute la suite concerne la gestion de la sélection, sélection par glissement etc ...
# au cas ou plusieurs objet sont sous le curseur, le premier qui a été tracé est sélectionné,
# je ne gère pas les objets multiples. Il faudrait étudier les valeurs de profondeur qui sont stockés dans
# le tampon
if ((button == GLUT_LEFT_BUTTON) and (state == GLUT_DOWN)) :left_button_pressed = True
if ((button == GLUT_LEFT_BUTTON) and (state == GLUT_UP)): left_button_pressed = False
if ((nb_int == 0) and (not selected)): # si aucun objet se trouvait sous le curseur ( nb_int = 0 ) et qu'aucune sélection par glissement est en cours
if ((button == GLUT_LEFT_BUTTON) and (state == GLUT_DOWN) and (not shift_pressed)):
if (not ctrl_pressed):
sl_list.clear() # alors on vide la sélection
glutPostRedisplay()
return
if ((button == GLUT_LEFT_BUTTON) and (state == GLUT_DOWN)):# si le bouton gauche de la souris a été pressé
if (not shift_pressed): sl_list.clear() # si shift n'est pas presse, on vide la sélection, et on ne selectionnera que le point juste selectionne
if (not sl_list.find(pt_list.get_point(name[0]))): # si le point sélectionne n'est pas trouve, on l'ajoute a la selection
sl_list.add_point(pt_list.get_point(name[0]))
last_point_added = name[0] # on mémorise le dernier point ajouté.
something_clicked = True
if ((button == GLUT_LEFT_BUTTON) and (state == GLUT_UP) and (not selected) and (last_point_added != int(name[0])) and (sl_list.find(pt_list.get_point(name[0]))) and (not point_has_moved)): # si le bouton est laché, qu'une sélection par glissement n'est pas activé, et que le point en cours n'est pas celui qui vient d'etre ajouté lors de l'appel précédent de cette fonction. On vérifie que les points n'ont pas bougés.
sl_list.remove_point(pt_list.get_point(name[0]))
elif ((button == GLUT_LEFT_BUTTON) and (state == GLUT_UP) and (selected)): # si une sélection par glissement est en cours, on la détruit, mais l'ajoute au préalable a la sélection normal.
sl_list.add_selection(sweep_list)
if ((button == GLUT_LEFT_BUTTON) and (state == GLUT_UP)): last_point_added = -1 # dans tous les cas, aucun point n'a été sélectionné.
selected = False
point_has_moved = False
glutPostRedisplay()
def MotionMouse( x, y):
global pt_list
global sl_list
global sweep_list
global mouse_x
global mouse_y
global show_bezier
global show_spline
global show_cat
global b_curve
global s_curve
global c_curve
global last_point_added
# booléens qui servent pour la gestion de la sélection
global left_button_pressed
global something_clicked
global point_has_moved
global ctrl_pressed
global shift_pressed
global selected
global sl_x1
global sl_y1
selected = False # on réinitialise les booléens qui seront, s'il le faut, remis a True.
point_has_moved = False
if ((left_button_pressed) and ((something_clicked) or (ctrl_pressed))) :
# si on maintient cliqué sur un point, ou si CTRL est pressé (ce qui permet de déplacé les points
# sans forcément avoir cliqué dessus ce qui est tjs difficile si on veut aller vite), on déplace
# l'ensemble de la sélection
sl_list.move(float(x-mouse_x), -float(y-mouse_y))
point_has_moved = True
# on recalcule pour un affichage dynamique
if globals().has_key('b_curve'): b_curve.compute() #on teste l'existence des variables
if globals().has_key('s_curve'): s_curve.compute() #on teste l'existence des variables
if globals().has_key('c_curve'): c_curve.compute() #on teste l'existence des variables
elif ((left_button_pressed) and (not something_clicked) and (not ctrl_pressed)) :
# sinon c'est que l'utilisateur déclenche une sélection par glissement
selected = True
# le processus est le meme a part la zone de picking qui correspond au carré de sélection.
viewport=glGetIntegerv (GL_VIEWPORT) # different du c++
if ((sl_x1-mouse_x != 0.0) and (sl_y1-(viewport[3] - mouse_y) != 0.0)):
sweep_list.clear()
glSelectBuffer(BUFFER_SIZE)
glRenderMode(GL_SELECT)
glInitNames()
glPushName(10000)
glMatrixMode(GL_PROJECTION)
glPushMatrix()
glLoadIdentity()
gluPickMatrix((sl_x1+mouse_x)/2.0, (sl_y1+(viewport[3] - mouse_y))/2.0, abs(sl_x1-mouse_x), abs(sl_y1-(viewport[3]-mouse_y)), viewport) # on détecte tous ce qui se trouve dans la zone de sélection
gluOrtho2D(0.0, viewport[2], 0.0, viewport[3])
pt_list.draw_all_point(GL_SELECT)
glMatrixMode(GL_PROJECTION)
glPopMatrix()
glFlush()
tampon = glRenderMode(GL_RENDER)
nb_int= len(tampon)
for hits in tampon:
zmin, zmax, name=hits
#print zmin, zmax,name, tampon,nb_int,len(tampon),len(name)
sweep_list.add_point(pt_list.get_point(name[0]))
# tous les points sélectionnés sont ajouté a la sélection par glissement (sweep_list)
mouse_x = x
mouse_y = y
glutPostRedisplay()
# gestion des menus de GLUT actionné pour le bouton droit de la souris.
def glut_bezier_menu(i):
global b_curve
if i==1:
b_curve.Inc_Precision()
b_curve.compute()
#break
elif i==2:
b_curve.Dec_Precision()
b_curve.compute()
#break
elif i==3:
if (b_curve.Toggle_Tangeante()):
glutChangeToMenuEntry(3, "Masquer tangeantes", 3)
else:
glutChangeToMenuEntry(3, "Afficher tangeantes", 3)
#break
elif i==4:
if (b_curve.Toggle_Number()):
glutChangeToMenuEntry(4, "Masquer numéros", 4)
else :
glutChangeToMenuEntry(4, "Afficher numéros", 4)
#break
glutPostRedisplay()
def glut_spline_menu(i):
global s_curve
if i == 1:
s_curve.Inc_Precision()
s_curve.compute()
#break
elif i== 2:
s_curve.Dec_Precision()
s_curve.compute()
#break
elif i== 3:
if (s_curve.Toggle_Number()):
glutChangeToMenuEntry(3, "Masquer numéros", 3)
else :
glutChangeToMenuEntry(3, "Afficher numéros", 3)
#break
elif i== 4:
if (s_curve.Toggle_Rep()) :
glutChangeToMenuEntry(4, "Masquer repères", 4)
else:
glutChangeToMenuEntry(4, "Afficher repères", 4)
#break
glutPostRedisplay()
def glut_cat_menu( i):
global c_curve
if i == 1:
c_curve.Inc_Precision()
c_curve.compute()
#break
elif i== 2:
c_curve.Dec_Precision()
c_curve.compute()
#break
elif i== 3:
if (c_curve.Toggle_Number()) :
glutChangeToMenuEntry(3, "Masquer numéros", 3)
else :
glutChangeToMenuEntry(3, "Afficher numéros", 3)
#break
glutPostRedisplay()
def glut_main_menu( i):
global show_bezier
global show_spline
global show_cat
global b_curve
global s_curve
global c_curve
if i == 7:
del b_curve
del s_curve
del c_curve
exit(0)
#break
elif i== 6:
if (show_cat):
show_cat = not show_cat
glutChangeToMenuEntry(6, "Masquer courbe Cattmul-rom",6)
else :
show_cat = not show_cat
glutChangeToMenuEntry(6, "Afficher courbe Cattmul-rom", 6)
#break
elif i== 5:
if (show_spline ):
show_spline = not show_spline
glutChangeToMenuEntry(5, "Masquer courbe Spline",5)
else:
show_spline = not show_spline
glutChangeToMenuEntry(5, "Afficher courbe Spline", 5)
#break
elif i== 4:
if (show_bezier ) :
show_bezier = not show_bezier
glutChangeToMenuEntry(4, "Masquer courbe Bézier", 4)
else :
show_bezier = not show_bezier
glutChangeToMenuEntry(4, "Afficher courbe Bézier", 4)
#break
glutPostRedisplay()
def main():
global pt_list
global sl_list
global sweep_list
global mouse_x
global mouse_y
global show_bezier
global show_spline
global show_cat
global b_curve
global s_curve
global c_curve
global last_point_added
# booléens qui servent pour la gestion de la sélection
global left_button_pressed
global something_clicked
global point_has_moved
global ctrl_pressed
global shift_pressed
global selected
global sl_x1
global sl_y1
pt_list.add_point( point(30.0,30.0))
pt_list.add_point( point(100.0,30.0))
pt_list.add_point( point(200.0,200.0))
pt_list.add_point( point(250.0,200.0))
pt_list.add_point( point(300.0,200.0))
pt_list.add_point( point(400.0,300.0))
pt_list.add_point( point(500.0,300.0))
pt_list.add_point( point(600.0,400.0))
b_curve = bezier_curve(pt_list)
b_curve.compute()
s_curve = spline_curve(pt_list)
s_curve.compute()
c_curve = cat_curve(pt_list)
c_curve.compute()
glutInit(sys.argv)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA)
glutInitWindowSize(SCR_X,SCR_Y)
glutInitWindowPosition(100,100)
glutCreateWindow("Catmul-Rom")
# initialisation d'openGL
glClearColor(1.0, 1.0, 1.0, 0.0)
glEnable(GL_LINE_SMOOTH)
glEnable(GL_BLEND)
#glEnable(GL_COLOR)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glPointSize(4.0)
# fonction callback de GLUT
glutDisplayFunc(display)
glutReshapeFunc(reshape)
#glutIdleFunc(Idle)
glutMouseFunc(Mouse)
glutMotionFunc(MotionMouse)
# création du menu sous GLUT
bezier_menu = glutCreateMenu(glut_bezier_menu)
glutAddMenuEntry("Précision du calcul x2",1)
glutAddMenuEntry("Précision du calcul /2",2)
glutAddMenuEntry("Masquer tangeantes",3)
glutAddMenuEntry("Masquer numéro", 4)
spline_menu = glutCreateMenu(glut_spline_menu)
glutAddMenuEntry("Précision du calcul x2",1)
glutAddMenuEntry("Précision du calcul /2",2)
glutAddMenuEntry("Masquer numéros", 3)
glutAddMenuEntry("Masquer repères", 4)
cat_menu = glutCreateMenu(glut_cat_menu)
glutAddMenuEntry("Précision du calcul x2",1)
glutAddMenuEntry("Précision du calcul /2",2)
glutAddMenuEntry("Masquer numéros", 3)
main_menu = glutCreateMenu(glut_main_menu)
glutAddSubMenu("Courbe de Bézier",bezier_menu)
glutAddSubMenu("Courbe Spline",spline_menu)
glutAddSubMenu("Courbe Cattmulrom",cat_menu)
glutAddMenuEntry("Afficher courbe de Bézier", 4)
glutAddMenuEntry("Afficher courbe Spline", 5)
glutAddMenuEntry("Afficher courbe Cattmulrom", 6)
glutAddMenuEntry("Quitter",7)
glutAttachMenu(GLUT_RIGHT_BUTTON) # quel bouton de la souris active le menu.
glutMainLoop()
main()
Conclusion :
Ce code est intéressant non seulement parce qu'on comprends mieux un code en python qu'en c++, mais aussi pour mettre en valeur des différences dans l'opengl python et c++. Exemples:
viewport=glGetIntegerv(GL_VIEWPORT) acquisition du viewport
glSelectBuffer(BUFFER_SIZE) dimensionnement du buffer différent en python qu'en c++
glRenderMode(GL_RENDER) ne retourne pas le nombre de hit mais le buffer
glutBitmapCharacter (GLUT_BITMAP_HELVETICA_10, ord(i)) il fallait le voir celui là!! en c++ il mange du char alors qu'en python il prend l'unicode du charactere, d'où l'utilisation de la fonction ord
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.