【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; }
自己随便摆动了下箱子(这个箱子看的我满满的回忆,好像上次看到在某仓库)
代码如下:
<!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>
笔记:
本案例学的内容包括
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; }
效果
个人翻译
<!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; }
效果
笔记:
这个里面存在一个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轴的判断