Manipulation des modèles

Dans certains cas, il peut arriver que vous deviez modifier la géométrie d'un objet pendant que le jeu est en cours d'exécution; par exemple, si vous avez un objet pouvant être déformé avec une arme particulière. Cette déformation peut être réalisée à l'aide de vertex shader. Mais c'est plutôt compliqué. C'est pourquoi Ultimate 3D vous donne la possibilité de manipuler la géométrie d'un mesh en temps réel. Vous pouvez éditer chacun des vertex du mesh. Vous pouvez aussi modifier la façon dont les vertices sont mis ensembles en triangles. Vous pouvez changer le matériau en cours d'utilisation par un triangle. En fait, vous pourriez utiliser Ultimate 3D pour faire un programme de modélisation étant donné qu'il est possible de créer des meshs à partir de rien.

Il est également assez courant que l'animation d'un modèle doive être modifiée. Par exemple, dans les jeux à la troisième personne, vous voulez peut-être que le torse ou la tête du personnage tourne lorsqu'il regarde dans une autre direction. Cela peut être fait dans Ultimate 3D de deux façons différentes.

Manipulation de la géométrie des meshs

Avant que je n'explique comment manipuler la géométrie des meshs, je vais donner une explication du terme mesh lui même, car il se peut que vous n'ayez pas une idée exacte de ce que c'est. Un mesh est un morceau de géométrie. Il peut être composé d'un nombre arbitraire de triangles et de vertices. Si vous avez un fichier *.md2, chaque frame est un mesh. Si vous avez un fichier *.3ds, il se peut que votre modèle soit fait de plusieurs meshs. Si vous avez un fichier animé *.an8, chaque objet que vous avez créé dans Anim8or est un mesh. De plus, une copie de chacun des meshs sera créée lorsque vous ajouter un nouveau LoD (niveau de détail) à votre modèle.

Il est très important de garder à l'esprit qu'Ultimate 3D ne créera jamais le même mesh deux fois! Si vous charger un modèle d'un fichier, tous les objets basés sur ce modèle utiliseront les mêmes meshs. Cela serait une énorme gaspillage de mémoire si cela n'avait pas été fait ainsi. Donc si vous modifier le mesh d'un objet, ce mesh sera modifié pour chaque objet qui utilisent le même fichier. Pour d'autres données, telles que les matériaux et les os, ce n'est pas le cas parce qu'il ne prennent pas beaucoup de mémoire.

Désormais, il y a un autre terme nouveau que vous devez connaître. Jusqu'à présent vous avez appris que chaque objet 3D est fait de vertices et que ces vertices sont mis ensembles en triangles. Donc que chaque triangle est fait de trois vertices. Maintenant regardez l'illustration suivante.

ModelManipulationIndexBuffer.png

Comme vous pouvez le voir, ce rectangle est composé de neuf vertices différents (marqués par les petits carrés) et de huit triangles. Etant donné que chaque triangle est fait de trois vertices, vous supposez probablement que ce petit mesh requière 8*3 = 24 vertices pour être affichés. Mais il n'y a que 9 vertices différents, et seulement deux sont utilisés par seulement un seul triangle (marqués en vert). Le vertex du milieu est utilisé par six triangles. Et des choses comme ça arrivent vraiment souvent. Heureusement une simple méthode fut inventée il y a longtemps pour éviter ce gaspillage de mémoire. Si vous avez des modèles complexes, il peut arriver que le modèle a deux fois plus de triangles que de vertices. Mais comment cela fonctionne? C'est très simple. Vous sauvegardez chacun des vertex exactement une fois. L'ordre ne joue pas. Ensuite vous ajoutez un buffer nommé buffer d'index (et c'est le terme que vous devez vous rappeller) qui contient trois indices (des nombres entiers qui correspondent aux vertices) pour chaque triangle. Donc en réalité, un triangle n'est pas fait de trois vertices, mais de trois références à des vertices.

Après ce peu de théorie, il est temps de pratiquer. Dans Ultimate 3D, vous pouvez vérouiller n'importe quel mesh de n'importe quel objet de modèle à n'importe quel moment. Verouiller un mesh, signifie le préparer pour retrouver et changer ses données. Cela est nécessaire parce que la mémoire où les données du mesh sont sauvegardées peuvent être gérée par le périphérique graphique. Il est vraiment important que vous déverrouilliez chaque mesh que vous verrouillez. Si vous oubliez de le faire, il est possible qu'une violation d'accès se produise lorsque le mesh sera rendu à l'écran, et cela peut amener à de nombreuses erreurs de rendu ou à une erreur de Game Maker "unexpected errors". Pour verouiller les meshs, il existe la fonction suivante: 

Cette fonction verouille le mesh donné de l'objet par lequel elle est appellée.

LockMesh(
LockedMeshIndex,
MeshIndex,
Frame,
LoD
)

LockedMeshIndex
Dans Ultimate 3D, vous ne pouvez pas vérouiller plus de 32 meshs à la fois. Cela n'aurait pas posé de problème de définir une limite plus haute ici, mais si vous n'oubliez pas de débloquer les meshs, vous n'aurez jamais plus de 32 meshs bloqués en même temps de toute façon. La valeur de ce paramètre doit être entre 0 et 31. C'est l'indice qui sera associé au mesh vérouillé.

MeshIndex
L'indice du mesh que vous voulez verrouiller. Je vous conseille d'écrire une boucle for pour boucler à travers tout les meshs de l'objet. Vous pouvez utiliser la fonction GetMeshCount() pour obtenir le nombre de mesh qu'un objet a par frame.

Frame
La Frame dans laquelle vous voulez modifier un mesh. Si vous utilisez cette fonction pour un modèle qui n'a pas été chargé depuis une fichier *.md2 ou pour un objet créé avec AddFrame(...), vous devez toujours mettre 0 pour ce paramètre.

LoD
Le niveau de détail que vous voulez modifier. Le niveau de détail le plus élevé a l'indice 0. C'est aussi la valeur que vous devez entrer si vous n'utilisez pas plusieurs niveaux de détails pour le modèle.

Cette fonction déverrouille un mesh et redéfinit les données associées à l'indice du mesh verrouillé aux données par défaut. Elle doit être appellée une fois pour chaque appell de LockMesh(...)! 

UnlockMesh(
LockedMeshIndex
)

LockedMeshIndex
L'indice du mesh que vous voulez déverrouiller.

Une fois que vous avez verrouillé un mesh, vous pouvez le modifier de toutes les manières imaginables. Vous pouvez modifier ses vertex, ses indices de triangles et les matériaux qui sont associés avec chacun des triangles. Vous pouvez aussi référencer toutes ces informations. Pour chacune de ces tâches, il y a une fonction différente:

Cette fonction modifie un vertex du mesh verrouillé avec l'index donné:

SetLockedMeshVertex(
LockedMeshIndex,
VertexIndex,
ValueIndex,
NewValue
)

LockedMeshIndex
L'indice du mesh vérouillé que vous souhaitez modifier. C'est la valeur que vous mettez en premier paramètre lorsque vous appellez LockMesh(...) pour verrouiller le mesh.

VertexIndex
L'indice du vertex que vous voulez modifier. Je vous recommande d'écrire une boucle for pour boucler au travers de tous les vertices. Vous pouvez utiliser 
GetLockedMeshVertexCount(LockedMeshIndex) pour obtenir le nombre de vertices que le mesh vérouillé donné possède.

ValueIndex
Ce paramètre donne la partie de la donnée du vertex qui doit être changée. Etant donné qu'Ultimate 3D utilise un système de coordonnées différent que Game Maker, cette donnée est ordonnée de la façon suivante:
0 = VertexPositionX
1 = VertexPositionZ
2 = VertexPositionY
3 = VertexNormalX
4 = VertexNormalZ
5 = VertexNormalY
6 = VertexTextureCoordinate1U
7 = VertexTextureCoordinate1V
Ensuite les coordonnées de texture qui ont été ajoutées en utilisant AddTextureCoordinateSet(...) suivent. La normale d'un vertex est un vecteur requis pour calculer l'éclairage des objets. Habituellement, il n'y a pas besoin de les modifier manuellement. Si vous changer la géométrie du mesh, vous devriez appeller une fois RecalculateNormals() pour mettre à jour les normales. 

NewValue
La nouvelle valeur que vous voulez définir pour la partie donnée du vertex spécifié.

Cette fonction retourne une partie des données d'un vertex du mesh spécifié:

GetLockedMeshVertex(
LockedMeshIndex,
VertexIndex,
ValueIndex
)

LockedMeshIndex
L'indice du mesh verrouillé dont vous voulez récupérer des données. C'est la valeur que vous mettez comme premier paramètre lors de l'appel de la fonction LockMesh(...)

VertexIndex
L'indice du vertex dont vous voulez récupérer des données. Je vous recommande d'écrire une boucle for pour boucler au travers de tous les vertices. Vous pouvez utiliser  GetLockedMeshVertexCount(LockedMeshIndex) pour obtenir le nombre de vertices que le mesh vérouillé donné possède.

ValueIndex
Ce paramètre est exactement le même que ValueIndex dans SetLockedMeshVertex(...), regardez donc sa description.

Cette fonction modifie les vertices qui sont utilisés par le triangle ayant l'indice donné du mesh verrouillé spécifié.

SetLockedMeshTriangle(
LockedMeshIndex,
TriangleIndex,
VertexIndexA, VertexIndexB, VertexIndexC
)

LockedMeshIndex
L'indice du mesh verrouillé que vous voulez modifier. C'est la valeur que vous mettez en tant que premier paramètre lors de l'appel de LockMesh(...) pour verrouiller le mesh.

TriangleIndex
L'indice du triangle que vous souhaitez modifier. Je vous conseille d'écrire une boucle for pour boucler au travers de tous les triangles. Vous pouvez utiliser la fonction
GetLockedMeshTriangleCount(LockedMeshIndex) pour obtenir le nombre de triangle du mesh verrouillé spécifié. 

VertexIndexA, VertexIndexB, VertexIndexC
Les indices des vertices qui sont utilisés pour le triangle. Remarquez que l'ordre de ces paramètres a une influence, à cause du back face culling. Vous ne devez jamais entrer une valeur plus grande que le nombre de vertex du mesh verrouillé ici. Cela pourrait donner lieu à de sérieux problèmes d'affichage.

Cette fonction permet de retrouver l'indice d'un vertex d'un triangle dans le mesh verrouillé donné:

GetLockedMeshTriangle(
LockedMeshIndex,
TriangleIndex,
RequestedVertexIndex
)

LockedMeshIndex
L'indice du mesh verouillé dont vous voulez extraire des données. C'est la valeur que vous avez entré pour le premier paramètre de LockMesh(...) lorsque vous avez verrouillé le mesh. 

TriangleIndex
L'indice du triangle dont vous voulez extraire les données. Je vous conseille d'écrire une boucle for pour boucler au travers de tous les triangles. Vous pouvez utiliser la fonction GetLockedMeshTriangleCount(LockedMeshIndex) pour obtenir le nombre de triangles du mesh verrouillé spécifié. 

RequestedVertexIndex
Pour ce paramètre, vous pouvez passer 0, 1 ou 2 pour récupérer le premier, le deuxième ou le troisième indice de vertex du triangle.

Cette fonction change le matériau utilisé pour le triangle donné du mesh spécifié:

SetLockedMeshTriangleMaterial(
LockedMeshIndex,
TriangleIndex,
NewMaterialIndex
)

LockedMeshIndex
L'indice du mesh verrouillé pour lequel vous voulez changer le matériau du triangle. C'est la valeur que vous avez entré pour le premier paramètre de LockMesh(...) lors du verrouillage du mesh.

TriangleIndex
L'indice du triangle pour lequel vous voulez changer le matériau. Je vous conseille d'écrire une boucle for pour boucler au travers de tous les triangles. Vous pouvez utiliser la fonction GetLockedMeshTriangleCount(LockedMeshIndex) pour obtenir le nombre de triangles du mesh verrouillé spécifié. 

NewMaterialIndex
Le nouvel indice du matériau que vous voulez définir pour le triangle. Vous pouvez utiliser GetMaterialIndex(...) pour obtenir cette valeur.

Cette fonction retourne l'indice du matériau qui est actuellement utilisé par le triangle donné du mesh verouillé spécifié.

GetLockedMeshTriangleMaterial(
LockedMeshIndex,
TriangleIndex
)

LockedMeshIndex
L'indice du mesh verrouillé dont vous voulez extraire les données. C'est la valeur que vous avez entré pour le premier paramètre de LockMesh(...) lors du verrouillage du mesh.

TriangleIndex
L'indice du triangle dont vous voulez extraire les données. Je vous conseille d'écrire une boucle for pour boucler au travers de tous les triangles. Vous pouvez utiliser la fonction GetLockedMeshTriangleCount(LockedMeshIndex) pour obtenir le nombre de triangles du mesh verrouillé spécifié.

Il existe une autre fonction de manipulation de modèles qui a été mentionnée à quelques reprises auparavant. Elle peut être utilisée pour ajouter un nouvel ensemble de coordonnées de texture à tous les meshs d'un objet (les meshs ne doivent pas être verrouillés lorsque vous faites cela). Vous avez déjà vu comment remplir les coordonnées de texture ajoutées avec des données en utilisant la fonction SetLockedMeshVertex(...). Un moyen simple d'obtenir les données est de créer deux versions du même modèle avec deux ensembles de coordonnées de texture différents. Ensuite, vous pouvez créer une instance temporaire de la seconde version du modèle, bloquer ses meshs et les meshs du premier modèle, copier les coordonnées de texture du second modèle dans le premier modèle en quelques boucles for. Lorsque vous en aurez fini, vous pourrez détruire le second modèle temporaire. Mais venons en à la fonction.

Cette fonction peut être utilisée pour ajouter un nouvel ensemble de coordonnées de texture multidimensionnelles à tous les meshs de l'objet qui appelle la fonction (et tous les objets basés sur le même modèle!).

AddTextureCoordinateSet(
DimensionCount
)

DimensionCount
Le nombre de dimensions de l'ensemble de coordonnées de texture qu'il devrait avoir. Cette valeur peut être un entier entre 1 et 4. Une dimension signifie qu'il n'y aura qu'une seule valeur réelle dans la coordonnée de texture (U), deux dimensions signifie qu'il y en a deux (U, V), trois dimensions signifie qu'il y en a trois (U, V, W) et quatre signifie qu'il y en a quatre (U, V, W, Q).

Finalement, il y a une fonction qui permet l'utilisation de plusieurs ensembles de coordonnées de texture beaucoup plus facilement. Souvent vous avez besoin de ne charger simplement que deux ensembles de coordonnées de texture différents pour un modèle. Par exemple, le light mapping requiert un ensemble de coordonnées de texture pour la diffuse map et un second ensemble de coordonnées de texture pour la light map. Le problème est qu'aucun des formats de fichier supporté, mis à part les *.u3d, ne supportent plusieurs ensembles de coordonnées de texture. La solution pour ce problème est de créer deux versions du modèle, chacun d'eux ayant un ensemble de coordonnées de texture différent. Ensuite vous pouvez utiliser la fonction suivante pour combiner les deux.

Cette fonction copie tous les ensembles de coordonnées de texture du modèle donné aux meshs de l'objet de modèle qui appelle cette fonction et à tous les objets qui sont basés sur le même fichier de modèle. Les meshs de cet objet ne doivent pas être verrouillés.

AddTextureCoordinateSetsFromModel(
ModelFile, Password
)

ModelFile
Le modèle de fichier qui possède les ensembles de coordonnées de texture qui sont à ajouter. Ce modèle de fichier doit avoir le même nombre de meshs que l'objet de modèle qui appelle cette fonction, et tous les meshs doivent avoir le même nombre de vertices.

Password
Si ModelFile se réfère à un modèle Ultimate 3D crypté, vous pouvez passer le mot de passe à ce paramètre. Autrement, vous ne devez rien passer ou une chaîne vide.  

Manipulation d'animation

En particulier, dans les jeux à la troisième personne, il arrive très souvent que le personnage doive se déplacer interactivement. Par exemple, si vous avez un personnage avec une arme qui vise quelque part, son torse doit se lever et se baisser quand le joueur vise en haut ou en bas pour le rendre réaliste. Ultimate 3D propose deux façons différentes de faire cela. La première change simplement la rotation d'un os particulier. Cela peut être utilisé pour atteindre l'effet désiré assez facilement, mais cela ne rendra pas forcément bien. Pour cette raison, il y a aussi la possibilité de faire en sorte que des os particuliers utilisent d'autres valeurs de frame que les autres os. De cette façon, vous pouvez par exemple faire en sorte que la partie supérieure du corps d'un personnage utilise une animation différente que le reste. Pour les deux méthodes, vous avez besoin d'une fonction pour récupérer l'indice de l'os que vous voulez modifier.

Cette fonction retourne l'indice de l'os avec le nom donné, ou 0 s'il n'existe pas.

GetBoneIndex(
BoneName
)

BoneName
Le nom de l'os. Cela dépend du programme de modélisation que vous utilisez.

Si vous voulez faire quelque chose automatiquement pour tous les os dans un modèle, il est utile d'écrire une boucle, qui passe au travers de tous les os d'un modèle. Pour ce faire, vous avez besoin de savoir combien d'os font partie du modèle. Cette information peut être récupérée à l'aide de la fonction GetBoneCount() qui retourne le nombre d'os disponibles de l'objet de modèle qui l'appelle. Toutes les valeurs entières dans la fourchette allant de 0 à GetBoneCount()-1 sont des indices d'os valides. Une autre fonction, qui est utile lorsque vous voulez avoir un code qui fonctionne automatiquement avec les os est la suivante. 

Cette fonction retourne l'indice de l'os parent de l'os avec l'indice donné. Si l'os n'a pas d'os parent -1 est retourné.

GetBoneParent(
BoneIndex
)

BoneIndex
L'indice de l'os pour lequel vous voulez retrouver l'indice de l'os parent.

La fonction suivante est une de celles qui peuvent être utilisées pour faire pivoter un os. Cela donne habituellement un résultat assez irréaliste lorsque c'est utilisé pour des modèles de personnage, mais cela peut être très utile pour objets mécaniques tels que les tanks. Par exemple, il est très simple de donner une rotation à la tourelle d'un tank avec cette fonction.

Cette fonction supprimme toutes les clés de rotation de l'os avec l'indice donné, de l'objet qui appelle la fonction et crée une seule nouvelle clé de rotation avec la rotation spécifiée.

SetBoneRotation(
BoneIndex,
RotationX, RotationY, RotationZ
)

BoneIndex
L'indice de l'os que vous voulez modifier.

RotationX, RotationY, RotationZ
La nouvelle rotation. Les variables sont interprétées de la même façon que les variables rotx, roty et rotz des objets de modèle.

Voici la dernière fonction qui peut être utilisée pour des animations de personnages vraiment interactive et authentiques. Par exemple, vous pourriez faire un modèle qui a une animation pour la partie supérieure du corps dans laquelle il vise vers le haut et vers le bas et differentes animations lorsqu'il court pour les jambes. Ensuite cette fonction pourrait être utilisée pour faire en sorte que la partie supérieure du corps vise vers le haut ou le bas selon la position du viseur du joueur, tandis que les jambes seraient en train de courrir dans des directions différentes ou même en train d'attendre.

Cette fonction peut être utilisée pour définir une autre valeur de frame pour un os particulier, de l'objet qui l'appelle.

SetBoneFrame(
BoneIndex,
Frame,
AffectChildBones

BoneIndex
L'indice de l'os dont vous voulez changer la valeur de frame.

Frame
Une valeur positive donnant une valeur de frame absolue qui est destinée à être utilisée pour l'os. Elle sera utilisée à la place de la valeur de la variable frame, qui correspond à la valeur de retour de GetCurrentFrame(). 

AffectChildBones
Si vous passez true pour ce paramètre, la valeur de frame précisée sera utilisée non selon pour l'os avec l'indice BoneIndex, mais aussi pour tous les autres os qui sont attachés à cet os. Sinon, seul cet os sera affecté. Si l'un des os enfant a sa propre valeur de frame définie à l'aide de SetBoneFrame(...) celle-ci sera utilisée à la place, que vous passiez true ou false.

Un autre type important de la manipulation d'animation est l'interpolation entre deux poses dans une animation. Imaginez que votre personnage est en train de courrir. Le joueur arrête d'appuyer la touche qui le fait courrir, de sorte que le personnage doit s'arrêter. Maintenant cela serait assez laid si l'animation sauterait seulement à l'animation d'arrêt. Il serait plus agréable si cela s'interpolait doucement entre l'animation de course et l'animation d'arrêt. C'est là l'utilité de l'interpolation des poses.

Cette fonction commence une interpolation entre la pose actuelle et la pose du modèle à la frame de destination donnée.

StartPoseInterpolation(
DestinationFrame,
InterpolationDuration
)

DestinationFrame
La frame du modèle qui a la pose de destination.

InterpolationDuration
Le temps que prendra l'interpolation en steps. Au cours cet interval de temps, l'objet procèdera à l'interpolation entre les poses. Après quoi, cela continuera à jouer l'animation à partir de DestinationFrame, à moins que les valeurs first_frame et last_frame ne le permettent pas. Si vous voulez annuler l'interpolation d'une pose vous pouvez appeller à nouveau cette fonction et passer 0 pour ce paramètre.

Lorsque vous avez un modèle avec de très nombreuses animations différentes, vous trouverez peut-être inconfortable d'avoir toutes ces animations dans un seul fichier, avec une séquence d'animation après l'autre. Il serait plus agréable d'avoir un fichier pour chaque animation. Ultimate 3D propose une fonctionnalité à cette fin. Ce n'est pas une solution parfaite, mais ça fonctionne. Cela vous permet de charger des animations depuis un fichier de modèle.

Cette fonction copie une animation d'un fichier de modèle donné dans l'objet de modèle par lequel elle est appellée. Elle fait ça en remplaçant toutes les frames dans l'animation de cet objet de modèle, par celles sauvegardées dans modèle de fichier donné.

CopyAnimation(
SourceFile,
SourceFilePassword,
CopyRotationKeysOnly
)

SourceFile
Le fichier source depuis lequel vous souhaitez copier l'animation. Vous voulez peut-être précharger ce fichier de modèle à l'aide de PreloadMesh(...) pour éviter un lag.

SourceFilePassword
Si le fichier source est un fichier de modèle Ultimate 3D crypté  (*.u3d), vous pouvez entrer le mot de passe pour ce paramètre. Sinon, vous devez passer une chaîne vide. 

CopyRotationKeysOnly
Si ce paramètre est true, la fonction copiera exclusivement les clés de rotation, autrement toutes les clés seront copiées. Si le squelette de l'objet de modèle de destination ne correspond pas exactement au squelette du modèle source, cela peut être souhaitable.

Cette fonction doit être utilisée avec prudence. Cela ne peut fonctionner correctement seulement si le modèle source et l'objet de modèle de destination ont des squelettes identiques. Si vous passez true pour CopyRotationKeysOnly cela peut aussi fonctionner pour les modèles avec un squelette un tantinet différent, mais vous ne devriez pas vous appuyer là desssus. 

Création de meshs particuliers

Dans certains cas, il est nécessaire de créer des meshs à partir de zéro. Cela peut être fait facilement avec Ultimate 3D. Vous créer ces objets comme tous les autres. D'abord vous définissez un certain nombre de variables, ensuite vous appellez une fonction de création une fois et enfin vous devez ajouter Step() et Destroy() dans les évènements correspondants.

material_count
Le nombre de matériaux que le nouvel objet aura. Cette valeur ne peut être zéro.

vertex_count
Le nombre de vertices que l'unique mesh du nouvel objet aura. Cela doit être supérieur à trois.

triangle_count
Le nombre de triangle qu'aura le seul mesh du nouvel objet. Cette valeur ne peut pas être égale à zéro.

Après avoir défini ces variables, vous pouvez appeller CreateEmptyMesh(). Ensuite un objet avec le matériau donné, le nombre de vertices et de triangles sera créé et associé avec l'objet qui a appellé la fonction. Après que vous ayez ajouté Step() et Destroy() l'objet sera prêt à être utilisé. Mais avant que vous obteniez des résultats visibles, vous devez utiliser les fonctions de manipulation de modèle que j'ai introduit ci-dessus pour remplir le mesh avec une géométrie valide. Par défaut toutes les données de vertex et toutes les données d'indices seront remplies avec des zéros et tous les matériaux seront blancs et non texturés.

Fonctions de manipulation de modèles préconçues

Il y a un ensemble d'opérations de manipulation de mesh qui doivent être faites très souvent. Ultimate 3D propose quelques fonction facile à utiliser pour réaliser ces opérations. La plus importante recalcule les normales des vecteurs qui sont nécessaires pour obtenir un éclairage par pixel correct. Une autre adoucit les normales des meshs. Cela signifie qu'elle cherche les vertices ayant la même position mais des normales différentes pour fixer cela. La troisième calcule quelque chose nommé matrices inverse de l'espace tangent pour chacun des vertex. Une brève explication de ce que cela signifie peut être trouvée ci-dessous.

Cette fonction calcule un vertex de la normale de chacun des vertex de chaque mesh de l'objet qui l'appelle. Elle devrait être appellée à chaque fois que vous changez la géométrie du mesh, parce que les anciennes normales ne seront plus d'actualités. Elle ne prend pas d'arguments.

RecalculateNormals()

Il arrive très souvent que des plis apparaissent à la surface si les normales sont calculées de cette façon. Etant donné que les normales ne sont pas seulement requises pour le calcul de l'éclairage mais aussi pour les effets tels que le cel-shading et l'environment mapping, c'est vraiment indésirable. L'illustration suivante montre un modèle qui utilise l'environment mapping, regardez s'il y a des plis sur celui-ci.

ModelManipulationSmoothNormals.jpg

Pour éviter cela, Ultimate 3D propose une fonction simple. Elle cherche les plis dans le modèle et si elle en trouve elle les adoucit. Voici sa description.

Cette fonction cherche les vertices avec positions identiques, mais avec des normales différentes. Si elle en trouve, elle vérifie que l'angle entre leurs normales est plus petit que l'angle donné, et si c'est le cas elle les adoucit. Noter que ce processus est très intensif en temps de calcul.

SmoothNormals(
SmoothingAngle
)

SmoothingAngle
L'angle de lissage en degrés. La fonction adoucit les normales des deux vertices, uniquement, si l'angle entre elles est plus petit que celui-ci.

La fonction suivante a un but très spécifique. À moins que vous ne vouliez vous mettre à la programmation de pixel shader, vous n'avez pas besoin de la comprendre. Vous pouvez passer l'explication suivante. Beaucoup d'effets spéciaux, celui-ci en particulier, qui implémente une sorte de per pixel lighting, utilise les maps de normales. Les normal maps donnent les normales dans l'espace de la texture. C'est espace est appellé espace tangent. Les informations telles que celles de position des sources de lumières sont usuellement données dans l'espace de l'ensemble de mesh. Pour cette raison une méthode est requise pour obtenir les informations à propos des sources de lumières de l'ensemble de mesh en espace tangent. Une matrice (regardez le chapitre à propos des fonctions mathématiques) est nécessaire pour apporter des informations depuis l'ensemble des meshs à l'espace tangent. Et étant donné que chaque triangle est texturé différemment, cette matrice est requise pour chaque vertex.

Cette fonction calcule la matrice inverse de l'espace tangent (de l'ensemble de mesh à l'espace tangent) pour chaque vertex de chaque mesh de l'objet qui appelle la fonction, cela signifie qu'elle écrase les normales des meshs avec la troisième colonne de la matrice. Habituellement la troisième colonne est très proche des normales, cela ne fait donc pas d'énorme changement. Cela ajoute aussi deux nouveaux ensembles 3D de coordonées de texture. Le premier sera utilisé pour sauvegarder la première colonne de la matrice inverse de l'espace tangent, et le deuxième pour sauvegarder la deuxième colonne. Cette fonction ne prend pas de paramètres.

AddInverseTangentSpaceMatrices()


Cel-shading

Le Cel-shading est une technique courramment utilisée pour créer des graphismes qui ont l'air de faire partie d'une bande déssinée. Cela peut aussi être utilisé pour marquer un objet particulier en créant un surlignement autour de lui. Fondamentalement le Cel-shading crée une version extrudée de chaque mesh et calcule son rendu en utilisant un back face culling inversé. Cela consiste en un contour marqué autour du modèle. Lors de l'application du Cel-shading, vous pouvez r la largeur du contour dans l'espace de mesh et la couleur du contour. Communément la couleur du contour est un noir solide. Mais vous pouvez aussi utiliser d'autres couleurs pour réaliser d'autre effets super-cools. Par exemple, vous pouvez utiliser un rouge transparent pour mettre une accent sur l'objet auquel il est appliqué. Activer le cel-shading est très simple. Voici la fonction qui le fait: 

Cette fonction active le cel-shading pour l'objet de modèle par lequel elle est appellée.

ApplyCelShading(
LineWidth,
LineColorR, LineColorG, LineColorB, LineColorA
)

LineWidth
La largeur du contour que vous voulez créer dans l'ensemble de mesh.

LineColorR, LineColorG, LineColorB, LineColorA
La couleur du contour. Les valeurs pour ces paramètres doivent être comprises entre 0 et 255. LineColorA définit l'opacité du contour. 0 signifie aucune opacité (complètement transparent) et 255 complètement opaque.

Notez que le cel-shading utilise un vertex shader. Pour cette raison, les modèles utilisant le vertex skinning et du cel-shading ne doivent pas utiliser plus de 28 os, sinon, quelques os ne seront pas appliqués correctements.



© Christoph Peters. Certains droits réservés. (Traduction FR 04/2008, Franck Vernel / Damien Buhl).

Creative Commons License XHTML 1.0 Transitional