ThreeJS:在鼠标单击坐标处绘制线条



我正在与ThreeJS合作创建一个太阳系。我有一个太阳在中间,绕着它有8个轨道。现在我想在用户点击地图上的任意位置时获得最近的环位!

这是一张图片,直观地描述我的意思

箭头代表用户的"点击",然后应该有一个函数来获取最近的轨道及其坐标(白点),点击点和中间之间的线碰撞。

尝试了在这里找到的许多不同功能,但没有一个给了我想要的结果。

感谢您的帮助!

代码当前如下所示:

            var container, stats, parent, pivots, domEvents, twins, planets, sun, fleets, raycaster, mouse;
            var camera, controls, scene, renderer;
            var cross;
            planets = new Array();
            init();
            animate();
            function init()
            {

                raycaster = new THREE.Raycaster();
                mouse = new THREE.Vector2();
                //init
                camera = new THREE.PerspectiveCamera(10, 1, 1, 4000);
                camera.position.z = 200;
                camera.position.x = 200;
                camera.position.y = 200;
                controls = new THREE.OrbitControls(camera);
                controls.addEventListener('change', render);
                scene = new THREE.Scene();
                scene.fog = new THREE.FogExp2(0x000000, 0);
                // renderer
                renderer = new THREE.WebGLRenderer({antialias: false, alpha: true});
                renderer.setSize(document.getElementById('canvasreference').offsetWidth, document.getElementById('canvasreference').offsetWidth);
                renderer.setClearColor(0x787878, 0.5); // the default
                container = document.getElementById('canvasreference');
                container.appendChild(renderer.domElement);
                window.addEventListener('resize', onWindowResize, false);
                domEvents = new THREEx.DomEvents(camera, renderer.domElement);
                //axihelper
                scene.add(new THREE.AxisHelper(130));
                // parent
                parent = new THREE.Object3D();
                scene.add(parent);
                //arrays
                orbits = new Array();

                addOrbit();
                window.addEventListener('click', onMouseMove, false);
            }

            function onMouseMove(event) {
                    canvas = renderer.domElement;
                raycaster = new THREE.Raycaster();
                mousePosition = new THREE.Vector2();
                canvasPosition = $("#canvasreference canvas").position();
                console.log(canvasPosition);
                mousePosition.x = ((event.clientX - canvasPosition.left) / canvas.width) * 2 - 1;
                mousePosition.y = -((event.clientY - canvasPosition.top) / canvas.height) * 2 + 1;
                raycaster.setFromCamera(mousePosition, camera);

                 var geometry = new THREE.Geometry();
                 var origin = new THREE.Vector3(raycaster.ray.origin.x, 0, raycaster.ray.origin.y);
                 geometry.vertices.push(origin);
                 var vektor = new THREE.Vector3(raycaster.ray.direction.x, 0, raycaster.ray.direction.y);
                 for (var i = 0; i < 1000; i++)
                 {
                 origin.add(vektor);
                 geometry.vertices.push(vektor);
                 }

                 var material = new THREE.LineBasicMaterial({
                 color: 0xffffff, linewidth: 20
                 });
                 var line = new THREE.Line(geometry, material);
                 scene.add(line);
                 renderer.render(scene, camera);


            }
            function onWindowResize() {
                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();
                renderer.setSize(600, 600);
                render();
            }
            function animate() {
                requestAnimationFrame(animate);
                controls.update();
                renderer.render(scene, camera);
            }
            function render() {
                renderer.render(scene, camera);
            }

            /**
             * add Orbit line
             * @param {type} orbit
             * @returns {undefined}
             */
            function addOrbit(orbit)
            {
                for (var i = 0; i < 8; i++)
                {
                    //make orbit line
                    var orbit = new THREE.EllipseCurve(
                            0, 0, // ax, aY
                            i * 10 + 30, i * 10 + 30, // xRadius, yRadius
                            0, 2 * Math.PI, // aStartAngle, aEndAngle
                            false, // aClockwise
                            0                 // aRotation 
                            );
                    var path = new THREE.Path(orbit.getPoints(100));
                    var geometry = path.createPointsGeometry(100);
                    var material = new THREE.LineBasicMaterial({color: 0xffffff});
                    var ellipse = new THREE.Line(geometry, material);
                    ellipse.rotation.x = 1.5708;
                    scene.add(ellipse);
                }
            }

        </script>

将光线从相机投射到鼠标所在的点。然后使用distanceToPoint函数检查从该射线到太阳系中部的最近距离。输出矢量的长度将是光线与之相切的球体的半径。使用此长度,您可以确定与轨道球体的距离以及是否应选择它。以下是该检查的一些伪代码:

var length = getDistanceToCenter(...);
var closestSphere = _(orbits).min(function(orbit) { return Math.abs(length - orbit.radius); });
if (Math.abs(closestSphere.radius - length) < EPSILON) { 
    selectOrbit(closestSphere);
}

最新更新