playcanvas
Version:
PlayCanvas WebGL game engine
137 lines (134 loc) • 4.19 kB
JavaScript
import { math } from '../../core/math/math.js';
import { Vec3 } from '../../core/math/vec3.js';
import { DISTANCE_INVERSE, DISTANCE_LINEAR, DISTANCE_EXPONENTIAL } from './constants.js';
import { hasAudioContext } from './capabilities.js';
import { Channel } from './channel.js';
var MAX_DISTANCE = 10000;
class Channel3d extends Channel {
getPosition() {
return this.position;
}
setPosition(position) {
this.position.copy(position);
var panner = this.panner;
if ('positionX' in panner) {
panner.positionX.value = position.x;
panner.positionY.value = position.y;
panner.positionZ.value = position.z;
} else if (panner.setPosition) {
panner.setPosition(position.x, position.y, position.z);
}
}
getVelocity() {
return this.velocity;
}
setVelocity(velocity) {
this.velocity.copy(velocity);
}
getMaxDistance() {
return this.panner.maxDistance;
}
setMaxDistance(max) {
this.panner.maxDistance = max;
}
getMinDistance() {
return this.panner.refDistance;
}
setMinDistance(min) {
this.panner.refDistance = min;
}
getRollOffFactor() {
return this.panner.rolloffFactor;
}
setRollOffFactor(factor) {
this.panner.rolloffFactor = factor;
}
getDistanceModel() {
return this.panner.distanceModel;
}
setDistanceModel(distanceModel) {
this.panner.distanceModel = distanceModel;
}
_createSource() {
var context = this.manager.context;
this.source = context.createBufferSource();
this.source.buffer = this.sound.buffer;
this.source.connect(this.panner);
this.panner.connect(this.gain);
this.gain.connect(context.destination);
if (!this.loop) {
this.source.onended = this.pause.bind(this);
}
}
constructor(manager, sound, options){
super(manager, sound, options);
this.position = new Vec3();
this.velocity = new Vec3();
if (hasAudioContext()) {
this.panner = manager.context.createPanner();
} else {
this.maxDistance = MAX_DISTANCE;
this.minDistance = 1;
this.rollOffFactor = 1;
this.distanceModel = DISTANCE_INVERSE;
}
}
}
if (!hasAudioContext()) {
var offset = new Vec3();
var fallOff = function fallOff(posOne, posTwo, refDistance, maxDistance, rolloffFactor, distanceModel) {
offset = offset.sub2(posOne, posTwo);
var distance = offset.length();
if (distance < refDistance) {
return 1;
} else if (distance > maxDistance) {
return 0;
}
var result = 0;
if (distanceModel === DISTANCE_LINEAR) {
result = 1 - rolloffFactor * (distance - refDistance) / (maxDistance - refDistance);
} else if (distanceModel === DISTANCE_INVERSE) {
result = refDistance / (refDistance + rolloffFactor * (distance - refDistance));
} else if (distanceModel === DISTANCE_EXPONENTIAL) {
result = Math.pow(distance / refDistance, -rolloffFactor);
}
return math.clamp(result, 0, 1);
};
Object.assign(Channel3d.prototype, {
setPosition: function setPosition(position) {
this.position.copy(position);
if (this.source) {
var listener = this.manager.listener;
var lpos = listener.getPosition();
var factor = fallOff(lpos, this.position, this.minDistance, this.maxDistance, this.rollOffFactor, this.distanceModel);
var v = this.getVolume();
this.source.volume = v * factor;
}
},
getMaxDistance: function getMaxDistance() {
return this.maxDistance;
},
setMaxDistance: function setMaxDistance(max) {
this.maxDistance = max;
},
getMinDistance: function getMinDistance() {
return this.minDistance;
},
setMinDistance: function setMinDistance(min) {
this.minDistance = min;
},
getRollOffFactor: function getRollOffFactor() {
return this.rollOffFactor;
},
setRollOffFactor: function setRollOffFactor(factor) {
this.rollOffFactor = factor;
},
getDistanceModel: function getDistanceModel() {
return this.distanceModel;
},
setDistanceModel: function setDistanceModel(distanceModel) {
this.distanceModel = distanceModel;
}
});
}
export { Channel3d };