Actu Smile

Introducing 3B : a converter between Three.js and Babylon.js

  • Date de l’événement 08 Aug. 2024
  • Temps de lecture min.

Discover ThreeXBabylon, the tool for seamlessly converting 3D scenes between Three.js and Babylon.js, overcoming limitations for immersive web projects.

Introducing 3B : a converter between Three.js and Babylon.js

In the realm of real-time 3D graphics within web browsers, two prominent JavaScript libraries stand out: Three.js and Babylon.js. These libraries serve as powerful 3D engines, enabling the creation and display of immersive scenes. Our focus is on developing a library that facilitates seamless scene transformation between Three.js and Babylon.js, and vice versa.

ThreeXBabylon aims to provide a functional implementation that allows for smooth conversion between Three.js and Babylon.js. In this blog, we will introduce the tool, and identify and address its constraints and limitations.

Architecture

ThreeXBabylon facilitates the transition between Three.js and Babylon.js using a gltf file as the initial input. When a valid gltf file is provided, the scene is loaded, and each component within the scene is converted to its equivalent in the other framework.

 

Component Conversion and Parameters Mapping

The conversion of scene components is accomplished by creating specific classes that act as bridges between the equivalent components in each framework. For instance, let's consider the HemisphericLight component. Suppose we want to transition from Three.js to Babylon.js. In this case, a specialized class called BabylonHemisphericLight is instantiated. It takes, as parameters in its constructor, an instance of HemisphereLight in Three.js. These parameters, such as color and direction vector, are then mapped to create a new instance of HemisphericLight in Babylon.js, which is then returned. This process ensures seamless conversion between the frameworks while preserving the essential properties of each component.

constructor(threeLight: HemisphereLight, scene: BABYLON.Scene, x?: number, y?: number, z?: number) {
BabylonHemiSphericLight._lightNumber++;
this.name = this.name + BabylonHemiSphericLight._lightNumber;
this.light = new BABYLON.HemisphericLight(this.name, new BABYLON.Vector3(this.x, this.y, this.z), scene);
this.light.diffuse = this.convertColor(threeLight.color);
}

 

Adapter Pattern

To facilitate this transition, we employed the Adapter design pattern, which enables collaboration between objects with incompatible interfaces. The adapter acts as a mediator, wrapping one of the objects to conceal the complexities of conversion occurring in the background. In our scenario, we need to develop two adapters (ThreeToBabylon and BabylonToThree) to handle the conversion process in both directions. Each adapter implementation defines the logic for converting the components.

The key benefit of using the adapter pattern is its ability to abstract away the complexities, making the transition between the two frameworks seamless and straightforward. By encapsulating the conversion logic within the adapters, users can easily interact with the system without needing to understand the intricacies of the underlying conversion process.

Scene Conversion

The Scene Conversion process is a crucial step where all the necessary operations are consolidated into a single class. The objective is to unify the responsibility of converting an entire scene within this class, equipped with all the essential elements to construct the converted scene seamlessly.

We utilize two significant converters to facilitate the bidirectional conversion between Babylon.js and Three.js. These converters are initialized with the path to the gltf file representing the scene to be converted.

Subsequently, we traverse through all the components of the loaded scene, converting each component to its counterpart in the alternate library using the Adapter implementation mentioned earlier. Here's a snippet illustrating this process:

convertThreeSceneChildren() {
this.threeScene = this.threeLoader.scene;
this.threeScene.children.forEach((child) => {
let childComponent = this.threeComonentBuilder.builChild(child);
this.threeToBabylon.convertComponent(childComponent, this.scene, this.canvas);
});
}

Once the scene is converted, we proceed to render it:

this.threeLoader.loadSceneFromJson().then(() => {
this.convertThreeSceneChildren();
this.render();
this.dispose();
});

Result

In our demonstration, we began by setting up an initial scene in both Babylon.js and Three.js frameworks, each consisting of three components:

  • Box
  • HemisphericLight
  • Camera

The image below illustrates the outcome of converting a simple scene between Babylon.js and Three.js:

Note: The current implementation supports the conversion of only these three components and certain types of meshes.

Restrictions and Limits

Constraints and Challenges

It's crucial to address some of the challenges encountered during the development phase and shed light on the limitations of this approach.

 

Accuracy Concerns

First and foremost, achieving 100% accuracy in component conversion remains a challenge. Due to variations in parameter types between equivalent components in the two frameworks, despite our efforts to map these parameters, achieving complete accuracy remains elusive.

 

Incompatibility of Components

Furthermore, certain components lack direct equivalents in their counterpart framework. For instance, consider the Mesh component. While Three.js provides pre-defined mesh types like SphereGeometry and CylinderGeometry, Babylon.js simplifies the process by returning a generic Mesh without distinct types or specific parameters. This disparity complicates the transformation of meshes.

 

Scene Rendering

The differences in rendering engines and underlying philosophies between Three.js and Babylon.js pose significant challenges. While Three.js serves as a cross-platform JavaScript library, Babylon.js functions as a real-time 3D engine, offering enhanced capabilities. These disparities affect the scene rendering process during conversion, leading to synchronization issues, particularly when transitioning from Babylon to Three.js scenes.

 

Handling Special Mesh Textures

Converting special material textures for meshes presents considerable complexity. Additionally, differences in how materials are treated between the two frameworks further complicate the conversion process.

Conclusion

Throughout this project, we've demonstrated the technical feasibility of such conversions. However, for widespread adoption, the conversion tool must support a sufficient range of components and address the majority of restrictions and limitations inherent in transitioning between the two frameworks.

As a starting point, there is ample room for further development, with various potential solutions available to implement. However, there is still a considerable journey ahead to make it perfect.

Ibrahim Talbi

Ibrahim Talbi

Software engineer