Le Langage VREL
Virtual Reality Engine Language
Introduction
*
1 Structure d’un programme VREL
*1.1 Forme générale d’un programme VREL
*a) Directives d’importation :
*b) Déclarations globales :
*c) Les définitions de classes :
*d) La fonction principale :
*1.2 Symboles d’un programme VREL
*a) Commentaires :
*b) Identificateurs :
*c) Mots-clés :
*d) Littéraux :
*
2 INSTRUCTIONS SIMPLES
*2.1 Déclaration de constantes et de variables :
*2.2 Affectation simple :
*
3 Expressions et opérateurs
*3.1 Les opérateurs
*a) L’opérateur d’affectation
*b) Les opérateurs arithmétiques
*c) Les opérateurs relationnels
*d) Les opérateurs logiques
*3.2 Ordre de précédence des opérateurs
*
4 Instructions de contrôle
*4.1 Séquence d’instructions
*4.2 Sélection par if
*4.3 Boucle while
*
5 Classes et objets
*5.1 La création d’objets
*5.2 Les classes composées
*5.3 Les classes étendues
*
6 Classes primitives de VREL
*6.1 Classe wall et classes dérivées
*a) Classe wall
*b) Classe step
*c) Classe board
*d) Classe web
*e) Classe vrml
*f) Classe doc
*g) Classe host
*6.2 Classes complexes
*a) Classe button
*b) Classe door
*c) Classe gate
*d) Classe aoi
*e) Classe earth
*f) Classe cauldron
*g) Classe backwalls
*
7 Exemples
*
Introduction
Le langage de programmation VREL a été développé de janvier à mars 2000 par Pascal Belin, Yanneck Chevalier, Julien Dauphin et Alexis Jeannerod, élève à l’Ecole Nationale Supérieure des Télécommunications (ENST), dans le cadre d’un projet de dominante Informatique. Il s’inscrit dans un projet beaucoup plus large qu’est le développement de VREng, Virtual Reality Engine, un moteur de réalité virtuelle développé à l’ENST.
Dans VREng, les mondes en 3 dimensions et les objets sont décrit au moyen de fichiers de configuration qui ont un aspect suffisamment rebutant pour décourager tout individu à créer son propre monde. En effet, on y trouve les coordonnées spatiales de l’objet (X, Y, Z, alpha), puis la dimension de l'objet (x, y, z) et éventuellement des éclairages (r, v, b) et des textures (une par plan), tout cela sur une même ligne. D'autres informations telles de des adresses numériques (IP, port, ttl) ou des chaînes de caractères pour le nommage peuvent intervenir pour certains objets.
Le langage VREL a donc pour objectif de pouvoir de décrire et coder facilement les mondes de VREng. VREL est un langage de type langage objet, très largement inspiré de Java.
Les fichiers VREL se traduisent en fichier de configuration grâce au logiciel ‘vrel’, développé en parallèle de VREL et dont les sources sont totalement libres. Nous renvoyons le lecteur au ‘man’ de ce logiciel pour connaître son fonctionnement.
Tout programme VREL est composé :
Directives d’importation :
Les directives d’importation permettent d’inclure des bibliothèques de classes d’objets, codées en VREL. Chaque directive d’inclusion commence par le mot import suivi du nom du fichier à inclure entre guillemets.
import "bibli1.vrel"
Il n’y a pas de distinction de type de variable dans VREL. Une variable ou une constante peut être déclarée globalement pour tout le programme. Une variable globale est une variable dont la portée s’étend sur l’intégralité des fonctions contenues dans le fichier. Les variables globales sont à déclarer, au choix, avant ou après la fonction principale, et en dehors des séquences d’instructions (voir paragraphe 4.1).
Une classe sert à décrire un objet type du monde 3D. Elle peut être de 2 types :
Dans les deux cas, la définition contient :
La fonction principale :
C’est dans cette fonction que sera décrit le monde. Elle doit être précédée du mot begin et d’une accolade ouvrante {, et finie par une accolade fermante } et le mot end. Elle est composée d’instructions terminées par un point-virgule.
L’importance des commentaires dans un programme n’est plus à démontrer. Ceux-ci peuvent être introduits dans un programme VREL de deux façons :
Identificateurs :
Un identificateur est le nom que le programme donne à une variable, une constante ou une classe. Il est formé d’un nombre quelconque de lettres majuscules ou minuscules non accentuées, de chiffres, ainsi que du caractère souligné considéré comme une lettre. Le premier caractère doit être une lettre. Les majuscules et les minuscules sont considérées comme des caractères différents.
Par convention :
Mots-clés :
Les mots-clés du langage, réservés à des fins spéciales sont présentés ci-dessous :
abs |
constructor |
extends |
mod |
TRUE |
begin |
do |
FALSE |
new |
var |
class |
Else |
if |
not |
while |
compound |
end |
import |
this |
|
On peut ajouter à ces identificateurs les noms des classes primitives d’objets du langage :
aoi |
button |
door |
host |
wall |
backwalls |
cauldron |
earth |
step |
web |
board |
doc |
gate |
vrml |
|
Les littéraux sont des constantes associées aux différents types de base du langage. On distingue deux sortes de littéraux :
6,52 est une constante numérique.
"images/wood.gif" est une constante chaînée.
Il est très fréquent d’utiliser dans un programme une même valeur, comme Pi en mathématiques. Une telle donnée, dont la valeur ne change pas au cours du programme, s’appelle une constante. A l’inverse, une variable est une donnée dont le contenu peut varier au cours de l’exécution du programme.
En VREL, il n’y a pas de distinction entre ces deux types, et c’est donc au programmeur de gérer la constance de certaines valeurs.
Comme beaucoup de langages, VREL permet de donner un nom à une constante ou une variable. La déclaration d’une variable consiste à donner un nom de variable, précédé du mot-clé var :
var hauteur ;
Les variables peuvent être initialisées lors de leur déclaration :
var longueur = 6 ;
var wood = "images/wood.gif" ;
La déclaration d’une variable doit être faite avant toute utilisation de celle-ci. Puisqu’une déclaration est considérée comme une instruction, elle peut intervenir n’importe où dans le programme. Une déclaration introduit un nom dans une portée. Pour un nom local déclaré dans un constructeur de classe, la portée s’étend depuis le point de déclaration jusqu’à la fin du bloc. Pour une variable globale, la portée s’étend sur toutes les fonctions décrites dans le fichier.
L’instruction d’affectation permet de donner ou d’affecter le résultat d’une expression à une variable. Le symbole utilisé pour l’affectation simple est le signe = .
var hauteur ;
hauteur = 10 ;
Une expression est l’association d’opérateurs et opérandes qui doivent être compatibles entre eux. Les opérandes peuvent être des variables, des constantes ou des objets. Les opérateurs dans VREL peuvent être classé en quatre classes :
Une affectation est la mémorisation du résultat d’une expression dans une variable. L’opérateur de l’affectation de VREL est le signe = est et se lit " égal à ". Cet opérateur ne permet que les affectations simples, c’est à dire ne comprenant qu’un signe =, comme par exemple :
hauteur = largeur / 3
mur = new wall (x, y, z,
a, l, w, h)Les affectations multiples ne sont pas acceptées. L’instruction suivante est incorrecte :
hauteur = largeur = 5 ;
Les opérateurs suivants servent à effectuer les opérations arithmétiques de base. Leurs opérandes sont des variables contenant des entiers ou des réels. Les opérateurs division / et modulo % font éventuellement des conversion de genre.
Opérateur |
Opération |
Remarque |
+ |
Addition |
|
- |
Soustraction |
|
* |
Produit |
|
/ |
Quotient |
Division entière si les opérandes sont tous les deux des entiers |
% |
Modulo |
Convertit préalablement les réels en leur partie entière |
L’expression 5.2/2 renvoie le réel 2.60000
L’expression 5/2 renvoie l’entier 2
L’expression 5%2 renvoie le reste de la division euclidienne : 1
Ces opérateurs servent à comparer les valeurs de différentes expressions. Si la condition est vérifiée, l’opérateur renvoie un booléen 1 (vrai), sinon, un booléen 0 (faux).
Opérateur |
Opération |
== |
Egalité |
!= |
Inégalité |
< |
Plus petit |
> |
Plus grand |
<= |
Plus petit ou égal |
>= |
Plus grand ou égal |
L’expression 7 == 4 renvoie le booléen 0
L’expression 7 > 4 renvoie le booléen 1
Ce type d’opérateur accepte des booléens comme opérandes et renvoie un booléen qui est le résultat du test logique.
Opérateur |
Opération |
! |
Négation logique |
&& |
ET logique |
|| |
OU logique |
L’expression !(7 == 4) renvoie le booléen 1
L’expression (7 > 4) && 0 renvoie le booléen 0
L’expression 1 || 0 renvoie le booléen 1
Quand une expression comporte plusieurs opérateurs, son évaluation se fait en respectant un certain ordre de priorité sur ses opérateurs. La priorité est toujours accordée aux parenthèses. La lecture des opérateurs est effectué suivant l’associativité et les ordres de priorité suivants :
Priorité |
Opérateurs |
Associativité |
1 |
() |
gauche à droite |
2 |
! |
droite à gauche |
3 |
* / % |
gauche à droite |
4 |
+ - |
gauche à droite |
5 |
< <= > >= == != |
gauche à droite |
6 |
&& || |
gauche à droite |
Le langage VREL dispose d’un jeu réduit d’instructions de contrôle qui est néanmoins suffisant pour la création efficace de mondes virtuels.
Une séquence d’instructions est une suite d’instructions entourées par des accolades { }. On aligne généralement ces instructions les unes sous les autres par convention et par commodité de lecture.
{
largeur = 40 ;
hauteur = 13 ;
new murblanc(largeur, hauteur) ;
}
La sélection (ou instruction conditionnelle) if permet de choisir l’exécution ou non d’une séquence d’instructions en fonction d’une condition. Cette condition est une expression renvoyant une valeur booléenne. La plupart du temps, elle est composée d’une ou plusieurs relations de comparaison articulées par des opérateurs logiques. La condition est remplie si la valeur booléenne renvoyée est TRUE.
If peut être suivi ou non d’une alternative qui sera exécutée si la condition du if n’est pas satisfaite. Cette alternative constitue une séquence d’instructions introduite par le mot réservé else.
Utilisation de if sans alternative :
if (i == 10){
mur = new murtexture(x, y, z,
a, l, w, h) ;mur.tex_xp = wood ;
}
Utilisation de if suivi de else :
if ( (i <= 4) && (i != 0)){
hauteur = largeur / i ;
}
else{
hauteur = largeur / 3 ;
}
A noter que les accolades sont obligatoires même si if ou else n’est suivi que d’une instruction.
Cette instruction est une instruction d’itération qui permet d’exécuter l’exécution d’une séquence d’instructions tant que la condition prescrite est respectée. La syntaxe de l’instruction while est semblable à celle de l’instruction if non suivie de else. Il est indispensable qu’une itération au sein de la séquence d’instructions assure la sortie de la boucle lors de l’exécution du programme.
while (i < 15)
{
Fonction(lieu_x + i*5, lieu_y) ;
i = i + 1 ;
}
La boucle for n’a pas été incorporée au langage VREL car elle est aisément remplaçable par une boucle while correctement programmée.
Le langage VREL est partiellement orienté objet. Partiellement seulement car ce langage n’a qu’une vocation descriptive, et il n’était pas nécessaire d’y introduire la notion de méthodes et d’héritage de méthodes que les lecteurs familiers des langages objet connaissent. La seule méthode proposée dans VREL est la méthode d’auto construction des objets.
La notion d’héritage est néanmoins présente pour les attributs et les types d’objets. Tous les objets crées en VREL héritent de méta classes qui sont les primitives de VREng, dont vous trouverez une description dans la section suivante.
Dans cette partie nous décrirons comment instancier un objet, puis comment créer de nouvelles classes à partir d’autres classes. VREL utilise pour cela 2 concepts : les classes composées et le classes étendues.
La création d’un objet à partir d’une classe est faite en appliquant l’opérateur new sur un constructeur de classe. Ce constructeur doit comporter le bon nombre de paramètres, tout en sachant qu’une classe peut admettre plusieurs constructeurs. Chaque constructeur d’une même classe ne diffère que par son nombre d’arguments.
new wall (5, 7, 1, 0, 5, 6, 1) ;
(voir la section 6 pour connaître les paramètres du constructeur de la classe wall)
Un objet ainsi créé peut affecter une variable (cette variable d’un type particulier n’a pas besoin d’être déclarée au préalable).
W1 = new wall (5, 7, 1, 0, 5, 6, 1) ;
Ceci permet ensuite de pouvoir modifier les attributs de l’objet ainsi créé :
W1.tex_xp = wood ;
Attention à bien faire la distinction entre les arguments du constructeur et les attributs d’une classe qui ne sont généralement pas les mêmes. Les attributs sont des champs facultatifs qui sont modifiables par notation pointée ; les arguments sont les paramètres obligatoires du constructeur.
Le langage VREL offre la possibilité de construire de nouvelles classes d’objets à partir de classes déjà existantes (primitives ou d’autres classes composées ou étendues crées par le programmeur).
En VREL, la définition de nouvelle classes composées est introduite par le mot class. Celui-ci doit être suivi du nom de la classe créée, et du mot compound. La définition de la classe est ensuite mise, entre accolades.
class tabouret compound
{
// définition de la classe
}
Dans la définition de la classe, on distingue deux sections qui sont, dans l’ordre :
la liste des attributs ;
la liste des constructeurs ;
La liste des attributs se présente comme une liste de déclarations de variables. On peut affecter une valeur par défaut à un ou plusieurs attributs :
class tabouret compound
{
// attribut de la classe :
var texture = wood ;
// constructeurs de la classe :
}
Une classe peut ensuite admettre plusieurs constructeurs, ceux-ci devant avoir un nombre différent de d’arguments. Chaque constructeur est précédé du mot constructor, suivi de la liste des arguments entre parenthèses, puis d’une liste d’instructions entre accolades. Ces instructions constituent la méthodes de construction de la classe.
class tabouret compound
{
// attribut de la classe :
var texture = wood ;
// constructeur de la classe :
constructor (posX, posY, posZ)
{
w1 = new wall(posX, posY, posZ, 0, 2.5, 2.5, 0.2) ;
w1.tex_zp = texture ;
w2 = new wall(posX+2.2, posY+2.2, posZ-2.5, 0, 0.1, 0.1, 2.5);
w3 = new wall(posX–2.2, posY+2.2, posZ–2.5, 0, 0.1, 0.1, 2.5);
w4 = new wall(posX+2.2, posY-2.2, posZ-2.5, 0, 0.1, 0.1, 2.5);
w5 = new wall(posX-2.2, posY-2.2, posZ-2.5, 0, 0.1, 0.1, 2.5);
}
}
Il existe une syntaxe plus simple lorsqu’il s’agit de faire une simple extension d’une classe. On peut vouloir par exemple faire une classe " mur_bleu " qui ne serait qu’une extension de wall avec les attributs de texture précisés à bleu.
Pour réaliser ce type d’extension, on remplace le compound de la méthode précédente par extends suivi de la classe dont la classe étendue hérite. La définition de la classe ne comporte plus que des affectations.
Class mur_bleu extends wall
{
tex_xp = bleu ;
tex_xn = bleu ;
tex_yp = bleu ;
// etc…
}
Attention : un attribut fixer dans un extends n’est plus modifiable.
W = new mur_bleu (1, 1, 0, 0, 4, 4, 6) ;
W.tex_xp = wood ; // cette affectation n’a aucun effet.
Ces classes sont la base de la programmation VREL car toutes les classes d’objets que l’utilisateur créera les réutiliseront. Nous allons en faire une description succincte, le lecteur pourra se référer à la documentation de Holger Krauth Comment écrire des fichiers de configuration pour une explication détaillé des primitives de VREng.
L’utilisation avancée de ces classes peut paraître difficile, mais le but de VREL est de proposer des bibliothèques de classes pré configurées, ce qui allège le travail des concepteurs de monde.
Avertissement : Pour éviter les redondances, nous avons défini des champs de paramètres dont les noms sont soulignés, et dont le contenu n’est expliqué qu’une seule fois. La description de la classe wall éclairera le lecteur sur les champs de paramètres les plus fréquemment rencontrés, comme Position, Orientation et Dimension.
La classe wall est la base d’une famille de classes qu’on pourrait appeler box (boite). Les autres classes décrites dans cette partie ne font qu’ajouter à wall des actions associées. Il est conseillé au débutant de bien se familiariser avec la classe wall.
La classe wall est la classe de base de VREL : il s’agit en fait d’un parallélépipède rectangle dont il faut préciser obligatoirement les attributs suivants : position, orientation et dimensions. Ces trois informations forment les paramètres d’appel de la classe wall.
Un appel de wall se fait nécessairement par :
new wall(x, y, z,
a, dx, dy, dz) ;
La classe wall possède également des attributs optionnels : textures, jeux de lumière.
pour les faces perpendiculaires à l’axe des x : tex_xp, tex_xn, où p et n indique qu’il s’agit de la face orientée vers les abscisses positifs ou négatifs.
De même, pour les autres faces, on a tex_yp, tex_yn, tex_zp, tex_zn.
diffRed, diffGreen, diffBlue
, pour l’éclairage diffus.ambRed, ambGreen, ambBlue
, pour la lumière d’ambiance.shinPar1, shinPar2, shinPar3
, pour la brillance.specPar1, specPar2, specPar3
, pour la réflexion.Les valeurs des composantes …Red …Green …Blue de la lumière dans éclairage diffus et lumière d’ambiance sont des valeurs comprises entre 0 et 1
Pour créer un mur texturé sur sa face supérieure, il faut d’abord instancier un wall puis affecter l’attribut correspondant à la face supérieure :
mur = new wall(x, y, z,
a, dx, dy, dz) ;mur.tex_zp = "http://www.enst.fr/images/wood.gif" ;
La classe step est similaire à la classe wall. Contrairement à cette dernière qui ne permet pas l’escalade, elle fait automatiquement monter l’avatar sur la face supérieure du parallélépipède (sans utiliser la touche insert qui permet de voler). Elle est particulièrement utile pour construire des escaliers.
Pour la construction, se référer à la classe wall.
Un appel de step se fait par :
new step(x, y, z,
a, dx, dy, dz) ;La classe board est également similaire à la classe wall, mais elle possède une action associée : l’ouverture d’une application de dessin
Pour la construction, se référer derechef à la classe wall.
Un appel de board se fait par :
new board(x, y, z,
a, dx, dy, dz) ;La classe web fonctionne exactement comme la classe wall, sauf pour l’appel de la classe qui contient un argument supplémentaire :
Un appel de web se fait par :
new web(x, y, z,
a, url, dx, dy, dz) ;La classe vrml ressemble comme deux gouttes d’eau à la classe web, mais l’action associée est l’ouverture d’un fichier vrml (extension .wrl) et non d’une page html. On utilise exactement la même syntaxe que pour web.
Un appel de vrml se fait par :
new vrml(x, y, z,
a, url, dx, dy, dz) ;La classe doc fonctionne comme la classe web, mais l’action associée est l’ouverture d’un fichier Postscript (extension .ps) et non d’une page html. On utilise exactement la même syntaxe que pour web.
Un appel de doc se fait par :
new doc(x, y, z,
a, url, dx, dy, dz) ;La classe host se base sur la classe wall, mais elle a un argument supplémentaire. L’action associée est l’ouverture d’une wall connexion telnet avec un hôte spécifié :
Un appel de host se fait par :
new host(x, y, z,
a, hostname, dx, dy, dz) ;
Ces classes reprennent pour la plupart des champs de paramètres rencontrés dans la partie précédente. Elles introduisent néanmoins des nouveautés notables.
La classe button est comme un wall, mais associée à une action de commutation entre deux états, comme par exemple pour ouvrir une porte. Il faut donc préciser un objet cible sur lequel l’action sera effectuée. Pour l’instant, les objets dont l’avatar peut modifier l’état sont les portes et les boutons.
Cette classe fait intervenir plusieurs champs de paramètres nouveaux :
Un appel de button se fait par :
new button( x, y, z,
a, startstate, targetname, method1,method2, SID/OID, dx, dy, dz)
;La classe door est le second type d’objet modifiable par l’avatar, il peut l’ouvrir ou la fermer. Des paramètres spéciaux doivent être ici aussi précisés.
Un appel de door se fait par :
new door( name, x, y, z,
a, angleopen, angleclosed, speed,xoffset, SID/OID, dx, dy, dz)
;
La classe gate permet d’accéder à un autre monde VREng par l’action de téléportation. Elle fonctionne comme la classe wall, sauf pour l’appel de la classe qui contient deux arguments supplémentaires :
Un appel de gate se fait par :
new gate(x, y, z,
a, url, ipm, dx, dy, dz) ;On pourra faire par exemple :
adresse = "www.enst.fr/~perso/monde.cfg";
ipmulti = "225.224.0.2/62666/15";
new gate(12, 4, 0,
0, adresse, ipmulti, 0.1, 2, 2) ;
L’acronyme aoi désigne Area Of Interest, à savoir une région parallélépipédique de l’espace où tous les avatars présents peuvent communiquer entre eux via une adresse IP multicast. Pour une définition plus détaillé des aoi, se référer à la documentation existante.
La déclaration d’une aoi ressemble à celle du wall à quelques exceptions près. Les paramètres d’appel obligatoires sont la Position, le Nom de l’aoi, son Adresse IP multicast et sa Dimension :
Attention : il n’y a pas de champ Orientation.
Un appel de aoi se fait par :
new aoi(x, y, z, aoiname, ipm, dx, dy, dz)
;
La classe earth décrit une sphère qui tourne lentement. Ses propriétés sont évidemment radicalement différentes de celles de wall. On retrouve le champ Position, mais il y a un nouveau paramètre obligatoire :
Un appel de earth se fait par :
new earth(x, y, z, r)
;Attention : un monde ne peut contenir qu’un objet de la classe earth.
Comme une sphère blanche qui tourne n’est pas très intéressante, l’usage des textures est fortement recommandé. Il faut modifier l’attribut texture après l’instanciation de la sphère.
De la même manière que pour le wall, il y a des attributs Jeux de lumière.
On pourra faire par exemple :
wood = "http://www.enst.fr/~perso/images/wood.gif"
;rayon = 1
;terre = new earth(12, 4, 0, rayon)
;terre.tex = wood
;
La classe cauldron crée un tore solide. Elle est assez simple car il n’y a pas de texture. Cette classe reprend le champ Position, et utilise également un champ pour ses dimensions propres :
Un appel de cauldron se fait par :
new cauldron(x, y, z, R, r)
;Encore une fois, il y a des attributs Jeux de lumière comme pour wall.
Un backwall est un wall le long duquel on peut glisser. Il faut le spécifier dans un fichier de configuration spécial (d’extension .cfg) contenant dix colonnes :
xStart xEnd yStart yEnd zSart zEnd red green blue
On ne peut pas les tourner ni leur donner de textures. On ne donne que les coordonnées des points où les murs commencent et finissent. Les champs red, green et blue définissent les composantes primaires de la couleur du mur, elles ont des valeurs entre 0 et 1.
La classe primitive backwalls de VREL fait simplement appel à l’adresse URL de ce fichier de configuration spécial.
Un appel de backwalls se fait par :
new backwalls(url)
;
Le lecteur trouvera dans cette partie différents exemples de fichiers Vrel afin de mieux comprendre le langage décrit dans les parties précédentes. Les exemples proposent de construire des objets de type mobiliers.
Fichier walluni.vrel :
Var wood = "http://www.infres.enst.fr/vreng/gif/wood.gif"
class WallUni compound
{
var text ;
constructor(posX, posY, posZ, Angle, EpX, EpY, EpZ, text)
{
w = new wall(posX, posY, posZ, Angle, EpX, EpY, EpZ);
w.tex_xp = text ;
w.tex_xn = text ;
w.tex_yp = text ;
w.tex_yn = text ;
w.tex_zp = text ;
w.tex_zn = text ;
}
constructor(posX, posY, posZ, Angle, EpX, EpY, EpZ)
{
w = new wall(posX, posY, posZ, Angle, EpX, EpY, EpZ);
w.tex_xp = tex ;
w.tex_xn = tex ;
w.tex_yp = tex ;
w.tex_yn = tex ;
w.tex_zp = tex ;
w.tex_zn = tex ;
}
}
class wallwood extends wallUni
{
text = wood ;
}
Fichier tabouret.vrel :
import "walluni.vrel"
class Tabouret compound
{
constructor (posX, posY, posZ)
{
new wallwood(posX, posY, posZ, 0, 2.5, 2.5, 0.2) ;
new wallwood(posX+2.2, posY+2.2, posZ-2.5, 0, 0.1, 0.1, 2.5);
new wallwood(posX–2.2, posY+2.2, posZ–2.5, 0, 0.1, 0.1, 2.5);
new wallwood(posX+2.2, posY-2.2, posZ-2.5, 0, 0.1, 0.1, 2.5);
new wallwood(posX-2.2, posY-2.2, posZ-2.5, 0, 0.1, 0.1, 2.5);
}
}
Fichier chaise.vrel :
import "tabouret.vrel"
class Chaise compound
{
constructor (posX, posY, posZ)
{
new Tabouret (posX, posY, posZ) ;
new Wallwood (posX+2.4, posY, posZ+2.5, 0, 0.1, 2.5, 2.5) ;
}
}
Fichier table.vrel
import "walluni.vrel"
class Table compound
{
constructor (posX, posY, posZ)
{
new WallUni(posX, posY, posZ-2.5, 0, 7.5, 5, 0.2, wood);
new WallUni(posX+6.6, posY+4.4, posZ-5, 0, 0.15, 0.15, 2.5, wood);
new WallUni(posX–6.6, posY+4.4, posZ-5, 0, 0.15, 0.15, 2.5, wood);
new WallUni(posX+6.6, posY-4.4, posZ-5, 0, 0.15, 0.15, 2.5, wood);
new WallUni(posX–6.6, posY-4.4, posZ-5, 0, 0.15, 0.15, 2.5, wood);
}
constructor(posX, posY, posZ, texture)
{
w1 = new WallUni(posX, posY, posZ, 0, 0.25, 0.25, 0.02, wood) ;
w2 = new WallUni(posX+2.2, posY+2.2, posZ–2.5, 0, 0.1, 0.1, 2.5);
w3 = new WallUni(posX-2.2, posY+2.2, posZ-2.5, 0, 0.1, 0.1, 2.5);
w4 = new WallUni(posX+2.2, posY-2.2, posZ–2.5, 0, 0.1, 0.1, 2.5);
w5 = new WallUni(posX-2.2, posY-2.2, posZ-2.5, 0, 0.1, 0.1, 2.5);
w1.tex = texture ;
w2.tex = texture ;
w3.tex = texture ;
w4.tex = texture ;
w5.tex = texture ;
}
}
Fichier main :
import "chaise.vrel"
import "table.vrel"
var N = 5 ;
begin
{
var i ;
i = 0 ;
while (i < N)
{
new Chaise (5 * i, 15, 0.5) ;
new Table (4 * i, 15, 1);
i = i+1 ;
}
}
end