Skip to content

Commit 638853a

Browse files
re-implemented point drawing with instanced spheres
1 parent 409b6b9 commit 638853a

File tree

3 files changed

+72
-46
lines changed

3 files changed

+72
-46
lines changed

lib/api/bitbybit/point.ts

Lines changed: 68 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
import { Color3, Mesh, StandardMaterial, VertexBuffer, VertexData } from "@babylonjs/core";
2+
import * as BABYLON from "@babylonjs/core";
33
import { Context } from "../context";
44
import { GeometryHelper } from "../geometry-helper";
55
import * as Inputs from "../inputs/inputs";
@@ -25,21 +25,21 @@ export class Point {
2525
* @drawable false
2626
* @ignore true
2727
*/
28-
drawPoint(inputs: Inputs.Point.DrawPointDto): Mesh {
28+
drawPoint(inputs: Inputs.Point.DrawPointDto): BABYLON.Mesh {
2929
const vectorPoints = [inputs.point];
3030

31-
let colours;
31+
let colorsHex: string[] = [];
3232
if (Array.isArray(inputs.colours)) {
33-
colours = inputs.colours.map(colour => Color3.FromHexString(colour));
33+
colorsHex = inputs.colours;
3434
} else {
35-
colours = [Color3.FromHexString(inputs.colours)];
35+
colorsHex = [inputs.colours];
3636
}
37-
const { positions, colors } = this.setUpPositionsAndColours(vectorPoints, colours);
37+
// const { positions, colors } = this.setUpPositionsAndColours(vectorPoints, colours);
3838
if (inputs.pointMesh && inputs.updatable) {
39-
this.updatePoints(inputs.pointMesh, inputs.opacity, inputs.size, positions, colors);
39+
this.updatePointsInstances(inputs.pointMesh, vectorPoints);
4040
} else {
41-
inputs.pointMesh = this.createNewMesh(
42-
`poinsMesh${Math.random()}`, positions, colors, inputs.opacity, inputs.size, inputs.updatable
41+
inputs.pointMesh = this.createPointSpheresMesh(
42+
`poinsMesh${Math.random()}`, vectorPoints, colorsHex, inputs.opacity, inputs.size, inputs.updatable
4343
);
4444
}
4545
return inputs.pointMesh;
@@ -54,28 +54,29 @@ export class Point {
5454
* @drawable false
5555
* @ignore true
5656
*/
57-
drawPoints(inputs: Inputs.Point.DrawPointsDto): Mesh {
57+
drawPoints(inputs: Inputs.Point.DrawPointsDto): BABYLON.Mesh {
5858
const vectorPoints = inputs.points;
59-
60-
let colours;
59+
let coloursHex: string[] = [];
6160
if (Array.isArray(inputs.colours)) {
62-
colours = inputs.colours.map(colour => Color3.FromHexString(colour));
61+
coloursHex = inputs.colours;
62+
if (coloursHex.length === 1) {
63+
coloursHex = inputs.points.map(() => coloursHex[0]);
64+
}
6365
} else {
64-
colours = [Color3.FromHexString(inputs.colours)];
66+
coloursHex = inputs.points.map(() => inputs.colours as string);
6567
}
66-
const { positions, colors } = this.setUpPositionsAndColours(vectorPoints, colours);
6768
if (inputs.pointsMesh && inputs.updatable) {
68-
if (inputs.pointsMesh.getTotalVertices() === vectorPoints.length) {
69-
this.updatePoints(inputs.pointsMesh, inputs.opacity, inputs.size, positions, colors);
69+
if (inputs.pointsMesh.getChildMeshes().length === vectorPoints.length) {
70+
this.updatePointsInstances(inputs.pointsMesh, vectorPoints);
7071
} else {
7172
inputs.pointsMesh.dispose();
72-
inputs.pointsMesh = this.createNewMesh(
73-
`pointsMesh${Math.random()}`, positions, colors, inputs.opacity, inputs.size, inputs.updatable
73+
inputs.pointsMesh = this.createPointSpheresMesh(
74+
`pointsMesh${Math.random()}`, vectorPoints, coloursHex, inputs.opacity, inputs.size, inputs.updatable
7475
);
7576
}
7677
} else {
77-
inputs.pointsMesh = this.createNewMesh(
78-
`pointsMesh${Math.random()}`, positions, colors, inputs.opacity, inputs.size, inputs.updatable
78+
inputs.pointsMesh = this.createPointSpheresMesh(
79+
`pointsMesh${Math.random()}`, vectorPoints, coloursHex, inputs.opacity, inputs.size, inputs.updatable
7980
);
8081
}
8182
return inputs.pointsMesh;
@@ -90,7 +91,7 @@ export class Point {
9091
* @drawable false
9192
* @ignore true
9293
*/
93-
drawPointsAsync(inputs: Inputs.Point.DrawPointsDto): Promise<Mesh> {
94+
drawPointsAsync(inputs: Inputs.Point.DrawPointsDto): Promise<BABYLON.Mesh> {
9495
return Promise.resolve(this.drawPoints(inputs));
9596
}
9697

@@ -351,38 +352,63 @@ export class Point {
351352
return { index: closestPointIndex + 1, distance, point };
352353
}
353354

354-
private createNewMesh(
355-
meshName: string, positions: number[], colors: number[], opacity: number, size: number, updatable: boolean): Mesh {
355+
private createPointSpheresMesh(
356+
meshName: string, positions: Base.Point3[], colors: string[], opacity: number, size: number, updatable: boolean): BABYLON.Mesh {
356357

357-
const vertexData = new VertexData();
358+
const positionsModel = positions.map((pos, index) => {
359+
return {
360+
position: pos,
361+
color: colors[index],
362+
index
363+
};
364+
});
358365

359-
vertexData.positions = positions;
360-
vertexData.colors = colors;
366+
const colorSet = Array.from(new Set(colors));
367+
const materialSet = colorSet.map((colour, index) => {
361368

362-
const pointsMesh = new Mesh(meshName, this.context.scene);
363-
vertexData.applyToMesh(pointsMesh, updatable);
369+
const mat = new BABYLON.StandardMaterial(`mat${Math.random()}`, this.context.scene);
364370

365-
const mat = new StandardMaterial(`mat${Math.random()}`, this.context.scene);
371+
mat.disableLighting = true;
372+
mat.emissiveColor = BABYLON.Color3.FromHexString(colour);
373+
mat.alpha = opacity;
366374

367-
mat.emissiveColor = new Color3(1, 1, 1);
368-
mat.disableLighting = true;
369-
mat.pointsCloud = true;
370-
mat.alpha = opacity;
371-
mat.pointSize = size;
375+
const positions = positionsModel.filter(s => s.color === colour);
372376

373-
pointsMesh.material = mat;
377+
return { hex: colorSet, material: mat, positions };
378+
});
379+
380+
const pointsMesh = new BABYLON.Mesh(meshName, this.context.scene);
381+
382+
materialSet.forEach(ms => {
383+
const sphereOriginal = BABYLON.MeshBuilder.CreateSphere(`sphere${Math.random()}`, { diameter: size, segments: 6, updatable }, this.context.scene);
384+
sphereOriginal.material = ms.material;
385+
sphereOriginal.isVisible = false;
386+
ms.positions.forEach((pos, index) => {
387+
const instance = sphereOriginal.createInstance(`sphere-${index}-${Math.random()}`);
388+
instance.position = new BABYLON.Vector3(pos.position[0], pos.position[1], pos.position[2]);
389+
instance.metadata = { index: pos.index };
390+
instance.parent = pointsMesh;
391+
instance.isVisible = true;
392+
});
393+
});
374394

375395
return pointsMesh;
376396
}
377397

378-
private updatePoints(mesh: Mesh, opacity: number, size: number, positions: any[], colors: any[]): void {
379-
mesh.updateVerticesData(VertexBuffer.PositionKind, positions);
380-
mesh.updateVerticesData(VertexBuffer.ColorKind, colors);
381-
mesh.material.alpha = opacity;
382-
mesh.material.pointSize = size;
398+
private updatePointsInstances(mesh: BABYLON.Mesh, positions: any[]): void {
399+
400+
const children = mesh.getChildMeshes();
401+
const po = {};
402+
positions.forEach((pos, index) => {
403+
po[index] = new BABYLON.Vector3(pos[0], pos[1], pos[2]);
404+
});
405+
406+
children.forEach((child: BABYLON.InstancedMesh) => {
407+
child.position = po[child.metadata.index];
408+
});
383409
}
384410

385-
private setUpPositionsAndColours(vectorPoints: number[][], colours: Color3[]): { positions, colors } {
411+
private setUpPositionsAndColours(vectorPoints: number[][], colours: BABYLON.Color3[]): { positions, colors } {
386412
const positions = [];
387413
const colors = [];
388414

lib/api/inputs/draw-inputs.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,12 @@ export namespace Draw {
110110
colours: string | string[] = "#ff0000";
111111
/**
112112
* Size affect how big the drawn points are and how wide lines are.
113-
* @default 3
113+
* @default 0.1
114114
* @minimum 0
115115
* @maximum Infinity
116116
* @step 0.1
117117
*/
118-
size = 3;
118+
size = 0.1;
119119
/**
120120
* Opacity of the point 0 to 1
121121
* @default 1

lib/api/inputs/point-inputs.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,12 @@ export namespace Point {
128128
opacity = 1;
129129
/**
130130
* Size of the points
131-
* @default 3
131+
* @default 0.1
132132
* @minimum 0
133133
* @maximum Infinity
134134
* @step 0.1
135135
*/
136-
size = 3;
136+
size = 0.1;
137137
/**
138138
* Hex colour string or collection of strings
139139
* @default #444444

0 commit comments

Comments
 (0)