Sensibilisation à l'Informatique - INSA 2ème année - TP VRML - Embryon de solution...

Modélisation d'un dé à jouer
  1. il faut ici modéliser un dé à l'aide d'un IndexedFaceSet (afin de pouvoir le déformer à volonté par la suite)
  2. pour représenter les valeurs sur les faces du dé, soit on modélisera ensuite des sphères noires, soit on plaquera une texture adaptée sur les faces du dé
  3. on placera des points de vue de façon à se trouver face à chaque face du dé
  4. on utilisera deux objets pour déclencher et stopper une animation de rotation du dé (lors d'une reprise on reprendra l'animation à zéro)
  5. on utilisera un objet (avec mémorisation de son état et changement de sa couleur) pour déclencher et reprendre une animation de déformation du dé (lors d'une reprise on reprendra l'animation du moment où l'on s'était arrêté)
  6. on créera un observateur du dé qui s'orientera toujours vers le dé (pour des déplacements plans du dé et de l'observateur)

Fichier de départ, à compléter...
#--------------------------------------------------------------------------

WorldInfo {
title "Dé"
info [ "Copyright (c) septembre 2008, Sensibilisation Informatique INSA" ]
}

#--------------------------------------------------------------------------

NavigationInfo {
type [ "EXAMINE", "ANY" ]
headlight TRUE
}

Modélisation du dé à l'aide d'un IndexedFaceSet
      Shape {
geometry IndexedFaceSet {
coord DEF Coordonnees Coordinate {
point [
-1.0 -1.0 -1.0, # 0 gauche bas arrière
-1.0 -1.0 1.0, # 1 gauche bas avant
-1.0 1.0 -1.0, # 2 gauche haut arrière
-1.0 1.0 1.0, # 3 gauche haut avant
1.0 -1.0 -1.0, # 4 droit bas arrière
1.0 -1.0 1.0, # 5 droit bas avant
1.0 1.0 -1.0, # 6 droit haut arrière
1.0 1.0 1.0, # 7 droit haut avant
]
}
coordIndex [
1, 5, 7, 3, -1, # face avant
4, 6, 7, 5, -1, # face droite
2, 3, 7, 6, -1, # face dessus
0, 2, 6, 4, -1, # face arrière
0, 1, 3, 2, -1, # face gauche
0, 4, 5, 1, -1, # face dessous
  ]
solid TRUE
}
}

Placage de texture sur le dé
         appearance Appearance {
texture ImageTexture { url "textureDe.jpg" }
}
            texCoord TextureCoordinate {
point [
0.000 1.0, # 0
0.000 0.5, # 1
0.000 0.0, # 2
0.33 1.0, # 3
0.33 0.5, # 4
0.33 0.0, # 5
0.667 1.0, # 6
0.667 0.5, # 7
0.667 0.0, # 8
1.000 1.0, # 9
1.000 0.5, # 10
1.000 0.0, # 11
]
}
texCoordIndex [ # seule la première face est correcte
0, 1, 4, 3, -1,
0, 1, 4, 3, -1,
0, 1, 4, 3, -1,
0, 1, 4, 3, -1,
0, 1, 4, 3, -1,
0, 1, 4, 3, -1,
]


Ajout de points de vues dans l'environnement
Viewpoint {
position 0.0 0.0 10.0
orientation 0.0 1.0 0.0 0.0
description "Vue de Face"
}


Ajout d'un Transform nommé pour pouvoir animer le dé
DEF De Transform {
children [
Shape {
geometry IndexedFaceSet {
coord DEF Coordonnees Coordinate {
point [
-1.0 -1.0 -1.0, # 0 gauche bas arrière
-1.0 -1.0 1.0, # 1 gauche bas avant
-1.0 1.0 -1.0, # 2 gauche haut arrière
-1.0 1.0 1.0, # 3 gauche haut avant
1.0 -1.0 -1.0, # 4 droit bas arrière
1.0 -1.0 1.0, # 5 droit bas avant
1.0 1.0 -1.0, # 6 droit haut arrière
1.0 1.0 1.0, # 7 droit haut avant
]
}
coordIndex [
1, 5, 7, 3, -1, # face avant
4, 6, 7, 5, -1, # face droite
2, 3, 7, 6, -1, # face dessus
0, 2, 6, 4, -1, # face arrière
0, 1, 3, 2, -1, # face gauche
0, 4, 5, 1, -1, # face dessous
  ]
solid TRUE
}
}
]
}


Animation (rotation) du dé
# une interpolation pour la rotation :
# au moins 3 clés sinon pas de rotation du tout,
# car orientation initiale = orientation finale (modulo 2 * pi)
# l'axe de rotation : 1 1 1 ("grande diagonale" du dé)
# les 3 valeurs d'angle : 0, pi, 2 * pi

DEF Tourneur OrientationInterpolator {
key [ 0.0, 0.5, 1.0 ]
keyValue [ 1.0 1.0 1.0 0.0, 1.0 1.0 1.0 3.14, 1.0 1.0 1.0 6.28 ]
}

# un démarreur pour déclencher l'animation, il faudra cliquer sur une sphère verte

Transform {
# positionnement absolu du démarreur
translation -1 -1 2
children [
# le TouchSensor à l'écoute des clics sur la géométrie associée
DEF Declencheur TouchSensor {}
# la forme géométrique associée
Shape {
# elle sera de couleur verte
appearance Appearance {
material Material {
diffuseColor 0.0 1.0 0.0
}
}
# ce sera une petite sphère
geometry Sphere {
radius 0.05
}
}
]
}

# un stoppeur pour arrêter l'animation : toujours par un clic...

Transform {
...
}

# l'horloge d'animation de la rotation :
# temps de cycle : 4 secondes, ne boucle pas,
# à l'arrêt initialement car doit être déclenchée sur un clic
# donc son stopTime doit être plus grand que son startTime (et loin dans le passé)


DEF HorlogePourLaRotation TimeSensor {
cycleInterval 4.0
loop FALSE
startTime 0.0
stopTime 1.0
}

# les routages pour la rotation :

# 1 - un clic déclenchera l'horloge
ROUTE Declencheur.touchTime TO HorlogePourLaRotation.set_startTime
# 2 - un autre clic l'arrêtera
#ROUTE ...
# 3 - l'horloge fera évoluer l'interpolateur
ROUTE HorlogePourLaRotation.fraction_changed TO Tourneur.set_fraction
# 4 - l'interpolateur fera évoluer le Transform du dé
ROUTE Tourneur.value_changed TO De.set_rotation


Animation de déformation du dé
# une interpolation pour la déformation :
# déformation puis retour à l'état initial
# donc 3 états : initial, déformé, final = initial

DEF Deformation CoordinateInterpolator {
key [ 0.0, 0.5, 1.0 ]
keyValue [
# état initial
-1.0 -1.0 -1.0, # 0 gauche bas arrière
-1.0 -1.0 1.0, # 1 gauche bas avant
-1.0 1.0 -1.0, # 2 gauche haut arrière
-1.0 1.0 1.0, # 3 gauche haut avant
1.0 -1.0 -1.0, # 4 droit bas arrière
1.0 -1.0 1.0, # 5 droit bas avant
1.0 1.0 -1.0, # 6 droit haut arrière
1.0 1.0 1.0, # 7 droit haut avant
# état déformé
0.0 0.0 0.0, # 0 gauche bas arrière
0.0 0.0 0.0, # 1 gauche bas avant
0.0 0.0 0.0, # 2 gauche haut arrière
0.0 0.0 0.0, # 3 gauche haut avant
0.0 0.0 0.0, # 4 droit bas arrière
0.0 0.0 0.0, # 5 droit bas avant
0.0 0.0 0.0, # 6 droit haut arrière
0.0 0.0 0.0, # 7 droit haut avant
# état final = état initial
-1.0 -1.0 -1.0, # 0 gauche bas arrière
-1.0 -1.0 1.0, # 1 gauche bas avant
-1.0 1.0 -1.0, # 2 gauche haut arrière
-1.0 1.0 1.0, # 3 gauche haut avant
1.0 -1.0 -1.0, # 4 droit bas arrière
1.0 -1.0 1.0, # 5 droit bas avant
1.0 1.0 -1.0, # 6 droit haut arrière
1.0 1.0 1.0, # 7 droit haut avant
]
}

# l'horloge d'animation de la déformation :
# doit être cyclique, c'est tout...
# son stopTime plus grand que son startTime (et loin dans le passé)
# font que l'horloge est arrêtée au chargement de ces noeuds

DEF HorlogeDeformation TimeSensor {
cycleInterval 2.0
loop TRUE
startTime 0.0
stopTime 1.0
}

# un objet 3D "toggle" qui permet de lancer ou d'arrêter
# l'animation de déformation selon l'état de cette animation :
# quand il sera possible de lancer la déformation, l'objet de vra être vert et un
# clic sur cet objet devra déclencher la déformation,
# quand l'animation sera en cours, l'objet devra être rouge et
# clic sur cet objet devra interrompre l'animation

Transform {
translation 1.5 -1.0 -1.4
children [
DEF AlternateDeformation TouchSensor {}
Shape {
appearance Appearance {
# nommage du material pour pouvoir en changer la couleur
# initialement l'objet sera vert (et l'animation sera à l'arrêt)
material DEF couleurToggle Material {
diffuseColor 0.0 1.0 0.0
}
}
geometry Cylinder {
radius 0.05
height 0.1
}
}
]
}

# un script pour mémoriser l'état du "Toggle" et pour réagir correctement aux clics

DEF ToggleDeformation Script {
# attributs du Script
field SFBool actif FALSE # l'état du toggle
field SFColor vert 0.0 1.0 0.0 # définition du vert
field SFColor rouge 1.0 0.0 0.0 # définition du rouge
field SFTime deltaTime 0.0 # le temps d'animation écoulé
# fonctions d'entrées du script
eventIn SFTime set_time # réaction aux clics
# variables à produire
eventOut SFTime startTime_changed
eventOut SFTime stopTime_changed
eventOut SFColor color_changed
# code javascript
url "javascript:
function set_time (t, ts) {
...
}
"

}

# les routages pour la déformation

ROUTE AlternateDeformation.touchTime TO ToggleDeformation.set_time
ROUTE ToggleDeformation.startTime_changed TO HorlogeDeformation.set_startTime
ROUTE ToggleDeformation.stopTime_changed TO HorlogeDeformation.set_stopTime
#ROUTE HorlogeDeformation.XXX TO Deformation.XXX
#ROUTE Deformation.XXX TO Coordonnees.set_point
#ROUTE ToggleDeformation.XXX TO couleurToggle.set_XXX

Interaction pour déplacer le dé
# pour déplacer le Dé, non demandé,
# mais permet de tester le changement d'orientation de l'observateur

DEF De Transform {
children [
DEF Mover PlaneSensor {} # permettra de déplacer le dé dans un plan
Shape {
...
}
]
}

ROUTE Mover.translation_changed TO De.set_translation

Objet observateur du dé
# noeud destiné à se tourner toujours vers le dé ...

DEF Observateur Transform {
children [
Viewpoint {
position 0.0 0.0 0.0
orientation 1.0 0.0 0.0 1.57
description "Vue permanente sur le cube"
}
# un PlaneSensor pour pouvoir bouger l'objet dans le plan
DEF MoverObs PlaneSensor {}
Transform {
# l'observateur est tourné de pi autour de l'axe des Z (tête en bas, pied en haut)
rotation 0.0 0.0 1.0 3.14
children [
Shape {
# l'observateur est de couleur jaune
appearance Appearance {
material Material {
 diffuseColor 1.0 1.0 0.0
 }
}
# c'est un cone, mais à cause le la rotation du Transform, il aura la pointe vers le bas !
geometry Cone {
height 1
bottomRadius 0.5
}
}
]
}
]
}

# routage permettant de déplacer l'observateur

ROUTE MoverObs.translation_changed TO Observateur.set_translation

# noeud calculant une valeur d'orientation permettant de s'orienter vers une cible

DEF Orienteur Script {
# attributs du script
field SFVec3f positionCible 0.0 0.0 0.0
field SFVec3f positionObservateur 0.0 0.0 0.0
# fonctions d'entrées du script
eventIn SFVec3f set_positionCible
eventIn SFVec3f set_positionObservateur
# valeur à produire
eventOut SFRotation orientationObservateur_changed
url "javascript:
function initialize () {
orientationObservateur_changed [0] = 0.0 ;
orientationObservateur_changed [1] = 0.0 ;
orientationObservateur_changed [2] = 1.0 ;
orientationObservateur_changed [3] = 0.0 ;
}
function set_positionCible (pos, t) {
// c'est cette fonction qui est supposee exister ...
// dans le cas general, il faut des calculs 3D,
// mais ici on suppose que la cible et l'observateur resteront
// toujours dans le meme plan, ce qui simplifie grandement les calculs
positionCible = pos ;
miseAJourOrientation () ;
}
function set_positionObservateur (pos, t) {
// non demande, mais intéressant ici ...
positionObservateur = pos ;
miseAJourOrientation () ;
}
function miseAJourOrientation () {
// on suppose donc ici que c'est un pb 2D ...
// dx = ... ;
// dy = ... ;
orientationObservateur_changed [3] = - (Math.atan2 (dx, dy)) ;
}
"
}

# routage qui permet de réagir aux changements de position de la cible
ROUTE De.translation_changed TO Orienteur.set_positionCible
# routage supplémentaire pour tenir compte d'un déplacement de l'observateur
#ROUTE ...
# routage du résultat de calcul d'orientation vers l'orientation de l'observateur
#ROUTE ...