2.3.2 Les formes basées sur les polygones

2.3.2.1 L'objet "mesh"

Vous savez que vous avez fait trop de raytracing quand ...
... Vous pensez que la théorie de l'évolution a été basée sur l'origine triangulaire de la roue.
-- Mark Kadela

Les objets maillés sont très pratiques car ils nous autorisent la création d'objets contenant des centaines de milliers de triangles. Comparé à une simple union de triangles, l'objet maillé stocke plus efficacement les triangles. Les copies d'objets maillés ne demandent qu'un peu de mémoire supplémentaire car les triangles ne sont stockés qu'une seule fois.

Pratiquement tous les objets peuvent être créés en utilisant des triangles, mais nous avons besoin de beaucoup de triangles pour créer des formes complexes. Aussi, nous ne créerons que des exemples simples. Ces exemples montreront malgré tout une caractéristique utile des triangles maillés : une texture différente peut être donnée à chaque triangle.

Commençons. Nous créerons une simple boîte avec des côtés de couleur différente. Nous créons un fichier vide appelé meshdemo.pov et ajoutons les lignes suivantes. Notez qu'un maillage est - sans surprise - déclaré en utilisant le mot clé mesh.

camera {
	location <20, 20,-50>
	look_at <0, 5, 0>
}
light_source {<50, 50,-50> color rgb <1, 1, 1>}
#declare Red = texture {
	pigment {color rgb <0.8, 0.2, 0.2>}
	finish {ambient 0.2 diffuse 0.5}
}
#declare Green = texture {
	pigment {color rgb <0.2, 0.8, 0.2>}
	finish {ambient 0.2 diffuse 0.5}
}
#declare Blue = texture {
	pigment {color rgb <0.2, 0.2, 0.8>}
	finish {ambient 0.2 diffuse 0.5}
}

Nous devons déclarer toutes les textures, avant de créer le maillage. Les textures ne peuvent pas être spécifiées dans le maillage, à cause des pauvres performances qui en résulteraient.

Maintenant, nous ajoutons l'objet maillé. Trois cotés utiliseront les textures définies, alors que le reste prendra la texture globale.

mesh {
	/* Côté haut */
	triangle {
		<-10, 10,-10>, <10, 10,-10>, <10, 10, 10>
		texture {Red}
	}
	triangle {
		<-10, 10,-10>, <-10, 10, 10>, <10, 10, 10>
		texture {Red}
	}
	/* Côté bas */
	triangle {<-10,-10,-10>, <10,-10,-10>, <10,-10, 10>}
	triangle {<-10,-10,-10>, <-10,-10, 10>, <10,-10, 10>}
	/* Côté gauche */
	triangle {<-10,-10,-10>, <-10,-10, 10>, <-10, 10, 10>}
	triangle {<-10,-10,-10>, <-10, 10,-10>, <-10, 10, 10>}
	/* Côté droit */
	triangle {
		<10,-10,-10>, <10,-10, 10>, <10, 10, 10>
		texture {Green}
	}
	triangle {
		<10,-10,-10>, <10, 10,-10>, <10, 10, 10>
		texture {Green}
	}
	/* Côté avant */
	triangle {
		<-10,-10,-10>, <10,-10,-10>, <-10, 10,-10>
		texture {Blue}
	}
	triangle {
		<-10, 10,-10>, <10, 10,-10>, <10,-10,-10>
		texture {Blue}
	}
	/* Côté arrière */
	triangle {<-10,-10, 10>, <10,-10, 10>, <-10, 10, 10>}
	triangle {<-10, 10, 10>, <10, 10, 10>, <10,-10, 10>}
	texture {
		pigment {color rgb <0.9, 0.9, 0.9>}
		finish {ambient 0.2 diffuse 0.7}
	}
}

Traçant cette scène à 320x240 nous verrons que le haut, la droite et la face de la boîte ont des textures différentes. Bien que cela ne soit pas un exemple impressionnant, il montre ce que nous pouvons faire. Des exemples plus complexes, utilisant aussi des triangles lissés, peuvent être trouvés dans le répertoire des scènes, comme chesmsh.pov.

2.3.2.2 L'objet "mesh2"

Le mesh2 est une représentation d'un maillage, c'est plus la représentation interne du maillage de POV-Ray que le mesh standard. Par conséquent, il est analysé plus vite et sa taille de fichier est moindre.

A cause de sa nature, mesh2 n'est pas réellement pratique pour construire des maillages à la main, il est prévu pour l'utilisation par les modeleurs et les convertisseurs de format de fichier. Une autre option est de construire les maillages avec des macros. Maintenant, pour comprendre le format, nous allons faire un petit exemple à la main et voir les options.

Ecrit comme 'mesh2'
Ecrit comme "mesh2"

Nous allons transformer ce maillage en objet mesh2. Le maillage est fait de 8 triangles, chacun avec 3 sommets, beaucoup de ces sommets sont partagés entre les triangles. Cela sera utilisé plus tard pour optimiser le maillage. D'abord nous allons aller au plus court.

Dans mesh2 tous les angles sont regroupés dans une liste appelée vertex_vectors{}. Une deuxième liste, face_indices{}, nous dit comment placer ensemble trois angles pour faire un triangle, en pointant sur le numéro d'index d'un sommet. Toute liste de mesh2 est de base zéro, le numéro du premier angle est 0. Le tout premier élément d'une liste est le nombre d'angles, de normales ou de vecteurs uv qu'elle contient. mesh2 doit être spécifié dans l'ordre VECTORS..., LISTS..., INDICES....

Voyons le maillage de dessus, nous faisons son décompte. Le nombre total d'angle est 24 (8 triangles * 3 angles).

mesh2 {
	vertex_vectors {
		24,
		...

Maintenant, nous pouvons ajouter les coordonnées des angles du premier triangle :

mesh2 {
	vertex_vectors {
		24,
		<0, 0, 0>, <0.5, 0, 0>, <0.5, 0.5, 0>
		..

Ensuite, il faut dire au maillage le mode de création du triangle; il y a un total de 8 faces (8 triangles). Le premier point de la première face, pointe sur le premier vecteur d'angle (0: <0, 0, 0>), le second sur le second (1: <0.5, 0, 0>), etc...

mesh2 {
	vertex_vectors {
		24,
		<0, 0, 0>, <0.5, 0, 0>, <0.5, 0.5, 0>
		...
	}
	face_indices {
		8,
		<0, 1, 2>
		...

Le maillage complet :

mesh2 {
	vertex_vectors {
		24,
		<0, 0, 0>, <0.5, 0, 0>, <0.5, 0.5, 0>,	// 1
		<0.5, 0, 0>, <1, 0, 0>, <0.5, 0.5, 0>,	// 2
		<1, 0, 0>, <1, 0.5, 0>, <0.5, 0.5, 0>,	// 3
		<1, 0.5, 0>, <1, 1, 0>, <0.5, 0.5, 0>,	// 4
		<1, 1, 0>, <0.5, 1, 0>, <0.5, 0.5, 0>,	// 5
		<0.5, 1, 0>, <0, 1, 0>, <0.5, 0.5, 0>,	// 6
		<0, 1, 0>, <0, 0.5, 0>, <0.5, 0.5, 0>,	// 7
		<0, 0.5, 0>, <0, 0, 0>, <0.5, 0.5, 0>	// 8
	}
	face_indices {
		8,
		<0, 1, 2>, <3, 4, 5>,	//1 2
		<6, 7, 8>, <9, 10, 11>,	//3 4
		<12, 13, 14>, <15, 16, 17>,	//5 6
		<18, 19, 20>, <21, 22, 23>	//7 8
	}
	pigment {rgb 1}
}

Comme mentionné plus haut, de nombreux angles sont partagés par les triangles. Nous pouvons optimiser le maillage en enlevant tous les angles dupliqués sauf un. Dans l'exemple cela réduit le nombre de 24 à 9.

mesh2 {
	vertex_vectors {
		9,
		<0, 0, 0>, <0.5, 0, 0>, <0.5, 0.5, 0>,
		/*comme 1*/ <1, 0, 0>, /*comme 2*/
		/*comme 3*/ <1, 0.5, 0>, /*comme 2*/
		/*comme 4*/ <1, 1, 0>, /*comme 2*/
		/*comme 5*/ <0.5, 1, 0>, /*comme 2*/
		/*comme 6*/ <0, 1, 0>, /*comme 2*/
		/*comme 7*/ <0, 0.5, 0>, /*comme 2*/
		/*comme 8*/ /*comme 0*/ /*comme 2*/
	}
	...

La phase suivante est de reconstruire la liste des indices de faces, puisqu'ils pointent sur des vertex_vector{} qui n'existent plus.

...
	face_indices {
		8,
		<0, 1, 2>, <1, 3, 2>,
		<3, 4, 2>, <4, 5, 2>,
		<5, 6, 2>, <6, 7, 2>,
		<7, 8, 2>, <8, 0, 2>
	}
	pigment {rgb 1}
}
2.3.2.2.1 Les triangles lissés et "mesh2"

Dans le cas où nous voulons un maillage lissé, les mêmes phases effectées s'appliquent aussi aux normales du maillage. Pour chaque angle, il y a un vecteur de normale listé dans normal_vectors{}, les duplicata peuvent être enlevés. Si le nombre de normales égale le nombre d'angles alors la liste normal_indices{} est optionnelle et les index de la liste face_indices{} sont utilisés à la place.

mesh2 {
	vertex_vectors {
		9,
		<0, 0, 0>, <0.5, 0, 0>, <0.5, 0.5, 0>,
		<1, 0, 0>, <1, 0.5, 0>, <1, 1, 0>,
		<0.5, 1, 0>, <0, 1, 0>, <0, 0.5, 0>
	}
	normal_vectors {
		9,
		<-1,-1, 0>, <0,-1, 0>, <0, 0, 1>,
		/*comme 1*/ <1,-1, 0>, /*comme 2*/
		/*comme 3*/ <1, 0, 0>, /*comme 2*/
		/*comme 4*/ <1, 1, 0>, /*comme 2*/
		/*comme 5*/ <0, 1, 0>, /*comme 2*/
		/*comme 6*/ <-1, 1, 0>, /*comme 2*/
		/*comme 7*/ <-1, 0, 0>, /*comme 2*/
		/*comme 8*/ /*comme 0*/  /*comme 2*/
	}
	face_indices {
		8,
		<0, 1, 2>, <1, 3, 2>,
		<3, 4, 2>, <4, 5, 2>,
		<5, 6, 2>, <6, 7, 2>,
		<7, 8, 2>, <8, 0, 2>
	}
	pigment {rgb 1}
}

Quand un maillage a un mélange de triangles plats et adoucis, une liste de normal_indices{} doit être ajoutée, où chaque entrée pointe sur un angle qui demande une normale. Dans l'exemple, seulement les quatre premières normales sont utilisées.

mesh2 {
	vertex_vectors {
		9,
		<0, 0, 0>, <0.5, 0, 0>, <0.5, 0.5, 0>,
		<1, 0, 0>, <1, 0.5, 0>, <1, 1, 0>,
		<0.5, 1, 0>, <0, 1, 0>, <0, 0.5, 0>
	}
	normal_vectors {
		9,
		<-1,-1, 0>, <0,-1, 0>, <0, 0, 1>,
		<1,-1, 0>, <1, 0, 0>, <1, 1, 0>,
		<0, 1, 0>, <-1, 1, 0>, <-1, 0, 0>
	}
	face_indices {
		8,
		<0, 1, 2>, <1, 3, 2>,
		<3, 4, 2>, <4, 5, 2>,
		<5, 6, 2>, <6, 7, 2>,
		<7, 8, 2>, <8, 0, 2>
	}
	normal_indices {
		4,
		<0, 1, 2>, <1, 3, 2>,
		<3, 4, 2>, <4, 5, 2>
	}
	pigment {rgb 1}
}
2.3.2.2.2 La projection UV et "mesh2"

La projection UV est une méthode de collage de textures 2D sur un objet de manière à ce que cela suive la forme de l'objet. Pour les triangles, immaginez-le comme suit; d'abord vous découpez une section triangulaire de la texture dans le plan xy. Puis étirez, tassez et déformez le morceau de texture pour qu'il emplisse le triangle et collez-le.

Maintenant, dans mesh2 nous construisons d'abord une liste de vecteurs 2D qui sont les coordonnées des sections triangulaires dans le plan xy. C'est la liste uv_vectors{}. Dans l'exemple, nous appliquons la texture de l'aire rectangulaire <-0.5,-0.5>, <0.5, 0.5> sur les triangles du maillage. Nous pouvons encore omettre les coordonnées dupliquées

mesh2 {
	vertex_vectors {
		9,
		<0, 0, 0>, <0.5, 0, 0>, <0.5, 0.5, 0>,
		<1, 0, 0>, <1, 0.5, 0>, <1, 1, 0>,
		<0.5, 1, 0>, <0, 1, 0>, <0, 0.5, 0>
	}
	uv_vectors {
		9
		<-0.5,-0.5>, <0,-0.5>, <0, 0>,
		/*comme 1*/ <0.5,-0.5>, /*comme 2*/
		/*comme 3*/ <0.5, 0>, /*comme 2*/
		/*comme 4*/ <0.5, 0.5>, /*comme 2*/
		/*comme 5*/ <0, 0.5>, /*comme 2*/
		/*comme 6*/ <-0.5, 0.5>, /*comme 2*/
		/*comme 7*/ <-0.5, 0>, /*comme 2*/
		/*comme 8*/ /*comme 0*/ /*comme 2*/
	}
	face_indices {
		8,
		<0, 1, 2>, <1, 3, 2>,
		<3, 4, 2>, <4, 5, 2>,
		<5, 6, 2>, <6, 7, 2>,
		<7, 8, 2>, <8, 0, 2>
	}
	uv_mapping
	pigment {wood scale 0.2}
}

Comme pour le normal_vectors, si le nombre de uv_vectors est égal au nombre d'angles, alors la liste uv_indices{} est optionnelle et les indices de la liste face_indices{} sont utilisés.

A l'inverse de la liste normal_indices, si la liste uv_indices est utilisée, le nombre d'indices doit être égal au nombre de face_indices. Dans l'exemple, une seule section de texture seulement est spécifiée et utilisée sur tous les triangles, en utilisant le uv_indices.

mesh2 {
	vertex_vectors {
		9,
		<0, 0, 0>, <0.5, 0, 0>, <0.5, 0.5, 0>,
		<1, 0, 0>, <1, 0.5, 0>, <1, 1, 0>,
		<0.5, 1, 0>, <0, 1, 0>, <0, 0.5, 0>
	}
	uv_vectors {
		3
		<0, 0>, <0.5, 0>, <0.5, 0.5>
	}
	face_indices {
		8,
		<0, 1, 2>, <1, 3, 2>,
		<3, 4, 2>, <4, 5, 2>,
		<5, 6, 2>, <6, 7, 2>,
		<7, 8, 2>, <8, 0, 2>
	}
	uv_indices {
		8,
		<0, 1, 2>, <0, 1, 2>,
		<0, 1, 2>, <0, 1, 2>,
		<0, 1, 2>, <0, 1, 2>,
		<0, 1, 2>, <0, 1, 2>
	}
	uv_mapping
	pigment {gradient x scale 0.2}
}
2.3.2.2.3 Une texture différente par triangle

En utilisant texture_list il est possible de spécifier une texture par triangle ou même par angle du maillage. Dans le dernier cas, les trois textures par triangle seront interpolées. Pour permettre à POV-Ray de connaître quelle texture appliquer à un triangle, l'index d'une texture est ajouté à la liste face_indices, après l'index de la face à laquelle elle appartient.

mesh2 {
	vertex_vectors {
		9,
		<0, 0, 0>, <0.5, 0, 0>, <0.5, 0.5, 0>,
		<1, 0, 0>, <1, 0.5, 0>, <1, 1, 0>
		<0.5, 1, 0>, <0, 1, 0>, <0, 0.5, 0>
	}
	texture_list {
		2,
		texture {pigment {rgb <0, 0, 1>}}
		texture {pigment {rgb <1, 0, 0>}}
	}
	face_indices {
		8,
		<0, 1, 2>, 0, <1, 3, 2>, 1,
		<3, 4, 2>, 0, <4, 5, 2>, 1,
		<5, 6, 2>, 0, <6, 7, 2>, 1,
		<7, 8, 2>, 0, <8, 0, 2>, 1
	}
}

Pour spécifier une texture par angle, trois indices texture_list sont ajoutés après le face_indices

mesh2 {
	vertex_vectors {
		9,
		<0, 0, 0>, <0.5, 0, 0>, <0.5, 0.5, 0>,
		<1, 0, 0>, <1, 0.5, 0>, <1, 1, 0>
		<0.5, 1, 0>, <0, 1, 0>, <0, 0.5, 0>
	}
	texture_list {
		3,
		texture {pigment {rgb <0, 0, 1>}}
		texture {pigment {rgb 1}}
		texture {pigment {rgb <1, 0, 0>}}
	}
	face_indices {
		8,
		<0, 1, 2>, 0, 1, 2, <1, 3, 2>, 1, 0, 2,
		<3, 4, 2>, 0, 1, 2, <4, 5, 2>, 1, 0, 2,
		<5, 6, 2>, 0, 1, 2, <6, 7, 2>, 1, 0, 2,
		<7, 8, 2>, 0, 1, 2, <8, 0, 2>, 1, 0, 2
	}
}

L'assignation d'une texture basée sur texture_list et l'interpolation est faite sur la base d'un triangle par triangle. Aussi il est possible de mélanger les triangles avec une seule texture et les triangles avec trois textures dans un maillage. Il est même possible d'y mélanger des triangles sans texture, ils prendront leur texture d'un élément texture général dans le mesh2. La projection UV est supportée pour les textures en utilisant texture_list.

2.3.2.3 L'objet polygone

Le polygon peut être utilisé pour créer tout objet plan, à n côtés comme les carrés, rectangles, pentagones, hexagones, octogones, etc.

Un polygone est défini par un nombre de points qui délimitent sa forme. Comme il doit être fermé, le premier point doit être répété à la fin de la séquence.

Dans l'exemple suivant, nous créerons le mot POV en utilisant seulement une déclaration.

Nous commençons par réfléchir aux points nécessaires aux formes désirées. Nous voulons que les lettres se couchent sur le plan x-y, avec la lettre O au centre. Les lettres s'étendent de y = 0 à y = 1. Ainsi nous avons les points suivants pour chaque lettre (la coordonnée z est automatiquement mise à zéro).

Lettre P (polygone externe) :

<-0.8, 0.0>, <-0.8, 1.0>,
<-0.3, 1.0>, <-0.3, 0.5>,
<-0.7, 0.5>, <-0.7, 0.0>

Lettre P (polygone interne) :

<-0.7, 0.6>, <-0.7, 0.9>,
<-0.4, 0.9>, <-0.4, 0.6>

Lettre O (polygone externe) :

<-0.25, 0.0>, <-0.25, 1.0>,
<0.25, 1.0>, <0.25, 0.0>

Lettre O (polygone interne) :

<-0.15, 0.1>, <-0.15, 0.9>,
<0.15, 0.9>, <0.15, 0.1>

Lettre V :

<0.45, 0.0>, <0.30, 1.0>,
<0.40, 1.0>, <0.55, 0.1>,
<0.70, 1.0>, <0.80, 1.0>,
<0.65, 0.0>

Les deux lettres P et O ont un trou, alors que V est un polygone unique. Nous commencerons avec la lettre V parce qu'elle est plus facile à définir.

Nous créons un nouveau fichier appelé polygdem.pov et ajoutons le teste suivant :

camera {
	orthographic
	location <0, 0,-10>
	right 1.3 * 4/3 * x
	up 1.3 * y
	look_at <0, 0.5, 0>
}
light_source {<25, 25,-100> color rgb 1}
polygon {
	8,
	<0.45, 0.0>, <0.30, 1.0>,	// Lettre "V"
	<0.40, 1.0>, <0.55, 0.1>,
	<0.70, 1.0>, <0.80, 1.0>,
	<0.65, 0.0>,
	<0.45, 0.0>
	pigment {color rgb <1, 0, 0>}
}

Comme noté précédemment, le polygone doit être fermé en ajoutant le premier point à la fin de la séquence. Un polygone fermé est toujours défini par une séquence de points qui se termine quand un point est identique au premier.

Après avoir créé la lettre V, nous continuerons avec le P. Puisqu'il a un trou, nous devons trouver le moyen de couper ce trou dans la forme de base. Cela est relativement facile. Nous devons définir la forme extérieure de la lettre P, qui est un polygone fermé, et ajouter la description du trou, qui est aussi un polygone fermé. C'est tout ce que nous avons à faire. Il y aura un trou quand les deux polygones se superposeront.

En général, nous obtenons des trous chaque fois qu'un nombre impair de sous-polygones se superposent dans une déclaration de polygone. Un sous-polygone est défini par une séquence de points fermée.

La lettre P consiste en deux sous-polygones, un pour la forme extérieure et un pour le trou. Puisque le polygone du trou se superpose à la forme externe, nous obtiendrons un trou.

Après avoir compris comment se comportent les sous-polygones dans une déclaration de polygone, il est aisé d'ajouter la lettre O manquante.

Finalement, nous obtenons le mot POV au complet.

polygon {
	30,
	<-0.8, 0.0>, <-0.8, 1.0>,	// Lettre "P"
	<-0.3, 1.0>, <-0.3, 0.5>,	// forme externe
	<-0.7, 0.5>, <-0.7, 0.0>,
	<-0.8, 0.0>,
	<-0.7, 0.6>, <-0.7, 0.9>,	// trou
	<-0.4, 0.9>, <-0.4, 0.6>,
	<-0.7, 0.6>
	<-0.25, 0.0>, <-0.25, 1.0>,	// Lettre "O"
	<0.25, 1.0>, <0.25, 0.0>,	// forme externe
	<-0.25, 0.0>,
	<-0.15, 0.1>, <-0.15, 0.9>,	// trou
	<0.15, 0.9>, <0.15, 0.1>,
	<-0.15, 0.1>,
	<0.45, 0.0>, <0.30, 1.0>,	// Lettre "V"
	<0.40, 1.0>, <0.55, 0.1>,
	<0.70, 1.0>, <0.80, 1.0>,
	<0.65, 0.0>,
	<0.45, 0.0>
	pigment {color rgb <1, 0, 0>}
}
Le mot 'POV' fait avec des déclarations de polygones
Le mot 'POV' fait avec des déclarations de polygones

Complément sur le "mesh"

2.3.1 Les formes basées sur les courbes 2.3.1 Les formes basées sur les courbes 2.3.3 Les autres formes 2.3.3 Les autres formes