Babylonjs 加载glTF,OBJ,STL模型
Babylon.js内置的模型格式是.babylon,Babylon.js可以不需要其它额外的插件即可加载。
基本用法
要加载指定的类型的文件,Babylon.js首先需要引入相应文件的插件。
目前支持的文件格式类型:
如果想要快速添加对所有的文件格式的支持,可以将以下脚本引入到页面中:
<script src="https://cdn.babylonjs.com/babylon.js"></script>
<script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
有关NPM的使用,请参阅:babylonjs-loaders
引入插件以后,可以使用SceneLoader类加载模型,它提供了一些加载方法。
SceneLoader.Append
从文件文件夹中加载所有的模型资源并添加到babylon场景中
配置项:文件夹路径,资源名称,场景对象,回调函数
BABYLON.SceneLoader.Append("./", "duck.gltf", scene, function (scene) {
// 模型添加成功后,执行场景对象的一些方法
});
SceneLoader.Load
从文件中加载模型文件并创建一个新的场景对象
配置项:文件夹路径,资源名称,引擎对象,回调函数
BABYLON.SceneLoader.Load("/assets/", "batman.obj", engine, function (newScene) {
// ...
});
SceneLoader.ImportMesh
从文件中加载模型并将它们添加到场景中,这个和Append区别在于,回调返回的是模型对象而不是场景对象。我们可以在成功的回调里面对模型再进行进一步的处理。
配置项:将要添加到场景中的模型名称或为空(将所有模型或者骨骼加载),文件夹路径,资源名称,场景对象,回调函数
资源名称一定是模型文件名称,不能带有任何路径,即一定是xxx.babylon。而不能是xxx/xxx.babylon,而前面的文件夹路径才是用来设置路径的。
BABYLON.SceneLoader.ImportMesh(["myMesh1", "myMesh2"], "./", "duck.gltf", scene, function (newMeshes, particleSystems,skeletons){
// 对骨骼和模型进行进一步操作
// 对于glTF文件,粒子系统默认为空
});
从文件夹中添加所有的资源到babylon,但不会自动添加到场景中
配置项:文件夹路径,资源名称,场景对象,回调函数
BABYLON.SceneLoader.LoadAssetContainer("./", "duck.gltf", scene, function (container) {
var meshes = container.meshes;
var materials = container.materials;
//...
// Adds all elements to the scene
container.addAllToScene();
});
回调函数会返回一个容器对象,里面包含所有模型加载的资源光源,模型,相机等等。如果需要将模型添加到场景,需要使用:
container.addAllToScene();
将添加的容器内容从场景中删除,则使用:
container.removeAllFromScene();
SceneLoader.AppendAsync
我们还可以通过使用Async函数来实现链式回调:
BABYLON.SceneLoader.AppendAsync("./", "duck.gltf", scene).then(function (scene) {
// do something with the scene
});
123
请参阅如何使用Promises了解有关使用promises的更多信息。
高级用法
使用onPluginActivatedObservable设置属性和调用特定于特定加载器的方法。
BABYLON.SceneLoader.OnPluginActivatedObservable.add(function (loader) {
if (loader.name === "gltf") {
// do something with the loader
// loader.<option1> = <...>
// loader.<option2> = <...>
// loader.dispose();
}
});
或者,静态同步SceneLoader函数返回插件。
var loader = BABYLON.SceneLoader.Load("./", "duck.gltf", engine, function (scene) {
// do something with the scene
});
// do something with the loader
// loader.<option1> = <...>
// loader.<option2> = <...>
// loader.dispose();
加载多个模型
为了方便开发者加载多个模型,Babylon.js从1.14版本引入了AssetsManager类。
此类可用于将模型导入场景活加载文本和二进制文件。
注意:导入的模型具有旋转四元数设置,因此使用rotation设置旋转会发现会旋转到意想不到的位置,如果使用rotation请将rotationQuaternion设置为空。
使用AssetsManager
初始化和创建任务
要使用它,首先要先通过场景进行实例化:
var assetsManager = new BABYLON.AssetsManager(scene);
然后,可以通过管理器的addMeshTask
方法添加任务:
var meshTask = assetsManager.addMeshTask("skull task", "", "scenes/", "skull.babylon");
每个任务都有一个成功回调和错误回调:
meshTask.onSuccess = function (task) {
task.loadedMeshes[0].position = BABYLON.Vector3.Zero();
}
meshTask.onError = function (task, message, exception) {
console.log(message, exception);
}
你也可以使用相同的方式加载文本addTextFileTask
和二进制文件addBinaryFileTask
:
var textTask = assetsManager.addTextFileTask("text task", "msg.txt");
textTask.onSuccess = function(task) {
console.log(task.text);
}
var binaryTask = assetsManager.addBinaryFileTask("binary task", "grass.jpg");
binaryTask.onSuccess = function (task) {
// Do something with task.data
}
管理器也支持加载图像addImageTask
:
var imageTask = assetsManager.addImageTask("image task", "img.jpg");
imageTask.onSuccess = function(task) {
console.log(task.image.width);
}
管理器也可以通过addTextureTask
来创建加载纹理任务:
var textureTask = assetsManager.addTextureTask("image task", "img.jpg");
textureTask.onSuccess = function(task) {
material.diffuseTexture = task.texture;
}
任务状态和错误处理
每个任务都有一个状态对象,表示当前任务的执行状态。状态由枚举表示,BABYLON.AssetTaskState有4种状态:
- INIT - 在任务开始执行之前
- RUNNING - 当任务开始执行但尚未完成时
- DONE - 当任务成功完成执行时
- ERROR - 任务失败时
如果任务具有错误状态(BABYLON.AssetTaskState.ERROR),则将向该任务添加新对象:task.errorObject。错误对象定义了2个变量,两个都是可选的:
- message - 一个很快解释错误的字符串(例如“请求返回404”)
- exception - 如果在执行期间抛出异常,异常对象将包含堆栈跟踪信息
这样,通过管理器也可以访问错误:
assetsManager.onTaskErrorObservable.add(function(task) {
console.log('task failed', task.errorObject.message, task.errorObject.exception);
});
管理器回调和观察者模式
管理器自身拥有四个回调:
- onFinish
- onProgress
- onTaskSuccess
- onTaskError
assetsManager.onProgress = function(remainingCount, totalCount, lastFinishedTask) {
engine.loadingUIText = 'We are loading the scene. ' + remainingCount + ' out of ' + totalCount + ' items still need to be loaded.';
};
assetsManager.onFinish = function(tasks) {
engine.runRenderLoop(function() {
scene.render();
});
};
管理器还允许你使用观察者回调来处理onFinish,onProgress,onTaskSuccess和onTaskError:
- onTaskSuccessObservable - 当单个任务成功完成时,将执行已注册的观察者回调。
- onTaskErrorObservable - 当单个任务失败时,将执行已注册的观察者回调。
- onProgressObservable - 当单个任务成功完成或失败时,将执行已注册的观察者回调。
- onTasksDoneObservable - 当所有任务执行完成(成功或失败!)时,将执行已注册的观察者回调
assetsManager.onTaskSuccessObservable.add(function(task) {
console.log('task successful', task)
});
123
assetsManager.onTasksDoneObservable.add(function(tasks) {
var errors = tasks.filter(function(task) {return task.taskState === BABYLON.AssetTaskState.ERROR});
var successes = tasks.filter(function(task) {return task.taskState !== BABYLON.AssetTaskState.ERROR});
});
开始任务
设置好任务以后,开启必须调用开始:
assetsManager.load();
可用任务
你可以使用管理器去实现加载7种类型数据的任务。
每个任务都使用以下属性扩展AbstractAssetTask类(并实现IAssetTask接口):
onSuccess: (task: IAssetTask) => void;
onError: (task: IAssetTask, message?: string, exception?: any) => void;
isCompleted: boolean = false;
name: string;
taskState: AssetTaskState;
errorObject: { message?: string; exception?: any; };
注意,加载的任务数据类型必须与创建的任务数据类型对应。例如,CubeTextureAssetTask的构造函数签名采用与类BABYLON.CubeTexture相同的变量。变量的顺序可能会有所不同。
MeshAssetTask
MeshAssetTask用于加载外部的模型(.babylon,.obj,.gltf等)。
构造函数配置指定:
constructor(name: string, meshesNames: any, rootUrl: string, sceneFilename: string)
额外属性:
public loadedMeshes: Array<AbstractMesh>;
public loadedParticleSystems: Array<ParticleSystem>;
public loadedSkeletons: Array<Skeleton>;
TextFileAssetTask
用于异步加载(文本)文件。
构造函数配置指定:
constructor(name: string, url: string)
额外属性:
public url: string;
public text: string;
BinaryFileAssetTask
此任务用于加载二进制文件。它与TextFileAssetTask的主要区别在于数据将存储在ArrayBuffer中
构造函数配置指定:
constructor(name: string, url: string)
额外属性:
public url: string;
public data: ArrayBuffer;
ImageAssetTask
此功能将加载图像(.png,.jpg,.gif)。它将创建一个HTMLImageElement对象
构造函数配置指定:
constructor(name: string, url: string)
额外属性:
public url: string;
public image: HTMLImageElement;
TextureAssetTask
这将从提供的单个URL创建一个新的BABYLON.Texture。
构造函数配置指定:
constructor(name: string, url: string, noMipmap?: boolean, invertY?: boolean, samplingMode: number = BABYLON.Texture.TRILINEAR_SAMPLINGMODE)
额外属性:
public texture: Texture;
CubeTextureAssetTask
与TextureAssetTask相同,但对于立方体纹理
构造函数配置指定:
constructor(name: string, url: string, extensions?: string[], noMipmap?: boolean, files?: string[])
额外属性:
public texture: CubeTexture;
HDRCubeTextureAssetTask
与CubeTextureAssetTask相同,但适用于HDR立方体纹理
构造函数配置指定:
constructor(name: string, url: string, size?: number, noMipmap = false, generateHarmonics = true, useInGammaSpace = false, usePMREMGenerator = false)
额外属性:
public texture: HDRCubeTexture;
EquiRectangularCubeTextureAssetTask
与CubeTextureAssetTask相同,但对于Equirectangular立方体纹理
构造函数配置指定:
constructor(name: string, url: string, size: number, noMipmap = false, useInGammaSpace = true)
额外属:
public texture: EquiRectangularCubeTexture;
使用加载屏幕
默认情况下,AssetsManager将在加载资源时显示加载屏幕:
如果要禁用加载屏幕,则必须设置useDefaultLoadingScreen为false:
assetsManager.useDefaultLoadingScreen = false;
如果ShowLoadingScreen设置为true(默认情况下),则在使用SceneLoader加载场景时也会显示加载屏幕。
BABYLON.SceneLoader.ShowLoadingScreen = false;
同样,您也可以使用以下功能手动显示或隐藏加载屏幕:
engine.displayLoadingUI();
engine.hideLoadingUI();
使用loadingUIText设置显示加载文本:
engine.loadingUIText = "text";
使用loadingUIBackgroundColor方法控制背景颜色:
engine.loadingUIBackgroundColor = "red";