Update water contact patch collection and handling in rendering and runtime modules
This commit is contained in:
@@ -100,7 +100,7 @@ function createInverseVolumeRotation(rotationDegrees: Vec3) {
|
|||||||
.invert();
|
.invert();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function collectWaterContactPatches(volume: OrientedWaterVolume, contactBounds: WaterContactBounds[]): WaterContactPatch[] {
|
export function collectWaterContactPatches(volume: OrientedWaterVolume, contactBounds: WaterContactSource[]): WaterContactPatch[] {
|
||||||
const inverseRotation = createInverseVolumeRotation(volume.rotationDegrees);
|
const inverseRotation = createInverseVolumeRotation(volume.rotationDegrees);
|
||||||
const halfX = Math.max(volume.size.x * 0.5, WATER_CONTACT_EPSILON);
|
const halfX = Math.max(volume.size.x * 0.5, WATER_CONTACT_EPSILON);
|
||||||
const halfY = Math.max(volume.size.y * 0.5, WATER_CONTACT_EPSILON);
|
const halfY = Math.max(volume.size.y * 0.5, WATER_CONTACT_EPSILON);
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import {
|
|||||||
resolveBoxVolumeRenderPaths,
|
resolveBoxVolumeRenderPaths,
|
||||||
type ResolvedBoxVolumeRenderPaths
|
type ResolvedBoxVolumeRenderPaths
|
||||||
} from "../rendering/advanced-rendering";
|
} from "../rendering/advanced-rendering";
|
||||||
import { collectWaterContactPatches, createWaterContactPatchUniformValue, createWaterMaterial } from "../rendering/water-material";
|
import { collectWaterContactPatches, createWaterContactPatchAxisUniformValue, createWaterContactPatchUniformValue, createWaterMaterial } from "../rendering/water-material";
|
||||||
import {
|
import {
|
||||||
areAdvancedRenderingSettingsEqual,
|
areAdvancedRenderingSettingsEqual,
|
||||||
cloneAdvancedRenderingSettings,
|
cloneAdvancedRenderingSettings,
|
||||||
@@ -71,6 +71,7 @@ interface LocalLightRenderObjects {
|
|||||||
interface RuntimeWaterContactUniformBinding {
|
interface RuntimeWaterContactUniformBinding {
|
||||||
brush: RuntimeBoxBrushInstance;
|
brush: RuntimeBoxBrushInstance;
|
||||||
uniform: { value: import("three").Vector4[] };
|
uniform: { value: import("three").Vector4[] };
|
||||||
|
axisUniform: { value: import("three").Vector2[] };
|
||||||
staticContactPatches: ReturnType<typeof collectWaterContactPatches>;
|
staticContactPatches: ReturnType<typeof collectWaterContactPatches>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -631,10 +632,11 @@ export class RuntimeHost {
|
|||||||
this.volumeAnimatedUniforms.push(waterMaterial.animationUniform);
|
this.volumeAnimatedUniforms.push(waterMaterial.animationUniform);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (faceId === "posY" && waterMaterial.contactPatchesUniform !== null) {
|
if (faceId === "posY" && waterMaterial.contactPatchesUniform !== null && waterMaterial.contactPatchAxesUniform !== null) {
|
||||||
this.runtimeWaterContactUniforms.push({
|
this.runtimeWaterContactUniforms.push({
|
||||||
brush,
|
brush,
|
||||||
uniform: waterMaterial.contactPatchesUniform,
|
uniform: waterMaterial.contactPatchesUniform,
|
||||||
|
axisUniform: waterMaterial.contactPatchAxesUniform,
|
||||||
staticContactPatches
|
staticContactPatches
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -811,10 +813,31 @@ export class RuntimeHost {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private collectRuntimeStaticWaterContactPatches(brush: RuntimeBoxBrushInstance) {
|
private collectRuntimeStaticWaterContactPatches(brush: RuntimeBoxBrushInstance) {
|
||||||
const contactBounds = this.runtimeScene?.colliders.map((collider) => ({
|
const contactBounds: Parameters<typeof collectWaterContactPatches>[1] = [];
|
||||||
min: collider.worldBounds.min,
|
|
||||||
max: collider.worldBounds.max
|
for (const otherBrush of this.runtimeScene?.brushes ?? []) {
|
||||||
})) ?? [];
|
if (otherBrush.id === brush.id || otherBrush.volume.mode !== "none") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
contactBounds.push({
|
||||||
|
kind: "orientedBox",
|
||||||
|
center: otherBrush.center,
|
||||||
|
rotationDegrees: otherBrush.rotationDegrees,
|
||||||
|
size: otherBrush.size
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const collider of this.runtimeScene?.colliders ?? []) {
|
||||||
|
if (collider.source !== "modelInstance") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
contactBounds.push({
|
||||||
|
min: collider.worldBounds.min,
|
||||||
|
max: collider.worldBounds.max
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return collectWaterContactPatches(
|
return collectWaterContactPatches(
|
||||||
{
|
{
|
||||||
@@ -852,9 +875,9 @@ export class RuntimeHost {
|
|||||||
|
|
||||||
private updateRuntimeWaterContactUniforms() {
|
private updateRuntimeWaterContactUniforms() {
|
||||||
for (const binding of this.runtimeWaterContactUniforms) {
|
for (const binding of this.runtimeWaterContactUniforms) {
|
||||||
binding.uniform.value = createWaterContactPatchUniformValue(
|
const mergedPatches = this.mergeRuntimeWaterContactPatches(binding.staticContactPatches, this.collectRuntimePlayerWaterContactPatches(binding.brush));
|
||||||
this.mergeRuntimeWaterContactPatches(binding.staticContactPatches, this.collectRuntimePlayerWaterContactPatches(binding.brush))
|
binding.uniform.value = createWaterContactPatchUniformValue(mergedPatches);
|
||||||
);
|
binding.axisUniform.value = createWaterContactPatchAxisUniformValue(mergedPatches);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3007,14 +3007,19 @@ export class ViewportHost {
|
|||||||
rotationDegrees: Vec3,
|
rotationDegrees: Vec3,
|
||||||
size: Vec3
|
size: Vec3
|
||||||
) {
|
) {
|
||||||
const contactBounds: GeneratedColliderBounds[] = [];
|
const contactBounds: Parameters<typeof collectWaterContactPatches>[1] = [];
|
||||||
|
|
||||||
for (const brush of Object.values(document.brushes)) {
|
for (const brush of Object.values(document.brushes)) {
|
||||||
if (brush.id === excludedBrushId || brush.volume.mode !== "none") {
|
if (brush.id === excludedBrushId || brush.volume.mode !== "none") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
contactBounds.push(getBoxBrushBounds(brush));
|
contactBounds.push({
|
||||||
|
kind: "orientedBox",
|
||||||
|
center: brush.center,
|
||||||
|
rotationDegrees: brush.rotationDegrees,
|
||||||
|
size: brush.size
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const modelInstance of getModelInstances(document.modelInstances)) {
|
for (const modelInstance of getModelInstances(document.modelInstances)) {
|
||||||
|
|||||||
@@ -84,6 +84,52 @@ describe("water material helpers", () => {
|
|||||||
expect(patches).toHaveLength(0);
|
expect(patches).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("preserves oriented contact regions for rotated boxes", () => {
|
||||||
|
const patches = collectWaterContactPatches(
|
||||||
|
{
|
||||||
|
center: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
},
|
||||||
|
rotationDegrees: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
x: 10,
|
||||||
|
y: 2,
|
||||||
|
z: 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[
|
||||||
|
{
|
||||||
|
kind: "orientedBox",
|
||||||
|
center: {
|
||||||
|
x: 0,
|
||||||
|
y: 1,
|
||||||
|
z: 0
|
||||||
|
},
|
||||||
|
rotationDegrees: {
|
||||||
|
x: 0,
|
||||||
|
y: 45,
|
||||||
|
z: 0
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
x: 2,
|
||||||
|
y: 1,
|
||||||
|
z: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(patches).toHaveLength(1);
|
||||||
|
expect(Math.abs(patches[0]?.axisX ?? 0)).toBeGreaterThan(0.65);
|
||||||
|
expect(Math.abs(patches[0]?.axisZ ?? 0)).toBeGreaterThan(0.65);
|
||||||
|
});
|
||||||
|
|
||||||
it("builds a shared quality shader material for visible tinted water", () => {
|
it("builds a shared quality shader material for visible tinted water", () => {
|
||||||
const result = createWaterMaterial({
|
const result = createWaterMaterial({
|
||||||
colorHex: "#4da6d9",
|
colorHex: "#4da6d9",
|
||||||
|
|||||||
Reference in New Issue
Block a user