Création de hotspots dans un panorama

Cet article a été mis à jour le 14 mars 2009 afin d'être compatible avec la dernière version en date de Papervision

Les hotspots représentent des zones d'interactivité dans un panorama. Ils peuvent avoir pour but le déplacement de pièces en pièces, l'affichage d'informations, le lancement d'une vidéo, etc...

Pour démarrer en douceur , nous allons commencer par ajouter des hotspots sur une des visionneuses du post précédent.
Ceux-ci afficheront un simple texte lorsque l'on clique dessus.

I> Création des hotspots

Pour réaliser nos hotspots, nous allons ajouter un simple plan transparent devant chaque élément qui nous intéresse dans le panorama.
Cet exemple se base sur la visionneuse qui projete les 6 images (512*512) d'une pièce sur un cube (cf exemple ici).
Les images se trouvent ici, et le code source .

Commençons par décider quels seront nos objets interactifs. Par exemple, j'ai choisi le radiateur qui est sur l'image de la
face droite :

et l'armoire de la face gauche:

Les dimensions de ces zones sont respectivement de 221*124 et 332*329. Elles nous serviront un peu plus tard.

Pour ajouter nos plans qui serviront de zone sensible, rien de plus facile. Cette méthode a d'ailleurs été vue dans un précédent billet : On crée un plan grâce à l'objet 'Plane' en lui spécifiant une texture, une taille, ainsi que son nombre de faces. On l'ajoute ensuite à la scène.

Comme texture, on peut utiliser une simple texture couleur, puisque le plan sera transparent par la suite.

Pour calculer la taille du plan, il suffit de faire une règle de trois. Les images de 512*512 sont appliquées sur des plans
de 1000*1000 donc notre zone interactive qui fait 221*124 sur l'image sera représenté par un plan de 431*242 pour le radiateur et de 648*642 pour l'armoire. Pour les coordonnées x,y ont fait pareil.

Etant donnée que cette solution est assez lourde , un des prochains billets expliquera comment mettre en place un éditeur de hotspots.

Il ne reste plus qu'à ajouter les plans sur la scène. Vous devriez obtenir quelque chose comme ceci pour le moment.

On peut remarquer par certains moments, selon l'orientation de la caméra, certains artefacts sur ces nouveaux plans. Cela est du à
l'algorithme de tri des faces de Papervision. Lorsque 2 objets sont très
rapprochés , il peut arriver que certaines faces passent derrière d'autres alors qu'il ne le faudrait pas.(Plus d'infos
sur cette démo)
Alors que dans les versions précédentes de Papervision, il fallait passer par quelques hacks pour résoudrent ces problèmes, on peut maintenant utiliser des ViewportLayer pour indiquer au moteur de quelle manière trier les éléments de la scène.

II> Ajout des événements souris

L'activation des évenements souris nécessitent 3 étapes :

  • Mettre la propriété interactive du viewport à true.
  • Mettre la propriété interactive du materiel des objets interactifs à true.
  • Ajouter un écouteur sur un évenement de type InteractiveScene3DEvent aux objets.
Actionscript:
  1. ...
  2. public function VisionneuseCubeHotspots()
  3. {
  4.     super( 800, 512, true, true, CameraType.FREE );
  5.            ...
  6.            var colorMaterial:ColorMaterial = new ColorMaterial();
  7.            colorMaterial.interactive = true;
  8.            var plane:Plane = new Plane( colorMaterial, 431, 242, 1, 1 );
  9.            ...
  10.            plane.addEventListener( InteractiveScene3DEvent.OBJECT_PRESS, onMouseDown);
  11.            plane.addEventListener( InteractiveScene3DEvent.OBJECT_RELEASE, onMouseUp);

Il ne reste plus qu'à définir les finctions onMouseDown et onMouseUp et de rendre nos plans transparent

La version finale avec le code source. A venir, l'éditeur de hotspots.

Actionscript:
  1. package {
  2.     import flash.events.Event;
  3.     import flash.text.TextField;
  4.     import flash.text.TextFieldAutoSize;
  5.     import flash.text.TextFormat;
  6.    
  7.     import org.papervision3d.cameras.CameraType;
  8.     import org.papervision3d.events.InteractiveScene3DEvent;
  9.     import org.papervision3d.materials.BitmapFileMaterial;
  10.     import org.papervision3d.materials.BitmapMaterial;
  11.     import org.papervision3d.materials.ColorMaterial;
  12.     import org.papervision3d.materials.utils.MaterialsList;
  13.     import org.papervision3d.objects.primitives.Cube;
  14.     import org.papervision3d.objects.primitives.Plane;
  15.     import org.papervision3d.view.BasicView;
  16.     import org.papervision3d.view.layer.ViewportLayer;
  17.  
  18.     [SWF( width='800', height='512', backgroundColor='0x000000', frameRate='30' )]
  19.     public class VisionneuseCubeHotspots extends BasicView
  20.     {
  21.         private static const IMG_BASE_URL:String = "assets/rendu_cubique_";
  22.         private static var MAX_X_ROTATION:int = 50;
  23.        
  24.         private var cube:Cube;
  25.         private var label:TextField;
  26.        
  27.         public function VisionneuseCubeHotspots()
  28.         {
  29.             super( 800, 512, true, true, CameraType.FREE );
  30.  
  31.             createTextfield();
  32.             createCube();         
  33.             createHotspots();
  34.  
  35.             camera.z = 0;
  36.             startRendering();
  37.         }
  38.        
  39.         private function createCube():void
  40.         {
  41.             var frontMat:BitmapMaterial = new BitmapFileMaterial( IMG_BASE_URL+"FR.jpg" );
  42.             var backMat:BitmapFileMaterial =  new BitmapFileMaterial( IMG_BASE_URL+"BK.jpg" );
  43.             var leftMat:BitmapFileMaterial = new BitmapFileMaterial( IMG_BASE_URL+"LF.jpg" );
  44.             var rightMat:BitmapFileMaterial = new BitmapFileMaterial( IMG_BASE_URL+"RT.jpg" );
  45.             var upMat:BitmapFileMaterial = new BitmapFileMaterial( IMG_BASE_URL+"UP.jpg" );
  46.             var downMat:BitmapFileMaterial = new BitmapFileMaterial( IMG_BASE_URL+"DN.jpg" );
  47.            
  48.             frontMat.doubleSided = true;
  49.             backMat.doubleSided = true;
  50.             leftMat.doubleSided = true;
  51.             rightMat.doubleSided = true;
  52.             upMat.doubleSided = true;
  53.             downMat.doubleSided = true;
  54.            
  55.            
  56.             var imgMaterialList:MaterialsList = new MaterialsList(
  57.             {
  58.                front: frontMat,
  59.                back: backMat,
  60.                left: leftMat,
  61.                right: rightMat,
  62.                top: upMat,
  63.                bottom: downMat
  64.          });
  65.          
  66.             cube = new Cube( imgMaterialList, 1000, 1000, 1000, 16, 16, 16 );
  67.             scene.addChild( cube );
  68.         }
  69.        
  70.         private function createHotspots():void
  71.         {
  72.             var colorMaterial:ColorMaterial = new ColorMaterial();
  73.             colorMaterial.doubleSided = true;
  74.             colorMaterial.interactive = true;
  75.            
  76.             //radiateur
  77.             var plane:Plane = new Plane( colorMaterial, 431, 242, 1, 1 );
  78.             plane.name = "radiateur";
  79.             plane.y = -70;
  80.             plane.z = -200;
  81.             plane.x = 500;
  82.             plane.rotationY = -90;
  83.             plane.addEventListener( InteractiveScene3DEvent.OBJECT_PRESS, onMouseDown);
  84.             plane.addEventListener( InteractiveScene3DEvent.OBJECT_RELEASE, onMouseUp);
  85.             scene.addChild( plane );
  86.            
  87.             //armoire
  88.             var plane2:Plane = new Plane( colorMaterial, 648, 642, 1, 1 );
  89.             plane2.name = "armoire";
  90.             plane2.y = 10;
  91.             plane2.z = -120;
  92.             plane2.x = -500;
  93.             plane2.rotationY = -90;
  94.             plane2.addEventListener( InteractiveScene3DEvent.OBJECT_PRESS, onMouseDown);
  95.             plane2.addEventListener( InteractiveScene3DEvent.OBJECT_RELEASE, onMouseUp);
  96.             scene.addChild( plane2 );
  97.            
  98.             //force l'affichage des hotspots
  99.             var vp:ViewportLayer = viewport.getChildLayer(plane, true);
  100.             vp.addDisplayObject3D( plane2 );
  101.             vp.layerIndex = 1;
  102.             vp.alpha = 0;
  103.            
  104.         }
  105.        
  106.         private function createTextfield():void
  107.         {
  108.             label = new TextField();
  109.             label.autoSize = TextFieldAutoSize.LEFT;
  110.             label.background = true;
  111.             label.border = true;
  112.  
  113.             var format:TextFormat = new TextFormat();
  114.             format.font = "Verdana";
  115.             format.color = 0xFF0000;
  116.             format.size = 16;
  117.             format.underline = true;
  118.  
  119.             label.defaultTextFormat = format;
  120.         }
  121.        
  122.         private function onMouseDown( e:InteractiveScene3DEvent ):void
  123.         {
  124.             label.text = "clic sur "+ e.displayObject3D.name
  125.             addChild(label);
  126.         }
  127.    
  128.         private function onMouseUp(event:Event):void
  129.         {
  130.             removeChild(label);
  131.         }
  132.  
  133.        
  134.         override protected function onRenderTick(event:Event=null):void
  135.         {
  136.             camera.rotationY += ( mouseX - ( stage.width/2 ) ) / MAX_X_ROTATION;
  137.             camera.rotationX += ( mouseY - ( stage.height/2 ) ) / MAX_X_ROTATION;
  138.            
  139.             //on limite la rotation verticale
  140.             if( camera.rotationX> MAX_X_ROTATION )
  141.             {
  142.                 camera.rotationX = MAX_X_ROTATION;
  143.             }
  144.             if( camera.rotationX <- MAX_X_ROTATION )
  145.             {
  146.                 camera.rotationX = - MAX_X_ROTATION;
  147.             }
  148.             super.onRenderTick( event );
  149.         }
  150.     }
  151. }


Tags: , ,


Fatal error: Call to undefined function: st_related_posts() in /homez.144/astrois/www/blog/wp-content/themes/simplicitybright/single.php on line 14