如视 Five SDK
    Preparing search index...

    如视 Five SDK

    Five.js

    npm version

    贝壳如视三维渲染框架

    Five贝壳如视(realsee.com) 提供的在浏览器中运行的三维空间渲染 Javascript SDK。您可以通过如视开发者中心的数据服务,并结合Five,制作丰富多彩的三维空间应用。

    并且Five提供了一系列的方法、事件、生命周期函数。您可以方便地基于Five进行二次开发,并结合到您自身的项目中,为您的项目添砖加瓦。

    Five通过 TypeScript 编写,保证开发的质量以及编程体验,推荐通过 Visual Studio CodeWebStorm 等现代源代码编辑器,您将可以体验到友好的代码提示以及自动补全。

    Five还提供了完善的 React Hooks API ,可以方便的通过 React 开发复杂的响应式数据应用。当然直接使用Five开发也是没有问题的。

    Five提供通过 npm 的方式安装。Five基于 Three.js, 所以同时您需要安装相关依赖。

    目前依赖的three版本为 115 ~ 117 的版本

    npm install @realsee/five three@0.117.1
    

    如果您使用React Hooks API,那么也请同时安装React的相关依赖。

    npm install @realsee/five three@0.117.1 react react-dom @types/react @types/react-dom
    

    接下来便可以在您的项目使用Five了。

    import { Five } from "@realsee/five";
    // 如果您使用 React Hoos API
    import { useFiveState } from "@realsee/five/react";
    Safari Safari on iOS Chrome Chrome for Android Edge Firefox
    >= 9 >= 9 >= 49 >= 93 >= 13 >= 45

    Five提供了快速上手体验的项目生成工具,您可以通过他熟悉Five的功能以及尝试基于Five开发功能。

    1. 先创建一个文件夹five-quick-start, 作为项目根目录并且使用 npm init 命令初始化一个工程。
    mkdir five-quick-start && cd five-quick-start && npm init -y
    
    1. 安装Five
    npm install @realsee/five
    
    1. 通过Five的内置的five-quick-start-init脚本来快速补完当前项目
    npx five-quick-start-init
    

    项目的文件结构如下

    .
    ├── README.md
    ├── assets 静态文件测试数据
    │ ├── data0.json
    │ └── data1.json
    ├── index.html 页面模版
    ├── index.tsx 逻辑代码
    ├── package.json npm 包管理描述
    ├── tsconfig.json typescript 配置
    ├── webpack.config.js webpack 开发环境配置
    └── webpack.production.js webpack 生产配置

    npm script运行测试环境

    npm run dev
    

    默认将会在 port: 3000 开启 webpack dev server。您也可以在 webpack.config.js 中修改配置。

    1. 现在可以打来浏览器 http://0.0.0.0:3000 来看看项目初始化的效果了。您可以修改代码来体验一下如何使用Five来二次开发。

    Five的简单使用样例:

    import { Five } from "@realsee/five";

    // 构造函数的具体参数见文档
    const five = new Five();

    // 将渲染视图的 canvas 添加到 DOM 中
    five.appendTo(document.getElementById('app')!);

    // 如果显示区域需要变动,在变动时请调用 refresh 重置显示参数
    window.addEventListener('resize', () => five.refresh());

    // 获取三维空间的 Work 数据,加载进来
    // Work 数据可以通过如视开发者中心获取
    fetch(`./work.json`)
    .then(res => res.json())
    .then(work => five.load(work));

    其他的 Five API 待补充

    React框架中使用Five的简单使用样例:

    import * as React from "react";
    import * as ReactDOM from "react-dom";
    import {Five, Work, parseWork} from "@realsee/five";
    import {createFiveProvider, FiveCanvas} from "@realsee/five/react";

    // 创建 Provider, 参数与 new Five 参数类似
    // 构造函数的具体参数见文档
    const FiveProvider = createFiveProvider();

    const App: React.FC = () => {

    // 声明 State: Work
    const [work, setWork] = React.useState<Work | null>(null);

    // 声明 State: Size<{width, height}>
    const [size, setSize] = React.useState({
    width: window.innerWidth,
    height: window.innerHeight
    })

    // 获取三维空间的 Work 数据,加载进来
    const loadWork = React.useCallback((url: string) => {
    fetch(url)
    .then(res => res.json())
    .then(data => setWork(parseWork(data)));
    }, []);

    React.useEffect(() => {
    loadWork("./data0.json");
    }, []);

    // 如果显示区域需要变动,在变动时请调用 FiveCanvas 的 size
    React.useEffect(() => {
    const onResize = () => {
    setSize({
    width: window.innerWidth,
    height: window.innerHeight
    });
    }
    window.addEventListener("resize", onResize, false);
    return () => window.removeEventListener("resize", onResize, false);
    });

    if (work) {
    {/*
    在 FiveProvider 内承载一个 Five 实例,
    在他内部的组件可以使用 Five React Hook API 来获取/设置/操作 他
    一个页面中也可以有多个 FiveProvider
    */}
    return <FiveProvider initialWork={work}>
    {/*
    将渲染视图的 canvas 添加到 DOM 中
    FiveCanvas 需要出现在 FiveProvider 内,他将渲染 FiveProvider 的视图
    这样的设计可以实现不同的 DOM 层级结构
    在 FiveProvider 内的其他组件也可以使用 Five React Hook API 来获取/设置/操作 他外部的 FiveProvider
    */}
    <FiveCanvas width={size.width} height={size.height}/>
    </FiveProvider>
    }
    return null;
    }

    ReactDOM.render(<App></App>, document.getElementById("app"));

    其他的Five React Hook API文档建设中...

    欢迎查看 Five API 文档

    该文档由 TypeDoc 生成,您可以详细查看 api 使用方式,调用参数,数据结构。

    Work如视开发者中心 提供的对于一个三维空间的描述。 是通过如视硬件设备(如视扫描仪如视Lite全景相机如视VR App )扫描并处理之后用于三维空间展示的数据。

    WorkJSON作为数据格式Five框架可以解析Work数据并展示。一个Five实例每次可以载入并展示一个Work。并且也可以在不同的Work之间动态切换。

    Work的数据样例如下

    {
    "initial": {
    "mode": "Panorama",
    "pano_index": 6,
    "longitude": 2.6869287662553916,
    "latitude": 0,
    "fov": 95
    },
    "model": {
    "file_url": "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/model\/auto3d-DJaa08PIzN4JYluXQ1j2VS.at3d",
    "material_textures": [
    "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/materials\/texture_0.jpg",
    "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/materials\/texture_1.jpg",
    "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/materials\/texture_2.jpg",
    "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/materials\/texture_3.jpg",
    "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/materials\/texture_4.jpg",
    "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/materials\/texture_5.jpg",
    "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/materials\/texture_6.jpg",
    "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/materials\/texture_7.jpg",
    "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/materials\/texture_8.jpg",
    "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/materials\/texture_9.jpg"
    ]
    },
    "panorama": {
    "list": [
    {
    "up": "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/images\/cube_2048\/0\/2257f0f0b29d5b00ff01934ce51aaa35\/0_u.jpg",
    "down": "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/images\/cube_2048\/0\/2257f0f0b29d5b00ff01934ce51aaa35\/0_d.jpg",
    "left": "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/images\/cube_2048\/0\/2257f0f0b29d5b00ff01934ce51aaa35\/0_l.jpg",
    "right": "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/images\/cube_2048\/0\/2257f0f0b29d5b00ff01934ce51aaa35\/0_r.jpg",
    "front": "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/images\/cube_2048\/0\/2257f0f0b29d5b00ff01934ce51aaa35\/0_f.jpg",
    "back": "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/images\/cube_2048\/0\/2257f0f0b29d5b00ff01934ce51aaa35\/0_b.jpg"
    },
    {
    "up": "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/images\/cube_2048\/1\/ecb554bb1c122fa90186d176ccfecde4\/1_u.jpg",
    "down": "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/images\/cube_2048\/1\/ecb554bb1c122fa90186d176ccfecde4\/1_d.jpg",
    "left": "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/images\/cube_2048\/1\/ecb554bb1c122fa90186d176ccfecde4\/1_l.jpg",
    "right": "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/images\/cube_2048\/1\/ecb554bb1c122fa90186d176ccfecde4\/1_r.jpg",
    "front": "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/images\/cube_2048\/1\/ecb554bb1c122fa90186d176ccfecde4\/1_f.jpg",
    "back": "https:\/\/vrlab-public.ljcdn.com\/release\/auto3dhd\/a62e1ebf7d013f7df117551a14af79fc\/images\/cube_2048\/1\/ecb554bb1c122fa90186d176ccfecde4\/1_b.jpg"
    }
    ],
    },
    "observers": [
    {
    "visible_nodes": [ 1 ],
    "accessible_nodes": [ 1 ],
    "quaternion": {
    "w": 0.45076583925142194,
    "x": 0.010070951976936936,
    "y": -0.8925839597148215,
    "z": -0.0016154299986102319
    },
    "standing_position": [
    -6.956049919128418,
    -1.3924440682333898,
    1.6591600179672241
    ],
    "position": [
    -6.956049919128418,
    -0.10312400013208389,
    1.6591600179672241
    ],
    "floor_index": 0
    },
    {
    "visible_nodes": [ 0 ],
    "accessible_nodes": [ 0 ],
    "index": 1,
    "quaternion": {
    "w": -0.9884643083591809,
    "x": -0.0038900979633806664,
    "y": 0.1512670435365699,
    "z": -0.006439990839033269
    },
    "standing_position": [
    -6.176340103149414,
    -1.380554749576384,
    2.179759979248047
    ],
    "position": [
    -6.176340103149414,
    -0.10025200247764587,
    2.179759979248047
    ],
    "floor_index": 0,
    }
    ]
    }

    Work 的数据说明

    • initial: 初始化数据,是一个 State 数据。描述Work被加载初始状态的位姿,也叫做VR的初始视角

      • mode: 模态
      • pano_index: 初始化点位
      • longitude: 相机的水平角
      • latitude: 相机的偏航角
      • fov: 相机垂直方向的可视角度
    • model: 三维模型

      • file_url: 三维模型的资源地址,文件为 .at3d 为如视定制的模型格式
      • material_textures: 三维模型的贴图资源地址
    • panorama: 全景彩色信息

      • list:
        • up / down / left / right / front / back: 全景彩色信息以 cubemap 方式存储和使用。
    • observers: 采集点信息

      • visible_nodes: 采集点之间的可见性列表
      • accessible_nodes: 采集点之间的连通性列表
      • quaternion: 采集点与模型坐标的旋转偏移量
      • standing_position: 采集点地面坐标
      • position: 采集点坐标
      • floor_index: 采集点楼层

    StateFive框架用于描述状态的数据结构。他包含了模态、位于的采集点位、相机的方向、相机可视角度的信息。 您可以使用State来操作Five或者获取Five当前的状态。

    interface State {
    "mode": Five.Mode,
    "panoIndex": number,
    "longitude": number,
    "latitude": number,
    "fov": number,
    "distanace": number,
    "offset": THREE.Vector3,
    }

    State的数据描述

    • mode: 当前的模态 Five 常用有 5 种模态,可以使用 Five.Mode 获得

      • Panorama: 全景游走模态,该模态下视图将在采集点间游走,手势操作可以旋转/放大视角/切换采集点,适合查看采集的全景信息。
      • Floorplan: 空间总览模态, 该模态下视图以模型为中心,手势操作可以旋转/放大模型/切换楼层,适合查看模型的整体效果。
      • Topview: 户型图模态,该模态下视图以模型为中心,垂直俯视模型,手势操作可以平移/放大模型/切换楼层,适合查看模型平面结构。
      • Model: 模型游走模态,该模态下视图将在模型中自由游走,手势操作可以旋转/放大视角/位移,适合查看模型的细节,做一些定位操作。
      • Mapview: 地图模态, 该模态下视图将类似三维地图,手势操作可以旋转/放大视角/位移,适合查看模型的细节。适合展示小区,工厂等较大的模型。
      • VRPanorama: VR 眼镜模态,该模态下可以使用 Cardboard 眼镜 或者他的第三方衍生产品,实现 VR 虚拟显示效果。
      • XRPanorama: XR 眼镜模态,该模态下可以使用头戴显示设备比如 Pico, Meta Quest 等,实现沉浸式体验。
    • panoIndex: 采集点位

    • longitude / latitude: 相机的水平角 / 相机的偏航角(弧度),我们使用类似经纬度的方式描述相机位置。

    • fov: 相机垂直方向的可视角度 (角度)

    • distance: 相机距 offset 的距离

    • offset: 相机看向的目标

    目前涉及到的模型类型 at3d / domez / 3d-tile(b3dm, pnts, glb)

    • world: five.scene 场景下的坐标。属于 view 下的绝对坐标。坐标的上方向是 Y 轴,单位米。
    • local: 单个模型的相对坐标。坐标的上方向是 Y 轴,单位米。 单个模型受到 work.transform 的影响会产生一定的位姿变化进行项目拼接(比如沙盘项目)。这种情况下,会与 world 有一定偏转。
    • enu: 模型描述坐标(East-North-Up)。坐标的上方向是 Z 轴,单位米。需要在算法模型输入/输出时使用这个坐标系。
    • ecef: 模型在地球的坐标系(Earth-centered, Earth-fixed)。坐标的上方向是 Z 轴并且固定是北,单位米。
    • lla: 模型在地球的经纬高度 (Latitude-Longitude-Altitude)。 经纬度单位是弧度,高度单位是米。

    转换:

    • localworld 的转换依赖 work.transform
    • localenu 的转换是固定的 yUp 转 zUp
    • enuecef 依赖 tileset.jsonrootMeta.coordinate.pose_ecef_to_enu / rootMeta.coordinate.pose_enu_to_ecef。 如果缺损,则使用 a=6378137.0;invf=298.257223563 的椭球近似计算
    • lla 通过 a=6378137.0;invf=298.257223563 的椭球近似计算

    椭球近似计算: (enu + lla) 与 ecef 可以相互推导。

    • 在 five 环境下,通过 viewLayer 对象,即 five.models[number].viewLayer[number].scene 转化。提供对应方法。
      • localToWorld(vector: THREE.Vector3): THREE.Vector3
      • worldToLocal(vector: THREE.Vector3): THREE.Vector3
      • localToEnu(vector: THREE.Vector3): THREE.Vector3
      • enuToLocal(vector: THREE.Vector3): THREE.Vector3
      • localToEcef(vector: THREE.Vector3): THREE.Vector3
      • ecefToLocal(vector: THREE.Vector3): THREE.Vector3
      • localToLla(vector: THREE.Vector3): THREE.Vector3
      • llaToLocal(vector: THREE.Vector3): THREE.Vector3
      • worldToEnu(vector: THREE.Vector3): THREE.Vector3
      • enuToWorld(vector: THREE.Vector3): THREE.Vector3
      • worldToEcef(vector: THREE.Vector3): THREE.Vector3
      • ecefToWorld(vector: THREE.Vector3): THREE.Vector3
      • worldToLla(vector: THREE.Vector3): THREE.Vector3
      • llaToWorld(vector: THREE.Vector3): THREE.Vector3

    这些函数均为直接修改传入 vector。 如果要保持原先的数据,请实现 vector.clone()

    通过 intersectRaycaster 方法得到的 Intersectionworld 坐标系下, 并返回对应的 modelviewLayer

    目前约定为,算法的模型输入输出均使用 enu 坐标系。