在 Three.js 中更改 MouseOver 上的纹理颜色
Change Color of Textures on MouseOver in Three.js
除了使用 "disc.png" 创建的纹理(这些是结果中的红点 window).我希望能够做相反的事情,只改变纹理的颜色。我需要更改代码的哪一部分才能实现这一目标?
var renderer, scene, camera;
var control;
var stats;
var cameraControl;
//var radius = 7.7;
var radius = 15;
var group = new THREE.Object3D();
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector3(), INTERSECTED;
// Initialize the scene, camera and objects.
function init() {
// To display anything, you need 3 things: (1) Scene, (2) Camera, (3) Renderer
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x000000, 1.0);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
// Mars needs (1) geometry, (2) material, (3) mesh
var sphereGeometry = new THREE.SphereGeometry(15, 60, 60);
var sphereMaterial = createMarsMaterial();
var marsMesh = new THREE.Mesh(sphereGeometry, sphereMaterial);
marsMesh.name = 'mars';
scene.add(marsMesh);
// position and point the camera to the center of the scene
camera.position.x = 25;
camera.position.y = 26;
camera.position.z = 30;
camera.lookAt(scene.position);
// add controls
cameraControl = new THREE.OrbitControls(camera);
// setup the control object for the control gui
control = new function () {
this.rotationSpeed = 0.000;
};
// add extras
addControlGui(control);
addStatsObject();
// add the output of the renderer to the html element
document.body.appendChild(renderer.domElement);
// add a star field
var starsGeometry = new THREE.Geometry();
for ( var i = 0; i < 10000; i ++ ) {
var star = new THREE.Vector3();
star.x = THREE.Math.randFloatSpread( 2000 );
star.y = THREE.Math.randFloatSpread( 2000 );
star.z = THREE.Math.randFloatSpread( 2000 );
starsGeometry.vertices.push( star )
}
var starsMaterial = new THREE.PointsMaterial( { color: 0xF9F9CF } )
var starField = new THREE.Points( starsGeometry, starsMaterial );
scene.add( starField );
// start animating
render();
}
function createMarsMaterial() {
// 4096 is the maximum width for maps
var marsTexture = THREE.ImageUtils;
marsTexture.crossOrigin = "";
marsTexture = THREE.ImageUtils.loadTexture("https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/mars.jpg");
var marsMaterial = new THREE.MeshBasicMaterial();
marsMaterial.map = marsTexture;
return marsMaterial;
}
function addControlGui(controlObject) {
var gui = new dat.GUI();
gui.add(controlObject, 'rotationSpeed', -0.01, 0.01);
}
function addStatsObject() {
stats = new Stats();
stats.setMode(0);
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild(stats.domElement);
}
function render() {
stats.update();
cameraControl.update();
scene.getObjectByName('mars').rotation.y += control.rotationSpeed;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
function handleResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
window.onload = init;
window.addEventListener('resize', handleResize, false);
window.addEventListener( 'mousemove', onMouseMove, false );
var Landing_Sites = "https://tatornator12.github.io/classes/final-project/Mars_LandingSites2.json";
d3.queue()
.defer(d3.json, Landing_Sites)
.await(ready);
function ready(error, json) {
if (error) throw error;
scene.add(graticule = wireframe(graticule10(), new THREE.LineBasicMaterial({color: 0xaaaaaa})));
json.features.forEach(function(d) { group.add(createDot(d)) });
scene.add(group);
d3.timer(function(t) {
//group.rotation.y = Math.sin(t / 11000) * Math.PI / 3 - Math.PI / 2;
// group.rotation.y = t / 10000;
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)
);
}
function createDot(feature) {
var landingSitesGeometry = new THREE.Geometry();
var position = vertex(feature.geometry.coordinates);
landingSitesGeometry.vertices.push( position );
var landingSitesMaterial = new THREE.PointsMaterial({ size: 1.5, color: 0xff0000, map: THREE.ImageUtils.loadTexture("https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/sprites/disc.png"), transparent: true });
var dot = new THREE.Points(landingSitesGeometry, landingSitesMaterial);
dot.position.set(position.x, position.y, position.z);
return dot;
}
// Converts a GeoJSON MultiLineString in spherical coordinates to a THREE.LineSegments.
function wireframe(multilinestring, material) {
var geometry = new THREE.Geometry;
multilinestring.coordinates.forEach(function(line) {
d3.pairs(line.map(vertex), function(a, b) {
geometry.vertices.push(a, b);
});
});
return new THREE.LineSegments(geometry, material);
}
// See https://github.com/d3/d3-geo/issues/95
function graticule10() {
var epsilon = 1e-6,
x1 = 180, x0 = -x1, y1 = 80, y0 = -y1, dx = 10, dy = 10,
X1 = 180, X0 = -X1, Y1 = 90, Y0 = -Y1, DX = 90, DY = 360,
x = graticuleX(y0, y1, 2.5), y = graticuleY(x0, x1, 2.5),
X = graticuleX(Y0, Y1, 2.5), Y = graticuleY(X0, X1, 2.5);
function graticuleX(y0, y1, dy) {
var y = d3.range(y0, y1 - epsilon, dy).concat(y1);
return function(x) { return y.map(function(y) { return [x, y]; }); };
}
function graticuleY(x0, x1, dx) {
var x = d3.range(x0, x1 - epsilon, dx).concat(x1);
return function(y) { return x.map(function(x) { return [x, y]; }); };
}
return {
type: "MultiLineString",
coordinates: d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X)
.concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y))
.concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return Math.abs(x % DX) > epsilon; }).map(x))
.concat(d3.range(Math.ceil(y0 / dy) * dy, y1 + epsilon, dy).filter(function(y) { return Math.abs(y % DY) > epsilon; }).map(y))
};
}
function onMouseMove( event ) {
// calculate mouse position in normalized device coordinates
// (-1 to +1) for both components
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
// update the picking ray with the camera and mouse position
raycaster.setFromCamera( mouse, camera );
// calculate objects intersecting the picking ray
var intersects = raycaster.intersectObjects( scene.children );
// if there is one (or more) intersections
if ( intersects.length > 0 )
{
// if the closest object intersected is not the currently stored intersection object
if ( intersects[ 0 ].object != INTERSECTED )
{
// restore previous intersection object (if it exists) to its original color
if ( INTERSECTED )
INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
// store reference to closest object as current intersection object
INTERSECTED = intersects[ 0 ].object;
// store color of closest object (for later restoration)
INTERSECTED.currentHex = INTERSECTED.material.color.getHex();
// set a new color for closest object
INTERSECTED.material.color.setHex( 0x00ff00 );
}
}
else // there are no intersections
{
// restore previous intersection object (if it exists) to its original color
if ( INTERSECTED )
INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
// remove previous intersection object reference
// by setting current intersection object to "nothing"
INTERSECTED = null;
}
}
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script src="https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/three.js"></script>
<script src="https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/OrbitControls.js"></script>
<script src="https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/dat.gui.min.js"></script>
<script src="https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/stats.min.js"></script>
Point 的边界球体被初始化为零半径。你的鼠标永远不会击中它。我不得不手动构建边界球。
var renderer, scene, camera;
var control;
var stats;
var cameraControl;
//var radius = 7.7;
var radius = 15;
var group = new THREE.Object3D();
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector3(), INTERSECTED;
// Initialize the scene, camera and objects.
function init() {
// To display anything, you need 3 things: (1) Scene, (2) Camera, (3) Renderer
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x000000, 1.0);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
// Mars needs (1) geometry, (2) material, (3) mesh
var sphereGeometry = new THREE.SphereGeometry(15, 60, 60);
var sphereMaterial = createMarsMaterial();
var marsMesh = new THREE.Mesh(sphereGeometry, sphereMaterial);
marsMesh.name = 'mars';
scene.add(marsMesh);
// position and point the camera to the center of the scene
camera.position.x = 25;
camera.position.y = 26;
camera.position.z = 30;
camera.lookAt(scene.position);
// add controls
cameraControl = new THREE.OrbitControls(camera);
// setup the control object for the control gui
control = new function () {
this.rotationSpeed = 0.000;
};
// add extras
addControlGui(control);
addStatsObject();
// add the output of the renderer to the html element
document.body.appendChild(renderer.domElement);
// add a star field
var starsGeometry = new THREE.Geometry();
for ( var i = 0; i < 10000; i ++ ) {
var star = new THREE.Vector3();
star.x = THREE.Math.randFloatSpread( 2000 );
star.y = THREE.Math.randFloatSpread( 2000 );
star.z = THREE.Math.randFloatSpread( 2000 );
starsGeometry.vertices.push( star )
}
var starsMaterial = new THREE.PointsMaterial( { color: 0xF9F9CF } )
var starField = new THREE.Points( starsGeometry, starsMaterial );
scene.add( starField );
// start animating
render();
}
function createMarsMaterial() {
// 4096 is the maximum width for maps
var marsTexture = THREE.ImageUtils;
marsTexture.crossOrigin = "";
marsTexture = THREE.ImageUtils.loadTexture("https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/mars.jpg");
var marsMaterial = new THREE.MeshBasicMaterial();
marsMaterial.map = marsTexture;
return marsMaterial;
}
function addControlGui(controlObject) {
var gui = new dat.GUI();
gui.add(controlObject, 'rotationSpeed', -0.01, 0.01);
}
function addStatsObject() {
stats = new Stats();
stats.setMode(0);
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild(stats.domElement);
}
function render() {
stats.update();
cameraControl.update();
scene.getObjectByName('mars').rotation.y += control.rotationSpeed;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
function handleResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
window.onload = init;
window.addEventListener('resize', handleResize, false);
window.addEventListener( 'mousemove', onMouseMove, false );
var Landing_Sites = "https://tatornator12.github.io/classes/final-project/Mars_LandingSites2.json";
d3.queue()
.defer(d3.json, Landing_Sites)
.await(ready);
function ready(error, json) {
if (error) throw error;
scene.add(graticule = wireframe(graticule10(), new THREE.LineBasicMaterial({color: 0xaaaaaa})));
json.features.forEach(function(d) { group.add(createDot(d)) });
scene.add(group);
d3.timer(function(t) {
//group.rotation.y = Math.sin(t / 11000) * Math.PI / 3 - Math.PI / 2;
// group.rotation.y = t / 10000;
renderer.render(scene, camera);
});
console.clear();
}
// 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)
);
}
function createDot(feature) {
var landingSitesGeometry = new THREE.Geometry();
var position = vertex(feature.geometry.coordinates);
landingSitesGeometry.vertices.push( position );
var landingSitesMaterial = new THREE.PointsMaterial({ size: 1.5, color: 0xff0000, map: THREE.ImageUtils.loadTexture("https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/sprites/disc.png"), transparent: true });
var dot = new THREE.Points(landingSitesGeometry, landingSitesMaterial);
dot.position.set(position.x, position.y, position.z);
dot.geometry.boundingSphere = new THREE.Sphere();
dot.geometry.boundingSphere.center.x = position.x;
dot.geometry.boundingSphere.center.y = position.y;
dot.geometry.boundingSphere.center.z = position.z;
dot.geometry.boundingSphere.radius = 1.5;
return dot;
}
// Converts a GeoJSON MultiLineString in spherical coordinates to a THREE.LineSegments.
function wireframe(multilinestring, material) {
var geometry = new THREE.Geometry;
multilinestring.coordinates.forEach(function(line) {
d3.pairs(line.map(vertex), function(a, b) {
geometry.vertices.push(a, b);
});
});
return new THREE.LineSegments(geometry, material);
}
// See https://github.com/d3/d3-geo/issues/95
function graticule10() {
var epsilon = 1e-6,
x1 = 180, x0 = -x1, y1 = 80, y0 = -y1, dx = 10, dy = 10,
X1 = 180, X0 = -X1, Y1 = 90, Y0 = -Y1, DX = 90, DY = 360,
x = graticuleX(y0, y1, 2.5), y = graticuleY(x0, x1, 2.5),
X = graticuleX(Y0, Y1, 2.5), Y = graticuleY(X0, X1, 2.5);
function graticuleX(y0, y1, dy) {
var y = d3.range(y0, y1 - epsilon, dy).concat(y1);
return function(x) { return y.map(function(y) { return [x, y]; }); };
}
function graticuleY(x0, x1, dx) {
var x = d3.range(x0, x1 - epsilon, dx).concat(x1);
return function(y) { return x.map(function(x) { return [x, y]; }); };
}
return {
type: "MultiLineString",
coordinates: d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X)
.concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y))
.concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return Math.abs(x % DX) > epsilon; }).map(x))
.concat(d3.range(Math.ceil(y0 / dy) * dy, y1 + epsilon, dy).filter(function(y) { return Math.abs(y % DY) > epsilon; }).map(y))
};
}
function onMouseMove( event ) {
// calculate mouse position in normalized device coordinates
// (-1 to +1) for both components
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
// update the picking ray with the camera and mouse position
raycaster.setFromCamera( mouse, camera );
// calculate objects intersecting the picking ray
var intersects = raycaster.intersectObjects( scene.children[3].children );
// if there is one (or more) intersections
if ( intersects.length > 0 )
{
// if the closest object intersected is not the currently stored intersection object
if ( intersects[ 0 ].object != INTERSECTED )
{
// restore previous intersection object (if it exists) to its original color
if ( INTERSECTED )
INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
// store reference to closest object as current intersection object
INTERSECTED = intersects[ 0 ].object;
// store color of closest object (for later restoration)
INTERSECTED.currentHex = INTERSECTED.material.color.getHex();
// set a new color for closest object
INTERSECTED.material.color.setHex( 0x00ff00 );
}
}
else // there are no intersections
{
// restore previous intersection object (if it exists) to its original color
if ( INTERSECTED )
INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
// remove previous intersection object reference
// by setting current intersection object to "nothing"
INTERSECTED = null;
}
}
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script src="https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/three.js"></script>
<script src="https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/OrbitControls.js"></script>
<script src="https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/dat.gui.min.js"></script>
<script src="https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/stats.min.js"></script>
除了使用 "disc.png" 创建的纹理(这些是结果中的红点 window).我希望能够做相反的事情,只改变纹理的颜色。我需要更改代码的哪一部分才能实现这一目标?
var renderer, scene, camera;
var control;
var stats;
var cameraControl;
//var radius = 7.7;
var radius = 15;
var group = new THREE.Object3D();
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector3(), INTERSECTED;
// Initialize the scene, camera and objects.
function init() {
// To display anything, you need 3 things: (1) Scene, (2) Camera, (3) Renderer
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x000000, 1.0);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
// Mars needs (1) geometry, (2) material, (3) mesh
var sphereGeometry = new THREE.SphereGeometry(15, 60, 60);
var sphereMaterial = createMarsMaterial();
var marsMesh = new THREE.Mesh(sphereGeometry, sphereMaterial);
marsMesh.name = 'mars';
scene.add(marsMesh);
// position and point the camera to the center of the scene
camera.position.x = 25;
camera.position.y = 26;
camera.position.z = 30;
camera.lookAt(scene.position);
// add controls
cameraControl = new THREE.OrbitControls(camera);
// setup the control object for the control gui
control = new function () {
this.rotationSpeed = 0.000;
};
// add extras
addControlGui(control);
addStatsObject();
// add the output of the renderer to the html element
document.body.appendChild(renderer.domElement);
// add a star field
var starsGeometry = new THREE.Geometry();
for ( var i = 0; i < 10000; i ++ ) {
var star = new THREE.Vector3();
star.x = THREE.Math.randFloatSpread( 2000 );
star.y = THREE.Math.randFloatSpread( 2000 );
star.z = THREE.Math.randFloatSpread( 2000 );
starsGeometry.vertices.push( star )
}
var starsMaterial = new THREE.PointsMaterial( { color: 0xF9F9CF } )
var starField = new THREE.Points( starsGeometry, starsMaterial );
scene.add( starField );
// start animating
render();
}
function createMarsMaterial() {
// 4096 is the maximum width for maps
var marsTexture = THREE.ImageUtils;
marsTexture.crossOrigin = "";
marsTexture = THREE.ImageUtils.loadTexture("https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/mars.jpg");
var marsMaterial = new THREE.MeshBasicMaterial();
marsMaterial.map = marsTexture;
return marsMaterial;
}
function addControlGui(controlObject) {
var gui = new dat.GUI();
gui.add(controlObject, 'rotationSpeed', -0.01, 0.01);
}
function addStatsObject() {
stats = new Stats();
stats.setMode(0);
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild(stats.domElement);
}
function render() {
stats.update();
cameraControl.update();
scene.getObjectByName('mars').rotation.y += control.rotationSpeed;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
function handleResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
window.onload = init;
window.addEventListener('resize', handleResize, false);
window.addEventListener( 'mousemove', onMouseMove, false );
var Landing_Sites = "https://tatornator12.github.io/classes/final-project/Mars_LandingSites2.json";
d3.queue()
.defer(d3.json, Landing_Sites)
.await(ready);
function ready(error, json) {
if (error) throw error;
scene.add(graticule = wireframe(graticule10(), new THREE.LineBasicMaterial({color: 0xaaaaaa})));
json.features.forEach(function(d) { group.add(createDot(d)) });
scene.add(group);
d3.timer(function(t) {
//group.rotation.y = Math.sin(t / 11000) * Math.PI / 3 - Math.PI / 2;
// group.rotation.y = t / 10000;
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)
);
}
function createDot(feature) {
var landingSitesGeometry = new THREE.Geometry();
var position = vertex(feature.geometry.coordinates);
landingSitesGeometry.vertices.push( position );
var landingSitesMaterial = new THREE.PointsMaterial({ size: 1.5, color: 0xff0000, map: THREE.ImageUtils.loadTexture("https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/sprites/disc.png"), transparent: true });
var dot = new THREE.Points(landingSitesGeometry, landingSitesMaterial);
dot.position.set(position.x, position.y, position.z);
return dot;
}
// Converts a GeoJSON MultiLineString in spherical coordinates to a THREE.LineSegments.
function wireframe(multilinestring, material) {
var geometry = new THREE.Geometry;
multilinestring.coordinates.forEach(function(line) {
d3.pairs(line.map(vertex), function(a, b) {
geometry.vertices.push(a, b);
});
});
return new THREE.LineSegments(geometry, material);
}
// See https://github.com/d3/d3-geo/issues/95
function graticule10() {
var epsilon = 1e-6,
x1 = 180, x0 = -x1, y1 = 80, y0 = -y1, dx = 10, dy = 10,
X1 = 180, X0 = -X1, Y1 = 90, Y0 = -Y1, DX = 90, DY = 360,
x = graticuleX(y0, y1, 2.5), y = graticuleY(x0, x1, 2.5),
X = graticuleX(Y0, Y1, 2.5), Y = graticuleY(X0, X1, 2.5);
function graticuleX(y0, y1, dy) {
var y = d3.range(y0, y1 - epsilon, dy).concat(y1);
return function(x) { return y.map(function(y) { return [x, y]; }); };
}
function graticuleY(x0, x1, dx) {
var x = d3.range(x0, x1 - epsilon, dx).concat(x1);
return function(y) { return x.map(function(x) { return [x, y]; }); };
}
return {
type: "MultiLineString",
coordinates: d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X)
.concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y))
.concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return Math.abs(x % DX) > epsilon; }).map(x))
.concat(d3.range(Math.ceil(y0 / dy) * dy, y1 + epsilon, dy).filter(function(y) { return Math.abs(y % DY) > epsilon; }).map(y))
};
}
function onMouseMove( event ) {
// calculate mouse position in normalized device coordinates
// (-1 to +1) for both components
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
// update the picking ray with the camera and mouse position
raycaster.setFromCamera( mouse, camera );
// calculate objects intersecting the picking ray
var intersects = raycaster.intersectObjects( scene.children );
// if there is one (or more) intersections
if ( intersects.length > 0 )
{
// if the closest object intersected is not the currently stored intersection object
if ( intersects[ 0 ].object != INTERSECTED )
{
// restore previous intersection object (if it exists) to its original color
if ( INTERSECTED )
INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
// store reference to closest object as current intersection object
INTERSECTED = intersects[ 0 ].object;
// store color of closest object (for later restoration)
INTERSECTED.currentHex = INTERSECTED.material.color.getHex();
// set a new color for closest object
INTERSECTED.material.color.setHex( 0x00ff00 );
}
}
else // there are no intersections
{
// restore previous intersection object (if it exists) to its original color
if ( INTERSECTED )
INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
// remove previous intersection object reference
// by setting current intersection object to "nothing"
INTERSECTED = null;
}
}
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script src="https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/three.js"></script>
<script src="https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/OrbitControls.js"></script>
<script src="https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/dat.gui.min.js"></script>
<script src="https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/stats.min.js"></script>
Point 的边界球体被初始化为零半径。你的鼠标永远不会击中它。我不得不手动构建边界球。
var renderer, scene, camera;
var control;
var stats;
var cameraControl;
//var radius = 7.7;
var radius = 15;
var group = new THREE.Object3D();
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector3(), INTERSECTED;
// Initialize the scene, camera and objects.
function init() {
// To display anything, you need 3 things: (1) Scene, (2) Camera, (3) Renderer
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x000000, 1.0);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
// Mars needs (1) geometry, (2) material, (3) mesh
var sphereGeometry = new THREE.SphereGeometry(15, 60, 60);
var sphereMaterial = createMarsMaterial();
var marsMesh = new THREE.Mesh(sphereGeometry, sphereMaterial);
marsMesh.name = 'mars';
scene.add(marsMesh);
// position and point the camera to the center of the scene
camera.position.x = 25;
camera.position.y = 26;
camera.position.z = 30;
camera.lookAt(scene.position);
// add controls
cameraControl = new THREE.OrbitControls(camera);
// setup the control object for the control gui
control = new function () {
this.rotationSpeed = 0.000;
};
// add extras
addControlGui(control);
addStatsObject();
// add the output of the renderer to the html element
document.body.appendChild(renderer.domElement);
// add a star field
var starsGeometry = new THREE.Geometry();
for ( var i = 0; i < 10000; i ++ ) {
var star = new THREE.Vector3();
star.x = THREE.Math.randFloatSpread( 2000 );
star.y = THREE.Math.randFloatSpread( 2000 );
star.z = THREE.Math.randFloatSpread( 2000 );
starsGeometry.vertices.push( star )
}
var starsMaterial = new THREE.PointsMaterial( { color: 0xF9F9CF } )
var starField = new THREE.Points( starsGeometry, starsMaterial );
scene.add( starField );
// start animating
render();
}
function createMarsMaterial() {
// 4096 is the maximum width for maps
var marsTexture = THREE.ImageUtils;
marsTexture.crossOrigin = "";
marsTexture = THREE.ImageUtils.loadTexture("https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/mars.jpg");
var marsMaterial = new THREE.MeshBasicMaterial();
marsMaterial.map = marsTexture;
return marsMaterial;
}
function addControlGui(controlObject) {
var gui = new dat.GUI();
gui.add(controlObject, 'rotationSpeed', -0.01, 0.01);
}
function addStatsObject() {
stats = new Stats();
stats.setMode(0);
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild(stats.domElement);
}
function render() {
stats.update();
cameraControl.update();
scene.getObjectByName('mars').rotation.y += control.rotationSpeed;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
function handleResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
window.onload = init;
window.addEventListener('resize', handleResize, false);
window.addEventListener( 'mousemove', onMouseMove, false );
var Landing_Sites = "https://tatornator12.github.io/classes/final-project/Mars_LandingSites2.json";
d3.queue()
.defer(d3.json, Landing_Sites)
.await(ready);
function ready(error, json) {
if (error) throw error;
scene.add(graticule = wireframe(graticule10(), new THREE.LineBasicMaterial({color: 0xaaaaaa})));
json.features.forEach(function(d) { group.add(createDot(d)) });
scene.add(group);
d3.timer(function(t) {
//group.rotation.y = Math.sin(t / 11000) * Math.PI / 3 - Math.PI / 2;
// group.rotation.y = t / 10000;
renderer.render(scene, camera);
});
console.clear();
}
// 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)
);
}
function createDot(feature) {
var landingSitesGeometry = new THREE.Geometry();
var position = vertex(feature.geometry.coordinates);
landingSitesGeometry.vertices.push( position );
var landingSitesMaterial = new THREE.PointsMaterial({ size: 1.5, color: 0xff0000, map: THREE.ImageUtils.loadTexture("https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/sprites/disc.png"), transparent: true });
var dot = new THREE.Points(landingSitesGeometry, landingSitesMaterial);
dot.position.set(position.x, position.y, position.z);
dot.geometry.boundingSphere = new THREE.Sphere();
dot.geometry.boundingSphere.center.x = position.x;
dot.geometry.boundingSphere.center.y = position.y;
dot.geometry.boundingSphere.center.z = position.z;
dot.geometry.boundingSphere.radius = 1.5;
return dot;
}
// Converts a GeoJSON MultiLineString in spherical coordinates to a THREE.LineSegments.
function wireframe(multilinestring, material) {
var geometry = new THREE.Geometry;
multilinestring.coordinates.forEach(function(line) {
d3.pairs(line.map(vertex), function(a, b) {
geometry.vertices.push(a, b);
});
});
return new THREE.LineSegments(geometry, material);
}
// See https://github.com/d3/d3-geo/issues/95
function graticule10() {
var epsilon = 1e-6,
x1 = 180, x0 = -x1, y1 = 80, y0 = -y1, dx = 10, dy = 10,
X1 = 180, X0 = -X1, Y1 = 90, Y0 = -Y1, DX = 90, DY = 360,
x = graticuleX(y0, y1, 2.5), y = graticuleY(x0, x1, 2.5),
X = graticuleX(Y0, Y1, 2.5), Y = graticuleY(X0, X1, 2.5);
function graticuleX(y0, y1, dy) {
var y = d3.range(y0, y1 - epsilon, dy).concat(y1);
return function(x) { return y.map(function(y) { return [x, y]; }); };
}
function graticuleY(x0, x1, dx) {
var x = d3.range(x0, x1 - epsilon, dx).concat(x1);
return function(y) { return x.map(function(x) { return [x, y]; }); };
}
return {
type: "MultiLineString",
coordinates: d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X)
.concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y))
.concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return Math.abs(x % DX) > epsilon; }).map(x))
.concat(d3.range(Math.ceil(y0 / dy) * dy, y1 + epsilon, dy).filter(function(y) { return Math.abs(y % DY) > epsilon; }).map(y))
};
}
function onMouseMove( event ) {
// calculate mouse position in normalized device coordinates
// (-1 to +1) for both components
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
// update the picking ray with the camera and mouse position
raycaster.setFromCamera( mouse, camera );
// calculate objects intersecting the picking ray
var intersects = raycaster.intersectObjects( scene.children[3].children );
// if there is one (or more) intersections
if ( intersects.length > 0 )
{
// if the closest object intersected is not the currently stored intersection object
if ( intersects[ 0 ].object != INTERSECTED )
{
// restore previous intersection object (if it exists) to its original color
if ( INTERSECTED )
INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
// store reference to closest object as current intersection object
INTERSECTED = intersects[ 0 ].object;
// store color of closest object (for later restoration)
INTERSECTED.currentHex = INTERSECTED.material.color.getHex();
// set a new color for closest object
INTERSECTED.material.color.setHex( 0x00ff00 );
}
}
else // there are no intersections
{
// restore previous intersection object (if it exists) to its original color
if ( INTERSECTED )
INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
// remove previous intersection object reference
// by setting current intersection object to "nothing"
INTERSECTED = null;
}
}
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script src="https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/three.js"></script>
<script src="https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/OrbitControls.js"></script>
<script src="https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/dat.gui.min.js"></script>
<script src="https://tatornator12.github.io/classes/final-project/Using_Three_-_D3/stats.min.js"></script>