如视 Five SDK
    Preparing search index...

    Release Note 6.7.x

    6.7.x 版本发布日志

    npm install @realsee/five@6.7
    

    five.load 时,现在可选择追加或者替换。 并且在切换过程中,可以不再发生切换/锁定视角等妨碍用户持续操作的行为。 这方面的改动只要适用于多项目下,项目追加,分批次加载的情况。

    // 替换项目
    // mode: 'replace' 默认
    five.load([parseWork(json1), parseWork(json2)], 'inherit', { mode: 'replace' });

    // 追加项目
    // mode: 'add'
    five.load(parseWork(json2), 'inherit', { mode: 'add' });

    注意事项:

    • Work 的唯一标识依旧是 workCode。 同一场景下,不允许出现两个相同的 workCode 的 Work。如果出现会报错处理。
    • 如果通过 replace 替换的 Work 的 workCode 和当前场景中有一样的(相当于替换一个一样的 Work),则会保留之前的 Work 的模型,直接挂在到新 Work 上,而不是重新加载。
    five.load(parseWork(json), 'inherit', { mode: 'add' });
    

    state=inherit 时,在切换过程中,可以不再发生切换/锁定视角等妨碍用户持续操作的行为。

    • 在模型态:保持当前视角状态
    • 在全景态:如果当前 work 存在则不改变。不存在切换到一个可用的全景点。

    针对大项目,对 work 的 json。做精简优化,减少网络传输时间。并且增加灵活性。

    通过模版的模式匹配减少重复内容。 panoram 中的 hash,index 等参数的重复度很高,对一样的内容可以通过这种方式减少文件长度。

    Before:

    "panorama": {
    "count": 465,
    "list": [
    {
    "index": 0,
    "derived_id": 0,
    "derived_id_str": "auto3d-light-vEY8Zp4lPlkZ7R9K_1735117678",
    "up": "images/cube_2048/0/0fd265355dbb94cb22fb930e52dd3c19/0_u.jpg",
    "down": "images/cube_2048/0/0fd265355dbb94cb22fb930e52dd3c19/0_d.jpg",
    "left": "images/cube_2048/0/0fd265355dbb94cb22fb930e52dd3c19/0_l.jpg",
    "right": "images/cube_2048/0/0fd265355dbb94cb22fb930e52dd3c19/0_r.jpg",
    "front": "images/cube_2048/0/0fd265355dbb94cb22fb930e52dd3c19/0_f.jpg",
    "back": "images/cube_2048/0/0fd265355dbb94cb22fb930e52dd3c19/0_b.jpg",
    "size_list": [ 2048, 4096 ],
    "tiles": [ 1, 2, 3 ],

    },
    {
    "index": 1,
    "derived_id": 0,
    "derived_id_str": "auto3d-light-vEY8Zp4lPlkZ7R9K_1735117799",
    "up": "images/cube_2048/1/a6ca1991fc6bdb2dbd1a1003d9f62394/1_u.jpg",
    "down": "images/cube_2048/1/a6ca1991fc6bdb2dbd1a1003d9f62394/1_d.jpg",
    "left": "images/cube_2048/1/a6ca1991fc6bdb2dbd1a1003d9f62394/1_l.jpg",
    "right": "images/cube_2048/1/a6ca1991fc6bdb2dbd1a1003d9f62394/1_r.jpg",
    "front": "images/cube_2048/1/a6ca1991fc6bdb2dbd1a1003d9f62394/1_f.jpg",
    "back": "images/cube_2048/1/a6ca1991fc6bdb2dbd1a1003d9f62394/1_b.jpg",
    "size_list": [ 2048, 4096 ],
    "tiles": [ 1, 2, 3 ],
    },
    {
    "index": 2,
    "derived_id": 0,
    "derived_id_str": "auto3d-light-vEY8Zp4lPlkZ7R9K_1735117912",
    "up": "images/cube_2048/2/567f94406885bf06f5586d7972da2b5e/2_u.jpg",
    "down": "images/cube_2048/2/567f94406885bf06f5586d7972da2b5e/2_d.jpg",
    "left": "images/cube_2048/2/567f94406885bf06f5586d7972da2b5e/2_l.jpg",
    "right": "images/cube_2048/2/567f94406885bf06f5586d7972da2b5e/2_r.jpg",
    "front": "images/cube_2048/2/567f94406885bf06f5586d7972da2b5e/2_f.jpg",
    "back": "images/cube_2048/2/567f94406885bf06f5586d7972da2b5e/2_b.jpg",
    "size_list": [ 2048, 4096 ],
    "tiles": [ 1, 2, 3 ],
    },
    {
    "index": 3,
    "derived_id": 0,
    "derived_id_str": "auto3d-light-vEY8Zp4lPlkZ7R9K_1735118067",
    "up": "images/cube_2048/3/fa70f0f26594d3023a3824c9a92033da/3_u.jpg",
    "down": "images/cube_2048/3/fa70f0f26594d3023a3824c9a92033da/3_d.jpg",
    "left": "images/cube_2048/3/fa70f0f26594d3023a3824c9a92033da/3_l.jpg",
    "right": "images/cube_2048/3/fa70f0f26594d3023a3824c9a92033da/3_r.jpg",
    "front": "images/cube_2048/3/fa70f0f26594d3023a3824c9a92033da/3_f.jpg",
    "back": "images/cube_2048/3/fa70f0f26594d3023a3824c9a92033da/3_b.jpg",
    "size_list": [ 2048, 4096 ],
    "tiles": [ 1, 2, 3 ],
    },
    ...
    ]
    }

    After:

    "panorama": {
    "count": 465,
    "pattern": {
    "up": "images/cube_2048/{index}/{hash}/{index}_u.jpg",
    "down": "images/cube_2048/{index}/{hash}/{index}_d.jpg",
    "left": "images/cube_2048/{index}/{hash}/{index}_l.jpg",
    "right": "images/cube_2048/{index}/{hash}/{index}_r.jpg",
    "front": "images/cube_2048/{index}/{hash}/{index}_f.jpg",
    "back": "images/cube_2048/{index}/{hash}/{index}_b.jpg",
    "size_list": [ 2048, 4096 ],
    "tiles": [ 1, 2, 3]
    },
    "list": [
    {
    "hash": "0fd265355dbb94cb22fb930e52dd3c19",
    "derived_id": 0,
    "derived_id_str": "auto3d-light-vEY8Zp4lPlkZ7R9K_1735117678",
    "index": 0
    },
    {
    "hash": "a6ca1991fc6bdb2dbd1a1003d9f62394",
    "derived_id": 0,
    "derived_id_str": "auto3d-light-vEY8Zp4lPlkZ7R9K_1735117799",
    "index": 1
    },
    {
    "hash": "567f94406885bf06f5586d7972da2b5e",
    "derived_id": 0,
    "derived_id_str": "auto3d-light-vEY8Zp4lPlkZ7R9K_1735117912",
    "index": 2
    },
    {
    "hash": "fa70f0f26594d3023a3824c9a92033da",
    "derived_id": 0,
    "derived_id_str": "auto3d-light-vEY8Zp4lPlkZ7R9K_1735118067",
    "index": 3
    },
    ...
    ]
    }

    在序列话 Work Json 时。资源的地址,均尝试存储为 base_url 的相对地址,减少存储的开销。

    • 可以通过 work.getURL 获取到完整地址。

      // 获取图片地址
      work.getURL(work.observers[0].image.left);
    • 可以通过修改 work.baseURL= 修改前缀。

    • 现在 accessable_nodes 与 visible_nodes 不再有行为差异。visible_nodes 将废弃。
    • observers[].derived_id 的缺损值不再是 undefiend. 而是 0。
    • observers[].derived_id_str 的缺损值不再是 undefiend. 而是 空字符串。
    • 优化 at3d / pbm 的 material_textures 的参数的各种兼容问题 以及 错误的警告信息。
    • model.coordinate 同 tileeset.rootMeta.coordinate。声明 file_url 的世界坐标。
    • model.up_axis 设置 file_url 模型的上方向, 仅针对 obj / ply 等自身没有上方向定义的模型格式。
    • 通过 work.toJSON() 可以获取到当前序列化后的标准 Work Json。类型为 WorkJson
    • 该方法并不是返回当时 parseWork 时的 Json。 而是从 work 数据中序列化后的结果。
    • 并不包含 _signature certificate 等字段。
    • 优化 对于 avif 格式的 cube 图的处理的效率。
    • 优化 全景图片瓦片的切割参数,该有尽有。
    • 优化 图片的清晰度参数,目前均使用 95 最为图片质量。

    优化 Gltf PBR 材质渲染。 对技术美术输出的模型,更准确的还原。

    • 解决混合底色是白色的问题 从修改 CustomBlending 改为在着色器中处理,所以只有使用 PBM 的材质支持。three 默认材质不处理这个改动。
    • 优化 gltf 骨骼绑定,对于骨骼关联大于 4 的情况,使用前 4 个权重大的骨骼,并归一化。并且考虑通过整形数组 normalize 的情况。
    • 修改 gltf 中对 uv2 copy 的逻辑,添加当检测到有 occlusionTexture 材质时,如果没有 uv2 自动拷贝 uv -> uv2。

    地址: https://vradmin.lianjia.com/gltf/

    • 支持加载 线上 / 本地文件。gltf / glb。
    • 支持链接 单独的 gltf / glb 动画文件。
    • 内置了 gltf 官方测试集。https://github.com/KhronosGroup/glTF-Sample-Assets/
    • 内置多个环境光照,以及上传自定义环境光照 (.exr)。

    扩展 threejs 的 Raycaster。 支持多个自定义参数。

    declare module 'three' {

    export interface Raycaster {
    /**
    * 只捕获第一个交点
    */
    firstHitOnly?: boolean;

    /**
    * 对交点进行筛选
    */
    hitFilter?: (intersect: THREE.Intersection) => boolean;

    /**
    * 作用楼层
    */
    floorIndex?: number;
    }

    }
    • firstHitOnly - 只捕获第一个交点。比获取全部取第一个更快获取到结果。
    • hitFilter - 过滤函数,可以根据逻辑否绝一些交点。配合 firstHitOnly 可以更加匹配业务需求。
    • floorIndex - 过滤楼层。默认为当前显示楼层,-1 为所有楼层。其他数字则定向对应的楼层。

    同时一些内部逻辑变化

    • 内置事件生成的 Raycaster。均设置 firstHitOnly = true。
    • 交点获取,内置过滤掉了 模型裁剪 clippers 中的内容。

    目的是通过有限的内存,获取到最清晰的模型效果。

    // 设置内存最高缓存到 512 MB
    five.modelScene.parameter.set('maxMemoryUsage', 512);

    // 设置 maxScreenSpaceError 到 32
    five.modelScene.parameter.set('maxScreenSpaceError', 32);

    // 设置通过内存上限动态调整 maxScreenSpaceError
    five.modelScene.parameter.set('memoryAdjustedScreenSpaceError', true);

    当设置的 maxScreenSpaceError 已经全部加载完毕后,发现内存空间仍有剩余。则会尝试降低 maxScreenSpaceError 知道内存大体到达 maxMemoryUsage 设置的水平。

    • 如果设置的 maxScreenSpaceError 已经全部加载完毕后,内存已经大于 maxMemoryUsage 设置的水平则不会变化。
    • 因为是动态尝试, 所以悲观情况下会出现在 maxMemoryUsage 附近摆动的情况。导致模型反复加载/销毁。
    • 只针对 layer 生效。多个 layer 是单独计算,并不是综合计算。

    通过过渡到模型实现点位游走效果

    five.moveToPano(0, {
    effect: 'model',
    });

    目前支持:

    • fly - 通过相机移动方式变化
    • instant - 直接变化
    • fade - 通过渐变方式变化
    • montage - 通过渐变穿插到黑屏方式变化
    • spread - 通过扩散方式变化
    • zoomin - 通过放大变化
    • zoomout - 通过缩小变化
    • model - 通过过度到模型
    function easeInQuad(x: number): number {
    return x * x;
    };

    five.moveToPano({
    workCode: "axv2ZQMaKZcMl5Bc6x",
    panoIndex: 51,
    }, {
    latitude: 0.5314685806864204,
    longitude: 4.324187623631265,
    fov: 90,
    effectEasing: easeInQuad
    })
    • effectEasing 生命一个函数,接受一个 0 到 1 的数字, 返回一个 0 到 1 的数字。
    • 当值为 0 时显示前一个全景图。 为 1 时显示后一个全景图。 中间数值为两个全景图的混合, 数值表示混合比例。
    • 用于 地面-天空 等切换切换占比差异较大的情况下单独设置。

    默认逻辑为:

    const five = new Five({
    panorama: {
    aerialObserverMinHeight: 5,
    panoCircleMeshCreator: (observer, options) => {
    const distance = observer.position.distanceTo(observer.standingPosition);
    if (distance > options.aerialObserverMinHeight) {
    return new PanoCircleMeshSolid();
    } else {
    return new PanoCircleMesh();
    }
    },
    }
    }
    • 如果距地大于 5 米的点位为航拍点。
    • 如果是航拍点,则使用 PanoCircleMeshSolid, 否则使用 PanoCircleMesh。
    • 内部逻辑。航拍点会面向相机展示。

    业务可以修改或介入这个逻辑。

    重写了渲染相关的逻辑。将 scene-renderer 和 postprocessing 分开

    • scene-renderer 场景的渲染相关,需要多次渲染场景采样比如抗锯齿(aa),或者对场景内容改变,必须点云的点融合等。
    • postprocessing 后处理,将 scene-renderer 的结果通过多次处理,比如轮廓增强,调整亮度等,将最终处理后的结果显示到画布上。
    • scene-renderer - 直接渲染
    • point-cloud-high-quality-scene-renderer - 点云融合渲染
    • ssaa-scene-renderer - SSAA算法的抗锯齿渲染
    // 通过 renderMode 切换

    // 直接渲染
    five.renderMode = 'default';

    // 点云融合渲染
    five.renderMode = 'point-cloud-high-quality';

    // SSAA算法的抗锯齿渲染
    five.renderMode = 'ssaa';
    • adaptive-luminance-pass - 屏幕空间动态亮度
    • eye-dome-lighting-pass - 轮廓增强
    // 开启 eye-dome-lighting-pass
    five.enableEDL = true;

    // 开启 adaptive-luminance-pass
    five.enableAdaptiveLuminance = true;

    后处理支持 THREE 对于 后处理 Pass 的定义。可以自定义追加。

    注意:目前不支持 mask 模版剔除部分的逻辑。


    interface Pass {
    enabled: boolean;
    needsSwap: boolean;
    clear: boolean;
    renderToScreen: boolean;
    setSize(width: number, height: number): void;
    render(
    renderer: THREE.WebGLRenderer,
    writeBuffer: THREE.WebGLRenderTarget,
    readBuffer: THREE.WebGLRenderTarget,
    deltaTime?: number,
    maskActive?: boolean
    ): void;
    }

    const myPass: Pass = ...;

    this.fiveRenderer.composer.addPass(myPass)
    • 不再使用分层渲染。enableLayeringRendering 参数废弃。
    • 修复 涉嫌计算 intersectRaycaster, 如果 origin 离得太近会出现取不到的问题,优化 bvhbox 的距离判断逻辑。
    • 优化近处点云碰撞时,规避掉角度大 distanceToRay / distance > 0.07 的点云。
    • 修复多个 five 实例间,共用同一个 work 时 proxy 指向错误 five 实例的问题。
    • 修复 mesh 模型 material.vertexMarks 没有同步 parameterValue.vertexMarks 的问题