做网站dw怎么用,吉安网站建设343000,网络seo优化公司,dw下载免费中文版光线投射Raycaster 光线投射详细介绍可参考#xff1a;https://en.wikipedia.org/wiki/Ray_casting#xff0c; ThreeJS中#xff0c;提供了Raycaster类#xff0c;用于进行鼠标拾取#xff0c;即#xff1a;当三维场景中鼠标移动时#xff0c;利用光线投射#xff0c;…光线投射Raycaster 光线投射详细介绍可参考https://en.wikipedia.org/wiki/Ray_casting ThreeJS中提供了Raycaster类用于进行鼠标拾取即当三维场景中鼠标移动时利用光线投射可计算出鼠标划过了哪些物体。 ThreeJS官方案例webgl_interactive_cubes演示了光线投射的具体应用 通过Raycaster类实例的intersectObjects方法可以获取到与射线Ray相交的一组物体 通过Raycaster类实例的intersectObject方法可以获取到与Ray射线相交的第一个物体 此外在鼠标点击或移动时我们是需要不断去更新Ray射线的这样才能选中正确的3D物体可以通过setFromCamera方法来更新射线 接着还有一个要解决的问题就是这里的标准化设备坐标中的二维坐标如何进行处理才是符合ThreeJS的接口规范的 核心代码如下
const mousePosition new THREE.Vector2(); //记录鼠标位置
//TODO:监听鼠标移动事件
function onPointerMove( event ) {mousePosition.x ( event.clientX / window.innerWidth ) * 2 - 1;mousePosition.y - ( event.clientY / window.innerHeight ) * 2 1;
}
document.addEventListener(mousemove,onPointerMove); 注意到计算mousePosition.y的计算结果相比mousePosition.x多乘了一个-1这是因为屏幕坐标系和ThreeJS的XYZ空间直角坐标系两者的Y轴是相反的。 3D场景鼠标交互案例 下面来实现一个利用光线投射控制鼠标选中物体高亮显示的案例主要效果如下
①鼠标选中物体高亮显示 ②鼠标离开物体取消高亮显示 完整示例代码如下
import * as THREE from three;
import { OrbitControls } from three/addons/controls/OrbitControls.js; //轨道控制器
import { GUI } from three/examples/jsm/libs/lil-gui.module.min.js; //lil-gui调试工具
import { RGBELoader } from three/examples/jsm/loaders/RGBELoader.js; //HDR加载器
import { GLTFLoader } from three/examples/jsm/loaders/GLTFLoader.js; //GLTF加载器
import { DRACOLoader } from three/examples/jsm/loaders/DRACOLoader.js;const gui new GUI();//TODO:打印版本
console.warn(threejs版本:, THREE.REVISION);
//TODO:创建时钟
const clock new THREE.Clock();
//TODO:创建场景
const scene new THREE.Scene();
//TODO:创建透视相机
const camera new THREE.PerspectiveCamera(45, //视角window.innerWidth / window.innerHeight,0.1, //近平面1000.0 //远平面
);//TODO:创建渲染器
const renderer new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);//TODO:轨道控制器
const orbitControls new OrbitControls(camera, renderer.domElement);
//设置阻尼效果
// orbitControls.enableDamping true;
orbitControls.update();document.body.appendChild(renderer.domElement);//TODO:添加光源
const light new THREE.PointLight(0xffffff, 1000, 1000);
light.position.set(15, 15, 15);
scene.add(light);scene.background new THREE.Color(0xbfe3dd);//TODO添加3个球体
const ball1 new THREE.SphereGeometry(1);
const ballMaterial new THREE.MeshBasicMaterial({color:0xffff00});
const ballMesh1 new THREE.Mesh(ball1,ballMaterial);
ballMesh1.geometry.scale(0.5,0.5,0.5);
ballMesh1.position.set(-1.0,-1.0,-1.0);const ballMesh2 new THREE.Mesh(ball1,ballMaterial);
ballMesh2.geometry.scale(0.5,0.5,0.5);
ballMesh2.position.set(1.0,-1.0,-1.0);const ballMesh3 new THREE.Mesh(ball1,ballMaterial);
ballMesh3.geometry.scale(0.5,0.5,0.5);
ballMesh3.position.set(1.0,1.0,-1.0);const ballMesh4 new THREE.Mesh(ball1,ballMaterial);
ballMesh4.geometry.scale(0.5,0.5,0.5);
ballMesh4.position.set(1.0,1.0,1.0);scene.add(ballMesh1);
scene.add(ballMesh2);
scene.add(ballMesh3);
scene.add(ballMesh4);//TODO:设置相机位置
camera.position.z 5.0;
camera.position.y 2.0;
camera.position.x 2.0;
camera.lookAt(0, 0, 0);//TODO:利用光线投射,使用鼠标选中Mesh
const rayCaster new THREE.Raycaster();
const mousePosition new THREE.Vector2(); //记录鼠标位置
const hightLightColor new THREE.Color(0xff0000);//高亮颜色
const highlightMaterial new THREE.MeshBasicMaterial({color:hightLightColor});
const lastSelected {originMaterial:null,//被选中的3D物体的materialinstance:null,//被选中的3D物体
}
//TODO:监听鼠标移动事件
function onPointerMove( event ) {mousePosition.x ( event.clientX / window.innerWidth ) * 2 - 1;mousePosition.y - ( event.clientY / window.innerHeight ) * 2 1;
}
document.addEventListener(mousemove,onPointerMove);//TODO:还原上一次被选中的3D物体
function resetLastSelected(){if(lastSelected.instance lastSelected.originMaterial){lastSelected.instance.material lastSelected.originMaterial;lastSelected.instance null;lastSelected.originMaterial null;}
}function pick3DObject(){// 通过摄像机和鼠标位置更新射线_[使用一个新的原点和方向来更新射线。]rayCaster.setFromCamera(mousePosition,camera);/*** objects —— 检测和射线相交的一组物体。recursive —— 若为true则同时也会检测所有物体的后代。否则将只会检测对象本身的相交部分。默认值为true。*/const interscets rayCaster.intersectObjects(scene.children,false);if(interscets.length0){const interscetObject interscets[ 0 ].object;console.log(interscets::,interscetObject);//TODO:还原上一次选中的3D物体resetLastSelected();if(interscetObject){//TODO:鼠标选中3D物体,设置高亮效果//记录当前被选中的物体lastSelected.instance interscetObject;lastSelected.originMaterial interscetObject.material;//设置高亮interscetObject.material highlightMaterial;}}else{//TODO:鼠标离开3D物体,还原MaterialresetLastSelected();}
}//TODO:创建坐标辅助器
// const axesHelper new THREE.AxesHelper(5);
// scene.add(axesHelper);//TODO:渲染函数
function animate() {requestAnimationFrame(animate);//TODO:旋转立方体// mesh.rotation.x 0.01;// mesh.rotation.y 0.01;pick3DObject();//TODO:更新轨道控制器orbitControls.update();//TODO:渲染renderer.render(scene, camera);
}
window.onresize function () {//TODO:重置渲染器宽高比renderer.setSize(window.innerWidth, window.innerHeight);//TODO:重置相机宽高比camera.aspect window.innerWidth / window.innerHeight;//TODO:更新相机投影矩阵camera.updateProjectionMatrix();
};animate();//TODO:lil-gui添加调试按钮
const myObject {// myBoolean: true,fullScreenBtnFunction: function () {document.body.requestFullscreen();},exitFullScreenBtnFunction: function () {document.exitFullscreen();},wireframeMode: false,renderMode: 1,colorSpace: 0,
};gui.add(myObject, fullScreenBtnFunction).name(全屏显示); // Button
gui.add(myObject, exitFullScreenBtnFunction).name(退出全屏); // Button
//TODO:开启/关闭线框模式
gui.add(myObject, wireframeMode).name(线框模式).onChange(function (value) {console.log(value);mesh.material.wireframe value;});
// gui.add(myObject, myString); // Text Field
// gui.add(myObject, myNumber); // Number Field//TODO:控制Mesh网格正反面显示模式
gui.add(myObject, renderMode, { 双面模式: 0, 正面模式: 1, 背面模式: 2 }).name(三角形正反面显示模式).onChange(function (value) {console.log(value);switch (value) {case 0: {triangleMesh.material.side THREE.DoubleSide;break;}case 1: {triangleMesh.material.side THREE.FrontSide;break;}case 2: {triangleMesh.material.side THREE.BackSide;break;}}});//TODO:控制颜色空间
gui.add(myObject, colorSpace, {NoColorSpace: 0,SRGBColorSpace: 1,LinearSRGBColorSpace: 2,}).onChange((value) {console.log(修改颜色空间::, value);switch (value) {case 0: {diffuseMap.colorSpace THREE.NoColorSpace;break;}case 1: {diffuseMap.colorSpace THREE.SRGBColorSpace;break;}case 2: {diffuseMap.colorSpace THREE.LinearSRGBColorSpace;break;}}});