码农PHP666 2019-11-04 18:47 采纳率: 0%
浏览 1080

各位大神们,谁知道怎样通过three.js导入外部3d模型,然后可以拖动模型,并且模型的一部分不能被单独拖动,这个问题困扰我很多天,现在还是没办法解决,求助各位大神了,万分感谢!

各位大神们,我现在可以导入3d模型,并且这个模型可以拖动,但是一部分模型被单独拖动,其他模型不动,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>拖拽控件</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }

        #label {
            position: absolute;
            padding: 10px;
            background: rgba(255, 255, 255, 0.6);
            line-height: 1;
            border-radius: 5px;
        }
    </style>
    <script src="js/three.js"></script>
    <script src="js/jquery-1.9.1.js"></script>
    <script src="js/Detector.js"></script>
    <script src="js/TrackballControls.js"></script>
    <script src="js/dat.gui.min.js"></script>
    <script src="js/stats.min.js"></script>
    <script src="js/OBJLoader.js"></script>
    <script src="js/FBXLoader.js"></script>
    <script src="js/inflate.min.js"></script>

    <!--拖拽控件-->
    <script src="js/DragControls.js"></script>
    <!--可视化平移控件-->
    <script src="js/TransformControls.js"></script>
</head>
<body>
<div id="WebGL-output"></div>
<div id="Stats-output"></div>

<div id="label"></div>
<script>
var objects=[];
    var stats = initStats();
    var scene, camera, renderer, controls, light, selectObject;

    // 场景
    function initScene() {
        scene = new THREE.Scene();
    }

    // 相机
    function initCamera() {
        camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
        camera.position.set(0, 400, 600);
        camera.lookAt(new THREE.Vector3(0, 0, 0));
    }

    // 渲染器
    function initRenderer() {
        if (Detector.webgl) {
            renderer = new THREE.WebGLRenderer({antialias: true});
        } else {
            renderer = new THREE.CanvasRenderer();
        }
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.setClearColor(0x050505);
        document.body.appendChild(renderer.domElement);
    }

    // 初始化模型
    function initContent() {

        var helper = new THREE.GridHelper(1800, 50, 0x4A4A4A);
        helper.setColors(0x9370DB);
        scene.add(helper);

        var loader = new THREE.OBJLoader();
        loader.load( "moder/obj/windmill.obj", function ( group ) {
            group.position.x=400;
             group.scale.set(20, 20, 20);//模型放大20倍
            //group.scale.color(0x3CB37
            group.name="groups"
             scene.add( group );

            objects.push(group);
        } );

        var loader = new THREE.OBJLoader();
        loader.load( "moder/obj/low.obj", function ( group ) {
            group.position.x=-400;
            group.scale.set(20, 20, 20);//模型放大20倍
            //group.scale.color(0x3CB37
            group.name="groupss";
            scene.add( group );
            objects.push(group);
        } );


        var loader = new THREE.FBXLoader();
        //Samba Dancing idle_2
        loader.load( 'moder/fbx/pipeline.fbx', function ( object ) {
            //console.log(object);
            object.scale.set(1,1,1);
            scene.add( object );
            objects.push(object);
            mixers=object.mixer = new THREE.AnimationMixer( object );
            var action = object.mixer.clipAction( object.animations[0]);
            action.play();

            object.traverse( function ( child ) {

                if ( child.isMesh ) {

                    child.castShadow = true;
                    child.receiveShadow = true;

                }

            } );
            console.log(object);
        } );

        /*var cubeGeometry = new THREE.BoxGeometry(100, 100, 100);
        var cubeMaterial = new THREE.MeshLambertMaterial({color: 0x9370DB});
        var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
        cube.position.x = -600;
        cube.position.y = 50;
        cube.name = "cubes";
        scene.add(cube);

        var sphereGeometry = new THREE.SphereGeometry(50, 50, 50, 50);
        var sphereMaterial = new THREE.MeshLambertMaterial({color: 0x3CB371});
        var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
        sphere.position.x = 200;
        sphere.position.y = 50;
        sphere.name = "sphere";
        // sphere.position.z = 200;
        scene.add(sphere);

        var cylinderGeometry = new THREE.CylinderGeometry(50, 50, 100, 100);
        var cylinderMaterial = new THREE.MeshLambertMaterial({color: 0xCD7054});
        var cylinder = new THREE.Mesh(cylinderGeometry, cylinderMaterial);
        cylinder.position.x = -200;
        cylinder.position.y = 50;
        cylinder.name = "cylinder";
        scene.add(cylinder);*/
    }

console.log(objects);
    // 鼠标双击触发的方法
    function onMouseDblclick(event) {

        // 获取 raycaster 和所有模型相交的数组,其中的元素按照距离排序,越近的越靠前
        var intersects = getIntersects(event);

        // 获取选中最近的 Mesh 对象
        if (intersects.length != 0 && intersects[0].object ) {
            selectObject = intersects[0].object.parent;

            changeMaterial(selectObject);
            console.log(changeMaterial);
        } else {
            alert("未选中 Mesh!");
        }
    }

    // 获取与射线相交的对象数组
    function getIntersects(event) {
        event.preventDefault();
        console.log("event.clientX:" + event.clientX)
        console.log("event.clientY:" + event.clientY)

        // 声明 raycaster 和 mouse 变量
        var raycaster = new THREE.Raycaster();
        var mouse = new THREE.Vector2();

        // 通过鼠标点击位置,计算出 raycaster 所需点的位置,以屏幕为中心点,范围 -1 到 1
        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

        //通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线位置
        raycaster.setFromCamera(mouse, camera);

        // 获取与射线相交的对象数组,其中的元素按照距离排序,越近的越靠前
        var intersects = raycaster.intersectObjects(scene.children);
        var intersects=intersects.parent;
        console.log(intersects);
        //返回选中的对象
        return intersects;
    }

    // 窗口变动触发的方法
    function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
    }

    // 键盘按下触发的方法
    function onKeyDown(event) {
        switch (event.keyCode) {
            case 13:
                initCamera();
                initControls();
                break;
        }
    }

    // 改变对象材质属性
    function changeMaterial(object) {

        var material = new THREE.MeshLambertMaterial({
            color: 0xffffff * Math.random(),
            transparent: object.material.transparent ? false : true,
            opacity: 0.8,
        });
        object.material = material;
    }

    // 初始化轨迹球控件
    function initControls() {
        controls = new THREE.TrackballControls(camera, renderer.domElement);
        // controls.noRotate = true;
        controls.noPan = true;
        // 视角最小距离
        controls.minDistance = 1000;
        // 视角最远距离
        controls.maxDistance = 5000;
    }

    // 添加拖拽控件
    function initDragControls() {
        // 添加平移控件
        var transformControls = new THREE.TransformControls(camera, renderer.domElement);
        scene.add(transformControls);

        // 过滤不是 Mesh 的物体,例如辅助网格
        //var objects = [];
    /*for (let i = 0; i < scene.children.length; i++) {
            if (scene.children[i].isMesh) {
                    objects.push(scene.children[i]);

            }
            //objects.push(object[i].parent);
        }*/


        // 初始化拖拽控件
        var dragControls = new THREE.DragControls(objects, camera, renderer.domElement);

        // 鼠标略过事件
        dragControls.addEventListener('hoveron', function (event) {
            // 让变换控件对象和选中的对象绑定
            transformControls.attach(event.object);

        });
        // 开始拖拽

            dragControls.addEventListener('dragstart', function (event) {
                controls.enabled = false;
            });


        // 拖拽结束

            dragControls.addEventListener('dragend', function (event) {
                controls.enabled = true;
            });

        console.log(objects.length);
    }

    // 初始化灯光
    function initLight() {
        light = new THREE.SpotLight(0xffffff);
        light.position.set(-300, 600, -400);
        light.castShadow = true;

        scene.add(light);
        scene.add(new THREE.AmbientLight(0x5C5C5C));
    }

    // 初始化 dat.GUI
    function initGui() {
        // 保存需要修改相关数据的对象
        gui = new function () {

        }
        // 属性添加到控件
        var guiControls = new dat.GUI();
    }

    // 初始化性能插件
    function initStats() {
        var stats = new Stats();

        stats.domElement.style.position = 'absolute';
        stats.domElement.style.left = '0px';
        stats.domElement.style.top = '0px';

        document.body.appendChild(stats.domElement);
        return stats;
    }

    // 更新div的位置
    function renderDiv(object) {
        // 获取窗口的一半高度和宽度
        let halfWidth = window.innerWidth / 2;
        let halfHeight = window.innerHeight / 2;

        // 逆转相机求出二维坐标
        let vector = object.position.clone().project(camera);

        // 修改 div 的位置
        $("#label").css({
            left: vector.x * halfWidth + halfWidth,
            top: -vector.y * halfHeight + halfHeight - object.position.y
        });
        // 显示模型信息
        //$("#label").text("name:" + object.name);
    }

    // 更新控件
    function update() {
        stats.update();
        controls.update();
        controls.handleResize();
        //transformControls.update();
    }

    // 初始化
    function init() {
        initScene();
        initCamera();
        initRenderer();
        initContent();
        initLight();
        initControls();
        initGui();
        initDragControls();
        // addEventListener('dblclick', onMouseDblclick, false);
        addEventListener('resize', onWindowResize, false);
        addEventListener('keydown', onKeyDown, false);

    }

    function animate() {
        if (selectObject != undefined && selectObject != null) {
            renderDiv(selectObject);
        }
        requestAnimationFrame(animate);
        renderer.render(scene, camera);
        update();
    }

    init();
    animate();

</script>
</body>
</html>

一部分模型被单独拖动的效果如下:

图片说明

然后我再修改当鼠标略过事件:
图片说明

整个模型可以一起被拖动,但是模型混乱:效果图如下:

![图片说明](https://img-ask.csdn.net/upload/201911/05/1572916540_633061.png)

希望路过的好心人帮帮忙,万分感谢!!!!!!

  • 写回答

2条回答

  • will_zhanShmily 2023-05-22 17:49
    关注

    19年的问题,这怕是csdn数据出bug了

    评论

报告相同问题?

悬赏问题

  • ¥15 seatunnel-web使用SQL组件时候后台报错,无法找到表格
  • ¥15 fpga自动售货机数码管(相关搜索:数字时钟)
  • ¥15 用前端向数据库插入数据,通过debug发现数据能走到后端,但是放行之后就会提示错误
  • ¥30 3天&7天&&15天&销量如何统计同一行
  • ¥30 帮我写一段可以读取LD2450数据并计算距离的Arduino代码
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型
  • ¥15 vs2019中数据导出问题
  • ¥20 云服务Linux系统TCP-MSS值修改?
  • ¥20 关于#单片机#的问题:项目:使用模拟iic与ov2640通讯环境:F407问题:读取的ID号总是0xff,自己调了调发现在读从机数据时,SDA线上并未有信号变化(语言-c语言)
  • ¥20 怎么在stm32门禁成品上增加查询记录功能