Babylonjs代码解读一
Scene 、Engine 之间的关系
从API层面,我们使用Babylon就是需要用户构建一个场景Scene就可以里,在场景中添加,相机,灯光,几何体,材质就可以完成一个场景,在初始化场景的时候,需要传入一个引擎Engine。
const createScene = () => {
const scene = new BABYLON.Scene(engine);
const camera = new BABYLON.ArcRotateCamera("camera", -Math.PI / 2, Math.PI / 2.5, 3, new BABYLON.Vector3(0, 0, 0));
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0));
const box = BABYLON.MeshBuilder.CreateBox("box", {});
return scene;
}
在代码面是讲,场景Scene是引擎的一个属性,代码如下:
// Scene.ts 中的代码
this._engine = engine || EngineStore.LastCreatedEngine;
if (!fullOptions.virtual) {
EngineStore._LastCreatedScene = this;
this._engine.scenes.push(this);
} else {
this._engine._virtualScenes.push(this);
}
// Engine.ts中的属性代码
/**
* Gets the list of created scenes
*/
public scenes = new Array<Scene>();
/** @hidden */
public _virtualScenes = new Array<Scene>();
Mesh 、Scene之间的关系
在API层面,Mesh的创建,需要传入Scene,如第一段代码中所示,那底层到底做了什么,就拿创建一个立方体BoxMesh来说,所有的Mesh都挂载在BABYLON.MeshBuilder
在Node.ts类中,通过私有属性_Scene来保存Scene的指针,通过getScene() 获取当前的Scene,在TransFormNode.ts中,将boxMesh加载到场景中,代码如下
// TransFormNode 初始化代码
constructor(name: string, scene: Nullable<Scene> = null, isPure = true) {
super(name, scene);
// 只有isPure为true,才执行
if (isPure) {
// 将mesh 添加到场景中
this.getScene().addTransformNode(this);
}
}
这里并没有执行,addTransformNode的实现,通过abstractMesh.ts 初试化代码可以看到,是调用的scene.ts中的addMesh
// abstractMesh.ts的初始化
/**
* Creates a new AbstractMesh
* @param name defines the name of the mesh
* @param scene defines the hosting scene
*/
constructor(name: string, scene: Nullable<Scene> = null) {
// 这里设置transformNode中,isPure 为false,跳过了addTransformNode
super(name, scene, false);
this.getScene().addMesh(this);
this._resyncLightSources();
// Mesh Uniform Buffer.
this._uniformBuffer = new UniformBuffer(this.getScene().getEngine(), undefined, undefined, name);
this._buildUniformLayout();
}
// Scene 中将Mesh对象都存放在 meshes 中
/**
* Add a mesh to the list of scene's meshes
* @param newMesh defines the mesh to add
* @param recursive if all child meshes should also be added to the scene
*/
public addMesh(newMesh: AbstractMesh, recursive = false) {
if (this._blockEntityCollection) {
return;
}
this.meshes.push(newMesh);
newMesh._resyncLightSources();
if (!newMesh.parent) {
newMesh._addToSceneRootNodes();
}
this.onNewMeshAddedObservable.notifyObservers(newMesh);
if (recursive) {
newMesh.getChildMeshes().forEach((m) => {
this.addMesh(m);
});
}
}
在node.ts中,讲记录Scene与Mesh之间的父子关系,如果已经添加到场景中,再次添加,就不在执行_addToSceneRootNodes,
// node.ts中的代码
/** @hidden */
public _addToSceneRootNodes() {
if (this._nodeDataStorage._sceneRootNodesIndex === -1) {
this._nodeDataStorage._sceneRootNodesIndex = this._scene.rootNodes.length;
this._scene.rootNodes.push(this);
}
}
在Scene根节点下的mesh的parent的值为null
Mesh的Geometry如何转化为Buffer
通过MeshBuilder下的CreateXXX,创建Mesh,那么渲染的时候,这些Mesh中的Geometry又是如何转变到buffer
整个过程,在创建的时候就逐步调用被生成。
…… 后续继续补充