原帖:https://blog.csdn.net/zhishiqu/article/details/79077883
这篇帖子讲述了如何将cesium和threejs结合,但是如果跟着代码敲一遍,会发现并不能加载出threejs的模型。仔细跟着写了编,把遇到的坑做一下说明。
1.要注意threejs的版本。文中所用为r87版的threejs,尝试换成r92,r103,都找不到模型,这个问题后续再探究一下是为什么。
2.代码中涉及很多的cesium中js的引用,cesium中的文件尽量要齐全。
3.关于three的模型在cesium中的位置变幻:
文中设置了一个最大坐标和最小坐标,位置如图:
function _3DObject(){
//THREEJS 3DObject.mesh
this.threeMesh = null;
//location bounding box
this.minWGS84 = null;
this.maxWGS84 = null;
}
var minWGS84 = [115.23,39.55];
var maxWGS84 = [116.23,41.55];
//位置变换
for(var id in _3Dobjects){
minWGS84 = _3Dobjects[id].minWGS84;
maxWGS84 = _3Dobjects[id].maxWGS84;
// convert lat/long center position to Cartesian3
var center = CesiumCartesian3.fromDegrees(116.39,39.9); //设置模型的插入点经纬度
// get forward direction for orienting model
var centerHigh = CesiumCartesian3.fromDegrees(116.39,39.9,1); //设置插入点向上的向量
// use direction from bottom left to top left as up-vector
var bottomLeft = cartToVec(CesiumCartesian3.fromDegrees(minWGS84[0], minWGS84[1]));
var topLeft = cartToVec(CesiumCartesian3.fromDegrees(minWGS84[0], maxWGS84[1]));
var latDir = new THREE.Vector3().subVectors(bottomLeft,topLeft ).normalize(); //设置y轴应该的指向
// configure entity position and orientation
// _3Dobjects[id].threeMesh.position.copy(center);
_3Dobjects[id].threeMesh.lookAt(centerHigh); //模型的朝向
_3Dobjects[id].threeMesh.up.copy(latDir); //指定y轴的朝向
}
位置变换前three的坐标系如图(红色为x轴,绿色为y轴,蓝色为z轴):
进行位置变化后:
4.关于自己的模型变黑:加载帖子中的两个自建模型,颜色是很明显的彩色,如图所示:
加载其他自建模型或其他导入的模型,则是如图:
原因是threejs渲染器中并没有加灯光进去,加上灯光就好了。至于为什么原贴中是有颜色的,等再看看再做解答。
(与原文中的位置有偏差是因为重新设置了模型的经纬度,放置在了北京正中心)。
附源码
var Cesium = {};
define([
'Cesium/Core/Cartesian3',
'Cesium/Widgets/Viewer/Viewer',
'Cesium/Scene/ShadowMode',
'Cesium/Core/Color',
'Cesium/Core/Math',
'Three/three.min',
], function(
CesiumCartesian3,
CesiumViewer,
CesiumShadowMode,
CesiumColor,
CesiumMath,
// CesiumUrlTemplateImageryProvider,
THREE) {
'use strict';
var loadingIndicator = document.getElementById('loadingIndicator');
loadingIndicator.style.display = 'none';
// boundaries in WGS84 around the object
var minWGS84 = [115.23,39.55];
var maxWGS84 = [116.23,41.55];
var cesiumContainer = document.getElementById("cesiumContainer");
var ThreeContainer = document.getElementById("ThreeContainer");
var _3Dobjects = []; //Could be any Three.js object mesh
var three = {
renderer: null,
camera: null,
scene: null
};
var cesium = {
viewer: null
};
function _3DObject(){
//THREEJS 3DObject.mesh
this.threeMesh = null;
//location bounding box
this.minWGS84 = null;
this.maxWGS84 = null;
}
function initCesium(){
cesium.viewer = new CesiumViewer(cesiumContainer,{
useDefaultRenderLoop: false,
selectionIndicator : false,
homeButton:false,
sceneModePicker:false,
infoBox : false,
navigationHelpButton:false,
navigationInstructionsInitiallyVisible:false,
animation : false,
timeline : false,
fullscreenButton : false,
allowTextureFilterAnisotropic: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 : googlemap,
baseLayerPicker : true,
geocoder : false,
automaticallyTrackDataSourceClocks: false,
dataSources: null,
clock: null,
terrainShadows: CesiumShadowMode.DISABLED
});
var center = CesiumCartesian3.fromDegrees(
(minWGS84[0] + maxWGS84[0]) / 2,
((minWGS84[1] + maxWGS84[1]) / 2)-1,
200000
);
cesium.viewer.camera.flyTo({
destination :center,
orientation : {
heading : CesiumMath.toRadians(0),
pitch : CesiumMath.toRadians(-60),
roll : CesiumMath.toRadians(0)
},
duration: 3
});
}
function initThree(){
var fov = 45;
var width = window.innerWidth;
var height = window.innerHeight;
var aspect = width / height;
var near = 1;
var 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});
var Amlight=new THREE.AmbientLight(0xffffff,2);
// three.scene.add(Amlight);
ThreeContainer.appendChild(three.renderer.domElement);
}
function init3DObject(){
//Cesium entity
var entity = {
name : 'Polygon',
polygon : {
hierarchy : CesiumCartesian3.fromDegreesArray([
minWGS84[0], minWGS84[1],
maxWGS84[0], minWGS84[1],
maxWGS84[0], maxWGS84[1],
minWGS84[0], maxWGS84[1],
]),
material : CesiumColor.RED.withAlpha(0.2)
}
};
var Polygon = cesium.viewer.entities.add(entity);
//Three.js Objects
// Lathe geometry
//加载json
var loader = new THREE.ObjectLoader();
var mesh = [];
loader.load('./Model/model-a2-1.json', function (obj) {
obj.scale.x = obj.scale.y = obj.scale.z =1;
mesh.push(obj);
three.scene.add(obj); //加载外部json
obj.castShadow = true;
obj.name="121";
var position=new CesiumCartesian3.fromDegrees(116.39,39.9,0);
obj.position.set(position.x,position.y,position.z);
var _3DOB = new _3DObject();
_3DOB.threeMesh = obj;
_3DOB.minWGS84 = minWGS84;
_3DOB.maxWGS84 = maxWGS84;
_3Dobjects.push(_3DOB);
var mat=new THREE.MeshLambertMaterial({color:0xff0000});
var geo=new THREE.BoxGeometry(200,200,200);
var objects=new THREE.Group();
for (var i = 0; i < 10; i++) {
var object = new THREE.Mesh(geo,mat);
object.position.x = Math.round(Math.random() * 10000);
objects.add(object);
}
three.scene.add(objects); //用cube模拟x轴
var _3DOB = new _3DObject();
_3DOB.threeMesh = objects;
_3DOB.minWGS84 = minWGS84;
_3DOB.maxWGS84 = maxWGS84;
_3Dobjects.push(_3DOB);
// objects.position.set(position.x,position.y,position.z);
var mat2=new THREE.MeshLambertMaterial({color:0x00ff00});
var geo2=new THREE.BoxGeometry(200,200,200);
var objects2=new THREE.Group();
for (var i = 0; i < 20;i++) {
var object2 = new THREE.Mesh(geo2,mat2);
object2.position.y = Math.round(Math.random() * 10000);
objects2.add(object2);
}
three.scene.add(objects2); //模拟y轴
var _3DOB = new _3DObject();
_3DOB.threeMesh = objects2;
_3DOB.minWGS84 = minWGS84;
_3DOB.maxWGS84 = maxWGS84;
_3Dobjects.push(_3DOB);
// objects2.position.set(position.x,position.y,position.z);
var mat3=new THREE.MeshLambertMaterial({color:0x0000ff});
var geo3=new THREE.BoxGeometry(200,200,200);
var objects3=new THREE.Group();
for (var i = 0; i < 20;i++) {
var object3 = new THREE.Mesh(geo3,mat3);
object3.position.z = Math.round(Math.random() * 10000);
objects3.add(object3);
}
three.scene.add(objects3); //模拟z轴
var _3DOB = new _3DObject();
_3DOB.threeMesh = objects3;
_3DOB.minWGS84 = minWGS84;
_3DOB.maxWGS84 = maxWGS84;
_3Dobjects.push(_3DOB);
});
//原贴中的模型
// var doubleSideMaterial = new THREE.MeshNormalMaterial({
// side: THREE.DoubleSide
// });
// var segments = 10;
// var points = [];
// for ( var i = 0; i < segments; i ++ ) {
// points.push( new THREE.Vector2( Math.sin( i * 0.2 ) * segments + 5, ( i - 5 ) * 2 ) );
// }
// var geometry = new THREE.LatheGeometry( points );
// var latheMesh = new THREE.Mesh( geometry, doubleSideMaterial ) ;
// latheMesh.scale.set(1500,1500,1500); //scale object to be visible at planet scale
// latheMesh.position.z += 15000.0; // translate "up" in Three.js space so the "bottom" of the mesh is the handle
// latheMesh.rotation.x = Math.PI / 2; // rotate mesh for Cesium's Y-up system
// var latheMeshYup = new THREE.Group();
// latheMeshYup.add(latheMesh)
// three.scene.add(latheMeshYup); // don’t forget to add it to the Three.js scene manually
//
// //Assign Three.js object mesh to our object array
// var _3DOB = new _3DObject();
// _3DOB.threeMesh = latheMeshYup;
// _3DOB.minWGS84 = minWGS84;
// _3DOB.maxWGS84 = maxWGS84;
// _3Dobjects.push(_3DOB);
//
// // dodecahedron
// geometry = new THREE.DodecahedronGeometry();
// var 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 += 15000.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
// var dodecahedronMeshYup = new THREE.Group();
// dodecahedronMeshYup.add(dodecahedronMesh)
// three.scene.add(dodecahedronMesh); // don’t forget to add it to the Three.js scene manually
//
// //Assign Three.js object mesh to our object array
// _3DOB = new _3DObject();
// _3DOB.threeMesh = dodecahedronMesh;
// _3DOB.minWGS84 = minWGS84;
// _3DOB.maxWGS84 = maxWGS84;
// _3Dobjects.push(_3DOB);
}
// Looping Renderer
function renderCesium(){
cesium.viewer.render();
}
function renderThreeObj(){
// register Three.js scene with Cesium
three.camera.fov = CesiumMath.toDegrees(cesium.viewer.camera.frustum.fovy) // ThreeJS FOV is vertical
three.camera.updateProjectionMatrix();
var 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(var id in _3Dobjects){
minWGS84 = _3Dobjects[id].minWGS84;
maxWGS84 = _3Dobjects[id].maxWGS84;
// convert lat/long center position to Cartesian3
var center = CesiumCartesian3.fromDegrees(116.39,39.9);
// get forward direction for orienting model
var centerHigh = CesiumCartesian3.fromDegrees(116.39,39.9,1);
// use direction from bottom left to top left as up-vector
var bottomLeft = cartToVec(CesiumCartesian3.fromDegrees(minWGS84[0], minWGS84[1]));
var topLeft = cartToVec(CesiumCartesian3.fromDegrees(minWGS84[0], maxWGS84[1]));
var latDir = new THREE.Vector3().subVectors(bottomLeft,topLeft ).normalize();
// configure entity position and orientation
_3Dobjects[id].threeMesh.position.copy(center);
_3Dobjects[id].threeMesh.lookAt(centerHigh);
_3Dobjects[id].threeMesh.up.copy(latDir); //指定y轴的朝向
}
// 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;
var cvm = cesium.viewer.camera.viewMatrix;
var civm = cesium.viewer.camera.inverseViewMatrix;
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.camera.lookAt(new THREE.Vector3(0,0,0));
var width = ThreeContainer.clientWidth;
var height = ThreeContainer.clientHeight;
var aspect = width / height;
three.camera.aspect = aspect;
three.camera.updateProjectionMatrix();
three.renderer.setSize(width, height);
three.renderer.render(three.scene, three.camera);
}
function loop(){
renderCesium();
renderThreeObj();
requestAnimationFrame(loop);
}
initCesium(); // Initialize Cesium renderer
initThree(); // Initialize Three.js renderer
init3DObject(); // Initialize Three.js object mesh with Cesium Cartesian coordinate system
loop(); // Looping renderer
});