个人Babylonjs学习笔记
文章目录
- framework
- Camera
- UniversalCamera——通用相机
- ArcRotateCamera——弧形旋转相机
- FollowCamera——跟随相机
- 其他相机
- Light
- PointLight——点光
- DirectionalLight——平行光
- SpotLight——聚光灯
- HemisphericLight——半球光
- 灯光属性
- BABYLON.MeshBuilder
- CreateSphere——球
- CreateBox——盒子
- CreateCylinder——圆柱/棱柱
- CreatePlane——平面
- CreateGround——地面
- CreateGroundFromHeightMap——高度地图
- CreateLine——线
- CreateLathe——车床
- ExtrudeShape——挤压形状
- position & rotation & scaling
- position——定位
- rotation——旋转
- scaling——缩放
- Material
- 材质颜色属性
- 材质纹理属性
- backFaceCulling——背面剔除
- wireFrame——线框
- GUI
- AdvancedDynamicTexture
- Animation——动画
- 标准动画
- 排序动画
- 分组动画
- 组合动画(连续动画)
- 动画人物
- Audio——声音
- 行为
- 相机行为(弹跳等)
- 网格行为(拖动物体等)
- 其他
- **导入场景或模型**
- 声音
- faceUV
- 组合网格
- 复制网格
- 造车!
- 天空盒
- Animate !
- 避免碰撞
- SpriteManager——精灵管理
- ParticleSystem——粒子系统
- onPointerObservable——点击
- ShadowGenerator——阴影
- VR
- 重力
进度:https://doc.babylonjs.com/start/chap6/particlespray
framework
一个球
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><title>Babylon Template</title><style>html, body {overflow: hidden;width: 100%;height: 100%;margin: 0;padding: 0;}#renderCanvas {width: 100%;height: 100%;touch-action: none;}</style><script src="https://cdn.babylonjs.com/babylon.js"></script><script src="https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js"></script><!-- 允许您将模型导入场景。 --><script src="https://code.jquery.com/pep/0.4.3/pep.js"></script><!-- 允许您使用触摸屏。 --></head><body><canvas id="renderCanvas" touch-action="none"></canvas> <!-- touch-action="none" for best results from PEP --><script>const canvas = document.getElementById("renderCanvas");const engine = new BABYLON.Engine(canvas, true);const createScene = () => {const scene = new BABYLON.Scene(engine);const camera = new BABYLON.ArcRotateCamera("Camera", -3 * Math.PI / 4, Math.PI / 3, 50, BABYLON.Vector3.Zero(), scene);camera.attachControl(canvas, true);const light = new BABYLON.DirectionalLight("dir01", new BABYLON.Vector3(0, -1, 1), scene);light.position = new BABYLON.Vector3(0, 15, -30);var ground = BABYLON.Mesh.CreateGround("ground", 100, 100, 1, scene, false);ground.receiveShadows = true;var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {}, scene); return scene;};const scene = createScene();engine.runRenderLoop(function () {scene.render();});window.addEventListener("resize", function () {engine.resize();});</script></body>
</html>
Camera
将相机连接到画布:
camera.attachControl(canvas, true);//第二个参数可选,默认false,阻止画布上的默认事件,true即允许
使相机不显示低于地面的物体:
camera.upperBetaLimit = Math.PI / 2.2;// β上限
UniversalCamera——通用相机
默认的行为是:
1.keyboard键盘-左和右箭头移动相机左右,上下箭头移动它向前和向后;
2.mouse鼠标——用相机旋转相机的原点;
3.touch向左或向右滑动,左右移动相机,上下滑动,向前和向后移动;
4.gamepad手柄-对应于设备。
构建一个通用相机
// 参数:名称、位置、场景
var camera = new BABYLON.UniversalCamera("UniversalCamera", new BABYLON.Vector3(0, 0, -10), scene);// 把相机对准一个特定的位置。在这个例子中是场景的原点
camera.setTarget(BABYLON.Vector3.Zero());// 把相机固定在画布上
camera.attachControl(canvas, true);
ArcRotateCamera——弧形旋转相机
- 相机总是指向一个给定的目标位置,并可以在目标周围旋转,目标是旋转的中心。
- 它可以用光标、鼠标和触摸事件来控制
- 它相对于目标(地球)的位置可以由三个参数设定,alpha(弧度)经度(横切面)的旋转,beta(弧度)的纬度(纵切面)的旋转和半径(目标位置的距离)。
- 由于技术原因,将beta值设置为0或PI会导致问题,在这种情况下,beta偏移0.1弧度(大约0.6度)。
- alpha和beta都是顺时针方向增长的
- 相机的位置也可以由一个矢量来设定,这个矢量将会超过alpha、beta和半径的任何现值。这比计算所需的角度要容易得多。
- 无论是使用键盘、鼠标还是触摸式滑动,都可以改变alpha值和向下方向的变化。
构建一个弧旋转相机:
//参数:alpha、beta、半径、目标位置、场景
var camera = new BABYLON.ArcRotateCamera("Camera", 0, 0, 10, new BABYLON.Vector3(0, 0, 0), scene);//定位摄像机覆盖alpha,beta,半径
camera.setPosition(new BABYLON.Vector3(0, 0, 20));//把相机连接到画布上
camera.attachControl(canvas, true);
通过使用CTRL+MouseLeftClick,也可以使用ArcRotateCamera来进行Panning移镜头操作。你可以指定使用MouseRightClick来替代,通过在attachControl调用中设置useCtrlForPanning:
camera.attachControl(canvas, noPreventDefault, useCtrlForPanning);
如果需要的话,你也可以通过设置来完全禁用panning :
scene.activeCamera.panningSensibility = 0;
如果将弧形旋转相机的parent设为人物,则可实现跟随人物运动:
camera.parent = dude;
FollowCamera——跟随相机
两种跟随相机:
- followCamera:自由版本
- arcFollowCamera:弧度旋转版本
给它一个网格作为目标并跟随其移动
当它被创建时,跟随相机的初始位置设置,然后目标位置设置为三个参数:
- 距离目标的距离-摄像机半径camera.radius;
- 目标上方的高度
- 在x y平面上的角度
相机移动到目标位置的速度是通过它的加速度(camera.cameraAcceleration)达到最大速度(camera.maxCameraSpeed)。
构建一个跟随相机:
// 参数:名称、位置、场景
var camera = new BABYLON.FollowCamera("FollowCam", new BABYLON.Vector3(0, 10, -10), scene);//半径:相机距离目标距离
camera.radius = 30;// 相机高于目标中心(原点)的目标高度
camera.heightOffset = 10;// 目标在x y平面上绕目标(中心)的目标旋转角度
camera.rotationOffset = 0;//从当前位置到目标位置移动相机的加速度
camera.cameraAcceleration = 0.005//停止的加速度
camera.maxCameraSpeed = 10//把相机连接到画布上
camera.attachControl(canvas, true);// 相机锁定目标 = 人物
camera.lockedTarget = dude;
其他相机
浮雕相机
该AnaglyphUniversalCamera和AnaglyphArcRotateCamera延长使用使用通用和弧形旋转相机用红色和青色的3D眼镜。他们使用后处理过滤技术。
构造立体浮雕通用相机
// //参数:名称,位置,眼睛位置,场景
var camera = new BABYLON.AnaglyphUniversalCamera("af_cam", new BABYLON.Vector3(0, 1, -15), 0.033, scene);
构造立体浮雕旋转相机:
//参数:名称,alpha,beta,半径,目标,eyeSpace,场景
var camera = new BABYLON.AnaglyphArcRotateCamera("aar_cam", -Math.PI / 2, Math.PI / 4, 20, BABYLON.Vector3.Zero(), 0.033, scene);
该eyeSpace
参数设置左眼视图和右眼视图之间的偏移量。戴好3D眼镜后,您可能需要尝试使用此float值。
您可以通过访问Wikipedia页面全面了解浮雕知识,对其进行详细介绍。
设备定位相机
所述DeviceOrientationCamera是专门设计来给设备取向事件作出反应,例如被倾斜一个现代移动设备向前,后,左,或右。
构造设备定位相机:
//参数:名称,位置,场景
var camera = new BABYLON.DeviceOrientationCamera("DevOr_camera", new BABYLON.Vector3(0, 0, 0), scene);
//将相机对准特定位置
camera.setTarget(new BABYLON.Vector3(0, 0, -10));
//设置摄像机对移动和旋转的敏感度
camera.angularSensibility = 10;
camera.moveSensibility = 10;
//将相机连接到画布
camera.attachControl(canvas, true);
虚拟操纵杆相机
该VirtualJoysticksCamera专门向虚拟摇杆事件做出反应。虚拟操纵杆是屏幕上的2D图形,用于控制相机或其他场景项目。
**注意:**这台相机需要第三方文件hand.js。
完整样本:
document.addEventListener("DOMContentLoaded", startGame, false);
function startGame() {if (BABYLON.Engine.isSupported()) {var canvas = document.getElementById("renderCanvas");var engine = new BABYLON.Engine(canvas, true);BABYLON.SceneLoader.Load("Espilit/", "Espilit.babylon", engine, function (newScene) {var VJC = new BABYLON.VirtualJoysticksCamera("VJC", newScene.activeCamera.position, newScene);VJC.rotation = newScene.activeCamera.rotation;VJC.checkCollisions = newScene.activeCamera.checkCollisions;VJC.applyGravity = newScene.activeCamera.applyGravity;//等待纹理和着色器准备就绪newScene.executeWhenReady(function () {newScene.activeCamera = VJC;//将相机连接到画布输入newScene.activeCamera.attachControl(canvas);//加载场景后,只需注册一个渲染循环即可渲染它engine.runRenderLoop(function () {newScene.render();}),}),}, function (progress) {//要做:向用户提供进度反馈。}),}
}
如果您切换回另一台摄像机,请不要忘记先打电话dispose()
。在VirtualJoysticks
创建的3D WebGL的顶部的2D画布画布绘制青色和黄色圆圈的操纵杆。如果您忘记打电话dispose()
,2D画布将保留并继续处理触摸事件。
VR设备定向相机
VRDeviceOrientationFreeCamera,VRDeviceOrientationArcRotateCamera,和VRDeviceOrientationGamepadCamera是从一个VR设备延伸上方的摄像机手柄装置定向相机一个较新的集合。
FlyCamera
FlyCamera模仿3D空间中的自由运动,认为是“空间中的幽灵”。它具有逐步校正侧倾的选项,以及模拟倾斜转弯的选项。
其默认值为:
- 键盘-A和D键可左右移动摄像机。在W与S键向前和向后移动。在E与Q键和上下移动。
- 鼠标-以摄像机为原点,绕俯仰和偏航(X,Y)轴旋转摄像机。按住right mouse button旋转,以照相机为原点,使照相机绕Roll(Z)轴旋转。
构造飞行相机:
//参数:名称,位置,场景
var camera = new BABYLON.FlyCamera("FlyCamera", new BABYLON.Vector3(0, 5, -10), scene);
//像飞机一样旋转,具有更快的侧倾校正和倾斜转弯。
//默认值为100。数字越大,校正速度越慢。
camera.rollCorrect = 10;
//默认为false。
camera.bankedTurn = true;
//弧度默认为90度,以弧度表示倾斜角度。
camera.bankedTurnLimit = Math.PI / 2;
//多少偏航(转弯)会影响滚动(倾斜转弯)。
//小于1会减少滚动,大于1会增加滚动。
camera.bankedTurnMultiplier = 1;
//这会将相机附加到画布上
camera.attachControl(canvas, true);
详情请见:https://doc.babylonjs.com/divingDeeper/cameras/camera_introduction
Light
所有的网格都允许光通过它们,除非阴影生成被激活。允许的默认灯光数是4,但这可以增加。
PointLight——点光
// 参数:名字, 位置, 场景
var light = new BABYLON.PointLight("pointLight", new BABYLON.Vector3(1, 10, 1), scene);
DirectionalLight——平行光
// 参数:名字,位置,场景
var light = new BABYLON.DirectionalLight("DirectionalLight", new BABYLON.Vector3(0, -1, 0), scene);
SpotLight——聚光灯
聚光灯是由一个位置、一个方向、一个角度和一个指数来定义的。这些值定义了一个从位置开始的光锥,向方向发射。
在弧度中,角度定义了聚光灯的锥形光束的大小(照明区域),指数定义了光的衰减速度和距离(范围)。
// 参数:名字,位置,方向,角度,指数,场景
var light = new BABYLON.SpotLight("spotLight", new BABYLON.Vector3(0, 30, -10), new BABYLON.Vector3(0, -1, 0), Math.PI / 3, 2, scene);
HemisphericLight——半球光
也就是周围环境光
// 参数:名字, 方向,场景
var light = new BABYLON.HemisphericLight("HemiLight", new BABYLON.Vector3(0, 1, 0), scene);
灯光属性
颜色。。
限制:
默认一个场景总最多有4个灯光
var material = new BABYLON.StandardMaterial("mat", scene);
material.maxsimultaneousLights = 6;
打开:
light.setEnabled(true);
关闭:
light.setEnabled(false);
强度:
light0.intensity = 0.5;
light1.intensity = 2.4;
光的范围:
适用于点光与聚光灯
light.range = 100;
Choosing Meshes to Light?
当一个光被创造出来时,所有的现有网格都将被它点亮。有两种方法可以将一些网格从被点亮的地方排除出去。
一个网格可以添加到独占的网格数组中,或者添加不被排除在包含的列表中。
被排除的网格的数量可能是决定使用哪种方法的一个因素。
BABYLON.MeshBuilder
CreateSphere——球
var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {}, scene); //默认的球体spherevar mySphere = BABYLON.MeshBuilder.CreateSphere("mySphere", {diameter: 2, diameterX: 3}, scene);
//optinon: segments(段数) diameter(直径)diameterX diameterY diameterZ arc(弧度)slice(切片) updatable(可更新的) sideOrientation(边方向)
CreateBox——盒子
var box = BABYLON.MeshBuilder.CreateBox("box", {}, scene); //默认的盒子boxvar myBox = BABYLON.MeshBuilder.CreateBox("myBox", {height: 5, width: 2, depth: 0.5}, scene);
//option: size height width depth(深度) faceColors(面颜色,6种颜色的数组,每个框面一个)faceUV(面UV,6个矢量阵列,每个盒子面一个) updatable(可更新的) sideOrientation(边方向)
CreateCylinder——圆柱/棱柱
// 参数:名字,配置{// height?: number; 高度 默认2
// diameterTop?: number; 上直径 默认1
// diameterBottom?: number; 下直径 默认1
// diameter?: number; 直径 !=0 会被上两个覆盖
// tessellation?: number; 镶嵌(即圆柱边数量,默认24) 3为三棱柱,4为四棱柱
// subdivisions?: number; 细分 沿着圆柱体高度设置环的数量,默认1 ?没用到过
// arc?: number;
// faceColors?: BABYLON.Color4[];
// ... 7 more ...;
// backUVs?: BABYLON.Vector4;}
const roof = BABYLON.MeshBuilder.CreateCylinder("roof", {diameter: 1.3, height: 1.2, tessellation: 3});
roof.scaling.x = 0.75;
roof.rotation.z = Math.PI / 2;
roof.position.y = 1.22;
CreatePlane——平面
var plane = BABYLON.MeshBuilder.CreatePlane("plane", {}, scene); //默认的平面planevar myPlane = BABYLON.MeshBuilder.CreatePlane("myPlane", {width: 5, height: 2}, scene);
//option: size width height updatable(可更新的) sideOrientation(边方向) // frontUVs(前UV,只有当边方向设置为 sideOrientation:BABYLON.Mesh.DOUBLESIDE)// backUVs(后UV,只有当边方向设置为 sideOrientation:BABYLON.Mesh.DOUBLESIDE)// sourcePlane(源平面,源平面(数学)网格将被转换为)// sourcePlane是一个平面网格的独特选择,它提供了一种方法来定向和定位它。
CreateGround——地面
var ground = BABYLON.MeshBuilder.CreateGround("ground", {}, scene); //默认的地面groundvar myGround = BABYLON.MeshBuilder.CreateGround("myGround", {width: 6, height: 4, subdivsions: 4}, scene);
CreateGroundFromHeightMap——高度地图
const largeGround = BABYLON.MeshBuilder.CreateGroundFromHeightMap("largeGround", "https://assets.babylonjs.com/environments/villageheightmap.png", {width:150, height:150,subdivisions: 20,// 细分:棱角分明程度,数值越大坡度越大,越棱角分明minHeight:0, maxHeight: 10}
);const largeGroundMat = new BABYLON.StandardMaterial("largeGroundMat");
largeGroundMat.diffuseTexture = new BABYLON.Texture("url to large ground texture");largeGround.material = largeGroundMat;largeGround.position.y = -0.01; // 确保两个地面不发生冲突并引起闪烁。
CreateLine——线
var myPoints = [];var point1 = new BABYLON.Vector3(0, 0, 0);
myPoints.push(point1);
var point2 = new BABYLON.Vector3(0, 1, 1);
myPoints.push(point2);
var point3 = new BABYLON.Vector3(0, 1, 0);
myPoints.push(point3);//或者var myPoints =[new BABYLON.Vector3(0, 0, 0),new BABYLON.Vector3(0, 1, 1),new BABYLON.Vector3(0, 1, 0)
];//然后,这些点的数组必须传递给点选项//创建线linesvar lines = BABYLON.MeshBuilder.CreateLines("lines", {points: myPoints}, scene);//您可以创建虚线CreateDashedLines,并将破折号dashNb的数量作为一个选项。
CreateLathe——车床
在x,y正半轴的象限中绘制半个图像轮廓,然后沿着y轴旋转所形成的图形
const fountainProfile = [new BABYLON.Vector3(0, 0, 0),new BABYLON.Vector3(10, 0, 0),new BABYLON.Vector3(10, 4, 0),new BABYLON.Vector3(8, 4, 0),new BABYLON.Vector3(8, 1, 0),new BABYLON.Vector3(1, 2, 0),new BABYLON.Vector3(1, 15, 0),new BABYLON.Vector3(3, 17, 0)
];// sideOrientain属性将网格设置为双面,因为内部可见,而且顶部和中空部分是倾斜的
const fountain = BABYLON.MeshBuilder.CreateLathe("fountain", {shape: fountainProfile, sideOrientation: BABYLON.Mesh.DOUBLESIDE}, scene);
ExtrudeShape——挤压形状
创建一个挤压形状网格。
挤压是一个参数形状。
它没有预定义的形状。
它的最终形状将取决于输入参数。
//shape to extrude
const lampShape = [];
for(let i = 0; i < 20; i++) {lampShape.push(new BABYLON.Vector3(Math.cos(i * Math.PI / 10), Math.sin(i * Math.PI / 10), 0));
}
lampShape.push(lampShape[0]); //close shape//extrusion path
const lampPath = [];
lampPath.push(new BABYLON.Vector3(0, 0, 0));
lampPath.push(new BABYLON.Vector3(0, 10, 0));
for(let i = 0; i < 20; i++) {lampPath.push(new BABYLON.Vector3(1 + Math.cos(Math.PI - i * Math.PI / 40), 10 + Math.sin(Math.PI - i * Math.PI / 40), 0));
}
lampPath.push(new BABYLON.Vector3(3, 11, 0));const yellowMat = new BABYLON.StandardMaterial("yellowMat");
yellowMat.emissiveColor = BABYLON.Color3.Yellow();//extrude lamp
const lamp = BABYLON.MeshBuilder.ExtrudeShape("lamp", {cap: BABYLON.Mesh.CAP_END, shape: lampShape, path: lampPath, scale: 0.5});
ExtrudeShape中options的参数:
- shape:是一个必须的连续Vector3数组。该阵列描述了要在其局部空间中挤压的形状:该形状必须在xOy平面上设计,并将沿着Z轴挤压。
- path:是一个必须的连续Vector3数组。这是形状被挤压的轴线曲线。
- rotate: (float,默认0弧度)是沿着曲线旋转形状每一步(每个路径点)的角度值,从前一步开始(所以每一步都添加旋转)。
- scale: (float,默认为1)是缩放形状的值。
- cap:设置挤压形状的封顶方式。可能的值:BABYLON.Mesh。BABYLON.Mesh NO_CAP(默认)。CAP_START BABYLON.Mesh。CAP_END, BABYLON.Mesh.CAP_ALL
position & rotation & scaling
position——定位
pilot.position = new BABYLON.Vector3(2, 3, 4);//或者pilot.position.x = 2;
pilot.position.y = 3;
pilot.position.z = 4;
rotation——旋转
pilot.rotation = new BABYLON.Vector3(alpha, beta, gamma);//或者pilot.rotation.x = alpha; //绕x轴旋转
pilot.rotation.y = beta; //绕y轴旋转
pilot.rotation.z = gamma; //绕z轴旋转box.rotation.y = Math.PI / 4;
box.rotation.y = BABYLON.Tools.ToRadians(45);// 以度为单位,与上一行效果相同
scaling——缩放
//沿着x轴、y轴和z轴进行缩放
mesh.scaling = new BABYLON.Vector3(scale_x, scale_y, scale_z);//或单独设置
mesh.scaling.y = 5;
Material
//创建一个材质使用: 参数:名字, 场景(可选,默认当前场景)
var myMaterial = new BABYLON.StandardMaterial("myMaterial", scene);
材质颜色属性
- diffuseColor——固有色
- specularColor——高光反射色
- emissiveColor——放射色
- ambientColor环境色
- 只有场景环境颜色scene ambient color 设置好时,才会使用ambientColor
var myMaterial = new BABYLON.StandardMaterial("myMaterial", scene);myMaterial.diffuseColor = new BABYLON.Color3(1, 0, 1);
myMaterial.specularColor = new BABYLON.Color3(0.5, 0.6, 0.87);
myMaterial.emissiveColor = new BABYLON.Color3(1, 1, 1);
myMaterial.ambientColor = new BABYLON.Color3(0.23, 0.98, 0.53);mesh.material = myMaterial;
材质纹理属性
- diffuseTexture——固有纹理
- specularTexture——高光反射纹理
- emissiveTexture——放射纹理
- ambientTexture ——环境纹理
- 只有场景环境颜色scene ambient color 设置好时,才会使用ambientTexture
var myMaterial = new BABYLON.StandardMaterial("myMaterial", scene);myMaterial.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/roof.jpg", scene);
myMaterial.specularTexture = new BABYLON.Texture("PATH TO IMAGE", scene);
myMaterial.emissiveTexture = new BABYLON.Texture("PATH TO IMAGE", scene);
myMaterial.ambientTexture = new BABYLON.Texture("PATH TO IMAGE", scene);mesh.material = myMaterial;
backFaceCulling——背面剔除
myMaterial.backFaceCulling = true;//默认为false,一般情况下不渲染材质的背面,设为true即渲染材质背面,如天空盒子的应用
wireFrame——线框
materialSphere1.wireframe = true;//你可以在线框模式下看到一个网格,如碰撞检测时可见网格的应用
GUI
向场景添加图形用户界面。
将其加载到页面:
<script>https://cdn.babylonjs.com/gui/babylon.gui.min.js</script>
可通过设置光照强度来改变白天和黑夜。
AdvancedDynamicTexture
先进的动态纹理
// 基于全屏创建GUI
const adt = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");// 创建控制面板,设置其位置
const panel = new BABYLON.GUI.StackPanel();panel.width = "220px";panel.top = "-25px";panel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_RIGHT;panel.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_BOTTOM;adt.addControl(panel); // 并将adt GUI对象的控制权交给panel// 文本面板const header = new BABYLON.GUI.TextBlock();header.text = "Night to Day";header.height = "30px";header.color = "white";panel.addControl(header); // 滑块const slider = new BABYLON.GUI.Slider();slider.minimum = 0;slider.maximum = 1;slider.borderColor = "black";slider.color = "gray";slider.background = "white";slider.value = 1;slider.height = "20px";slider.width = "200px";// 为滑块添加数据改变事件slider.onValueChangedObservable.add((value) => {if (light) {light.intensity = value;}});panel.addControl(slider);
Animation——动画
动画是由一系列图像,帧构成的,它们依次显示。
尽管我们可以在Babylon.js中将整个成品视为动画,但动画也是一个特定的对象,它详细说明了可以应用于任何网格,相机或灯光的变换,定时和循环。
标准动画
滑动滑块:
const box = BABYLON.MeshBuilder.CreateBox("box", {});
box.position.x = 2;// 帧率
const frameRate = 10;// 参数:名称,动画属性, 帧/秒,动画数据类型,动画循环模式
const xSlide = new BABYLON.Animation("xSlide", "position.x", frameRate, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);// 关键帧数组
const keyFrames = []; keyFrames.push({frame: 0,value: 2
});keyFrames.push({frame: frameRate,value: -2
});keyFrames.push({frame: 2 * frameRate,value: 2
});xSlide.setKeys(keyFrames);box.animations.push(xSlide);// 参数: 动画对象,开始动画的帧,动画结束的帧,是否循环动画
scene.beginAnimation(box, 0, 2 * frameRate, true);// 将多个动画应用于同一个目标的方法:
// 参数:动画对象,动画数组[],开始动画的帧,动画结束的帧,是否循环动画
scene.beginDirectAnimation(target, animations, from, to, loop)
动画数据类型的值:
- BABYLON.Animation.ANIMATIONTYPE_COLOR3
BABYLON.Animation.ANIMATIONTYPE_FLOAT
BABYLON.Animation.ANIMATIONTYPE_MATRIX
BABYLON.Animation.ANIMATIONTYPE_QUATERNION
BABYLON.Animation.ANIMATIONTYPE_VECTOR2
BABYLON.Animation.ANIMATIONTYPE_VECTOR3
循环模式的值:
- BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE-从初始值重新启动动画
BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT-以最终值暂停动画
BABYLON.Animation.ANIMATIONLOOPMODE_RELATIVE-使用键值渐变重复动画递增。以这种方式,例如,可以循环显示以步行运动方式显示角色的双腿的_ clip *,以显示角色在场景中的前进过程。
动画对象的方法:
- pause():暂停
- restart():重新开始
- stop():停止
- reset():重置
排序动画
var frameRate = 20;// 相机旋转动画 0-9s不动,9-14s旋转180°
var rotate = new BABYLON.Animation("rotate", "rotation.y", frameRate, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);var rotate_keys = []; rotate_keys.push({frame: 0,value: 0});rotate_keys.push({frame: 9 * frameRate,value: 0});rotate_keys.push({frame: 14 * frameRate,value: Math. PI});rotate.setKeys(rotate_keys);//相机移动动画:0-3s移动,3-5s不动,5-8s移动var movein = new BABYLON.Animation("movein", "position", frameRate, BABYLON.Animation.ANIMATIONTYPE_VECTOR3, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);var movein_keys = []; movein_keys.push({frame: 0,value: new BABYLON.Vector3(0, 5, -30)});movein_keys.push({frame: 3 * frameRate,value: new BABYLON.Vector3(0, 2, -10)});movein_keys.push({frame: 5 * frameRate,value: new BABYLON.Vector3(0, 2, -10)});movein_keys.push({frame: 8 * frameRate,value: new BABYLON.Vector3(-2, 2, 3)});movein.setKeys(movein_keys);// 门的打开与关闭:0-3s不动,3-5s旋转60°,5-13s不动,13-15s旋转-60°var sweep = new BABYLON.Animation("sweep", "rotation.y", frameRate, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);var sweep_keys = []; sweep_keys.push({frame: 0,value: 0});sweep_keys.push({frame: 3 * frameRate,value: 0});sweep_keys.push({frame: 5 * frameRate,value: Math.PI/3});sweep_keys.push({frame: 13 * frameRate,value: Math.PI/3});sweep_keys.push({frame: 15 * frameRate,value: 0});sweep.setKeys(sweep_keys);// 光的明暗:0-7s暗,7-10s变亮,10-14亮,14-15变暗var lightDimmer = new BABYLON.Animation("dimmer", "intensity", frameRate, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);var light_keys = []; light_keys.push({frame: 0,value: 0});light_keys.push({frame: 7 * frameRate,value: 0});light_keys.push({frame: 10 * frameRate,value: 1});light_keys.push({frame: 14 * frameRate,value: 1});light_keys.push({frame: 15 * frameRate,value: 0});lightDimmer.setKeys(light_keys);// 运行动画scene.beginDirectAnimation(camera, [movein, rotate], 0, 25 * frameRate, false);scene.beginDirectAnimation(hinge, [sweep], 0, 25 * frameRate, false);scene.beginDirectAnimation(spotLights[0], [lightDimmer], 0, 25 * frameRate, false);scene.beginDirectAnimation(spotLights[1], [lightDimmer.clone()], 0, 25 * frameRate, false);
分组动画
AnAnimationGroup允许您将动画和网格链接在一起并进行播放,暂停和停止。
// 创建动画组
var animationGroup1 = new BABYLON.AnimationGroup("Group1");// 向动画组中添加动画,并与网格连接
animationGroup1.addTargetedAnimation(animation1, mesh1);
animationGroup1.addTargetedAnimation(animation3, mesh1);
animationGroup1.addTargetedAnimation(animation2, mesh2);// 由于动画可能是用不同的时间线创建的,因此必须使用规范化来对齐它们
// 从第0帧到第100帧,第一个参数不能小于动画组中所有动画的最小帧,第二个参数不能大于动画组中所有动画的最大帧
animationGroup1.normalize(0, 100);// 可以为动画组中所以动画设置组速比speedRadio,用来加快或减慢动画
animationGroup1.speedRatio = 0.25;// 从现有的动画制作组中创建一个组
var animationGroup = new BABYLON.AnimationGroup("my-animation-group");
for (anim of idleAnim.getAnimations()) {animationGroup.addTargetedAnimation(anim.animation, anim.target);
}// 动画结束后触发的回调函数:
animationGroup1.onAnimationEndObservable.add(function() {mesh2.material = redMaterial;
});// 有一个onAnimationLoopObservable对象,它可以在每个动画循环时触发一个函数。(组循环完成后,每个动画对象都会触发一次该函数)
animationGroup1.onAnimationLoopObservable.add(function(targetAnimation) {console.log(targetAnimation.animation.name);
});// 还有一个onAnimationGroupLoopObservable对象,它可以在组的所有动画都已循环完成时触发一个函数:
animationGroup1.onAnimationGroupLoopObservable.add(function(group) {console.log("Group looped!");
});
组合动画(连续动画)
为了使一个动画跟随另一个动画,则需要将另一个参数添加到beginDirectAnimation函数中。此参数本身是由beginDirectAnimation开始的动画结束时要调用的函数。
scene.beginAnimation(目标,开始帧,结束帧,循环,速度,动画结束时);
- target - BabylonJS对象,要动画的theBabylon.js对象
- animations - array,所有要应用于目标的动画
- start frame - number,开始动画的帧
- end frame - number,结束动画的帧
- loop - boolean:可选,要激活动画的循环模式时为true ,否则为false以仅运行一次动画
- speed - number:可选,默认值1,与动画帧速率匹配,数字越大,动画速度越快;数字越低,动画速度越慢
- 在动画结束-功能:可选,调用函数时动画结束,需要循环是false
var frameRate = 10;var xSlide = new BABYLON.Animation("xSlide", "position.x", frameRate, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);var keyFramesP = []; keyFramesP.push({frame: 0,value: 2
});keyFramesP.push({frame: frameRate,value: -2
});keyFramesP.push({frame: 2 * frameRate,value: 2
});xSlide.setKeys(keyFramesP);var yRot = new BABYLON.Animation("yRot", "rotation.y", frameRate, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);var keyFramesR = []; keyFramesR.push({frame: 0,value: 0
});keyFramesR.push({frame: 2.5 * frameRate,value: 2 * Math.PI
});keyFramesR.push({frame: 5 * frameRate,value: 4 * Math.PI
});yRot.setKeys(keyFramesR);var nextAnimation = function() {scene.beginDirectAnimation(box, [yRot, xSlide], 0, 2 * frameRate, true);
}scene.beginDirectAnimation(box, [yRot], 0, 2 * frameRate, false, 1, nextAnimation);
动画人物
在Blender中创建角色,使用Mixamo向其中添加动画并将其组合为单个模型,再到通过键盘控制动画角色的移动。
有不同的工具和可能的工作流程来创建可以在Babylon.js项目中使用的动画模型。
以下是此操作方法的详细工作流程:
- 使用Blender创建模型
- 将模型导出为.FBX
- 将模型加载到Mixamo中以进行绑定并添加动画
- 将动画模型下载为.FBX文件
- 使用Blender将动画模型组合为一个
- 导出为.GLB(动画为动画组)
- 将.GLB加载到Babylon.js游乐场中,并通过键盘控制模型的移动
官方文档:https://doc.babylonjs.com/divingDeeper/animation/animatedCharacter
没看懂:
- 先进的动画方法:https://doc.babylonjs.com/divingDeeper/animation/animatedCharacter
- 使用渲染训话的动画:https://doc.babylonjs.com/divingDeeper/animation/render_frame_animation
Audio——声音
Babylon.js声音引擎基于Web音频规范。
我们决定不对音频标签或其他机制提供后备支持。因此,要使用我们的声音引擎,您需要使用与Web Audio兼容的浏览器。
不过,如果您在不兼容的浏览器上使用它,它将不会破坏我们引擎的其余部分,它只是不播放声音。
声音引擎提供环境声音,空间声音和定向声音。可以通过代码或加载.babylon文件来创建它。它遵循了您将要看到的其他引擎的简单而强大的原理。
支持的声音格式是浏览器中的一种。通常至少是**.mp3和.wav**。
环境声音:
// 加载声音并在准备好后自动播放
// 参数:名称, url, 场景, 加载完成后的回调函数, 配置{循环与自动播放等}
var music = new BABYLON.Sound("Music", "music.wav", scene, null, {loop: true,autoplay: true,// volume: volume, // 音量// spatialSound: true // 是否为空间声音
});// 回调函数的使用
var music = new BABYLON.Sound("Music", "music.wav", scene, function() {//声音已下载并解码,参数:number(几秒后播放)music.play();
});
单击鼠标或按下按键时播放声音:
var gunshot = new BABYLON.Sound("gunshot", "sounds/gunshot.wav", scene);
window.addEventListener("mousedown", function(evt) {// left click to fireif (evt.button === 0) {gunshot.play();gunshot.setVolume(volume);// 调整音量}
});
window.addEventListener("keydown", function(evt) {// Press space key to fireif (evt.keyCode === 32) {gunshot.play();}
});
设置全局音量:
BABYLON.Engine.audioEngine.setGlobalVolume(0.5);
同时播放多个声音并同步:
var music1 = new BABYLON.Sound("Violons11","sounds/violons11.wav",scene,soundReady,{ loop: true }
);var music2 = new BABYLON.Sound("Violons18","sounds/violons18.wav",scene,soundReady,{ loop: true }
);var music3 = new BABYLON.Sound("Cellolong","sounds/cellolong.wav",scene,soundReady,{ loop: true }
);var soundsReady = 0;function soundReady() {soundsReady++;if (soundsReady === 3) {music1.play();music2.play();music3.play();}
}
空间声音
// 创建空间声音
var music = new BABYLON.Sound("music", "music.wav", scene, null, {loop: true,autoplay: true,spatialSound: true
});
空间声音的默认属性是:
- distanceModel(衰减)默认情况下使用“线性”方程式。其他选项是“反”或“指数”。
- maxDistance设置为100。这意味着一旦听众距离声音的距离超过100个单位,音量将为0。您再也听不到声音了
- panningModel设置为“ equalpower ”;等功率平移算法通常被认为是简单而高效的。另一个可用选项是“ HRTF ”。规范说:“一种更高质量的空间化算法,使用卷积和来自人类对象的测得的冲激响应。这种平移方法呈现立体声输出“。这是使用耳机时的最佳算法。
maxDistance仅在使用“线性”衰减时使用。否则,您可以使用rolloffFactor和refDistance选项调整其他模型的衰减。默认情况下两者都设置为1,但是您当然可以更改它。
例如:
var music = new BABYLON.Sound("music", "music.wav", scene, null, {loop: true,autoplay: true,spatialSound: true,distanceModel: "exponential",rolloffFactor: 2 // 下降因子
});
声音在3D世界中的默认位置是(0,0,0)
。要更改此设置,请使用以下setPosition()
功能:
music.setPosition(new BABYLON.Vector3(100, 0, 0));
将声音附加到网格
var music = new BABYLON.Sound("Violons", "sounds/violons11.wav", scene, null, {loop: true,autoplay: true
});
// Sound will now follow the box mesh position
music.attachToMesh(box);
将位置设为音频监听器
默认情况下,场景的“耳朵”(即听众)始终是当前活动的摄像机。有时,例如在制作第三人称游戏时,您可能需要将另一个网格设置为侦听器-例如角色头像。这可以通过audioListenerPositionProvider
在场景上设置属性来实现。
您创建的方法必须返回一个有效的Vector3
对象。
//返回静态位置
scene.audioListenerPositionProvider = () => {return new BABYLON.Vector3(0, 0, 10);
};
//返回网格的当前位置
//!建议使用'absolutePosition'属性
//反映网格在世界上的位置
scene.audioListenerPositionProvider = () => {//返回静态位置return myMesh.absolutePosition;
};
要切换回使用相机作为侦听器,只需将属性设置为null
。
创建定向3D声音
默认情况下,空间声音是全向的。但是,如果您愿意,可以有定向声音。
**注意:**定向声音仅适用于连接到网格的空间声音。
var music = new BABYLON.Sound("Violons", "violons11.wav", scene, null, {loop: true,autoplay: true
});
// 设置定向锥,参数:内圆锥的大小(以度为单位),外部圆锥的大小(以度为单位),当您位于外部圆锥体之外时的声音音量(介于0.0和1.0之间)
music.setDirectionalCone(90, 180, 0);
music.setLocalDirectionToMesh(new BABYLON.Vector3(1, 0, 0));
music.attachToMesh(box);
锥体的外角必须大于或等于内角,否则将记录错误,并且定向声音将不起作用。
setLocalDirectionToMesh()
只是与您连接到的网格有关的圆锥的方向。默认情况下为(1,0,0)
。
创建自己的自定义衰减
如果要使用特定算法管理衰减(或Web Audio中的距离模型),则可以使用Babylon.js自定义衰减功能绕过本机Web Audio衰减。
注意: Web Audio是硬件加速的。这意味着它主要由设备上的专用音频芯片通过本机代码(浏览器)处理。这样一来,在3D实时渲染的性能方面几乎不会花费任何成本。切换到自定义衰减将使用基于JavaScript的Babylon.js距离计算,并且速度较慢。
而且,自定义衰减仅适用于空间声音(显然),而且还适用于连接到Babylon.js网格的声音。就是说,现在让我们查看执行此操作的代码。首先,必须在选项中指定它:
//创建并加载异步声音
var music = new BABYLON.Sound("Music", "music.wav", scene, null, {loop: true,autoplay: true,useCustomAttenuation: true
});
您将切换到内部Babylon.js数学计算。默认的自定义衰减功能是线性的。
要创建自己的逻辑,您需要以下代码:
//创建自定义衰减功能。在对象附近,音量几乎为0。
//最远,更大声
music.setAttenuationFunction(function(currentVolume,currentDistance,maxDistance,refDistance,rolloffFactor
) {return (currentVolume * currentDistance) / maxDistance;
});
您可以使用这5个参数进行操作,并随心所欲地进行操作。只需返回一个数字,该数字将成为应用于声音的音量。
在此示例中,逻辑有点奇怪,因为您离网格越远,音量越大。
个人Babylonjs学习笔记相关推荐
- PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 call
您的位置 首页 PyTorch 学习笔记系列 PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 发布: 2017年8月4日 7,195阅读 ...
- 容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程
暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...
- 容器云原生DevOps学习笔记——第二期:如何快速高质量的应用容器化迁移
暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...
- 2020年Yann Lecun深度学习笔记(下)
2020年Yann Lecun深度学习笔记(下)
- 2020年Yann Lecun深度学习笔记(上)
2020年Yann Lecun深度学习笔记(上)
- 知识图谱学习笔记(1)
知识图谱学习笔记第一部分,包含RDF介绍,以及Jena RDF API使用 知识图谱的基石:RDF RDF(Resource Description Framework),即资源描述框架,其本质是一个 ...
- 计算机基础知识第十讲,计算机文化基础(第十讲)学习笔记
计算机文化基础(第十讲)学习笔记 采样和量化PictureElement Pixel(像素)(链接: 采样的实质就是要用多少点(这个点我们叫像素)来描述一张图像,比如,一幅420x570的图像,就表示 ...
- Go 学习推荐 —(Go by example 中文版、Go 构建 Web 应用、Go 学习笔记、Golang常见错误、Go 语言四十二章经、Go 语言高级编程)
Go by example 中文版 Go 构建 Web 应用 Go 学习笔记:无痕 Go 标准库中文文档 Golang开发新手常犯的50个错误 50 Shades of Go: Traps, Gotc ...
- MongoDB学习笔记(入门)
MongoDB学习笔记(入门) 一.文档的注意事项: 1. 键值对是有序的,如:{ "name" : "stephen", "genda" ...
最新文章
- Swift default参数
- Apache Struts 和 Spring 开源漏洞状况的对比
- 请问spfa+stack 和spfa+queue 是什么原理
- 无损1080i到1080p是如何制作的
- 应用EtherNet IP转Modbus网关连接施耐德PLC和AB PLC
- stm32f103r6最小系统原理图_stm32f103c8t6封装及最小系统原理图
- EasyUI - panel 高度自适应
- PAT甲级 1012 The Best Rank
- hive reduce
- 什么是知识,什么是知识图谱,有什么作用,有哪些应用领域?
- 微信小程序开发基础知识2(黑马)
- H5身份证上传识别功能
- Windows 搭建 Nexus3 私服
- R语言一般线性模型(涉及因变量是虚拟变量(哑变量))
- jquery国际化 i18n.js
- syslog与rsyslog
- linux下开启、关闭、重启mysql服务
- PyCharm取消下划线
- Qt编写视频监控管理平台(支持海康/大华/宇视/华为/天地伟业/H264/H265等)
- CSS实现背景网格线(background-image)
热门文章
- Spark 基本知识介绍
- 夸西莫多的一首短诗--《瞬息间是夜晚》
- 开放信息抽取(OIE)系统(四)-- 第三代开放信息抽取系统(基于子句, clause-based, 句子重组、删减)
- 装X时刻!win10/CentOS 7双系统成功安装小白教程
- HR做新员工线上培训,怎样做更有效果
- 加减乘除计算机英语,英语里的加减乘除
- 关于rx,tx或I2C串口不够的问题
- 2020届秋招 网易互娱游戏研发工程师面经(已offer)
- matlab语音频谱,信号与系统:用matlab分析wav音频的频谱
- 覆盖vue3.0的最全Vue知识点