BlazorBabylonJs
BlazorBabylonJs copied to clipboard
Define A Goal (for the project)
Description
This thread is primarily directed at @SQL-MisterMagoo but everyone is welcome to participate in this discussion.
History
I created this project because I wanted to see if I could get the BabylonJs 3D framework to work with Blazor. I got that working and then parameterized the sample code in an attempt to make it generic.
@SQL-MisterMagoo then got a hold of the project and introduced a radically different structure that among other things allows you to use declarative syntax. Essentially the Blazor C# code allows you to call JavaScript methods on this file.
I can't stress how powerful this is and what possibilities it opens up. The question is now, where do we go from here?
Proposed Features
- [ ] Sound
-
- -[ ] Load Audio
-
- -[ ] Play/Pause/Stop Audio
-
- -[ ] Display Audio Visually
- [ ] Control Camera
- [ ] Control Lights
- [ ] Support/Enable The Inspector
- [ ] Amp360Video
- [ ] MeshWriter (Generate letters in BABYLON meshes)
- [ ] Distribute as a Nuget Package (Blazored)
They all sound like good features.
As far as the code goes, I would probably propose that we have a JavaScript (or TypeScript) module for the actual interop - with a corresponding C# api so from code we could do things like
var myBabylon = BabylonBlazor.WithDefaults().WithLights(MySetOfLights);
myBabylon.Cameras.Add(new Camera(...));
var textMesh = MeshWriter.Create("Hello World");
myBabylon.LoadMesh(textMesh);
I would see these sorts of API calls being pretty much a gateway to the JS library - like any JSInterop library - but perhaps there could be some batching of operations or even some caching/recording (undo/redo?) of operations.
But these apis would also be the basis of declarative components, like in the current demo.
<BabylonCanvas>
<Light PropertyX="1"/>
<Camera LookAt="SomeMeshId"/>
<Mesh Source="MeshWriter.Create("Hello World")/>
</BabylonCanvas>
@SQL-MisterMagoo Two Issues:
- No one loves Typescript as much as I do, but, NPM, for this project, is a non-starter for me (I have had too many nightmares where programmers on my team got stuck because of 'NPM Hell'). Do you think we can we use Typescript without NPM (or some other 'extra technology' that could potentially be a 'roadblock' for neophytes)?
Meaning, I would rather just continue to code in JavaScript so that a neophyte could just pull this project down and it-just-works 😜
- I love this As-The-"Goal" 💖:
var myBabylon = BabylonBlazor.WithDefaults().WithLights(MySetOfLights);
myBabylon.Cameras.Add(new Camera(...));
var textMesh = MeshWriter.Create("Hello World");
myBabylon.LoadMesh(textMesh);
<BabylonCanvas>
<Light PropertyX="1"/>
<Camera LookAt="SomeMeshId"/>
<Mesh Source="MeshWriter.Create("Hello World")/>
</BabylonCanvas>
If you also agree then we can close this issue and I will move the other features to their own issues, so they can be addressed in the future.
So, for the main goal, what is the first step?
🤣
I only included TypeScript as an option - I am personally just as comfortable with plain JS.
I'm happy for us to have a set of issues as you suggest.
My initial thoughts would be that the C# api (calling into JS) is the key - if we get that right, so the end user of the package doesn't have to see any JS then it's a win.
Wrapping components around that C# API should then be a very simple job.
Where do we start and what can I do?
I think - as you suggested - a set of issues listing the basic requirements for the api...
I feel like we need to figure out the "how" of doing this - the reason I picked up that web-component was because it made life easier - we need to make life easier still...
How do we plan to build a scene - is it a case of setting up a load of configuration and saying "build" and then it's static? probably not - we want to be more dynamic I think - adding and removing objects from the scene, switching scenes, saving/loading scenes?
Can we define an api that lets us - from code initially - create a scene, display it, modify it and destroy it. How does that look? Is it a "builder" pattern like above or some other ?
If you could have a think about how you would like that api to look and map out some high level goals as issues I think it would be a good start.
Sounds perfect. Give me a day to think on this and write down some ideas.
I thought about it, I think we need to first agree on some basic Assumptions?
- There is only one engine (we make it for you)
- You can build and control a scene using declarative markup
- You can have multiple scenes on a page
- You can call any unsupported BabylonJS feature, from Blazor, using C# code

Quick note to anyone wanting to catch up on how Blazor works with JavaScript, this YouTube video by @SteveSandersonMS offers a good overview.
https://youtu.be/QnBYmTpugz0?t=137
However, this project implements most of the suggestions covered, plus, additional advanced architecture.
Can we define an api that lets us - from code initially - create a scene, display it, modify it and destroy it. How does that look? Is it a "builder" pattern like above or some other ?
Create a Scene
<BabylonCanvas>
<Scene ="@Scene1"/>
</BabylonCanvas>
@code {
Scene Scene1 = new BabylonBlazor.Scene();
Camera Camera1 = new BabylonBlazor.Camera { LookAt="SomeMeshId" };
Scene1.Cameras.Add(Camera1);
var textMesh = MeshWriter.Create("Hello World");
Scene1.LoadMesh(textMesh);
}
I then had a thought, what if we created C# classes for the TypeScript classes in BabylonJS? I then looked to see if anyone else did that and found the Retyped/BabylonJsDemo.
They use a Bridge.NET Compiler and even have a Retyped.babylon NuGet package.
They end up with C# code like this:
using Retyped;
using static Retyped.babylon_js.BABYLON;
namespace BabylonJsDemo.SceneProviders
{
/// <summary>
/// Original sources: http://www.babylonjs-playground.com/#12S23Y
/// </summary>
public class Scene1Provider : AbstractSceneProvider
{
public override Scene CreateScene(dom.HTMLCanvasElement canvas, Engine engine)
{
// This creates a basic Babylon Scene object (non-mesh)
var scene = new Scene(engine);
// This creates and positions a free camera (non-mesh)
var camera = new FreeCamera("camera1", new Vector3(0, 5, -10), scene);
// This targets the camera to scene origin
camera.setTarget(Vector3.Zero());
// This attaches the camera to the canvas
camera.attachControl(canvas, true);
// This creates a light, aiming 0,1,0 - to the sky (non-mesh)
var light = new HemisphericLight("light1", new Vector3(0, 1, 0), scene);
// Default intensity is 1. Let's dim the light a small amount
light.intensity = 0.7;
// Our built-in 'sphere' shape. Params: name, subdivs, size, scene
var sphere = Mesh.CreateSphere("sphere1", 16, 2, scene);
// Move the sphere upward 1/2 its height
sphere.position.y = 1;
// Our built-in 'ground' shape. Params: name, width, depth, subdivs, scene
var ground = Mesh.CreateGround("ground1", 6, 6, 2, scene);
return scene;
}
}
}
Is this something that could help us?
For now I created this task for myself: Try to use the Retyped.babylon NuGet package
... For now I created this task for myself: Try to use the Retyped.babylon NuGet package
This so didn't work :( Could not get the thing to compile. They don't provide the source code so I can't diagnose what is wrong.