Le concept derrière les objets primitifs (en bref, primitives) est de vous donner la possibilité de créer facilement des scènes 3d simples. Un grand choix de primitives peut ainsi être rendues de manière très efficace. Définir un objet dans Ultimate 3D fonctionne de la façon suivante. Comme je l'ai déjà dit, chaque objet dans Ultimate 3D doit être représenté par une instance d'objet dans Game Maker. Donc, vous devez créer un nouvel objet d'abord. Ensuite, vous devez définir un ensemble de variables pour cet objet. Enfin vous appelez une fonction qui transmet les valeurs des variables à Ultimate 3D et crée votre objet. Nous pouvons commencer avec un premier objet visible.
Un objet wall est totalement plat et orienté verticalement. Avant de le créer, vous devez définir les variables suivantes:
height
Cette variable indique la hauteur du mur.
x2, y2
Ces deux variables indiquent jusqu'où le mur va à partir de ses positions x et y. Le graphique suivant l'illustre:
texture
Vous devez assigner cette variable à l'un des indices
que vous aviez attribué précedemment à une texture lors de l'utilisation de la fonction LoadTexture(...). Cette texture sera alors utilisée pour le mur. Si vous ne
souhaitez pas utiliser une texture, vous pouvez définir cette variable à
-1.
texx1, texy1, texx2, texy2 (optionnel)
Ces variables sont facultatives. Si vous n'avez pas
définit ces variables, toute la texture sera utilisée. Ils définissent les
deux prétendues coordonnées de la texture. Les coordonnées de texture x = 0 et y =
0 (en bref (0|0)) se réfèrent à la partie supérieure gauche de la texture. Les
coordonnées de texture (0.5|0.5) correspondent au milieu d'une texture, les
coordonnées de texture (0|1) à la partie inférieure gauche de la texture, les
coordonnées de texture (1|1) à la partie inférieure droite, et ainsi de suite. L'objet mur
utilisera la partie de la texture qui se trouve entre les deux données des
coordonnées de la texture. Les coordonnées de texture peuvent aussi être faites pour
des valeurs plus grandes que 1. Ensuite, la texture sera appliquée (de la même façon que le tuilage mais pour les textures)
Il y a deux variables supplémentaires qui sont utilisées pour les murs mais pour l'instant, vous n'avez pas besoin de les connaitre. Les primitives Floor et Cube les possèdent elles aussi. Elles sont décrites dans le tutorial "Ajout de lumières".
Maintenant que vous avez mis en place toutes les
variables requises, vous pouvez appeler CreateWall()
une fois. Cette fonction
ne prend aucun paramètre. Elle reçoit toutes les informations nécessaires à partir
des variables. Cependant, il faut mettre Step()
dans l'évènement step de
l'objet et Destroy()
, dans l'évènement destroy de ce dernier. Aucune de ces fonctions ne requièrent de paramètres. Destroy()
doit être mis dans l'évènement destroy parce qu'autrement Ultimate 3D
ne saurait jamais quand l'instance serait détruite. Dans ce cas, l'instance ne
disparaîtrait tout simplement pas. Ce que Step()
fait est le thème de la
prochaine partie de ce tutoriel. Donc accrochez-vous ! ;) .
Transformer... étrange mot. Cela paraît un peu compliqué, n'est-ce pas ? Eh bien, n'ayez pas peur, vous savez déjà comment transformer quelque chose; vous ne saviez juste pas que c'était appelé "transformation". Transformer quelque chose implique de changer son orientation. Si vous prenez un objet et le déplacez, c'est une transformation. Si vous le faite pivoter c'est une transformation aussi. Il y a une transformation qui ne peut se faire dans la vraie vie, mais vous le savez déjà de la 2D: scaler quelque chose. Scaler décrit les moyens de changer la taille d'un objet. Un objet peut être extrapolé (scalé) sur trois axes. Tous ces processus sont appelés transformations. Donc, la chose qu'il faudra retenir est que la transformation est la combinaison du scaling (changement de taille), la rotation et la translation (déplacement).
Et maintenant pour
transformer les primitives. Vous savez comment le faire, car vous avez
transformé un autre objet avant (si vous lisez ce tutorial
complètement): l'objet caméra. Comme l'objet caméra, chaque objet
primitif contient les variables x
, y
, z
, rotx
, roty
et rotz.
En outre, il gère également les variables scalx
, scaly
, scalz
. Etant donné que l'explication de l'utilité de rotx
, roty
et rotz
n'était pas détaillée dans le tutorial à propos des Objets caméras, voici une description plus détaillée, ainsi qu'une description de scalx
, scaly
, et
scalz
.
rotx, roty, rotz
Comme je l'ai déjà dit dans le tutoriel sur les Objets caméras, la variable rotx
donne la rotation de l'objet (le pitch), la variable roty
donne la rotation de lacet (yaw)
et la variable rotz
donne la rotation de roulis (roll). Le schéma ci-dessous illustre l'effet de ces variables.
Incrémenter rotx
pivotera le nez de l'avion vers les bas, décrémenter rotx
pivotera le nez de l'avion vers les haut. La rotation de lacet : yaw (roty
)
dirige l'objet sans changer sa coordonnée z. Enfin, il y a la rotation
de roulis (roll). Je pense qu'il n'y a rien de plus à dire à propos.
Notez que la rotation de roulis (roll) est appliquée en premier,
ensuite la rotation pitch et seulement la rotation de lacet (yaw) est
réalisée.
Un bref commentaire à ce sujet: Si vous avez lu attentivement, vous aurez peut-être
remarqué que roty
tourne autour de l'axe z alors que rotz
tourne autour de l'axe des ordonnées (y). Cette petite incohérence est
un vestige de la première version d'Ultimate 3D. Ces variables sont
nommées selon le système de coordonnées qui est utilisé par Ultimate 3D
en interne. Vous n'avez pas besoin de pécisions à ce sujet, il suffit
de garder à l'esprit que roty
tourne autour de l'axe z et rotz
tourne
autour de l'axe des ordonnées (y).
scalx, scaly, scalz
La notion de changement d'échelle (scaling) est très facile à
comprendre. Une échelle d'une valeur 1 signifie que rien ne
change, une échelle de valeur de 2 signifie que tout devient deux fois
plus important, et une échelle de valeur de 0.5 signifie que tout
devient moitié de la taille. Habituellement, vous ne devez pas utiliser
d'échelle de valeur négative. La seule chose qui me reste à vous
expliquer est pourquoi, il y a trois valeurs d'échelle (scaling). Parce
que de cette façon vous avez la possibilité de scalé la grosseur de
l'objet indépendamment dans les trois axes (x, y et z) du système de
coordonnées 3D. Mais dans la plupart des cas, vous voudrez scaler votre
objet de la même manière tout au long des trois axes, vous devrez alors
définir la même valeur pour les trois axes d'échelle. Notez que le
scaling se fait avant la rotation.
Une autre chose que vous ne devez jamais oublier, c'est que chaque objet Ultimate 3D doit contenir un appel à la fonction Step() dans leur évènement step. Sinon, les variables n'auront pas d'incidence sur la transformation du modèle!
Les objets Floor n'ont pas de taille le long de l'axe z, ce qui signifie qu'ils sont totalement plats et horizontaux. Les variables que vous devez mettre en place avant la création d'objets Floor sont les suivantes:
width, height
width
décrit la taille du sol le long de l'axe x et height
la taille du sol le long de l'axe y.
texture
Indice de la texture qui va être utilisée pour cet objet ou -1 pour aucune. Pour
une description plus détaillée, allez jeter un oeil sur le texte d'Objets Wall.
texx1, texy1, texx2, texy2 (optionnel)
La partie de la texture qui va être utilisée. Pour
une description plus détaillée, allez jeter un oeil sur le texte d'Objets Wall.
Comme
vous pouvez le voir, il n'y a pas beaucoup de changement par rapport
aux objets wall. À nouveau, il y a deux autres variables qui
seront introduites dans le tutorial à propos des sources de lumière. Après l'affectation
de ces variables, vous devez appeler CreateFloor()
pour initialiser l'objet floor. Et comme d'habitude, vous avez besoin de Step() et Destroy()
dans les événements correspondants.
Les objets cube sont un peu plus complexes que les sols et les murs, mais ils peuvent être utilisés pour des choses plutôt cool. Dans l'ancienne démo d'Ultimate 3D v. 1.31 tous les bâtiments étaient constitués de simples cubes. Comme avec d'autres primitives, vous devez configurer plusieurs variables avant de pouvoir créer un cube. Voici une liste de ces dernières:
width, height, depth2
Les dimensions du cube. width
donne la largeur du cube (axe x), depth2
donne la profondeur du cube, soit sa taille sur l'axe y et height
donne la taille du cube sur l'axe z. depth2
s'appelle "depth2" au lieu de
"depth", parce que la variable depth
est déjà utilisée par Game Maker.
texx1, texy1, texz1, texx2, texy2, texz2 (optionnel)
La partie de la texture qui va être utilisée. Pour
une description plus détaillée de ces paramètres, allez jeter un oeil sur le texte des Objets Wall.
Etant donné que les objets cube sont en trois dimensions alors que les
murs sont en deux dimensions, les objets ont trois paires de ces
paramètres.
texture
L'indice de la texture qui va être utilisée pour cet objet ou -1 pour aucune. Pour
une description plus détaillée allez jeter un oeil sur le texte sur les Objets Wall.
subdivide_texture (optional)
Comme chacun le sait, un cube a six faces. Si vous définissez
cette variable à "false" toutes les faces utiliseront la même partie de
la texture. Si vous la définissez à "true", la texture sera subdivisée en
six parties et chaque côté du cube utilisera une autre partie de la
texture. Le schéma suivant montre comment cela fonctionne.
Quand subdivide_texture est "false", l'ensemble de la texture est affichée de chaque côté. Quand il est "true", chaque côté ne montre qu'une seule partie.
originx, originy, originz (optionnel)
Ces variables prennent habituellement des valeurs dans la
fourchette de 0 à 1. Elles définissent où l'origine du cube se
trouve. Par exemple, la saisie de 0.5 pour chacune d'entre elle
voudrait dire que l'origine du cube se trouve exactement au milieu.
Saisir les valeurs correctes pour ces variables est très important,
surtout lorsque vous faites pivoter le cube. Le schéma suivant en
illustre le mécanisme:
Après l'affectation de ces variables, vous devez appeler la fonction CreateCube()
une
fois pour initialiser l'objet cube. Et comme d'habitude, vous avez besoin de Step() et Destroy() dans les événements correspondants.
Les billboards diffèrent un peu de tous les autres objets 3D. La raison en est simple. Ils ne sont pas en 3D. Il arrive souvent que de la géométrie extrêmement complexe soit requise pour certains objets. Les arbres sont le meilleur exemple. Pour éviter cette géométrie complexe, vous pouvez utiliser les billboards. Dans les jeux anciens, vous voyez souvent que les arbres sont en 2D alors que tout le reste est en 3D. Voici les billboards. Des billboards sont des objets 2D dans un espace 3D. Ils sont fixés à un point dans un espace 3D et leur taille sur l'écran change en fonction de la distance de la caméra.
Quoi qu'il en soit, la création de billboards n'est pas plus difficile que toute la création d'autres objets primitifs. Voici les variables qui doivent être mise en place pour cela:
width, height
Les dimensions du billboard.
originx, originy
Ces variables définissent l'origine du billboard. L'origine est
le point du billboard qui ne change pas de position dans l'espace 3D
lorsque la caméra pivote. En général il est quelque part au milieu du
billboard. En principe, il fonctionne de la même façon que les
variables originx/y/z
des Objets Cube. Alors, jetez un coup d'œil à leur description.
texture
Indice de la texture qui va être utilisé pour cet objet ou -1 pour aucune. Pour
une description plus détaillée de ces paramètres, allez jeter un oeil au texte d'Objets Wall.
texx1, texy1, texx2, texy2 (optionnel)
La partie de la texture qui va être utilisée. Pour
une description plus détaillée de ces paramètres, allez jeter un oeil au texte d'Objets Wall.
Après la mise en place de ces variables, vous devez appeler la fonction Create2D()
une fois pour initialiser l'objet billboard. Et comme d'habitude, vous avez besoin de
Step() et Destroy() dans les événements correspondants.
Dans la partie de cette documentation destinée aux utilisateurs avancés vous constaterez que tout modèle peut être manipulé comme un objet primitif. Cependant actuellement, vous ne savez pas que les objets polygones sont les primitives les plus complexes que vous allez connaître. Avant de vous dire ce qu'est un objet polygon, je vais vous expliquer que signifie le terme: vertex. Un vertex est un point dans un espace 3D, possèdant les coordonnées d'une texture, faisant partie d'un objet 3D. Un triangle est toujours constitué de trois vertices (sommets) et chaque objet 3D est constitué d'un ensemble de triangles. Donc on pourrait dire des vertices que c'est la plus petite unité des objets 3d.
Les polygones ne sont pas définis par un ensemble de variables. À la place de quoi vous appelez trois fonctions. Vous avez besoin d'une instance d'objet pour chaque objet polygon. La première fonction que vous devez appeler se nomme BeginPolygon(...). Cela informe Ultimate 3D que vous désirez créer un objet polygon et prépare tout ce qui est nécessaire dans ce but. Voici un description de la fonction:
BeginPolygon(
VertexNumber
)
|
---|
VertexNumber
Le nombre de vertices (sommets) du polygone que vous vous apprêtez à créer. La
valeur de cette variable doit toujours être supérieure ou égale à trois, sinon
vous n'obtiendrez pas un véritable polygone.
Après avoir appellé BeginPolygon(...) vous devez appeler AddVertex(...) plusieurs fois en fonction de la valeur que vous avez passé à BeginPolygon(...). Voici la description de AddVertex(...):
AddVertex(
X,Y,Z,
U,V
)
|
---|
X, Y, Z
La position du vertex. Notez que ces positions sont transformées selon les
valeurs que vous avez choisies précedemment pour x
, y
, z
, scalx/y/z
et rotx/y/z
. Ainsi, la position est donnée à l'échelle de l'objet.
U, V
La coordonnée de la texture du vertex. Pour obtenir une description détaillée de ce
qu'est une coordonée de texture, lisez la description des variables
texx1 et texy1 des Objets Wall.
Lorsque vous avez appelé AddVertex(...) suffisamment, vous pouvez appeler CreatePolygon()
pour créer l'objet polygon. Comme pour tous les autres objets
primitifs, il possède la variable texture
, et les variables de transformation (pour plus
d'information jetez un coup d'œil à la description des Objets Wall au
sujet de la transformation des primitives). Pour cette raison, vous devez mettre Step() et Destroy() dans les évènements Game Maker correspondants.
Voici un exemple de code qui montre comment créer un objet polygon simple:
BeginPolygon(5);
|
---|
Cette image montre le résultat de l'appel de ces fonctions:
Chacun des vertex d'un objet polygon peut être modifié après la creation du polygône. Pour faire cela, il y a deux fonctions: l'une pour récupérer des données à propos du polygône, et l'autre pour changer ces données. Voici une description de deux d'entre elles:
Cette fonction permet d'extraire des données de l'objet polygône qui appelle la fonction. Elle peut être appelée après CreatePolygon().
GetVertex(
VertexIndex,
ElementIndex
)
|
---|
VertexIndex
Ce paramètre permet d'identifier le vertex duquel vous souhaitez obtenir des
informations. Le vertex qui a été ajouté en premier au polygône a l'indice 0. L'indice le plus élevé valable est VertexNumber
-1.
ElementIndex
Ce paramètre indique dans Ultimate 3D quel type d'information doit être récupéré.
Voici la signification de chaque valeur:
0 = X;
1 = Y;
2 = Z;
3 = U;
4 = V;
Cette fonction modifie les données de l'un des vertices d'un objet polygône qui appelle la fonction. Elle peut être appelée après CreatePolygon().
SetVertex(
VertexIndex,
X,Y,Z,
U,V
)
|
---|
VertexIndex
Ce paramètre permet d'identifier le vertex dont vous
souhaitez modifier les informations. Le vertex qui a été ajouté en
premier au polygône a l'indice 0. L'indice le plus élevé valable est VertexNumber
-1.
X, Y, Z
La position du vertex. Pour plus d'informations, jettez un oeil à la description
de la fonction AddVertex().
U, V
Les coordonnée de la texture du vertex. Pour obtenir une description détaillée de ce
qu'est une coordonnée de texture, jetez un œil à la description des
variables texx1
et texy1
Objets Wall.
C'est tout ce dont vous avez besoin pour modifier la géométrie d'un polygone. Voici un exemple pour illustrer cela. Placé dans l'évènement step de l'objet polygone, le troisième vertex se déplace un peu vers le haut à chaque step.
SetVertex(2, GetVertex(2,0), GetVertex(2,1)+0.1, GetVertex(2,2), GetVertex(2,3), GetVertex(2,4)); |
---|
Dans sa forme la plus simple, en changeant les matériaux d'un objet on entend "changer sa couleur". Pour ce faire Ultimate 3D dispose d'une fonction très simple:
Cette fonction change l'étoffe (ses couleurs) de l'objet primitive qui est appellé.
SetMaterial(
Red,
Green,
Blue,
Alpha
)
|
---|
Red, Green, Blue
Ces paramètres définissent la nouvelle couleur qui va être utilisée. Les valeurs
des paramètres peuvent être de l'ordre de 0 à 255. (0 | 0 | 0), le noir et (255
| 255 | 255) signifie blanc.
Alpha
Ce paramètre donne l'opacité de l'objet. Il est défini de 0 à
255. 0 signifie qu'il n'y a pas d'opacité (totalement transparent) et 255 signifie qu'il est
totalement opaque.
Cette fonction modifie la partie émissive d'un matériau. La partie émissive d'un matériau n'est pas influencée par l'éclairage. Un bon exemple pour un matériau qui devrait utiliser l'éclairage émissif est un écran de TV. Il émet de la lumière ainsi sa luminosité n'est pas relative à la lumière. Vous pouvez également utiliser des matériaux émissifs si vous ne voulez pas que des objets soient influencés par la lumière. Par exemple, il semble généralement assez bizarre que les billboards soient influencés par la lumière.
SetMaterialEmissive(
Red,
Green,
Blue
)
|
---|
Red, Green, Blue
La couleur qui doit être utilisé pour la partie émissive de la matière. Là
encore, les valeurs doivent être contenue entre 0 et 255.
Vous savez déjà que vous pouvez changer la transformation d'une primitive après
sa création en utilisant les variables x
, y
, z
, rotx/y/z
, scalx/y/z
. La
même chose peut être faite avec la texture. Elle peut être modifiée à tout moment.
Mais qu'en est-il des autres propriétés d'une primitive? Par exemple, si vous souhaitez
animer une texture en changeant texx1
, texy1
, texx2
et texy2
? Si vous changez
ces variables après la création de la ligne primitive, l'objet ne change pas.
Pour cette raison, il y a la fonction RecreatePrimitive()
. Cette dernière fait exactement ce
que son nom indique. Elle détruit les primitives qu'elle recrée ensuite avec les nouvelles
données des variables.
© Christoph Peters. Certains droits réservés. (Traduction FR 04/2008, Franck Vernel / Damien Buhl).