Skip to content

Commit 88257e3

Browse files
committed
refactor: sole sampler for bouyancy
1 parent 0102ad8 commit 88257e3

File tree

6 files changed

+91
-64
lines changed

6 files changed

+91
-64
lines changed

graphics/gizmos.ts

+13-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { Transform } from './transform';
55
import { createGrid } from './mesh';
66
import { Camera } from './camera';
77
import { vs, fs } from './programs/mesh';
8-
import { FloatingBody } from '../ocean';
8+
import { FloatingBody, OceanFieldBuoyancy } from '../ocean';
99

1010
export class Gizmos {
1111
private readonly wiredSphereGeometry: Geometry;
@@ -137,6 +137,7 @@ export class Gizmos {
137137
drawFloatingBody(
138138
camera: Camera,
139139
body: FloatingBody,
140+
boyancy: OceanFieldBuoyancy,
140141
geometry?: Geometry
141142
): void {
142143
const position = vec3.create();
@@ -150,10 +151,18 @@ export class Gizmos {
150151
this.drawGeometry(camera, geometry, position, rotation);
151152
}
152153

153-
if (body.sampled) {
154+
if (boyancy['sampled']) {
154155
this.gpu.context.disable(WebGL2RenderingContext.DEPTH_TEST);
155-
body['world'].forEach((world, i) => {
156-
const sampled = body['sampled'][i];
156+
const startIndex = boyancy['bodies']
157+
.slice(0, boyancy['bodies'].indexOf(body))
158+
.reduce((acc, curr) => acc + curr.floaters.length, 0);
159+
const endIndex = startIndex + body.floaters.length;
160+
161+
const bodyWorld = boyancy['world'].slice(startIndex, endIndex);
162+
const bodySampled = boyancy['sampled'].slice(startIndex, endIndex);
163+
164+
bodyWorld.forEach((world, i) => {
165+
const sampled = bodySampled[i];
157166
const submerged = sampled?.[1] >= world?.[1];
158167
const color = !submerged
159168
? vec4.fromValues(0.5, 1.0, 0.5, 0.0)

ocean/buoyancy/floating-body.ts

+10-41
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,25 @@
1-
import { vec2, vec3 } from 'gl-matrix';
1+
import { vec3 } from 'gl-matrix';
22

3-
import { PointsSampler, Sample, SampleStatus } from '../sampler';
43
import { RigidBodyInterface } from './rigid-body.interface';
54

65
export class FloatingBody {
7-
public readonly world: vec3[] = [];
8-
public readonly points: vec2[] = [];
9-
public sampled: vec3[] | null = null;
10-
public sample: Sample<vec3[]> = null;
11-
126
constructor(
137
public readonly body: RigidBodyInterface,
148
public readonly floaters: vec3[],
159
public readonly submergeDepth: number,
1610
public readonly buoyancyStrength: number,
1711
public readonly waterDrag: number,
1812
public readonly waterAngularDrag: number,
19-
public readonly gravity: vec3,
20-
public readonly sampler: PointsSampler
21-
) {
22-
this.floaters.forEach(() => {
23-
this.world.push(vec3.create());
24-
this.points.push(vec2.create());
25-
});
26-
}
27-
28-
applyForces(): void {
29-
if (!this.sample) {
30-
this.floaters.forEach((floater, i) => {
31-
vec3.transformMat4(this.world[i], floater, this.body.transform);
32-
vec2.set(this.points[i], this.world[i][0], this.world[i][2]);
33-
});
34-
this.sample = this.sampler.sample(...this.points);
35-
} else {
36-
const status = this.sample.status();
37-
if (status !== SampleStatus.Pending) {
38-
if (status === SampleStatus.Complete) {
39-
this.sampled = this.sample.outcome();
40-
}
41-
this.sample.release();
42-
this.sample = null;
43-
}
44-
}
45-
46-
if (this.sampled) {
47-
this.applyForcesInternal(this.sampled, this.world);
48-
}
49-
}
13+
public readonly gravity: vec3
14+
) {}
5015

51-
private applyForcesInternal(sampled: vec3[], world: vec3[]) {
16+
applyForces(sampled: vec3[], world: vec3[], offset: number) {
5217
const center = vec3.create();
53-
for (let i = 0; i < this.floaters.length; i++) {
18+
for (
19+
let i = offset, j = 0, end = this.floaters.length + offset;
20+
i < end;
21+
i++, j++
22+
) {
5423
if (sampled[i][1] <= world[i][1]) {
5524
continue;
5625
}
@@ -65,7 +34,7 @@ export class FloatingBody {
6534
this.gravity,
6635
-this.body.mass * submerging * this.buoyancyStrength
6736
),
68-
this.floaters[i]
37+
this.floaters[j]
6938
);
7039
this.body.applyForce(
7140
vec3.scale(

ocean/buoyancy/ocean-field-buoyancy.ts

+65-13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import { vec3 } from 'gl-matrix';
1+
import { vec2, vec3 } from 'gl-matrix';
2+
import { SampleStatus } from '..';
23

34
import { OceanField } from '../ocean-field';
45
import { PointsSampler } from '../sampler';
6+
import { Sample } from '../sampler/sample';
57
import { FloatingBody } from './floating-body';
68
import { RigidBodyInterface } from './rigid-body.interface';
79

@@ -22,7 +24,13 @@ export const floatingBodyDefaultOptions: FloatingBodyOptions = {
2224
};
2325

2426
export class OceanFieldBuoyancy {
25-
public readonly bodies = new Set<FloatingBody>();
27+
private readonly bodies: FloatingBody[] = [];
28+
private readonly world: vec3[] = [];
29+
private readonly points: vec2[] = [];
30+
private sampled: vec3[] | null = null;
31+
private sample: Sample<vec3[]> = null;
32+
private sampler: PointsSampler;
33+
private dirty = true;
2634

2735
constructor(public readonly oceanField: OceanField) {}
2836

@@ -33,33 +41,77 @@ export class OceanFieldBuoyancy {
3341
): FloatingBody {
3442
options = { ...floatingBodyDefaultOptions, ...options };
3543

36-
const sampler = new PointsSampler(this.oceanField, floaters.length);
3744
const floatingBody = new FloatingBody(
3845
body,
3946
floaters,
4047
options.submergeDepth,
4148
options.buoyancyStrengh,
4249
options.waterDrag,
4350
options.waterAngularDrag,
44-
options.gravity,
45-
sampler
51+
options.gravity
4652
);
47-
this.bodies.add(floatingBody);
53+
this.bodies.push(floatingBody);
54+
55+
floaters.forEach(() => {
56+
this.world.push(vec3.create());
57+
this.points.push(vec2.create());
58+
});
59+
60+
this.dirty = true;
61+
this.sample = null;
4862

4963
return floatingBody;
5064
}
5165

5266
update() {
53-
for (const body of this.bodies) {
54-
body.applyForces();
67+
this.sampleOceanField();
68+
if (this.sampled) {
69+
let offset = 0;
70+
for (const body of this.bodies) {
71+
body.applyForces(this.sampled, this.world, offset);
72+
offset += body.floaters.length;
73+
}
5574
}
5675
}
5776

58-
destroy(body: FloatingBody) {
59-
body.sampler.dispose();
60-
if (body.sample) {
61-
body.sample.release();
77+
destroyFloatingBody(body: FloatingBody) {
78+
this.bodies.splice(this.bodies.indexOf(body), 1);
79+
body.floaters.forEach(() => {
80+
this.world.pop();
81+
this.points.pop();
82+
});
83+
84+
this.dirty = true;
85+
this.sample = null;
86+
}
87+
88+
private sampleOceanField() {
89+
if (!this.sample) {
90+
let i = 0;
91+
for (const body of this.bodies) {
92+
for (const floater of body.floaters) {
93+
vec3.transformMat4(this.world[i], floater, body.body.transform);
94+
vec2.set(this.points[i], this.world[i][0], this.world[i][2]);
95+
i++;
96+
}
97+
}
98+
99+
if (this.dirty) {
100+
this.sampler?.dispose();
101+
this.sampler = new PointsSampler(this.oceanField, i);
102+
this.dirty = false;
103+
}
104+
105+
this.sample = this.sampler.sample(...this.points);
106+
} else {
107+
const status = this.sample.status();
108+
if (status !== SampleStatus.Pending) {
109+
if (status === SampleStatus.Complete) {
110+
this.sampled = this.sample.outcome();
111+
}
112+
this.sample.release();
113+
this.sample = null;
114+
}
62115
}
63-
this.bodies.delete(body);
64116
}
65117
}

physics/interfaces/intergrator.interface.ts

-3
This file was deleted.

physics/interfaces/intergrator.ts

-1
This file was deleted.

viewport.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,16 @@ export class Viewport {
8888
this.renderFloatings();
8989
}
9090

91-
public renderGrid() {
91+
private renderGrid() {
9292
this.gizmos.drawGrid(this.cameraController.camera);
9393
}
9494

95-
public renderFloatings() {
95+
private renderFloatings() {
9696
this.floaters.forEach(([floater, geometry]) =>
9797
this.gizmos.drawFloatingBody(
9898
this.cameraController.camera,
9999
floater,
100+
this.buoyancy,
100101
geometry
101102
)
102103
);

0 commit comments

Comments
 (0)