Skip to content

Commit 9a6c45f

Browse files
migrated angular laptop holder example to new angular, removed simple threejs example as it was based on old angular and did not provide value anymore.
1 parent bd4888e commit 9a6c45f

File tree

4 files changed

+475
-0
lines changed

4 files changed

+475
-0
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import { Component } from "@angular/core";
2+
import { BitByBitBase } from "@bitbybit-dev/babylonjs";
3+
import { OccStateEnum } from "@bitbybit-dev/occt-worker";
4+
import { Scene, Engine, Color4, HemisphericLight, Vector3, ArcRotateCamera, Light } from "@babylonjs/core";
5+
import { LaptopLogic } from "./laptop";
6+
class Laptop {
7+
id: string;
8+
width: number;
9+
height: number;
10+
length: number;
11+
}
12+
13+
@Component({
14+
selector: "app-root",
15+
templateUrl: "./app.component.html",
16+
styleUrls: ["./app.component.css"],
17+
})
18+
export class AppComponent {
19+
20+
bitbybit = new BitByBitBase();
21+
22+
title = "trialwebsite";
23+
showSpinner = true;
24+
bitbybitInitialised = false;
25+
26+
prevLaptops: Laptop[];
27+
laptops: Laptop[] = [
28+
{
29+
id: Math.random().toString(),
30+
width: 30.41,
31+
length: 1.5,
32+
height: 21.24,
33+
}
34+
];
35+
36+
scene: Scene;
37+
engine: Engine;
38+
timePassedFromPreviousIteration = 0;
39+
40+
private laptopService: LaptopLogic;
41+
42+
renderLoopFunction = () => {
43+
this.scene.render();
44+
};
45+
46+
ngOnInit() {
47+
const canvas = document.getElementById("renderCanvas") as HTMLCanvasElement;
48+
49+
this.engine = new Engine(canvas);
50+
this.scene = new Scene(this.engine);
51+
this.engine.setHardwareScalingLevel(0.5);
52+
this.scene.clearColor = new Color4(26 / 255, 28 / 255, 31 / 255, 1);
53+
const camera = new ArcRotateCamera("Camera", 0, 10, 10, new Vector3(0, 0, 0), this.scene);
54+
camera.attachControl(canvas, true);
55+
56+
const light = new HemisphericLight("HemiLight", new Vector3(0, 1, 0), this.scene);
57+
light.intensityMode = Light.INTENSITYMODE_ILLUMINANCE;
58+
light.intensity = 1;
59+
this.scene.metadata = { shadowGenerators: [] };
60+
61+
const occt = new Worker(new URL("./occ.worker", import.meta.url), { name: "OCC", type: "module" });
62+
const jscad = new Worker(new URL("./jscad.worker", import.meta.url), { name: "JSCAD", type: "module" });
63+
64+
this.bitbybit.init(this.scene, occt, jscad);
65+
66+
this.bitbybit.occtWorkerManager.occWorkerState$.subscribe(s => {
67+
if (s.state === OccStateEnum.initialised) {
68+
this.showSpinner = false;
69+
this.bitbybitInitialised = true;
70+
this.engine.resize();
71+
this.laptopService = new LaptopLogic(this.bitbybit);
72+
this.laptopService.do();
73+
} else if (s.state === OccStateEnum.computing) {
74+
this.showSpinner = true;
75+
} else if (s.state === OccStateEnum.loaded) {
76+
this.showSpinner = false;
77+
}
78+
});
79+
80+
this.engine.runRenderLoop(this.renderLoopFunction);
81+
82+
window.onresize = () => {
83+
if (this.engine) {
84+
this.engine.resize();
85+
}
86+
};
87+
}
88+
89+
async jscadDrawBox() {
90+
const cube = await this.bitbybit.occt.shapes.solid.createBox({ width: 2, length: 2, height: 2, center: [0, 0, 0] });
91+
await this.bitbybit.draw.drawAnyAsync({ entity: cube, options: undefined });
92+
}
93+
94+
render() {
95+
if (!this.prevLaptops || this.laptopsNotTheSame(this.prevLaptops, this.laptops)) {
96+
this.laptopService.render(this.laptops);
97+
this.prevLaptops = [...this.laptops.map(l => ({ ...l }))];
98+
}
99+
}
100+
101+
downloadStep() {
102+
this.laptopService.downloadStep();
103+
}
104+
105+
downloadStl() {
106+
this.laptopService.downloadStl();
107+
}
108+
109+
laptopWidthChanged(val, laptop: Laptop) {
110+
laptop.width = val;
111+
}
112+
113+
laptopLengthChanged(val, laptop: Laptop) {
114+
laptop.length = val;
115+
}
116+
117+
laptopHeightChanged(val, laptop: Laptop) {
118+
laptop.height = val;
119+
}
120+
121+
add() {
122+
this.laptops.push({
123+
id: Math.random().toString(),
124+
width: 30.41,
125+
length: 1.5,
126+
height: 21.24,
127+
});
128+
this.render();
129+
}
130+
131+
remove(laptop) {
132+
this.laptops = this.laptops.filter(s => s.id !== laptop.id);
133+
this.render();
134+
}
135+
136+
137+
private laptopsNotTheSame(prev: Laptop[], current: Laptop[]) {
138+
let result = false;
139+
if (prev.length !== current.length) {
140+
result = true;
141+
} else {
142+
this.prevLaptops.forEach((c) => {
143+
const laptop = this.laptops.find(s => s.id === c.id);
144+
if (!laptop) {
145+
result = true;
146+
} else if (laptop.width !== c.width || laptop.height !== c.height || laptop.length !== c.length) {
147+
result = true;
148+
}
149+
});
150+
}
151+
return result;
152+
}
153+
154+
155+
}
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
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

Comments
 (0)