对象网格在渲染图像的相反方向上运行
Object Mesh Orbiting Opposite Direction of Rendered Image
我正在尝试使用 Three.JS 重新创建一个 Flash 网站,但在尝试创建某些功能时遇到了 运行 障碍。
应该发生的是我想让一些按钮图像围绕屏幕中心旋转。如果鼠标悬停在它们上面然后单击以打开网站上的不同位置,它们应该能够停止。
我已经完成了所有工作,直到要求当鼠标悬停在按钮上时按钮停止。我正在尝试使用光线投射来实现这一点,但是当我在场景中移动鼠标时,似乎网格与渲染纹理不在同一位置。事实上,网格和渲染图像几乎看起来是在彼此相反的方向上运行。
这是我的代码,我将 link 您转到我网站上的一个页面,我正在该页面上测试此改版,以便您获得真实世界的示例:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style type="text/css">
body { margin: 0;}
canvas { display: block;}
</style>
</head>
<body>
<script>
//var THREE = new THREE();
var renderer,scene,camera,nucleus;
var width = window.innerWidth;
var height = window.innerHeight;
var fov = 60;
var near = 1;
var far = 10000;
var min = 0;
var max = 10;
var insObjSpeed = 0;
var buttons = [];
var numOfBtns = 1;
var projector, mouse = { x: 0, y: 0 }, INTERSECTED;
//var mouse;
function populateScene(){
var geom = new THREE.CircleGeometry(3,50);
var matTx = new THREE.TextureLoader().load('imgs/buttons/logo.png');
var mat = new THREE.MeshBasicMaterial({map:matTx});
nucleus = new THREE.Mesh(geom, mat);
nucleus.position.set(0,0,0);
scene.add(nucleus);
var btn = null;
var btnMat = null;
var plane = new THREE.Plane();
var point = new THREE.Vector3();
var btnMats = [new THREE.TextureLoader().load('imgs/buttons/georo.png'),
new THREE.TextureLoader().load('imgs/buttons/wiki.png'),
new THREE.TextureLoader().load('imgs/buttons/port.png'),
new THREE.TextureLoader().load('imgs/buttons/yt.png'),
new THREE.TextureLoader().load('imgs/buttons/l2r.png'),
new THREE.TextureLoader().load('imgs/buttons/ci.png'),
new THREE.TextureLoader().load('imgs/buttons/ov.png'),
new THREE.TextureLoader().load('imgs/buttons/ttv.png'),
new THREE.TextureLoader().load('imgs/buttons/tw.png'),
new THREE.TextureLoader().load('imgs/buttons/ffs.png')];
var usedMats = [];
for (var i1 = 0; i1 < numOfBtns; i1++){
var matIdx = Math.floor(Math.random() * (max - min + 1)) + min;
var matTx = btnMats[matIdx];
if (usedMats.includes(matTx)){
while (usedMats.includes(matTx)){
matIdx = Math.floor(Math.random() * (max - min + 1)) + min;
matTx = btnMats[matIdx];
}
}
usedMats.push(matTx);
//var matTx = new THREE.TextureLoader().load('imgs/buttons/georo.png')
var geom2 = new THREE.CircleGeometry(3,50);
var mat = new THREE.MeshBasicMaterial({map:matTx});
btn = new THREE.Mesh(geom2, mat);
btn.angle = new THREE.Vector3(Math.random(),
Math.random(),
Math.random()).normalize();
btn.orbitSpeed = 0.0045; //Math.random() * 0.05) * 0.5;
plane.normal.copy(btn.angle);
point.set(Math.random(),Math.random(),Math.random());
plane.projectPoint(point, btn.position);
if (Math.random() > 0.5) { btn.orbitSpeed *= -1; }
btn.position.setLength(Math.floor(Math.random() * 20) + 15);
btn.position.applyAxisAngle(btn.angle, Math.random() / 10);
btn.position.add(nucleus.position);
buttons.push(btn);
scene.add(btn);
}
}
function updateBtns() {
var obj = null;
for (var i1 = 0; i1 < numOfBtns; i1++){
obj = buttons[i1];
obj.position.sub(nucleus.position);
obj.position.applyAxisAngle(obj.angle,obj.orbitSpeed);
obj.position.add(nucleus.position);
//if (i1 == 0){ console.log(obj.position); }
}
}
function init() {
document.body.style.backgroundColor = "#333333";
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
mouse = new THREE.Vector2();
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
document.body.style.overflow = "hidden";
document.body.style.margin = "0";
document.body.style.padding = "0";
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(fov, width/height, near, far);
camera.position.z = 100;
scene.add(camera);
//controls = new THREE.TrackballControls(camera, renderer.domElement);
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
projector = new THREE.Projector();
resize();
window.onresize = resize;
populateScene();
animate();
}
function onDocumentMouseMove( event )
{
// the following line would stop any other event handler from firing
// (such as the mouse's TrackballControls)
event.preventDefault();
// update the mouse variable
mouse.x = ( event.clientX / renderer.domElement.clientWidth) * 2 - 1;
mouse.y = -( event.clientY / renderer.domElement.clientHeight) * 2 + 1;
console.log("mouse pos: " + mouse.x + ", " + mouse.y);
}
function resize(){
width = window.innerWidth;
height = window.innerHeight;
if (renderer && camera){
renderer.setSize(width, height);
camera.aspect = width / height;
camera.updateProjectionMatrix();
}
}
function render(){
renderer.render(scene, camera);
}
function animate(){
checkMouse();
requestAnimationFrame(animate);
updateBtns();
render();
//checkMouseHover();
}
function checkMouse(){
var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );
console.log("ray vec: " + vector.x + ", " + vector.y);
projector.unprojectVector( vector, camera );
var ray = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
// create an array containing all objects in the scene with which the ray intersects
var intersects = ray.intersectObjects( scene.children, true );
// INTERSECTED = the object in the scene currently closest to the camera
// and intersected by the Ray projected from the mouse position
// 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 && intersects[0].object !== nucleus) {
// restore previous intersection object (if it exists) to its original color
if ( INTERSECTED ) {
console.log("Intersection detected at: " + intersects[0].point);
INTERSECTED = intersects[0].object;
INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
// store reference to closest object as current intersection 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( 0xffff00 );
}
}
}
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;
}
}
function onMouseOver(ev){
insObjSpeed = ev.object.orbitSpeed;
//ev.object.orbitSpeed = 0.0;
}
function onMouseOut(ev) { ev.object.orbitSpeed = insObjSpeed; }
function THREEReady() { init(); }
function onMouseMove(event){
mouse.x = (event.clientX/width)*2-1;
mouse.y = (event.clientY/height)*2-1;
}
(function() {
window.addEventListener('mousemove',onMouseMove,false);
function addScript(url, callback){
callback = callback || function() {};
var script = document.createElement("script");
script.addEventListener("load", callback);
script.setAttribute("src", url);
document.head.appendChild(script);
}
addScript("./js/ThreeJS_0.119.1.js",function() {
addScript("./js/ThreeJS_0.119.1_Projector.js",function(){
THREEReady();
})});
})();
</script>
</body>
首先,您的 mouseMove()
在 y-value 计算之前缺少负号。这意味着您的 y-value 被翻转了(它应该是 +1
时是 -1
)它应该如下所示:
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
其次,我不确定您为什么要在每一帧上创建一个新的 Vector3,而您只能使用现有的 mouse
Vector2,如 outlined in the docs。
// 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 );
无需执行 unprojectVector
然后减去相机位置,或者如果您使用 setFromCamera()
.
编辑:只要意识到您还有两个相互覆盖的侦听器(onMouseMove
和 onDocumentMouseMove
),其中一个的计算公式错误 mouse.y
,这就是原因你得到一个倒置的 y 值。
我正在尝试使用 Three.JS 重新创建一个 Flash 网站,但在尝试创建某些功能时遇到了 运行 障碍。
应该发生的是我想让一些按钮图像围绕屏幕中心旋转。如果鼠标悬停在它们上面然后单击以打开网站上的不同位置,它们应该能够停止。
我已经完成了所有工作,直到要求当鼠标悬停在按钮上时按钮停止。我正在尝试使用光线投射来实现这一点,但是当我在场景中移动鼠标时,似乎网格与渲染纹理不在同一位置。事实上,网格和渲染图像几乎看起来是在彼此相反的方向上运行。
这是我的代码,我将 link 您转到我网站上的一个页面,我正在该页面上测试此改版,以便您获得真实世界的示例:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style type="text/css">
body { margin: 0;}
canvas { display: block;}
</style>
</head>
<body>
<script>
//var THREE = new THREE();
var renderer,scene,camera,nucleus;
var width = window.innerWidth;
var height = window.innerHeight;
var fov = 60;
var near = 1;
var far = 10000;
var min = 0;
var max = 10;
var insObjSpeed = 0;
var buttons = [];
var numOfBtns = 1;
var projector, mouse = { x: 0, y: 0 }, INTERSECTED;
//var mouse;
function populateScene(){
var geom = new THREE.CircleGeometry(3,50);
var matTx = new THREE.TextureLoader().load('imgs/buttons/logo.png');
var mat = new THREE.MeshBasicMaterial({map:matTx});
nucleus = new THREE.Mesh(geom, mat);
nucleus.position.set(0,0,0);
scene.add(nucleus);
var btn = null;
var btnMat = null;
var plane = new THREE.Plane();
var point = new THREE.Vector3();
var btnMats = [new THREE.TextureLoader().load('imgs/buttons/georo.png'),
new THREE.TextureLoader().load('imgs/buttons/wiki.png'),
new THREE.TextureLoader().load('imgs/buttons/port.png'),
new THREE.TextureLoader().load('imgs/buttons/yt.png'),
new THREE.TextureLoader().load('imgs/buttons/l2r.png'),
new THREE.TextureLoader().load('imgs/buttons/ci.png'),
new THREE.TextureLoader().load('imgs/buttons/ov.png'),
new THREE.TextureLoader().load('imgs/buttons/ttv.png'),
new THREE.TextureLoader().load('imgs/buttons/tw.png'),
new THREE.TextureLoader().load('imgs/buttons/ffs.png')];
var usedMats = [];
for (var i1 = 0; i1 < numOfBtns; i1++){
var matIdx = Math.floor(Math.random() * (max - min + 1)) + min;
var matTx = btnMats[matIdx];
if (usedMats.includes(matTx)){
while (usedMats.includes(matTx)){
matIdx = Math.floor(Math.random() * (max - min + 1)) + min;
matTx = btnMats[matIdx];
}
}
usedMats.push(matTx);
//var matTx = new THREE.TextureLoader().load('imgs/buttons/georo.png')
var geom2 = new THREE.CircleGeometry(3,50);
var mat = new THREE.MeshBasicMaterial({map:matTx});
btn = new THREE.Mesh(geom2, mat);
btn.angle = new THREE.Vector3(Math.random(),
Math.random(),
Math.random()).normalize();
btn.orbitSpeed = 0.0045; //Math.random() * 0.05) * 0.5;
plane.normal.copy(btn.angle);
point.set(Math.random(),Math.random(),Math.random());
plane.projectPoint(point, btn.position);
if (Math.random() > 0.5) { btn.orbitSpeed *= -1; }
btn.position.setLength(Math.floor(Math.random() * 20) + 15);
btn.position.applyAxisAngle(btn.angle, Math.random() / 10);
btn.position.add(nucleus.position);
buttons.push(btn);
scene.add(btn);
}
}
function updateBtns() {
var obj = null;
for (var i1 = 0; i1 < numOfBtns; i1++){
obj = buttons[i1];
obj.position.sub(nucleus.position);
obj.position.applyAxisAngle(obj.angle,obj.orbitSpeed);
obj.position.add(nucleus.position);
//if (i1 == 0){ console.log(obj.position); }
}
}
function init() {
document.body.style.backgroundColor = "#333333";
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
mouse = new THREE.Vector2();
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
document.body.style.overflow = "hidden";
document.body.style.margin = "0";
document.body.style.padding = "0";
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(fov, width/height, near, far);
camera.position.z = 100;
scene.add(camera);
//controls = new THREE.TrackballControls(camera, renderer.domElement);
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
projector = new THREE.Projector();
resize();
window.onresize = resize;
populateScene();
animate();
}
function onDocumentMouseMove( event )
{
// the following line would stop any other event handler from firing
// (such as the mouse's TrackballControls)
event.preventDefault();
// update the mouse variable
mouse.x = ( event.clientX / renderer.domElement.clientWidth) * 2 - 1;
mouse.y = -( event.clientY / renderer.domElement.clientHeight) * 2 + 1;
console.log("mouse pos: " + mouse.x + ", " + mouse.y);
}
function resize(){
width = window.innerWidth;
height = window.innerHeight;
if (renderer && camera){
renderer.setSize(width, height);
camera.aspect = width / height;
camera.updateProjectionMatrix();
}
}
function render(){
renderer.render(scene, camera);
}
function animate(){
checkMouse();
requestAnimationFrame(animate);
updateBtns();
render();
//checkMouseHover();
}
function checkMouse(){
var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );
console.log("ray vec: " + vector.x + ", " + vector.y);
projector.unprojectVector( vector, camera );
var ray = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
// create an array containing all objects in the scene with which the ray intersects
var intersects = ray.intersectObjects( scene.children, true );
// INTERSECTED = the object in the scene currently closest to the camera
// and intersected by the Ray projected from the mouse position
// 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 && intersects[0].object !== nucleus) {
// restore previous intersection object (if it exists) to its original color
if ( INTERSECTED ) {
console.log("Intersection detected at: " + intersects[0].point);
INTERSECTED = intersects[0].object;
INTERSECTED.material.color.setHex( INTERSECTED.currentHex );
// store reference to closest object as current intersection 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( 0xffff00 );
}
}
}
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;
}
}
function onMouseOver(ev){
insObjSpeed = ev.object.orbitSpeed;
//ev.object.orbitSpeed = 0.0;
}
function onMouseOut(ev) { ev.object.orbitSpeed = insObjSpeed; }
function THREEReady() { init(); }
function onMouseMove(event){
mouse.x = (event.clientX/width)*2-1;
mouse.y = (event.clientY/height)*2-1;
}
(function() {
window.addEventListener('mousemove',onMouseMove,false);
function addScript(url, callback){
callback = callback || function() {};
var script = document.createElement("script");
script.addEventListener("load", callback);
script.setAttribute("src", url);
document.head.appendChild(script);
}
addScript("./js/ThreeJS_0.119.1.js",function() {
addScript("./js/ThreeJS_0.119.1_Projector.js",function(){
THREEReady();
})});
})();
</script>
</body>
首先,您的 mouseMove()
在 y-value 计算之前缺少负号。这意味着您的 y-value 被翻转了(它应该是 +1
时是 -1
)它应该如下所示:
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
其次,我不确定您为什么要在每一帧上创建一个新的 Vector3,而您只能使用现有的 mouse
Vector2,如 outlined in the docs。
// 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 );
无需执行 unprojectVector
然后减去相机位置,或者如果您使用 setFromCamera()
.
编辑:只要意识到您还有两个相互覆盖的侦听器(onMouseMove
和 onDocumentMouseMove
),其中一个的计算公式错误 mouse.y
,这就是原因你得到一个倒置的 y 值。