GUI Example CAD Configurator

GUI Example CAD Configurator script details
Author
matas
Type
Typescript logo image
typescript
App Version
0.14.0
Visibility
public
Date Created
Nov 15, 2023, 2:10:39 PM
Last Edit Date
Jan 18, 2024, 12:13:10 PM

Script Details

The Code
let computing = false; let previousStarMesh: BABYLON.Mesh; let previousStarShape: Bit.Inputs.OCCT.TopoDSShapePointer; let previousMeshInstances: BABYLON.InstancedMesh[] = []; type Model = { nrRays: number, innerRadius: number, outerRadius: number, nrSections: number } const model: Model = { nrRays: 5, nrSections: 3, innerRadius: 1, outerRadius: 3, } const start = async () => { bitbybit.draw.drawGridMesh(new Bit.Inputs.Draw.SceneDrawGridMeshDto()) createGUI(); const dirLight = new Bit.Inputs.BabylonScene.DirectionalLightDto(); dirLight.direction = [-20, -20, -20]; dirLight.shadowGeneratorMapSize = 2056; dirLight.intensity = 4; bitbybit.babylon.scene.drawDirectionalLight(dirLight); createShape(model); const skyBoxOptions = new Bit.Inputs.BabylonScene.SkyboxDto(); skyBoxOptions.skybox = Bit.Inputs.Base.skyboxEnum.default; skyBoxOptions.blur = 5; bitbybit.babylon.scene.enableSkybox(skyBoxOptions); } start(); async function createShape(m: Model) { computing = true; await disposePrevious(); const shapesToDelete = []; const star1 = await bitbybit.occt.shapes.wire.createStarWire({ numRays: m.nrRays, innerRadius: m.innerRadius, outerRadius: m.outerRadius, center: [0, 0, 0], direction: [0, 1, 0], half: false, }); const star2 = await bitbybit.occt.shapes.wire.createStarWire({ numRays: m.nrRays, innerRadius: m.innerRadius, outerRadius: m.outerRadius, center: [0, Math.random(), 0], direction: [0, 1, 0], half: false, }); shapesToDelete.push(star1, star2); const cornerPoints1 = await bitbybit.occt.shapes.edge.getCornerPointsOfEdgesForShape({ shape: star1 }); const cornerPoints2 = await bitbybit.occt.shapes.edge.getCornerPointsOfEdgesForShape({ shape: star2 }); const pts = []; for (let i = 0; i < cornerPoints1.length; i++) { if (i % 2 === 0) { const pt = cornerPoints2[i]; pt[1] += Math.random() * 2; pts.push(pt); } else { const pt = cornerPoints1[i]; pts.push(pt); } } const flower = await bitbybit.occt.shapes.wire.createPolygonWire({ points: pts, }); shapesToDelete.push(flower); const flowerFillet = await bitbybit.occt.fillets.fillet3DWire({ shape: flower, direction: [0, 10, 0], radius: 360 / m.nrRays / 600, }); shapesToDelete.push(flowerFillet); const flowers = []; for (let r = 1; r <= m.nrSections; r++) { const scaled = await bitbybit.occt.transforms.scale3d({ shape: flowerFillet, scale: [1 / r, r % 2 === 0 ? r / m.nrSections * 2 : r / m.nrSections * 1.5, 1 / r], center: [0, 0, 0], }); shapesToDelete.push(scaled); const translated = await bitbybit.occt.transforms.translate({ shape: scaled, translation: [0, r % 2 === 0 ? r / 4 : r / 3, 0] }); flowers.push(translated); shapesToDelete.push(translated); } const mirrored = await bitbybit.occt.transforms.mirrorAlongNormalShapes({ shapes: flowers, normals: flowers.map(() => [0, -1, 0]), origins: flowers.map(() => [0, 0, 0]), }); mirrored.reverse().forEach(m => { flowers.push(m); shapesToDelete.push(m); }) const loftOptions = new Bit.Inputs.OCCT.LoftAdvancedDto<Bit.Inputs.OCCT.TopoDSWirePointer>(flowers); loftOptions.straight = true; loftOptions.closed = true; loftOptions.makeSolid = true; previousStarShape = await bitbybit.occt.operations.loftAdvanced(loftOptions) const options = new Bit.Inputs.Draw.DrawOcctShapeOptions(); options.precision = 0.01; options.drawEdges = true; options.edgeWidth = 0.5; options.edgeColour = "#f0b89d"; const mat = new BABYLON.PBRMetallicRoughnessMaterial("mat"); mat.roughness = 0.1; mat.baseColor = new BABYLON.Color3(1, 1, 1); mat.zOffset = 1; mat.metallic = 0.9; options.faceMaterial = mat; previousStarMesh = await bitbybit.draw.drawAnyAsync({ entity: previousStarShape, options }); await bitbybit.occt.deleteShapes({ shapes: shapesToDelete }) // previousStarMesh.receiveShadows = true; const meshes = previousStarMesh.getChildMeshes(); const coord = 60; const step = 10; for (let x = -coord; x < coord; x += step) { for (let z = -coord; z < coord; z += step) { const randomAngle = Math.random(); meshes.forEach((m: BABYLON.Mesh, index) => { const inst = m.createInstance(`inst${index}-${x}-${z}`); inst.rotateAround(new BABYLON.Vector3(0, 0, 0), new BABYLON.Vector3(0, 1, 0), Math.PI * 2 * randomAngle); inst.scaling = new BABYLON.Vector3(1 + randomAngle / 4, 1 + randomAngle, 1 + randomAngle / 4) inst.position = new BABYLON.Vector3(x, 0, z); previousMeshInstances.push(inst); }); } } meshes.forEach(m => { m.disableEdgesRendering(); m.isVisible = false; }); previousStarMesh.isVisible = false; computing = false; } async function disposePrevious() { if (previousStarMesh) { previousStarMesh.dispose(); } if (previousStarShape) { await bitbybit.occt.deleteShape({ shape: previousStarShape }); } if (previousMeshInstances.length) { previousMeshInstances.forEach(s => s.dispose()); previousMeshInstances = []; } } async function createGUI() { var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI"); var panel = new BABYLON.GUI.StackPanel(); panel.width = "800px"; panel.background = "#00000055"; panel.paddingLeftInPixels = 40; panel.paddingRightInPixels = 40; panel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT; panel.adaptHeightToChildren = true; advancedTexture.addControl(panel); var header1 = new BABYLON.GUI.TextBlock("GUI EXAMPLE"); header1.text = "GUI EXAMPLE"; header1.height = "80px"; header1.color = "#f0b89d"; header1.fontSize = "40px" panel.addControl(header1); const label1 = "Nr Rays:"; createSliderWithLabel(panel, label1, model.nrRays, 3, 10, 1, (slider: BABYLON.GUI.Slider, header: BABYLON.GUI.TextBlock) => { header.text = label1 + " " + slider.value; model.nrRays = slider.value; if (!computing) { createShape(model); } } ); const label2 = "Nr Sections:"; createSliderWithLabel(panel, label2, model.nrSections, 2, 20, 1, (slider: BABYLON.GUI.Slider, header: BABYLON.GUI.TextBlock) => { header.text = label2 + " " + slider.value; model.nrSections = slider.value; if (!computing) { createShape(model); } } ); const label3 = "Inner Radius:"; createSliderWithLabel(panel, label3, model.innerRadius, 0.4, 3, 0.1, (slider: BABYLON.GUI.Slider, header: BABYLON.GUI.TextBlock) => { if (slider.value > model.outerRadius) { model.innerRadius = model.outerRadius - 0.1; slider.value = model.innerRadius; } else { model.innerRadius = slider.value; } header.text = label3 + " " + slider.value.toFixed(2); if (!computing) { createShape(model); } } ); const label4 = "Outer Radius:"; createSliderWithLabel(panel, label4, model.outerRadius, 0.4, 3, 0.1, (slider: BABYLON.GUI.Slider, header: BABYLON.GUI.TextBlock) => { if (slider.value < model.innerRadius) { model.outerRadius = model.innerRadius + 0.1; slider.value = model.outerRadius; } else { model.outerRadius = slider.value; } header.text = label4 + " " + slider.value.toFixed(2); if (!computing) { createShape(model); } } ); var header2 = new BABYLON.GUI.TextBlock("bitbybit.dev"); header2.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_BOTTOM; header2.text = "bitbybit.dev"; header2.height = "120px"; header2.color = "#f0b89d"; header2.fontSize = "40px"; panel.addControl(header2); } function createSliderWithLabel( panel: BABYLON.GUI.StackPanel, name: string, defaultVal: number, min: number, max: number, step: number, funcToRun: (slider: BABYLON.GUI.Slider, label: BABYLON.GUI.TextBlock) => void ) { var header = new BABYLON.GUI.TextBlock(name); header.paddingTopInPixels = 10; header.text = name + " " + defaultVal; header.height = "60px"; header.color = "white"; header.fontSize = "30px" panel.addControl(header); var slider = new BABYLON.GUI.Slider(name); slider.thumbColor = "#f0b89d"; slider.isThumbCircle = true; slider.borderColor = "#f0b89d" slider.minimum = min; slider.maximum = max; slider.step = step; slider.value = defaultVal; slider.paddingLeftInPixels = 10; slider.paddingRightInPixels = 10; slider.isVertical = false; slider.alpha = 1; slider.height = "25px"; slider.onPointerUpObservable.add(() => { funcToRun(slider, header); }); panel.addControl(slider); }