Для того, чтобы получить координаты мыши в пространстве, необходимо посмотреть пересечение луча с контейнером или объектом, на котором мы хотим отлавливать событие мыши. Хочу сразу сказать, что тут вообще ничего сложного нету, но из-за того, что я не сразу понял, что нужно отключить mouseChildren у контейнера, из-за чего у меня получалась каша с координатами. Спасибо большое Дмитрию [focus] Юханову, с которым мы созвонились по скайпу и начали искать в чем проблема. Дим, спасибо за помощь! Так же, не забывайте, что в скачанном архиве альтернативы лежит не только документация, но и примеры использования движка.
Вначале посмотрим сам метод intersectRay, который доступен любому Object3D

Стандартный пример:

package intersectrayexample 
{
 import alternativa.engine3d.containers.ConflictContainer;
   import alternativa.engine3d.controllers.SimpleObjectController;
 import alternativa.engine3d.core.Camera3D;
  import alternativa.engine3d.core.MipMapping;
    import alternativa.engine3d.core.MouseEvent3D;
  import alternativa.engine3d.core.Object3D;
  import alternativa.engine3d.core.Object3DContainer;
 import alternativa.engine3d.core.RayIntersectionData;
   import alternativa.engine3d.core.Sorting;
   import alternativa.engine3d.core.View;
  import alternativa.engine3d.materials.FillMaterial;
 import alternativa.engine3d.materials.TextureMaterial;
  import alternativa.engine3d.primitives.Box;
 import alternativa.engine3d.primitives.Plane;
 
    import flash.display.BitmapData;
    import flash.display.Shape;
 import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
  import flash.geom.Point;
    import flash.geom.Vector3D;
 
    /**
  * Пример работы с поиском пересечения луча с геометрией в Alternativa3D.
     */
 public class IntersectRayExample extends Sprite
 {
       //ембедим наш файл текстуры в EmbedTexture
       [Embed(source="texture.jpg")] static private const EmbedTexture:Class;
 
        private var rootContainer:Object3DContainer = new Object3DContainer();
 
        private var camera:Camera3D;
        private var controller:SimpleObjectController;
 
        public function IntersectRayExample() 
      {
           stage.align = StageAlign.TOP_LEFT;
          stage.scaleMode = StageScaleMode.NO_SCALE;
 
            // Создание камеры и вьюпорта
            camera = new Camera3D();
            camera.view = new View(stage.stageWidth, stage.stageHeight);
            addChild(camera.view);
          addChild(camera.diagram);
 
            // Установка начального положения камеры
          camera.rotationX = -110*Math.PI/180;
            camera.y = -1200;
           camera.z = 300;
         controller = new SimpleObjectController(stage, camera, 200);
            rootContainer.addChild(camera);
 
            // Создание объектов
            var plane:Plane = new Plane(1200, 1200);
            plane.setMaterialToAllFaces(new TextureMaterial(new BitmapData(800, 800, false, 0xAFC47D)));
            plane.z = -100;
         plane.rotationZ = -30*Math.PI/180;
          rootContainer.addChild(plane);
 
 
            var box:Box = new Box(100, 100, 100);
           box.sorting = Sorting.DYNAMIC_BSP;
          box.setMaterialToAllFaces(new TextureMaterial(new EmbedTexture().bitmapData, false, true, MipMapping.OBJECT_DISTANCE));
 
            var container:ConflictContainer = new ConflictContainer();
          container.rotationZ = -30*Math.PI/180;
          for (var i:int = 0; i < 5; i++) 
            {
               for (var j:int = 0; j < 5; j++) 
                {
                   var object:Object3D = box.clone();
                  object.x = i*180 - 360;
                 object.y = j*180 - 360;
                 container.addChild(object);
             }
           }
 
            rootContainer.addChild(container);
 
            // Мышиные события в 3D
          camera.view.interactive = true;
         //ОТКЛЮЧАЕМ ОТ МЫШИ ДЕТЕЙ
           container.mouseChildren = false;
            container.addEventListener(MouseEvent3D.MOUSE_DOWN, addBox);
            plane.addEventListener(MouseEvent3D.MOUSE_DOWN, drawSpot);
 
            // Подписка на события
         stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
            stage.addEventListener(Event.RESIZE, onResize);
     }
 
        private function addBox(e:MouseEvent3D):void 
       {
           var container:Object3DContainer = e.target as Object3DContainer;
            //получаем результат пересечения луча 
          //с объектом на который добавили слушатель события
            var data:RayIntersectionData = container.intersectRay(e.localOrigin, e.localDirection);
         //если есть рузультат
          if (data != null) 
          {
               //и вот он наш Vector3D
                var point:Vector3D = data.object.matrix.transformVector(data.point);
                var box:Box = new Box(15, 15, 15);
              box.setMaterialToAllFaces(new FillMaterial(0xFF0000));
              box.x = point.x;
                box.y = point.y;
                box.z = point.z;
                container.addChild(box);
            }
       }
 
        private function drawSpot(e:MouseEvent3D):void 
     {
 
            var object:Object3D = e.target as Object3D;
         //получаем результат пересечения луча 
          //с объектом на который добавили слушатель события
            var data:RayIntersectionData = object.intersectRay(e.localOrigin, e.localDirection);
            //если есть рузультат
          if (data != null) 
          {
               var texture:BitmapData = (data.face.material as TextureMaterial).texture;
               var uv:Point = data.face.getUV(data.point);
             var spot:Shape = new Shape();
               spot.graphics.beginFill(0x0000FF, 0.5);
             spot.graphics.drawCircle(uv.x*texture.width, uv.y*texture.height, 20);
              texture.draw(spot);
         }
       }
 
        private function onEnterFrame(e:Event):void 
        {
           controller.update();
            camera.render();
        }
       private function onResize(e:Event = null):void 
     {
           // Установка ширины и высоты вьюпорта
         camera.view.width = stage.stageWidth;
           camera.view.height = stage.stageHeight;
     }
   }
}

5 Responses to “Alternativa3D определение координат мыши в пространстве”

  1. focus says:

    Всегда пожалуйста, Серёг, было здорово =)
    Альтернатива за статьи и уроки теперь платит по 100 баксов, кстати )

  2. Мы всё читаем, если что :)
    Молодец, Сергей! Так держать.
    Кстати, сегодня Вова продемонстрировал нормальные человеческие маус-евенты в 7.6, так что скоро будет проще.

  3. Спасибо большое, я стараюсь!
    С нетерпением жду 7.6)

  4. На форуме помощи просят, посмотришь?
    http://forum.alternativaplatform.com/posts/list/3207.page

  5. Да, конечно

Leave a Reply