Babylon.js 实现鼠标拾取操作

Babylon.js 实现鼠标拾取操作

  • 通过scene.pick(scene.pointerX, scene.pointerY);API实现物体选中,并返回结果对象
  • hit(bool):如果点击击中了场景中的一个对象,则为true。
  • distance(float):当前活动相机与命中点之间的距离(如果未命中任何物体,则为infinite无限)。
  • pickMesh(BABYLON.Mesh):如果击中一个物体,则这就是这个物体的实例对象。 如果不是,则为空。
  • pickPoint(BABYLON.Vector3):单击的点,已经转换为3D坐标,具体取决于单击的对象。
  • 可通过 mesh.isPickable属性选中开启或关闭pick选项
效果

在这里插入图片描述

代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Babulon</title>
    <style>
      html,
      body {
        overflow: hidden;
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
      }

      #renderCanvas {
        width: 100%;
        height: 100%;
        touch-action: none;
      }
    </style>
  </head>
  <body>
    <script src="https://preview.babylonjs.com/babylon.js"></script>
    <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
    <script src="https://code.jquery.com/pep/0.4.3/pep.js"></script>
    <canvas id="renderCanvas" touch-action="none"></canvas>
    <script>
      const canvas = document.getElementById("renderCanvas");
      const engine = new BABYLON.Engine(canvas, true);

      const initRender = (scene, animation) => {
        engine.runRenderLoop(function () {
          scene.render();
          animation();
        });
        window.addEventListener("resize", function () {
          engine.resize();
        });
      };

      const initScene = () => {
        // 场景
        const scene = new BABYLON.Scene(engine);
        scene.ambientColor = new BABYLON.Color3(1, 1, 1);
        // 相机
        const camera = new BABYLON.ArcRotateCamera(
          "Camera",
          Math.PI / 2,
          Math.PI / 2,
          100,
          new BABYLON.Vector3(0, 0, 0),
          scene
        );
        camera.attachControl(canvas, true);
        // 灯光
        const light1 = new BABYLON.HemisphericLight(
          "light1",
          new BABYLON.Vector3(0, 1000, 0),
          scene
        );
        const light2 = new BABYLON.HemisphericLight(
          "light2",
          new BABYLON.Vector3(0, -1000, 0),
          scene
        );
        return {
          scene,
          camera,
          light1,
          light2,
        };
      };

      const createScene = (scene) => {
        const bigBox = BABYLON.MeshBuilder.CreateBox(
          "bigBox",
          { height: 50, width: 50, depth: 50 },
          scene
        );
        const bigBoxMaterial = new BABYLON.StandardMaterial(
          "bigBoxMaterial",
          scene
        );
        bigBoxMaterial.wireframe = true;
        bigBox.material = bigBoxMaterial;
        // 禁止选中
        bigBox.isPickable = false;

        for (let i = 0; i < 100; i++) {
          const r = Math.random() * 8;
          const range = 50 - r;
          const box = BABYLON.MeshBuilder.CreateBox(
            "box",
            { height: r, width: r, depth: r },
            scene
          );
          const boxMaterial = new BABYLON.StandardMaterial(
            "bigBoxMaterial",
            scene
          );
          boxMaterial.diffuseColor = new BABYLON.Color3(
            Math.random(),
            Math.random(),
            Math.random()
          );
          box.material = boxMaterial;

          box.position = new BABYLON.Vector3(
            Math.random() * range - range / 2,
            Math.random() * range - range / 2,
            Math.random() * range - range / 2
          );
        }
        let activeModel = null;
        let activeColor = null;
        // window.addEventListener("click", function () {
        //   // We try to pick an object
        //   const pickResult = scene.pick(scene.pointerX, scene.pointerY);
        //   if (pickResult.hit) {
        //     const model = pickResult.pickedMesh;
        //     model.material.diffuseColor = new BABYLON.Color3(1, 0, 0);
        //   }
        // });
        window.addEventListener("mousemove", function () {
          // We try to pick an object
          const pickResult = scene.pick(scene.pointerX, scene.pointerY);
          if (pickResult.hit) {
            // 选中模型
            if (!activeModel) {
              // 选中模型不存在
              activeModel = pickResult.pickedMesh;
              activeColor = new BABYLON.Color3(
                ...Object.values(pickResult.pickedMesh.material.diffuseColor)
              );
            }
            if (activeModel && activeModel != pickResult.pickedMesh) {
              // 选中新模式
              activeModel.material.diffuseColor = activeColor;
              activeModel = pickResult.pickedMesh;
              activeColor = new BABYLON.Color3(
                ...Object.values(pickResult.pickedMesh.material.diffuseColor)
              );
            }
            activeModel.material.diffuseColor = new BABYLON.Color3(1, 0, 0);
          } else if (activeModel) {
            // 未选中模型
            activeModel.material.diffuseColor = activeColor;
            activeModel = null;
            activeColor = null;
          }
        });
        const animation = () => {};
        return {
          animation,
        };
      };

      (() => {
        const { scene } = initScene();
        const { animation } = createScene(scene);
        initRender(scene, animation);
      })();
    </script>
  </body>
</html>


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
你可以通过在场景中添加一个事件侦听器,然后在事件处理程序中使用raycasting技术来获取鼠标点击位置和角度。具体来说,可以使用以下代码: ``` var canvas = document.getElementById('renderCanvas'); // 获取Canvas对象 var engine = new BABYLON.Engine(canvas, true); // 创建Babylon.js引擎 var scene = createScene(); // 创建场景 // 添加鼠标点击事件 canvas.addEventListener("pointerdown", function (event) { // 计算出鼠标点击位置 var pickResult = scene.pick(scene.pointerX, scene.pointerY); // 判断是否点中物体 if (pickResult.hit) { var selectedObject = pickResult.pickedMesh; // 获取选中的物体 // 计算出鼠标点击位置和相机的角度 var cameraPosition = scene.activeCamera.position; var cameraRotation = scene.activeCamera.rotation; var pickPosition = pickResult.pickedPoint; var pickAngle = BABYLON.Vector3.Normalize(pickPosition.subtract(cameraPosition)); console.log('选中的物体: ' + selectedObject.name); console.log('鼠标点击位置: ' + pickPosition); console.log('相机角度: ' + cameraRotation); console.log('选中物体的角度: ' + pickAngle); } }); // 渲染场景 engine.runRenderLoop(function () { scene.render(); }); // 创建场景的函数 function createScene() { var scene = new BABYLON.Scene(engine); // 添加相机 var camera = new BABYLON.FreeCamera("Camera", new BABYLON.Vector3(0, 5, -10), scene); camera.setTarget(BABYLON.Vector3.Zero()); camera.attachControl(canvas, true); // 添加灯光 var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene); light.intensity = 0.7; // 添加网格 var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {diameter: 2}, scene); return scene; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值