国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

three.js實現(xiàn)VR看房自由

這篇具有很好參考價值的文章主要介紹了three.js實現(xiàn)VR看房自由。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

需求:

? ? ? ?在很多看房軟件,例如貝殼看房、VR博物館或者VR展廳等等,為了更加真實的展示產(chǎn)品或者場景的特色,通常會通過一些VR或者全景圖的方式,給用戶帶來沉浸式的體驗,給視覺上帶來比較震撼的效果,再加上一些動感的音樂,仿佛讓人深陷其中,無法自拔。假的,因為這些實現(xiàn)效果比較便宜,而且性能要求不高

實現(xiàn)原理:

? ? ? 通過全景圖的方式實現(xiàn),其實就是在一個球體內(nèi)部或者球體雙面貼上全景圖(下面簡稱全景球),讓相機位于該球體的中心,當鼠標移動是,旋轉(zhuǎn)相機即可;當需要漫游的時候,根據(jù)點擊的點位獲取下一個相機位置,并將相機移動至點擊的全景球,影藏其他的全景球,顯示下一個全景球;重復(fù)上面過程。怎么樣,是不是很簡單?

需要解決哪些問題:

1.初始化場景的時候相機是出于什么位置或者姿態(tài)?

答:從眾多點位中的選取一個全景球的中心位置相機高度可以根據(jù)需要調(diào)節(jié),作為相機的初始位置,不然相機就跑去了全景球?qū)е驴吹呐K東西。

2.當點擊地面上的軌跡時,如何找到下一個全景球,也就是即將要進入的全景球

答:因為軌跡的點位和全景球在創(chuàng)建的時候,是有規(guī)律的,比如他們的命名是一一對應(yīng)的,例如全景球的命名為VR_AA,那全景球?qū)?yīng)的軌跡點可以命名為VR_A;當我們點擊的到軌跡點VR_A時,就可以根據(jù)字符串的包含在之前的全景球數(shù)組中找到VR_AA,并且將它顯示出來,這種情況每次都要遍歷一次全景球數(shù)組;當然也可以創(chuàng)建一個方法,根據(jù)傳進去的軌跡點name,然后對于的全景球

3.相機如何平滑的移動到指定的位置?

答:我們可以利用一個叫tweenjs/tween.js的庫,把相機當前位置和目標位置生成一個平滑的過渡效果,然后應(yīng)用在相機上就可以了

4.如果單純的現(xiàn)實目標全景球和影藏全景球,那效果太生硬了,和網(wǎng)上看到的VR效果差別很大,如何實現(xiàn)顯示和影藏的效果漸變呢?

答:相機在當前全景球位置平滑移動至目標全景球時,會有一個距離的比率ratio,這個比率很好理解,從A移動到B的時候,如果還沒開始那ratio就是1.0;如果朝著B移動的距離是一半,那就是0.5;如果到達B了,那ratio就是0.0了,而這個ratio就可以用來設(shè)置A的透明度;而B的透明度則是1.0-ratio。

標簽:坐標精準度不高

? ? ? 試想一下,在任何三維場景或者VR的場景中我們都會有很多標簽信息,并綁定一些事件進行交互,然而這些標簽的位置基本都是手動在場景中進行拾取的,那會帶來什么問題呢?因為我們位于全景圖中,當點擊全景圖中的物體的時候(其實點擊的就是全景圖中的某個位置),比如我們在全景球A中標記了空調(diào)的位置,并且保存了位置。那么這個空調(diào)的位置只會在全景球A中生效,也就是可以正確的展示空調(diào)的位置上,在其他的全景球無法正確展示空調(diào)的位置

? ? ? ?解決辦法一:把標簽打在模型上面,也就是在全景球外面加載一個簡單的模型作為輔助,不過不展示它,鼠標拾取位置的時候,拾取鼠標模型上的點作為標簽的位置;這樣子可以稍微解決一下標簽位置不準確的位置上,但是也會有一定的誤差,但是整個VR場景只需要一套標簽即可

? ? ? 解決辦法二:那就是簡單粗暴,每個全景球?qū)τ谝惶讟撕?,這樣子位置絕對的準確,但是顯得有點笨拙。

控制器:自定義一個VR控制器

因為three.js沒有自帶的類似babylon.js中的Freecamera, 可以根據(jù)官方的demo寫一個簡單版的控制器,控制器可以鼠標移動的來決定的相機的旋轉(zhuǎn),以下是控制代碼

import * as THREE from "three";

export default class VRcontrol extends THREE.EventDispatcher {
  autoRotate = false;
  onPointerDownMouseX = 0;
  onPointerDownMouseY = 0;
  lon = 0;
  onPointerDownLon = 0;
  lat = 0;
  onPointerDownLat = 0;
  phi = 0;
  theta = 0;

  keyDown = false;

  camera: THREE.PerspectiveCamera;
  domElement: HTMLElement;

  constructor(camera: THREE.PerspectiveCamera, domElement: HTMLElement) {
    super();
    this.camera = camera;
    this.domElement = domElement;
    this.domElement.addEventListener(
      "pointerdown",
      this.onPointerDown.bind(this)
    );
    this.domElement.addEventListener(
      "pointermove",
      this.onPointerMove.bind(this)
    );
    window.addEventListener("pointerup", this.onPointerUp.bind(this));
    this.domElement.addEventListener(
      "wheel",
      this.onDocumentMouseWheel.bind(this)
    );
  }

  onPointerDown(event: PointerEvent) {
    if (event.isPrimary === false) return;

    this.keyDown = true;

    this.onPointerDownMouseX = event.clientX;
    this.onPointerDownMouseY = event.clientY;

    this.onPointerDownLon = this.lon;
    this.onPointerDownLat = this.lat;
  }

  onPointerMove(event: PointerEvent) {
    if (event.isPrimary === false || !this.keyDown) return;
    this.lon =
      (this.onPointerDownMouseX - event.clientX) * 0.1 + this.onPointerDownLon;
    this.lat =
      (event.clientY - this.onPointerDownMouseY) * 0.1 + this.onPointerDownLat;

    // 分發(fā)事件
    this.dispatchEvent({
      type: "camera",
      camera: this.camera,
    });
  }

  onPointerUp(event: PointerEvent) {
    if (event.isPrimary === false) return;

    this.keyDown = false;

    this.domElement.removeEventListener("pointermove", this.onPointerMove);
  }

  onDocumentMouseWheel(event: WheelEvent) {
    const fov = this.camera.fov + event.deltaY * 0.05;

    this.camera.fov = THREE.MathUtils.clamp(fov, 10, 75);

    this.camera.updateProjectionMatrix();
  }

  update() {
    if (this.autoRotate) {
      this.lon += 0.1;
    }

    this.lat = Math.max(-85, Math.min(85, this.lat));
    this.phi = THREE.MathUtils.degToRad(90 - this.lat);
    this.theta = THREE.MathUtils.degToRad(this.lon);

    const x = 500 * Math.sin(this.phi) * Math.cos(this.theta);
    const y = 500 * Math.cos(this.phi);
    const z = 500 * Math.sin(this.phi) * Math.sin(this.theta);

    this.camera.lookAt(x, y, z);
  }

  remove() {
    this.domElement.removeEventListener(
      "pointerdown",
      this.onPointerDown.bind(this)
    );
    this.domElement.removeEventListener(
      "pointermove",
      this.onPointerMove.bind(this)
    );
    window.removeEventListener("pointerup", this.onPointerUp.bind(this));
    this.domElement.removeEventListener(
      "wheel",
      this.onDocumentMouseWheel.bind(this)
    );
  }
}

接下來給出場景的核心代碼,里面寫的是一些demo,沒有經(jīng)過封裝,里面包含了兩個渲染器,一個是webGL,另外一個是CSS2DRenderer,主要用來渲染標簽,里面也包含了一些創(chuàng)建標簽的方法

import * as THREE from "three";
import FirstPersonCameraControl from "../controls/Mycontrol";
import { CSS2DRenderer } from "three/examples/jsm/renderers/CSS2DRenderer";
import {
  createrPoint,
  createVRItem,
  createVideoLabel,
  createIconLabel,
} from "../tools";
import TWEEN from "@tweenjs/tween.js";

export default class VR extends THREE.EventDispatcher {
  radii: number;
  parent: THREE.Group;
  pointObj: THREE.Group;
  currentVRItem: THREE.Mesh | any;
  preVRItem: THREE.Mesh | any;

  container: string | HTMLElement | any;
  scene: THREE.Scene;
  camera: THREE.PerspectiveCamera;
  renderer: THREE.WebGLRenderer;
  labelRenderer: CSS2DRenderer;
  initLocaltion: any;
  raycaster: THREE.Raycaster;
  mouse: THREE.Vector2;
  control: any;
  getMousePosition: (event: any) => void;
  onMouseDown: (event: any) => void;
  onResize: () => void;

  marking: boolean;
  labelContent: string;
  videoUrl: string;
  imgUrl: string;
  labelType: number;
  effective: number;

  textures: THREE.Texture[] = [];

  clock = new THREE.Clock();

  Pupop: THREE.Object3D<THREE.Event> | undefined;

  constructor(option: any) {
    super();
    this.marking = false;
    this.videoUrl = "";
    this.labelContent = "";
    this.imgUrl = "";
    this.labelType = 0;
    this.effective = 1;
    this.radii = 4; // 全景球半徑
    this.pointObj = new THREE.Group();
    this.parent = new THREE.Group();

    this.container =
      option.container instanceof HTMLElement
        ? option.container
        : document.getElementById(option.container); // 渲染的DOM節(jié)點

    this.scene = new THREE.Scene(); // 三維場景
    this.scene.background = new THREE.Color(0xaaccff);
    this.scene.add(this.parent); // 全景球集合
    this.scene.add(this.pointObj); // 點集合

    this.camera = new THREE.PerspectiveCamera(
      70,
      this.container.clientWidth / this.container.clientHeight,
      0.05,
      500
    ); // 透視相機初始化

    // 初始化渲染器
    this.renderer = new THREE.WebGLRenderer({
      antialias: true,
      alpha: true,
      logarithmicDepthBuffer: true,
    });

    // 初始化標簽渲染器
    this.labelRenderer = new CSS2DRenderer();
    this.labelRenderer.setSize(
      this.container.clientWidth,
      this.container.clientHeight
    );
    this.labelRenderer.domElement.style.position = "absolute";
    this.labelRenderer.domElement.style.top = "0px";

    this.renderer.setSize(
      this.container.clientWidth,
      this.container.clientHeight
    );
    // 設(shè)置渲染的尺寸
    // this.renderer.setPixelRatio = window.devicePixelRatio

    this.renderer.setClearColor(new THREE.Color("#1e1e1e"));
    this.initLocaltion = option.initLocaltion; // 全景圖初始位置

    this.container.appendChild(this.labelRenderer.domElement);
    this.container.appendChild(this.renderer.domElement);

    this.raycaster = new THREE.Raycaster(); // 初始化射線
    this.mouse = new THREE.Vector2(); //初始化鼠標位置

    // 控制器
    this.control = new FirstPersonCameraControl(
      this.camera,
      this.labelRenderer.domElement
    );

    // 獲取鼠標坐標
    this.getMousePosition = function (event) {
      this.mouse.x = (event.offsetX / this.container.clientWidth) * 2 - 1;
      this.mouse.y = -(event.offsetY / this.container.clientHeight) * 2 + 1; //這里為什么是-號,沒有就無法點中
    };

    this.onMouseDown = async function (event) {
      this.getMousePosition(event);
      //將平面坐標系轉(zhuǎn)為世界坐標系
      this.raycaster.setFromCamera(this.mouse, this.camera);
      //得到點擊的幾何體
      const raycasters = this.raycaster.intersectObjects(
        this.pointObj.children
      );

      const name = raycasters.length > 0 && raycasters[0].object.name;

      this.currentVRItem = this.scene.getObjectByName(name + "VR");
      if (this.currentVRItem) {
        const position = this.currentVRItem.position.clone();
        this.ChangeScene(position, () => {
          this.parent.children.forEach((mesh) => {
            if (mesh.name != name + "VR") {
              mesh.visible = false;
            }
          });
        });
      }
      const currentVRLocal = raycasters.find((item) => {
        if (item.distance > this.radii - 0.2 && item.distance < this.radii) {
          return item;
        }
      });

      let currentLabel;
      if (currentVRLocal && this.marking) {
        switch (this.labelType) {
          case 0:
            const position = currentVRLocal.point.clone();
          case 1:
            currentLabel = this.imgUrl && createIconLabel(this.imgUrl);
            break;
          case 2:
            currentLabel = this.videoUrl && createVideoLabel(this.videoUrl);
          default:
            break;
        }

        const position = currentVRLocal.point.clone();

        currentLabel && currentLabel.position.copy(position);
        currentLabel && this.scene.add(currentLabel);
      }
    };
    this.onResize = function () {
      this.renderer.setSize(
        this.container.clientWidth,
        this.container.clientHeight
      );
      this.camera.aspect =
        this.container.clientWidth / this.container.clientHeight;
      this.camera.updateProjectionMatrix();
    };

    this.container.addEventListener(
      "mousedown",
      this.onMouseDown.bind(this),
      false
    ); // 鼠標點擊事件
    window.addEventListener("resize", this.onResize.bind(this), false); // 窗口縮重新渲染
  }

  // 切換動畫
  ChangeScene(newTarget: THREE.Vector3, callback: () => void) {
    const leng = this.camera.position.clone().distanceTo(newTarget);
    const time = THREE.MathUtils.clamp(leng * 200, 800, 1200);
    const that = this;
    that.currentVRItem.visible = true;

    new TWEEN.Tween(that.camera.position)
      .to(newTarget, time)
      // easing緩動函數(shù),Out表示最開始加速,最后放緩
      .easing(TWEEN.Easing.Quadratic.InOut)
      .onUpdate(function () {
        const ratio = that.camera.position.distanceTo(newTarget);
        const Ratio = ratio / leng;

        if (that.currentVRItem) {
          that.currentVRItem.material.uniforms.ratio.value = 1 - Ratio;
        }

        that.dispatchEvent({
          type: "camera",
          camera: that.camera,
        });
      })
      .start()
      .onComplete(function () {
        that.preVRItem = that.currentVRItem;
        callback();
      });
  }

  // 渲染函數(shù)
  renderFn() {
    TWEEN.update();
    this.control.update();
    this.renderer.render(this.scene, this.camera);

    this.labelRenderer.render(this.scene, this.camera);
    requestAnimationFrame(this.renderFn.bind(this));
  }

  initVR(infoList: any[]) {
    infoList.forEach((item) => {
      const point = createrPoint(item.id, item.tz, -0.5 * this.radii, item.tx);
      this.pointObj.add(point);

      const VRitem = createVRItem(
        item.img,
        item.id + "VR",
        item.tz,
        item.ty,
        item.tx
      );
      this.parent.add(VRitem.skyBox);
      this.textures.push(VRitem.textureA);
    });

    if (this.initLocaltion) {
      this.preVRItem = this.scene.getObjectByName(this.initLocaltion);
    } else {
      this.preVRItem = this.parent.children[0];
    }

    this.preVRItem.visible = true;

    this.camera.position.set(
      this.preVRItem.position.x,
      this.preVRItem.position.y,
      this.preVRItem.position.z
    );
  }
  dispose() {
    this.scene.children.forEach((item) => {
      if (item instanceof THREE.Mesh) {
        item.material.dispose();
        item.geometry.dispose();
      }
    });
    this.textures.forEach((texture) => {
      texture.dispose();
    });
    this.renderer.clear()
    this.renderer.forceContextLoss();
    this.renderer.dispose();
    this.scene.clear();
  }
}

還有一下幾個工具方法,用來創(chuàng)建軌跡點的createrPoint,創(chuàng)建全景球的createVRItem,在著色器材質(zhì)中,接收一個從當前點到下一個點的距離除以總距離,得到一個比率ratio,將這個比率作為一個透明度,傳給著色器

import * as THREE from "three";
import { CSS2DObject } from "three/examples/jsm/renderers/CSS2DRenderer";
import { Font, FontLoader } from "three/examples/jsm/loaders/FontLoader";
import { TextGeometry } from "three/examples/jsm/geometries/TextGeometry";

/**
 *
 * @param {string} id
 * @param {string} tx
 * @param {string} ty
 * @param {string} tz
 * @returns {THREE.Mesh}
 */
export const createrPoint = (
  id: string,
  tx: number,
  ty: number,
  tz = 0
): THREE.Mesh => {
  const geometry = new THREE.CircleGeometry(0.15, 30);
  const material = new THREE.MeshBasicMaterial({ color: "#eeeeee" });

  const circle = new THREE.Mesh(geometry, material);
  circle.name = id;
  circle.translateX(tx);
  circle.translateY(ty);
  circle.translateZ(tz);
  circle.rotateX(-Math.PI / 2);
  return circle;
};

export const createVRItem = (
  url: string,
  id: string,
  tx: number,
  ty: number,
  tz = 0,
  radii = 4
) => {
  const vertexShader = `
    varying vec2 vUv;
    void main(){
        vUv = uv;
        gl_Position = projectionMatrix*viewMatrix*modelMatrix*vec4( position, 1.0 );
    }
`;
  const fragmentShader = `
    uniform sampler2D texture1;
    uniform float ratio;
    varying vec2 vUv;
    void main() {
        vec4 vcolor = texture2D( texture1, vUv );
        vec4 tcolor = vec4(0.,0.,0.,0.);
        gl_FragColor = mix(tcolor,vcolor,ratio);
     }
`;
  const textureA = new THREE.TextureLoader().load(url);
  const materialObj = new THREE.ShaderMaterial({
    uniforms: {
      texture1: {
        value: textureA,
      },
      ratio: {
        value: 1.0,
      },
    },
    vertexShader,
    fragmentShader,
  });

  materialObj.transparent = true;
  materialObj.depthWrite = false;

  const skyBox = new THREE.Mesh(
    new THREE.SphereGeometry(radii, 40, 40),
    materialObj
  );
  skyBox.name = id;
  skyBox.translateX(tx);
  skyBox.translateY(0);
  skyBox.translateZ(tz);
  skyBox.geometry.scale(1, 1, -1);
  skyBox.visible = false;
  return {
    skyBox,
    textureA,
  };
};

export const createVideoLabel = (url: string): CSS2DObject => {
  const x = document.createElement("video");
  x.setAttribute("width", "320");
  x.setAttribute("height", "240");
  x.setAttribute("controls", "controls");
  x.setAttribute("src", url);

  const videoObj = new CSS2DObject(x);
  videoObj.name = "video";
  return videoObj;
};

export const createIconLabel = (url: string, height = 50): CSS2DObject => {
  const img = document.createElement("img");
  img.src = url;
  img.height = height;

  const imgObj = new CSS2DObject(img);
  imgObj.name = "icon";
  return imgObj;
};

export const text3D = async (text: string): Promise<THREE.Mesh> => {
  const loader = new FontLoader();
  return new Promise((resolve) => {
    loader.load("font/helvetiker_regular.typeface.json", function (response) {
      const textGeo = new TextGeometry(text, {
        font: response,
        size: 1,
        height: 200,
        curveSegments: 1,
        bevelThickness: 1,
        bevelSize: 1,
        bevelEnabled: false,
      });

      const materials = [
        new THREE.MeshPhongMaterial({ color: 0xffffff, flatShading: true }), // front
        new THREE.MeshPhongMaterial({ color: 0xffffff }), // side
      ];
      const mesh = new THREE.Mesh(textGeo, materials);
      resolve(mesh);
    });
  });
};

使用的時候直接實例化VR這個類就可以了

        vrScene = new VR({
            container: 'threeContainer'
        })

        vrScene.initVR(dataList)
        vrScene.renderFn()
        vrScene.addEventListener('camera', cameraFn)
    }
})
export const dataList = [
    {
        id: '01',
        tx: 0,
        ty: 0,
        tz: 0,
        img: 'models/gardent/別墅_地下室.jpg'
    },
    {
        id: '02',
        tx: 2,
        ty: 0,
        tz: 2,
        img: 'models/gardent/別墅_主衛(wèi).jpg'
    },
    {
        id: '03',
        tx: 2,
        ty: 0,
        tz: 5,
        img: 'models/gardent/別墅_主臥.jpg'
    },
    {
        id: '04',
        tx: 5,
        ty: 0,
        tz: 9,
        img: 'models/gardent/臥室1.jpg'
    },
    {
        id: '05',
        tx: 6,
        ty: 0,
        tz: 1,
        img: 'models/gardent/臥室2.jpg'
    }
]

上面是數(shù)據(jù)格式文章來源地址http://www.zghlxwxcb.cn/news/detail-802047.html

到了這里,關(guān)于three.js實現(xiàn)VR看房自由的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • vue2+three.js實現(xiàn)類似VR、3D全景效果

    vue2+three.js實現(xiàn)類似VR、3D全景效果

    效果圖: 倆圖標是我自己加的前進后退按鈕,也是百度了好久,再加上GPT的幫助,才給搞出來。因為需求急,都不看官方文檔,百度到一個能跑的demo之后改吧改吧,就先用著了。 下面是代碼: 這里 代碼有很多用不到的地方和需要優(yōu)化的地方,我是來不及改了,就先這樣吧

    2024年02月15日
    瀏覽(87)
  • Vue實現(xiàn)vr看房效果

    1.下載依賴: VS code終端執(zhí)行兩個命令 2.template模塊代碼 3.script模塊代碼 4.style模塊的代碼:

    2024年02月11日
    瀏覽(21)
  • three.js實戰(zhàn)模擬VR全景視圖

    three.js實戰(zhàn)模擬VR全景視圖

    文章中使用到的案例圖片都來源于:Humus - Textures 里面有很多免費的資源,可以直接下載,每個資源里面都提供6個不同方位的圖片,我們通過threejs稍微處理一下,就能實現(xiàn)以下3D效果的場景了。

    2024年02月04日
    瀏覽(18)
  • three.js實現(xiàn)3D室內(nèi)全景看房

    three.js實現(xiàn)3D室內(nèi)全景看房

    首先我們先搭建一個項目,我選擇使用vite來進行項目的搭建,執(zhí)行命令如下: 這樣一個基本的項目就搭建成功了,目錄如下所示 然后,下載一下three.js工具,執(zhí)行如下命令 頁面中引入 先搭建一個立體圖形,并畫出輔助線,如下所示 ?實現(xiàn)代碼如下: 接著,給我們的立體圖

    2024年02月12日
    瀏覽(27)
  • 微信小程序集成three.js--VR全景項目源碼

    微信小程序集成three.js--VR全景項目源碼

    小程序集成Three.js,展示不同貼圖材質(zhì)的運用 實現(xiàn)VR全景效果的部分,主要實現(xiàn)步驟如下: 1 創(chuàng)建一個正方體 2加載6個不同面的圖片作為正方體的材質(zhì) 3設(shè)置正方體屬性?cube.geometry.scale(1,1,-1),即完成了正方體面的反轉(zhuǎn) 4將camera的位置設(shè)置在正方體內(nèi)部,即實現(xiàn)了從內(nèi)部觀察正

    2024年02月11日
    瀏覽(44)
  • Three.js--》探秘虛擬現(xiàn)實VR展廳的視覺盛宴

    Three.js--》探秘虛擬現(xiàn)實VR展廳的視覺盛宴

    今天簡單實現(xiàn)一個three.js的小Demo,加強自己對three知識的掌握與學(xué)習,只有在項目中才能靈活將所學(xué)知識運用起來,話不多說直接開始。 源碼下載地址:地址 在線體驗地址:地址 目錄 項目搭建 初始化three代碼 camera-controls控制器使用 添加畫框 畫框處理事件 添加機器人模型

    2024年04月23日
    瀏覽(19)
  • Three.js系列: 在元宇宙看電影,享受 VR 視覺盛宴

    Three.js系列: 在元宇宙看電影,享受 VR 視覺盛宴

    本文 gihtub 地址: https://github.com/hua1995116/Fly-Three.js 最近元宇宙的概念很火,并且受到疫情的影響,我們的出行總是受限,電影院也總是關(guān)門,但是在家里又沒有看大片的氛圍,這個時候我們就可以通過自己來造一個宇宙,并在 VR 設(shè)備(Oculus 、cardboard)中來觀看。 今天我打算

    2024年02月08日
    瀏覽(24)
  • vue 項目使用three.js 實現(xiàn)3D看房效果

    vue 項目使用three.js 實現(xiàn)3D看房效果

    0.前言 該教程能幫助直接寫出vue項目的3D看房效果?。?! 先上效果圖 1.安裝依賴 2.vue代碼 這里文件名為three.vue 代碼非原創(chuàng),出處 vue3+threejs實現(xiàn)全景看房 (異步加載 BOLLROOM 部件為對原代碼的修改) 注意這里的hdr 文件必須要放在assets文件夾中,且要通過import模塊的形式導(dǎo)入!

    2024年02月13日
    瀏覽(94)
  • VR全景如何應(yīng)用在房產(chǎn)行業(yè),VR看房有哪些優(yōu)勢

    VR全景如何應(yīng)用在房產(chǎn)行業(yè),VR看房有哪些優(yōu)勢

    導(dǎo)語: 在如今的數(shù)字時代,虛擬現(xiàn)實(VR)技術(shù)的迅猛發(fā)展為許多行業(yè)帶來了福音,特別是在房產(chǎn)樓盤行業(yè)中。通過利用VR全景技術(shù),開發(fā)商和銷售人員可以為客戶提供沉浸式的樓盤瀏覽體驗,從而帶來諸多優(yōu)勢。 一、了解VR全景技術(shù)的基本原理 VR全景技術(shù)是一種模擬真實場

    2024年02月03日
    瀏覽(23)
  • 線上售樓vr全景看房成為企業(yè)數(shù)字化營銷工具

    線上售樓vr全景看房成為企業(yè)數(shù)字化營銷工具

    在房地產(chǎn)業(yè)中,VR全景拍攝為買家提供了虛擬看房的全新體驗。買家可以通過相關(guān)設(shè)備,遠程參觀各個樓盤的樣板間和實景,感受房屋的空間布局和環(huán)境氛圍,極大地提高了購房決策的準確性。對于房地產(chǎn)開發(fā)商和中介機構(gòu)來說,VR全景拍攝還可以幫助他們在線上展示各種房源

    2024年02月12日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包