zoukankan      html  css  js  c++  java
  • 最新版cesium集成threejs

    最新版cesium集成three.js

    简介

    之前三维加载模型都是加载 glb 或者 gltf,模型不好找,一般需要定制,因此领导想加载 threejs的模型。

    按照官方示例(吐槽:2017年的示例 ,代码存在诸多问题,而且版本太老)。

    官方地址Integrating Cesium with Three.js

    githup地址cesium-threejs-experiment

    尝试了很多遍,无法加载模型;githup项目无法运行。

    后来在搜索到一篇博客,修改之后可以加载模型,但是模型没有添加到地球在中,经过修改,完成地球加载three模型,并且同步。

    完整代码

    基本上是参照官方示例,和大神博客来完成的。自己修改部分主要是:

    cesium初始化增加底图、three初始化修改容器
    同步cesium画布和three画布位置,画布叠加在一起
    解决cesium初始化找不到容器的问题
    增加立方体模型

    使用版本

    cesium 1.88 (目前最新版)
    thee.js r135 (目前最新版)
    在这里插入图片描述
    ---------------------------------------------------------------------------------------------------------------------------
    在这里插入图片描述

    html 代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="utf-8">
    	<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    	<meta name="viewport"
    		  content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
    	<title>Cesium integrate Threejs</title>
    	<!--cesium样式-->
    	<link rel="stylesheet" href="./Widgets/widgets.css">
    	<!--cesium-->
    	<script src="./Cesium.js"></script>
    	<!--three-->
    	<script src="./threejs/three.js"></script>
        <style>
    		/*设置cesium和three的画布位置*/
            .container-integrate canvas {
                position: absolute;
                top: 0;
            }
    		/*three画布禁止鼠标操作*/
            .container-integrate canvas:nth-child(3) {
                pointer-events: none;
    
            }
        </style>
    </head>
    
    <body onload="pageload()">
    
    <div class="container-integrate" style="">
    	<!--cesium容器-->
        <div id="cesiumContainer" style="height: 800px; 100%;"></div>
    </div>
    
    

    JavaScript代码

    
    // three对象
    let three = {
        renderer: null,
        camera: null,
        scene: null
    };
    
    //cesium对象
    let cesium = {
        viewer: null
    };
    
    function pageload() {
    
        // 模型定位范围
        let minWGS84 = [115.56936458615716, 39.284100766866445];
        let maxWGS84 = [117.10745052365716, 41.107831235616445];
    
        // cesium 容器
        let cesiumContainer = document.getElementById("cesiumContainer");
        let _3Dobjects = []; //Could be any Three.js object mesh
    
        // three对象
        function _3DObject() {
            //THREEJS 3DObject.mesh
            this.threeMesh = null;
            //location bounding box
            this.minWGS84 = null;
            this.maxWGS84 = null;
        }
    
        // 初始化地球
        function initCesium() {
            cesium.viewer = new Cesium.Viewer(cesiumContainer, {
    
                useDefaultRenderLoop: false,
                selectionIndicator: false,
                homeButton: false,
                sceneModePicker: false,
                infoBox: false,
                navigationHelpButton: false,
                navigationInstructionsInitiallyVisible: false,
                animation: false,
                timeline: false,
                fullscreenButton: false,
                allowTextureFilterAnisotropic: false,
                baseLayerPicker: false,
    
                contextOptions: {
                    webgl: {
                        alpha: false,
                        antialias: true,
                        preserveDrawingBuffer: true,
                        failIfMajorPerformanceCaveat: false,
                        depth: true,
                        stencil: false,
                        anialias: false
                    },
                },
    
                targetFrameRate: 60,
                resolutionScale: 0.1,
                orderIndependentTranslucency: true,
                //加载底图
                imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
                    url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer",
                }),
                geocoder: false,
                automaticallyTrackDataSourceClocks: false,
                // creditContainer : "hidecredit", //注意:这里需要注释掉,否则会报找不到容器的问题
                dataSources: null,
                clock: null,
                terrainShadows: Cesium.ShadowMode.DISABLED
            });
            let center = Cesium.Cartesian3.fromDegrees(
                (minWGS84[0] + maxWGS84[0]) / 2,
                ((minWGS84[1] + maxWGS84[1]) / 2) - 1,
                200000
            );
            cesium.viewer.camera.flyTo({
                destination: center,
                orientation: {
                    heading: Cesium.Math.toRadians(0),
                    pitch: Cesium.Math.toRadians(-60),
                    roll: Cesium.Math.toRadians(0)
                },
                duration: 3
            });
        }
    
        //初始化three
        function initThree() {
            let fov = 45;
            let width = window.innerWidth;
            let height = window.innerHeight;
            let aspect = width / height;
            let near = 1;
            let far = 10 * 1000 * 1000;
            three.scene = new THREE.Scene();
            three.camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
            three.renderer = new THREE.WebGLRenderer({alpha: true});
            let Amlight = new THREE.AmbientLight(0xffffff, 2);
            three.scene.add(Amlight);
            // 注意这里,直接把three容器(canvas 添加到 cesium中,在cesium的canvas之下),
            // 这样的话,两个canvas才会重叠起来。
            cesium.viewer.cesiumWidget.canvas.parentElement.appendChild(three.renderer.domElement);
            // ThreeContainer.appendChild(three.renderer.domElement);
        }
    
        //创建 cesium 图形,跟three无关
        function createPolygon() {
            let entity = {
                name: 'Polygon',
                polygon: {
                    hierarchy: Cesium.Cartesian3.fromDegreesArray([
                        minWGS84[0], minWGS84[1],
                        maxWGS84[0], minWGS84[1],
                        maxWGS84[0], maxWGS84[1],
                        minWGS84[0], maxWGS84[1],
                    ]),
                    material: Cesium.Color.BLUE.withAlpha(0.4)
                }
            };
            let Polygon = cesium.viewer.entities.add(entity);
        }
    
        // 加载three模型
        function getModel(geometry) {
            geometry = new THREE.DodecahedronGeometry();
            const material = new THREE.MeshBasicMaterial({color: 0x0000ff});
            let dodecahedronMesh = new THREE.Mesh(geometry, material);
            // let dodecahedronMesh = new THREE.Mesh(geometry, new THREE.MeshNormalMaterial());
            dodecahedronMesh.scale.set(5000, 5000, 5000); //scale object to be visible at planet scale
            dodecahedronMesh.position.z += 25000.0; // translate "up" in Three.js space so the "bottom" of the mesh is the handle
            dodecahedronMesh.rotation.x = Math.PI / 2; // rotate mesh for Cesium's Y-up system
            let dodecahedronMeshYup = new THREE.Group();
            dodecahedronMeshYup.add(dodecahedronMesh)
            three.scene.add(dodecahedronMeshYup); // don’t forget to add it to the Three.js scene manually
            //Assign Three.js object mesh to our object array
            let _3DOB = new _3DObject();
            _3DOB.threeMesh = dodecahedronMeshYup;
            _3DOB.minWGS84 = minWGS84;
            _3DOB.maxWGS84 = maxWGS84;
            _3Dobjects.push(_3DOB);
        }
    
        // 加载three立方体模型
        function cube() {
            const geometry = new THREE.BoxGeometry();
            const material = new THREE.MeshBasicMaterial({color: 0x00ff00});
            const dodecahedronMesh = new THREE.Mesh(geometry, material);
            dodecahedronMesh.scale.set(15000, 15000, 15000); //scale object to be visible at planet scale
            dodecahedronMesh.position.z += 7000.0; // translate "up" in Three.js space so the "bottom" of the mesh is the handle
            dodecahedronMesh.rotation.x = Math.PI / 2; // rotate mesh for Cesium's Y-up system
            let dodecahedronMeshYup = new THREE.Group();
            dodecahedronMeshYup.add(dodecahedronMesh)
            three.scene.add(dodecahedronMeshYup); // don’t forget to add it to the Three.js scene manually
            //Assign Three.js object mesh to our object array
            let _3DOB = new _3DObject();
            _3DOB.threeMesh = dodecahedronMeshYup;
            _3DOB.minWGS84 = minWGS84;
            _3DOB.maxWGS84 = maxWGS84;
            _3Dobjects.push(_3DOB);
        }
    
        // 创建three 对象
        function createThreeObject() {
            getModel();
            cube();
        }
    
        // 初始化模型
        function init3DObject() {
            //Cesium entity
            createPolygon()
            //Three.js Objects
            createThreeObject()
        }
    
        // cesium 渲染
        function renderCesium() {
            cesium.viewer.render();
        }
    
        function renderThreeObj() {
    
            // register Three.js scene with Cesium
            three.camera.fov = Cesium.Math.toDegrees(cesium.viewer.camera.frustum.fovy) // ThreeJS FOV is vertical
            //three.camera.updateProjectionMatrix();
            let cartToVec = function (cart) {
                return new THREE.Vector3(cart.x, cart.y, cart.z);
            };
    
            // Configure Three.js meshes to stand against globe center position up direction
            for (let id in _3Dobjects) {
                minWGS84 = _3Dobjects[id].minWGS84;
                maxWGS84 = _3Dobjects[id].maxWGS84;
                // convert lat/long center position to Cartesian3
                let center = Cesium.Cartesian3.fromDegrees((minWGS84[0] + maxWGS84[0]) / 2, (minWGS84[1] + maxWGS84[1]) / 2);
                // get forward direction for orienting model
                let centerHigh = Cesium.Cartesian3.fromDegrees((minWGS84[0] + maxWGS84[0]) / 2, (minWGS84[1] + maxWGS84[1]) / 2, 1);
                // use direction from bottom left to top left as up-vector
                let bottomLeft = cartToVec(Cesium.Cartesian3.fromDegrees(minWGS84[0], minWGS84[1]));
                let topLeft = cartToVec(Cesium.Cartesian3.fromDegrees(minWGS84[0], maxWGS84[1]));
                let latDir = new THREE.Vector3().subVectors(bottomLeft, topLeft).normalize();
                // configure entity position and orientation
                _3Dobjects[id].threeMesh.position.copy(center);
                _3Dobjects[id].threeMesh.lookAt(centerHigh.x, centerHigh.y, centerHigh.z);
                _3Dobjects[id].threeMesh.up.copy(latDir);
            }
            // Clone Cesium Camera projection position so the
            // Three.js Object will appear to be at the same place as above the Cesium Globe
            three.camera.matrixAutoUpdate = false;
            let cvm = cesium.viewer.camera.viewMatrix;
            let civm = cesium.viewer.camera.inverseViewMatrix;
    
            // 注意这里,经大神博客得知,three高版本这行代码需要放在 three.camera.matrixWorld 之前
            three.camera.lookAt(0, 0, 0);
    
            three.camera.matrixWorld.set(
                civm[0], civm[4], civm[8], civm[12],
                civm[1], civm[5], civm[9], civm[13],
                civm[2], civm[6], civm[10], civm[14],
                civm[3], civm[7], civm[11], civm[15]
            );
    
            three.camera.matrixWorldInverse.set(
                cvm[0], cvm[4], cvm[8], cvm[12],
                cvm[1], cvm[5], cvm[9], cvm[13],
                cvm[2], cvm[6], cvm[10], cvm[14],
                cvm[3], cvm[7], cvm[11], cvm[15]
            );
    
            // 设置three宽高
            let width = cesiumContainer.clientWidth;
            let height = cesiumContainer.clientHeight;
    
            let aspect = width / height;
            three.camera.aspect = aspect;
            three.camera.updateProjectionMatrix();
            three.renderer.setSize(width, height);
            three.renderer.clear();
            three.renderer.render(three.scene, three.camera);
        }
    
        // 同步
        function loop() {
            requestAnimationFrame(loop);
            renderCesium();
            renderThreeObj();
        }
    
        initCesium(); // Initialize Cesium renderer
        initThree(); // Initialize Three.js renderer
        init3DObject(); // Initialize Three.js object mesh with Cesium Cartesian coordinate system
        loop(); // Looping renderer
    }
    
    
    

    实现效果

    在这里插入图片描述

    项目在线示例

    在线示例,可以直接扒代码在本地运行

    参考博客:

    cesium与three.js 结合的栗子,结合了一下网友们的栗子,解决了three.js 高版本模型出不来的问题
    cesium+threejs结合实现GIS+BIM大场景-2

    本文转自 https://blog.csdn.net/linzi19900517/article/details/121792022?spm=1001.2014.3001.5501,如有侵权,请联系删除。

  • 相关阅读:
    webrtc源码分析-视频发送流程
    webrtc源码分析-Api接口
    webrtc源码分析-线程任务管理
    webrtc源码分析- jitter delay计算详解
    傅里叶变换
    从贝叶斯到卡尔曼滤波
    sql---case...when...
    python---collections模块记录(defaultdict, namedtuple, ChainMap)
    宏判断是否为Excel打开,若不是则关闭表格
    Golang混淆
  • 原文地址:https://www.cnblogs.com/hustshu/p/15689937.html
Copyright © 2011-2022 走看看