2017-04-26 94 views
0

我已經能夠實現MouseOver事件以更改我的應用程序中幾個對象的顏色,但使用「disc.png」創建的紋理除外(這些是結果窗口中的紅點)。我希望能夠做到相反,只是改變紋理的顏色。爲了實現這一目標,我需要更改哪部分代碼?在Three.js中更改MouseOver上紋理的顏色

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) { 
 

 
\t // calculate mouse position in normalized device coordinates 
 
\t // (-1 to +1) for both components 
 
    
 
    event.preventDefault(); 
 

 
\t mouse.x = (event.clientX/window.innerWidth) * 2 - 1; 
 
\t mouse.y = - (event.clientY/window.innerHeight) * 2 + 1; 
 

 
    // update the picking ray with the camera and mouse position 
 
\t raycaster.setFromCamera(mouse, camera); 
 
    
 
    
 
    // calculate objects intersecting the picking ray 
 
\t 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>

+0

有些東西似乎是錯誤的代碼。即使您刪除圖像紋理,它也不起作用。放置斷點表明該raycast不檢測交集。奇怪... – Nate

+0

有關如何修改這個的任何想法?你的意思是在我創建紋理的代碼中有什麼錯誤?或者與十字路口? – Lprox5

+0

我希望我知道。我昨天玩弄了它,不知道是什麼導致了這個問題。我會再看看我的停頓時間。 – Nate

回答

1

點的包圍球被初始化爲零的半徑。你的鼠標永遠不會打它。我不得不手動構建邊界球。

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) { 
 

 
\t // calculate mouse position in normalized device coordinates 
 
\t // (-1 to +1) for both components 
 
    
 
    event.preventDefault(); 
 

 
\t mouse.x = (event.clientX/window.innerWidth) * 2 - 1; 
 
\t mouse.y = - (event.clientY/window.innerHeight) * 2 + 1; 
 

 
    // update the picking ray with the camera and mouse position 
 
\t raycaster.setFromCamera(mouse, camera); 
 
    
 
    
 
    // calculate objects intersecting the picking ray 
 
\t 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>

+0

太棒了!它在沒有着色器的情況下運行得非常完美。我想知道是否必須不使用着色器,因爲它不會識別mouseover事件。不過,我真的很感激你的時間和幫助! – Lprox5

+0

@ Lprox5不客氣!祝你好運着色器=) – Nate