Présentation du module vpython dédié à l'animation 3d

Description

Présentation ludique du module vpython avec une interface graphique basée sur l'utilisation du module tkinter.
Ce programme permet d'inserer des formes géométriques dans un espace 3D à partir de leurs coordonnées et des vecteurs définissants leur position. On peut également charger/sauvegarder la scène (fichier vPyScene.py).

Les modules indispensables sont Tkinter, vpython , et math (le module math facilite le calcul lors de la création d'animation par exemple). Il est possible d'exporter la scène crée au format POV en utilisant le module povexport . Pour convertir l'image au format bmp, je propose le logiciel libre POV-Ray . Dans ce cas, vous pouvez lever les commentaires ('#') des lignes 6 et 218 en précisant la chemin vers votre répertoire d'instalation de POV-Ray ce qui permet de lancer automatiquement la conversion de la scène.

Concernant le programme, j'ai essayé de le rendre simple et lisible afin de présenter simplement une facette du module vpython. En effet, vpython présente de nombreuses autres caractéristiques. Sans être exaustif, on peut citer :
  • des formes non présentées (types courbes, etc...)
  • la possibilité de gérer les sources de lumière
  • la possibilité de fusionner des objects
  • la possibilité de gérer les évènement clavier et souris
  • la possibilité d'insérer des boutons de controle
  • la possibilité bien entendue d'animer les objects

Source / Exemple :


#! D:\Python25\python.exe
from Tkinter import *
from visual import *
from math import *
import povexport
#import os

class PyIGU3D:
	def __init__(self, parent):
		"""Initialisation de l'IGU"""
		self.parent=parent
		self.parent.title('Controles de la vision 3D')
		self.menuBar()
		self.container=Frame(self.parent)
		self.interface=Text(self.container)
		self.interface.insert('end','Bonjour et bienvenu\nPour tout renseignement tonny.rosca@gmail.com\n...')
		self.interface.pack(side='left',expand=YES,fill=BOTH)
		self.yscrollbar=Scrollbar(self.container)
		self.yscrollbar.pack(side='right',fill=Y)
		self.container.pack(fill=BOTH)
		self.yscrollbar.config(command=self.interface.yview)

	def menuBar(self):
		"""Initialisation de la barre de menu"""
		menu=Menu()
		fichier=Menu()
		fichier.add_command(label='Nouveau',command=self.newScene)
		fichier.add_command(label='Charger la scene',command=self.loadScene)
		fichier.add_command(label='Sauvegarder la scene',command=self.saveScene)
		fichier.add_command(label='Exporter la scene',command=self.exportScene)
		fichier.add_command(label='Quitter',command=self.parent.destroy)
		menu.add_cascade(label='Fichier',menu=fichier)
		affichage=Menu()
		affichage.add_command(label='Lister les objects',command=self.listObjects)
		affichage.add_command(label='Parametres par default',command=self.allDefault)
		menu.add_cascade(label='Affichage',menu=affichage)
		inserer=Menu()
		inserer.add_command(label='Cube',command=self.addCube)
		inserer.add_command(label='Cone',command=self.addCone)
		inserer.add_command(label='Cylindre',command=self.addCylinder)
		inserer.add_command(label='Boulle',command=self.addBall)
		menu.add_cascade(label='Inserer',menu=inserer)
		zoom=Menu()
		zoom.add_command(label='Zoom +',command=self.zoomIn)
		zoom.add_command(label='Zoom -',command=self.zoomOut)
		zoom.add_command(label='Zoom auto',command=self.zoomAuto)
		menu.add_cascade(label='Zoom',menu=zoom)
		vue=Menu()
		vue.add_command(label="Decalage vers la droite",command=self.rightMove)
		vue.add_command(label="Decalage vers la gauche",command=self.leftMove)
		vue.add_command(label="Decalage vers le haut",command=self.upMove)
		vue.add_command(label="Decalage vers le bas",command=self.downMove)
		vue.add_command(label="Decalage vers le fond",command=self.topMove)
		vue.add_command(label="Decalage vers l'ecran",command=self.backMove)
		vue.add_command(label="Recentrer la vue",command=self.centerAuto)
		vue.add_command(label="Imposer les coordonnees",command=self.coordCenter)
		menu.add_cascade(label='Vue',menu=vue)
		couleur=Menu()
		couleur.add_command(label='Changer la couleur du fond',command=self.paramColor)
		menu.add_cascade(label='Couleur',menu=couleur)
		camera=Menu()
		camera.add_command(label='Decaler vers le haut',command=self.cameraUp)
		camera.add_command(label='Decaler vers le bas',command=self.cameraDown)
		camera.add_command(label='Decaler vers la droite',command=self.cameraRight)
		camera.add_command(label='Decaler vers la gauche',command=self.cameraLeft)
		camera.add_command(label='Vue par default',command=self.cameraDefault)
		camera.add_separator()
		camera.add_command(label="Augmenter l'angle",command=self.angleMore)
		camera.add_command(label="Diminuer l'angle",command=self.angleLess)
		camera.add_command(label="Angle par default",command=self.angleDefault)
		menu.add_cascade(label='Camera',menu=camera)
		animation=Menu()
		animation.add_command(label="Parametres de l'animation",command=self.paramAnim)
		menu.add_cascade(label='Animation',menu=animation)
		aide=Menu()
		aide.add_command(label='A propos...',command=self.aboutVersion)
		aide.add_command(label='Aide',command=self.aboutAuthor)
		menu.add_cascade(label='?',menu=aide)
		self.parent.config(menu=menu)

	def paramColor(self):
		"""Fenetre d'ajustement de la couleur de fond"""
		self.windowColor=Toplevel()
		self.windowColor.title('Parametres')
		self.containerP1=Frame(self.windowColor)
		self.containerP1.pack(fill=X)
		self.redBackground=Scale(self.containerP1,from_=0,to=1,resolution=0.01,label='Rouge',orient='horizontal')
		self.redBackground.pack(fill=X)
		self.greenBackground=Scale(self.containerP1,from_=0,to=1,resolution=0.01,label='Vert',orient='horizontal')
		self.greenBackground.pack(fill=X)
		self.blueBackground=Scale(self.containerP1,from_=0,to=1,resolution=0.01,label='Bleu',orient='horizontal')
		self.blueBackground.pack(fill=X)
		self.buttonP1=Button(self.containerP1,text='Valider',command=self.colorBackground)
		self.buttonP1.pack(fill=X)
		self.buttonP2=Button(self.containerP1,text='Annuler',command=self.windowColor.destroy)
		self.buttonP2.pack(fill=X)

	def zoomIn(self):
		"""Zoom In"""
		self.scene.range=(self.scene.range[0]/1.5,self.scene.range[1]/1.5,self.scene.range[2]/1.5)

	def zoomOut(self):
		"""Zoom Out"""
		self.scene.range=(1.5*self.scene.range[0],1.5*self.scene.range[1],1.5*self.scene.range[2])

	def zoomAuto(self):
		"""Zoom automatique"""
		self.scene.autoscale=1

	def centerAuto(self):
		"""Centrer la vue"""
		self.scene.autocenter=1

	def rightMove(self):
		"""Decaler vers la droite"""
		self.scene.center=(self.scene.center[0]+10,self.scene.center[1],self.scene.center[2])

	def leftMove(self):
		"""Decaler vers la gauche"""
		self.scene.autocenter=0
		self.scene.center=(self.scene.center[0]-10,self.scene.center[1],self.scene.center[2])

	def upMove(self):
		"""Decaler vers le haut"""
		self.scene.autocenter=0
		self.scene.center=(self.scene.center[0],self.scene.center[1]-10,self.scene.center[2])

	def downMove(self):
		"""Decaler vers le bas"""
		self.scene.autocenter=0
		self.scene.center=(self.scene.center[0],self.scene.center[1]+10,self.scene.center[2])

	def topMove(self):
		"""Decaler vers le devant"""
		self.scene.autocenter=0
		self.scene.center=(self.scene.center[0],self.scene.center[1],self.scene.center[2]+10)

	def backMove(self):
		"""Decaler vers le derriere"""
		self.scene.autocenter=0
		self.scene.center=(self.scene.center[0],self.scene.center[1],self.scene.center[2]-10)

	def coordCenter(self):
		"""Imposer les coordonnees du centre de la camera"""
		self.windowCoordCenter=Toplevel()
		self.windowCoordCenter.title('Parametres')
		self.containerP1=Frame(self.windowCoordCenter)
		self.containerP1.pack(fill=X)
		self.x0perso=Scale(self.containerP1,from_=-500,to=500,resolution=1,label='Origine de x',orient='horizontal')
		self.x0perso.pack(fill=X)
		self.y0perso=Scale(self.containerP1,from_=-500,to=500,resolution=1,label='Origine de y',orient='horizontal')
		self.y0perso.pack(fill=X)
		self.z0perso=Scale(self.containerP1,from_=-500,to=500,resolution=1,label='Origine de z',orient='horizontal')
		self.z0perso.pack(fill=X)
		self.buttonP1=Button(self.containerP1,text='Valider',command=self.validCoordCenter)
		self.buttonP1.pack(fill=X)
		self.buttonP2=Button(self.containerP1,text='Annuler',command=self.windowCoordCenter.destroy)
		self.buttonP2.pack(fill=X)

	def validCoordCenter(self):
		"""Valide le choix des coordonnees et recentre la vue"""
		self.scene.center=(self.x0perso.get(),self.y0perso.get(),self.z0perso.get())
		self.windowCoordCenter.destroy()

	def colorBackground(self):
		"""Zoom In"""
		self.scene.background=(self.redBackground.get(),self.greenBackground.get(),self.blueBackground.get())
		self.windowColor.destroy()

	def cameraUp(self):
		"""Deplacement de la camera vers le haut"""
		self.scene.forward=(self.scene.forward[0],self.scene.forward[1]+0.5,self.scene.forward[2])

	def cameraDown(self):
		"""Deplacement de la camera vers le bas"""
		self.scene.forward=(self.scene.forward[0],self.scene.forward[1]-0.5,self.scene.forward[2])

	def cameraRight(self):
		"""Deplacement de la camera vers la droite"""
		self.scene.forward=(self.scene.forward[0]-0.5,self.scene.forward[1],self.scene.forward[2])

	def cameraLeft(self):
		"""Deplacement de la camera vers la gauche"""
		self.scene.forward=(self.scene.forward[0]+0.5,self.scene.forward[1],self.scene.forward[2])

	def cameraDefault(self):
		"""Retour de la camera dans la position par default"""
		self.scene.forward=(0,0,-1)

	def angleMore(self):
		"""Augmente l'angle de focale de la camera"""
		try:
			self.scene.fov=self.scene.fov*1.2
		except:
			self.interface.insert('end','Angle maximal atteint : 180 degres')
			self.yscrollbar.config(command=self.interface.yview)

	def angleLess(self):
		"""Diminue l'angle de focale de la camera"""
		self.scene.fov=self.scene.fov/1.2

	def angleDefault(self):
		"""Retablie l'angle de focale de la camera par default"""
		self.scene.fov=pi/3

	def allDefault(self):
		"""Retablir les parametres par default"""
		self.scene.fov=pi/3
		self.scene.forward=(0,0,-1)
		self.scene.autocenter=1
		self.scene.autoscale=1

	def exportScene(self):
		"""Exportation de la scene au format pov"""
		try:
			povexport.export(display=self.scene, filename='monVpython.POV')
			self.interface.insert('end',"Fichier exporte avec succes\n...")
			#os.popen("D:\\POV\\bin\\pvengine.exe monVpython.Pov")
		except:
			self.interface.insert('end',"Erreur lors de l'exportation du fichier\n...")
		self.yscrollbar.config(command=self.interface.yview)

	def loadScene(self):
		"""Chargement d'une scene enregistree"""
		from vPyScene import forLoadScene
		self.scene=forLoadScene()

	def saveScene(self):
		"""Sauvegarde de la scene sous"""
		try:
			outputFile=open("vPyScene.py",'w')
			#Sauvegarde de la scene
			outputFile.write("from visual import *\ndef forLoadScene():\n")
			outputFile.write("\tscene=display(title='Ma presentation de vpython',exit=0,background="+str(scene.background)+")\n")
			outputFile.write("\tscene.forward=("+str(self.scene.forward[0])+","+str(self.scene.forward[1])+","+str(self.scene.forward[2])+")\n")
			outputFile.write("\tscene.range=("+str(self.scene.range[0])+","+str(self.scene.range[1])+","+str(self.scene.range[2])+")\n")
			outputFile.write("\tscene.center=("+str(self.scene.center[0])+","+str(self.scene.center[1])+","+str(self.scene.center[2])+")\n")
			outputFile.write("\tscene.fov="+str(self.scene.fov)+"\n")
			index=0
			for obj in self.scene.objects:
				index+=1
				if obj.__class__==box:
					outputFile.write("\tobj"+str(index)+"=box(pos=("+str(obj.pos[0])+","+str(obj.pos[1])+","+str(obj.pos[2])+"),size=("+str(obj.size[0])+","+str(obj.size[1])+","+str(obj.size[2])+"),color=("+str(obj.color[0])+","+str(obj.color[1])+","+str(obj.color[2])+"))\n")
				elif obj.__class__==sphere:
					outputFile.write("\tobj"+str(index)+"=sphere(pos=("+str(obj.pos[0])+","+str(obj.pos[1])+","+str(obj.pos[2])+"),radius="+str(obj.radius)+",color=("+str(obj.color[0])+","+str(obj.color[1])+","+str(obj.color[2])+"))\n")
				elif obj.__class__==cone:
					outputFile.write("\tobj"+str(index)+"=cone(pos=("+str(obj.pos[0])+","+str(obj.pos[1])+","+str(obj.pos[2])+"),radius="+str(obj.radius)+",color=("+str(obj.color[0])+","+str(obj.color[1])+","+str(obj.color[2])+"),axis=("+str(obj.axis[0])+","+str(obj.axis[1])+","+str(obj.axis[2])+"))\n")
				elif obj.__class__==cylinder:
					outputFile.write("\tobj"+str(index)+"=cylinder(pos=("+str(obj.pos[0])+","+str(obj.pos[1])+","+str(obj.pos[2])+"),radius="+str(obj.radius)+",color=("+str(obj.color[0])+","+str(obj.color[1])+","+str(obj.color[2])+"),axis=("+str(obj.axis[0])+","+str(obj.axis[1])+","+str(obj.axis[2])+"))\n")
			outputFile.write("\treturn scene")
			outputFile.close
			self.interface.insert('end','Sauvegarde effectuee avec succes.\n...')
		except:
			self.interface.insert('end','Erreur lors de la sauvegarde du fichier.\n...')
		self.yscrollbar.config(command=self.interface.yview)

	def listObjects(self):
		for obj in self.scene.objects:
			if obj.__class__==box:
				self.interface.insert('end',"Object : Un cube.\n...\tDimensions :\n...\t\tX : "+str(obj.size[0])+"\n...\t\tY : "+str(obj.size[1])+"\n...\t\tZ : "+str(obj.size[2])+"\n...")
			elif obj.__class__==sphere:
				self.interface.insert('end',"Object : Une spere.\n...\tRayon : "+str(obj.radius)+"\n...\t")
			elif obj.__class__==cylinder:
				self.interface.insert('end',"Object : Un cylindre.\n...\tRayon : "+str(obj.radius)+"\n...\tDimensions :\n...\t\tX : "+str(obj.axis[0])+"\n...\t\tY : "+str(obj.axis[1])+"\n...\t\tZ : "+str(obj.axis[2])+"\n...")
			elif obj.__class__==cone:
				self.interface.insert('end',"Object : Un cone.\n...\tRayon : "+str(obj.radius)+"\n...\tDimensions :\n...\t\tX : "+str(obj.axis[0])+"\n...\t\tY : "+str(obj.axis[1])+"\n...\t\tZ : "+str(obj.axis[2])+"\n...")
			self.interface.insert('end',"\tPosition de l'object :\n...\t\tX : "+str(obj.pos[0])+"\n...\t\tY : "+str(obj.pos[1])+"\n...\t\tZ : "+str(obj.pos[2])+"\n...")
			self.interface.insert('end',"\tCouleur de l'object :\n...\t\tRouge : "+str(obj.color[0])+"\n...\t\tVert : "+str(obj.color[1])+"\n...\t\tBleue : "+str(obj.color[2])+"\n...")
		self.yscrollbar.config(command=self.interface.yview)

	def aboutAuthor(self):
		"""Joindre l'auteur"""
		self.interface.insert('end','1. Creer une scene (Fichier--Nouveau)\n...2. Inserer des objects (Inserer)\n...Pour tout renseignement tonny.rosca@gmail.com\n...')
		self.yscrollbar.config(command=self.interface.yview)

	def aboutVersion(self):
		"""Version"""
		self.interface.insert('end','Tutorial vPython V2.0\n...')
		self.yscrollbar.config(command=self.interface.yview)

	def validScene(self):
		"""Creation d'un nouvelle scene"""
		self.interface.insert('end',"Nouvelle scene cree ("+str(self.xWin.get())+"*"+str(self.yWin.get())+").\n...")
		self.scene=display(title='Ma presentation de vpython',x=0,y=0,width=self.xWin.get(), height=self.yWin.get(),center=(0,0,0), background=(0,0,0),exit=0)
		self.windowScene.destroy()
		self.yscrollbar.config(command=self.interface.yview)

	def newScene(self):
		"""Ouverture d'une fenetre presentant les parametres de la nouvelle scene"""
		self.windowScene=Toplevel()
		self.windowScene.title('Parametres de la scene')
		self.containerS1=Frame(self.windowScene)
		self.xWin=Scale(self.containerS1,from_=10,to=1024,resolution=1,label='Largeur de la fenetre',orient='horizontal')
		self.xWin.pack(fill=X)
		self.xWin.set(300)
		self.yWin=Scale(self.containerS1,from_=10,to=780,resolution=1,label='Hauteur de la fenetre',orient='horizontal')
		self.yWin.pack(fill=X)
		self.yWin.set(200)
		self.containerS2=Frame(self.windowScene)
		self.buttonS1=Button(self.containerS2,text='Valider',command=self.validScene)
		self.buttonS1.pack(fill=X)
		self.buttonS2=Button(self.containerS2,text='Annuler',command=self.windowScene.destroy)
		self.buttonS2.pack(fill=X)
		self.containerS1.pack(fill=X)
		self.containerS2.pack(fill=X)

	def addCube(self):
		"""Ouverture d'une fenetre presentant les parametres du cube"""
		try:
			self.interface.insert('end',"Codage de la scene : "+str(self.scene)+").\n...")
		except:
			self.newScene()
		self.windowCube=Toplevel()
		self.windowCube.title('Inserer un cube')
		self.containerP1=Frame(self.windowCube)
		self.redCube=Scale(self.containerP1,from_=0,to=1,resolution=0.01,label='Rouge',orient='horizontal')
		self.redCube.pack(fill=X)
		self.greenCube=Scale(self.containerP1,from_=0,to=1,resolution=0.01,label='Vert',orient='horizontal')
		self.greenCube.pack(fill=X)
		self.greenCube.set(1)
		self.blueCube=Scale(self.containerP1,from_=0,to=1,resolution=0.01,label='Bleu',orient='horizontal')
		self.blueCube.pack(fill=X)
		self.containerP2=Frame(self.windowCube)
		self.x0Cube=Scale(self.containerP2,from_=-500,to=500,resolution=1,label='Origine x',orient='horizontal')
		self.x0Cube.pack(fill=X)
		self.y0Cube=Scale(self.containerP2,from_=-500,to=500,resolution=1,label='Origine y',orient='horizontal')
		self.y0Cube.pack(fill=X)
		self.z0Cube=Scale(self.containerP2,from_=-500,to=500,resolution=1,label='Origine z',orient='horizontal')
		self.z0Cube.pack(fill=X)
		self.containerP3=Frame(self.windowCube)
		self.xxCube=Scale(self.containerP3,from_=0,to=500,resolution=1,label='Taille x',orient='horizontal')
		self.xxCube.pack(fill=X)
		self.xxCube.set(30)
		self.yyCube=Scale(self.containerP3,from_=0,to=500,resolution=1,label='Taille y',orient='horizontal')
		self.yyCube.pack(fill=X)
		self.yyCube.set(30)
		self.zzCube=Scale(self.containerP3,from_=0,to=500,resolution=1,label='Taille z',orient='horizontal')
		self.zzCube.pack(fill=X)
		self.zzCube.set(30)
		self.containerP4=Frame(self.windowCube)
		self.buttonP1=Button(self.containerP4,text='Valider',command=self.validCube)
		self.buttonP1.pack(fill=X)
		self.buttonP2=Button(self.containerP4,text='Annuler',command=self.windowCube.destroy)
		self.buttonP2.pack(fill=X)
		self.containerP1.pack(side='left',fill=X)
		self.containerP2.pack(side='left',fill=X)
		self.containerP3.pack(side='left',fill=X)
		self.containerP4.pack(side='bottom',fill=X)
		self.yscrollbar.config(command=self.interface.yview)

	def validCube(self):
		"""Creation du cube"""
		self.interface.insert('end',"Creation du cube.\n...")
		self.cube=box(pos=(self.x0Cube.get(),self.y0Cube.get(),self.z0Cube.get()), size=(self.xxCube.get(),self.yyCube.get(),self.zzCube.get()),color=(self.redCube.get(),self.greenCube.get(),self.blueCube.get()))
		self.windowCube.destroy()
		self.yscrollbar.config(command=self.interface.yview)

	def addBall(self):
		"""Ouverture d'une fenetre presentant les parametres du cube"""
		try:
			self.interface.insert('end',"Codage de la scene : "+str(self.scene)+").\n...")
		except:
			self.newScene()
		self.windowBall=Toplevel()
		self.windowBall.title('Inserer un cube')
		self.containerP1=Frame(self.windowBall)
		self.redBall=Scale(self.containerP1,from_=0,to=1,resolution=0.01,label='Rouge',orient='horizontal')
		self.redBall.pack(fill=X)
		self.redBall.set(1)
		self.greenBall=Scale(self.containerP1,from_=0,to=1,resolution=0.01,label='Vert',orient='horizontal')
		self.greenBall.pack(fill=X)
		self.blueBall=Scale(self.containerP1,from_=0,to=1,resolution=0.01,label='Bleu',orient='horizontal')
		self.blueBall.pack(fill=X)
		self.containerP2=Frame(self.windowBall)
		self.x0Ball=Scale(self.containerP2,from_=-500,to=500,resolution=1,label='Origine x',orient='horizontal')
		self.x0Ball.pack(fill=X)
		self.y0Ball=Scale(self.containerP2,from_=-500,to=500,resolution=1,label='Origine y',orient='horizontal')
		self.y0Ball.pack(fill=X)
		self.z0Ball=Scale(self.containerP2,from_=-500,to=500,resolution=1,label='Origine z',orient='horizontal')
		self.z0Ball.pack(fill=X)
		self.containerP3=Frame(self.windowBall)
		self.rayBall=Scale(self.containerP3,from_=0,to=500,resolution=1,label='Rayon',orient='horizontal')
		self.rayBall.pack(fill=X)
		self.rayBall.set(30)
		self.containerP4=Frame(self.windowBall)
		self.buttonP1=Button(self.containerP4,text='Valider',command=self.validBall)
		self.buttonP1.pack(fill=X)
		self.buttonP2=Button(self.containerP4,text='Annuler',command=self.windowBall.destroy)
		self.buttonP2.pack(fill=X)
		self.containerP1.pack(side='left',fill=X)
		self.containerP2.pack(side='left',fill=X)
		self.containerP3.pack(side='left',fill=X)
		self.containerP4.pack(side='bottom',fill=X)
		self.yscrollbar.config(command=self.interface.yview)

	def validBall(self):
		"""Creation du cube"""
		self.interface.insert('end',"Creation de la boulle.\n...")
		self.ball=sphere(pos=(self.x0Ball.get(),self.y0Ball.get(),self.z0Ball.get()), radius=self.rayBall.get(),color=(self.redBall.get(),self.greenBall.get(),self.blueBall.get()))
		self.windowBall.destroy()
		self.yscrollbar.config(command=self.interface.yview)

	def addCylinder(self):
		"""Ouverture d'une fenetre presentant les parametres du cylindre"""
		try:
			self.interface.insert('end',"Codage de la scene : "+str(self.scene)+").\n...")
		except:
			self.newScene()
		self.windowCylinder=Toplevel()
		self.windowCylinder.title('Inserer un cylindre')
		self.containerCy1=Frame(self.windowCylinder)
		self.redCylinder=Scale(self.containerCy1,from_=0,to=1,resolution=0.01,label='Rouge',orient='horizontal')
		self.redCylinder.pack(fill=X)
		self.greenCylinder=Scale(self.containerCy1,from_=0,to=1,resolution=0.01,label='Vert',orient='horizontal')
		self.greenCylinder.pack(fill=X)
		self.blueCylinder=Scale(self.containerCy1,from_=0,to=1,resolution=0.01,label='Bleu',orient='horizontal')
		self.blueCylinder.pack(fill=X)
		self.blueCylinder.set(1)
		self.containerCy2=Frame(self.windowCylinder)
		self.x0Cylinder=Scale(self.containerCy2,from_=-500,to=500,resolution=1,label='Origine x',orient='horizontal')
		self.x0Cylinder.pack(fill=X)
		self.y0Cylinder=Scale(self.containerCy2,from_=-500,to=500,resolution=1,label='Origine y',orient='horizontal')
		self.y0Cylinder.pack(fill=X)
		self.z0Cylinder=Scale(self.containerCy2,from_=-500,to=500,resolution=1,label='Origine z',orient='horizontal')
		self.z0Cylinder.pack(fill=X)
		self.containerCy3=Frame(self.windowCylinder)
		self.xxCylinder=Scale(self.containerCy3,from_=-500,to=500,resolution=1,label='Taille x',orient='horizontal')
		self.xxCylinder.pack(fill=X)
		self.xxCylinder.set(30)
		self.yyCylinder=Scale(self.containerCy3,from_=-500,to=500,resolution=1,label='Taille y',orient='horizontal')
		self.yyCylinder.pack(fill=X)
		self.yyCylinder.set(30)
		self.zzCylinder=Scale(self.containerCy3,from_=-500,to=500,resolution=1,label='Taille z',orient='horizontal')
		self.zzCylinder.pack(fill=X)
		self.zzCylinder.set(30)
		self.containerCy4=Frame(self.windowCylinder)
		self.rayCylinder=Scale(self.containerCy3,from_=0,to=500,resolution=1,label='Rayon',orient='horizontal')
		self.rayCylinder.pack(fill=X)
		self.rayCylinder.set(30)
		self.containerCy5=Frame(self.windowCylinder)
		self.buttonCy1=Button(self.containerCy5,text='Valider',command=self.validCylinder)
		self.buttonCy1.pack(fill=X)
		self.buttonCy2=Button(self.containerCy5,text='Annuler',command=self.windowCylinder.destroy)
		self.buttonCy2.pack(fill=X)
		self.containerCy1.pack(side='left',fill=X)
		self.containerCy2.pack(side='left',fill=X)
		self.containerCy3.pack(side='left',fill=X)
		self.containerCy4.pack(side='left',fill=X)
		self.containerCy5.pack(side='bottom',fill=X)
		self.yscrollbar.config(command=self.interface.yview)

	def validCylinder(self):
		"""Creation du cylindre"""
		self.interface.insert('end',"Creation du cylindre\n...")
		self.cylindre=cylinder(pos=(self.x0Cylinder.get(),self.y0Cylinder.get(),self.z0Cylinder.get()),axis=(self.xxCylinder.get(),self.yyCylinder.get(),self.zzCylinder.get()),radius=self.rayCylinder.get(),color=(self.redCylinder.get(),self.greenCylinder.get(),self.blueCylinder.get()))
		self.windowCylinder.destroy()
		self.yscrollbar.config(command=self.interface.yview)

	def addCone(self):
		"""Ouverture d'une fenetre presentant les parametres du cone"""
		try:
			self.interface.insert('end',"Codage de la scene : "+str(self.scene)+").\n...")
		except:
			self.newScene()
		self.windowCone=Toplevel()
		self.windowCone.title('Inserer un cone')
		self.containerCo1=Frame(self.windowCone)
		self.redCone=Scale(self.containerCo1,from_=0,to=1,resolution=0.01,label='Rouge',orient='horizontal')
		self.redCone.pack(fill=X)
		self.redCone.set(1)
		self.greenCone=Scale(self.containerCo1,from_=0,to=1,resolution=0.01,label='Vert',orient='horizontal')
		self.greenCone.pack(fill=X)
		self.greenCone.set(1)
		self.blueCone=Scale(self.containerCo1,from_=0,to=1,resolution=0.01,label='Bleu',orient='horizontal')
		self.blueCone.pack(fill=X)
		self.containerCo2=Frame(self.windowCone)
		self.x0Cone=Scale(self.containerCo2,from_=-500,to=500,resolution=1,label='Origine x',orient='horizontal')
		self.x0Cone.pack(fill=X)
		self.y0Cone=Scale(self.containerCo2,from_=-500,to=500,resolution=1,label='Origine y',orient='horizontal')
		self.y0Cone.pack(fill=X)
		self.z0Cone=Scale(self.containerCo2,from_=-500,to=500,resolution=1,label='Origine z',orient='horizontal')
		self.z0Cone.pack(fill=X)
		self.containerCo3=Frame(self.windowCone)
		self.xxCone=Scale(self.containerCo3,from_=-500,to=500,resolution=1,label='Taille x',orient='horizontal')
		self.xxCone.pack(fill=X)
		self.xxCone.set(30)
		self.yyCone=Scale(self.containerCo3,from_=-500,to=500,resolution=1,label='Taille y',orient='horizontal')
		self.yyCone.pack(fill=X)
		self.yyCone.set(30)
		self.zzCone=Scale(self.containerCo3,from_=-500,to=500,resolution=1,label='Taille z',orient='horizontal')
		self.zzCone.pack(fill=X)
		self.zzCone.set(30)
		self.containerCo4=Frame(self.windowCone)
		self.rayCone=Scale(self.containerCo3,from_=0,to=500,resolution=1,label='Rayon',orient='horizontal')
		self.rayCone.pack(fill=X)
		self.rayCone.set(30)
		self.containerCo5=Frame(self.windowCone)
		self.buttonCo1=Button(self.containerCo5,text='Valider',command=self.validCone)
		self.buttonCo1.pack(fill=X)
		self.buttonCo2=Button(self.containerCo5,text='Annuler',command=self.windowCone.destroy)
		self.buttonCo2.pack(fill=X)
		self.containerCo1.pack(side='left',fill=X)
		self.containerCo2.pack(side='left',fill=X)
		self.containerCo3.pack(side='left',fill=X)
		self.containerCo4.pack(side='left',fill=X)
		self.containerCo5.pack(side='bottom',fill=X)
		self.yscrollbar.config(command=self.interface.yview)

	def validCone(self):
		"""Creation du cone"""
		self.interface.insert('end',"Creation du cone\n...")
		self.leCone=cone(pos=(self.x0Cone.get(),self.y0Cone.get(),self.z0Cone.get()),axis=(self.xxCone.get(),self.yyCone.get(),self.zzCone.get()),radius=self.rayCone.get(),color=(self.redCone.get(),self.greenCone.get(),self.blueCone.get()))
		self.windowCone.destroy()
		self.yscrollbar.config(command=self.interface.yview)

	def paramAnim(self):
		"""Lancement d'une animation de type rotation de la camera autours du point central selon x"""
		self.windowAnim=Toplevel()
		self.windowAnim.title=("Parametres de l'animation")
		self.containerAn1=Frame(self.windowAnim)
		self.x0Anim=Scale(self.containerAn1,from_=-500,to=500,resolution=1,label='Origine x',orient='horizontal')
		self.x0Anim.pack(fill=X)
		self.y0Anim=Scale(self.containerAn1,from_=-500,to=500,resolution=1,label='Origine y',orient='horizontal')
		self.y0Anim.pack(fill=X)
		self.z0Anim=Scale(self.containerAn1,from_=-500,to=500,resolution=1,label='Origine z',orient='horizontal')
		self.z0Anim.pack(fill=X)
		self.z0Anim.set(-1)
		self.containerAn2=Frame(self.windowAnim)
		self.xTemp=Entry(self.containerAn2)
		self.xTemp.pack(fill=X)
		self.xTemp.insert('0','xt=-1+sin(2*pi*t/30)')
		self.yTemp=Entry(self.containerAn2)
		self.yTemp.pack(fill=X)
		self.yTemp.insert('0','yt=-0.5')
		self.zTemp=Entry(self.containerAn2)
		self.zTemp.pack(fill=X)
		self.zTemp.insert('0','zt=cos(2*pi*t/30)-1')
		self.zoomTemp=Entry(self.containerAn2)
		self.zoomTemp.pack(fill=X)
		self.zoomTemp.insert('0','zoomt='+str(self.scene.range[0])+'+40*t**2-100*t')
		self.totalTime=Scale(self.containerAn2,from_=0.1,to=60,resolution=0.1,label='Temps total',orient='horizontal')
		self.totalTime.pack(fill=X)
		self.totalTime.set(1)
		self.containerAn3=Frame(self.windowAnim)
		self.buttonAn1=Button(self.containerAn3,text='Valider',command=self.validAnim)
		self.buttonAn1.pack(fill=X)
		self.buttonAn1=Button(self.containerAn3,text='Exporter',command=self.exportAnim)
		self.buttonAn1.pack(fill=X)
		self.buttonAn2=Button(self.containerAn3,text='Annuler',command=self.windowAnim.destroy)
		self.buttonAn2.pack(fill=X)
		self.containerAn1.pack(side='left',fill=X)
		self.containerAn2.pack(side='left',fill=X)
		self.containerAn3.pack(side='bottom',fill=X)

	def validAnim(self):
		"""Lance l'animation en fonction des equations donnes par l'utilisateur"""
		t=0
		dt=0.01
		finished=False
		self.scene.forward=(self.x0Anim.get(),self.y0Anim.get(),self.z0Anim.get())
		while not finished:
			rate(100)
			exec(self.xTemp.get())
			exec(self.yTemp.get())
			exec(self.zTemp.get())
			exec(self.zoomTemp.get())
			self.scene.range=(zoomt,zoomt,zoomt)
			self.scene.forward=(xt,yt,zt)
			t+=dt
			if t>=self.totalTime.get():
				finished=True
		#self.windowAnim.destroy()

	def exportAnim(self):
		"""Exporter l'animation"""
		t=0
		dt=0.01
		finished=False
		cpt=0
		self.scene.forward=(self.x0Anim.get(),self.y0Anim.get(),self.z0Anim.get())
		while not finished:
			rate(100)
			exec(self.xTemp.get())
			exec(self.yTemp.get())
			exec(self.zTemp.get())
			exec(self.zoomTemp.get())
			self.scene.range=(zoomt,zoomt,zoomt)
			self.scene.forward=(xt,yt,zt)
			t+=dt
			try:
				povexport.export(display=self.scene, filename='monVpython'+str(cpt)+'.POV')
				self.interface.insert('end',"Fichier exporte avec succes\n...")
				#os.popen('D:\\POV\\bin\\pvengine.exe monVpython'+str(cpt)+'.POV')
			except:
				self.interface.insert('end',"Erreur lors de l'exportation du fichier\n...")
			self.yscrollbar.config(command=self.interface.yview)
			cpt+=1
			if t>=self.totalTime.get():
				finished=True

root=Tk()
myapp=PyIGU3D(root)
root.mainloop()

Conclusion :


Si quelqu'un veut ajouter des fonctionnalités et faire avancer le code pour mieux exploiter le module, ce serait un plaisir.
Pour les possibles mises à jour, ou pour le plaisir, aller faire un tour sur mon site : http://gdaveau.free.fr

Codes Sources

A voir également

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.