fix(cloth-icm): reuse contour mesh so contours draw
Contour lines were disposed and rebuilt when their shape changed, so the new shader never finished compiling before removal. Keep one mesh and set its geometry each frame. Hide it when there are no contours. Draw contours green and culled BVH boxes cyan for contrast.
This commit is contained in:
1 parent
b1607a4b00
commit
ba82df7694
1 file changed
+14
-21
@@ -1,5 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
ArcRotateCamera, Color3, Color4, LinesMesh, Mesh, MeshBuilder, Scene, ShaderMaterial, StandardMaterial, Vector3, VertexBuffer, VertexData
|
ArcRotateCamera, Color3, Color4, CreateLineSystemVertexData, LinesMesh, Mesh, MeshBuilder, Scene, ShaderMaterial, StandardMaterial, Vector3, VertexBuffer, VertexData
|
||||||
} from '@babylonjs/core';
|
} from '@babylonjs/core';
|
||||||
import {CLOTH_FRAGMENT_SHADER_GLSL, CLOTH_VERTEX_SHADER_GLSL} from '../cloth/cloth-glsl.shader';
|
import {CLOTH_FRAGMENT_SHADER_GLSL, CLOTH_VERTEX_SHADER_GLSL} from '../cloth/cloth-glsl.shader';
|
||||||
import {ClothIcmScene} from './cloth-icm-scenes';
|
import {ClothIcmScene} from './cloth-icm-scenes';
|
||||||
@@ -10,8 +10,8 @@ import {DOP_SIZE} from './collision/dop18';
|
|||||||
import {Contour} from './collision/intersection-contours';
|
import {Contour} from './collision/intersection-contours';
|
||||||
import {IntersectionSet} from './collision/intersection-set';
|
import {IntersectionSet} from './collision/intersection-set';
|
||||||
|
|
||||||
const CONTOUR_COLOR = new Color3(1, 0.1, 0.1);
|
const CONTOUR_COLOR = new Color3(0.1, 1, 0.2);
|
||||||
const CULLED_COLOR = new Color4(0.2, 0.9, 0.3, 1);
|
const CULLED_COLOR = new Color4(0.2, 0.8, 1, 1);
|
||||||
const TESTED_COLOR = new Color4(0.6, 0.6, 0.6, 1);
|
const TESTED_COLOR = new Color4(0.6, 0.6, 0.6, 1);
|
||||||
const OBSTACLE_COLOR = new Color3(0.35, 0.55, 0.9);
|
const OBSTACLE_COLOR = new Color3(0.35, 0.55, 0.9);
|
||||||
const GROUND_SIZE = 8;
|
const GROUND_SIZE = 8;
|
||||||
@@ -35,7 +35,6 @@ export class ClothIcmRenderer {
|
|||||||
private bvhLines: LinesMesh | null = null;
|
private bvhLines: LinesMesh | null = null;
|
||||||
private vertexBuffer = new Float32Array(0);
|
private vertexBuffer = new Float32Array(0);
|
||||||
private culledRegion = new Uint8Array(0);
|
private culledRegion = new Uint8Array(0);
|
||||||
private contourShape: number[] = [];
|
|
||||||
private bvhBoxes: BvhBox[] = [];
|
private bvhBoxes: BvhBox[] = [];
|
||||||
private bvhPaths: Vector3[][] = [];
|
private bvhPaths: Vector3[][] = [];
|
||||||
private bvhPathColors: Color4[][] = [];
|
private bvhPathColors: Color4[][] = [];
|
||||||
@@ -67,7 +66,6 @@ export class ClothIcmRenderer {
|
|||||||
this.obstacles.forEach(mesh => mesh.dispose());
|
this.obstacles.forEach(mesh => mesh.dispose());
|
||||||
this.obstacleMaterial?.dispose();
|
this.obstacleMaterial?.dispose();
|
||||||
this.contourLines = null;
|
this.contourLines = null;
|
||||||
this.contourShape = [];
|
|
||||||
this.bvhLines = null;
|
this.bvhLines = null;
|
||||||
this.bvhBoxes = [];
|
this.bvhBoxes = [];
|
||||||
this.bvhPaths = [];
|
this.bvhPaths = [];
|
||||||
@@ -153,31 +151,26 @@ export class ClothIcmRenderer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The hit points come from the detection, which runs on the predicted positions before the solver moves the cloth,
|
* The hit points come from the detection, which runs on the predicted positions before the solver moves the cloth,
|
||||||
* so the lines can be a little off the drawn cloth (up to about 0.05 m). Babylon can only update a line system in
|
* so the lines can be a little off the drawn cloth (up to about 0.05 m).
|
||||||
* place while every line keeps its point count; otherwise the mesh is rebuilt.
|
* The mesh is created once and gets new geometry every frame. Disposing and creating it again would drop its shader
|
||||||
|
* (reference counted) and recompile it; the line shader compiles asynchronously, so a mesh whose point layout changes
|
||||||
|
* every frame (the drop scene) was never ready to draw.
|
||||||
*/
|
*/
|
||||||
private updateContourLines(scene: Scene, set: IntersectionSet, contours: Contour[]): void {
|
private updateContourLines(scene: Scene, set: IntersectionSet, contours: Contour[]): void {
|
||||||
if (contours.length === 0) {
|
if (contours.length === 0) {
|
||||||
this.contourLines?.dispose();
|
this.contourLines?.setEnabled(false);
|
||||||
this.contourLines = null;
|
|
||||||
this.contourShape = [];
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const lines = contours.map(contour => this.contourPath(set, contour));
|
const vertexData = CreateLineSystemVertexData({lines: contours.map(contour => this.contourPath(set, contour))});
|
||||||
const shape = lines.map(line => line.length);
|
if (!this.contourLines) {
|
||||||
const existing = this.contourLines;
|
const mesh = new LinesMesh('clothIcmContours', scene);
|
||||||
const sameShape = shape.length === this.contourShape.length && shape.every((length, index) => length === this.contourShape[index]);
|
|
||||||
if (existing && sameShape) {
|
|
||||||
MeshBuilder.CreateLineSystem('clothIcmContours', {lines, instance: existing});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.contourLines?.dispose();
|
|
||||||
const mesh = MeshBuilder.CreateLineSystem('clothIcmContours', {lines, updatable: true}, scene);
|
|
||||||
mesh.color = CONTOUR_COLOR;
|
mesh.color = CONTOUR_COLOR;
|
||||||
mesh.renderingGroupId = OVERLAY_RENDERING_GROUP;
|
mesh.renderingGroupId = OVERLAY_RENDERING_GROUP;
|
||||||
mesh.alwaysSelectAsActiveMesh = true;
|
mesh.alwaysSelectAsActiveMesh = true;
|
||||||
this.contourLines = mesh;
|
this.contourLines = mesh;
|
||||||
this.contourShape = shape;
|
}
|
||||||
|
vertexData.applyToMesh(this.contourLines, true);
|
||||||
|
this.contourLines.setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private contourPath(set: IntersectionSet, contour: Contour): Vector3[] {
|
private contourPath(set: IntersectionSet, contour: Contour): Vector3[] {
|
||||||
|
|||||||
Reference in new issue
Block a user