BIM轻量化之路(四)-模型优化

一、模型居中

上文加载模型后发现threejs的原点对应的是revit的项目基点,这样导致初始加载后左右拖动建筑是围绕Y旋转,体验很差,所以模型初始化时候模型居中、旋转,代码如下:

    function setCenter() {
        var box3 = new THREE.Box3();
		// 计算层级模型group的包围盒
		// 模型group是加载一个三维模型返回的对象,包含多个网格模型
		//扩展此包围盒的边界,使得对象及其子对象在包围盒内,包括对象和子对象的世界坐标的变换。
        box3.expandByObject(scene);
        var center = new THREE.Vector3(0, 0, 0);
		// 计算一个层级模型对应包围盒的几何体中心在世界坐标中的位置
        box3.getCenter(center);
        console.log('查看几何体中心坐标', center);
        console.log('坐标', scene.position);
		// 重新设置模型的位置,使之居中。
        scene.position.x = scene.position.x - center.x
        scene.position.y = scene.position.y - center.y
        scene.position.z = scene.position.z - center.z;
        console.log('坐标', scene.position);
    }

原理是将场景放入到box中,拓展包围盒与场景的大小一致,然后通过包围盒居中的坐标计算后将场景居中。
如果想和revit展示一致,需要对模型进行180度的旋转,因为revit和threejs的坐标系表示不同,左手坐标系和右手坐标系。
在这里插入图片描述

gLTFLoader.load(url, function(obj) {
        obj.scene.rotateY(Math.PI);//旋转180度
        .....
   }, onProgress);``

二、z-fighting 问题

加载的模型有些叠加的部分随着摄像机的拉动会闪烁,如图:
在这里插入图片描述
查询资料是因为叠加部分的mesh共用了一个深度值,渲染器不知道该渲染那个导致闪烁,这便是Z-Fighting问题,相关问题的详细说明:
https://www.cnblogs.com/lst619247/p/9098845.html

 this.renderer = new THREE.WebGLRenderer({
        canvas: document.getElementById("canvas-model-view"),
        antialias: true, //设置抗锯齿
        alpha: true, //背景透明
        autoClear: true,
        logarithmicDepthBuffer: true
    });

需要将logarithmicDepthBuffer参数设为true即可

二、平滑移动

要想使摄像机平滑移动至某一点,需要贝塞尔曲线,贝塞尔曲线通过很少的控制点,去生成复杂的平滑曲线,通过获取到了曲线上的点来移动摄像机从而达到平滑移动的效果,threejs提供了CubicBezierCurve3方法来实现贝塞尔曲线。

function toPosition(targetX,targetY,targetZ){
    //获取当前camera位置
    let camPosition=viewer.camera.position;         //获取摄像机当前位置
    let newPosition=new THREE.Vertex(targetX,targetY,targetZ);     //设置目标位置
    let curve=addLines(camPosition,newPosition).curve;    //绘制贝塞尔曲线
    //取curve的10个点
    let points=curve.getPoints(10);
    let index=0;
    //摄像机每50毫秒移动一个点的位置
    let a=setInterval(function () {
        viewer.camera.position.set(points[index].x,points[index].y,points[index].z);
        viewer.camera.lookAt(new THREE.Vertex(0,0,0))
        index++;
        viewer.render();
        if(index>10){
            clearInterval(a);
        }
    },50);
}
// 添加线条
function addLines(v0, v3) {
    // 计算向量夹角
    let angle = v0.angleTo(v3) * 270 / Math.PI / 10; // 0 ~ Math.PI
    let aLen = angle * 50,
        hLen = angle * angle * 120;
    let p0 = new THREE.Vector3(0, 0, 0);
    // 开始,结束点
    // let v0 = groupDots.firstObjectren[0].position;
    // let v3 = groupDots.children[1].position;
    // 法线向量
    let rayLine = new THREE.Ray(p0, getVCenter(v0.clone(), v3.clone()));
    // 顶点坐标
    let vtop = rayLine.at(hLen / rayLine.at(1).distanceTo(p0));
    // 控制点坐标
    let v1 = getLenVcetor(v0.clone(), vtop, aLen);
    let v2 = getLenVcetor(v3.clone(), vtop, aLen);
    // 绘制贝塞尔曲线
    let curve = new THREE.CubicBezierCurve3(v0, v1, v2, v3);
    let geo = new THREE.Geometry();
    geo.vertices = curve.getPoints(10);
    let mat = new THREE.LineBasicMaterial({color: 0xff0000});
    return {
        curve: curve,
        lineMesh: new THREE.Line(geo, mat)
    };
}
// 计算v1,v2 的中点
function getVCenter(v1, v2) {
    let v = v1.add(v2);
    return v.divideScalar(2);
}

// 计算V1,V2向量固定长度的点
function getLenVcetor(v1, v2, len) {
    let v1v2Len = v1.distanceTo(v2);
    return v1.lerp(v2, len / v1v2Len);
}

效果如下:
在这里插入图片描述

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值