Better sounds; actually run cleanups (!)

This commit is contained in:
Tony Garnock-Jones 2023-01-12 16:34:54 +01:00
parent cb53f9b16f
commit a1f3db6e1b
8 changed files with 74 additions and 24 deletions

View File

@ -8,5 +8,12 @@ PortalDestination =
Gravity = <gravity @direction shapes.Vector3> . Gravity = <gravity @direction shapes.Vector3> .
AmbientSound = <ambient-sound @name string @spec SoundSpec> .
SoundSpec =
/ @stream <stream @url string>
/ @loop <loop @url string>
.
; Message ; Message
Touch = <touch @subject string @object string> . Touch = <touch @subject string @object string> .

View File

@ -34,7 +34,7 @@ Color =
/ @transparent <color @r double @g double @b double @alpha double @shape Shape> / @transparent <color @r double @g double @b double @alpha double @shape Shape>
. .
Sound = <sound @url string @shape Shape> . Sound = <sound @spec scene.SoundSpec @shape Shape> .
Name = <name @base string @shape Shape> . Name = <name @base string @shape Shape> .

View File

@ -76,14 +76,13 @@
<texture ["textures/oak-herringbone-5e80fb40b00c9-1200.jpg" <texture ["textures/oak-herringbone-5e80fb40b00c9-1200.jpg"
<v 1.0 3.0 1.0> <v 1.0 3.0 1.0>
<v 0.0 0.0 0.0>] <v 0.0 0.0 0.0>]
<sound "https://streams.95bfm.com/stream95" <sound <stream "https://streams.95bfm.com/stream95">
<csg <csg
<subtract [ <subtract [
<move <v 0.0 0.0 0.5> <scale <v 1.1 3.1 1.1> <mesh <box>>>> <move <v 0.0 0.0 0.5> <scale <v 1.1 3.1 1.1> <mesh <box>>>>
<move <v 0.0 0.0 0.5> <scale <v 1.0 3.0 1.0> <mesh <box>>>> <move <v 0.0 0.0 0.5> <scale <v 1.0 3.0 1.0> <mesh <box>>>>
]> ]>
>> >>>>>
>>>
; <Exit "y" "lobby"> ; <Exit "y" "lobby">
; <sprite "y" ; <sprite "y"

View File

@ -2,6 +2,8 @@
;<gravity <v 0.0 -9.81 0.0>> ;<gravity <v 0.0 -9.81 0.0>>
<sprite "sky" <skybox "textures/eso0932a">> <sprite "sky" <skybox "textures/eso0932a">>
<ambient-sound "space" <loop "sounds/Space-atmosphere-sound/Space-atmosphere-sound.mp3">>
; <sprite "ground2" ; <sprite "ground2"
; <texture ["textures/oak-herringbone-5e80fb40b00c9-1200.jpg" ; <texture ["textures/oak-herringbone-5e80fb40b00c9-1200.jpg"
; <v 100.0 100.0> ; <v 100.0 100.0>

View File

@ -0,0 +1,15 @@
Hello from Orange Free Sounds,
Stock audio - Free sound effects, loops and music.
There are no hidden costs or need to sign-up.
License: The sound effect is permitted for non-commercial use under license “Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)
https://orangefreesounds.com/

View File

@ -15,7 +15,7 @@ import {
WebXRCamera, WebXRCamera,
} from '@babylonjs/core/Legacy/legacy'; } from '@babylonjs/core/Legacy/legacy';
import { activeFloorMeshes, activeTouchableMeshes, ShapeTree, scale3, builder as B } from './shapes.js'; import { activeFloorMeshes, activeTouchableMeshes, ShapeTree, scale3, buildSound, builder as B } from './shapes.js';
import { RunningEngine } from './engine.js'; import { RunningEngine } from './engine.js';
import { uuid } from './uuid.js'; import { uuid } from './uuid.js';
@ -32,6 +32,14 @@ function interpretScene(myId: string, runningEngine: RunningEngine, rootMesh: Me
spriteMain(name, runningEngine, rootMesh, sceneDs); spriteMain(name, runningEngine, rootMesh, sceneDs);
} }
} }
during SceneProtocol.AmbientSound({
"name": $name: string,
"spec": $spec: SceneProtocol.SoundSpec
}) => spawn named `sound:${name}` {
const sound = buildSound(name, runningEngine.scene, spec, false);
on stop sound.dispose();
}
} }
} }

View File

@ -4,6 +4,7 @@ import {
CubeTexture, CubeTexture,
CSG, CSG,
HemisphericLight, HemisphericLight,
ISoundOptions,
Material, Material,
Matrix, Matrix,
Mesh, Mesh,
@ -22,6 +23,7 @@ import {
import { KeyedDictionary, Value, is } from "@syndicate-lang/core"; import { KeyedDictionary, Value, is } from "@syndicate-lang/core";
import * as Shapes from './gen/shapes.js'; import * as Shapes from './gen/shapes.js';
import * as SceneProtocol from './gen/scene.js';
export const activeFloorMeshes: Array<AbstractMesh> = []; export const activeFloorMeshes: Array<AbstractMesh> = [];
export const activeTouchableMeshes: Array<AbstractMesh> = []; export const activeTouchableMeshes: Array<AbstractMesh> = [];
@ -30,6 +32,7 @@ export class ShapeTree<N extends Node = Node> {
shapePreserve: Value; shapePreserve: Value;
cleanups: Array<() => void> = []; cleanups: Array<() => void> = [];
subnodes: Promise<N[]>; subnodes: Promise<N[]>;
subtrees: ShapeTree[] = [];
constructor ( constructor (
public scene: Scene, public scene: Scene,
@ -60,8 +63,15 @@ export class ShapeTree<N extends Node = Node> {
} }
} }
set parent(t: ShapeTree) {
t.subtrees.push(this);
this.rootnode.parent = t.rootnode;
}
remove() { remove() {
this.subtrees.forEach(t => t.remove());
this.allnodes.then(ns => ns.forEach(n => n.dispose())); this.allnodes.then(ns => ns.forEach(n => n.dispose()));
this.cleanups.forEach(c => c());
} }
static empty(name: string, scene: Scene): ShapeTree { static empty(name: string, scene: Scene): ShapeTree {
@ -181,6 +191,26 @@ export function buildMesh(
} }
} }
export function buildSound(name: string, scene: Scene, spec: SceneProtocol.SoundSpec, spatial: boolean): Sound {
const options: ISoundOptions = {
loop: true,
autoplay: true,
skipCodecCheck: true,
};
if (spatial) {
options.distanceModel = "inverse";
options.rolloffFactor = 0.25;
}
switch (spec._variant) {
case "stream":
options.streaming = true;
break;
case "loop":
break;
}
return new Sound(name, spec.url, scene, null, options);
}
export function build(name: string, scene: Scene, shape: Shapes.Shape, customize: MeshCustomizer): ShapeTree { export function build(name: string, scene: Scene, shape: Shapes.Shape, customize: MeshCustomizer): ShapeTree {
switch (shape._variant) { switch (shape._variant) {
case "Mesh": { case "Mesh": {
@ -199,14 +229,14 @@ export function build(name: string, scene: Scene, shape: Shapes.Shape, customize
case "Scale": { case "Scale": {
const t = ShapeTree.transform(name, scene, shape); const t = ShapeTree.transform(name, scene, shape);
t.rootnode.scaling = v3(shape.value.v); t.rootnode.scaling = v3(shape.value.v);
build(name + '.inner', scene, shape.value.shape, customize).rootnode.parent = t.rootnode; build(name + '.inner', scene, shape.value.shape, customize).parent = t;
return t; return t;
} }
case "Move": { case "Move": {
const t = ShapeTree.transform(name, scene, shape); const t = ShapeTree.transform(name, scene, shape);
t.rootnode.position = v3(shape.value.v); t.rootnode.position = v3(shape.value.v);
build(name + '.inner', scene, shape.value.shape, customize).rootnode.parent = t.rootnode; build(name + '.inner', scene, shape.value.shape, customize).parent = t;
return t; return t;
} }
@ -221,14 +251,14 @@ export function build(name: string, scene: Scene, shape: Shapes.Shape, customize
t.rootnode.rotationQuaternion = q(shape.value.q); t.rootnode.rotationQuaternion = q(shape.value.q);
break; break;
} }
build(name + '.inner', scene, shape.value.shape, customize).rootnode.parent = t.rootnode; build(name + '.inner', scene, shape.value.shape, customize).parent = t;
return t; return t;
} }
case "many": { case "many": {
const t = ShapeTree.transform(name, scene, shape); const t = ShapeTree.transform(name, scene, shape);
shape.value.forEach((s, i) => { shape.value.forEach((s, i) => {
build(name + '[' + i + ']', scene, s, customize).rootnode.parent = t.rootnode; build(name + '[' + i + ']', scene, s, customize).parent = t;
}); });
return t; return t;
} }
@ -254,24 +284,13 @@ export function build(name: string, scene: Scene, shape: Shapes.Shape, customize
} }
case "Sound": { case "Sound": {
const sound = new Sound( const sound = buildSound(name + ".sound", scene, shape.value.spec, true);
name + ".sound", const t = build(name + ".inner", scene, shape.value.shape, {
shape.value.url,
scene,
null,
{
distanceModel: "inverse",
loop: true,
rolloffFactor: 0.25,
autoplay: true,
streaming: true,
skipCodecCheck: true,
});
console.log(sound);
return build(name + ".inner", scene, shape.value.shape, {
... customize, ... customize,
sound: async m => sound.attachToMesh(m.rootnode), sound: async m => sound.attachToMesh(m.rootnode),
}); });
t.cleanups.push(() => sound.dispose());
return t;
} }
case "Name": case "Name":