Three.js - 如何围绕球体(globe)定位物体
Three.js - How to position objects around a sphere (globe)
我有一个 json 国家边界文件,用于在 three.js (mbostock example) 中构建地图。
我想要的是将每个圆柱体的位置映射到其各自的国家 - 如下所示:
请查看以下代码段。目前我正在取每个几何体的边界框的中心,它工作得很好,但圆柱体并不像图像中那样指向外。我试过使用 lookAt() 但效果不佳。还有一个 for 循环可以旋转我的国家和圆柱体,但它们没有按应有的方式移动(取消注释以进行测试)。
如何正确定位气缸?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id='my_dataviz'></div>
<script src="https://d3js.org/d3.v6.js"></script>
<script src="https://unpkg.com/topojson-client@3"></script>
<script src="https://unpkg.com/d3-array@1"></script>
<script src="https://unpkg.com/d3-collection@1"></script>
<script src="https://unpkg.com/d3-dispatch@1"></script>
<script src="https://unpkg.com/d3-request@1"></script>
<script src="https://unpkg.com/d3-timer@1"></script>
<script type='module'>
import * as THREE from "https://unpkg.com/three@0.127.0/build/three.module.js";
import {OrbitControls} from "https://unpkg.com/three@0.127.0/examples/jsm/controls/OrbitControls.js";
var width1 = 860,
height1 = 860,
radius = 168,
mesh,
graticule,
scene = new THREE.Scene,
camera = new THREE.PerspectiveCamera(70, width1 / height1, 1, 1000),
renderer = new THREE.WebGLRenderer({alpha: true}),
container = document.getElementById( 'my_dataviz' ),
controls;
camera.position.z = 400;
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width1, height1);
container.appendChild(renderer.domElement);
const geometry = new THREE.SphereGeometry(98, 52, 36 );
const material = new THREE.MeshBasicMaterial( { color: "rgb(220,229,229)", opacity:0.7, transparent: true} );
const sphere = new THREE.Mesh( geometry, material );
d3.json("https://cdn.jsdelivr.net/npm/world-atlas@2/countries-50m.json", function(error, topology) {
if (error) throw error;
var countries = []
var cones = []
for (var i = 0; i < topology.objects.countries.geometries.length; i++) {
var rgb = [];
var newcolor;
for(var j = 0; j < 3; j++){
rgb.push(Math.floor(Math.random() * 255));
newcolor = 'rgb('+ rgb.join(',') +')';
}
var mesh = wireframe(topojson.mesh(topology, topology.objects.countries.geometries[i]), new THREE.LineBasicMaterial({color:newcolor, linewidth: 5}))
countries.push(mesh);
scene.add(mesh);
mesh.geometry.computeBoundingBox()
var center = new THREE.Vector3();
mesh.geometry.boundingBox.getCenter(center)
const geometry = new THREE.BoxGeometry( 1, i/10, 1 );
const material = new THREE.MeshBasicMaterial( {color: newcolor} );
const cone = new THREE.Mesh( geometry, material );
cone.position.x = center.x;
cone.position.y = center.y;
cone.position.z = center.z;
// cone.lookAt(mesh.position);
cones.push(cone);
scene.add( cone );
}
console.log(sphere.position)
scene.add(sphere);
controls = new OrbitControls( camera, renderer.domElement );
d3.timer(function(t) {
for (var i = 0; i < countries.length; i++) {
// countries[i].rotation.x = Math.sin(t / 21000) * Math.PI / 3 - Math.PI / 2;
// countries[i].rotation.z = t / 20000;
// cones[i].rotation.x = Math.sin(t / 21000) * Math.PI / 3 - Math.PI / 2;
// cones[i].rotation.z = t / 20000;
}
renderer.render(scene, camera)
});
});
// Converts a point [longitude, latitude] in degrees to a THREE.Vector3.
function vertex(point) {
var lambda = point[0] * Math.PI / 180,
phi = point[1] * Math.PI / 180,
cosPhi = Math.cos(phi);
return new THREE.Vector3(
radius * cosPhi * Math.cos(lambda),
radius * cosPhi * Math.sin(lambda),
radius * Math.sin(phi)
);
}
// Converts a GeoJSON MultiLineString in spherical coordinates to a THREE.LineSegments.
function wireframe(multilinestring, material) {
var geometry = new THREE.BufferGeometry;
var pointsArray = new Array();
multilinestring.coordinates.forEach(function(line) {
d3.pairs(line.map(vertex), function(a, b) {
pointsArray.push(a,b);
});
});
geometry.setFromPoints(pointsArray);
return new THREE.LineSegments(geometry, material);
}
</script>
</body>
群!!
圆柱体没有围绕正确的原点旋转。
let earthPivot = new THREE.Group(); //this is what matters
mesh.add( earthPivot ); //'mesh' is the globe
const geometry = new THREE.BoxGeometry( 1, 1+i/10, 1 );
const material = new THREE.MeshBasicMaterial( {color: newcolor} );
const cone = new THREE.Mesh( geometry, material );
cone.position.x = center.x;
cone.position.y = center.y;
cone.position.z = center.z;
cones.push(cone);
earthPivot.add( cone ); //this is what matters
将您的对象分组并将该组添加到您希望对象围绕其旋转的网格中。
我有一个 json 国家边界文件,用于在 three.js (mbostock example) 中构建地图。
我想要的是将每个圆柱体的位置映射到其各自的国家 - 如下所示:
请查看以下代码段。目前我正在取每个几何体的边界框的中心,它工作得很好,但圆柱体并不像图像中那样指向外。我试过使用 lookAt() 但效果不佳。还有一个 for 循环可以旋转我的国家和圆柱体,但它们没有按应有的方式移动(取消注释以进行测试)。
如何正确定位气缸?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id='my_dataviz'></div>
<script src="https://d3js.org/d3.v6.js"></script>
<script src="https://unpkg.com/topojson-client@3"></script>
<script src="https://unpkg.com/d3-array@1"></script>
<script src="https://unpkg.com/d3-collection@1"></script>
<script src="https://unpkg.com/d3-dispatch@1"></script>
<script src="https://unpkg.com/d3-request@1"></script>
<script src="https://unpkg.com/d3-timer@1"></script>
<script type='module'>
import * as THREE from "https://unpkg.com/three@0.127.0/build/three.module.js";
import {OrbitControls} from "https://unpkg.com/three@0.127.0/examples/jsm/controls/OrbitControls.js";
var width1 = 860,
height1 = 860,
radius = 168,
mesh,
graticule,
scene = new THREE.Scene,
camera = new THREE.PerspectiveCamera(70, width1 / height1, 1, 1000),
renderer = new THREE.WebGLRenderer({alpha: true}),
container = document.getElementById( 'my_dataviz' ),
controls;
camera.position.z = 400;
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width1, height1);
container.appendChild(renderer.domElement);
const geometry = new THREE.SphereGeometry(98, 52, 36 );
const material = new THREE.MeshBasicMaterial( { color: "rgb(220,229,229)", opacity:0.7, transparent: true} );
const sphere = new THREE.Mesh( geometry, material );
d3.json("https://cdn.jsdelivr.net/npm/world-atlas@2/countries-50m.json", function(error, topology) {
if (error) throw error;
var countries = []
var cones = []
for (var i = 0; i < topology.objects.countries.geometries.length; i++) {
var rgb = [];
var newcolor;
for(var j = 0; j < 3; j++){
rgb.push(Math.floor(Math.random() * 255));
newcolor = 'rgb('+ rgb.join(',') +')';
}
var mesh = wireframe(topojson.mesh(topology, topology.objects.countries.geometries[i]), new THREE.LineBasicMaterial({color:newcolor, linewidth: 5}))
countries.push(mesh);
scene.add(mesh);
mesh.geometry.computeBoundingBox()
var center = new THREE.Vector3();
mesh.geometry.boundingBox.getCenter(center)
const geometry = new THREE.BoxGeometry( 1, i/10, 1 );
const material = new THREE.MeshBasicMaterial( {color: newcolor} );
const cone = new THREE.Mesh( geometry, material );
cone.position.x = center.x;
cone.position.y = center.y;
cone.position.z = center.z;
// cone.lookAt(mesh.position);
cones.push(cone);
scene.add( cone );
}
console.log(sphere.position)
scene.add(sphere);
controls = new OrbitControls( camera, renderer.domElement );
d3.timer(function(t) {
for (var i = 0; i < countries.length; i++) {
// countries[i].rotation.x = Math.sin(t / 21000) * Math.PI / 3 - Math.PI / 2;
// countries[i].rotation.z = t / 20000;
// cones[i].rotation.x = Math.sin(t / 21000) * Math.PI / 3 - Math.PI / 2;
// cones[i].rotation.z = t / 20000;
}
renderer.render(scene, camera)
});
});
// Converts a point [longitude, latitude] in degrees to a THREE.Vector3.
function vertex(point) {
var lambda = point[0] * Math.PI / 180,
phi = point[1] * Math.PI / 180,
cosPhi = Math.cos(phi);
return new THREE.Vector3(
radius * cosPhi * Math.cos(lambda),
radius * cosPhi * Math.sin(lambda),
radius * Math.sin(phi)
);
}
// Converts a GeoJSON MultiLineString in spherical coordinates to a THREE.LineSegments.
function wireframe(multilinestring, material) {
var geometry = new THREE.BufferGeometry;
var pointsArray = new Array();
multilinestring.coordinates.forEach(function(line) {
d3.pairs(line.map(vertex), function(a, b) {
pointsArray.push(a,b);
});
});
geometry.setFromPoints(pointsArray);
return new THREE.LineSegments(geometry, material);
}
</script>
</body>
群!!
圆柱体没有围绕正确的原点旋转。
let earthPivot = new THREE.Group(); //this is what matters
mesh.add( earthPivot ); //'mesh' is the globe
const geometry = new THREE.BoxGeometry( 1, 1+i/10, 1 );
const material = new THREE.MeshBasicMaterial( {color: newcolor} );
const cone = new THREE.Mesh( geometry, material );
cone.position.x = center.x;
cone.position.y = center.y;
cone.position.z = center.z;
cones.push(cone);
earthPivot.add( cone ); //this is what matters
将您的对象分组并将该组添加到您希望对象围绕其旋转的网格中。