BabylonJS 3D Logo

BabylonJS 3D Logo script details
Author
matas
Type
Typescript logo image
typescript
App Version
0.13.0
Visibility
public
Date Created
Oct 25, 2023, 11:19:14 AM
Last Edit Date
Dec 5, 2023, 2:10:02 PM

Script Details

The Code
// We use bitbybit to get the default engine const engine = bitbybit.babylon.engine.getEngine(); const scene = new BABYLON.Scene(engine); // It is important to inform bitbybit that we use non-default scene bitbybit.babylon.scene.setAndAttachScene({ scene }); var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(2, 2, -2), scene); camera.setTarget(BABYLON.Vector3.Zero()); // We can only re-use the existing rendering canvas from default engine const canvas = bitbybit.babylon.engine.getRenderingCanvas(); camera.attachControl(canvas, true); camera.speed = 0.05; camera.minZ = 0; scene.clearColor = new BABYLON.Color4(26 / 255, 28 / 255, 31 / 255, 1); // BabylonJS way of creating lights const light = new BABYLON.HemisphericLight("HemiLight", new BABYLON.Vector3(0, 1, 0), scene); light.intensityMode = BABYLON.Light.INTENSITYMODE_ILLUMINANCE; light.intensity = 1; const createPointLightThroughBitByBit = async () => { // Bitbybit way of creating a point light, which also will create shadow generator and do some magic const ptLightDto = new Bit.Inputs.BabylonScene.PointLightDto(); ptLightDto.position = [0.7, 2, -1.5]; ptLightDto.intensity = 400; ptLightDto.radius = 0.1; bitbybit.babylon.scene.drawPointLight(ptLightDto); } const createBabylonJSLogo = async () => { const baseCube = await bitbybit.occt.shapes.solid.createBox({ width: 1, height: 1, length: 1, center: [0, 0, 0] }); const thirdSize = 0.33333334; const twoThirdsSize = 0.666666667; const halfThird = 0.1666666; const baseCutout = await bitbybit.occt.shapes.solid.createBox({ width: thirdSize, height: thirdSize, length: thirdSize, center: [thirdSize, thirdSize, -thirdSize] }); const diffedCube = await bitbybit.occt.booleans.difference({ shape: baseCube, shapes: [baseCutout], keepEdges: false, }); const whiteBox1 = await bitbybit.occt.shapes.solid.createBox({ width: twoThirdsSize, height: twoThirdsSize, length: twoThirdsSize, center: [halfThird, halfThird, -halfThird] }); const whiteBox2 = await bitbybit.occt.shapes.solid.createBox({ width: thirdSize, height: twoThirdsSize, length: thirdSize, center: [0, halfThird, thirdSize] }); const whiteUnion = await bitbybit.occt.booleans.union({ shapes: [whiteBox1, whiteBox2], keepEdges: false, }); const whiteCubeCutout = await bitbybit.occt.shapes.solid.createBox({ width: 0.95, height: 0.95, length: 0.95, center: [0, 0, 0] }); const diffedWhite = await bitbybit.occt.booleans.difference({ shape: whiteUnion, shapes: [whiteCubeCutout, baseCutout], keepEdges: false, }); const diffedRed = await bitbybit.occt.booleans.difference({ shape: diffedCube, shapes: [diffedWhite], keepEdges: false, }); const drawOptions = new Bit.Inputs.Draw.DrawOcctShapeOptions(); drawOptions.drawEdges = false; const redPartMesh = await bitbybit.draw.drawAnyAsync({ entity: diffedRed, options: drawOptions }); const whitePartMesh = await bitbybit.draw.drawAnyAsync({ entity: diffedWhite, options: drawOptions }); // this is how you can access results of the drawing operation const surfaceMesh = whitePartMesh.getChildMeshes()[0]; const mat = new BABYLON.PBRMetallicRoughnessMaterial("surface-material"); mat.baseColor = new BABYLON.Color3(1, 1, 1); mat.metallic = 0.4; mat.roughness = 0.7; surfaceMesh.material = mat; // this will just group red and white meshes under one parent mesh const meshParent = new BABYLON.Mesh("parent-for-logo", scene); whitePartMesh.parent = meshParent; redPartMesh.parent = meshParent; return meshParent; } const createText = async () => { const textOptions = new Bit.Advanced.Text3D.Text3DDto(); textOptions.text = "BabylonJS"; textOptions.fontSize = 0.3; textOptions.height = 0.04; textOptions.origin = [1, 0, 0]; textOptions.direction = [1, 0, 0]; textOptions.rotation = 90; const text = await bitbybit.advanced.text3d.create(textOptions); // we center the text const textMoved = await bitbybit.occt.transforms.translate({ shape: text.compound, translation: [0, 0, -text.advanceWidth / 2] }); const textDrawOptions = new Bit.Inputs.Draw.DrawOcctShapeOptions(); textDrawOptions.edgeWidth = 0.3; textDrawOptions.edgeColour = "#ffffff"; textDrawOptions.faceColour = "#ff0000"; const drawnText = await bitbybit.draw.drawAnyAsync({ entity: textMoved, options: textDrawOptions, }); return drawnText; } const start = async () => { createPointLightThroughBitByBit(); const logoMesh = await createBabylonJSLogo(); const textMesh = await createText(); const ground = await bitbybit.occt.shapes.face.createRectangleFace({ width: 22, length: 22, center: [0, -0.5, 0], direction: [0, -1, 0], }); const groundDrawOptions = new Bit.Inputs.Draw.DrawOcctShapeOptions(); groundDrawOptions.faceOpacity = 0.4; bitbybit.draw.drawAnyAsync({ entity: ground, options: groundDrawOptions }); // this is one way to animate resulting mesh scene.onBeforeRenderObservable.add(s => { textMesh.rotate(new BABYLON.Vector3(0, 1, 0), -0.005); }); // lets create a grid of instanced meshes const size = 10; const step = 2.5; for (let i = -size; i <= size; i += step) { for (let j = -size; j <= size; j += step) { // we need children because logo mesh consists of two childs - red and white mesh const children = logoMesh.getChildMeshes(); children.forEach((c: BABYLON.Mesh) => { const verticeData = c.getVerticesData(BABYLON.VertexBuffer.PositionKind); if (verticeData && verticeData.length > 0) { const inst = c.createInstance(`${i}-${j}-mesh-${c.name}`); inst.position = new BABYLON.Vector3(i, -2, j); scene.metadata.shadowGenerators.forEach(sh => { sh.addShadowCaster(inst, true); }); } }); } } } start();