cesium集成threejs
index.html
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cesium and Three.js Integration</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div id="three"></div>
<div id="cesium"></div>
<script type="module" src="src/main.ts"></script>
</body>
</html>
style.css
css
html,
body {
width: 100%;
height: 100%;
overflow: hidden;
}
#cesium {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
}
#three {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
pointer-events: none;
}
main.ts
ts
import * as Cesium from "cesium";
import * as THREE from 'three';
import {createColoredCube} from "./cube";
import Stats from 'stats.js'
import airlines from './airlines.json'
interface AirlinePoint {
latitude: number,
longitude: number,
height: number
}
const stats = new Stats()
stats.showPanel(0) // 0: fps, 1: ms, 2: mb, 3+: custom
document.body.appendChild(stats.dom)
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIwM2E2NmM4MC05NjdjLTQ2OTMtYWE2My1hODgwNjY3ZTExZTgiLCJpZCI6MzEzMTMsInNjb3BlcyI6WyJhc2wiLCJhc3IiLCJhc3ciLCJnYyIsInByIl0sImlhdCI6MTU5NTIzNzM1Mn0.K4-n5E9TZOEPpkGLwfIQibplnnU88PfrahgHrrrqRDk'
const location = {
lon: 120.2,
lat: 29.374215639751842,
height: 5000
};
const position = Cesium.Cartesian3.fromDegrees(location.lon, location.lat, location.height);
// CesiumJS
const cesiumViewer = new Cesium.Viewer("cesium", {
// terrainProvider: await Cesium.createWorldTerrainAsync(),
// useDefaultRenderLoop: false,
skyBox: false,
baseLayerPicker: false,
geocoder: false,
sceneModePicker: false,
animation: false,
timeline: false,
navigationHelpButton: false,
});
cesiumViewer.scene.debugShowFramesPerSecond = true;
const osmBuildings = await Cesium.createOsmBuildingsAsync();
cesiumViewer.scene.primitives.add(osmBuildings);
// Three.js
const threeContainer = document.getElementById("three");
const threeScene = new THREE.Scene();
const threeCamera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 50000000);
const threeRenderer = new THREE.WebGLRenderer({alpha: true});
threeRenderer.setSize(window.innerWidth, window.innerHeight);
threeContainer?.appendChild(threeRenderer.domElement);
var aLight = new THREE.AmbientLight(0xffffff, 0.3);
var dLight = new THREE.DirectionalLight(0xffffff, 1);
dLight.position.set(1000, -100, 900);
threeScene.add(dLight);
threeScene.add(aLight);
const axesHelper = new THREE.AxesHelper(50000000);
threeScene.add(axesHelper);
// Create a cube in Three.js and add it to the scene
const cube = createColoredCube();
cube.position.set(position.x, position.y, position.z);
threeScene.add(cube)
const box = new THREE.Box3();
box.setFromCenterAndSize(new THREE.Vector3(position.x, position.y, position.z), new THREE.Vector3(1000, 1000, 1000));
const helper = new THREE.Box3Helper(box, 0xffff00);
threeScene.add(helper);
const material = new THREE.MeshLambertMaterial({color: '#65EEEF', wireframe: true, transparent: true, opacity: 0.36})
const curve = new THREE.CatmullRomCurve3((airlines as AirlinePoint[]).map(point => {
const degrees = Cesium.Cartesian3.fromDegrees(point.longitude, point.latitude, point.height)
console.log('>>>:', degrees.x, degrees.y, degrees.z)
return new THREE.Vector3(degrees.x, degrees.y, degrees.z)
}))
const geometry = new THREE.TubeGeometry(curve, 20, 20, 30, false)
const mesh = new THREE.Mesh(geometry, material)
threeScene.add(mesh)
// Direct the Cesium camera to look at the cube
// cesiumViewer.camera.lookAt(position, new Cesium.Cartesian3(200.0, 500.0, 300.0));
// cesiumViewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
cesiumViewer.camera.flyTo({
destination: position,
orientation: {
heading: 6.283185307179586,
pitch: -0.8004940871228587,
roll: 0.0
},
})
function updateThreeJS() {
// Update Three.js camera field of view to match Cesium camera's vertical FOV
threeCamera.fov = Cesium.Math.toDegrees(cesiumViewer.camera.frustum.fovy);
threeCamera.updateProjectionMatrix();
// Sync Three.js camera with Cesium camera
const cesiumCamera = cesiumViewer.camera;
const cvm = cesiumCamera.viewMatrix;
const civm = cesiumCamera.inverseViewMatrix;
// Fix the extraction of camera position and direction from matrices
const cameraPosition = Cesium.Cartesian3.fromElements(civm[12], civm[13], civm[14]);
const cameraDirection = new Cesium.Cartesian3(-cvm[2], -cvm[6], -cvm[10]);
const cameraUp = new Cesium.Cartesian3(cvm[1], cvm[5], cvm[9]);
const cameraPositionVec3 = new THREE.Vector3(cameraPosition.x, cameraPosition.y, cameraPosition.z);
const cameraDirectionVec3 = new THREE.Vector3(cameraDirection.x, cameraDirection.y, cameraDirection.z);
const cameraUpVec3 = new THREE.Vector3(cameraUp.x, cameraUp.y, cameraUp.z);
// Update Three.js camera position and orientation
threeCamera.position.copy(cameraPositionVec3);
threeCamera.up.copy(cameraUpVec3);
threeCamera.lookAt(cameraPositionVec3.clone().add(cameraDirectionVec3));
// Apply rotation to the cube
cube.rotation.x += 0.01;
// Render the scene with the updated camera
threeRenderer.render(threeScene, threeCamera);
};
// Handle window resizing
window.addEventListener('resize', () => {
const width = window.innerWidth;
const height = window.innerHeight;
threeRenderer.setSize(width, height);
threeCamera.aspect = width / height;
threeCamera.updateProjectionMatrix();
});
function renderLoop() {
requestAnimationFrame(renderLoop);
cesiumViewer.render();
updateThreeJS();
stats.begin();
// monitored code goes here
stats.end();
}
renderLoop();
cube.ts
ts
import * as THREE from 'three';
function createColoredCube() {
const size = 500;
const geometry = new THREE.BoxGeometry(size, size, size);
const materials = [
new THREE.MeshBasicMaterial({ color: 0xff0000 }), // Right face - Red
new THREE.MeshBasicMaterial({ color: 0x00ff00 }), // Left face - Green
new THREE.MeshBasicMaterial({ color: 0x0000ff }), // Top face - Blue
new THREE.MeshBasicMaterial({ color: 0xffff00 }), // Bottom face - Yellow
new THREE.MeshBasicMaterial({ color: 0x00ffff }), // Front face - Cyan
new THREE.MeshBasicMaterial({ color: 0xff00ff }) // Back face - Magenta
];
return new THREE.Mesh(geometry, materials);
};
export { createColoredCube };
airlines.json
json
[
{
"latitude": 30.29172919,
"longitude": 119.99546607,
"height": 0.0
},
{
"latitude": 30.29168269,
"longitude": 119.99526509,
"height": 65.0
},
{
"latitude": 30.29163619,
"longitude": 119.99506411,
"height": 65.0
},
{
"latitude": 30.2910048065,
"longitude": 119.9943008165,
"height": 65.0
},
{
"latitude": 30.2890523389,
"longitude": 119.9882997268,
"height": 100.0
},
{
"latitude": 30.2871316182,
"longitude": 119.9827192549,
"height": 100.0
},
{
"latitude": 30.2862897497,
"longitude": 119.9811652701,
"height": 90.0
},
{
"latitude": 30.2815104627,
"longitude": 119.9798140691,
"height": 62.0
},
{
"latitude": 30.2786136171,
"longitude": 119.9802778146,
"height": 50.0
},
{
"latitude": 30.2783176832,
"longitude": 119.9810727747,
"height": 50.0
},
{
"latitude": 30.27827,
"longitude": 119.98126791,
"height": 50.0
},
{
"latitude": 30.27827,
"longitude": 119.98147596,
"height": 50.0
},
{
"latitude": 30.27827,
"longitude": 119.981684,
"height": 0.0
}
]
最终效果

