我正试图创建一个围绕地球运行的国际空间站模型。我正在使用threeJS来实现这一目标。到目前为止,除了更新导入的ISS模型的位置之外,我还能完美地完成所有工作。我有一个球体围绕地球运行,每隔5秒从一次AJAX调用获得它的位置,然后转换为地球球体模型上的坐标。我本质上想用ISS的模型替换轨道上的球体(代码中的posSphere)。因模型异步加载而出现问题。我目前尝试的是在模型的animate函数中包含参数,并在回调时将其发送到animate函数,但这会导致整个场景冻结。
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - OBJLoader + MTLLoader</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #000;
color: #fff;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="Resources/three.js"></script>
<script src="Resources/TDSLoader.js"></script>
<script src="Resources/FBXLoader.js"></script>
<script src="Resources/GLTFLoader.js"></script>
<script src="Resources/inflate.min.js"></script>
<script src="Resources/TrackballControls.js"></script>
<script>
var lat, long, issPosition;
//*********************PRELIM FUNCTIONS BEGIN**********************************
//AJAX request for current position of the ISS
function GetValue() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var requestResponse = xhr.responseText;
var issInfo = JSON.parse(requestResponse);
var Lat = issInfo.iss_position.latitude;
var Long = issInfo.iss_position.longitude;
callback(Lat, Long); //callback function with lat and long info
}
};
xhr.open("GET", "http://api.open-notify.org/iss-now.json", true);
xhr.send();
}
function callback(Lat, Long) {
lat = Lat; //set global variables equal to lat and long so animate function has access
long = Long;
}
GetValue(); //function call to get iss location
setInterval(GetValue, 5000); //interval for iss location, updates every 5 seconds
//convert long & lat to 3D coordinate
function latLongToVector3(lat, lon, radius, heigth) {
var phi = (lat)*Math.PI/180;
var theta = (lon-180)*Math.PI/180;
var x = -(radius+heigth) * Math.cos(phi) * Math.cos(theta);
var y = (radius+heigth) * Math.sin(phi);
var z = (radius+heigth) * Math.cos(phi) * Math.sin(theta);
return new THREE.Vector3(x,y,z);
}
//******************PRELIM FUNCTIONS END********************************************
//******************THREE JS ENVIRONMENT BEGIN**************************************
var width = window.innerWidth;
var height = window.innerHeight;
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, width/height, 0.01, 1000);
camera.position.z = 400;
var controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
var renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);
var direcLight = new THREE.DirectionalLight(0xffffff, 0.3);
direcLight.position.set(-3,3,1.5);
direcLight.castShadow = true;
scene.add(direcLight);
var ambientLight = new THREE.AmbientLight(0xc9c9c9, 1.5);
scene.add(ambientLight);
var geometry1 = new THREE.SphereGeometry(200,32,32);
var geometry2 = new THREE.SphereGeometry(202.5,32,32);
var geometry3 = new THREE.SphereGeometry(3, 32, 32);
var material1 = new THREE.MeshBasicMaterial ({
color: 0xff0000
});
var material2 = new THREE.MeshPhongMaterial({
map: new THREE.TextureLoader().load('Resources/Earth3/earthmapoftwo.jpg'),
bumpMap: new THREE.TextureLoader().load('Resources/Earth3/Bump2.jpg'),
bumpScale: 1,
specularMap: new THREE.TextureLoader().load('Resources/Earth3/oceanmaskbytwo.png'),
specular: new THREE.Color('grey'),
shininess: 40
});
var material3 = new THREE.MeshPhongMaterial({
alphaMap: new THREE.TextureLoader().load('Resources/Earth3/Clouds.png'),
transparent: true,
});
var issModel;
var loaderGLTF = new THREE.GLTFLoader();
loaderGLTF.load(
"Resources/Earth3/iss.gltf",
function(gltf) { //I want to be able to access this gltf outside of this callback function
gltf.scene.scale.x = 0.1;
gltf.scene.scale.y = 0.1;
gltf.scene.scale.z = 0.1;
console.log(gltf.scene.position);
scene.add(gltf.scene);
animate(gltf); //send gltf to animate function, this does not work
}
)
var sphere = new THREE.Mesh(geometry1, material2);
var clouds = new THREE.Mesh(geometry2, material3);
var posSphere = new THREE.Mesh(geometry3, material1);
sphere.receiveShadow = true;
clouds.receiveShadow = true;
posSphere.receiveShadow = true;
scene.add(sphere);
scene.add(clouds);
scene.add(posSphere);
function animate(gltf) {
clouds.rotation.x += 0.0001;
clouds.rotation.y += 0.0001;
clouds.rotation.z += 0.0001;
issPosition = latLongToVector3(lat, long, 200, 10);
posSphere.position.x = issPosition.x; //sphere's location is updated with the issPosition & works
posSphere.position.y = issPosition.y;
posSphere.position.z = issPosition.z;
gltf.scene.position.x = issPosition.x; //Part I am struggling with here, how to access the gltf's position from within this function. Essentially I want to replace the sphere with the gltf
gltf.scene.position.y = issPosition.y;
gltf.scene.position.z = issPosition.z;
controls.update();
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
//**************************THREE JS ENVIRONMENT END*************************************
</script>
</body>
</html>
答案 0 :(得分:0)
您正在为animate函数定义一个参数,然后立即调用它而不使用参数..(在代码的最后一行向下)。这就是为什么你的应用程序是&#34;冻结&#34;。 (它没有冻结..它可能会抛出异常..您可以在调试器控制台中看到.. Ctrl + Shift + J < / kbd>在chrome或更多工具中 - >来自右上方菜单的开发人员工具。例外情况应该在底部显示为红色。)
取出你所做的代码行&#39; animate(gltf)&#39;而是做&#34; issModel = gltf.scene;&#34;
然后在你的动画函数中而不是做&#34; gltf.scene.position.x =&#34;等
执行&#34; issModel.position.copy(issPosition);&#34;
如果你仍然陷入困境,请尝试在某个地方在线托管,我们可以深入了解。