<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Select Object</title>
<script src="../../three-part/threejs/three.js"></script>
<script src="../../three-part/utils/stats.min.js"></script>
<script src="../../three-part/utils/dat.gui.min.js"></script>
<script src="../controls/TrackballControls.js"></script>
<script src="../util/util.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="container"></div>
<script type="text/javascript">
init();
function init() {
// show FPS
let stats = initStats();
// resize
window.addEventListener('resize', onResize, false);
document.addEventListener('click', onDocumentMouseDown, false);
document.addEventListener('mousemove', onDocumentMouseMove, false);
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 30;
camera.lookAt(scene.position);
let renderer = new THREE.WebGLRenderer();
renderer.setClearColor(new THREE.Color(0x000000));
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
document.getElementById("container").appendChild(renderer.domElement);
// init trackball control
let trackballControls = initTrackballControls(camera, renderer);
let clock = new THREE.Clock();
let tube;
// add a plane
let planeGeometry = new THREE.PlaneGeometry(100, 100, 1, 1);
let planeMaterial = new THREE.MeshLambertMaterial({
color: 0xffffff
});
let plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.receiveShadow = true;
plane.rotation.x = -0.5 * Math.PI;
scene.add(plane);
// create a cube
let cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
let cubeMaterial = new THREE.MeshStandardMaterial({color: 0xff0000});
let cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.castShadow = true;
cube.position.set(-10, 4, 0);
scene.add(cube);
// create a sphere
let sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
let sphereMaterial = new THREE.MeshStandardMaterial({color: 0x7777ff});
let sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.set(20, 5, 2);
sphere.castShadow = true;
scene.add(sphere);
// create a cylinder
let cylinderGeometry = new THREE.CylinderGeometry(2, 2, 20);
let cylinderMaterial = new THREE.MeshStandardMaterial({color: 0x77ff77});
let cylinder = new THREE.Mesh(cylinderGeometry, cylinderMaterial);
cylinder.castShadow = true;
cylinder.position.set(0, 5, 1);
scene.add(cylinder);
let ambienLight = new THREE.AmbientLight(0x353535, 3);
scene.add(ambienLight);
// attributes which can be modified in GUI
const controls = {
"showRay" : false
};
// init GUI
initGUI();
renderScene();
function initGUI(){
let gui = new dat.GUI();
gui.add(controls, 'showRay').onChange(function (e) {
if (tube) scene.remove(tube)
});
}
function onResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onDocumentMouseDown(event) {
let vector = new THREE.Vector3((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1, 0.5);
// Unprojects the vector with the camera's projection matrix.
vector = vector.unproject(camera);
/**
* Raycaster( origin : Vector3, direction : Vector3, near : Float, far : Float ) {
* origin — The origin vector where the ray casts from.
* direction — The direction vector that gives direction to the ray. Should be normalized.
* near — All results returned are further away than near. Near can't be negative. Default value is 0.
* far — All results returned are closer than far. Far can't be lower than near. Default value is Infinity.
* @type {Raycaster}
*/
let raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
/**
* intersectObjects ( objects : Array, recursive : Boolean, optionalTarget : Array )
* objects — The objects to check for intersection with the ray.
* recursive — If true, it also checks all descendants of the objects. Otherwise it only checks intersection with the objects. Default is false.
* optionalTarget — (optional) target to set the result. Otherwise a new Array is instantiated. If set, you must clear this array prior to each call (i.e., array.length = 0;).
* Checks all intersection between the ray and the objects with or without the descendants.
* Intersections are returned sorted by distance, closest first.
*/
let intersects = raycaster.intersectObjects([sphere, cylinder, cube]);
if (intersects.length > 0) {
intersects[0].object.material.transparent = true;
intersects[0].object.material.opacity = 0.1;
}
}
function onDocumentMouseMove(event) {
if (controls.showRay) {
let vector = new THREE.Vector3((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1, 0.5);
vector = vector.unproject(camera);
let raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
let intersects = raycaster.intersectObjects([sphere, cylinder, cube]);
if (intersects.length > 0) {
let points = [];
points.push(new THREE.Vector3(-30, 39.8, 30));
points.push(intersects[0].point);
let mat = new THREE.MeshBasicMaterial({color: 0xff0000, transparent: true, opacity: 0.6});
/**
* TubeGeometry(path : Curve, tubularSegments : Integer, radius : Float, radialSegments : Integer, closed : Boolean)
* path — Curve - A path that inherits from the Curve base class
* tubularSegments — Integer - The number of segments that make up the tube, default is 64
* radius — Float - The radius of the tube, default is 1
* radialSegments — Integer - The number of segments that make up the cross-section, default is 8
* closed — Boolean Is the tube open or closed, default is false
*
* CatmullRomCurve3( points : Array, closed : Boolean, curveType : String, tension : Float )
* points – An array of Vector3 points
* closed – Whether the curve is closed. Default is false.
* curveType – Type of the curve. Default is centripetal.
* tension – Tension of the curve. Default is 0.5.
* @type {TubeGeometry}
*/
let tubeGeometry = new THREE.TubeGeometry(new THREE.CatmullRomCurve3(points), 60, 0.001);
if (tube) scene.remove(tube);
if (controls.showRay) {
tube = new THREE.Mesh(tubeGeometry, mat);
scene.add(tube);
}
}
}
}
function renderScene(){
trackballControls.update(clock.getDelta());
stats.update();
requestAnimationFrame(renderScene);
renderer.render(scene, camera);
}
}
</script>
</body>
</html>
运行结果:
-
选中模型:
-
显示射线:
网友评论