Créer une sphère 3D texturée, au format obj


La présente page montre comment créer des sphères texturées au format wavefront obj, de façon automatique, à l'aide d'un programme python. Le fichier texture correspondant est réalisé à l'aide d'un logiciel graphique (kolourpaint sous Linux, paint sous Windows ou Gimp par exemple). Pour visualiser la sphère, on utilise ici le logiciel meshlab version 2020 sous ubuntu 18.04.

Le projet comprend 4 fichiers:
sphere.obj : fichier texte décrivant la sphère;
sphere.mtl : fichier texte décrivant les matériaux utilisés;
texture.png : fichier texture de taille carrée;
sphere.py : programme python permettant de générer automatiquement un fichier sphere.obj.

sphere.zip

1) Fichier sphere.obj

Le fichier sphere.obj est un fichier texte au format wavefront obj. Il est généré automatiquement par le programme python sphere.py ci-joint. Ce fichier contient la description complète de la sphère (sommets v, coordonnées de texture vt et faces f). Son contenu et sa taille dépendent des paramètres suivants (paramètres à préciser au début du programme sphere.py):
r: rayon de la sphère;
pa : nombre de parallèles (nombre impair supérieur ou égal à 3);
me: nombre de méridiens (nombre pair supérieur ou égal à 4).

Plus le nombre de parallèles et de méridiens est important, plus la sphère possède une résolution élevée et apparaît lisse.

On crée puis on utilise ce fichier de la façon suivante:
1) On fixe les valeurs de r, pa et me dans le programme sphere.py (lignes 21 à 23);
2) On exécute le programme sphere.py (depuis l'IDE python Thonny par exemple);
3) On place dans le même répertoire : le fichier sphere.obj (généré automatiquement par le programme sphere.py) et les fichiers sphere.mtl et texture.png fournis dans l'archive sphere.zip ci-dessus
4) On ouvre le fichier sphere.obj avec meshlab.

Exemple: fichier sphere.obj généré par sphere.py, avec r=1, pa=9 et me=100.

2) Fichier sphere.mtl

Le fichier sphere.mtl est constitué de 6 lignes. Les 3 premières lignes sont des commentaires. Les trois lignes suivantes indiquent que la sphère est recouverture par la texture texture.png et qu'elle diffuse toutes les composantes de couleurs (RVB)

#
# Wavefront material file
#
newmtl material_0
Kd 1.000000 1.000000 1.000000
map_Kd texture.png

3) Fichier texture

Le fichier texture.png contient une image de taille carré (1024x1024pixels par exemple). Si on a besoin d'améliorer la résolution de l'image (afin de faire apparaître certains détails dans cette image), on peut opter pour une taille plus grande (4096 ou 8192 pixels par exemple). On peut naturellement utiliser un fichier jpg au lieu d'un fichier png. Par exemple, si on utilise le fichier texture.jpg, il suffit de remplacer la ligne "map_Kd texture.png" par la ligne "map_Kd texture.jpg" dans le fichier sphere.mtl.

Dans le cas présent, on utilise le fichier texture.png de 1024x1024 pixels, créé avec kolourpaint, pour tester le programme sphere.py.

On utilise le fichier texture.jpg de 8192x8192 pixels, joint dans l'archive sphere.zip, pour afficher une mappemonde de haute résolution.

4) Fichier sphere.py

Le fichier source python ci-joint a été créé à l'aide de l'IDE Thonny 2.1.16

Fichier source python: sphere.py

On exprime les coordonnées des sommets de la sphère en coordonnées sphériques. On raisonne avec pa=3 parallèles et me=6 méridiens puis on généralise le raisonnement pour que l'algorithme de création des sommets soit valable pour une une valeur quelconque de pa impaire supérieure ou égale à 3 et me paire supérieure ou égale à 4.

Application d'une texture sur une sphère 3D

On numérote les sommets, les coordonnées de texture et les faces de la sphère de façon à pouvoir les parcourir séquentiellement de la manière la plus pratique possible avec des boucles de programme. Les sommets, les coordonnées de textures et les faces sont séquentielles (la première ligne de chaque série v, vt et f correspond au n°1, la seconde au n°2 et ainsi de suite...).
Les faces quadrangulaires (cotés de la sphère) sont codées sous la forme f v1/vt1 v2/vt2 v3/vt3 v4/vt4 avec v1 numéro du sommet 1, v2 numéro du sommet 2,..., vt1 numéro de la coordonnée de texture 1, vt2 numéro de la coordonnée de texture 2,...
Les faces triangulaires (dessus et dessous de la sphère) sont codées sous la forme f v1/vt1 v2/vt2 v3/vt3.

sphère 3D - sommets, faces et coordonnées de texture

On obtient le rendu suivant avec le fichier texture.png (1024x1024 pixels) ci-joint.

Sphère 3D - rendu avec meshlab

On obtient le rendu suivant avec le fichier texture.jpg (8192x8192 pixels) ci-joint.

Sphère 3D avec texture haute résolution - rendu avec meshlab

Remarque
Ce fichier a été créé avec Gimp, à partir d'une image de carte du monde obtenue sur le site Public domain vectors: Royalty-free vector clip art, svg files" https://publicdomainvectors.org.

4.1) Code source python sphere.py

#=============
# sphere.py - Auteur Claude Turrier - janvier 2021
# Ce programme génère un fichier sphere.obj (sphère 3d texturée)
# r: rayon de la sphère
# pa : nombre de parallèles (nombre impaire supérieur ou égal à 3)
# me: nombre de méridiens (nombre pair supérieur ou égal à 4) # Utilisation:
# 1) fixer les valeurs de r, pa et me dans le prgoramme (lignes 21 à 23)
# 2) Lancer le programme
# 3) Placer dans le même répertoire : le fichier sphere.obj,
# (généré automatiquement par le programme sphere.py
# et les fichiers sphere.mtl et texture.png ci-joints
# 4) Ouvrir sphere.obj avec meshlab
#=============
import math as m
import sys
import os
#-------------
# Valeurs à fixer
#-------------
r=1.0
pa=3 # nombre de parallèles (nombre impair supérieur ou égal à 3)
me=6 # nombre de méridiens (nombre pair supérieur ou égal à 4)
#-------------
# Variables du programme
#-------------
pi=m.pi; v="v";vt="vt";f="f"
ns=me*pa #nombre de sommets
nc=pa*me+pa #nombre de coordonnées de texture
nf=(pa-1)*me #nombre de faces quadrangulaires (cotés)
nft=(me-2)*2 #nombre de faces triangulaires (dessus et dessous)
phi= pi/(2*pa)
theta=2*pi/me
#----------
# Redirection de la sortie print vers le fichier sphere.obj
#-----------
if os.path.exists('sphere.obj'):
os.remove("sphere.obj")
temp = sys.stdout
sys.stdout = open('sphere.obj', 'a')
#--------------
# Création du fichier sphere.obj
#---------------
print ("#################")
print ("# SPHERE 3D")
print ("# OBJ File sphere.obj généré par sphere.py")
print ("# Auteur Claude Turrier - Janvier 2021")
print ("# Parallèles: %3d" %(pa))
print ("# Méridiens: %3d" %(me))
print ("# Sommets: %3d" %(ns))
print ("# Faces quadrangulaires: %4d (cotés)" %(nf))
print ("# Faces triangulaires: %4d (dessus et dessous)" %(nft))
print ("# Coordonnées de texture: %4d" %(nc))
print ("############")
print (" ")
print("mtllib ./sphere.mtl")
print("usemtl material_0")
print()
#--------------
# ns=me*pa=sommets v (ns=18 pour une sphere pa,pe=3,6)
#------------
for i in range (1,2*pa,2) :#formule générale
  for j in range (0,me) :
  x=r*m.sin(i*phi)*m.cos(j*theta)
  y=r*m.sin(i*phi)*m.sin(j*theta)
  z= r*m.cos(i*phi)
  print ("%1s %4f %4f %4f" %(v, x, y, z))
#-------
# nc=pa*me+pa coordonnées de textures (nc=21 pour une sphere pa,pe=3,6)
#---------
#vt numéro 1 à numéro pa*me
pas_horiz=1/me
pas_vert=1/(pa-1)
for i in range (0,pa) :
  for j in range (0,me) :
  u=0.0+pas_horiz*j
  v=1.0-i*pas_vert
  print ("%1s %4f %4f" %(vt, u, v))
#vt numéro pa*me+1 à numéro pa*me+pa
for i in range (0,pa) :
  u=1.0
  v=1.0-i*pas_vert
  print ("%1s %4f %4f" %(vt, u, v))
#--------
# nf=(pa-1)*me=12 faces (nf=18 pour une sphere pa,pe=3,6)
#--------
#faces numéro 1 à (me-1)*(pa-1)
for i in range (1,pa) :#formule générale
 for j in range (1,me) :
  v1=i*me+j; vt1=v1;
  v2=v1+1; vt2=v2
  v3=v1-me+1; vt3=v3
  v4=v3-1; vt4=v4
  v1=str(v1);vt1=str(vt1);
  v2=str(v2);vt2=str(vt2);
  v3=str(v3);vt3=str(vt3);
  v4=str(v4);vt4=str(vt4);
  chaine= f + " " +v1+"/"+vt1 + " "+ v2+"/"+vt2 + " " + v3+"/"+vt3 + " " + v4+"/"+vt4
  print ("%1s" %chaine)
#faces numéro (me-1)*(pa-1)+1 à me*(pa-1)
for i in range (1,pa) :
 v1=me+i*me; vt1=v1;
 v2=i*me+1; vt2=ns+i+1;
 v3=1+(i-1)*me; vt3=ns+i
 v4=i*me; vt4=v4
 v1=str(v1);vt1=str(vt1);
 v2=str(v2);vt2=str(vt2);
 v3=str(v3);vt3=str(vt3);
 v4=str(v4);vt4=str(vt4);
 chaine= f + " " +v1+"/"+vt1 + " "+ v2+"/"+vt2 + " " + v3+"/"+vt3 + " " + v4+"/"+vt4
 print ("%1s" %chaine)
#faces du dessus (triangulaires)
for i in range (1, me-1) :
 v1=1;vt1=8
 v2=i+1;vt2=2
 v3=i+2 ;vt3=1
 v1=str(v1);vt1=str(8);
 v2=str(v2);vt2=str(2);
 v3=str(v3);vt3=str(1);
 chaine= f + " " +v1+"/"+vt1 + " "+ v2+"/"+vt2 + " " + v3+"/"+vt3
 print ("%1s" %chaine)
#faces du dessous (triangulaires)
for i in range (1, me-1) :
 v1=ns;vt1=8
 v2=ns-i;vt2=2
 v3=ns-i-1 ;vt3=1
 v1=str(v1);vt1=str(8);
 v2=str(v2);vt2=str(2);
 v3=str(v3);vt3=str(1);
 chaine= f + " " +v1+"/"+vt1 + " "+ v2+"/"+vt2 + " " + v3+"/"+vt3
 print ("%1s" %chaine)
#-------------
# Redirection de la sortie print vers l'écran
#-------------
sys.stdout.close()
sys.stdout = temp

4.2) Globe terrestre 3D au format obj

Le globe terreste peut être directement affiché en format 3D obj dans les navigateurs compatiblec avec WebGL (navigateurs récents)

Globe terrestre 3D au format obj.