专栏首页前端之攻略threejs 之 复制删除正方体 原

threejs 之 复制删除正方体 原

这是threejs官方的一个例子webgl_interactive_voxelpainter.html  查看效果 查看效果

红色的正方体随着鼠标的移动而移动,单击时会创建另一个正方体,按住shift单击会删除点击的正方体。

主要用到的知识点

1、设置物体的位置为射线与物体相交的位置,并且把物体的位置设置到网格中心且高度全部在网格的上面

rollOverMesh.position.copy(intersect.point).add(intersect.face.normal)
rollOverMesh.position.divideScalar(50).floor().multiplyScalar(50).addScalar(25)

完整的代码:

<script src="../dist/js/three.js"></script>
<script src="../dist/js/WebGL.js"></script>
    <script>
    if (WEBGL.isWebGLAvailable() === false) {
        document.body.appendChild(WEBGL.getWebGLErrorMessage());
    }

    var camera, scene, renderer;
    var plane, cube;
    var mouse, raycaster, isShiftDown = false;

    var rollOverMesh, rollOverMaterial;
    var cubeGeo, cubeMaterial;
    var objects = [];
    var width, height;
    init();
    render();

    function init() {
        var container = document.getElementById('canvasWrap')
        width = document.getElementById('canvasWrap').clientWidth;
        height = document.getElementById('canvasWrap').clientHeight;
        camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);
        camera.position.set(150, 350, 1000); //position(0,300,1000) 中间的线会不显示
        camera.lookAt(0, 0, 0);

        scene = new THREE.Scene();
        scene.background = new THREE.Color(0xf0f0f0);

        //roll-over helpers
        var rollOverGeo = new THREE.BoxBufferGeometry(50, 50, 50);
        rollOverMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000, opacity: 0.5, transparent: true })
        rollOverMesh = new THREE.Mesh(rollOverGeo, rollOverMaterial);
        rollOverMesh.position.set(0, 25, 0)
        //console.log(rollOverMesh)
        scene.add(rollOverMesh);

        //cubes
        cubeGeo = new THREE.BoxBufferGeometry(50, 50, 50);
        cubeMaterial = new THREE.MeshLambertMaterial({ color: 0xfeb74c, map: new THREE.TextureLoader().load("../dist/textures/square-outline-textured.png") });
        var voxel = new THREE.Mesh(cubeGeo, cubeMaterial);
        voxel.position.set(500, 500, 0)
        console.log(voxel)
        //grid
        var gridHelper = new THREE.GridHelper(1000, 20, "red", "green");
        //gridHelper.position.set(0,-50,0)
        //console.log(gridHelper)
        scene.add(gridHelper)

        //raycaster
        raycaster = new THREE.Raycaster();
        mouse = new THREE.Vector2();

        var geometry = new THREE.PlaneBufferGeometry(1000, 1000)
        geometry.rotateX(-Math.PI / 2);

        plane = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({ visible: true }));
        //plane.position.set(0,-50,0)
        //console.log(plane)
        scene.add(plane);
        objects.push(plane);

        // lights
        var ambientLight = new THREE.AmbientLight(0x606060);
        scene.add(ambientLight);

        var directionalLight = new THREE.DirectionalLight(0xf3821e);
        //向量坐标都除于向量的长度
        //{1,2,3},长度是√1²+2²+3²=√14
        //标准化之后是
        //{1/√14,2/√14,3/√14}
        //新向量的长度恰好为1
        //directionalLight.position.set(1,0.75,0.5); //.normalize()好像不用也没看出啥区别
        directionalLight.position.set(100, 300, 300) //.normalize(); //设置平行光方向,normalize()正则化,变为单位向量
        scene.add(directionalLight);

        renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(width, height);
        container.appendChild(renderer.domElement);

        document.addEventListener("mousemove", onDocumentMouseMove, false);
        document.addEventListener("mousedown", onDocumentMouseDown, false);
        document.addEventListener("keydown", onDocumentKeyDown, false);
        document.addEventListener("keyup", onDocumentKeyUp, false);

        window.addEventListener("resize", onWindowResize, false);


    }


    function onWindowResize(event) {
        camera.aspect = width / height;
        camera.updateProjectionMatrix();
        renderer.setSize(width, height);
    }

    function onDocumentMouseMove(event) {
        event.preventDefault();
        //转换坐标至(-1,1)范围
        mouse.set((event.layerX / width) * 2 - 1, -(event.layerY / height) * 2 + 1);

        raycaster.setFromCamera(mouse, camera);
        var intersects = raycaster.intersectObjects(objects);
        if (intersects.length > 0) {
            var intersect = intersects[0];
            rollOverMesh.position.copy(intersect.point).add(intersect.face.normal)
            rollOverMesh.position.divideScalar(50).floor().multiplyScalar(50).addScalar(25)
        }
        render();
    }

    function onDocumentMouseDown(event) {
        event.preventDefault();
        mouse.set((event.layerX / width) * 2 - 1, -(event.layerY / height) * 2 + 1);
        raycaster.setFromCamera(mouse, camera);
        var intersects = raycaster.intersectObjects(objects);
        if (intersects.length > 0) {
            var intersect = intersects[0];
            //delete cube
            if (isShiftDown) {
                if (intersect.object !== plane) {
                    scene.remove(intersect.object);
                    objects.splice(objects.indexOf(intersect.object), 1)
                }
                // create cube
            } else {
                var voxel = new THREE.Mesh(cubeGeo, cubeMaterial);
                voxel.position.copy(intersect.point).add(intersect.face.normal);
                //.divideScalar ( s : Float )将该向量除以标量S
                //.multiplyScalar ( s : Float )将该向量与所传入的标量s进行相乘。
                //.floor () 向量的分量向下取整为最接近的整数值。
                //addScalar(s:Float)将传入的标量S和这个向量的X值、Y值以及Z值相加
                //下面重新设置position的目的是移动的方块的中心在网格的中心,Y轴为25
                voxel.position.divideScalar(50).floor().multiplyScalar(50).addScalar(25);
                scene.add(voxel);
                objects.push(voxel)
            }
            render()

        }
    }


    function onDocumentKeyDown(event) {
        switch (event.keyCode) {
            case 16:
                isShiftDown = true;
                break;
        }
    }

    function onDocumentKeyUp(event) {
        switch (event.keyCode) {
            case 16:
                isShiftDown = false;
                break;
        }
    }

    function render() {
        renderer.render(scene, camera);
    }
    </script>

(adsbygoogle = window.adsbygoogle || []).push({});

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • threejs之显示Label-CSS2DRenderer

    1、采用threeJs的精灵(Sprite),具体用法查看我另一篇博客https://my.oschina.net/u/2612473/blog/3038066...

    tianyawhl
  • three.js 带更新文字的旋转地球

    tianyawhl
  • JavaScript 数组总结 原

    JavaScript没有明确的数组数据类型,但是外面可以通过使用内置Array对象和它的方法对数组进行操作,Array对象有很多操作数组的方法,比如 合并,反转...

    tianyawhl
  • 使用Identity Server 4建立Authorization Server (1)

    本文内容基本完全来自于Identity Server 4官方文档: https://identityserver4.readthedocs.io/ 官方文档很详...

    solenovex
  • WCF实现长连接

    由于WCF的机制,连接池会在连接建立一定时间后超时,即使设置了超时时间非常长,也可能被服务端系统主动回收。之前做项目时碰到了这个问题,所以项目上考虑采...

    少羽大怪兽
  • Java几种单例模式的实现与利弊

    多线程环境下无法保证单例效果,会多次执行 instance=new Singleton(),需要考虑到多线程

    用户1154259
  • Java装饰者模式(decorator)

      装饰者模式又称为包装模式(Wrapper),作用是用来动态的为一个对象增加新的功能。装饰模式是一种用于代替继承的技术,无须通过继承增加子类就能扩展对象的新功...

    用户4919348
  • 重拾Kotlin(2)-包、类型别名、修饰符

    Kotlin 文件都能以一条 package 语句开头,而文件中定义的所有声明(类、函数和属性)都会被放到这个包中。如果其他文件中定义的声明也有相同的包,这个文...

    叶应是叶
  • 设计师编程指南之Sketch插件开发 8 之Cocoa基础知识

    往期文章索引: 1 / 入门基本概念、page的相关操作 2 / artboard 、NSFileManager 和 NSString 关于文件及文件夹的相关操...

    mixlab
  • 简单实现MySQL数据库的日志审计

    由于MySQL社区版没有自带的审计功能或插件,对于等级保护当中对数据库管理的要求的就存在一定的不满足情况的,抛开条条框框不说数据库的日志是值得研究的,通过收集数...

    FB客服

扫码关注云+社区

领取腾讯云代金券