初学WebGL引擎-BabylonJS:第6篇-碰撞交错与挑选

【playground】-collisions(碰撞)

 

先贴官方源码(机器翻译版本)

var createScene = function () {
    var scene = new BABYLON.Scene(engine);

    // Lights
    var light0 = new BABYLON.DirectionalLight("Omni", new BABYLON.Vector3(-2, -5, 2), scene);
    var light1 = new BABYLON.PointLight("Omni", new BABYLON.Vector3(2, -5, -2), scene);

    // Need a free camera for collisions
    var camera = new BABYLON.FreeCamera("FreeCamera", new BABYLON.Vector3(0, -8, -20), scene);
    camera.attachControl(canvas, true);

    //Ground
    var ground = BABYLON.Mesh.CreatePlane("ground", 20.0, scene);
    ground.material = new BABYLON.StandardMaterial("groundMat", scene);
    ground.material.diffuseColor = new BABYLON.Color3(1, 1, 1);
    ground.material.backFaceCulling = false;
    ground.position = new BABYLON.Vector3(5, -10, -15);
    ground.rotation = new BABYLON.Vector3(Math.PI / 2, 0, 0);

    //Simple crate
    var box = new BABYLON.Mesh.CreateBox("crate", 2, scene);
    box.material = new BABYLON.StandardMaterial("Mat", scene);
    box.material.diffuseTexture = new BABYLON.Texture("textures/crate.png", scene);
    box.material.diffuseTexture.hasAlpha = true;
    box.position = new BABYLON.Vector3(5, -9, -10);

    //Set gravity for the scene (G force like, on Y-axis)
    scene.gravity = new BABYLON.Vector3(0, -0.9, 0);

    // Enable Collisions
    scene.collisionsEnabled = true;

    //Then apply collisions and gravity to the active camera
    camera.checkCollisions = true;
    camera.applyGravity = true;

    //Set the ellipsoid around the camera (e.g. your player's size)
    camera.ellipsoid = new BABYLON.Vector3(1, 1, 1);

    //finally, say which mesh will be collisionable
    ground.checkCollisions = true;
    box.checkCollisions = true;

    return scene;
}
View Code

自己随便摆动了下箱子(这个箱子看的我满满的回忆,好像上次看到在某仓库)

 

代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html" charset="utf-8"/>
    <title>Babylon - Getting Started</title>
    <!-- link to the last version of babylon -->
    <script src="js/babylon.2.2.max.js"></script>
</head>
<style>
    html, body {
        overflow: hidden;
        width   : 100%;
        height  : 100%;
        margin  : 0;
        padding : 0;
    }

    #renderCanvas {
        width   : 100%;
        height  : 100%;
        touch-action: none;
    }
</style>

<body>
    <canvas id="renderCanvas"></canvas>
    <script>
    window.addEventListener('DOMContentLoaded', function() {
        //获取画布对象
       var canvas = document.getElementById('renderCanvas');
       //加载巴比伦3D引擎
       var engine = new BABYLON.Engine(canvas, true);
       //创建场景
       var createScene = function () {
            var scene = new BABYLON.Scene(engine);

            // 还是灯关,这里是一个定向灯关
            var light0 = new BABYLON.DirectionalLight("Omni", new BABYLON.Vector3(-2, -5, 2), scene);
            // 还是灯关,这里是一个点光源
            var light1 = new BABYLON.PointLight("Omni", new BABYLON.Vector3(2, -5, -2), scene);

            // 一个简单可碰撞的相机
            /**
            *对比旧版本
            *var camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(9, 95,50), scene);
            *
            */
            var camera = new BABYLON.FreeCamera("FreeCamera", new BABYLON.Vector3(0, -8, -20), scene);
            //附加控制
            camera.attachControl(canvas, true);

            //地面
            var ground = BABYLON.Mesh.CreatePlane("ground", 20.0, scene);
            ground.material = new BABYLON.StandardMaterial("groundMat", scene);
            ground.material.diffuseColor = new BABYLON.Color3(1, 1, 1);
            ground.material.backFaceCulling = false;
            ground.position = new BABYLON.Vector3(5, -10, -15);
            ground.rotation = new BABYLON.Vector3(Math.PI / 2, 0, 0);

            //BOX结构的箱子
            var box = new BABYLON.Mesh.CreateBox("crate", 2, scene);
            box.material = new BABYLON.StandardMaterial("Mat", scene);
            box.material.diffuseTexture = new BABYLON.Texture("map/crate.png", scene);
            box.material.diffuseTexture.hasAlpha = true;
            box.position = new BABYLON.Vector3(5, -9, -10);

            //我要拼凑一个曰
            var sun="1,1;1,2;1,3;1,4;2,1;2,4;3,1;3,2;3,3;3,4;4,1;4,4;5,1;5,2;5,3;5,4";
            for(var i=0;i<sun.split(';').length;i++){
                var xy=sun.split(';')[i].split(',');
                var x=parseInt(xy[1])*2;
                var y=parseInt(xy[0])*2;
                var box2 = new BABYLON.Mesh.CreateBox("crate"+x+y, 2, scene);
                box2.material = new BABYLON.StandardMaterial("Mat", scene);
                box2.material.diffuseTexture = new BABYLON.Texture("map/crate.png", scene);
                box2.material.diffuseTexture.hasAlpha = true;
                console.log(x+":"+y);
                box2.position = new BABYLON.Vector3(x, y-11, -12);
                box2.checkCollisions = true;
            }

            //设置场景的动力(G重力, 基于Y轴)
            scene.gravity = new BABYLON.Vector3(0, -0.9, 0);

            //设置场景碰撞
            scene.collisionsEnabled = true;

            //设置相机的碰撞
            camera.checkCollisions = true;
            //设置相机的重力
            camera.applyGravity = true;

            //将相机包围一个球形,用于碰撞
            camera.ellipsoid = new BABYLON.Vector3(1, 1, 1);

            //地面设置碰撞
            ground.checkCollisions = true;
            //箱子设置碰撞
            box.checkCollisions = true;
            return scene;
        }
        //赋予该场景于变量
        var scene = createScene();
        //在引擎中循环运行这个场景
        engine.runRenderLoop(function(){
            scene.render();
        });
        //追加事件:帆布与大小调整程序
        window.addEventListener('resize', function(){
            engine.resize();
        });
    });
    

</script>
</body>
</html>
View Code

笔记:

本案例学的内容包括

1.场景重力

2.各对象碰撞属性开启

【playground】-intersections(交错)

源码

var createScene = function () {
    var scene = new BABYLON.Scene(engine);

    var camera = new BABYLON.ArcRotateCamera("Camera", 1, 0.8, 70, new BABYLON.Vector3(5, 0, 0), scene);
    camera.attachControl(canvas, true);

    // Material
    var matPlan = new BABYLON.StandardMaterial("matPlan1", scene);
    matPlan.backFaceCulling = false;
    matPlan.emissiveColor = new BABYLON.Color3(0.2, 1, 0.2);

    var matBB = new BABYLON.StandardMaterial("matBB", scene);
    matBB.emissiveColor = new BABYLON.Color3(1, 1, 1);
    matBB.wireframe = true;

    // Intersection point
    var pointToIntersect = new BABYLON.Vector3(-30, 0, 0);
    var origin = BABYLON.Mesh.CreateSphere("origin", 4, 0.3, scene);
    origin.position = pointToIntersect;
    origin.material = matPlan;

    // Create two planes
    var plan1 = BABYLON.Mesh.CreatePlane("plane1", 20, scene);
    plan1.position = new BABYLON.Vector3(13, 0, 0);
    plan1.rotation.x = -Math.PI / 4;
    plan1.material = matPlan;

    var plan2 = BABYLON.Mesh.CreatePlane("plane2", 20, scene);
    plan2.position = new BABYLON.Vector3(-13, 0, 0);
    plan2.rotation.x = -Math.PI / 4;
    plan2.material = matPlan;

    // AABB - Axis aligned bounding box
    var planAABB = BABYLON.Mesh.CreateBox("AABB", 20, scene);
    planAABB.material = matBB;
    planAABB.position = new BABYLON.Vector3(13, 0, 0);
    planAABB.scaling = new BABYLON.Vector3(1, Math.cos(Math.PI / 4), Math.cos(Math.PI / 4));

    // OBB - Object boundind box
    var planOBB = BABYLON.Mesh.CreateBox("OBB", 20, scene);
    planOBB.scaling = new BABYLON.Vector3(1, 1, 0.05);
    planOBB.parent = plan2;
    planOBB.material = matBB;

    // Balloons
    var balloon1 = BABYLON.Mesh.CreateSphere("balloon1", 10, 2.0, scene);
    var balloon2 = BABYLON.Mesh.CreateSphere("balloon2", 10, 2.0, scene);
    var balloon3 = BABYLON.Mesh.CreateSphere("balloon3", 10, 2.0, scene);
    balloon1.material = new BABYLON.StandardMaterial("matBallon", scene);
    balloon2.material = new BABYLON.StandardMaterial("matBallon", scene);
    balloon3.material = new BABYLON.StandardMaterial("matBallon", scene);

    balloon1.position = new BABYLON.Vector3(6, 5, 0);
    balloon2.position = new BABYLON.Vector3(-6, 5, 0);
    balloon3.position = new BABYLON.Vector3(-30, 5, 0);

    //Animation
    var alpha = Math.PI;
    scene.registerBeforeRender(function () {

        //Balloon 1 intersection -- Precise = false
        if (balloon1.intersectsMesh(plan1, false)) {
            balloon1.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
        } else {
            balloon1.material.emissiveColor = new BABYLON.Color3(1, 1, 1);
        }

        //Balloon 2 intersection -- Precise = true
        if (balloon2.intersectsMesh(plan2, true)) {
            balloon2.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
        } else {
            balloon2.material.emissiveColor = new BABYLON.Color3(1, 1, 1);
        }

        //balloon 3 intersection on single point
        if (balloon3.intersectsPoint(pointToIntersect)) {
            balloon3.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
        } else {
            balloon3.material.emissiveColor = new BABYLON.Color3(1, 1, 1);
        }

        alpha += 0.01;
        balloon1.position.y += Math.cos(alpha) / 10;
        balloon2.position.y = balloon1.position.y;
        balloon3.position.y = balloon1.position.y;
    });


    return scene;
}
View Code

 效果

 

个人翻译

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html" charset="utf-8"/>
    <title>Babylon - Getting Started</title>
    <!-- link to the last version of babylon -->
    <script src="js/babylon.2.2.max.js"></script>
</head>
<style>
    html, body {
        overflow: hidden;
        width   : 100%;
        height  : 100%;
        margin  : 0;
        padding : 0;
    }

    #renderCanvas {
        width   : 100%;
        height  : 100%;
        touch-action: none;
    }
</style>

<body>
    <canvas id="renderCanvas"></canvas>
    <script>
    window.addEventListener('DOMContentLoaded', function() {
        //获取画布对象
       var canvas = document.getElementById('renderCanvas');
       //加载巴比伦3D引擎
       var engine = new BABYLON.Engine(canvas, true);
       //创建场景
       var createScene = function () {
            var scene = new BABYLON.Scene(engine);
            //还是光源
            var camera = new BABYLON.ArcRotateCamera("Camera", 1, 0.8, 70, new BABYLON.Vector3(5, 0, 0), scene);
            camera.attachControl(canvas, true);

            // 一个材质
            var matPlan = new BABYLON.StandardMaterial("matPlan1", scene);
            //背面处理
            matPlan.backFaceCulling = false;
            //发射光
            matPlan.emissiveColor = new BABYLON.Color3(0.2, 1, 0.2);

            // 又一个材质
            var matBB = new BABYLON.StandardMaterial("matBB", scene);
            //发射光
            matBB.emissiveColor = new BABYLON.Color3(1, 1, 1);
            //线框?
            matBB.wireframe = true;

            //<点相交的例子>
            //一个定位向量
            var pointToIntersect = new BABYLON.Vector3(-30, 0, 0);
            //创建一个球
            var origin = BABYLON.Mesh.CreateSphere("origin", 4, 0.3, scene);
            origin.position = pointToIntersect;
            origin.material = matPlan;

            // 创建一个面
            var plan1 = BABYLON.Mesh.CreatePlane("plane1", 20, scene);
            plan1.position = new BABYLON.Vector3(13, 0, 0);
            plan1.rotation.x = -Math.PI / 4;
            plan1.material = matPlan;


            var plan2 = BABYLON.Mesh.CreatePlane("plane2", 20, scene);
            plan2.position = new BABYLON.Vector3(-13, 0, 0);
            plan2.rotation.x = -Math.PI / 4;
            plan2.material = matPlan;

            // AABB - 轴对其的边界框(大的方型的框)
            var planAABB = BABYLON.Mesh.CreateBox("AABB", 20, scene);
            planAABB.material = matBB;
            planAABB.position = new BABYLON.Vector3(13, 0, 0);
            planAABB.scaling = new BABYLON.Vector3(1, Math.cos(Math.PI / 4), Math.cos(Math.PI / 4));

            // OBB - 对象外延的边界框(包裹在对象外面)
            var planOBB = BABYLON.Mesh.CreateBox("OBB", 20, scene);
            planOBB.scaling = new BABYLON.Vector3(1, 1, 0.05);
            planOBB.parent = plan2;
            planOBB.material = matBB;

            // 气球(这里是飞在外面移动的球)
            var balloon1 = BABYLON.Mesh.CreateSphere("balloon1", 10, 2.0, scene);
            var balloon2 = BABYLON.Mesh.CreateSphere("balloon2", 10, 2.0, scene);
            var balloon3 = BABYLON.Mesh.CreateSphere("balloon3", 10, 2.0, scene);
            balloon1.material = new BABYLON.StandardMaterial("matBallon", scene);
            balloon2.material = new BABYLON.StandardMaterial("matBallon", scene);
            balloon3.material = new BABYLON.StandardMaterial("matBallon", scene);

            balloon1.position = new BABYLON.Vector3(6, 5, 0);
            balloon2.position = new BABYLON.Vector3(-6, 5, 0);
            balloon3.position = new BABYLON.Vector3(-30, 5, 0);

            //下面定义动画
            var alpha = Math.PI;
            scene.registerBeforeRender(function () {

                //气球一的交错,非精确。为false时候,接触外框就是产生反应(面碰撞)
                if (balloon1.intersectsMesh(plan1, false)) {
                    balloon1.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
                } else {
                    balloon1.material.emissiveColor = new BABYLON.Color3(1, 1, 1);
                }

                //气球二的交错,精确。(面碰撞)
                if (balloon2.intersectsMesh(plan2, true)) {
                    balloon2.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
                } else {
                    balloon2.material.emissiveColor = new BABYLON.Color3(1, 1, 1);
                }

                //气球三的交错,碰撞到某向量的时候(点碰撞)
                if (balloon3.intersectsPoint(pointToIntersect)) {
                    balloon3.material.emissiveColor = new BABYLON.Color3(1, 0, 0);
                } else {
                    balloon3.material.emissiveColor = new BABYLON.Color3(1, 1, 1);
                }

                alpha += 0.01;
                balloon1.position.y += Math.cos(alpha) / 10;
                balloon2.position.y = balloon1.position.y;
                balloon3.position.y = balloon1.position.y;
            });


            return scene;
        }
        //赋予该场景于变量
        var scene = createScene();
        //在引擎中循环运行这个场景
        engine.runRenderLoop(function(){
            scene.render();
        });
        //追加事件:帆布与大小调整程序
        window.addEventListener('resize', function(){
            engine.resize();
        });
    });
    

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

本案例大致学的内容包括

1.线框材质

2.交错事件

【playground】-picking(挑选)

 源码

var createScene = function () {
    var scene = new BABYLON.Scene(engine);

    // setup environment
    var light0 = new BABYLON.PointLight("Omni", new BABYLON.Vector3(0, 10, 20), scene);
    var freeCamera = new BABYLON.FreeCamera("FreeCamera", new BABYLON.Vector3(0, 0, -30), scene);

    // Impact impostor
    var impact = BABYLON.Mesh.CreatePlane("impact", 1, scene);
    impact.material = new BABYLON.StandardMaterial("impactMat", scene);
    impact.material.diffuseTexture = new BABYLON.Texture("textures/impact.png", scene);
    impact.material.diffuseTexture.hasAlpha = true;
    impact.position = new BABYLON.Vector3(0, 0, -0.1);

    //Wall
    var wall = BABYLON.Mesh.CreatePlane("wall", 20.0, scene);
    wall.material = new BABYLON.StandardMaterial("wallMat", scene);
    wall.material.emissiveColor = new BABYLON.Color3(0.5, 1, 0.5);

    //When pointer down event is raised
    scene.onPointerDown = function (evt, pickResult) {
        // if the click hits the ground object, we change the impact position
        if (pickResult.hit) {
            impact.position.x = pickResult.pickedPoint.x;
            impact.position.y = pickResult.pickedPoint.y;
        }
    };

    return scene;
}
View Code

效果

笔记:

这个里面存在一个BUG,原本设计的想法是鼠标点击在绿色画布内,才允许触发事件。但实际上,当你点击在画布边缘的时候,可以慢慢点击到画布外蓝色区域

那么我试着解决这个BUG,在改变xy之前增加判断

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html" charset="utf-8"/>
    <title>Babylon - Getting Started</title>
    <!-- link to the last version of babylon -->
    <script src="js/babylon.2.2.max.js"></script>
</head>
<style>
    html, body {
        overflow: hidden;
        width   : 100%;
        height  : 100%;
        margin  : 0;
        padding : 0;
    }

    #renderCanvas {
        width   : 100%;
        height  : 100%;
        touch-action: none;
    }
</style>

<body>
    <canvas id="renderCanvas"></canvas>
    <script>
    window.addEventListener('DOMContentLoaded', function() {
        //获取画布对象
       var canvas = document.getElementById('renderCanvas');
       //加载巴比伦3D引擎
       var engine = new BABYLON.Engine(canvas, true);
       //创建场景
       var createScene = function () {
            var scene = new BABYLON.Scene(engine);

            // 灯关
            var light0 = new BABYLON.PointLight("Omni", new BABYLON.Vector3(0, 10, 20), scene);
            //相机(固定视角)
            var freeCamera = new BABYLON.FreeCamera("FreeCamera", new BABYLON.Vector3(0, 0, -30), scene);

            // 贴面(小图标)
            var impact = BABYLON.Mesh.CreatePlane("impact", 1, scene);
            impact.material = new BABYLON.StandardMaterial("impactMat", scene);
            impact.material.diffuseTexture = new BABYLON.Texture("map/impact.png", scene);
            impact.material.diffuseTexture.hasAlpha = true;
            impact.position = new BABYLON.Vector3(0, 0, -0.1);

            //墙(画布)
            var wall = BABYLON.Mesh.CreatePlane("wall", 20.0, scene);
            wall.material = new BABYLON.StandardMaterial("wallMat", scene);
            wall.material.emissiveColor = new BABYLON.Color3(0.5, 1, 0.5);

            //指针的点击事件onPointerDown
            scene.onPointerDown = function (evt, pickResult) {
                // 如果单击击中地面目标,我们改变位置的影响(点击地面时候产生影响)
                //当产生点击
                if (pickResult.hit) {
                    //此处增加基于xy轴的地理围栏,防止越界
                    var cX=pickResult.pickedPoint.x;
                    var maxX=wall.position.x+10;
                    var minX=wall.position.x-10;
                    var cY=pickResult.pickedPoint.y;
                    var maxY=wall.position.y+10;
                    var minY=wall.position.y-10;
                    console.log("当前坐标x="+cX+"|y="+cY);
                    if(cX>maxX||cX<minX){
                        console.log("x越界了");
                    }else{
                        impact.position.x = pickResult.pickedPoint.x;
                    }
                    if(cY>maxY||cY<minY){
                        console.log("y越界了");
                    }else{
                        impact.position.y = pickResult.pickedPoint.y;
                    }
                    
                    
                }
            };

            return scene;
        }

        //赋予该场景于变量
        var scene = createScene();
        //在引擎中循环运行这个场景
        engine.runRenderLoop(function(){
            scene.render();
        });
        //追加事件:帆布与大小调整程序
        window.addEventListener('resize', function(){
            engine.resize();
        });
    });
    

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

笔记:

1.增加固定相机

2.增加点击事件onPointerDown

3.设置基于xy轴的判断

你可能感兴趣的:(初学WebGL引擎-BabylonJS:第6篇-碰撞交错与挑选)