美文网首页
threejs 360房间的学习

threejs 360房间的学习

作者: squidbrother | 来源:发表于2023-03-29 11:21 被阅读0次

    操作流程学习

    准备的基本知识

    1. 360房间的制作
    • 准备正方体,添加六个面贴图实现
      具体操作:
      六面图可以通过天空盒子工具实现 - https://matheowis.github.io/HDRI-to-CubeMap/

    立方体屋子的具体操作:

    const textures = cubeTextureLoader.load([
      '/textures/px.jpg',
      '/textures/nx.jpg',
      '/textures/py.jpg',
      '/textures/ny.jpg',
      '/textures/pz.jpg',
      '/textures/nz.jpg'
    ]);
    
    const materials = [];
    for ( let i = 0; i < 6; i ++ ) {
      materials.push( new THREE.MeshBasicMaterial( { map: textures[ i ] } ) );
    }
    const skyBox = new THREE.Mesh( new THREE.BoxGeometry( 1, 1, 1 ), materials );
    skyBox.geometry.scale( 1, 1, - 1 );
    scene.add( skyBox );
    
    • 准备球体,通过全景图贴图实现 - (貌似球体比正方体好,没有面与面之间的白色线接细线)
      具体操作:
      方法1: 自己拍摄,用单反的全景模式拍摄
      方法2: 用现成的,球形全景图下载网站 - https://polyhaven.com/hdris

    球体360屋子的具体操作:

    const geometry = new THREE.SphereGeometry(16, 256, 256);
    const material = new THREE.MeshBasicMaterial({
      map: textLoader.load('全景图片地址'),
      //-- 球体内外均显示
      side: THREE.DoubleSide,
    });
    //-- 放大球体,让摄像机进入球体内部
    geometry.scale(1, 1, -1);
    const room = new THREE.Mesh(geometry, material);
    
    1. 房间展示的信息点,使用Sprite来实现
    • Sprite - 精灵是一个总是面朝着摄像机的平面,通常含有使用一个半透明的纹理
    1. 三维房间信息点,与鼠标实现交互
    • 通过光线投射Raycaster,这个类用于进行raycasting(光线投射)- 光线投射用于进行鼠标拾取
      代码片段:
    let raycaster = new THREE.Raycaster();
    let mouse = new THREE.Vector2();
    mouse.x = (e.clientX / element.clientWidth) * 2 - 1;
    mouse.y = -(e.clientY / element.clientHeight) * 2 + 1;
    raycaster.setFromCamera(mouse, this.camera);
    //-- 鼠标与照相机连线去穿透的对象集合,有几个穿透几个
    let intersects = raycaster.intersectObjects(创建信息点的对象数组, true);
    if (intersects.length > 0) {
        //--- 第1个被穿透,也就是纵深方向上,离你鼠标最近的对象
            console.log(intersects[0].object);
    }
    

    实现方式的不同

    同一个房间,换肤切换房间

    学习帖子地址 - https://juejin.cn/post/7047709128600322056#heading-1

    1. 创建一个场景,添加一个mash作为房间,仅通过更换mash的材质贴图来模拟房间的切换;
    //-- 替换场景360材质图 - 开始
    let texture = new THREE.TextureLoader().load('360图片链接');
    let sphereMaterial = new THREE.MeshBasicMaterial({
        map: texture,
        transparent: true,
        //设置默认透明 -- 为后续切换房间场景过渡做准备,防止黑屏生硬
        opacity: 0,
    });
    //-- 修改房屋mash的材质
    this.sphere.material = sphereMaterial;
    
    1. 房间场景切的换过渡
    • 因为不是真的切换房间物理位置,仅仅是切换贴图,所以仅通过改变透明度来优化
    import gsap from "gsap";
    ...
    //-- 针对房间新的360材质图,缓动透明从0 到 1
    gsap.to(sphereMaterial, { transparent: true, opacity: 1, duration: 2 });
    
    1. 标记点的添加与移除
    • 删除标记点
    this.scene.children = this.scene.children.filter(
            (item) => String(item.type) !== "Sprite"
    );
    
    • 添加标记点
    //-- 创建标记点材质
    let tipTexture = new THREE.TextureLoader().load(
        require("@/assets/image/tip.png")
    );
    let material = new THREE.SpriteMaterial({ map: tipTexture });
    //-- 添加一个带材质的
    let sprite = new THREE.Sprite(material);
    sprite.scale.set(xx, xx, xx);
    sprite.position.set(坐标x, 坐标y, 坐标z);
    sprite.content = xxxx;
    this.scene.add(sprite)
    
    1. 鼠标滑过移除信息点,显示隐藏信息的方式
    • 通过一个div浮层,修改内部文字改变信息,修改left,top的css样式改变显示隐藏
    真不同房间切换

    学习帖子地址 - https://juejin.cn/post/7215268204062490679

    1. 创建一个场景,添加多个mash作为房间,有各自贴图,在不同的sence坐标位置,各自看不见;
    const createRoom = (name, position, map) => {
      const geometry = new THREE.SphereGeometry(16, 256, 256);
      geometry.scale(1, 1, -1);
      const material = new THREE.MeshBasicMaterial({
        map: textLoader.load(map),
        side: THREE.DoubleSide,
      });
      const room = new THREE.Mesh(geometry, material);
      room.name = name;
      room.position.set(position.x, position.y, position.z);
      room.rotation.y = Math.PI / 2;
      scene.add(room);
      return room;
    };
    
    // 批量创建
    rooms.map((item) => {
      const room = createRoom(item.key, item.position, item.map);
      return room;
    });
    
    1. 房间场景切的换过渡,通过操作摄像机移动实现,移动过程中使用了tween库
    // 点击切换场景
    const handleSwitchButtonClick = async (key) => {
      const room = rooms.filter((item) => item.key === key)[0];
      if (data.camera) {
        const x = room.position.x;
        const y = room.position.y;
        const z = room.position.z;
        //-- 获取房间坐标信息,移动摄像机(缓动方式)
        Animations.animateCamera(data.camera, data.controls, { x, y, z: data.cameraZAxis }, { x, y, z }, 1600, () => {});
        data.controls.update();
      }
    }
    
    1. 缓动库 - 缓动动画修改摄像机位置,更新摄像机,更新轨道控制器
    import { TWEEN } from 'three/examples/jsm/libs/tween.module.min.js';
    
    const Animations = {
      // 相机移动实现漫游等动画
      animateCamera: (camera, controls, newP, newT, time = 2000, callBack) => {
        const tween = new TWEEN.Tween({
          x1: camera.position.x, // 相机x
          y1: camera.position.y, // 相机y
          z1: camera.position.z, // 相机z
          x2: controls.target.x, // 控制点的中心点x
          y2: controls.target.y, // 控制点的中心点y
          z2: controls.target.z, // 控制点的中心点z
        });
        tween.to(
          {
            x1: newP.x,
            y1: newP.y,
            z1: newP.z,
            x2: newT.x,
            y2: newT.y,
            z2: newT.z,
          },
          time,
        );
        tween.onUpdate(function (object) {
          camera.position.x = object.x1;
          camera.position.y = object.y1;
          camera.position.z = object.z1;
          controls.target.x = object.x2;
          controls.target.y = object.y2;
          controls.target.z = object.z2;
          controls.update();
        });
        tween.onComplete(function () {
          controls.enabled = true;
          controls.update();
          callBack();
        });
        tween.easing(TWEEN.Easing.Cubic.InOut);
        tween.start();
      },
    };
    export default Animations;
    

    相关文章

      网友评论

          本文标题:threejs 360房间的学习

          本文链接:https://www.haomeiwen.com/subject/yaoxddtx.html