// 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();