|
| 1 | +import { BitByBitBase, Inputs } from "@bitbybit-dev/babylonjs"; |
| 2 | +import { OCCTW } from "@bitbybit-dev/core"; |
| 3 | +export class LaptopLogic { |
| 4 | + |
| 5 | + private bitbybit: BitByBitBase; |
| 6 | + private occt: OCCTW; |
| 7 | + |
| 8 | + private laptops: Laptop[] = [ |
| 9 | + { |
| 10 | + width: 30.41, |
| 11 | + length: 1.5, |
| 12 | + height: 21.24, |
| 13 | + } |
| 14 | + ]; |
| 15 | + |
| 16 | + private laptopStand; |
| 17 | + private laptopStandMesh; |
| 18 | + private laptopsFilletsMesh; |
| 19 | + |
| 20 | + private controlPoints = [ |
| 21 | + [-12.5, 0, 0], |
| 22 | + [-8, 13, 0], |
| 23 | + [-4, 11, 0], |
| 24 | + [-2, 6, 0], |
| 25 | + [2, 6, 0], |
| 26 | + [4, 14, 0], |
| 27 | + [8, 17, 0], |
| 28 | + [12.5, 0, 0] |
| 29 | + ] as Inputs.Base.Point3[]; |
| 30 | + |
| 31 | + private whiteColor = "#ffffff"; |
| 32 | + private holderColor = "#333333"; |
| 33 | + private laptopLiftedHeight = 3; |
| 34 | + private distanceBetweenLaptops = 1.7; |
| 35 | + |
| 36 | + constructor(bitbybit: BitByBitBase) { |
| 37 | + this.bitbybit = bitbybit; |
| 38 | + this.occt = bitbybit.occt; |
| 39 | + } |
| 40 | + async renderLaptops(laptops) { |
| 41 | + |
| 42 | + laptops.forEach(laptop => { |
| 43 | + laptop.center = [0, laptop.height / 2 + this.laptopLiftedHeight, 0] as Inputs.Base.Point3; |
| 44 | + }); |
| 45 | + |
| 46 | + const laptopFillets = []; |
| 47 | + let totalDistance = 0; |
| 48 | + let previousLaptopLength = 0; |
| 49 | + |
| 50 | + laptops.forEach(async (laptop) => { |
| 51 | + totalDistance += this.distanceBetweenLaptops + laptop.length / 2 + previousLaptopLength / 2; |
| 52 | + previousLaptopLength = laptop.length; |
| 53 | + laptop.center[2] = totalDistance; |
| 54 | + const laptopBaseModel = await this.occt.shapes.solid.createBox({ |
| 55 | + width: laptop.width, |
| 56 | + length: laptop.length, |
| 57 | + height: laptop.height, |
| 58 | + center: laptop.center |
| 59 | + }); |
| 60 | + const laptopFillet = await this.occt.fillets.filletEdges({ shape: laptopBaseModel, radius: 0.2 }); |
| 61 | + laptopFillets.push(laptopFillet); |
| 62 | + |
| 63 | + const laptopVisModel = await this.occt.shapes.solid.createBox({ |
| 64 | + width: laptop.width, |
| 65 | + length: laptop.length - 0.01, |
| 66 | + height: laptop.height, |
| 67 | + center: laptop.center |
| 68 | + }); |
| 69 | + const laptopVisFillet = await this.occt.fillets.filletEdges({ shape: laptopVisModel, radius: 0.2 }); |
| 70 | + laptopFillets.push(laptopFillet); |
| 71 | + |
| 72 | + const di = new Inputs.OCCT.DrawShapeDto(); |
| 73 | + di.faceOpacity = 0.2; |
| 74 | + di.edgeWidth = 5; |
| 75 | + di.edgeOpacity = 0.6; |
| 76 | + di.edgeColour = this.whiteColor; |
| 77 | + di.faceColour = this.whiteColor; |
| 78 | + di.drawTwoSided = false; |
| 79 | + const laptopFilletMesh = await this.bitbybit.draw.drawAnyAsync({entity: laptopVisFillet, options: di}); |
| 80 | + this.laptopsFilletsMesh.push(laptopFilletMesh); |
| 81 | + }); |
| 82 | + |
| 83 | + const polygonWire = await this.occt.shapes.wire.createPolygonWire({ |
| 84 | + points: this.controlPoints |
| 85 | + }); |
| 86 | + const extrusion = await this.occt.operations.extrude({ |
| 87 | + shape: polygonWire, direction: [0, 0, totalDistance += this.distanceBetweenLaptops + previousLaptopLength / 2] |
| 88 | + }); |
| 89 | + const laptopStandFillet = await this.occt.fillets.filletEdges({ shape: extrusion, radius: 1 }); |
| 90 | + const laptopStandThick = await this.occt.operations.makeThickSolidSimple({ shape: laptopStandFillet, offset: -0.5 }); |
| 91 | + |
| 92 | + this.laptopStand = await this.occt.booleans.difference({ shape: laptopStandThick, shapes: laptopFillets, keepEdges: false }); |
| 93 | + const li = new Inputs.OCCT.DrawShapeDto(this.laptopStand); |
| 94 | + li.faceOpacity = 1; |
| 95 | + li.faceColour = this.holderColor; |
| 96 | + li.edgeColour = this.whiteColor; |
| 97 | + li.edgeWidth = 5; |
| 98 | + li.drawTwoSided = false; |
| 99 | + this.laptopStandMesh = await this.bitbybit.draw.drawAnyAsync({ entity: this.laptopStand, options: li }); |
| 100 | + } |
| 101 | + |
| 102 | + async do() { |
| 103 | + this.bitbybit.babylon.scene.backgroundColour({ colour: "#bbbbbb" }); |
| 104 | + |
| 105 | + const cameraConf = new Inputs.BabylonScene.CameraConfigurationDto(); |
| 106 | + cameraConf.lookAt = [0, 11, 0]; |
| 107 | + cameraConf.position = [30, 10, 35]; |
| 108 | + cameraConf.wheelPrecision = 0.3; |
| 109 | + cameraConf.panningSensibility = 1000; |
| 110 | + this.bitbybit.babylon.scene.adjustActiveArcRotateCamera(cameraConf); |
| 111 | + |
| 112 | + const pointLightConf = new Inputs.BabylonScene.PointLightDto(); |
| 113 | + pointLightConf.position = [-15, 20, -5]; |
| 114 | + pointLightConf.intensity = 8000; |
| 115 | + pointLightConf.diffuse = "#3333ff"; |
| 116 | + pointLightConf.radius = 0; |
| 117 | + pointLightConf.shadowGeneratorMapSize = 2056; |
| 118 | + const light = this.bitbybit.babylon.scene.drawPointLight(pointLightConf); |
| 119 | + light.shadowMinZ = 0.01; |
| 120 | + this.laptopsFilletsMesh = []; |
| 121 | + |
| 122 | + |
| 123 | + await this.renderLaptops(this.laptops); |
| 124 | + |
| 125 | + const ground = await this.bitbybit.occt.shapes.face.createCircleFace({ center: [0, 0, 0], direction: [0, 1, 0], radius: 75, }); |
| 126 | + const groundOptions = new Inputs.Draw.DrawOcctShapeOptions(); |
| 127 | + groundOptions.faceColour = this.whiteColor; |
| 128 | + groundOptions.drawEdges = false; |
| 129 | + await this.bitbybit.draw.drawAnyAsync({ entity: ground, options: groundOptions }); |
| 130 | + } |
| 131 | + |
| 132 | + downloadStep() { |
| 133 | + this.occt.io.saveShapeSTEP({ shape: this.laptopStand, fileName: "laptop-stand.step", adjustYtoZ: false }); |
| 134 | + } |
| 135 | + |
| 136 | + downloadStl() { |
| 137 | + this.occt.io.saveShapeStl({ shape: this.laptopStand, fileName: "laptop-stand", precision: 0.001, adjustYtoZ: false }); |
| 138 | + } |
| 139 | + |
| 140 | + async render(laptops: Laptop[]) { |
| 141 | + if (this.laptopStandMesh) { |
| 142 | + const lap = await this.laptopStandMesh; |
| 143 | + this.bitbybit.babylon.mesh.dispose({ babylonMesh: lap }); |
| 144 | + } |
| 145 | + if (this.laptopsFilletsMesh && this.laptopsFilletsMesh.length > 0) { |
| 146 | + const res = await Promise.all(this.laptopsFilletsMesh); |
| 147 | + res.forEach(r => { |
| 148 | + this.bitbybit.babylon.mesh.dispose({ babylonMesh: r }); |
| 149 | + }); |
| 150 | + } |
| 151 | + this.renderLaptops(laptops); |
| 152 | + } |
| 153 | +} |
| 154 | + |
| 155 | +class Laptop { |
| 156 | + width: number; |
| 157 | + length: number; |
| 158 | + height: number; |
| 159 | + center?: Inputs.Base.Point3; |
| 160 | +} |
0 commit comments