}
*/
PhysicsRadialExplosionEvent.prototype.getImpostorForceAndContactPoint = function (impostor, origin, radius, strength, falloff) {
if (impostor.mass === 0) {
return null;
}
if (!this._intersectsWithSphere(impostor, origin, radius)) {
return null;
}
if (impostor.object.getClassName() !== 'Mesh') {
return null;
}
var impostorObject = impostor.object;
var impostorObjectCenter = impostor.getObjectCenter();
var direction = impostorObjectCenter.subtract(origin);
var ray = new BABYLON.Ray(origin, direction, radius);
this._rays.push(ray);
var hit = ray.intersectsMesh(impostorObject);
var contactPoint = hit.pickedPoint;
if (!contactPoint) {
return null;
}
var distanceFromOrigin = BABYLON.Vector3.Distance(origin, contactPoint);
if (distanceFromOrigin > radius) {
return null;
}
var multiplier = falloff === PhysicsRadialImpulseFalloff.Constant
? strength
: strength * (1 - (distanceFromOrigin / radius));
var force = direction.multiplyByFloats(multiplier, multiplier, multiplier);
return { force: force, contactPoint: contactPoint };
};
/**
* Disposes the sphere.
* @param {bolean} force
*/
PhysicsRadialExplosionEvent.prototype.dispose = function (force) {
var _this = this;
if (force === void 0) { force = true; }
if (force) {
this._sphere.dispose();
}
else {
setTimeout(function () {
if (!_this._dataFetched) {
_this._sphere.dispose();
}
}, 0);
}
};
/*** Helpers ***/
PhysicsRadialExplosionEvent.prototype._prepareSphere = function () {
if (!this._sphere) {
this._sphere = BABYLON.MeshBuilder.CreateSphere("radialExplosionEventSphere", this._sphereOptions, this._scene);
this._sphere.isVisible = false;
}
};
PhysicsRadialExplosionEvent.prototype._intersectsWithSphere = function (impostor, origin, radius) {
var impostorObject = impostor.object;
this._prepareSphere();
this._sphere.position = origin;
this._sphere.scaling = new BABYLON.Vector3(radius * 2, radius * 2, radius * 2);
this._sphere._updateBoundingInfo();
this._sphere.computeWorldMatrix(true);
return this._sphere.intersectsMesh(impostorObject, true);
};
return PhysicsRadialExplosionEvent;
}());
BABYLON.PhysicsRadialExplosionEvent = PhysicsRadialExplosionEvent;
/***** Gravitational Field *****/
var PhysicsGravitationalFieldEvent = /** @class */ (function () {
function PhysicsGravitationalFieldEvent(physicsHelper, scene, origin, radius, strength, falloff) {
if (falloff === void 0) { falloff = PhysicsRadialImpulseFalloff.Constant; }
this._dataFetched = false; // check if the has been fetched the data. If not, do cleanup
this._physicsHelper = physicsHelper;
this._scene = scene;
this._origin = origin;
this._radius = radius;
this._strength = strength;
this._falloff = falloff;
this._tickCallback = this._tick.bind(this);
}
/**
* Returns the data related to the gravitational field event (sphere).
* @returns {PhysicsGravitationalFieldEventData}
*/
PhysicsGravitationalFieldEvent.prototype.getData = function () {
this._dataFetched = true;
return {
sphere: this._sphere,
};
};
/**
* Enables the gravitational field.
*/
PhysicsGravitationalFieldEvent.prototype.enable = function () {
this._tickCallback.call(this);
this._scene.registerBeforeRender(this._tickCallback);
};
/**
* Disables the gravitational field.
*/
PhysicsGravitationalFieldEvent.prototype.disable = function () {
this._scene.unregisterBeforeRender(this._tickCallback);
};
/**
* Disposes the sphere.
* @param {bolean} force
*/
PhysicsGravitationalFieldEvent.prototype.dispose = function (force) {
var _this = this;
if (force === void 0) { force = true; }
if (force) {
this._sphere.dispose();
}
else {
setTimeout(function () {
if (!_this._dataFetched) {
_this._sphere.dispose();
}
}, 0);
}
};
PhysicsGravitationalFieldEvent.prototype._tick = function () {
// Since the params won't change, we fetch the event only once
if (this._sphere) {
this._physicsHelper.applyRadialExplosionForce(this._origin, this._radius, this._strength * -1, this._falloff);
}
else {
var radialExplosionEvent = this._physicsHelper.applyRadialExplosionForce(this._origin, this._radius, this._strength * -1, this._falloff);
if (radialExplosionEvent) {
this._sphere = radialExplosionEvent.getData().sphere.clone('radialExplosionEventSphereClone');
}
}
};
return PhysicsGravitationalFieldEvent;
}());
BABYLON.PhysicsGravitationalFieldEvent = PhysicsGravitationalFieldEvent;
/***** Updraft *****/
var PhysicsUpdraftEvent = /** @class */ (function () {
function PhysicsUpdraftEvent(_scene, _origin, _radius, _strength, _height, _updraftMode) {
this._scene = _scene;
this._origin = _origin;
this._radius = _radius;
this._strength = _strength;
this._height = _height;
this._updraftMode = _updraftMode;
this._originTop = BABYLON.Vector3.Zero(); // the most upper part of the cylinder
this._originDirection = BABYLON.Vector3.Zero(); // used if the updraftMode is perpendicular
this._cylinderPosition = BABYLON.Vector3.Zero(); // to keep the cylinders position, because normally the origin is in the center and not on the bottom
this._dataFetched = false; // check if the has been fetched the data. If not, do cleanup
this._physicsEngine = this._scene.getPhysicsEngine();
this._origin.addToRef(new BABYLON.Vector3(0, this._height / 2, 0), this._cylinderPosition);
this._origin.addToRef(new BABYLON.Vector3(0, this._height, 0), this._originTop);
if (this._updraftMode === PhysicsUpdraftMode.Perpendicular) {
this._originDirection = this._origin.subtract(this._originTop).normalize();
}
this._tickCallback = this._tick.bind(this);
}
/**
* Returns the data related to the updraft event (cylinder).
* @returns {PhysicsUpdraftEventData}
*/
PhysicsUpdraftEvent.prototype.getData = function () {
this._dataFetched = true;
return {
cylinder: this._cylinder,
};
};
/**
* Enables the updraft.
*/
PhysicsUpdraftEvent.prototype.enable = function () {
this._tickCallback.call(this);
this._scene.registerBeforeRender(this._tickCallback);
};
/**
* Disables the cortex.
*/
PhysicsUpdraftEvent.prototype.disable = function () {
this._scene.unregisterBeforeRender(this._tickCallback);
};
/**
* Disposes the sphere.
* @param {bolean} force
*/
PhysicsUpdraftEvent.prototype.dispose = function (force) {
var _this = this;
if (force === void 0) { force = true; }
if (force) {
this._cylinder.dispose();
}
else {
setTimeout(function () {
if (!_this._dataFetched) {
_this._cylinder.dispose();
}
}, 0);
}
};
PhysicsUpdraftEvent.prototype.getImpostorForceAndContactPoint = function (impostor) {
if (impostor.mass === 0) {
return null;
}
if (!this._intersectsWithCylinder(impostor)) {
return null;
}
var impostorObjectCenter = impostor.getObjectCenter();
if (this._updraftMode === PhysicsUpdraftMode.Perpendicular) {
var direction = this._originDirection;
}
else {
var direction = impostorObjectCenter.subtract(this._originTop);
}
var multiplier = this._strength * -1;
var force = direction.multiplyByFloats(multiplier, multiplier, multiplier);
return { force: force, contactPoint: impostorObjectCenter };
};
PhysicsUpdraftEvent.prototype._tick = function () {
var _this = this;
this._physicsEngine.getImpostors().forEach(function (impostor) {
var impostorForceAndContactPoint = _this.getImpostorForceAndContactPoint(impostor);
if (!impostorForceAndContactPoint) {
return;
}
impostor.applyForce(impostorForceAndContactPoint.force, impostorForceAndContactPoint.contactPoint);
});
};
/*** Helpers ***/
PhysicsUpdraftEvent.prototype._prepareCylinder = function () {
if (!this._cylinder) {
this._cylinder = BABYLON.MeshBuilder.CreateCylinder("updraftEventCylinder", {
height: this._height,
diameter: this._radius * 2,
}, this._scene);
this._cylinder.isVisible = false;
}
};
PhysicsUpdraftEvent.prototype._intersectsWithCylinder = function (impostor) {
var impostorObject = impostor.object;
this._prepareCylinder();
this._cylinder.position = this._cylinderPosition;
return this._cylinder.intersectsMesh(impostorObject, true);
};
return PhysicsUpdraftEvent;
}());
BABYLON.PhysicsUpdraftEvent = PhysicsUpdraftEvent;
/***** Vortex *****/
var PhysicsVortexEvent = /** @class */ (function () {
function PhysicsVortexEvent(_scene, _origin, _radius, _strength, _height) {
this._scene = _scene;
this._origin = _origin;
this._radius = _radius;
this._strength = _strength;
this._height = _height;
this._originTop = BABYLON.Vector3.Zero(); // the most upper part of the cylinder
this._centripetalForceThreshold = 0.7; // at which distance, relative to the radius the centripetal forces should kick in
this._updraftMultiplier = 0.02;
this._cylinderPosition = BABYLON.Vector3.Zero(); // to keep the cylinders position, because normally the origin is in the center and not on the bottom
this._dataFetched = false; // check if the has been fetched the data. If not, do cleanup
this._physicsEngine = this._scene.getPhysicsEngine();
this._origin.addToRef(new BABYLON.Vector3(0, this._height / 2, 0), this._cylinderPosition);
this._origin.addToRef(new BABYLON.Vector3(0, this._height, 0), this._originTop);
this._tickCallback = this._tick.bind(this);
}
/**
* Returns the data related to the vortex event (cylinder).
* @returns {PhysicsVortexEventData}
*/
PhysicsVortexEvent.prototype.getData = function () {
this._dataFetched = true;
return {
cylinder: this._cylinder,
};
};
/**
* Enables the vortex.
*/
PhysicsVortexEvent.prototype.enable = function () {
this._tickCallback.call(this);
this._scene.registerBeforeRender(this._tickCallback);
};
/**
* Disables the cortex.
*/
PhysicsVortexEvent.prototype.disable = function () {
this._scene.unregisterBeforeRender(this._tickCallback);
};
/**
* Disposes the sphere.
* @param {bolean} force
*/
PhysicsVortexEvent.prototype.dispose = function (force) {
var _this = this;
if (force === void 0) { force = true; }
if (force) {
this._cylinder.dispose();
}
else {
setTimeout(function () {
if (!_this._dataFetched) {
_this._cylinder.dispose();
}
}, 0);
}
};
PhysicsVortexEvent.prototype.getImpostorForceAndContactPoint = function (impostor) {
if (impostor.mass === 0) {
return null;
}
if (!this._intersectsWithCylinder(impostor)) {
return null;
}
if (impostor.object.getClassName() !== 'Mesh') {
return null;
}
var impostorObject = impostor.object;
var impostorObjectCenter = impostor.getObjectCenter();
var originOnPlane = new BABYLON.Vector3(this._origin.x, impostorObjectCenter.y, this._origin.z); // the distance to the origin as if both objects were on a plane (Y-axis)
var originToImpostorDirection = impostorObjectCenter.subtract(originOnPlane);
var ray = new BABYLON.Ray(originOnPlane, originToImpostorDirection, this._radius);
var hit = ray.intersectsMesh(impostorObject);
var contactPoint = hit.pickedPoint;
if (!contactPoint) {
return null;
}
var absoluteDistanceFromOrigin = hit.distance / this._radius;
var perpendicularDirection = BABYLON.Vector3.Cross(originOnPlane, impostorObjectCenter).normalize();
var directionToOrigin = contactPoint.normalize();
if (absoluteDistanceFromOrigin > this._centripetalForceThreshold) {
directionToOrigin = directionToOrigin.negate();
}
// TODO: find a more physically based solution
if (absoluteDistanceFromOrigin > this._centripetalForceThreshold) {
var forceX = directionToOrigin.x * this._strength / 8;
var forceY = directionToOrigin.y * this._updraftMultiplier;
var forceZ = directionToOrigin.z * this._strength / 8;
}
else {
var forceX = (perpendicularDirection.x + directionToOrigin.x) / 2;
var forceY = this._originTop.y * this._updraftMultiplier;
var forceZ = (perpendicularDirection.z + directionToOrigin.z) / 2;
}
var force = new BABYLON.Vector3(forceX, forceY, forceZ);
force = force.multiplyByFloats(this._strength, this._strength, this._strength);
return { force: force, contactPoint: impostorObjectCenter };
};
PhysicsVortexEvent.prototype._tick = function () {
var _this = this;
this._physicsEngine.getImpostors().forEach(function (impostor) {
var impostorForceAndContactPoint = _this.getImpostorForceAndContactPoint(impostor);
if (!impostorForceAndContactPoint) {
return;
}
impostor.applyForce(impostorForceAndContactPoint.force, impostorForceAndContactPoint.contactPoint);
});
};
/*** Helpers ***/
PhysicsVortexEvent.prototype._prepareCylinder = function () {
if (!this._cylinder) {
this._cylinder = BABYLON.MeshBuilder.CreateCylinder("vortexEventCylinder", {
height: this._height,
diameter: this._radius * 2,
}, this._scene);
this._cylinder.isVisible = false;
}
};
PhysicsVortexEvent.prototype._intersectsWithCylinder = function (impostor) {
var impostorObject = impostor.object;
this._prepareCylinder();
this._cylinder.position = this._cylinderPosition;
return this._cylinder.intersectsMesh(impostorObject, true);
};
return PhysicsVortexEvent;
}());
BABYLON.PhysicsVortexEvent = PhysicsVortexEvent;
/***** Enums *****/
/**
* The strenght of the force in correspondence to the distance of the affected object
*/
var PhysicsRadialImpulseFalloff;
(function (PhysicsRadialImpulseFalloff) {
PhysicsRadialImpulseFalloff[PhysicsRadialImpulseFalloff["Constant"] = 0] = "Constant";
PhysicsRadialImpulseFalloff[PhysicsRadialImpulseFalloff["Linear"] = 1] = "Linear"; // impulse gets weaker if it's further from the origin
})(PhysicsRadialImpulseFalloff = BABYLON.PhysicsRadialImpulseFalloff || (BABYLON.PhysicsRadialImpulseFalloff = {}));
/**
* The strenght of the force in correspondence to the distance of the affected object
*/
var PhysicsUpdraftMode;
(function (PhysicsUpdraftMode) {
PhysicsUpdraftMode[PhysicsUpdraftMode["Center"] = 0] = "Center";
PhysicsUpdraftMode[PhysicsUpdraftMode["Perpendicular"] = 1] = "Perpendicular"; // once a impostor is inside the cylinder, it will shoot out perpendicular from the ground of the cylinder
})(PhysicsUpdraftMode = BABYLON.PhysicsUpdraftMode || (BABYLON.PhysicsUpdraftMode = {}));
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.physicsHelper.js.map
var BABYLON;
(function (BABYLON) {
var CannonJSPlugin = /** @class */ (function () {
function CannonJSPlugin(_useDeltaForWorldStep, iterations) {
if (_useDeltaForWorldStep === void 0) { _useDeltaForWorldStep = true; }
if (iterations === void 0) { iterations = 10; }
this._useDeltaForWorldStep = _useDeltaForWorldStep;
this.name = "CannonJSPlugin";
this._physicsMaterials = new Array();
this._fixedTimeStep = 1 / 60;
//See https://github.com/schteppe/CANNON.js/blob/gh-pages/demos/collisionFilter.html
this.BJSCANNON = typeof CANNON !== 'undefined' ? CANNON : (typeof require !== 'undefined' ? require('cannon') : undefined);
this._minus90X = new BABYLON.Quaternion(-0.7071067811865475, 0, 0, 0.7071067811865475);
this._plus90X = new BABYLON.Quaternion(0.7071067811865475, 0, 0, 0.7071067811865475);
this._tmpPosition = BABYLON.Vector3.Zero();
this._tmpDeltaPosition = BABYLON.Vector3.Zero();
this._tmpUnityRotation = new BABYLON.Quaternion();
if (!this.isSupported()) {
BABYLON.Tools.Error("CannonJS is not available. Please make sure you included the js file.");
return;
}
this._extendNamespace();
this.world = new this.BJSCANNON.World();
this.world.broadphase = new this.BJSCANNON.NaiveBroadphase();
this.world.solver.iterations = iterations;
}
CannonJSPlugin.prototype.setGravity = function (gravity) {
this.world.gravity.copy(gravity);
};
CannonJSPlugin.prototype.setTimeStep = function (timeStep) {
this._fixedTimeStep = timeStep;
};
CannonJSPlugin.prototype.getTimeStep = function () {
return this._fixedTimeStep;
};
CannonJSPlugin.prototype.executeStep = function (delta, impostors) {
this.world.step(this._fixedTimeStep, this._useDeltaForWorldStep ? delta : 0, 3);
};
CannonJSPlugin.prototype.applyImpulse = function (impostor, force, contactPoint) {
var worldPoint = new this.BJSCANNON.Vec3(contactPoint.x, contactPoint.y, contactPoint.z);
var impulse = new this.BJSCANNON.Vec3(force.x, force.y, force.z);
impostor.physicsBody.applyImpulse(impulse, worldPoint);
};
CannonJSPlugin.prototype.applyForce = function (impostor, force, contactPoint) {
var worldPoint = new this.BJSCANNON.Vec3(contactPoint.x, contactPoint.y, contactPoint.z);
var impulse = new this.BJSCANNON.Vec3(force.x, force.y, force.z);
impostor.physicsBody.applyForce(impulse, worldPoint);
};
CannonJSPlugin.prototype.generatePhysicsBody = function (impostor) {
//parent-child relationship. Does this impostor has a parent impostor?
if (impostor.parent) {
if (impostor.physicsBody) {
this.removePhysicsBody(impostor);
//TODO is that needed?
impostor.forceUpdate();
}
return;
}
//should a new body be created for this impostor?
if (impostor.isBodyInitRequired()) {
var shape = this._createShape(impostor);
//unregister events, if body is being changed
var oldBody = impostor.physicsBody;
if (oldBody) {
this.removePhysicsBody(impostor);
}
//create the body and material
var material = this._addMaterial("mat-" + impostor.uniqueId, impostor.getParam("friction"), impostor.getParam("restitution"));
var bodyCreationObject = {
mass: impostor.getParam("mass"),
material: material
};
// A simple extend, in case native options were used.
var nativeOptions = impostor.getParam("nativeOptions");
for (var key in nativeOptions) {
if (nativeOptions.hasOwnProperty(key)) {
bodyCreationObject[key] = nativeOptions[key];
}
}
impostor.physicsBody = new this.BJSCANNON.Body(bodyCreationObject);
impostor.physicsBody.addEventListener("collide", impostor.onCollide);
this.world.addEventListener("preStep", impostor.beforeStep);
this.world.addEventListener("postStep", impostor.afterStep);
impostor.physicsBody.addShape(shape);
this.world.add(impostor.physicsBody);
//try to keep the body moving in the right direction by taking old properties.
//Should be tested!
if (oldBody) {
['force', 'torque', 'velocity', 'angularVelocity'].forEach(function (param) {
impostor.physicsBody[param].copy(oldBody[param]);
});
}
this._processChildMeshes(impostor);
}
//now update the body's transformation
this._updatePhysicsBodyTransformation(impostor);
};
CannonJSPlugin.prototype._processChildMeshes = function (mainImpostor) {
var _this = this;
var meshChildren = mainImpostor.object.getChildMeshes ? mainImpostor.object.getChildMeshes(true) : [];
var currentRotation = mainImpostor.object.rotationQuaternion;
if (meshChildren.length) {
var processMesh = function (localPosition, mesh) {
if (!currentRotation || !mesh.rotationQuaternion) {
return;
}
var childImpostor = mesh.getPhysicsImpostor();
if (childImpostor) {
var parent = childImpostor.parent;
if (parent !== mainImpostor) {
var pPosition = mesh.getAbsolutePosition().subtract(mainImpostor.object.getAbsolutePosition());
var localRotation = mesh.rotationQuaternion.multiply(BABYLON.Quaternion.Inverse(currentRotation));
if (childImpostor.physicsBody) {
_this.removePhysicsBody(childImpostor);
childImpostor.physicsBody = null;
}
childImpostor.parent = mainImpostor;
childImpostor.resetUpdateFlags();
mainImpostor.physicsBody.addShape(_this._createShape(childImpostor), new _this.BJSCANNON.Vec3(pPosition.x, pPosition.y, pPosition.z), new _this.BJSCANNON.Quaternion(localRotation.x, localRotation.y, localRotation.z, localRotation.w));
//Add the mass of the children.
mainImpostor.physicsBody.mass += childImpostor.getParam("mass");
}
}
currentRotation.multiplyInPlace(mesh.rotationQuaternion);
mesh.getChildMeshes(true).filter(function (m) { return !!m.physicsImpostor; }).forEach(processMesh.bind(_this, mesh.getAbsolutePosition()));
};
meshChildren.filter(function (m) { return !!m.physicsImpostor; }).forEach(processMesh.bind(this, mainImpostor.object.getAbsolutePosition()));
}
};
CannonJSPlugin.prototype.removePhysicsBody = function (impostor) {
impostor.physicsBody.removeEventListener("collide", impostor.onCollide);
this.world.removeEventListener("preStep", impostor.beforeStep);
this.world.removeEventListener("postStep", impostor.afterStep);
this.world.remove(impostor.physicsBody);
};
CannonJSPlugin.prototype.generateJoint = function (impostorJoint) {
var mainBody = impostorJoint.mainImpostor.physicsBody;
var connectedBody = impostorJoint.connectedImpostor.physicsBody;
if (!mainBody || !connectedBody) {
return;
}
var constraint;
var jointData = impostorJoint.joint.jointData;
//TODO - https://github.com/schteppe/this.BJSCANNON.js/blob/gh-pages/demos/collisionFilter.html
var constraintData = {
pivotA: jointData.mainPivot ? new this.BJSCANNON.Vec3().copy(jointData.mainPivot) : null,
pivotB: jointData.connectedPivot ? new this.BJSCANNON.Vec3().copy(jointData.connectedPivot) : null,
axisA: jointData.mainAxis ? new this.BJSCANNON.Vec3().copy(jointData.mainAxis) : null,
axisB: jointData.connectedAxis ? new this.BJSCANNON.Vec3().copy(jointData.connectedAxis) : null,
maxForce: jointData.nativeParams.maxForce,
collideConnected: !!jointData.collision
};
switch (impostorJoint.joint.type) {
case BABYLON.PhysicsJoint.HingeJoint:
case BABYLON.PhysicsJoint.Hinge2Joint:
constraint = new this.BJSCANNON.HingeConstraint(mainBody, connectedBody, constraintData);
break;
case BABYLON.PhysicsJoint.DistanceJoint:
constraint = new this.BJSCANNON.DistanceConstraint(mainBody, connectedBody, jointData.maxDistance || 2);
break;
case BABYLON.PhysicsJoint.SpringJoint:
var springData = jointData;
constraint = new this.BJSCANNON.Spring(mainBody, connectedBody, {
restLength: springData.length,
stiffness: springData.stiffness,
damping: springData.damping,
localAnchorA: constraintData.pivotA,
localAnchorB: constraintData.pivotB
});
break;
case BABYLON.PhysicsJoint.LockJoint:
constraint = new this.BJSCANNON.LockConstraint(mainBody, connectedBody, constraintData);
break;
case BABYLON.PhysicsJoint.PointToPointJoint:
case BABYLON.PhysicsJoint.BallAndSocketJoint:
default:
constraint = new this.BJSCANNON.PointToPointConstraint(mainBody, constraintData.pivotA, connectedBody, constraintData.pivotA, constraintData.maxForce);
break;
}
//set the collideConnected flag after the creation, since DistanceJoint ignores it.
constraint.collideConnected = !!jointData.collision;
impostorJoint.joint.physicsJoint = constraint;
//don't add spring as constraint, as it is not one.
if (impostorJoint.joint.type !== BABYLON.PhysicsJoint.SpringJoint) {
this.world.addConstraint(constraint);
}
else {
impostorJoint.mainImpostor.registerAfterPhysicsStep(function () {
constraint.applyForce();
});
}
};
CannonJSPlugin.prototype.removeJoint = function (impostorJoint) {
this.world.removeConstraint(impostorJoint.joint.physicsJoint);
};
CannonJSPlugin.prototype._addMaterial = function (name, friction, restitution) {
var index;
var mat;
for (index = 0; index < this._physicsMaterials.length; index++) {
mat = this._physicsMaterials[index];
if (mat.friction === friction && mat.restitution === restitution) {
return mat;
}
}
var currentMat = new this.BJSCANNON.Material(name);
currentMat.friction = friction;
currentMat.restitution = restitution;
this._physicsMaterials.push(currentMat);
return currentMat;
};
CannonJSPlugin.prototype._checkWithEpsilon = function (value) {
return value < BABYLON.PhysicsEngine.Epsilon ? BABYLON.PhysicsEngine.Epsilon : value;
};
CannonJSPlugin.prototype._createShape = function (impostor) {
var object = impostor.object;
var returnValue;
var extendSize = impostor.getObjectExtendSize();
switch (impostor.type) {
case BABYLON.PhysicsImpostor.SphereImpostor:
var radiusX = extendSize.x;
var radiusY = extendSize.y;
var radiusZ = extendSize.z;
returnValue = new this.BJSCANNON.Sphere(Math.max(this._checkWithEpsilon(radiusX), this._checkWithEpsilon(radiusY), this._checkWithEpsilon(radiusZ)) / 2);
break;
//TMP also for cylinder - TODO Cannon supports cylinder natively.
case BABYLON.PhysicsImpostor.CylinderImpostor:
returnValue = new this.BJSCANNON.Cylinder(this._checkWithEpsilon(extendSize.x) / 2, this._checkWithEpsilon(extendSize.x) / 2, this._checkWithEpsilon(extendSize.y), 16);
break;
case BABYLON.PhysicsImpostor.BoxImpostor:
var box = extendSize.scale(0.5);
returnValue = new this.BJSCANNON.Box(new this.BJSCANNON.Vec3(this._checkWithEpsilon(box.x), this._checkWithEpsilon(box.y), this._checkWithEpsilon(box.z)));
break;
case BABYLON.PhysicsImpostor.PlaneImpostor:
BABYLON.Tools.Warn("Attention, PlaneImposter might not behave as you expect. Consider using BoxImposter instead");
returnValue = new this.BJSCANNON.Plane();
break;
case BABYLON.PhysicsImpostor.MeshImpostor:
// should transform the vertex data to world coordinates!!
var rawVerts = object.getVerticesData ? object.getVerticesData(BABYLON.VertexBuffer.PositionKind) : [];
var rawFaces = object.getIndices ? object.getIndices() : [];
if (!rawVerts)
return;
// get only scale! so the object could transform correctly.
var oldPosition = object.position.clone();
var oldRotation = object.rotation && object.rotation.clone();
var oldQuaternion = object.rotationQuaternion && object.rotationQuaternion.clone();
object.position.copyFromFloats(0, 0, 0);
object.rotation && object.rotation.copyFromFloats(0, 0, 0);
object.rotationQuaternion && object.rotationQuaternion.copyFrom(impostor.getParentsRotation());
object.rotationQuaternion && object.parent && object.rotationQuaternion.conjugateInPlace();
var transform = object.computeWorldMatrix(true);
// convert rawVerts to object space
var temp = new Array();
var index;
for (index = 0; index < rawVerts.length; index += 3) {
BABYLON.Vector3.TransformCoordinates(BABYLON.Vector3.FromArray(rawVerts, index), transform).toArray(temp, index);
}
BABYLON.Tools.Warn("MeshImpostor only collides against spheres.");
returnValue = new this.BJSCANNON.Trimesh(temp, rawFaces);
//now set back the transformation!
object.position.copyFrom(oldPosition);
oldRotation && object.rotation && object.rotation.copyFrom(oldRotation);
oldQuaternion && object.rotationQuaternion && object.rotationQuaternion.copyFrom(oldQuaternion);
break;
case BABYLON.PhysicsImpostor.HeightmapImpostor:
var oldPosition2 = object.position.clone();
var oldRotation2 = object.rotation && object.rotation.clone();
var oldQuaternion2 = object.rotationQuaternion && object.rotationQuaternion.clone();
object.position.copyFromFloats(0, 0, 0);
object.rotation && object.rotation.copyFromFloats(0, 0, 0);
object.rotationQuaternion && object.rotationQuaternion.copyFrom(impostor.getParentsRotation());
object.rotationQuaternion && object.parent && object.rotationQuaternion.conjugateInPlace();
object.rotationQuaternion && object.rotationQuaternion.multiplyInPlace(this._minus90X);
returnValue = this._createHeightmap(object);
object.position.copyFrom(oldPosition2);
oldRotation2 && object.rotation && object.rotation.copyFrom(oldRotation2);
oldQuaternion2 && object.rotationQuaternion && object.rotationQuaternion.copyFrom(oldQuaternion2);
object.computeWorldMatrix(true);
break;
case BABYLON.PhysicsImpostor.ParticleImpostor:
returnValue = new this.BJSCANNON.Particle();
break;
}
return returnValue;
};
CannonJSPlugin.prototype._createHeightmap = function (object, pointDepth) {
var pos = (object.getVerticesData(BABYLON.VertexBuffer.PositionKind));
var transform = object.computeWorldMatrix(true);
// convert rawVerts to object space
var temp = new Array();
var index;
for (index = 0; index < pos.length; index += 3) {
BABYLON.Vector3.TransformCoordinates(BABYLON.Vector3.FromArray(pos, index), transform).toArray(temp, index);
}
pos = temp;
var matrix = new Array();
//For now pointDepth will not be used and will be automatically calculated.
//Future reference - try and find the best place to add a reference to the pointDepth variable.
var arraySize = pointDepth || ~~(Math.sqrt(pos.length / 3) - 1);
var boundingInfo = object.getBoundingInfo();
var dim = Math.min(boundingInfo.boundingBox.extendSizeWorld.x, boundingInfo.boundingBox.extendSizeWorld.y);
var minY = boundingInfo.boundingBox.extendSizeWorld.z;
var elementSize = dim * 2 / arraySize;
for (var i = 0; i < pos.length; i = i + 3) {
var x = Math.round((pos[i + 0]) / elementSize + arraySize / 2);
var z = Math.round(((pos[i + 1]) / elementSize - arraySize / 2) * -1);
var y = -pos[i + 2] + minY;
if (!matrix[x]) {
matrix[x] = [];
}
if (!matrix[x][z]) {
matrix[x][z] = y;
}
matrix[x][z] = Math.max(y, matrix[x][z]);
}
for (var x = 0; x <= arraySize; ++x) {
if (!matrix[x]) {
var loc = 1;
while (!matrix[(x + loc) % arraySize]) {
loc++;
}
matrix[x] = matrix[(x + loc) % arraySize].slice();
//console.log("missing x", x);
}
for (var z = 0; z <= arraySize; ++z) {
if (!matrix[x][z]) {
var loc = 1;
var newValue;
while (newValue === undefined) {
newValue = matrix[x][(z + loc++) % arraySize];
}
matrix[x][z] = newValue;
}
}
}
var shape = new this.BJSCANNON.Heightfield(matrix, {
elementSize: elementSize
});
//For future reference, needed for body transformation
shape.minY = minY;
return shape;
};
CannonJSPlugin.prototype._updatePhysicsBodyTransformation = function (impostor) {
var object = impostor.object;
//make sure it is updated...
object.computeWorldMatrix && object.computeWorldMatrix(true);
// The delta between the mesh position and the mesh bounding box center
var bInfo = object.getBoundingInfo();
if (!bInfo)
return;
var center = impostor.getObjectCenter();
//m.getAbsolutePosition().subtract(m.getBoundingInfo().boundingBox.centerWorld)
this._tmpDeltaPosition.copyFrom(object.getAbsolutePivotPoint().subtract(center));
this._tmpDeltaPosition.divideInPlace(impostor.object.scaling);
this._tmpPosition.copyFrom(center);
var quaternion = object.rotationQuaternion;
if (!quaternion) {
return;
}
//is shape is a plane or a heightmap, it must be rotated 90 degs in the X axis.
if (impostor.type === BABYLON.PhysicsImpostor.PlaneImpostor || impostor.type === BABYLON.PhysicsImpostor.HeightmapImpostor || impostor.type === BABYLON.PhysicsImpostor.CylinderImpostor) {
//-90 DEG in X, precalculated
quaternion = quaternion.multiply(this._minus90X);
//Invert! (Precalculated, 90 deg in X)
//No need to clone. this will never change.
impostor.setDeltaRotation(this._plus90X);
}
//If it is a heightfield, if should be centered.
if (impostor.type === BABYLON.PhysicsImpostor.HeightmapImpostor) {
var mesh = object;
var boundingInfo = mesh.getBoundingInfo();
//calculate the correct body position:
var rotationQuaternion = mesh.rotationQuaternion;
mesh.rotationQuaternion = this._tmpUnityRotation;
mesh.computeWorldMatrix(true);
//get original center with no rotation
var c = center.clone();
var oldPivot = mesh.getPivotMatrix() || BABYLON.Matrix.Translation(0, 0, 0);
//calculate the new center using a pivot (since this.BJSCANNON.js doesn't center height maps)
var p = BABYLON.Matrix.Translation(boundingInfo.boundingBox.extendSizeWorld.x, 0, -boundingInfo.boundingBox.extendSizeWorld.z);
mesh.setPreTransformMatrix(p);
mesh.computeWorldMatrix(true);
//calculate the translation
var translation = boundingInfo.boundingBox.centerWorld.subtract(center).subtract(mesh.position).negate();
this._tmpPosition.copyFromFloats(translation.x, translation.y - boundingInfo.boundingBox.extendSizeWorld.y, translation.z);
//add it inverted to the delta
this._tmpDeltaPosition.copyFrom(boundingInfo.boundingBox.centerWorld.subtract(c));
this._tmpDeltaPosition.y += boundingInfo.boundingBox.extendSizeWorld.y;
//rotation is back
mesh.rotationQuaternion = rotationQuaternion;
mesh.setPreTransformMatrix(oldPivot);
mesh.computeWorldMatrix(true);
}
else if (impostor.type === BABYLON.PhysicsImpostor.MeshImpostor) {
this._tmpDeltaPosition.copyFromFloats(0, 0, 0);
//this._tmpPosition.copyFrom(object.position);
}
impostor.setDeltaPosition(this._tmpDeltaPosition);
//Now update the impostor object
impostor.physicsBody.position.copy(this._tmpPosition);
impostor.physicsBody.quaternion.copy(quaternion);
};
CannonJSPlugin.prototype.setTransformationFromPhysicsBody = function (impostor) {
impostor.object.position.copyFrom(impostor.physicsBody.position);
if (impostor.object.rotationQuaternion) {
impostor.object.rotationQuaternion.copyFrom(impostor.physicsBody.quaternion);
}
};
CannonJSPlugin.prototype.setPhysicsBodyTransformation = function (impostor, newPosition, newRotation) {
impostor.physicsBody.position.copy(newPosition);
impostor.physicsBody.quaternion.copy(newRotation);
};
CannonJSPlugin.prototype.isSupported = function () {
return this.BJSCANNON !== undefined;
};
CannonJSPlugin.prototype.setLinearVelocity = function (impostor, velocity) {
impostor.physicsBody.velocity.copy(velocity);
};
CannonJSPlugin.prototype.setAngularVelocity = function (impostor, velocity) {
impostor.physicsBody.angularVelocity.copy(velocity);
};
CannonJSPlugin.prototype.getLinearVelocity = function (impostor) {
var v = impostor.physicsBody.velocity;
if (!v) {
return null;
}
return new BABYLON.Vector3(v.x, v.y, v.z);
};
CannonJSPlugin.prototype.getAngularVelocity = function (impostor) {
var v = impostor.physicsBody.angularVelocity;
if (!v) {
return null;
}
return new BABYLON.Vector3(v.x, v.y, v.z);
};
CannonJSPlugin.prototype.setBodyMass = function (impostor, mass) {
impostor.physicsBody.mass = mass;
impostor.physicsBody.updateMassProperties();
};
CannonJSPlugin.prototype.getBodyMass = function (impostor) {
return impostor.physicsBody.mass;
};
CannonJSPlugin.prototype.getBodyFriction = function (impostor) {
return impostor.physicsBody.material.friction;
};
CannonJSPlugin.prototype.setBodyFriction = function (impostor, friction) {
impostor.physicsBody.material.friction = friction;
};
CannonJSPlugin.prototype.getBodyRestitution = function (impostor) {
return impostor.physicsBody.material.restitution;
};
CannonJSPlugin.prototype.setBodyRestitution = function (impostor, restitution) {
impostor.physicsBody.material.restitution = restitution;
};
CannonJSPlugin.prototype.sleepBody = function (impostor) {
impostor.physicsBody.sleep();
};
CannonJSPlugin.prototype.wakeUpBody = function (impostor) {
impostor.physicsBody.wakeUp();
};
CannonJSPlugin.prototype.updateDistanceJoint = function (joint, maxDistance, minDistance) {
joint.physicsJoint.distance = maxDistance;
};
// private enableMotor(joint: IMotorEnabledJoint, motorIndex?: number) {
// if (!motorIndex) {
// joint.physicsJoint.enableMotor();
// }
// }
// private disableMotor(joint: IMotorEnabledJoint, motorIndex?: number) {
// if (!motorIndex) {
// joint.physicsJoint.disableMotor();
// }
// }
CannonJSPlugin.prototype.setMotor = function (joint, speed, maxForce, motorIndex) {
if (!motorIndex) {
joint.physicsJoint.enableMotor();
joint.physicsJoint.setMotorSpeed(speed);
if (maxForce) {
this.setLimit(joint, maxForce);
}
}
};
CannonJSPlugin.prototype.setLimit = function (joint, upperLimit, lowerLimit) {
joint.physicsJoint.motorEquation.maxForce = upperLimit;
joint.physicsJoint.motorEquation.minForce = lowerLimit === void 0 ? -upperLimit : lowerLimit;
};
CannonJSPlugin.prototype.syncMeshWithImpostor = function (mesh, impostor) {
var body = impostor.physicsBody;
mesh.position.x = body.position.x;
mesh.position.y = body.position.y;
mesh.position.z = body.position.z;
if (mesh.rotationQuaternion) {
mesh.rotationQuaternion.x = body.quaternion.x;
mesh.rotationQuaternion.y = body.quaternion.y;
mesh.rotationQuaternion.z = body.quaternion.z;
mesh.rotationQuaternion.w = body.quaternion.w;
}
};
CannonJSPlugin.prototype.getRadius = function (impostor) {
var shape = impostor.physicsBody.shapes[0];
return shape.boundingSphereRadius;
};
CannonJSPlugin.prototype.getBoxSizeToRef = function (impostor, result) {
var shape = impostor.physicsBody.shapes[0];
result.x = shape.halfExtents.x * 2;
result.y = shape.halfExtents.y * 2;
result.z = shape.halfExtents.z * 2;
};
CannonJSPlugin.prototype.dispose = function () {
};
CannonJSPlugin.prototype._extendNamespace = function () {
//this will force cannon to execute at least one step when using interpolation
var step_tmp1 = new this.BJSCANNON.Vec3();
var Engine = this.BJSCANNON;
this.BJSCANNON.World.prototype.step = function (dt, timeSinceLastCalled, maxSubSteps) {
maxSubSteps = maxSubSteps || 10;
timeSinceLastCalled = timeSinceLastCalled || 0;
if (timeSinceLastCalled === 0) {
this.internalStep(dt);
this.time += dt;
}
else {
var internalSteps = Math.floor((this.time + timeSinceLastCalled) / dt) - Math.floor(this.time / dt);
internalSteps = Math.min(internalSteps, maxSubSteps) || 1;
var t0 = performance.now();
for (var i = 0; i !== internalSteps; i++) {
this.internalStep(dt);
if (performance.now() - t0 > dt * 1000) {
break;
}
}
this.time += timeSinceLastCalled;
var h = this.time % dt;
var h_div_dt = h / dt;
var interpvelo = step_tmp1;
var bodies = this.bodies;
for (var j = 0; j !== bodies.length; j++) {
var b = bodies[j];
if (b.type !== Engine.Body.STATIC && b.sleepState !== Engine.Body.SLEEPING) {
b.position.vsub(b.previousPosition, interpvelo);
interpvelo.scale(h_div_dt, interpvelo);
b.position.vadd(interpvelo, b.interpolatedPosition);
}
else {
b.interpolatedPosition.copy(b.position);
b.interpolatedQuaternion.copy(b.quaternion);
}
}
}
};
};
return CannonJSPlugin;
}());
BABYLON.CannonJSPlugin = CannonJSPlugin;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.cannonJSPlugin.js.map
var BABYLON;
(function (BABYLON) {
var OimoJSPlugin = /** @class */ (function () {
function OimoJSPlugin(iterations) {
this.name = "OimoJSPlugin";
this._tmpImpostorsArray = [];
this._tmpPositionVector = BABYLON.Vector3.Zero();
this.BJSOIMO = typeof OIMO !== 'undefined' ? OIMO : (typeof require !== 'undefined' ? require('./Oimo') : undefined);
this.world = new this.BJSOIMO.World(1 / 60, 2, iterations, true);
this.world.worldscale(1);
this.world.clear();
//making sure no stats are calculated
this.world.isNoStat = true;
}
OimoJSPlugin.prototype.setGravity = function (gravity) {
this.world.gravity.copy(gravity);
};
OimoJSPlugin.prototype.setTimeStep = function (timeStep) {
this.world.timeStep = timeStep;
};
OimoJSPlugin.prototype.getTimeStep = function () {
return this.world.timeStep;
};
OimoJSPlugin.prototype.executeStep = function (delta, impostors) {
var _this = this;
impostors.forEach(function (impostor) {
impostor.beforeStep();
});
this.world.step();
impostors.forEach(function (impostor) {
impostor.afterStep();
//update the ordered impostors array
_this._tmpImpostorsArray[impostor.uniqueId] = impostor;
});
//check for collisions
var contact = this.world.contacts;
while (contact !== null) {
if (contact.touching && !contact.body1.sleeping && !contact.body2.sleeping) {
contact = contact.next;
continue;
}
//is this body colliding with any other? get the impostor
var mainImpostor = this._tmpImpostorsArray[+contact.body1.name];
var collidingImpostor = this._tmpImpostorsArray[+contact.body2.name];
if (!mainImpostor || !collidingImpostor) {
contact = contact.next;
continue;
}
mainImpostor.onCollide({ body: collidingImpostor.physicsBody });
collidingImpostor.onCollide({ body: mainImpostor.physicsBody });
contact = contact.next;
}
};
OimoJSPlugin.prototype.applyImpulse = function (impostor, force, contactPoint) {
var mass = impostor.physicsBody.massInfo.mass;
impostor.physicsBody.applyImpulse(contactPoint.scale(this.BJSOIMO.INV_SCALE), force.scale(this.BJSOIMO.INV_SCALE * mass));
};
OimoJSPlugin.prototype.applyForce = function (impostor, force, contactPoint) {
BABYLON.Tools.Warn("Oimo doesn't support applying force. Using impule instead.");
this.applyImpulse(impostor, force, contactPoint);
};
OimoJSPlugin.prototype.generatePhysicsBody = function (impostor) {
var _this = this;
//parent-child relationship. Does this impostor has a parent impostor?
if (impostor.parent) {
if (impostor.physicsBody) {
this.removePhysicsBody(impostor);
//TODO is that needed?
impostor.forceUpdate();
}
return;
}
if (impostor.isBodyInitRequired()) {
var bodyConfig = {
name: impostor.uniqueId,
//Oimo must have mass, also for static objects.
config: [impostor.getParam("mass") || 1, impostor.getParam("friction"), impostor.getParam("restitution")],
size: [],
type: [],
pos: [],
rot: [],
move: impostor.getParam("mass") !== 0,
//Supporting older versions of Oimo
world: this.world
};
var impostors = [impostor];
var addToArray = function (parent) {
if (!parent.getChildMeshes)
return;
parent.getChildMeshes().forEach(function (m) {
if (m.physicsImpostor) {
impostors.push(m.physicsImpostor);
//m.physicsImpostor._init();
}
});
};
addToArray(impostor.object);
var checkWithEpsilon_1 = function (value) {
return Math.max(value, BABYLON.PhysicsEngine.Epsilon);
};
impostors.forEach(function (i) {
if (!impostor.object.rotationQuaternion) {
return;
}
//get the correct bounding box
var oldQuaternion = i.object.rotationQuaternion;
var rot = new _this.BJSOIMO.Euler().setFromQuaternion({
x: impostor.object.rotationQuaternion.x,
y: impostor.object.rotationQuaternion.y,
z: impostor.object.rotationQuaternion.z,
s: impostor.object.rotationQuaternion.w
});
var extendSize = i.getObjectExtendSize();
if (i === impostor) {
var center = impostor.getObjectCenter();
impostor.object.getAbsolutePivotPoint().subtractToRef(center, _this._tmpPositionVector);
_this._tmpPositionVector.divideInPlace(impostor.object.scaling);
//Can also use Array.prototype.push.apply
bodyConfig.pos.push(center.x);
bodyConfig.pos.push(center.y);
bodyConfig.pos.push(center.z);
//tmp solution
bodyConfig.rot.push(rot.x / (_this.BJSOIMO.degtorad || _this.BJSOIMO.TO_RAD));
bodyConfig.rot.push(rot.y / (_this.BJSOIMO.degtorad || _this.BJSOIMO.TO_RAD));
bodyConfig.rot.push(rot.z / (_this.BJSOIMO.degtorad || _this.BJSOIMO.TO_RAD));
}
else {
var localPosition = i.object.getAbsolutePosition().subtract(impostor.object.getAbsolutePosition());
bodyConfig.pos.push(localPosition.x);
bodyConfig.pos.push(localPosition.y);
bodyConfig.pos.push(localPosition.z);
//tmp solution until https://github.com/lo-th/OIMO.js/pull/37 is merged
bodyConfig.rot.push(0);
bodyConfig.rot.push(0);
bodyConfig.rot.push(0);
}
// register mesh
switch (i.type) {
case BABYLON.PhysicsImpostor.ParticleImpostor:
BABYLON.Tools.Warn("No Particle support in this.BJSOIMO.js. using SphereImpostor instead");
case BABYLON.PhysicsImpostor.SphereImpostor:
var radiusX = extendSize.x;
var radiusY = extendSize.y;
var radiusZ = extendSize.z;
var size = Math.max(checkWithEpsilon_1(radiusX), checkWithEpsilon_1(radiusY), checkWithEpsilon_1(radiusZ)) / 2;
bodyConfig.type.push('sphere');
//due to the way oimo works with compounds, add 3 times
bodyConfig.size.push(size);
bodyConfig.size.push(size);
bodyConfig.size.push(size);
break;
case BABYLON.PhysicsImpostor.CylinderImpostor:
var sizeX = checkWithEpsilon_1(extendSize.x) / 2;
var sizeY = checkWithEpsilon_1(extendSize.y);
bodyConfig.type.push('cylinder');
bodyConfig.size.push(sizeX);
bodyConfig.size.push(sizeY);
//due to the way oimo works with compounds, add one more value.
bodyConfig.size.push(sizeY);
break;
case BABYLON.PhysicsImpostor.PlaneImpostor:
case BABYLON.PhysicsImpostor.BoxImpostor:
default:
var sizeX = checkWithEpsilon_1(extendSize.x);
var sizeY = checkWithEpsilon_1(extendSize.y);
var sizeZ = checkWithEpsilon_1(extendSize.z);
bodyConfig.type.push('box');
bodyConfig.size.push(sizeX);
bodyConfig.size.push(sizeY);
bodyConfig.size.push(sizeZ);
break;
}
//actually not needed, but hey...
i.object.rotationQuaternion = oldQuaternion;
});
impostor.physicsBody = new this.BJSOIMO.Body(bodyConfig).body; //this.world.add(bodyConfig);
}
else {
this._tmpPositionVector.copyFromFloats(0, 0, 0);
}
impostor.setDeltaPosition(this._tmpPositionVector);
//this._tmpPositionVector.addInPlace(impostor.mesh.getBoundingInfo().boundingBox.center);
//this.setPhysicsBodyTransformation(impostor, this._tmpPositionVector, impostor.mesh.rotationQuaternion);
};
OimoJSPlugin.prototype.removePhysicsBody = function (impostor) {
//impostor.physicsBody.dispose();
//Same as : (older oimo versions)
this.world.removeRigidBody(impostor.physicsBody);
};
OimoJSPlugin.prototype.generateJoint = function (impostorJoint) {
var mainBody = impostorJoint.mainImpostor.physicsBody;
var connectedBody = impostorJoint.connectedImpostor.physicsBody;
if (!mainBody || !connectedBody) {
return;
}
var jointData = impostorJoint.joint.jointData;
var options = jointData.nativeParams || {};
var type;
var nativeJointData = {
body1: mainBody,
body2: connectedBody,
axe1: options.axe1 || (jointData.mainAxis ? jointData.mainAxis.asArray() : null),
axe2: options.axe2 || (jointData.connectedAxis ? jointData.connectedAxis.asArray() : null),
pos1: options.pos1 || (jointData.mainPivot ? jointData.mainPivot.asArray() : null),
pos2: options.pos2 || (jointData.connectedPivot ? jointData.connectedPivot.asArray() : null),
min: options.min,
max: options.max,
collision: options.collision || jointData.collision,
spring: options.spring,
//supporting older version of Oimo
world: this.world
};
switch (impostorJoint.joint.type) {
case BABYLON.PhysicsJoint.BallAndSocketJoint:
type = "jointBall";
break;
case BABYLON.PhysicsJoint.SpringJoint:
BABYLON.Tools.Warn("this.BJSOIMO.js doesn't support Spring Constraint. Simulating using DistanceJoint instead");
var springData = jointData;
nativeJointData.min = springData.length || nativeJointData.min;
//Max should also be set, just make sure it is at least min
nativeJointData.max = Math.max(nativeJointData.min, nativeJointData.max);
case BABYLON.PhysicsJoint.DistanceJoint:
type = "jointDistance";
nativeJointData.max = jointData.maxDistance;
break;
case BABYLON.PhysicsJoint.PrismaticJoint:
type = "jointPrisme";
break;
case BABYLON.PhysicsJoint.SliderJoint:
type = "jointSlide";
break;
case BABYLON.PhysicsJoint.WheelJoint:
type = "jointWheel";
break;
case BABYLON.PhysicsJoint.HingeJoint:
default:
type = "jointHinge";
break;
}
nativeJointData.type = type;
impostorJoint.joint.physicsJoint = new this.BJSOIMO.Link(nativeJointData).joint; //this.world.add(nativeJointData);
};
OimoJSPlugin.prototype.removeJoint = function (impostorJoint) {
//Bug in Oimo prevents us from disposing a joint in the playground
//joint.joint.physicsJoint.dispose();
//So we will bruteforce it!
try {
this.world.removeJoint(impostorJoint.joint.physicsJoint);
}
catch (e) {
BABYLON.Tools.Warn(e);
}
};
OimoJSPlugin.prototype.isSupported = function () {
return this.BJSOIMO !== undefined;
};
OimoJSPlugin.prototype.setTransformationFromPhysicsBody = function (impostor) {
if (!impostor.physicsBody.sleeping) {
//TODO check that
if (impostor.physicsBody.shapes.next) {
var parentShape = this._getLastShape(impostor.physicsBody);
impostor.object.position.x = parentShape.position.x * this.BJSOIMO.WORLD_SCALE;
impostor.object.position.y = parentShape.position.y * this.BJSOIMO.WORLD_SCALE;
impostor.object.position.z = parentShape.position.z * this.BJSOIMO.WORLD_SCALE;
}
else {
impostor.object.position.copyFrom(impostor.physicsBody.getPosition());
}
if (impostor.object.rotationQuaternion) {
impostor.object.rotationQuaternion.copyFrom(impostor.physicsBody.getQuaternion());
impostor.object.rotationQuaternion.normalize();
}
}
};
OimoJSPlugin.prototype.setPhysicsBodyTransformation = function (impostor, newPosition, newRotation) {
var body = impostor.physicsBody;
body.position.init(newPosition.x * this.BJSOIMO.INV_SCALE, newPosition.y * this.BJSOIMO.INV_SCALE, newPosition.z * this.BJSOIMO.INV_SCALE);
body.orientation.init(newRotation.w, newRotation.x, newRotation.y, newRotation.z);
body.syncShapes();
body.awake();
};
OimoJSPlugin.prototype._getLastShape = function (body) {
var lastShape = body.shapes;
while (lastShape.next) {
lastShape = lastShape.next;
}
return lastShape;
};
OimoJSPlugin.prototype.setLinearVelocity = function (impostor, velocity) {
impostor.physicsBody.linearVelocity.init(velocity.x, velocity.y, velocity.z);
};
OimoJSPlugin.prototype.setAngularVelocity = function (impostor, velocity) {
impostor.physicsBody.angularVelocity.init(velocity.x, velocity.y, velocity.z);
};
OimoJSPlugin.prototype.getLinearVelocity = function (impostor) {
var v = impostor.physicsBody.linearVelocity;
if (!v) {
return null;
}
return new BABYLON.Vector3(v.x, v.y, v.z);
};
OimoJSPlugin.prototype.getAngularVelocity = function (impostor) {
var v = impostor.physicsBody.angularVelocity;
if (!v) {
return null;
}
return new BABYLON.Vector3(v.x, v.y, v.z);
};
OimoJSPlugin.prototype.setBodyMass = function (impostor, mass) {
var staticBody = mass === 0;
//this will actually set the body's density and not its mass.
//But this is how oimo treats the mass variable.
impostor.physicsBody.shapes.density = staticBody ? 1 : mass;
impostor.physicsBody.setupMass(staticBody ? 0x2 : 0x1);
};
OimoJSPlugin.prototype.getBodyMass = function (impostor) {
return impostor.physicsBody.shapes.density;
};
OimoJSPlugin.prototype.getBodyFriction = function (impostor) {
return impostor.physicsBody.shapes.friction;
};
OimoJSPlugin.prototype.setBodyFriction = function (impostor, friction) {
impostor.physicsBody.shapes.friction = friction;
};
OimoJSPlugin.prototype.getBodyRestitution = function (impostor) {
return impostor.physicsBody.shapes.restitution;
};
OimoJSPlugin.prototype.setBodyRestitution = function (impostor, restitution) {
impostor.physicsBody.shapes.restitution = restitution;
};
OimoJSPlugin.prototype.sleepBody = function (impostor) {
impostor.physicsBody.sleep();
};
OimoJSPlugin.prototype.wakeUpBody = function (impostor) {
impostor.physicsBody.awake();
};
OimoJSPlugin.prototype.updateDistanceJoint = function (joint, maxDistance, minDistance) {
joint.physicsJoint.limitMotor.upperLimit = maxDistance;
if (minDistance !== void 0) {
joint.physicsJoint.limitMotor.lowerLimit = minDistance;
}
};
OimoJSPlugin.prototype.setMotor = function (joint, speed, maxForce, motorIndex) {
//TODO separate rotational and transational motors.
var motor = motorIndex ? joint.physicsJoint.rotationalLimitMotor2 : joint.physicsJoint.rotationalLimitMotor1 || joint.physicsJoint.rotationalLimitMotor || joint.physicsJoint.limitMotor;
if (motor) {
motor.setMotor(speed, maxForce);
}
};
OimoJSPlugin.prototype.setLimit = function (joint, upperLimit, lowerLimit, motorIndex) {
//TODO separate rotational and transational motors.
var motor = motorIndex ? joint.physicsJoint.rotationalLimitMotor2 : joint.physicsJoint.rotationalLimitMotor1 || joint.physicsJoint.rotationalLimitMotor || joint.physicsJoint.limitMotor;
if (motor) {
motor.setLimit(upperLimit, lowerLimit === void 0 ? -upperLimit : lowerLimit);
}
};
OimoJSPlugin.prototype.syncMeshWithImpostor = function (mesh, impostor) {
var body = impostor.physicsBody;
mesh.position.x = body.position.x;
mesh.position.y = body.position.y;
mesh.position.z = body.position.z;
if (mesh.rotationQuaternion) {
mesh.rotationQuaternion.x = body.orientation.x;
mesh.rotationQuaternion.y = body.orientation.y;
mesh.rotationQuaternion.z = body.orientation.z;
mesh.rotationQuaternion.w = body.orientation.s;
}
};
OimoJSPlugin.prototype.getRadius = function (impostor) {
return impostor.physicsBody.shapes.radius;
};
OimoJSPlugin.prototype.getBoxSizeToRef = function (impostor, result) {
var shape = impostor.physicsBody.shapes;
result.x = shape.halfWidth * 2;
result.y = shape.halfHeight * 2;
result.z = shape.halfDepth * 2;
};
OimoJSPlugin.prototype.dispose = function () {
this.world.clear();
};
return OimoJSPlugin;
}());
BABYLON.OimoJSPlugin = OimoJSPlugin;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.oimoJSPlugin.js.map
var BABYLON;
(function (BABYLON) {
/*
* Based on jsTGALoader - Javascript loader for TGA file
* By Vincent Thibault
* @blog http://blog.robrowser.com/javascript-tga-loader.html
*/
var TGATools = /** @class */ (function () {
function TGATools() {
}
TGATools.GetTGAHeader = function (data) {
var offset = 0;
var header = {
id_length: data[offset++],
colormap_type: data[offset++],
image_type: data[offset++],
colormap_index: data[offset++] | data[offset++] << 8,
colormap_length: data[offset++] | data[offset++] << 8,
colormap_size: data[offset++],
origin: [
data[offset++] | data[offset++] << 8,
data[offset++] | data[offset++] << 8
],
width: data[offset++] | data[offset++] << 8,
height: data[offset++] | data[offset++] << 8,
pixel_size: data[offset++],
flags: data[offset++]
};
return header;
};
TGATools.UploadContent = function (gl, data) {
// Not enough data to contain header ?
if (data.length < 19) {
BABYLON.Tools.Error("Unable to load TGA file - Not enough data to contain header");
return;
}
// Read Header
var offset = 18;
var header = TGATools.GetTGAHeader(data);
// Assume it's a valid Targa file.
if (header.id_length + offset > data.length) {
BABYLON.Tools.Error("Unable to load TGA file - Not enough data");
return;
}
// Skip not needed data
offset += header.id_length;
var use_rle = false;
var use_pal = false;
var use_grey = false;
// Get some informations.
switch (header.image_type) {
case TGATools._TYPE_RLE_INDEXED:
use_rle = true;
case TGATools._TYPE_INDEXED:
use_pal = true;
break;
case TGATools._TYPE_RLE_RGB:
use_rle = true;
case TGATools._TYPE_RGB:
// use_rgb = true;
break;
case TGATools._TYPE_RLE_GREY:
use_rle = true;
case TGATools._TYPE_GREY:
use_grey = true;
break;
}
var pixel_data;
// var numAlphaBits = header.flags & 0xf;
var pixel_size = header.pixel_size >> 3;
var pixel_total = header.width * header.height * pixel_size;
// Read palettes
var palettes;
if (use_pal) {
palettes = data.subarray(offset, offset += header.colormap_length * (header.colormap_size >> 3));
}
// Read LRE
if (use_rle) {
pixel_data = new Uint8Array(pixel_total);
var c, count, i;
var localOffset = 0;
var pixels = new Uint8Array(pixel_size);
while (offset < pixel_total && localOffset < pixel_total) {
c = data[offset++];
count = (c & 0x7f) + 1;
// RLE pixels
if (c & 0x80) {
// Bind pixel tmp array
for (i = 0; i < pixel_size; ++i) {
pixels[i] = data[offset++];
}
// Copy pixel array
for (i = 0; i < count; ++i) {
pixel_data.set(pixels, localOffset + i * pixel_size);
}
localOffset += pixel_size * count;
}
else {
count *= pixel_size;
for (i = 0; i < count; ++i) {
pixel_data[localOffset + i] = data[offset++];
}
localOffset += count;
}
}
}
else {
pixel_data = data.subarray(offset, offset += (use_pal ? header.width * header.height : pixel_total));
}
// Load to texture
var x_start, y_start, x_step, y_step, y_end, x_end;
switch ((header.flags & TGATools._ORIGIN_MASK) >> TGATools._ORIGIN_SHIFT) {
default:
case TGATools._ORIGIN_UL:
x_start = 0;
x_step = 1;
x_end = header.width;
y_start = 0;
y_step = 1;
y_end = header.height;
break;
case TGATools._ORIGIN_BL:
x_start = 0;
x_step = 1;
x_end = header.width;
y_start = header.height - 1;
y_step = -1;
y_end = -1;
break;
case TGATools._ORIGIN_UR:
x_start = header.width - 1;
x_step = -1;
x_end = -1;
y_start = 0;
y_step = 1;
y_end = header.height;
break;
case TGATools._ORIGIN_BR:
x_start = header.width - 1;
x_step = -1;
x_end = -1;
y_start = header.height - 1;
y_step = -1;
y_end = -1;
break;
}
// Load the specify method
var func = '_getImageData' + (use_grey ? 'Grey' : '') + (header.pixel_size) + 'bits';
var imageData = TGATools[func](header, palettes, pixel_data, y_start, y_step, y_end, x_start, x_step, x_end);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, header.width, header.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, imageData);
};
TGATools._getImageData8bits = function (header, palettes, pixel_data, y_start, y_step, y_end, x_start, x_step, x_end) {
var image = pixel_data, colormap = palettes;
var width = header.width, height = header.height;
var color, i = 0, x, y;
var imageData = new Uint8Array(width * height * 4);
for (y = y_start; y !== y_end; y += y_step) {
for (x = x_start; x !== x_end; x += x_step, i++) {
color = image[i];
imageData[(x + width * y) * 4 + 3] = 255;
imageData[(x + width * y) * 4 + 2] = colormap[(color * 3) + 0];
imageData[(x + width * y) * 4 + 1] = colormap[(color * 3) + 1];
imageData[(x + width * y) * 4 + 0] = colormap[(color * 3) + 2];
}
}
return imageData;
};
TGATools._getImageData16bits = function (header, palettes, pixel_data, y_start, y_step, y_end, x_start, x_step, x_end) {
var image = pixel_data;
var width = header.width, height = header.height;
var color, i = 0, x, y;
var imageData = new Uint8Array(width * height * 4);
for (y = y_start; y !== y_end; y += y_step) {
for (x = x_start; x !== x_end; x += x_step, i += 2) {
color = image[i + 0] + (image[i + 1] << 8); // Inversed ?
var r = (((color & 0x7C00) >> 10) * 255) / 0x1F | 0;
var g = (((color & 0x03E0) >> 5) * 255) / 0x1F | 0;
var b = ((color & 0x001F) * 255) / 0x1F | 0;
imageData[(x + width * y) * 4 + 0] = r;
imageData[(x + width * y) * 4 + 1] = g;
imageData[(x + width * y) * 4 + 2] = b;
imageData[(x + width * y) * 4 + 3] = (color & 0x8000) ? 0 : 255;
}
}
return imageData;
};
TGATools._getImageData24bits = function (header, palettes, pixel_data, y_start, y_step, y_end, x_start, x_step, x_end) {
var image = pixel_data;
var width = header.width, height = header.height;
var i = 0, x, y;
var imageData = new Uint8Array(width * height * 4);
for (y = y_start; y !== y_end; y += y_step) {
for (x = x_start; x !== x_end; x += x_step, i += 3) {
imageData[(x + width * y) * 4 + 3] = 255;
imageData[(x + width * y) * 4 + 2] = image[i + 0];
imageData[(x + width * y) * 4 + 1] = image[i + 1];
imageData[(x + width * y) * 4 + 0] = image[i + 2];
}
}
return imageData;
};
TGATools._getImageData32bits = function (header, palettes, pixel_data, y_start, y_step, y_end, x_start, x_step, x_end) {
var image = pixel_data;
var width = header.width, height = header.height;
var i = 0, x, y;
var imageData = new Uint8Array(width * height * 4);
for (y = y_start; y !== y_end; y += y_step) {
for (x = x_start; x !== x_end; x += x_step, i += 4) {
imageData[(x + width * y) * 4 + 2] = image[i + 0];
imageData[(x + width * y) * 4 + 1] = image[i + 1];
imageData[(x + width * y) * 4 + 0] = image[i + 2];
imageData[(x + width * y) * 4 + 3] = image[i + 3];
}
}
return imageData;
};
TGATools._getImageDataGrey8bits = function (header, palettes, pixel_data, y_start, y_step, y_end, x_start, x_step, x_end) {
var image = pixel_data;
var width = header.width, height = header.height;
var color, i = 0, x, y;
var imageData = new Uint8Array(width * height * 4);
for (y = y_start; y !== y_end; y += y_step) {
for (x = x_start; x !== x_end; x += x_step, i++) {
color = image[i];
imageData[(x + width * y) * 4 + 0] = color;
imageData[(x + width * y) * 4 + 1] = color;
imageData[(x + width * y) * 4 + 2] = color;
imageData[(x + width * y) * 4 + 3] = 255;
}
}
return imageData;
};
TGATools._getImageDataGrey16bits = function (header, palettes, pixel_data, y_start, y_step, y_end, x_start, x_step, x_end) {
var image = pixel_data;
var width = header.width, height = header.height;
var i = 0, x, y;
var imageData = new Uint8Array(width * height * 4);
for (y = y_start; y !== y_end; y += y_step) {
for (x = x_start; x !== x_end; x += x_step, i += 2) {
imageData[(x + width * y) * 4 + 0] = image[i + 0];
imageData[(x + width * y) * 4 + 1] = image[i + 0];
imageData[(x + width * y) * 4 + 2] = image[i + 0];
imageData[(x + width * y) * 4 + 3] = image[i + 1];
}
}
return imageData;
};
//private static _TYPE_NO_DATA = 0;
TGATools._TYPE_INDEXED = 1;
TGATools._TYPE_RGB = 2;
TGATools._TYPE_GREY = 3;
TGATools._TYPE_RLE_INDEXED = 9;
TGATools._TYPE_RLE_RGB = 10;
TGATools._TYPE_RLE_GREY = 11;
TGATools._ORIGIN_MASK = 0x30;
TGATools._ORIGIN_SHIFT = 0x04;
TGATools._ORIGIN_BL = 0x00;
TGATools._ORIGIN_BR = 0x01;
TGATools._ORIGIN_UL = 0x02;
TGATools._ORIGIN_UR = 0x03;
return TGATools;
}());
BABYLON.TGATools = TGATools;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.tga.js.map
var BABYLON;
(function (BABYLON) {
// Based on demo done by Brandon Jones - http://media.tojicode.com/webgl-samples/dds.html
// All values and structures referenced from:
// http://msdn.microsoft.com/en-us/library/bb943991.aspx/
var DDS_MAGIC = 0x20534444;
var
//DDSD_CAPS = 0x1,
//DDSD_HEIGHT = 0x2,
//DDSD_WIDTH = 0x4,
//DDSD_PITCH = 0x8,
//DDSD_PIXELFORMAT = 0x1000,
DDSD_MIPMAPCOUNT = 0x20000;
//DDSD_LINEARSIZE = 0x80000,
//DDSD_DEPTH = 0x800000;
// var DDSCAPS_COMPLEX = 0x8,
// DDSCAPS_MIPMAP = 0x400000,
// DDSCAPS_TEXTURE = 0x1000;
var DDSCAPS2_CUBEMAP = 0x200;
// DDSCAPS2_CUBEMAP_POSITIVEX = 0x400,
// DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800,
// DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000,
// DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000,
// DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000,
// DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000,
// DDSCAPS2_VOLUME = 0x200000;
var
//DDPF_ALPHAPIXELS = 0x1,
//DDPF_ALPHA = 0x2,
DDPF_FOURCC = 0x4, DDPF_RGB = 0x40,
//DDPF_YUV = 0x200,
DDPF_LUMINANCE = 0x20000;
function FourCCToInt32(value) {
return value.charCodeAt(0) +
(value.charCodeAt(1) << 8) +
(value.charCodeAt(2) << 16) +
(value.charCodeAt(3) << 24);
}
function Int32ToFourCC(value) {
return String.fromCharCode(value & 0xff, (value >> 8) & 0xff, (value >> 16) & 0xff, (value >> 24) & 0xff);
}
var FOURCC_DXT1 = FourCCToInt32("DXT1");
var FOURCC_DXT3 = FourCCToInt32("DXT3");
var FOURCC_DXT5 = FourCCToInt32("DXT5");
var FOURCC_DX10 = FourCCToInt32("DX10");
var FOURCC_D3DFMT_R16G16B16A16F = 113;
var FOURCC_D3DFMT_R32G32B32A32F = 116;
var DXGI_FORMAT_R16G16B16A16_FLOAT = 10;
var DXGI_FORMAT_B8G8R8X8_UNORM = 88;
var headerLengthInt = 31; // The header length in 32 bit ints
// Offsets into the header array
var off_magic = 0;
var off_size = 1;
var off_flags = 2;
var off_height = 3;
var off_width = 4;
var off_mipmapCount = 7;
var off_pfFlags = 20;
var off_pfFourCC = 21;
var off_RGBbpp = 22;
var off_RMask = 23;
var off_GMask = 24;
var off_BMask = 25;
var off_AMask = 26;
// var off_caps1 = 27;
var off_caps2 = 28;
// var off_caps3 = 29;
// var off_caps4 = 30;
var off_dxgiFormat = 32;
;
var DDSTools = /** @class */ (function () {
function DDSTools() {
}
DDSTools.GetDDSInfo = function (arrayBuffer) {
var header = new Int32Array(arrayBuffer, 0, headerLengthInt);
var extendedHeader = new Int32Array(arrayBuffer, 0, headerLengthInt + 4);
var mipmapCount = 1;
if (header[off_flags] & DDSD_MIPMAPCOUNT) {
mipmapCount = Math.max(1, header[off_mipmapCount]);
}
var fourCC = header[off_pfFourCC];
var dxgiFormat = (fourCC === FOURCC_DX10) ? extendedHeader[off_dxgiFormat] : 0;
var textureType = BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT;
switch (fourCC) {
case FOURCC_D3DFMT_R16G16B16A16F:
textureType = BABYLON.Engine.TEXTURETYPE_HALF_FLOAT;
break;
case FOURCC_D3DFMT_R32G32B32A32F:
textureType = BABYLON.Engine.TEXTURETYPE_FLOAT;
break;
case FOURCC_DX10:
if (dxgiFormat === DXGI_FORMAT_R16G16B16A16_FLOAT) {
textureType = BABYLON.Engine.TEXTURETYPE_HALF_FLOAT;
break;
}
}
return {
width: header[off_width],
height: header[off_height],
mipmapCount: mipmapCount,
isFourCC: (header[off_pfFlags] & DDPF_FOURCC) === DDPF_FOURCC,
isRGB: (header[off_pfFlags] & DDPF_RGB) === DDPF_RGB,
isLuminance: (header[off_pfFlags] & DDPF_LUMINANCE) === DDPF_LUMINANCE,
isCube: (header[off_caps2] & DDSCAPS2_CUBEMAP) === DDSCAPS2_CUBEMAP,
isCompressed: (fourCC === FOURCC_DXT1 || fourCC === FOURCC_DXT3 || fourCC === FOURCC_DXT5),
dxgiFormat: dxgiFormat,
textureType: textureType
};
};
DDSTools._ToHalfFloat = function (value) {
if (!DDSTools._FloatView) {
DDSTools._FloatView = new Float32Array(1);
DDSTools._Int32View = new Int32Array(DDSTools._FloatView.buffer);
}
DDSTools._FloatView[0] = value;
var x = DDSTools._Int32View[0];
var bits = (x >> 16) & 0x8000; /* Get the sign */
var m = (x >> 12) & 0x07ff; /* Keep one extra bit for rounding */
var e = (x >> 23) & 0xff; /* Using int is faster here */
/* If zero, or denormal, or exponent underflows too much for a denormal
* half, return signed zero. */
if (e < 103) {
return bits;
}
/* If NaN, return NaN. If Inf or exponent overflow, return Inf. */
if (e > 142) {
bits |= 0x7c00;
/* If exponent was 0xff and one mantissa bit was set, it means NaN,
* not Inf, so make sure we set one mantissa bit too. */
bits |= ((e == 255) ? 0 : 1) && (x & 0x007fffff);
return bits;
}
/* If exponent underflows but not too much, return a denormal */
if (e < 113) {
m |= 0x0800;
/* Extra rounding may overflow and set mantissa to 0 and exponent
* to 1, which is OK. */
bits |= (m >> (114 - e)) + ((m >> (113 - e)) & 1);
return bits;
}
bits |= ((e - 112) << 10) | (m >> 1);
bits += m & 1;
return bits;
};
DDSTools._FromHalfFloat = function (value) {
var s = (value & 0x8000) >> 15;
var e = (value & 0x7C00) >> 10;
var f = value & 0x03FF;
if (e === 0) {
return (s ? -1 : 1) * Math.pow(2, -14) * (f / Math.pow(2, 10));
}
else if (e == 0x1F) {
return f ? NaN : ((s ? -1 : 1) * Infinity);
}
return (s ? -1 : 1) * Math.pow(2, e - 15) * (1 + (f / Math.pow(2, 10)));
};
DDSTools._GetHalfFloatAsFloatRGBAArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer, lod) {
var destArray = new Float32Array(dataLength);
var srcData = new Uint16Array(arrayBuffer, dataOffset);
var index = 0;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var srcPos = (x + y * width) * 4;
destArray[index] = DDSTools._FromHalfFloat(srcData[srcPos]);
destArray[index + 1] = DDSTools._FromHalfFloat(srcData[srcPos + 1]);
destArray[index + 2] = DDSTools._FromHalfFloat(srcData[srcPos + 2]);
if (DDSTools.StoreLODInAlphaChannel) {
destArray[index + 3] = lod;
}
else {
destArray[index + 3] = DDSTools._FromHalfFloat(srcData[srcPos + 3]);
}
index += 4;
}
}
return destArray;
};
DDSTools._GetHalfFloatRGBAArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer, lod) {
if (DDSTools.StoreLODInAlphaChannel) {
var destArray = new Uint16Array(dataLength);
var srcData = new Uint16Array(arrayBuffer, dataOffset);
var index = 0;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var srcPos = (x + y * width) * 4;
destArray[index] = srcData[srcPos];
destArray[index + 1] = srcData[srcPos + 1];
destArray[index + 2] = srcData[srcPos + 2];
destArray[index + 3] = DDSTools._ToHalfFloat(lod);
index += 4;
}
}
return destArray;
}
return new Uint16Array(arrayBuffer, dataOffset, dataLength);
};
DDSTools._GetFloatRGBAArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer, lod) {
if (DDSTools.StoreLODInAlphaChannel) {
var destArray = new Float32Array(dataLength);
var srcData = new Float32Array(arrayBuffer, dataOffset);
var index = 0;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var srcPos = (x + y * width) * 4;
destArray[index] = srcData[srcPos];
destArray[index + 1] = srcData[srcPos + 1];
destArray[index + 2] = srcData[srcPos + 2];
destArray[index + 3] = lod;
index += 4;
}
}
return destArray;
}
return new Float32Array(arrayBuffer, dataOffset, dataLength);
};
DDSTools._GetFloatAsUIntRGBAArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer, lod) {
var destArray = new Uint8Array(dataLength);
var srcData = new Float32Array(arrayBuffer, dataOffset);
var index = 0;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var srcPos = (x + y * width) * 4;
destArray[index] = BABYLON.Scalar.Clamp(srcData[srcPos]) * 255;
destArray[index + 1] = BABYLON.Scalar.Clamp(srcData[srcPos + 1]) * 255;
destArray[index + 2] = BABYLON.Scalar.Clamp(srcData[srcPos + 2]) * 255;
if (DDSTools.StoreLODInAlphaChannel) {
destArray[index + 3] = lod;
}
else {
destArray[index + 3] = BABYLON.Scalar.Clamp(srcData[srcPos + 3]) * 255;
}
index += 4;
}
}
return destArray;
};
DDSTools._GetHalfFloatAsUIntRGBAArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer, lod) {
var destArray = new Uint8Array(dataLength);
var srcData = new Uint16Array(arrayBuffer, dataOffset);
var index = 0;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var srcPos = (x + y * width) * 4;
destArray[index] = BABYLON.Scalar.Clamp(DDSTools._FromHalfFloat(srcData[srcPos])) * 255;
destArray[index + 1] = BABYLON.Scalar.Clamp(DDSTools._FromHalfFloat(srcData[srcPos + 1])) * 255;
destArray[index + 2] = BABYLON.Scalar.Clamp(DDSTools._FromHalfFloat(srcData[srcPos + 2])) * 255;
if (DDSTools.StoreLODInAlphaChannel) {
destArray[index + 3] = lod;
}
else {
destArray[index + 3] = BABYLON.Scalar.Clamp(DDSTools._FromHalfFloat(srcData[srcPos + 3])) * 255;
}
index += 4;
}
}
return destArray;
};
DDSTools._GetRGBAArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer, rOffset, gOffset, bOffset, aOffset) {
var byteArray = new Uint8Array(dataLength);
var srcData = new Uint8Array(arrayBuffer, dataOffset);
var index = 0;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var srcPos = (x + y * width) * 4;
byteArray[index] = srcData[srcPos + rOffset];
byteArray[index + 1] = srcData[srcPos + gOffset];
byteArray[index + 2] = srcData[srcPos + bOffset];
byteArray[index + 3] = srcData[srcPos + aOffset];
index += 4;
}
}
return byteArray;
};
DDSTools._ExtractLongWordOrder = function (value) {
if (value === 0 || value === 255 || value === -16777216) {
return 0;
}
return 1 + DDSTools._ExtractLongWordOrder(value >> 8);
};
DDSTools._GetRGBArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer, rOffset, gOffset, bOffset) {
var byteArray = new Uint8Array(dataLength);
var srcData = new Uint8Array(arrayBuffer, dataOffset);
var index = 0;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var srcPos = (x + y * width) * 3;
byteArray[index] = srcData[srcPos + rOffset];
byteArray[index + 1] = srcData[srcPos + gOffset];
byteArray[index + 2] = srcData[srcPos + bOffset];
index += 3;
}
}
return byteArray;
};
DDSTools._GetLuminanceArrayBuffer = function (width, height, dataOffset, dataLength, arrayBuffer) {
var byteArray = new Uint8Array(dataLength);
var srcData = new Uint8Array(arrayBuffer, dataOffset);
var index = 0;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var srcPos = (x + y * width);
byteArray[index] = srcData[srcPos];
index++;
}
}
return byteArray;
};
DDSTools.UploadDDSLevels = function (engine, gl, arrayBuffer, info, loadMipmaps, faces, lodIndex, currentFace) {
if (lodIndex === void 0) { lodIndex = -1; }
var ext = engine.getCaps().s3tc;
var header = new Int32Array(arrayBuffer, 0, headerLengthInt);
var fourCC, width, height, dataLength = 0, dataOffset;
var byteArray, mipmapCount, mip;
var internalFormat = 0;
var format = 0;
var blockBytes = 1;
if (header[off_magic] !== DDS_MAGIC) {
BABYLON.Tools.Error("Invalid magic number in DDS header");
return;
}
if (!info.isFourCC && !info.isRGB && !info.isLuminance) {
BABYLON.Tools.Error("Unsupported format, must contain a FourCC, RGB or LUMINANCE code");
return;
}
if (info.isCompressed && !ext) {
BABYLON.Tools.Error("Compressed textures are not supported on this platform.");
return;
}
var bpp = header[off_RGBbpp];
dataOffset = header[off_size] + 4;
var computeFormats = false;
if (info.isFourCC) {
fourCC = header[off_pfFourCC];
switch (fourCC) {
case FOURCC_DXT1:
blockBytes = 8;
internalFormat = ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
break;
case FOURCC_DXT3:
blockBytes = 16;
internalFormat = ext.COMPRESSED_RGBA_S3TC_DXT3_EXT;
break;
case FOURCC_DXT5:
blockBytes = 16;
internalFormat = ext.COMPRESSED_RGBA_S3TC_DXT5_EXT;
break;
case FOURCC_D3DFMT_R16G16B16A16F:
computeFormats = true;
break;
case FOURCC_D3DFMT_R32G32B32A32F:
computeFormats = true;
break;
case FOURCC_DX10:
// There is an additionnal header so dataOffset need to be changed
dataOffset += 5 * 4; // 5 uints
var supported = false;
switch (info.dxgiFormat) {
case DXGI_FORMAT_R16G16B16A16_FLOAT:
computeFormats = true;
supported = true;
break;
case DXGI_FORMAT_B8G8R8X8_UNORM:
info.isRGB = true;
info.isFourCC = false;
bpp = 32;
supported = true;
break;
}
if (supported) {
break;
}
default:
console.error("Unsupported FourCC code:", Int32ToFourCC(fourCC));
return;
}
}
var rOffset = DDSTools._ExtractLongWordOrder(header[off_RMask]);
var gOffset = DDSTools._ExtractLongWordOrder(header[off_GMask]);
var bOffset = DDSTools._ExtractLongWordOrder(header[off_BMask]);
var aOffset = DDSTools._ExtractLongWordOrder(header[off_AMask]);
if (computeFormats) {
format = engine._getWebGLTextureType(info.textureType);
internalFormat = engine._getRGBABufferInternalSizedFormat(info.textureType);
}
mipmapCount = 1;
if (header[off_flags] & DDSD_MIPMAPCOUNT && loadMipmaps !== false) {
mipmapCount = Math.max(1, header[off_mipmapCount]);
}
for (var face = 0; face < faces; face++) {
var sampler = faces === 1 ? gl.TEXTURE_2D : (gl.TEXTURE_CUBE_MAP_POSITIVE_X + face + (currentFace ? currentFace : 0));
width = header[off_width];
height = header[off_height];
for (mip = 0; mip < mipmapCount; ++mip) {
if (lodIndex === -1 || lodIndex === mip) {
// In case of fixed LOD, if the lod has just been uploaded, early exit.
var i = (lodIndex === -1) ? mip : 0;
if (!info.isCompressed && info.isFourCC) {
dataLength = width * height * 4;
var floatArray = null;
if (engine.badOS || engine.badDesktopOS || (!engine.getCaps().textureHalfFloat && !engine.getCaps().textureFloat)) {
if (bpp === 128) {
floatArray = DDSTools._GetFloatAsUIntRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, i);
}
else if (bpp === 64) {
floatArray = DDSTools._GetHalfFloatAsUIntRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, i);
}
info.textureType = BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT;
format = engine._getWebGLTextureType(info.textureType);
internalFormat = engine._getRGBABufferInternalSizedFormat(info.textureType);
}
else {
if (bpp === 128) {
floatArray = DDSTools._GetFloatRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, i);
}
else if (bpp === 64 && !engine.getCaps().textureHalfFloat) {
floatArray = DDSTools._GetHalfFloatAsFloatRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, i);
info.textureType = BABYLON.Engine.TEXTURETYPE_FLOAT;
format = engine._getWebGLTextureType(info.textureType);
internalFormat = engine._getRGBABufferInternalSizedFormat(info.textureType);
}
else {
floatArray = DDSTools._GetHalfFloatRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, i);
}
}
if (floatArray) {
engine._uploadDataToTexture(sampler, i, internalFormat, width, height, gl.RGBA, format, floatArray);
}
}
else if (info.isRGB) {
if (bpp === 24) {
dataLength = width * height * 3;
byteArray = DDSTools._GetRGBArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, rOffset, gOffset, bOffset);
engine._uploadDataToTexture(sampler, i, gl.RGB, width, height, gl.RGB, gl.UNSIGNED_BYTE, byteArray);
}
else {
dataLength = width * height * 4;
byteArray = DDSTools._GetRGBAArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer, rOffset, gOffset, bOffset, aOffset);
engine._uploadDataToTexture(sampler, i, gl.RGBA, width, height, gl.RGBA, gl.UNSIGNED_BYTE, byteArray);
}
}
else if (info.isLuminance) {
var unpackAlignment = gl.getParameter(gl.UNPACK_ALIGNMENT);
var unpaddedRowSize = width;
var paddedRowSize = Math.floor((width + unpackAlignment - 1) / unpackAlignment) * unpackAlignment;
dataLength = paddedRowSize * (height - 1) + unpaddedRowSize;
byteArray = DDSTools._GetLuminanceArrayBuffer(width, height, dataOffset, dataLength, arrayBuffer);
engine._uploadDataToTexture(sampler, i, gl.LUMINANCE, width, height, gl.LUMINANCE, gl.UNSIGNED_BYTE, byteArray);
}
else {
dataLength = Math.max(4, width) / 4 * Math.max(4, height) / 4 * blockBytes;
byteArray = new Uint8Array(arrayBuffer, dataOffset, dataLength);
engine._uploadCompressedDataToTexture(sampler, i, internalFormat, width, height, byteArray);
}
}
dataOffset += bpp ? (width * height * (bpp / 8)) : dataLength;
width *= 0.5;
height *= 0.5;
width = Math.max(1.0, width);
height = Math.max(1.0, height);
}
if (currentFace !== undefined) {
// Loading a single face
break;
}
}
};
DDSTools.StoreLODInAlphaChannel = false;
return DDSTools;
}());
BABYLON.DDSTools = DDSTools;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.dds.js.map
var BABYLON;
(function (BABYLON) {
/**
* for description see https://www.khronos.org/opengles/sdk/tools/KTX/
* for file layout see https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/
*/
var KhronosTextureContainer = /** @class */ (function () {
/**
* @param {ArrayBuffer} arrayBuffer- contents of the KTX container file
* @param {number} facesExpected- should be either 1 or 6, based whether a cube texture or or
* @param {boolean} threeDExpected- provision for indicating that data should be a 3D texture, not implemented
* @param {boolean} textureArrayExpected- provision for indicating that data should be a texture array, not implemented
*/
function KhronosTextureContainer(arrayBuffer, facesExpected, threeDExpected, textureArrayExpected) {
this.arrayBuffer = arrayBuffer;
// Test that it is a ktx formatted file, based on the first 12 bytes, character representation is:
// '�', 'K', 'T', 'X', ' ', '1', '1', '�', '\r', '\n', '\x1A', '\n'
// 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A
var identifier = new Uint8Array(this.arrayBuffer, 0, 12);
if (identifier[0] !== 0xAB || identifier[1] !== 0x4B || identifier[2] !== 0x54 || identifier[3] !== 0x58 || identifier[4] !== 0x20 || identifier[5] !== 0x31 ||
identifier[6] !== 0x31 || identifier[7] !== 0xBB || identifier[8] !== 0x0D || identifier[9] !== 0x0A || identifier[10] !== 0x1A || identifier[11] !== 0x0A) {
BABYLON.Tools.Error("texture missing KTX identifier");
return;
}
// load the reset of the header in native 32 bit int
var header = new Int32Array(this.arrayBuffer, 12, 13);
// determine of the remaining header values are recorded in the opposite endianness & require conversion
var oppositeEndianess = header[0] === 0x01020304;
// read all the header elements in order they exist in the file, without modification (sans endainness)
this.glType = oppositeEndianess ? this.switchEndainness(header[1]) : header[1]; // must be 0 for compressed textures
this.glTypeSize = oppositeEndianess ? this.switchEndainness(header[2]) : header[2]; // must be 1 for compressed textures
this.glFormat = oppositeEndianess ? this.switchEndainness(header[3]) : header[3]; // must be 0 for compressed textures
this.glInternalFormat = oppositeEndianess ? this.switchEndainness(header[4]) : header[4]; // the value of arg passed to gl.compressedTexImage2D(,,x,,,,)
this.glBaseInternalFormat = oppositeEndianess ? this.switchEndainness(header[5]) : header[5]; // specify GL_RGB, GL_RGBA, GL_ALPHA, etc (un-compressed only)
this.pixelWidth = oppositeEndianess ? this.switchEndainness(header[6]) : header[6]; // level 0 value of arg passed to gl.compressedTexImage2D(,,,x,,,)
this.pixelHeight = oppositeEndianess ? this.switchEndainness(header[7]) : header[7]; // level 0 value of arg passed to gl.compressedTexImage2D(,,,,x,,)
this.pixelDepth = oppositeEndianess ? this.switchEndainness(header[8]) : header[8]; // level 0 value of arg passed to gl.compressedTexImage3D(,,,,,x,,)
this.numberOfArrayElements = oppositeEndianess ? this.switchEndainness(header[9]) : header[9]; // used for texture arrays
this.numberOfFaces = oppositeEndianess ? this.switchEndainness(header[10]) : header[10]; // used for cubemap textures, should either be 1 or 6
this.numberOfMipmapLevels = oppositeEndianess ? this.switchEndainness(header[11]) : header[11]; // number of levels; disregard possibility of 0 for compressed textures
this.bytesOfKeyValueData = oppositeEndianess ? this.switchEndainness(header[12]) : header[12]; // the amount of space after the header for meta-data
// Make sure we have a compressed type. Not only reduces work, but probably better to let dev know they are not compressing.
if (this.glType !== 0) {
BABYLON.Tools.Error("only compressed formats currently supported");
return;
}
else {
// value of zero is an indication to generate mipmaps @ runtime. Not usually allowed for compressed, so disregard.
this.numberOfMipmapLevels = Math.max(1, this.numberOfMipmapLevels);
}
if (this.pixelHeight === 0 || this.pixelDepth !== 0) {
BABYLON.Tools.Error("only 2D textures currently supported");
return;
}
if (this.numberOfArrayElements !== 0) {
BABYLON.Tools.Error("texture arrays not currently supported");
return;
}
if (this.numberOfFaces !== facesExpected) {
BABYLON.Tools.Error("number of faces expected" + facesExpected + ", but found " + this.numberOfFaces);
return;
}
// we now have a completely validated file, so could use existence of loadType as success
// would need to make this more elaborate & adjust checks above to support more than one load type
this.loadType = KhronosTextureContainer.COMPRESSED_2D;
}
// not as fast hardware based, but will probably never need to use
KhronosTextureContainer.prototype.switchEndainness = function (val) {
return ((val & 0xFF) << 24)
| ((val & 0xFF00) << 8)
| ((val >> 8) & 0xFF00)
| ((val >> 24) & 0xFF);
};
/**
* It is assumed that the texture has already been created & is currently bound
*/
KhronosTextureContainer.prototype.uploadLevels = function (gl, loadMipmaps) {
switch (this.loadType) {
case KhronosTextureContainer.COMPRESSED_2D:
this._upload2DCompressedLevels(gl, loadMipmaps);
break;
case KhronosTextureContainer.TEX_2D:
case KhronosTextureContainer.COMPRESSED_3D:
case KhronosTextureContainer.TEX_3D:
}
};
KhronosTextureContainer.prototype._upload2DCompressedLevels = function (gl, loadMipmaps) {
// initialize width & height for level 1
var dataOffset = KhronosTextureContainer.HEADER_LEN + this.bytesOfKeyValueData;
var width = this.pixelWidth;
var height = this.pixelHeight;
var mipmapCount = loadMipmaps ? this.numberOfMipmapLevels : 1;
for (var level = 0; level < mipmapCount; level++) {
var imageSize = new Int32Array(this.arrayBuffer, dataOffset, 1)[0]; // size per face, since not supporting array cubemaps
for (var face = 0; face < this.numberOfFaces; face++) {
var sampler = this.numberOfFaces === 1 ? gl.TEXTURE_2D : (gl.TEXTURE_CUBE_MAP_POSITIVE_X + face);
var byteArray = new Uint8Array(this.arrayBuffer, dataOffset + 4, imageSize);
gl.compressedTexImage2D(sampler, level, this.glInternalFormat, width, height, 0, byteArray);
dataOffset += imageSize + 4; // size of the image + 4 for the imageSize field
dataOffset += 3 - ((imageSize + 3) % 4); // add padding for odd sized image
}
width = Math.max(1.0, width * 0.5);
height = Math.max(1.0, height * 0.5);
}
};
KhronosTextureContainer.HEADER_LEN = 12 + (13 * 4); // identifier + header elements (not including key value meta-data pairs)
// load types
KhronosTextureContainer.COMPRESSED_2D = 0; // uses a gl.compressedTexImage2D()
KhronosTextureContainer.COMPRESSED_3D = 1; // uses a gl.compressedTexImage3D()
KhronosTextureContainer.TEX_2D = 2; // uses a gl.texImage2D()
KhronosTextureContainer.TEX_3D = 3; // uses a gl.texImage3D()
return KhronosTextureContainer;
}());
BABYLON.KhronosTextureContainer = KhronosTextureContainer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.khronosTextureContainer.js.map
var BABYLON;
(function (BABYLON) {
var Debug = /** @class */ (function () {
function Debug() {
}
Debug.AxesViewer = /** @class */ (function () {
function AxesViewer(scene, scaleLines) {
if (scaleLines === void 0) { scaleLines = 1; }
this._xline = [BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero()];
this._yline = [BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero()];
this._zline = [BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero()];
this.scaleLines = 1;
this.scaleLines = scaleLines;
this._xmesh = BABYLON.Mesh.CreateLines("xline", this._xline, scene, true);
this._ymesh = BABYLON.Mesh.CreateLines("yline", this._yline, scene, true);
this._zmesh = BABYLON.Mesh.CreateLines("zline", this._zline, scene, true);
this._xmesh.renderingGroupId = 2;
this._ymesh.renderingGroupId = 2;
this._zmesh.renderingGroupId = 2;
this._xmesh.material.checkReadyOnlyOnce = true;
this._xmesh.color = new BABYLON.Color3(1, 0, 0);
this._ymesh.material.checkReadyOnlyOnce = true;
this._ymesh.color = new BABYLON.Color3(0, 1, 0);
this._zmesh.material.checkReadyOnlyOnce = true;
this._zmesh.color = new BABYLON.Color3(0, 0, 1);
this.scene = scene;
}
AxesViewer.prototype.update = function (position, xaxis, yaxis, zaxis) {
var scaleLines = this.scaleLines;
if (this._xmesh) {
this._xmesh.position.copyFrom(position);
}
if (this._ymesh) {
this._ymesh.position.copyFrom(position);
}
if (this._zmesh) {
this._zmesh.position.copyFrom(position);
}
var point2 = this._xline[1];
point2.x = xaxis.x * scaleLines;
point2.y = xaxis.y * scaleLines;
point2.z = xaxis.z * scaleLines;
BABYLON.Mesh.CreateLines("", this._xline, null, false, this._xmesh);
point2 = this._yline[1];
point2.x = yaxis.x * scaleLines;
point2.y = yaxis.y * scaleLines;
point2.z = yaxis.z * scaleLines;
BABYLON.Mesh.CreateLines("", this._yline, null, false, this._ymesh);
point2 = this._zline[1];
point2.x = zaxis.x * scaleLines;
point2.y = zaxis.y * scaleLines;
point2.z = zaxis.z * scaleLines;
BABYLON.Mesh.CreateLines("", this._zline, null, false, this._zmesh);
};
AxesViewer.prototype.dispose = function () {
if (this._xmesh) {
this._xmesh.dispose();
}
if (this._ymesh) {
this._ymesh.dispose();
}
if (this._zmesh) {
this._zmesh.dispose();
}
this._xmesh = null;
this._ymesh = null;
this._zmesh = null;
this.scene = null;
};
return AxesViewer;
}());
Debug.BoneAxesViewer = /** @class */ (function (_super) {
__extends(BoneAxesViewer, _super);
function BoneAxesViewer(scene, bone, mesh, scaleLines) {
if (scaleLines === void 0) { scaleLines = 1; }
var _this = _super.call(this, scene, scaleLines) || this;
_this.pos = BABYLON.Vector3.Zero();
_this.xaxis = BABYLON.Vector3.Zero();
_this.yaxis = BABYLON.Vector3.Zero();
_this.zaxis = BABYLON.Vector3.Zero();
_this.mesh = mesh;
_this.bone = bone;
return _this;
}
BoneAxesViewer.prototype.update = function () {
if (!this.mesh || !this.bone) {
return;
}
var bone = this.bone;
bone.getAbsolutePositionToRef(this.mesh, this.pos);
bone.getDirectionToRef(BABYLON.Axis.X, this.mesh, this.xaxis);
bone.getDirectionToRef(BABYLON.Axis.Y, this.mesh, this.yaxis);
bone.getDirectionToRef(BABYLON.Axis.Z, this.mesh, this.zaxis);
_super.prototype.update.call(this, this.pos, this.xaxis, this.yaxis, this.zaxis);
};
BoneAxesViewer.prototype.dispose = function () {
if (this.mesh) {
this.mesh = null;
this.bone = null;
_super.prototype.dispose.call(this);
}
};
return BoneAxesViewer;
}(Debug.AxesViewer));
Debug.PhysicsViewer = /** @class */ (function () {
function PhysicsViewer(scene) {
this._impostors = [];
this._meshes = [];
this._numMeshes = 0;
this._scene = scene || BABYLON.Engine.LastCreatedScene;
var physicEngine = this._scene.getPhysicsEngine();
if (physicEngine) {
this._physicsEnginePlugin = physicEngine.getPhysicsPlugin();
}
}
PhysicsViewer.prototype._updateDebugMeshes = function () {
var plugin = this._physicsEnginePlugin;
for (var i = 0; i < this._numMeshes; i++) {
var impostor = this._impostors[i];
if (!impostor) {
continue;
}
if (impostor.isDisposed) {
this.hideImpostor(this._impostors[i--]);
}
else {
var mesh = this._meshes[i];
if (mesh && plugin) {
plugin.syncMeshWithImpostor(mesh, impostor);
}
}
}
};
PhysicsViewer.prototype.showImpostor = function (impostor) {
if (!this._scene) {
return;
}
for (var i = 0; i < this._numMeshes; i++) {
if (this._impostors[i] == impostor) {
return;
}
}
var debugMesh = this._getDebugMesh(impostor, this._scene);
if (debugMesh) {
this._impostors[this._numMeshes] = impostor;
this._meshes[this._numMeshes] = debugMesh;
if (this._numMeshes === 0) {
this._renderFunction = this._updateDebugMeshes.bind(this);
this._scene.registerBeforeRender(this._renderFunction);
}
this._numMeshes++;
}
};
PhysicsViewer.prototype.hideImpostor = function (impostor) {
if (!impostor || !this._scene) {
return;
}
var removed = false;
for (var i = 0; i < this._numMeshes; i++) {
if (this._impostors[i] == impostor) {
var mesh = this._meshes[i];
if (!mesh) {
continue;
}
this._scene.removeMesh(mesh);
mesh.dispose();
this._numMeshes--;
if (this._numMeshes > 0) {
this._meshes[i] = this._meshes[this._numMeshes];
this._impostors[i] = this._impostors[this._numMeshes];
this._meshes[this._numMeshes] = null;
this._impostors[this._numMeshes] = null;
}
else {
this._meshes[0] = null;
this._impostors[0] = null;
}
removed = true;
break;
}
}
if (removed && this._numMeshes === 0) {
this._scene.unregisterBeforeRender(this._renderFunction);
}
};
PhysicsViewer.prototype._getDebugMaterial = function (scene) {
if (!this._debugMaterial) {
this._debugMaterial = new BABYLON.StandardMaterial('', scene);
this._debugMaterial.wireframe = true;
}
return this._debugMaterial;
};
PhysicsViewer.prototype._getDebugBoxMesh = function (scene) {
if (!this._debugBoxMesh) {
this._debugBoxMesh = BABYLON.MeshBuilder.CreateBox('physicsBodyBoxViewMesh', { size: 1 }, scene);
this._debugBoxMesh.renderingGroupId = 1;
this._debugBoxMesh.rotationQuaternion = BABYLON.Quaternion.Identity();
this._debugBoxMesh.material = this._getDebugMaterial(scene);
scene.removeMesh(this._debugBoxMesh);
}
return this._debugBoxMesh.createInstance('physicsBodyBoxViewInstance');
};
PhysicsViewer.prototype._getDebugSphereMesh = function (scene) {
if (!this._debugSphereMesh) {
this._debugSphereMesh = BABYLON.MeshBuilder.CreateSphere('physicsBodySphereViewMesh', { diameter: 1 }, scene);
this._debugSphereMesh.renderingGroupId = 1;
this._debugSphereMesh.rotationQuaternion = BABYLON.Quaternion.Identity();
this._debugSphereMesh.material = this._getDebugMaterial(scene);
scene.removeMesh(this._debugSphereMesh);
}
return this._debugSphereMesh.createInstance('physicsBodyBoxViewInstance');
};
PhysicsViewer.prototype._getDebugMesh = function (impostor, scene) {
var mesh = null;
if (impostor.type == BABYLON.PhysicsImpostor.BoxImpostor) {
mesh = this._getDebugBoxMesh(scene);
impostor.getBoxSizeToRef(mesh.scaling);
}
else if (impostor.type == BABYLON.PhysicsImpostor.SphereImpostor) {
mesh = this._getDebugSphereMesh(scene);
var radius = impostor.getRadius();
mesh.scaling.x = radius * 2;
mesh.scaling.y = radius * 2;
mesh.scaling.z = radius * 2;
}
return mesh;
};
PhysicsViewer.prototype.dispose = function () {
for (var i = 0; i < this._numMeshes; i++) {
this.hideImpostor(this._impostors[i]);
}
if (this._debugBoxMesh) {
this._debugBoxMesh.dispose();
}
if (this._debugSphereMesh) {
this._debugSphereMesh.dispose();
}
if (this._debugMaterial) {
this._debugMaterial.dispose();
}
this._impostors.length = 0;
this._scene = null;
this._physicsEnginePlugin = null;
};
return PhysicsViewer;
}());
Debug.SkeletonViewer = /** @class */ (function () {
function SkeletonViewer(skeleton, mesh, scene, autoUpdateBonesMatrices, renderingGroupId) {
if (autoUpdateBonesMatrices === void 0) { autoUpdateBonesMatrices = true; }
if (renderingGroupId === void 0) { renderingGroupId = 1; }
this.skeleton = skeleton;
this.mesh = mesh;
this.autoUpdateBonesMatrices = autoUpdateBonesMatrices;
this.renderingGroupId = renderingGroupId;
this.color = BABYLON.Color3.White();
this._debugLines = new Array();
this._isEnabled = false;
this._scene = scene;
this.update();
this._renderFunction = this.update.bind(this);
}
Object.defineProperty(SkeletonViewer.prototype, "isEnabled", {
get: function () {
return this._isEnabled;
},
set: function (value) {
if (this._isEnabled === value) {
return;
}
this._isEnabled = value;
if (value) {
this._scene.registerBeforeRender(this._renderFunction);
}
else {
this._scene.unregisterBeforeRender(this._renderFunction);
}
},
enumerable: true,
configurable: true
});
SkeletonViewer.prototype._getBonePosition = function (position, bone, meshMat, x, y, z) {
if (x === void 0) { x = 0; }
if (y === void 0) { y = 0; }
if (z === void 0) { z = 0; }
var tmat = BABYLON.Tmp.Matrix[0];
var parentBone = bone.getParent();
tmat.copyFrom(bone.getLocalMatrix());
if (x !== 0 || y !== 0 || z !== 0) {
var tmat2 = BABYLON.Tmp.Matrix[1];
BABYLON.Matrix.IdentityToRef(tmat2);
tmat2.m[12] = x;
tmat2.m[13] = y;
tmat2.m[14] = z;
tmat2.multiplyToRef(tmat, tmat);
}
if (parentBone) {
tmat.multiplyToRef(parentBone.getAbsoluteTransform(), tmat);
}
tmat.multiplyToRef(meshMat, tmat);
position.x = tmat.m[12];
position.y = tmat.m[13];
position.z = tmat.m[14];
};
SkeletonViewer.prototype._getLinesForBonesWithLength = function (bones, meshMat) {
var len = bones.length;
var meshPos = this.mesh.position;
for (var i = 0; i < len; i++) {
var bone = bones[i];
var points = this._debugLines[i];
if (!points) {
points = [BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero()];
this._debugLines[i] = points;
}
this._getBonePosition(points[0], bone, meshMat);
this._getBonePosition(points[1], bone, meshMat, 0, bone.length, 0);
points[0].subtractInPlace(meshPos);
points[1].subtractInPlace(meshPos);
}
};
SkeletonViewer.prototype._getLinesForBonesNoLength = function (bones, meshMat) {
var len = bones.length;
var boneNum = 0;
var meshPos = this.mesh.position;
for (var i = len - 1; i >= 0; i--) {
var childBone = bones[i];
var parentBone = childBone.getParent();
if (!parentBone) {
continue;
}
var points = this._debugLines[boneNum];
if (!points) {
points = [BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero()];
this._debugLines[boneNum] = points;
}
childBone.getAbsolutePositionToRef(this.mesh, points[0]);
parentBone.getAbsolutePositionToRef(this.mesh, points[1]);
points[0].subtractInPlace(meshPos);
points[1].subtractInPlace(meshPos);
boneNum++;
}
};
SkeletonViewer.prototype.update = function () {
if (this.autoUpdateBonesMatrices) {
this.skeleton.computeAbsoluteTransforms();
}
if (this.skeleton.bones[0].length === undefined) {
this._getLinesForBonesNoLength(this.skeleton.bones, this.mesh.getWorldMatrix());
}
else {
this._getLinesForBonesWithLength(this.skeleton.bones, this.mesh.getWorldMatrix());
}
if (!this._debugMesh) {
this._debugMesh = BABYLON.MeshBuilder.CreateLineSystem("", { lines: this._debugLines, updatable: true, instance: null }, this._scene);
this._debugMesh.renderingGroupId = this.renderingGroupId;
}
else {
BABYLON.MeshBuilder.CreateLineSystem("", { lines: this._debugLines, updatable: true, instance: this._debugMesh }, this._scene);
}
this._debugMesh.position.copyFrom(this.mesh.position);
this._debugMesh.color = this.color;
};
SkeletonViewer.prototype.dispose = function () {
if (this._debugMesh) {
this.isEnabled = false;
this._debugMesh.dispose();
this._debugMesh = null;
}
};
return SkeletonViewer;
}());
return Debug;
}());
BABYLON.Debug = Debug;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.debugModules.js.map
var BABYLON;
(function (BABYLON) {
var RayHelper = /** @class */ (function () {
function RayHelper(ray) {
this.ray = ray;
}
RayHelper.CreateAndShow = function (ray, scene, color) {
var helper = new RayHelper(ray);
helper.show(scene, color);
return helper;
};
RayHelper.prototype.show = function (scene, color) {
if (!this._renderFunction && this.ray) {
var ray = this.ray;
this._renderFunction = this._render.bind(this);
this._scene = scene;
this._renderPoints = [ray.origin, ray.origin.add(ray.direction.scale(ray.length))];
this._renderLine = BABYLON.Mesh.CreateLines("ray", this._renderPoints, scene, true);
if (this._renderFunction) {
this._scene.registerBeforeRender(this._renderFunction);
}
}
if (color && this._renderLine) {
this._renderLine.color.copyFrom(color);
}
};
RayHelper.prototype.hide = function () {
if (this._renderFunction && this._scene) {
this._scene.unregisterBeforeRender(this._renderFunction);
this._scene = null;
this._renderFunction = null;
if (this._renderLine) {
this._renderLine.dispose();
this._renderLine = null;
}
this._renderPoints = [];
}
};
RayHelper.prototype._render = function () {
var ray = this.ray;
if (!ray) {
return;
}
var point = this._renderPoints[1];
var len = Math.min(ray.length, 1000000);
point.copyFrom(ray.direction);
point.scaleInPlace(len);
point.addInPlace(ray.origin);
BABYLON.Mesh.CreateLines("ray", this._renderPoints, this._scene, true, this._renderLine);
};
RayHelper.prototype.attachToMesh = function (mesh, meshSpaceDirection, meshSpaceOrigin, length) {
this._attachedToMesh = mesh;
var ray = this.ray;
if (!ray) {
return;
}
if (!ray.direction) {
ray.direction = BABYLON.Vector3.Zero();
}
if (!ray.origin) {
ray.origin = BABYLON.Vector3.Zero();
}
if (length) {
ray.length = length;
}
if (!meshSpaceOrigin) {
meshSpaceOrigin = BABYLON.Vector3.Zero();
}
if (!meshSpaceDirection) {
// -1 so that this will work with Mesh.lookAt
meshSpaceDirection = new BABYLON.Vector3(0, 0, -1);
}
if (!this._meshSpaceDirection) {
this._meshSpaceDirection = meshSpaceDirection.clone();
this._meshSpaceOrigin = meshSpaceOrigin.clone();
}
else {
this._meshSpaceDirection.copyFrom(meshSpaceDirection);
this._meshSpaceOrigin.copyFrom(meshSpaceOrigin);
}
if (!this._updateToMeshFunction) {
this._updateToMeshFunction = this._updateToMesh.bind(this);
this._attachedToMesh.getScene().registerBeforeRender(this._updateToMeshFunction);
}
this._updateToMesh();
};
RayHelper.prototype.detachFromMesh = function () {
if (this._attachedToMesh) {
if (this._updateToMeshFunction) {
this._attachedToMesh.getScene().unregisterBeforeRender(this._updateToMeshFunction);
}
this._attachedToMesh = null;
this._updateToMeshFunction = null;
}
};
RayHelper.prototype._updateToMesh = function () {
var ray = this.ray;
if (!this._attachedToMesh || !ray) {
return;
}
if (this._attachedToMesh._isDisposed) {
this.detachFromMesh();
return;
}
this._attachedToMesh.getDirectionToRef(this._meshSpaceDirection, ray.direction);
BABYLON.Vector3.TransformCoordinatesToRef(this._meshSpaceOrigin, this._attachedToMesh.getWorldMatrix(), ray.origin);
};
RayHelper.prototype.dispose = function () {
this.hide();
this.detachFromMesh();
this.ray = null;
};
return RayHelper;
}());
BABYLON.RayHelper = RayHelper;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.rayHelper.js.map
var BABYLON;
(function (BABYLON) {
// load the inspector using require, if not present in the global namespace.
var DebugLayer = /** @class */ (function () {
function DebugLayer(scene) {
this.BJSINSPECTOR = typeof INSPECTOR !== 'undefined' ? INSPECTOR : undefined;
this._scene = scene;
// load inspector using require, if it doesn't exist on the global namespace.
}
/** Creates the inspector window. */
DebugLayer.prototype._createInspector = function (config) {
if (config === void 0) { config = {}; }
var popup = config.popup || false;
var initialTab = config.initialTab || 0;
var parentElement = config.parentElement || null;
if (!this._inspector) {
this.BJSINSPECTOR = this.BJSINSPECTOR || typeof INSPECTOR !== 'undefined' ? INSPECTOR : undefined;
this._inspector = new this.BJSINSPECTOR.Inspector(this._scene, popup, initialTab, parentElement, config.newColors);
} // else nothing to do,; instance is already existing
};
DebugLayer.prototype.isVisible = function () {
if (!this._inspector) {
return false;
}
return true;
};
DebugLayer.prototype.hide = function () {
if (this._inspector) {
try {
this._inspector.dispose();
}
catch (e) {
// If the inspector has been removed directly from the inspector tool
}
this._inspector = null;
}
};
DebugLayer.prototype.show = function (config) {
if (config === void 0) { config = {}; }
if (typeof this.BJSINSPECTOR == 'undefined') {
// Load inspector and add it to the DOM
BABYLON.Tools.LoadScript(DebugLayer.InspectorURL, this._createInspector.bind(this, config));
}
else {
// Otherwise creates the inspector
this._createInspector(config);
}
};
DebugLayer.InspectorURL = 'https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js';
return DebugLayer;
}());
BABYLON.DebugLayer = DebugLayer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.debugLayer.js.map
var BABYLON;
(function (BABYLON) {
var BoundingBoxRenderer = /** @class */ (function () {
function BoundingBoxRenderer(scene) {
this.frontColor = new BABYLON.Color3(1, 1, 1);
this.backColor = new BABYLON.Color3(0.1, 0.1, 0.1);
this.showBackLines = true;
this.renderList = new BABYLON.SmartArray(32);
this._vertexBuffers = {};
this._scene = scene;
}
BoundingBoxRenderer.prototype._prepareRessources = function () {
if (this._colorShader) {
return;
}
this._colorShader = new BABYLON.ShaderMaterial("colorShader", this._scene, "color", {
attributes: [BABYLON.VertexBuffer.PositionKind],
uniforms: ["world", "viewProjection", "color"]
});
var engine = this._scene.getEngine();
var boxdata = BABYLON.VertexData.CreateBox({ size: 1.0 });
this._vertexBuffers[BABYLON.VertexBuffer.PositionKind] = new BABYLON.VertexBuffer(engine, boxdata.positions, BABYLON.VertexBuffer.PositionKind, false);
this._createIndexBuffer();
};
BoundingBoxRenderer.prototype._createIndexBuffer = function () {
var engine = this._scene.getEngine();
this._indexBuffer = engine.createIndexBuffer([0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 7, 1, 6, 2, 5, 3, 4]);
};
BoundingBoxRenderer.prototype._rebuild = function () {
var vb = this._vertexBuffers[BABYLON.VertexBuffer.PositionKind];
if (vb) {
vb._rebuild();
}
this._createIndexBuffer();
};
BoundingBoxRenderer.prototype.reset = function () {
this.renderList.reset();
};
BoundingBoxRenderer.prototype.render = function () {
if (this.renderList.length === 0) {
return;
}
this._prepareRessources();
if (!this._colorShader.isReady()) {
return;
}
var engine = this._scene.getEngine();
engine.setDepthWrite(false);
this._colorShader._preBind();
for (var boundingBoxIndex = 0; boundingBoxIndex < this.renderList.length; boundingBoxIndex++) {
var boundingBox = this.renderList.data[boundingBoxIndex];
var min = boundingBox.minimum;
var max = boundingBox.maximum;
var diff = max.subtract(min);
var median = min.add(diff.scale(0.5));
var worldMatrix = BABYLON.Matrix.Scaling(diff.x, diff.y, diff.z)
.multiply(BABYLON.Matrix.Translation(median.x, median.y, median.z))
.multiply(boundingBox.getWorldMatrix());
// VBOs
engine.bindBuffers(this._vertexBuffers, this._indexBuffer, this._colorShader.getEffect());
if (this.showBackLines) {
// Back
engine.setDepthFunctionToGreaterOrEqual();
this._scene.resetCachedMaterial();
this._colorShader.setColor4("color", this.backColor.toColor4());
this._colorShader.bind(worldMatrix);
// Draw order
engine.drawElementsType(BABYLON.Material.LineListDrawMode, 0, 24);
}
// Front
engine.setDepthFunctionToLess();
this._scene.resetCachedMaterial();
this._colorShader.setColor4("color", this.frontColor.toColor4());
this._colorShader.bind(worldMatrix);
// Draw order
engine.drawElementsType(BABYLON.Material.LineListDrawMode, 0, 24);
}
this._colorShader.unbind();
engine.setDepthFunctionToLessOrEqual();
engine.setDepthWrite(true);
};
BoundingBoxRenderer.prototype.renderOcclusionBoundingBox = function (mesh) {
this._prepareRessources();
if (!this._colorShader.isReady() || !mesh._boundingInfo) {
return;
}
var engine = this._scene.getEngine();
engine.setDepthWrite(false);
engine.setColorWrite(false);
this._colorShader._preBind();
var boundingBox = mesh._boundingInfo.boundingBox;
var min = boundingBox.minimum;
var max = boundingBox.maximum;
var diff = max.subtract(min);
var median = min.add(diff.scale(0.5));
var worldMatrix = BABYLON.Matrix.Scaling(diff.x, diff.y, diff.z)
.multiply(BABYLON.Matrix.Translation(median.x, median.y, median.z))
.multiply(boundingBox.getWorldMatrix());
engine.bindBuffers(this._vertexBuffers, this._indexBuffer, this._colorShader.getEffect());
engine.setDepthFunctionToLess();
this._scene.resetCachedMaterial();
this._colorShader.bind(worldMatrix);
engine.drawElementsType(BABYLON.Material.LineListDrawMode, 0, 24);
this._colorShader.unbind();
engine.setDepthFunctionToLessOrEqual();
engine.setDepthWrite(true);
engine.setColorWrite(true);
};
BoundingBoxRenderer.prototype.dispose = function () {
if (!this._colorShader) {
return;
}
this.renderList.dispose();
this._colorShader.dispose();
var buffer = this._vertexBuffers[BABYLON.VertexBuffer.PositionKind];
if (buffer) {
buffer.dispose();
this._vertexBuffers[BABYLON.VertexBuffer.PositionKind] = null;
}
this._scene.getEngine()._releaseBuffer(this._indexBuffer);
};
return BoundingBoxRenderer;
}());
BABYLON.BoundingBoxRenderer = BoundingBoxRenderer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.boundingBoxRenderer.js.map
var BABYLON;
(function (BABYLON) {
var MorphTarget = /** @class */ (function () {
function MorphTarget(name, influence) {
if (influence === void 0) { influence = 0; }
this.name = name;
this.animations = new Array();
this._positions = null;
this._normals = null;
this._tangents = null;
this.onInfluenceChanged = new BABYLON.Observable();
this.influence = influence;
}
Object.defineProperty(MorphTarget.prototype, "influence", {
get: function () {
return this._influence;
},
set: function (influence) {
if (this._influence === influence) {
return;
}
var previous = this._influence;
this._influence = influence;
if (this.onInfluenceChanged.hasObservers) {
this.onInfluenceChanged.notifyObservers(previous === 0 || influence === 0);
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(MorphTarget.prototype, "hasPositions", {
get: function () {
return !!this._positions;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MorphTarget.prototype, "hasNormals", {
get: function () {
return !!this._normals;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MorphTarget.prototype, "hasTangents", {
get: function () {
return !!this._tangents;
},
enumerable: true,
configurable: true
});
MorphTarget.prototype.setPositions = function (data) {
this._positions = data;
};
MorphTarget.prototype.getPositions = function () {
return this._positions;
};
MorphTarget.prototype.setNormals = function (data) {
this._normals = data;
};
MorphTarget.prototype.getNormals = function () {
return this._normals;
};
MorphTarget.prototype.setTangents = function (data) {
this._tangents = data;
};
MorphTarget.prototype.getTangents = function () {
return this._tangents;
};
/**
* Serializes the current target into a Serialization object.
* Returns the serialized object.
*/
MorphTarget.prototype.serialize = function () {
var serializationObject = {};
serializationObject.name = this.name;
serializationObject.influence = this.influence;
serializationObject.positions = Array.prototype.slice.call(this.getPositions());
if (this.hasNormals) {
serializationObject.normals = Array.prototype.slice.call(this.getNormals());
}
if (this.hasTangents) {
serializationObject.tangents = Array.prototype.slice.call(this.getTangents());
}
// Animations
BABYLON.Animation.AppendSerializedAnimations(this, serializationObject);
return serializationObject;
};
// Statics
MorphTarget.Parse = function (serializationObject) {
var result = new MorphTarget(serializationObject.name, serializationObject.influence);
result.setPositions(serializationObject.positions);
if (serializationObject.normals) {
result.setNormals(serializationObject.normals);
}
if (serializationObject.tangents) {
result.setTangents(serializationObject.tangents);
}
// Animations
if (serializationObject.animations) {
for (var animationIndex = 0; animationIndex < serializationObject.animations.length; animationIndex++) {
var parsedAnimation = serializationObject.animations[animationIndex];
result.animations.push(BABYLON.Animation.Parse(parsedAnimation));
}
}
return result;
};
MorphTarget.FromMesh = function (mesh, name, influence) {
if (!name) {
name = mesh.name;
}
var result = new MorphTarget(name, influence);
result.setPositions(mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind));
if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
result.setNormals(mesh.getVerticesData(BABYLON.VertexBuffer.NormalKind));
}
if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.TangentKind)) {
result.setTangents(mesh.getVerticesData(BABYLON.VertexBuffer.TangentKind));
}
return result;
};
return MorphTarget;
}());
BABYLON.MorphTarget = MorphTarget;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.morphTarget.js.map
var BABYLON;
(function (BABYLON) {
var MorphTargetManager = /** @class */ (function () {
function MorphTargetManager(scene) {
if (scene === void 0) { scene = null; }
this._targets = new Array();
this._targetObservable = new Array();
this._activeTargets = new BABYLON.SmartArray(16);
this._supportsNormals = false;
this._supportsTangents = false;
this._vertexCount = 0;
this._uniqueId = 0;
this._tempInfluences = new Array();
if (!scene) {
scene = BABYLON.Engine.LastCreatedScene;
}
this._scene = scene;
if (this._scene) {
this._scene.morphTargetManagers.push(this);
this._uniqueId = this._scene.getUniqueId();
}
}
Object.defineProperty(MorphTargetManager.prototype, "uniqueId", {
get: function () {
return this._uniqueId;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MorphTargetManager.prototype, "vertexCount", {
get: function () {
return this._vertexCount;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MorphTargetManager.prototype, "supportsNormals", {
get: function () {
return this._supportsNormals;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MorphTargetManager.prototype, "supportsTangents", {
get: function () {
return this._supportsTangents;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MorphTargetManager.prototype, "numTargets", {
get: function () {
return this._targets.length;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MorphTargetManager.prototype, "numInfluencers", {
get: function () {
return this._activeTargets.length;
},
enumerable: true,
configurable: true
});
Object.defineProperty(MorphTargetManager.prototype, "influences", {
get: function () {
return this._influences;
},
enumerable: true,
configurable: true
});
MorphTargetManager.prototype.getActiveTarget = function (index) {
return this._activeTargets.data[index];
};
MorphTargetManager.prototype.getTarget = function (index) {
return this._targets[index];
};
MorphTargetManager.prototype.addTarget = function (target) {
var _this = this;
this._targets.push(target);
this._targetObservable.push(target.onInfluenceChanged.add(function (needUpdate) {
_this._syncActiveTargets(needUpdate);
}));
this._syncActiveTargets(true);
};
MorphTargetManager.prototype.removeTarget = function (target) {
var index = this._targets.indexOf(target);
if (index >= 0) {
this._targets.splice(index, 1);
target.onInfluenceChanged.remove(this._targetObservable.splice(index, 1)[0]);
this._syncActiveTargets(true);
}
};
/**
* Serializes the current manager into a Serialization object.
* Returns the serialized object.
*/
MorphTargetManager.prototype.serialize = function () {
var serializationObject = {};
serializationObject.id = this.uniqueId;
serializationObject.targets = [];
for (var _i = 0, _a = this._targets; _i < _a.length; _i++) {
var target = _a[_i];
serializationObject.targets.push(target.serialize());
}
return serializationObject;
};
MorphTargetManager.prototype._syncActiveTargets = function (needUpdate) {
var influenceCount = 0;
this._activeTargets.reset();
this._supportsNormals = true;
this._supportsTangents = true;
this._vertexCount = 0;
for (var _i = 0, _a = this._targets; _i < _a.length; _i++) {
var target = _a[_i];
this._activeTargets.push(target);
this._tempInfluences[influenceCount++] = target.influence;
var positions = target.getPositions();
if (positions) {
this._supportsNormals = this._supportsNormals && target.hasNormals;
this._supportsTangents = this._supportsTangents && target.hasTangents;
var vertexCount = positions.length / 3;
if (this._vertexCount === 0) {
this._vertexCount = vertexCount;
}
else if (this._vertexCount !== vertexCount) {
BABYLON.Tools.Error("Incompatible target. Targets must all have the same vertices count.");
return;
}
}
}
if (!this._influences || this._influences.length !== influenceCount) {
this._influences = new Float32Array(influenceCount);
}
for (var index = 0; index < influenceCount; index++) {
this._influences[index] = this._tempInfluences[index];
}
if (needUpdate && this._scene) {
// Flag meshes as dirty to resync with the active targets
for (var _b = 0, _c = this._scene.meshes; _b < _c.length; _b++) {
var mesh = _c[_b];
if (mesh.morphTargetManager === this) {
mesh._syncGeometryWithMorphTargetManager();
}
}
}
};
// Statics
MorphTargetManager.Parse = function (serializationObject, scene) {
var result = new MorphTargetManager(scene);
result._uniqueId = serializationObject.id;
for (var _i = 0, _a = serializationObject.targets; _i < _a.length; _i++) {
var targetData = _a[_i];
result.addTarget(BABYLON.MorphTarget.Parse(targetData));
}
return result;
};
return MorphTargetManager;
}());
BABYLON.MorphTargetManager = MorphTargetManager;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.morphTargetManager.js.map
var BABYLON;
(function (BABYLON) {
var Octree = /** @class */ (function () {
function Octree(creationFunc, maxBlockCapacity, maxDepth) {
if (maxDepth === void 0) { maxDepth = 2; }
this.maxDepth = maxDepth;
this.dynamicContent = new Array();
this._maxBlockCapacity = maxBlockCapacity || 64;
this._selectionContent = new BABYLON.SmartArrayNoDuplicate(1024);
this._creationFunc = creationFunc;
}
// Methods
Octree.prototype.update = function (worldMin, worldMax, entries) {
Octree._CreateBlocks(worldMin, worldMax, entries, this._maxBlockCapacity, 0, this.maxDepth, this, this._creationFunc);
};
Octree.prototype.addMesh = function (entry) {
for (var index = 0; index < this.blocks.length; index++) {
var block = this.blocks[index];
block.addEntry(entry);
}
};
Octree.prototype.select = function (frustumPlanes, allowDuplicate) {
this._selectionContent.reset();
for (var index = 0; index < this.blocks.length; index++) {
var block = this.blocks[index];
block.select(frustumPlanes, this._selectionContent, allowDuplicate);
}
if (allowDuplicate) {
this._selectionContent.concat(this.dynamicContent);
}
else {
this._selectionContent.concatWithNoDuplicate(this.dynamicContent);
}
return this._selectionContent;
};
Octree.prototype.intersects = function (sphereCenter, sphereRadius, allowDuplicate) {
this._selectionContent.reset();
for (var index = 0; index < this.blocks.length; index++) {
var block = this.blocks[index];
block.intersects(sphereCenter, sphereRadius, this._selectionContent, allowDuplicate);
}
if (allowDuplicate) {
this._selectionContent.concat(this.dynamicContent);
}
else {
this._selectionContent.concatWithNoDuplicate(this.dynamicContent);
}
return this._selectionContent;
};
Octree.prototype.intersectsRay = function (ray) {
this._selectionContent.reset();
for (var index = 0; index < this.blocks.length; index++) {
var block = this.blocks[index];
block.intersectsRay(ray, this._selectionContent);
}
this._selectionContent.concatWithNoDuplicate(this.dynamicContent);
return this._selectionContent;
};
Octree._CreateBlocks = function (worldMin, worldMax, entries, maxBlockCapacity, currentDepth, maxDepth, target, creationFunc) {
target.blocks = new Array();
var blockSize = new BABYLON.Vector3((worldMax.x - worldMin.x) / 2, (worldMax.y - worldMin.y) / 2, (worldMax.z - worldMin.z) / 2);
// Segmenting space
for (var x = 0; x < 2; x++) {
for (var y = 0; y < 2; y++) {
for (var z = 0; z < 2; z++) {
var localMin = worldMin.add(blockSize.multiplyByFloats(x, y, z));
var localMax = worldMin.add(blockSize.multiplyByFloats(x + 1, y + 1, z + 1));
var block = new BABYLON.OctreeBlock(localMin, localMax, maxBlockCapacity, currentDepth + 1, maxDepth, creationFunc);
block.addEntries(entries);
target.blocks.push(block);
}
}
}
};
Octree.CreationFuncForMeshes = function (entry, block) {
var boundingInfo = entry.getBoundingInfo();
if (!entry.isBlocked && boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
block.entries.push(entry);
}
};
Octree.CreationFuncForSubMeshes = function (entry, block) {
var boundingInfo = entry.getBoundingInfo();
if (boundingInfo.boundingBox.intersectsMinMax(block.minPoint, block.maxPoint)) {
block.entries.push(entry);
}
};
return Octree;
}());
BABYLON.Octree = Octree;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.octree.js.map
var BABYLON;
(function (BABYLON) {
var OctreeBlock = /** @class */ (function () {
function OctreeBlock(minPoint, maxPoint, capacity, depth, maxDepth, creationFunc) {
this.entries = new Array();
this._boundingVectors = new Array();
this._capacity = capacity;
this._depth = depth;
this._maxDepth = maxDepth;
this._creationFunc = creationFunc;
this._minPoint = minPoint;
this._maxPoint = maxPoint;
this._boundingVectors.push(minPoint.clone());
this._boundingVectors.push(maxPoint.clone());
this._boundingVectors.push(minPoint.clone());
this._boundingVectors[2].x = maxPoint.x;
this._boundingVectors.push(minPoint.clone());
this._boundingVectors[3].y = maxPoint.y;
this._boundingVectors.push(minPoint.clone());
this._boundingVectors[4].z = maxPoint.z;
this._boundingVectors.push(maxPoint.clone());
this._boundingVectors[5].z = minPoint.z;
this._boundingVectors.push(maxPoint.clone());
this._boundingVectors[6].x = minPoint.x;
this._boundingVectors.push(maxPoint.clone());
this._boundingVectors[7].y = minPoint.y;
}
Object.defineProperty(OctreeBlock.prototype, "capacity", {
// Property
get: function () {
return this._capacity;
},
enumerable: true,
configurable: true
});
Object.defineProperty(OctreeBlock.prototype, "minPoint", {
get: function () {
return this._minPoint;
},
enumerable: true,
configurable: true
});
Object.defineProperty(OctreeBlock.prototype, "maxPoint", {
get: function () {
return this._maxPoint;
},
enumerable: true,
configurable: true
});
// Methods
OctreeBlock.prototype.addEntry = function (entry) {
if (this.blocks) {
for (var index = 0; index < this.blocks.length; index++) {
var block = this.blocks[index];
block.addEntry(entry);
}
return;
}
this._creationFunc(entry, this);
if (this.entries.length > this.capacity && this._depth < this._maxDepth) {
this.createInnerBlocks();
}
};
OctreeBlock.prototype.addEntries = function (entries) {
for (var index = 0; index < entries.length; index++) {
var mesh = entries[index];
this.addEntry(mesh);
}
};
OctreeBlock.prototype.select = function (frustumPlanes, selection, allowDuplicate) {
if (BABYLON.BoundingBox.IsInFrustum(this._boundingVectors, frustumPlanes)) {
if (this.blocks) {
for (var index = 0; index < this.blocks.length; index++) {
var block = this.blocks[index];
block.select(frustumPlanes, selection, allowDuplicate);
}
return;
}
if (allowDuplicate) {
selection.concat(this.entries);
}
else {
selection.concatWithNoDuplicate(this.entries);
}
}
};
OctreeBlock.prototype.intersects = function (sphereCenter, sphereRadius, selection, allowDuplicate) {
if (BABYLON.BoundingBox.IntersectsSphere(this._minPoint, this._maxPoint, sphereCenter, sphereRadius)) {
if (this.blocks) {
for (var index = 0; index < this.blocks.length; index++) {
var block = this.blocks[index];
block.intersects(sphereCenter, sphereRadius, selection, allowDuplicate);
}
return;
}
if (allowDuplicate) {
selection.concat(this.entries);
}
else {
selection.concatWithNoDuplicate(this.entries);
}
}
};
OctreeBlock.prototype.intersectsRay = function (ray, selection) {
if (ray.intersectsBoxMinMax(this._minPoint, this._maxPoint)) {
if (this.blocks) {
for (var index = 0; index < this.blocks.length; index++) {
var block = this.blocks[index];
block.intersectsRay(ray, selection);
}
return;
}
selection.concatWithNoDuplicate(this.entries);
}
};
OctreeBlock.prototype.createInnerBlocks = function () {
BABYLON.Octree._CreateBlocks(this._minPoint, this._maxPoint, this.entries, this._capacity, this._depth, this._maxDepth, this, this._creationFunc);
};
return OctreeBlock;
}());
BABYLON.OctreeBlock = OctreeBlock;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.octreeBlock.js.map
var BABYLON;
(function (BABYLON) {
var VRDistortionCorrectionPostProcess = /** @class */ (function (_super) {
__extends(VRDistortionCorrectionPostProcess, _super);
function VRDistortionCorrectionPostProcess(name, camera, isRightEye, vrMetrics) {
var _this = _super.call(this, name, "vrDistortionCorrection", [
'LensCenter',
'Scale',
'ScaleIn',
'HmdWarpParam'
], null, vrMetrics.postProcessScaleFactor, camera, BABYLON.Texture.BILINEAR_SAMPLINGMODE) || this;
_this._isRightEye = isRightEye;
_this._distortionFactors = vrMetrics.distortionK;
_this._postProcessScaleFactor = vrMetrics.postProcessScaleFactor;
_this._lensCenterOffset = vrMetrics.lensCenterOffset;
_this.adaptScaleToCurrentViewport = true;
_this.onSizeChangedObservable.add(function () {
_this.aspectRatio = _this.width * .5 / _this.height;
_this._scaleIn = new BABYLON.Vector2(2, 2 / _this.aspectRatio);
_this._scaleFactor = new BABYLON.Vector2(.5 * (1 / _this._postProcessScaleFactor), .5 * (1 / _this._postProcessScaleFactor) * _this.aspectRatio);
_this._lensCenter = new BABYLON.Vector2(_this._isRightEye ? 0.5 - _this._lensCenterOffset * 0.5 : 0.5 + _this._lensCenterOffset * 0.5, 0.5);
});
_this.onApplyObservable.add(function (effect) {
effect.setFloat2("LensCenter", _this._lensCenter.x, _this._lensCenter.y);
effect.setFloat2("Scale", _this._scaleFactor.x, _this._scaleFactor.y);
effect.setFloat2("ScaleIn", _this._scaleIn.x, _this._scaleIn.y);
effect.setFloat4("HmdWarpParam", _this._distortionFactors[0], _this._distortionFactors[1], _this._distortionFactors[2], _this._distortionFactors[3]);
});
return _this;
}
return VRDistortionCorrectionPostProcess;
}(BABYLON.PostProcess));
BABYLON.VRDistortionCorrectionPostProcess = VRDistortionCorrectionPostProcess;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.vrDistortionCorrectionPostProcess.js.map
var BABYLON;
(function (BABYLON) {
var AnaglyphPostProcess = /** @class */ (function (_super) {
__extends(AnaglyphPostProcess, _super);
function AnaglyphPostProcess(name, options, rigCameras, samplingMode, engine, reusable) {
var _this = _super.call(this, name, "anaglyph", null, ["leftSampler"], options, rigCameras[1], samplingMode, engine, reusable) || this;
_this._passedProcess = rigCameras[0]._rigPostProcess;
_this.onApplyObservable.add(function (effect) {
effect.setTextureFromPostProcess("leftSampler", _this._passedProcess);
});
return _this;
}
return AnaglyphPostProcess;
}(BABYLON.PostProcess));
BABYLON.AnaglyphPostProcess = AnaglyphPostProcess;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.anaglyphPostProcess.js.map
var BABYLON;
(function (BABYLON) {
var StereoscopicInterlacePostProcess = /** @class */ (function (_super) {
__extends(StereoscopicInterlacePostProcess, _super);
function StereoscopicInterlacePostProcess(name, rigCameras, isStereoscopicHoriz, samplingMode, engine, reusable) {
var _this = _super.call(this, name, "stereoscopicInterlace", ['stepSize'], ['camASampler'], 1, rigCameras[1], samplingMode, engine, reusable, isStereoscopicHoriz ? "#define IS_STEREOSCOPIC_HORIZ 1" : undefined) || this;
_this._passedProcess = rigCameras[0]._rigPostProcess;
_this._stepSize = new BABYLON.Vector2(1 / _this.width, 1 / _this.height);
_this.onSizeChangedObservable.add(function () {
_this._stepSize = new BABYLON.Vector2(1 / _this.width, 1 / _this.height);
});
_this.onApplyObservable.add(function (effect) {
effect.setTextureFromPostProcess("camASampler", _this._passedProcess);
effect.setFloat2("stepSize", _this._stepSize.x, _this._stepSize.y);
});
return _this;
}
return StereoscopicInterlacePostProcess;
}(BABYLON.PostProcess));
BABYLON.StereoscopicInterlacePostProcess = StereoscopicInterlacePostProcess;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.stereoscopicInterlacePostProcess.js.map
var BABYLON;
(function (BABYLON) {
/**
* Takes information about the orientation of the device as reported by the deviceorientation event to orient the camera.
* Screen rotation is taken into account.
*/
var FreeCameraDeviceOrientationInput = /** @class */ (function () {
function FreeCameraDeviceOrientationInput() {
var _this = this;
this._screenOrientationAngle = 0;
this._screenQuaternion = new BABYLON.Quaternion();
this._alpha = 0;
this._beta = 0;
this._gamma = 0;
this._orientationChanged = function () {
_this._screenOrientationAngle = (window.orientation !== undefined ? +window.orientation : (window.screen.orientation && window.screen.orientation['angle'] ? window.screen.orientation.angle : 0));
_this._screenOrientationAngle = -BABYLON.Tools.ToRadians(_this._screenOrientationAngle / 2);
_this._screenQuaternion.copyFromFloats(0, Math.sin(_this._screenOrientationAngle), 0, Math.cos(_this._screenOrientationAngle));
};
this._deviceOrientation = function (evt) {
_this._alpha = evt.alpha !== null ? evt.alpha : 0;
_this._beta = evt.beta !== null ? evt.beta : 0;
_this._gamma = evt.gamma !== null ? evt.gamma : 0;
};
this._constantTranform = new BABYLON.Quaternion(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5));
this._orientationChanged();
}
Object.defineProperty(FreeCameraDeviceOrientationInput.prototype, "camera", {
get: function () {
return this._camera;
},
set: function (camera) {
this._camera = camera;
if (this._camera != null && !this._camera.rotationQuaternion) {
this._camera.rotationQuaternion = new BABYLON.Quaternion();
}
},
enumerable: true,
configurable: true
});
FreeCameraDeviceOrientationInput.prototype.attachControl = function (element, noPreventDefault) {
window.addEventListener("orientationchange", this._orientationChanged);
window.addEventListener("deviceorientation", this._deviceOrientation);
//In certain cases, the attach control is called AFTER orientation was changed,
//So this is needed.
this._orientationChanged();
};
FreeCameraDeviceOrientationInput.prototype.detachControl = function (element) {
window.removeEventListener("orientationchange", this._orientationChanged);
window.removeEventListener("deviceorientation", this._deviceOrientation);
};
FreeCameraDeviceOrientationInput.prototype.checkInputs = function () {
//if no device orientation provided, don't update the rotation.
//Only testing against alpha under the assumption thatnorientation will never be so exact when set.
if (!this._alpha)
return;
BABYLON.Quaternion.RotationYawPitchRollToRef(BABYLON.Tools.ToRadians(this._alpha), BABYLON.Tools.ToRadians(this._beta), -BABYLON.Tools.ToRadians(this._gamma), this.camera.rotationQuaternion);
this._camera.rotationQuaternion.multiplyInPlace(this._screenQuaternion);
this._camera.rotationQuaternion.multiplyInPlace(this._constantTranform);
//Mirror on XY Plane
this._camera.rotationQuaternion.z *= -1;
this._camera.rotationQuaternion.w *= -1;
};
FreeCameraDeviceOrientationInput.prototype.getClassName = function () {
return "FreeCameraDeviceOrientationInput";
};
FreeCameraDeviceOrientationInput.prototype.getSimpleName = function () {
return "deviceOrientation";
};
return FreeCameraDeviceOrientationInput;
}());
BABYLON.FreeCameraDeviceOrientationInput = FreeCameraDeviceOrientationInput;
BABYLON.CameraInputTypes["FreeCameraDeviceOrientationInput"] = FreeCameraDeviceOrientationInput;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.freeCameraDeviceOrientationInput.js.map
var BABYLON;
(function (BABYLON) {
var ArcRotateCameraVRDeviceOrientationInput = /** @class */ (function () {
function ArcRotateCameraVRDeviceOrientationInput() {
this.alphaCorrection = 1;
this.betaCorrection = 1;
this.gammaCorrection = 1;
this._alpha = 0;
this._gamma = 0;
this._dirty = false;
this._deviceOrientationHandler = this._onOrientationEvent.bind(this);
}
ArcRotateCameraVRDeviceOrientationInput.prototype.attachControl = function (element, noPreventDefault) {
this.camera.attachControl(element, noPreventDefault);
window.addEventListener("deviceorientation", this._deviceOrientationHandler);
};
ArcRotateCameraVRDeviceOrientationInput.prototype._onOrientationEvent = function (evt) {
if (evt.alpha !== null) {
this._alpha = +evt.alpha | 0;
}
if (evt.gamma !== null) {
this._gamma = +evt.gamma | 0;
}
this._dirty = true;
};
ArcRotateCameraVRDeviceOrientationInput.prototype.checkInputs = function () {
if (this._dirty) {
this._dirty = false;
if (this._gamma < 0) {
this._gamma = 180 + this._gamma;
}
this.camera.alpha = (-this._alpha / 180.0 * Math.PI) % Math.PI * 2;
this.camera.beta = (this._gamma / 180.0 * Math.PI);
}
};
ArcRotateCameraVRDeviceOrientationInput.prototype.detachControl = function (element) {
window.removeEventListener("deviceorientation", this._deviceOrientationHandler);
};
ArcRotateCameraVRDeviceOrientationInput.prototype.getClassName = function () {
return "ArcRotateCameraVRDeviceOrientationInput";
};
ArcRotateCameraVRDeviceOrientationInput.prototype.getSimpleName = function () {
return "VRDeviceOrientation";
};
return ArcRotateCameraVRDeviceOrientationInput;
}());
BABYLON.ArcRotateCameraVRDeviceOrientationInput = ArcRotateCameraVRDeviceOrientationInput;
BABYLON.CameraInputTypes["ArcRotateCameraVRDeviceOrientationInput"] = ArcRotateCameraVRDeviceOrientationInput;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.arcRotateCameraVRDeviceOrientationInput.js.map
var BABYLON;
(function (BABYLON) {
var VRCameraMetrics = /** @class */ (function () {
function VRCameraMetrics() {
this.compensateDistortion = true;
}
Object.defineProperty(VRCameraMetrics.prototype, "aspectRatio", {
get: function () {
return this.hResolution / (2 * this.vResolution);
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRCameraMetrics.prototype, "aspectRatioFov", {
get: function () {
return (2 * Math.atan((this.postProcessScaleFactor * this.vScreenSize) / (2 * this.eyeToScreenDistance)));
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRCameraMetrics.prototype, "leftHMatrix", {
get: function () {
var meters = (this.hScreenSize / 4) - (this.lensSeparationDistance / 2);
var h = (4 * meters) / this.hScreenSize;
return BABYLON.Matrix.Translation(h, 0, 0);
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRCameraMetrics.prototype, "rightHMatrix", {
get: function () {
var meters = (this.hScreenSize / 4) - (this.lensSeparationDistance / 2);
var h = (4 * meters) / this.hScreenSize;
return BABYLON.Matrix.Translation(-h, 0, 0);
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRCameraMetrics.prototype, "leftPreViewMatrix", {
get: function () {
return BABYLON.Matrix.Translation(0.5 * this.interpupillaryDistance, 0, 0);
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRCameraMetrics.prototype, "rightPreViewMatrix", {
get: function () {
return BABYLON.Matrix.Translation(-0.5 * this.interpupillaryDistance, 0, 0);
},
enumerable: true,
configurable: true
});
VRCameraMetrics.GetDefault = function () {
var result = new VRCameraMetrics();
result.hResolution = 1280;
result.vResolution = 800;
result.hScreenSize = 0.149759993;
result.vScreenSize = 0.0935999975;
result.vScreenCenter = 0.0467999987;
result.eyeToScreenDistance = 0.0410000011;
result.lensSeparationDistance = 0.0635000020;
result.interpupillaryDistance = 0.0640000030;
result.distortionK = [1.0, 0.219999999, 0.239999995, 0.0];
result.chromaAbCorrection = [0.995999992, -0.00400000019, 1.01400006, 0.0];
result.postProcessScaleFactor = 1.714605507808412;
result.lensCenterOffset = 0.151976421;
return result;
};
return VRCameraMetrics;
}());
BABYLON.VRCameraMetrics = VRCameraMetrics;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.vrCameraMetrics.js.map
var BABYLON;
(function (BABYLON) {
/**
* This represents a WebVR camera.
* The WebVR camera is Babylon's simple interface to interaction with Windows Mixed Reality, HTC Vive and Oculus Rift.
* @example http://doc.babylonjs.com/how_to/webvr_camera
*/
var WebVRFreeCamera = /** @class */ (function (_super) {
__extends(WebVRFreeCamera, _super);
/**
* Instantiates a WebVRFreeCamera.
* @param name The name of the WebVRFreeCamera
* @param position The starting anchor position for the camera
* @param scene The scene the camera belongs to
* @param webVROptions a set of customizable options for the webVRCamera
*/
function WebVRFreeCamera(name, position, scene, webVROptions) {
if (webVROptions === void 0) { webVROptions = {}; }
var _this = _super.call(this, name, position, scene) || this;
_this.webVROptions = webVROptions;
/**
* The vrDisplay tied to the camera. See https://developer.mozilla.org/en-US/docs/Web/API/VRDisplay
*/
_this._vrDevice = null;
/**
* The rawPose of the vrDevice.
*/
_this.rawPose = null;
_this._specsVersion = "1.1";
_this._attached = false;
_this._descendants = [];
// Represents device position and rotation in room space. Should only be used to help calculate babylon space values
_this._deviceRoomPosition = BABYLON.Vector3.Zero();
_this._deviceRoomRotationQuaternion = BABYLON.Quaternion.Identity();
_this._standingMatrix = null;
/**
* Represents device position in babylon space.
*/
_this.devicePosition = BABYLON.Vector3.Zero();
/**
* Represents device rotation in babylon space.
*/
_this.deviceRotationQuaternion = BABYLON.Quaternion.Identity();
/**
* The scale of the device to be used when translating from device space to babylon space.
*/
_this.deviceScaleFactor = 1;
_this._deviceToWorld = BABYLON.Matrix.Identity();
_this._worldToDevice = BABYLON.Matrix.Identity();
/**
* References to the webVR controllers for the vrDevice.
*/
_this.controllers = [];
/**
* Emits an event when a controller is attached.
*/
_this.onControllersAttachedObservable = new BABYLON.Observable();
/**
* Emits an event when a controller's mesh has been loaded;
*/
_this.onControllerMeshLoadedObservable = new BABYLON.Observable();
/**
* If the rig cameras be used as parent instead of this camera.
*/
_this.rigParenting = true;
_this._defaultHeight = undefined;
_this._workingVector = BABYLON.Vector3.Zero();
_this._oneVector = BABYLON.Vector3.One();
_this._workingMatrix = BABYLON.Matrix.Identity();
_this._cache.position = BABYLON.Vector3.Zero();
if (webVROptions.defaultHeight) {
_this._defaultHeight = webVROptions.defaultHeight;
_this.position.y = _this._defaultHeight;
}
_this.minZ = 0.1;
//legacy support - the compensation boolean was removed.
if (arguments.length === 5) {
_this.webVROptions = arguments[4];
}
// default webVR options
if (_this.webVROptions.trackPosition == undefined) {
_this.webVROptions.trackPosition = true;
}
if (_this.webVROptions.controllerMeshes == undefined) {
_this.webVROptions.controllerMeshes = true;
}
if (_this.webVROptions.defaultLightingOnControllers == undefined) {
_this.webVROptions.defaultLightingOnControllers = true;
}
_this.rotationQuaternion = new BABYLON.Quaternion();
if (_this.webVROptions && _this.webVROptions.positionScale) {
_this.deviceScaleFactor = _this.webVROptions.positionScale;
}
//enable VR
var engine = _this.getEngine();
_this._onVREnabled = function (success) { if (success) {
_this.initControllers();
} };
engine.onVRRequestPresentComplete.add(_this._onVREnabled);
engine.initWebVR().add(function (event) {
if (!event.vrDisplay || _this._vrDevice === event.vrDisplay) {
return;
}
_this._vrDevice = event.vrDisplay;
//reset the rig parameters.
_this.setCameraRigMode(BABYLON.Camera.RIG_MODE_WEBVR, { parentCamera: _this, vrDisplay: _this._vrDevice, frameData: _this._frameData, specs: _this._specsVersion });
if (_this._attached) {
_this.getEngine().enableVR();
}
});
if (typeof (VRFrameData) !== "undefined")
_this._frameData = new VRFrameData();
/**
* The idea behind the following lines:
* objects that have the camera as parent should actually have the rig cameras as a parent.
* BUT, each of those cameras has a different view matrix, which means that if we set the parent to the first rig camera,
* the second will not show it correctly.
*
* To solve this - each object that has the camera as parent will be added to a protected array.
* When the rig camera renders, it will take this array and set all of those to be its children.
* This way, the right camera will be used as a parent, and the mesh will be rendered correctly.
* Amazing!
*/
scene.onBeforeCameraRenderObservable.add(function (camera) {
if (camera.parent === _this && _this.rigParenting) {
_this._descendants = _this.getDescendants(true, function (n) {
// don't take the cameras or the controllers!
var isController = _this.controllers.some(function (controller) { return controller._mesh === n; });
var isRigCamera = _this._rigCameras.indexOf(n) !== -1;
return !isController && !isRigCamera;
});
_this._descendants.forEach(function (node) {
node.parent = camera;
});
}
});
scene.onAfterCameraRenderObservable.add(function (camera) {
if (camera.parent === _this && _this.rigParenting) {
_this._descendants.forEach(function (node) {
node.parent = _this;
});
}
});
return _this;
}
/**
* Gets the device distance from the ground in meters.
* @returns the distance in meters from the vrDevice to ground in device space. If standing matrix is not supported for the vrDevice 0 is returned.
*/
WebVRFreeCamera.prototype.deviceDistanceToRoomGround = function () {
if (this._standingMatrix) {
// Add standing matrix offset to get real offset from ground in room
this._standingMatrix.getTranslationToRef(this._workingVector);
return this._deviceRoomPosition.y + this._workingVector.y;
}
//If VRDisplay does not inform stage parameters and no default height is set we fallback to zero.
return this._defaultHeight || 0;
};
/**
* Enables the standing matrix when supported. This can be used to position the user's view the correct height from the ground.
* @param callback will be called when the standing matrix is set. Callback parameter is if the standing matrix is supported.
*/
WebVRFreeCamera.prototype.useStandingMatrix = function (callback) {
var _this = this;
if (callback === void 0) { callback = function (bool) { }; }
// Use standing matrix if available
this.getEngine().initWebVRAsync().then(function (result) {
if (!result.vrDisplay || !result.vrDisplay.stageParameters || !result.vrDisplay.stageParameters.sittingToStandingTransform) {
callback(false);
}
else {
_this._standingMatrix = new BABYLON.Matrix();
BABYLON.Matrix.FromFloat32ArrayToRefScaled(result.vrDisplay.stageParameters.sittingToStandingTransform, 0, 1, _this._standingMatrix);
if (!_this.getScene().useRightHandedSystem) {
[2, 6, 8, 9, 14].forEach(function (num) {
if (_this._standingMatrix) {
_this._standingMatrix.m[num] *= -1;
}
});
}
callback(true);
}
});
};
/**
* Enables the standing matrix when supported. This can be used to position the user's view the correct height from the ground.
* @returns A promise with a boolean set to if the standing matrix is supported.
*/
WebVRFreeCamera.prototype.useStandingMatrixAsync = function () {
var _this = this;
return new Promise(function (res, rej) {
_this.useStandingMatrix(function (supported) {
res(supported);
});
});
};
/**
* Disposes the camera
*/
WebVRFreeCamera.prototype.dispose = function () {
this.getEngine().onVRRequestPresentComplete.removeCallback(this._onVREnabled);
_super.prototype.dispose.call(this);
};
/**
* Gets a vrController by name.
* @param name The name of the controller to retreive
* @returns the controller matching the name specified or null if not found
*/
WebVRFreeCamera.prototype.getControllerByName = function (name) {
for (var _i = 0, _a = this.controllers; _i < _a.length; _i++) {
var gp = _a[_i];
if (gp.hand === name) {
return gp;
}
}
return null;
};
Object.defineProperty(WebVRFreeCamera.prototype, "leftController", {
/**
* The controller corrisponding to the users left hand.
*/
get: function () {
if (!this._leftController) {
this._leftController = this.getControllerByName("left");
}
return this._leftController;
},
enumerable: true,
configurable: true
});
;
Object.defineProperty(WebVRFreeCamera.prototype, "rightController", {
/**
* The controller corrisponding to the users right hand.
*/
get: function () {
if (!this._rightController) {
this._rightController = this.getControllerByName("right");
}
return this._rightController;
},
enumerable: true,
configurable: true
});
;
/**
* Casts a ray forward from the vrCamera's gaze.
* @param length Length of the ray (default: 100)
* @returns the ray corrisponding to the gaze
*/
WebVRFreeCamera.prototype.getForwardRay = function (length) {
if (length === void 0) { length = 100; }
if (this.leftCamera) {
// Use left eye to avoid computation to compute center on every call
return _super.prototype.getForwardRay.call(this, length, this.leftCamera.getWorldMatrix(), this.leftCamera.globalPosition); // Need the actual rendered camera
}
else {
return _super.prototype.getForwardRay.call(this, length);
}
};
/**
* Updates the camera based on device's frame data
*/
WebVRFreeCamera.prototype._checkInputs = function () {
if (this._vrDevice && this._vrDevice.isPresenting) {
this._vrDevice.getFrameData(this._frameData);
this.updateFromDevice(this._frameData.pose);
}
_super.prototype._checkInputs.call(this);
};
/**
* Updates the poseControlled values based on the input device pose.
* @param poseData Pose coming from the device
*/
WebVRFreeCamera.prototype.updateFromDevice = function (poseData) {
if (poseData && poseData.orientation) {
this.rawPose = poseData;
this._deviceRoomRotationQuaternion.copyFromFloats(poseData.orientation[0], poseData.orientation[1], -poseData.orientation[2], -poseData.orientation[3]);
if (this.getScene().useRightHandedSystem) {
this._deviceRoomRotationQuaternion.z *= -1;
this._deviceRoomRotationQuaternion.w *= -1;
}
if (this.webVROptions.trackPosition && this.rawPose.position) {
this._deviceRoomPosition.copyFromFloats(this.rawPose.position[0], this.rawPose.position[1], -this.rawPose.position[2]);
if (this.getScene().useRightHandedSystem) {
this._deviceRoomPosition.z *= -1;
}
}
}
};
/**
* WebVR's attach control will start broadcasting frames to the device.
* Note that in certain browsers (chrome for example) this function must be called
* within a user-interaction callback. Example:
* scene.onPointerDown = function() { camera.attachControl(canvas); }
*
* @param element html element to attach the vrDevice to
* @param noPreventDefault prevent the default html element operation when attaching the vrDevice
*/
WebVRFreeCamera.prototype.attachControl = function (element, noPreventDefault) {
_super.prototype.attachControl.call(this, element, noPreventDefault);
this._attached = true;
noPreventDefault = BABYLON.Camera.ForceAttachControlToAlwaysPreventDefault ? false : noPreventDefault;
if (this._vrDevice) {
this.getEngine().enableVR();
}
};
/**
* Detaches the camera from the html element and disables VR
*
* @param element html element to detach from
*/
WebVRFreeCamera.prototype.detachControl = function (element) {
this.getScene().gamepadManager.onGamepadConnectedObservable.remove(this._onGamepadConnectedObserver);
this.getScene().gamepadManager.onGamepadDisconnectedObservable.remove(this._onGamepadDisconnectedObserver);
_super.prototype.detachControl.call(this, element);
this._attached = false;
this.getEngine().disableVR();
};
/**
* @returns the name of this class
*/
WebVRFreeCamera.prototype.getClassName = function () {
return "WebVRFreeCamera";
};
/**
* Calls resetPose on the vrDisplay
* See: https://developer.mozilla.org/en-US/docs/Web/API/VRDisplay/resetPose
*/
WebVRFreeCamera.prototype.resetToCurrentRotation = function () {
//uses the vrDisplay's "resetPose()".
//pitch and roll won't be affected.
this._vrDevice.resetPose();
};
/**
* Updates the rig cameras (left and right eye)
*/
WebVRFreeCamera.prototype._updateRigCameras = function () {
var camLeft = this._rigCameras[0];
var camRight = this._rigCameras[1];
camLeft.rotationQuaternion.copyFrom(this._deviceRoomRotationQuaternion);
camRight.rotationQuaternion.copyFrom(this._deviceRoomRotationQuaternion);
camLeft.position.copyFrom(this._deviceRoomPosition);
camRight.position.copyFrom(this._deviceRoomPosition);
};
/**
* Updates the cached values of the camera
* @param ignoreParentClass ignores updating the parent class's cache (default: false)
*/
WebVRFreeCamera.prototype._updateCache = function (ignoreParentClass) {
var _this = this;
if (!this.rotationQuaternion.equals(this._cache.rotationQuaternion) || !this.position.equals(this._cache.position)) {
// Update to ensure devicePosition is up to date with most recent _deviceRoomPosition
if (!this.updateCacheCalled) {
// make sure it is only called once per loop. this.update() might cause an infinite loop.
this.updateCacheCalled = true;
this.update();
}
// Set working vector to the device position in room space rotated by the new rotation
this.rotationQuaternion.toRotationMatrix(this._workingMatrix);
BABYLON.Vector3.TransformCoordinatesToRef(this._deviceRoomPosition, this._workingMatrix, this._workingVector);
// Subtract this vector from the current device position in world to get the translation for the device world matrix
this.devicePosition.subtractToRef(this._workingVector, this._workingVector);
BABYLON.Matrix.ComposeToRef(this._oneVector, this.rotationQuaternion, this._workingVector, this._deviceToWorld);
// Add translation from anchor position
this._deviceToWorld.getTranslationToRef(this._workingVector);
this._workingVector.addInPlace(this.position);
this._workingVector.subtractInPlace(this._cache.position);
this._deviceToWorld.setTranslation(this._workingVector);
// Set an inverted matrix to be used when updating the camera
this._deviceToWorld.invertToRef(this._worldToDevice);
// Update the gamepad to ensure the mesh is updated on the same frame as camera
this.controllers.forEach(function (controller) {
controller._deviceToWorld.copyFrom(_this._deviceToWorld);
controller.update();
});
}
if (!ignoreParentClass) {
_super.prototype._updateCache.call(this);
}
this.updateCacheCalled = false;
};
/**
* Updates the current device position and rotation in the babylon world
*/
WebVRFreeCamera.prototype.update = function () {
// Get current device position in babylon world
BABYLON.Vector3.TransformCoordinatesToRef(this._deviceRoomPosition, this._deviceToWorld, this.devicePosition);
// Get current device rotation in babylon world
BABYLON.Matrix.FromQuaternionToRef(this._deviceRoomRotationQuaternion, this._workingMatrix);
this._workingMatrix.multiplyToRef(this._deviceToWorld, this._workingMatrix);
BABYLON.Quaternion.FromRotationMatrixToRef(this._workingMatrix, this.deviceRotationQuaternion);
_super.prototype.update.call(this);
};
/**
* Gets the view matrix of this camera (Always set to identity as left and right eye cameras contain the actual view matrix)
* @returns an identity matrix
*/
WebVRFreeCamera.prototype._getViewMatrix = function () {
return BABYLON.Matrix.Identity();
};
/**
* This function is called by the two RIG cameras.
* 'this' is the left or right camera (and NOT (!!!) the WebVRFreeCamera instance)
*/
WebVRFreeCamera.prototype._getWebVRViewMatrix = function () {
var _this = this;
// Update the parent camera prior to using a child camera to avoid desynchronization
var parentCamera = this._cameraRigParams["parentCamera"];
parentCamera._updateCache();
//WebVR 1.1
var viewArray = this._cameraRigParams["left"] ? this._cameraRigParams["frameData"].leftViewMatrix : this._cameraRigParams["frameData"].rightViewMatrix;
BABYLON.Matrix.FromArrayToRef(viewArray, 0, this._webvrViewMatrix);
if (!this.getScene().useRightHandedSystem) {
[2, 6, 8, 9, 14].forEach(function (num) {
_this._webvrViewMatrix.m[num] *= -1;
});
}
// update the camera rotation matrix
this._webvrViewMatrix.getRotationMatrixToRef(this._cameraRotationMatrix);
BABYLON.Vector3.TransformCoordinatesToRef(this._referencePoint, this._cameraRotationMatrix, this._transformedReferencePoint);
// Computing target and final matrix
this.position.addToRef(this._transformedReferencePoint, this._currentTarget);
// should the view matrix be updated with scale and position offset?
if (parentCamera.deviceScaleFactor !== 1) {
this._webvrViewMatrix.invert();
// scale the position, if set
if (parentCamera.deviceScaleFactor) {
this._webvrViewMatrix.m[12] *= parentCamera.deviceScaleFactor;
this._webvrViewMatrix.m[13] *= parentCamera.deviceScaleFactor;
this._webvrViewMatrix.m[14] *= parentCamera.deviceScaleFactor;
}
this._webvrViewMatrix.invert();
}
parentCamera._worldToDevice.multiplyToRef(this._webvrViewMatrix, this._webvrViewMatrix);
return this._webvrViewMatrix;
};
WebVRFreeCamera.prototype._getWebVRProjectionMatrix = function () {
var _this = this;
var parentCamera = this.parent;
parentCamera._vrDevice.depthNear = parentCamera.minZ;
parentCamera._vrDevice.depthFar = parentCamera.maxZ;
var projectionArray = this._cameraRigParams["left"] ? this._cameraRigParams["frameData"].leftProjectionMatrix : this._cameraRigParams["frameData"].rightProjectionMatrix;
BABYLON.Matrix.FromArrayToRef(projectionArray, 0, this._projectionMatrix);
//babylon compatible matrix
if (!this.getScene().useRightHandedSystem) {
[8, 9, 10, 11].forEach(function (num) {
_this._projectionMatrix.m[num] *= -1;
});
}
return this._projectionMatrix;
};
/**
* Initializes the controllers and their meshes
*/
WebVRFreeCamera.prototype.initControllers = function () {
var _this = this;
this.controllers = [];
var manager = this.getScene().gamepadManager;
this._onGamepadDisconnectedObserver = manager.onGamepadDisconnectedObservable.add(function (gamepad) {
if (gamepad.type === BABYLON.Gamepad.POSE_ENABLED) {
var webVrController = gamepad;
if (webVrController.defaultModel) {
webVrController.defaultModel.setEnabled(false);
}
if (webVrController.hand === "right") {
_this._rightController = null;
}
if (webVrController.hand === "left") {
_this._leftController = null;
}
var controllerIndex = _this.controllers.indexOf(webVrController);
if (controllerIndex !== -1) {
_this.controllers.splice(controllerIndex, 1);
}
}
});
this._onGamepadConnectedObserver = manager.onGamepadConnectedObservable.add(function (gamepad) {
if (gamepad.type === BABYLON.Gamepad.POSE_ENABLED) {
var webVrController_1 = gamepad;
webVrController_1.deviceScaleFactor = _this.deviceScaleFactor;
webVrController_1._deviceToWorld.copyFrom(_this._deviceToWorld);
if (_this.webVROptions.controllerMeshes) {
if (webVrController_1.defaultModel) {
webVrController_1.defaultModel.setEnabled(true);
}
else {
// Load the meshes
webVrController_1.initControllerMesh(_this.getScene(), function (loadedMesh) {
loadedMesh.scaling.scaleInPlace(_this.deviceScaleFactor);
_this.onControllerMeshLoadedObservable.notifyObservers(webVrController_1);
if (_this.webVROptions.defaultLightingOnControllers) {
if (!_this._lightOnControllers) {
_this._lightOnControllers = new BABYLON.HemisphericLight("vrControllersLight", new BABYLON.Vector3(0, 1, 0), _this.getScene());
}
var activateLightOnSubMeshes_1 = function (mesh, light) {
var children = mesh.getChildren();
if (children.length !== 0) {
children.forEach(function (mesh) {
light.includedOnlyMeshes.push(mesh);
activateLightOnSubMeshes_1(mesh, light);
});
}
};
_this._lightOnControllers.includedOnlyMeshes.push(loadedMesh);
activateLightOnSubMeshes_1(loadedMesh, _this._lightOnControllers);
}
});
}
}
webVrController_1.attachToPoseControlledCamera(_this);
// since this is async - sanity check. Is the controller already stored?
if (_this.controllers.indexOf(webVrController_1) === -1) {
//add to the controllers array
_this.controllers.push(webVrController_1);
// Forced to add some control code for Vive as it doesn't always fill properly the "hand" property
// Sometimes, both controllers are set correctly (left and right), sometimes none, sometimes only one of them...
// So we're overriding setting left & right manually to be sure
var firstViveWandDetected = false;
for (var i = 0; i < _this.controllers.length; i++) {
if (_this.controllers[i].controllerType === BABYLON.PoseEnabledControllerType.VIVE) {
if (!firstViveWandDetected) {
firstViveWandDetected = true;
_this.controllers[i].hand = "left";
}
else {
_this.controllers[i].hand = "right";
}
}
}
//did we find enough controllers? Great! let the developer know.
if (_this.controllers.length >= 2) {
_this.onControllersAttachedObservable.notifyObservers(_this.controllers);
}
}
}
});
};
return WebVRFreeCamera;
}(BABYLON.FreeCamera));
BABYLON.WebVRFreeCamera = WebVRFreeCamera;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.webVRCamera.js.map
var BABYLON;
(function (BABYLON) {
// We're mainly based on the logic defined into the FreeCamera code
/**
* This is a camera specifically designed to react to device orientation events such as a modern mobile device
* being tilted forward or back and left or right.
*/
var DeviceOrientationCamera = /** @class */ (function (_super) {
__extends(DeviceOrientationCamera, _super);
/**
* Creates a new device orientation camera. @see DeviceOrientationCamera
* @param name The name of the camera
* @param position The start position camera
* @param scene The scene the camera belongs to
*/
function DeviceOrientationCamera(name, position, scene) {
var _this = _super.call(this, name, position, scene) || this;
_this._quaternionCache = new BABYLON.Quaternion();
_this.inputs.addDeviceOrientation();
return _this;
}
/**
* Gets the current instance class name ("DeviceOrientationCamera").
* This helps avoiding instanceof at run time.
* @returns the class name
*/
DeviceOrientationCamera.prototype.getClassName = function () {
return "DeviceOrientationCamera";
};
/**
* Checks and applies the current values of the inputs to the camera. (Internal use only)
*/
DeviceOrientationCamera.prototype._checkInputs = function () {
_super.prototype._checkInputs.call(this);
this._quaternionCache.copyFrom(this.rotationQuaternion);
if (this._initialQuaternion) {
this._initialQuaternion.multiplyToRef(this.rotationQuaternion, this.rotationQuaternion);
}
};
/**
* Reset the camera to its default orientation on the specified axis only.
* @param axis The axis to reset
*/
DeviceOrientationCamera.prototype.resetToCurrentRotation = function (axis) {
var _this = this;
if (axis === void 0) { axis = BABYLON.Axis.Y; }
//can only work if this camera has a rotation quaternion already.
if (!this.rotationQuaternion)
return;
if (!this._initialQuaternion) {
this._initialQuaternion = new BABYLON.Quaternion();
}
this._initialQuaternion.copyFrom(this._quaternionCache || this.rotationQuaternion);
['x', 'y', 'z'].forEach(function (axisName) {
if (!axis[axisName]) {
_this._initialQuaternion[axisName] = 0;
}
else {
_this._initialQuaternion[axisName] *= -1;
}
});
this._initialQuaternion.normalize();
//force rotation update
this._initialQuaternion.multiplyToRef(this.rotationQuaternion, this.rotationQuaternion);
};
return DeviceOrientationCamera;
}(BABYLON.FreeCamera));
BABYLON.DeviceOrientationCamera = DeviceOrientationCamera;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.deviceOrientationCamera.js.map
var BABYLON;
(function (BABYLON) {
var VRDeviceOrientationFreeCamera = /** @class */ (function (_super) {
__extends(VRDeviceOrientationFreeCamera, _super);
function VRDeviceOrientationFreeCamera(name, position, scene, compensateDistortion, vrCameraMetrics) {
if (compensateDistortion === void 0) { compensateDistortion = true; }
if (vrCameraMetrics === void 0) { vrCameraMetrics = BABYLON.VRCameraMetrics.GetDefault(); }
var _this = _super.call(this, name, position, scene) || this;
vrCameraMetrics.compensateDistortion = compensateDistortion;
_this.setCameraRigMode(BABYLON.Camera.RIG_MODE_VR, { vrCameraMetrics: vrCameraMetrics });
return _this;
}
VRDeviceOrientationFreeCamera.prototype.getClassName = function () {
return "VRDeviceOrientationFreeCamera";
};
return VRDeviceOrientationFreeCamera;
}(BABYLON.DeviceOrientationCamera));
BABYLON.VRDeviceOrientationFreeCamera = VRDeviceOrientationFreeCamera;
var VRDeviceOrientationGamepadCamera = /** @class */ (function (_super) {
__extends(VRDeviceOrientationGamepadCamera, _super);
function VRDeviceOrientationGamepadCamera(name, position, scene, compensateDistortion, vrCameraMetrics) {
if (compensateDistortion === void 0) { compensateDistortion = true; }
if (vrCameraMetrics === void 0) { vrCameraMetrics = BABYLON.VRCameraMetrics.GetDefault(); }
var _this = _super.call(this, name, position, scene, compensateDistortion, vrCameraMetrics) || this;
_this.inputs.addGamepad();
return _this;
}
VRDeviceOrientationGamepadCamera.prototype.getClassName = function () {
return "VRDeviceOrientationGamepadCamera";
};
return VRDeviceOrientationGamepadCamera;
}(VRDeviceOrientationFreeCamera));
BABYLON.VRDeviceOrientationGamepadCamera = VRDeviceOrientationGamepadCamera;
var VRDeviceOrientationArcRotateCamera = /** @class */ (function (_super) {
__extends(VRDeviceOrientationArcRotateCamera, _super);
function VRDeviceOrientationArcRotateCamera(name, alpha, beta, radius, target, scene, compensateDistortion, vrCameraMetrics) {
if (compensateDistortion === void 0) { compensateDistortion = true; }
if (vrCameraMetrics === void 0) { vrCameraMetrics = BABYLON.VRCameraMetrics.GetDefault(); }
var _this = _super.call(this, name, alpha, beta, radius, target, scene) || this;
vrCameraMetrics.compensateDistortion = compensateDistortion;
_this.setCameraRigMode(BABYLON.Camera.RIG_MODE_VR, { vrCameraMetrics: vrCameraMetrics });
_this.inputs.addVRDeviceOrientation();
return _this;
}
VRDeviceOrientationArcRotateCamera.prototype.getClassName = function () {
return "VRDeviceOrientationArcRotateCamera";
};
return VRDeviceOrientationArcRotateCamera;
}(BABYLON.ArcRotateCamera));
BABYLON.VRDeviceOrientationArcRotateCamera = VRDeviceOrientationArcRotateCamera;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.vrDeviceOrientationCamera.js.map
var BABYLON;
(function (BABYLON) {
var AnaglyphFreeCamera = /** @class */ (function (_super) {
__extends(AnaglyphFreeCamera, _super);
function AnaglyphFreeCamera(name, position, interaxialDistance, scene) {
var _this = _super.call(this, name, position, scene) || this;
_this.interaxialDistance = interaxialDistance;
_this.setCameraRigMode(BABYLON.Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH, { interaxialDistance: interaxialDistance });
return _this;
}
AnaglyphFreeCamera.prototype.getClassName = function () {
return "AnaglyphFreeCamera";
};
return AnaglyphFreeCamera;
}(BABYLON.FreeCamera));
BABYLON.AnaglyphFreeCamera = AnaglyphFreeCamera;
var AnaglyphArcRotateCamera = /** @class */ (function (_super) {
__extends(AnaglyphArcRotateCamera, _super);
function AnaglyphArcRotateCamera(name, alpha, beta, radius, target, interaxialDistance, scene) {
var _this = _super.call(this, name, alpha, beta, radius, target, scene) || this;
_this.interaxialDistance = interaxialDistance;
_this.setCameraRigMode(BABYLON.Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH, { interaxialDistance: interaxialDistance });
return _this;
}
AnaglyphArcRotateCamera.prototype.getClassName = function () {
return "AnaglyphArcRotateCamera";
};
return AnaglyphArcRotateCamera;
}(BABYLON.ArcRotateCamera));
BABYLON.AnaglyphArcRotateCamera = AnaglyphArcRotateCamera;
var AnaglyphGamepadCamera = /** @class */ (function (_super) {
__extends(AnaglyphGamepadCamera, _super);
function AnaglyphGamepadCamera(name, position, interaxialDistance, scene) {
var _this = _super.call(this, name, position, scene) || this;
_this.interaxialDistance = interaxialDistance;
_this.setCameraRigMode(BABYLON.Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH, { interaxialDistance: interaxialDistance });
return _this;
}
AnaglyphGamepadCamera.prototype.getClassName = function () {
return "AnaglyphGamepadCamera";
};
return AnaglyphGamepadCamera;
}(BABYLON.GamepadCamera));
BABYLON.AnaglyphGamepadCamera = AnaglyphGamepadCamera;
var AnaglyphUniversalCamera = /** @class */ (function (_super) {
__extends(AnaglyphUniversalCamera, _super);
function AnaglyphUniversalCamera(name, position, interaxialDistance, scene) {
var _this = _super.call(this, name, position, scene) || this;
_this.interaxialDistance = interaxialDistance;
_this.setCameraRigMode(BABYLON.Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH, { interaxialDistance: interaxialDistance });
return _this;
}
AnaglyphUniversalCamera.prototype.getClassName = function () {
return "AnaglyphUniversalCamera";
};
return AnaglyphUniversalCamera;
}(BABYLON.UniversalCamera));
BABYLON.AnaglyphUniversalCamera = AnaglyphUniversalCamera;
var StereoscopicFreeCamera = /** @class */ (function (_super) {
__extends(StereoscopicFreeCamera, _super);
function StereoscopicFreeCamera(name, position, interaxialDistance, isStereoscopicSideBySide, scene) {
var _this = _super.call(this, name, position, scene) || this;
_this.interaxialDistance = interaxialDistance;
_this.isStereoscopicSideBySide = isStereoscopicSideBySide;
_this.setCameraRigMode(isStereoscopicSideBySide ? BABYLON.Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL : BABYLON.Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER, { interaxialDistance: interaxialDistance });
return _this;
}
StereoscopicFreeCamera.prototype.getClassName = function () {
return "StereoscopicFreeCamera";
};
return StereoscopicFreeCamera;
}(BABYLON.FreeCamera));
BABYLON.StereoscopicFreeCamera = StereoscopicFreeCamera;
var StereoscopicArcRotateCamera = /** @class */ (function (_super) {
__extends(StereoscopicArcRotateCamera, _super);
function StereoscopicArcRotateCamera(name, alpha, beta, radius, target, interaxialDistance, isStereoscopicSideBySide, scene) {
var _this = _super.call(this, name, alpha, beta, radius, target, scene) || this;
_this.interaxialDistance = interaxialDistance;
_this.isStereoscopicSideBySide = isStereoscopicSideBySide;
_this.setCameraRigMode(isStereoscopicSideBySide ? BABYLON.Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL : BABYLON.Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER, { interaxialDistance: interaxialDistance });
return _this;
}
StereoscopicArcRotateCamera.prototype.getClassName = function () {
return "StereoscopicArcRotateCamera";
};
return StereoscopicArcRotateCamera;
}(BABYLON.ArcRotateCamera));
BABYLON.StereoscopicArcRotateCamera = StereoscopicArcRotateCamera;
var StereoscopicGamepadCamera = /** @class */ (function (_super) {
__extends(StereoscopicGamepadCamera, _super);
function StereoscopicGamepadCamera(name, position, interaxialDistance, isStereoscopicSideBySide, scene) {
var _this = _super.call(this, name, position, scene) || this;
_this.interaxialDistance = interaxialDistance;
_this.isStereoscopicSideBySide = isStereoscopicSideBySide;
_this.setCameraRigMode(isStereoscopicSideBySide ? BABYLON.Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL : BABYLON.Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER, { interaxialDistance: interaxialDistance });
return _this;
}
StereoscopicGamepadCamera.prototype.getClassName = function () {
return "StereoscopicGamepadCamera";
};
return StereoscopicGamepadCamera;
}(BABYLON.GamepadCamera));
BABYLON.StereoscopicGamepadCamera = StereoscopicGamepadCamera;
var StereoscopicUniversalCamera = /** @class */ (function (_super) {
__extends(StereoscopicUniversalCamera, _super);
function StereoscopicUniversalCamera(name, position, interaxialDistance, isStereoscopicSideBySide, scene) {
var _this = _super.call(this, name, position, scene) || this;
_this.interaxialDistance = interaxialDistance;
_this.isStereoscopicSideBySide = isStereoscopicSideBySide;
_this.setCameraRigMode(isStereoscopicSideBySide ? BABYLON.Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL : BABYLON.Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER, { interaxialDistance: interaxialDistance });
return _this;
}
StereoscopicUniversalCamera.prototype.getClassName = function () {
return "StereoscopicUniversalCamera";
};
return StereoscopicUniversalCamera;
}(BABYLON.UniversalCamera));
BABYLON.StereoscopicUniversalCamera = StereoscopicUniversalCamera;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.stereoscopicCameras.js.map
var BABYLON;
(function (BABYLON) {
var VRExperienceHelperGazer = /** @class */ (function () {
function VRExperienceHelperGazer(scene, gazeTrackerToClone) {
if (gazeTrackerToClone === void 0) { gazeTrackerToClone = null; }
this.scene = scene;
this._pointerDownOnMeshAsked = false;
this._isActionableMesh = false;
this._teleportationRequestInitiated = false;
this._teleportationBackRequestInitiated = false;
this._dpadPressed = true;
this._activePointer = false;
this._id = VRExperienceHelperGazer._idCounter++;
// Gaze tracker
if (!gazeTrackerToClone) {
this._gazeTracker = BABYLON.Mesh.CreateTorus("gazeTracker", 0.0035, 0.0025, 20, scene, false);
this._gazeTracker.bakeCurrentTransformIntoVertices();
this._gazeTracker.isPickable = false;
this._gazeTracker.isVisible = false;
var targetMat = new BABYLON.StandardMaterial("targetMat", scene);
targetMat.specularColor = BABYLON.Color3.Black();
targetMat.emissiveColor = new BABYLON.Color3(0.7, 0.7, 0.7);
targetMat.backFaceCulling = false;
this._gazeTracker.material = targetMat;
}
else {
this._gazeTracker = gazeTrackerToClone.clone("gazeTracker");
}
}
VRExperienceHelperGazer.prototype._getForwardRay = function (length) {
return new BABYLON.Ray(BABYLON.Vector3.Zero(), new BABYLON.Vector3(0, 0, length));
};
VRExperienceHelperGazer.prototype._selectionPointerDown = function () {
this._pointerDownOnMeshAsked = true;
if (this._currentMeshSelected && this._currentHit) {
this.scene.simulatePointerDown(this._currentHit, { pointerId: this._id });
}
};
VRExperienceHelperGazer.prototype._selectionPointerUp = function () {
if (this._currentMeshSelected && this._currentHit) {
this.scene.simulatePointerUp(this._currentHit, { pointerId: this._id });
}
this._pointerDownOnMeshAsked = false;
};
VRExperienceHelperGazer.prototype._activatePointer = function () {
this._activePointer = true;
};
VRExperienceHelperGazer.prototype._deactivatePointer = function () {
this._activePointer = false;
};
VRExperienceHelperGazer.prototype._updatePointerDistance = function (distance) {
};
VRExperienceHelperGazer.prototype.dispose = function () {
this._interactionsEnabled = false;
this._teleportationEnabled = false;
};
VRExperienceHelperGazer._idCounter = 0;
return VRExperienceHelperGazer;
}());
var VRExperienceHelperControllerGazer = /** @class */ (function (_super) {
__extends(VRExperienceHelperControllerGazer, _super);
function VRExperienceHelperControllerGazer(webVRController, scene, gazeTrackerToClone) {
var _this = _super.call(this, scene, gazeTrackerToClone) || this;
_this.webVRController = webVRController;
// Laser pointer
_this._laserPointer = BABYLON.Mesh.CreateCylinder("laserPointer", 1, 0.004, 0.0002, 20, 1, scene, false);
var laserPointerMaterial = new BABYLON.StandardMaterial("laserPointerMat", scene);
laserPointerMaterial.emissiveColor = new BABYLON.Color3(0.7, 0.7, 0.7);
laserPointerMaterial.alpha = 0.6;
_this._laserPointer.material = laserPointerMaterial;
_this._laserPointer.rotation.x = Math.PI / 2;
_this._laserPointer.position.z = -0.5;
_this._laserPointer.isVisible = false;
if (!webVRController.mesh) {
// Create an empty mesh that is used prior to loading the high quality model
var preloadMesh = new BABYLON.Mesh("preloadControllerMesh", scene);
var preloadPointerPose = new BABYLON.Mesh(BABYLON.PoseEnabledController.POINTING_POSE, scene);
preloadPointerPose.rotation.x = -0.7;
preloadMesh.addChild(preloadPointerPose);
webVRController.attachToMesh(preloadMesh);
}
_this._setLaserPointerParent(webVRController.mesh);
return _this;
}
VRExperienceHelperControllerGazer.prototype._getForwardRay = function (length) {
return this.webVRController.getForwardRay(length);
};
VRExperienceHelperControllerGazer.prototype._activatePointer = function () {
_super.prototype._activatePointer.call(this);
this._laserPointer.isVisible = true;
};
VRExperienceHelperControllerGazer.prototype._deactivatePointer = function () {
_super.prototype._deactivatePointer.call(this);
this._laserPointer.isVisible = false;
};
VRExperienceHelperControllerGazer.prototype._setLaserPointerColor = function (color) {
this._laserPointer.material.emissiveColor = color;
};
VRExperienceHelperControllerGazer.prototype._setLaserPointerParent = function (mesh) {
var makeNotPick = function (root) {
root.name += " laserPointer";
root.getChildMeshes().forEach(function (c) {
makeNotPick(c);
});
};
makeNotPick(mesh);
var childMeshes = mesh.getChildMeshes();
this.webVRController._pointingPoseNode = null;
for (var i = 0; i < childMeshes.length; i++) {
if (childMeshes[i].name && childMeshes[i].name.indexOf(BABYLON.PoseEnabledController.POINTING_POSE) >= 0) {
mesh = childMeshes[i];
this.webVRController._pointingPoseNode = mesh;
break;
}
}
this._laserPointer.parent = mesh;
};
VRExperienceHelperControllerGazer.prototype._updatePointerDistance = function (distance) {
this._laserPointer.scaling.y = distance;
this._laserPointer.position.z = -distance / 2;
};
VRExperienceHelperControllerGazer.prototype.dispose = function () {
_super.prototype.dispose.call(this);
this._laserPointer.dispose();
};
return VRExperienceHelperControllerGazer;
}(VRExperienceHelperGazer));
var VRExperienceHelperCameraGazer = /** @class */ (function (_super) {
__extends(VRExperienceHelperCameraGazer, _super);
function VRExperienceHelperCameraGazer(getCamera, scene) {
var _this = _super.call(this, scene) || this;
_this.getCamera = getCamera;
return _this;
}
VRExperienceHelperCameraGazer.prototype._getForwardRay = function (length) {
var camera = this.getCamera();
if (camera) {
return camera.getForwardRay(length);
}
else {
return new BABYLON.Ray(BABYLON.Vector3.Zero(), BABYLON.Vector3.Forward());
}
};
return VRExperienceHelperCameraGazer;
}(VRExperienceHelperGazer));
/**
* Helps to quickly add VR support to an existing scene.
* See http://doc.babylonjs.com/how_to/webvr_helper
*/
var VRExperienceHelper = /** @class */ (function () {
/**
* Instantiates a VRExperienceHelper.
* Helps to quickly add VR support to an existing scene.
* @param scene The scene the VRExperienceHelper belongs to.
* @param webVROptions Options to modify the vr experience helper's behavior.
*/
function VRExperienceHelper(scene, /** Options to modify the vr experience helper's behavior. */ webVROptions) {
if (webVROptions === void 0) { webVROptions = {}; }
var _this = this;
this.webVROptions = webVROptions;
// Can the system support WebVR, even if a headset isn't plugged in?
this._webVRsupported = false;
// If WebVR is supported, is a headset plugged in and are we ready to present?
this._webVRready = false;
// Are we waiting for the requestPresent callback to complete?
this._webVRrequesting = false;
// Are we presenting to the headset right now?
this._webVRpresenting = false;
// Are we presenting in the fullscreen fallback?
this._fullscreenVRpresenting = false;
/**
* Observable raised when entering VR.
*/
this.onEnteringVRObservable = new BABYLON.Observable();
/**
* Observable raised when exiting VR.
*/
this.onExitingVRObservable = new BABYLON.Observable();
/**
* Observable raised when controller mesh is loaded.
*/
this.onControllerMeshLoadedObservable = new BABYLON.Observable();
this._useCustomVRButton = false;
this._teleportationRequested = false;
this._teleportActive = false;
this._floorMeshesCollection = [];
this._rotationAllowed = true;
this._teleportBackwardsVector = new BABYLON.Vector3(0, -1, -1);
this._rotationRightAsked = false;
this._rotationLeftAsked = false;
this._isDefaultTeleportationTarget = true;
this._teleportationFillColor = "#444444";
this._teleportationBorderColor = "#FFFFFF";
this._rotationAngle = 0;
this._haloCenter = new BABYLON.Vector3(0, 0, 0);
this._padSensibilityUp = 0.65;
this._padSensibilityDown = 0.35;
this.leftController = null;
this.rightController = null;
/**
* Observable raised when a new mesh is selected based on meshSelectionPredicate
*/
this.onNewMeshSelected = new BABYLON.Observable();
/**
* Observable raised when a new mesh is picked based on meshSelectionPredicate
*/
this.onNewMeshPicked = new BABYLON.Observable();
/**
* Observable raised before camera teleportation
*/
this.onBeforeCameraTeleport = new BABYLON.Observable();
/**
* Observable raised after camera teleportation
*/
this.onAfterCameraTeleport = new BABYLON.Observable();
/**
* Observable raised when current selected mesh gets unselected
*/
this.onSelectedMeshUnselected = new BABYLON.Observable();
/**
* Set teleportation enabled. If set to false camera teleportation will be disabled but camera rotation will be kept.
*/
this.teleportationEnabled = true;
this._teleportationInitialized = false;
this._interactionsEnabled = false;
this._interactionsRequested = false;
this._displayGaze = true;
this._displayLaserPointer = true;
this._onResize = function () {
_this.moveButtonToBottomRight();
if (_this._fullscreenVRpresenting && _this._webVRready) {
_this.exitVR();
}
};
this._onFullscreenChange = function () {
if (document.fullscreen !== undefined) {
_this._fullscreenVRpresenting = document.fullscreen;
}
else if (document.mozFullScreen !== undefined) {
_this._fullscreenVRpresenting = document.mozFullScreen;
}
else if (document.webkitIsFullScreen !== undefined) {
_this._fullscreenVRpresenting = document.webkitIsFullScreen;
}
else if (document.msIsFullScreen !== undefined) {
_this._fullscreenVRpresenting = document.msIsFullScreen;
}
if (!_this._fullscreenVRpresenting && _this._canvas) {
_this.exitVR();
if (!_this._useCustomVRButton) {
_this._btnVR.style.top = _this._canvas.offsetTop + _this._canvas.offsetHeight - 70 + "px";
_this._btnVR.style.left = _this._canvas.offsetLeft + _this._canvas.offsetWidth - 100 + "px";
}
}
};
this.beforeRender = function () {
if (_this.leftController && _this.leftController._activePointer) {
_this._castRayAndSelectObject(_this.leftController);
}
if (_this.rightController && _this.rightController._activePointer) {
_this._castRayAndSelectObject(_this.rightController);
}
if (!(_this.leftController && _this.leftController._activePointer) && !(_this.rightController && _this.rightController._activePointer)) {
_this._castRayAndSelectObject(_this._cameraGazer);
}
else {
_this._cameraGazer._gazeTracker.isVisible = false;
}
};
this._onNewGamepadConnected = function (gamepad) {
if (gamepad.type !== BABYLON.Gamepad.POSE_ENABLED) {
if (gamepad.leftStick) {
gamepad.onleftstickchanged(function (stickValues) {
if (_this._teleportationInitialized && _this.teleportationEnabled) {
// Listening to classic/xbox gamepad only if no VR controller is active
if ((!_this.leftController && !_this.rightController) ||
((_this.leftController && !_this.leftController._activePointer) &&
(_this.rightController && !_this.rightController._activePointer))) {
_this._checkTeleportWithRay(stickValues, _this._cameraGazer);
_this._checkTeleportBackwards(stickValues, _this._cameraGazer);
}
}
});
}
if (gamepad.rightStick) {
gamepad.onrightstickchanged(function (stickValues) {
if (_this._teleportationInitialized) {
_this._checkRotate(stickValues, _this._cameraGazer);
}
});
}
if (gamepad.type === BABYLON.Gamepad.XBOX) {
gamepad.onbuttondown(function (buttonPressed) {
if (_this._interactionsEnabled && buttonPressed === BABYLON.Xbox360Button.A) {
_this._cameraGazer._selectionPointerDown();
}
});
gamepad.onbuttonup(function (buttonPressed) {
if (_this._interactionsEnabled && buttonPressed === BABYLON.Xbox360Button.A) {
_this._cameraGazer._selectionPointerUp();
}
});
}
}
else {
var webVRController = gamepad;
var controller = new VRExperienceHelperControllerGazer(webVRController, _this._scene, _this._cameraGazer._gazeTracker);
if (webVRController.hand === "right" || (_this.leftController && _this.leftController.webVRController != webVRController)) {
_this.rightController = controller;
}
else {
_this.leftController = controller;
}
_this._tryEnableInteractionOnController(controller);
}
};
// This only succeeds if the controller's mesh exists for the controller so this must be called whenever new controller is connected or when mesh is loaded
this._tryEnableInteractionOnController = function (controller) {
if (_this._interactionsRequested && !controller._interactionsEnabled) {
_this._enableInteractionOnController(controller);
}
if (_this._teleportationRequested && !controller._teleportationEnabled) {
_this._enableTeleportationOnController(controller);
}
};
this._onNewGamepadDisconnected = function (gamepad) {
if (gamepad instanceof BABYLON.WebVRController) {
if (gamepad.hand === "left" && _this.leftController != null) {
_this.leftController.dispose();
_this.leftController = null;
}
if (gamepad.hand === "right" && _this.rightController != null) {
_this.rightController.dispose();
_this.rightController = null;
}
}
};
this._workingVector = BABYLON.Vector3.Zero();
this._workingQuaternion = BABYLON.Quaternion.Identity();
this._workingMatrix = BABYLON.Matrix.Identity();
this._scene = scene;
this._canvas = scene.getEngine().getRenderingCanvas();
// Parse options
if (webVROptions.createFallbackVRDeviceOrientationFreeCamera === undefined) {
webVROptions.createFallbackVRDeviceOrientationFreeCamera = true;
}
if (webVROptions.createDeviceOrientationCamera === undefined) {
webVROptions.createDeviceOrientationCamera = true;
}
if (webVROptions.defaultHeight === undefined) {
webVROptions.defaultHeight = 1.7;
}
if (webVROptions.useCustomVRButton) {
this._useCustomVRButton = true;
if (webVROptions.customVRButton) {
this._btnVR = webVROptions.customVRButton;
}
}
if (webVROptions.rayLength) {
this._rayLength = webVROptions.rayLength;
}
this._defaultHeight = webVROptions.defaultHeight;
if (webVROptions.positionScale) {
this._rayLength *= webVROptions.positionScale;
this._defaultHeight *= webVROptions.positionScale;
}
// Set position
if (this._scene.activeCamera) {
this._position = this._scene.activeCamera.position.clone();
}
else {
this._position = new BABYLON.Vector3(0, this._defaultHeight, 0);
}
// Set non-vr camera
if (webVROptions.createDeviceOrientationCamera || !this._scene.activeCamera) {
this._deviceOrientationCamera = new BABYLON.DeviceOrientationCamera("deviceOrientationVRHelper", this._position.clone(), scene);
// Copy data from existing camera
if (this._scene.activeCamera) {
this._deviceOrientationCamera.minZ = this._scene.activeCamera.minZ;
this._deviceOrientationCamera.maxZ = this._scene.activeCamera.maxZ;
// Set rotation from previous camera
if (this._scene.activeCamera instanceof BABYLON.TargetCamera && this._scene.activeCamera.rotation) {
var targetCamera = this._scene.activeCamera;
if (targetCamera.rotationQuaternion) {
this._deviceOrientationCamera.rotationQuaternion.copyFrom(targetCamera.rotationQuaternion);
}
else {
this._deviceOrientationCamera.rotationQuaternion.copyFrom(BABYLON.Quaternion.RotationYawPitchRoll(targetCamera.rotation.y, targetCamera.rotation.x, targetCamera.rotation.z));
}
this._deviceOrientationCamera.rotation = targetCamera.rotation.clone();
}
}
this._scene.activeCamera = this._deviceOrientationCamera;
if (this._canvas) {
this._scene.activeCamera.attachControl(this._canvas);
}
}
else {
this._existingCamera = this._scene.activeCamera;
}
// Create VR cameras
if (webVROptions.createFallbackVRDeviceOrientationFreeCamera) {
this._vrDeviceOrientationCamera = new BABYLON.VRDeviceOrientationFreeCamera("VRDeviceOrientationVRHelper", this._position, this._scene);
}
this._webVRCamera = new BABYLON.WebVRFreeCamera("WebVRHelper", this._position, this._scene, webVROptions);
this._webVRCamera.useStandingMatrix();
this._cameraGazer = new VRExperienceHelperCameraGazer(function () { return _this.currentVRCamera; }, scene);
// Create default button
if (!this._useCustomVRButton) {
this._btnVR = document.createElement("BUTTON");
this._btnVR.className = "babylonVRicon";
this._btnVR.id = "babylonVRiconbtn";
this._btnVR.title = "Click to switch to VR";
var css = ".babylonVRicon { position: absolute; right: 20px; height: 50px; width: 80px; background-color: rgba(51,51,51,0.7); background-image: url(data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%222048%22%20height%3D%221152%22%20viewBox%3D%220%200%202048%201152%22%20version%3D%221.1%22%3E%3Cpath%20transform%3D%22rotate%28180%201024%2C576.0000000000001%29%22%20d%3D%22m1109%2C896q17%2C0%2030%2C-12t13%2C-30t-12.5%2C-30.5t-30.5%2C-12.5l-170%2C0q-18%2C0%20-30.5%2C12.5t-12.5%2C30.5t13%2C30t30%2C12l170%2C0zm-85%2C256q59%2C0%20132.5%2C-1.5t154.5%2C-5.5t164.5%2C-11.5t163%2C-20t150%2C-30t124.5%2C-41.5q23%2C-11%2042%2C-24t38%2C-30q27%2C-25%2041%2C-61.5t14%2C-72.5l0%2C-257q0%2C-123%20-47%2C-232t-128%2C-190t-190%2C-128t-232%2C-47l-81%2C0q-37%2C0%20-68.5%2C14t-60.5%2C34.5t-55.5%2C45t-53%2C45t-53%2C34.5t-55.5%2C14t-55.5%2C-14t-53%2C-34.5t-53%2C-45t-55.5%2C-45t-60.5%2C-34.5t-68.5%2C-14l-81%2C0q-123%2C0%20-232%2C47t-190%2C128t-128%2C190t-47%2C232l0%2C257q0%2C68%2038%2C115t97%2C73q54%2C24%20124.5%2C41.5t150%2C30t163%2C20t164.5%2C11.5t154.5%2C5.5t132.5%2C1.5zm939%2C-298q0%2C39%20-24.5%2C67t-58.5%2C42q-54%2C23%20-122%2C39.5t-143.5%2C28t-155.5%2C19t-157%2C11t-148.5%2C5t-129.5%2C1.5q-59%2C0%20-130%2C-1.5t-148%2C-5t-157%2C-11t-155.5%2C-19t-143.5%2C-28t-122%2C-39.5q-34%2C-14%20-58.5%2C-42t-24.5%2C-67l0%2C-257q0%2C-106%2040.5%2C-199t110%2C-162.5t162.5%2C-109.5t199%2C-40l81%2C0q27%2C0%2052%2C14t50%2C34.5t51%2C44.5t55.5%2C44.5t63.5%2C34.5t74%2C14t74%2C-14t63.5%2C-34.5t55.5%2C-44.5t51%2C-44.5t50%2C-34.5t52%2C-14l14%2C0q37%2C0%2070%2C0.5t64.5%2C4.5t63.5%2C12t68%2C23q71%2C30%20128.5%2C78.5t98.5%2C110t63.5%2C133.5t22.5%2C149l0%2C257z%22%20fill%3D%22white%22%20/%3E%3C/svg%3E%0A); background-size: 80%; background-repeat:no-repeat; background-position: center; border: none; outline: none; transition: transform 0.125s ease-out } .babylonVRicon:hover { transform: scale(1.05) } .babylonVRicon:active {background-color: rgba(51,51,51,1) } .babylonVRicon:focus {background-color: rgba(51,51,51,1) }";
css += ".babylonVRicon.vrdisplaypresenting { display: none; }";
// TODO: Add user feedback so that they know what state the VRDisplay is in (disconnected, connected, entering-VR)
// css += ".babylonVRicon.vrdisplaysupported { }";
// css += ".babylonVRicon.vrdisplayready { }";
// css += ".babylonVRicon.vrdisplayrequesting { }";
var style = document.createElement('style');
style.appendChild(document.createTextNode(css));
document.getElementsByTagName('head')[0].appendChild(style);
this.moveButtonToBottomRight();
}
// VR button click event
if (this._btnVR) {
this._btnVR.addEventListener("click", function () {
if (!_this.isInVRMode) {
_this.enterVR();
}
else {
_this.exitVR();
}
});
}
// Window events
window.addEventListener("resize", this._onResize);
document.addEventListener("fullscreenchange", this._onFullscreenChange, false);
document.addEventListener("mozfullscreenchange", this._onFullscreenChange, false);
document.addEventListener("webkitfullscreenchange", this._onFullscreenChange, false);
document.addEventListener("msfullscreenchange", this._onFullscreenChange, false);
// Display vr button when headset is connected
if (webVROptions.createFallbackVRDeviceOrientationFreeCamera) {
this.displayVRButton();
}
else {
this._scene.getEngine().onVRDisplayChangedObservable.add(function (e) {
if (e.vrDisplay) {
_this.displayVRButton();
}
});
}
// Exiting VR mode using 'ESC' key on desktop
this._onKeyDown = function (event) {
if (event.keyCode === 27 && _this.isInVRMode) {
_this.exitVR();
}
};
document.addEventListener("keydown", this._onKeyDown);
// Exiting VR mode double tapping the touch screen
this._scene.onPrePointerObservable.add(function (pointerInfo, eventState) {
if (_this.isInVRMode) {
_this.exitVR();
if (_this._fullscreenVRpresenting) {
_this._scene.getEngine().switchFullscreen(true);
}
}
}, BABYLON.PointerEventTypes.POINTERDOUBLETAP, false);
// Listen for WebVR display changes
this._onVRDisplayChanged = function (eventArgs) { return _this.onVRDisplayChanged(eventArgs); };
this._onVrDisplayPresentChange = function () { return _this.onVrDisplayPresentChange(); };
this._onVRRequestPresentStart = function () {
_this._webVRrequesting = true;
_this.updateButtonVisibility();
};
this._onVRRequestPresentComplete = function (success) {
_this._webVRrequesting = false;
_this.updateButtonVisibility();
};
scene.getEngine().onVRDisplayChangedObservable.add(this._onVRDisplayChanged);
scene.getEngine().onVRRequestPresentStart.add(this._onVRRequestPresentStart);
scene.getEngine().onVRRequestPresentComplete.add(this._onVRRequestPresentComplete);
window.addEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange);
scene.onDisposeObservable.add(function () {
_this.dispose();
});
// Gamepad connection events
this._webVRCamera.onControllerMeshLoadedObservable.add(function (webVRController) { return _this._onDefaultMeshLoaded(webVRController); });
this._scene.gamepadManager.onGamepadConnectedObservable.add(this._onNewGamepadConnected);
this._scene.gamepadManager.onGamepadDisconnectedObservable.add(this._onNewGamepadDisconnected);
this.updateButtonVisibility();
//create easing functions
this._circleEase = new BABYLON.CircleEase();
this._circleEase.setEasingMode(BABYLON.EasingFunction.EASINGMODE_EASEINOUT);
}
Object.defineProperty(VRExperienceHelper.prototype, "onEnteringVR", {
/** Return this.onEnteringVRObservable
* Note: This one is for backward compatibility. Please use onEnteringVRObservable directly
*/
get: function () {
return this.onEnteringVRObservable;
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "onExitingVR", {
/** Return this.onExitingVRObservable
* Note: This one is for backward compatibility. Please use onExitingVRObservable directly
*/
get: function () {
return this.onExitingVRObservable;
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "onControllerMeshLoaded", {
/** Return this.onControllerMeshLoadedObservable
* Note: This one is for backward compatibility. Please use onControllerMeshLoadedObservable directly
*/
get: function () {
return this.onControllerMeshLoadedObservable;
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "teleportationTarget", {
/**
* The mesh used to display where the user is going to teleport.
*/
get: function () {
return this._teleportationTarget;
},
/**
* Sets the mesh to be used to display where the user is going to teleport.
*/
set: function (value) {
if (value) {
value.name = "teleportationTarget";
this._isDefaultTeleportationTarget = false;
this._teleportationTarget = value;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "gazeTrackerMesh", {
/**
* The mesh used to display where the user is selecting,
* when set bakeCurrentTransformIntoVertices will be called on the mesh.
* See http://doc.babylonjs.com/resources/baking_transformations
*/
get: function () {
return this._cameraGazer._gazeTracker;
},
set: function (value) {
if (value) {
this._cameraGazer._gazeTracker = value;
this._cameraGazer._gazeTracker.bakeCurrentTransformIntoVertices();
this._cameraGazer._gazeTracker.isPickable = false;
this._cameraGazer._gazeTracker.isVisible = false;
this._cameraGazer._gazeTracker.name = "gazeTracker";
if (this.leftController) {
this.leftController._gazeTracker = this._cameraGazer._gazeTracker.clone("gazeTracker");
}
if (this.rightController) {
this.rightController._gazeTracker = this._cameraGazer._gazeTracker.clone("gazeTracker");
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "displayGaze", {
/**
* If the ray of the gaze should be displayed.
*/
get: function () {
return this._displayGaze;
},
/**
* Sets if the ray of the gaze should be displayed.
*/
set: function (value) {
this._displayGaze = value;
if (!value) {
this._cameraGazer._gazeTracker.isVisible = false;
if (this.leftController) {
this.leftController._gazeTracker.isVisible = false;
}
if (this.rightController) {
this.rightController._gazeTracker.isVisible = false;
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "displayLaserPointer", {
/**
* If the ray of the LaserPointer should be displayed.
*/
get: function () {
return this._displayLaserPointer;
},
/**
* Sets if the ray of the LaserPointer should be displayed.
*/
set: function (value) {
this._displayLaserPointer = value;
if (!value) {
if (this.rightController) {
this.rightController._deactivatePointer();
this.rightController._gazeTracker.isVisible = false;
}
if (this.leftController) {
this.leftController._deactivatePointer();
this.leftController._gazeTracker.isVisible = false;
}
}
else {
if (this.rightController) {
this.rightController._activatePointer();
}
else if (this.leftController) {
this.leftController._activatePointer();
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "deviceOrientationCamera", {
/**
* The deviceOrientationCamera used as the camera when not in VR.
*/
get: function () {
return this._deviceOrientationCamera;
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "currentVRCamera", {
/**
* Based on the current WebVR support, returns the current VR camera used.
*/
get: function () {
if (this._webVRready) {
return this._webVRCamera;
}
else {
return this._scene.activeCamera;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "webVRCamera", {
/**
* The webVRCamera which is used when in VR.
*/
get: function () {
return this._webVRCamera;
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "vrDeviceOrientationCamera", {
/**
* The deviceOrientationCamera that is used as a fallback when vr device is not connected.
*/
get: function () {
return this._vrDeviceOrientationCamera;
},
enumerable: true,
configurable: true
});
Object.defineProperty(VRExperienceHelper.prototype, "_teleportationRequestInitiated", {
get: function () {
var result = this._cameraGazer._teleportationRequestInitiated
|| (this.leftController !== null && this.leftController._teleportationRequestInitiated)
|| (this.rightController !== null && this.rightController._teleportationRequestInitiated);
return result;
},
enumerable: true,
configurable: true
});
// Raised when one of the controller has loaded successfully its associated default mesh
VRExperienceHelper.prototype._onDefaultMeshLoaded = function (webVRController) {
if (this.leftController && this.leftController.webVRController == webVRController) {
if (webVRController.mesh) {
this.leftController._setLaserPointerParent(webVRController.mesh);
}
}
if (this.rightController && this.rightController.webVRController == webVRController) {
if (webVRController.mesh) {
this.rightController._setLaserPointerParent(webVRController.mesh);
}
}
try {
this.onControllerMeshLoadedObservable.notifyObservers(webVRController);
}
catch (err) {
BABYLON.Tools.Warn("Error in your custom logic onControllerMeshLoaded: " + err);
}
};
Object.defineProperty(VRExperienceHelper.prototype, "isInVRMode", {
/**
* Gets a value indicating if we are currently in VR mode.
*/
get: function () {
return this._webVRpresenting || this._fullscreenVRpresenting;
},
enumerable: true,
configurable: true
});
VRExperienceHelper.prototype.onVrDisplayPresentChange = function () {
var vrDisplay = this._scene.getEngine().getVRDevice();
if (vrDisplay) {
var wasPresenting = this._webVRpresenting;
// A VR display is connected
this._webVRpresenting = vrDisplay.isPresenting;
if (wasPresenting && !this._webVRpresenting)
this.exitVR();
}
else {
BABYLON.Tools.Warn('Detected VRDisplayPresentChange on an unknown VRDisplay. Did you can enterVR on the vrExperienceHelper?');
}
this.updateButtonVisibility();
};
VRExperienceHelper.prototype.onVRDisplayChanged = function (eventArgs) {
this._webVRsupported = eventArgs.vrSupported;
this._webVRready = !!eventArgs.vrDisplay;
this._webVRpresenting = eventArgs.vrDisplay && eventArgs.vrDisplay.isPresenting;
this.updateButtonVisibility();
};
VRExperienceHelper.prototype.moveButtonToBottomRight = function () {
if (this._canvas && !this._useCustomVRButton) {
this._btnVR.style.top = this._canvas.offsetTop + this._canvas.offsetHeight - 70 + "px";
this._btnVR.style.left = this._canvas.offsetLeft + this._canvas.offsetWidth - 100 + "px";
}
};
VRExperienceHelper.prototype.displayVRButton = function () {
if (!this._useCustomVRButton && !this._btnVRDisplayed) {
document.body.appendChild(this._btnVR);
this._btnVRDisplayed = true;
}
};
VRExperienceHelper.prototype.updateButtonVisibility = function () {
if (!this._btnVR || this._useCustomVRButton) {
return;
}
this._btnVR.className = "babylonVRicon";
if (this.isInVRMode) {
this._btnVR.className += " vrdisplaypresenting";
}
else {
if (this._webVRready)
this._btnVR.className += " vrdisplayready";
if (this._webVRsupported)
this._btnVR.className += " vrdisplaysupported";
if (this._webVRrequesting)
this._btnVR.className += " vrdisplayrequesting";
}
};
/**
* Attempt to enter VR. If a headset is connected and ready, will request present on that.
* Otherwise, will use the fullscreen API.
*/
VRExperienceHelper.prototype.enterVR = function () {
if (this.onEnteringVRObservable) {
try {
this.onEnteringVRObservable.notifyObservers(this);
}
catch (err) {
BABYLON.Tools.Warn("Error in your custom logic onEnteringVR: " + err);
}
}
if (this._scene.activeCamera) {
this._position = this._scene.activeCamera.position.clone();
// make sure that we return to the last active camera
this._existingCamera = this._scene.activeCamera;
}
if (this._webVRrequesting)
return;
// If WebVR is supported and a headset is connected
if (this._webVRready) {
if (!this._webVRpresenting) {
this._webVRCamera.position = this._position;
this._scene.activeCamera = this._webVRCamera;
}
}
else if (this._vrDeviceOrientationCamera) {
this._vrDeviceOrientationCamera.position = this._position;
this._scene.activeCamera = this._vrDeviceOrientationCamera;
this._scene.getEngine().switchFullscreen(true);
this.updateButtonVisibility();
}
if (this._scene.activeCamera && this._canvas) {
this._scene.activeCamera.attachControl(this._canvas);
}
if (this._interactionsEnabled) {
this._scene.registerBeforeRender(this.beforeRender);
}
};
/**
* Attempt to exit VR, or fullscreen.
*/
VRExperienceHelper.prototype.exitVR = function () {
if (this.onExitingVRObservable) {
try {
this.onExitingVRObservable.notifyObservers(this);
}
catch (err) {
BABYLON.Tools.Warn("Error in your custom logic onExitingVR: " + err);
}
}
if (this._webVRpresenting) {
this._scene.getEngine().disableVR();
}
if (this._scene.activeCamera) {
this._position = this._scene.activeCamera.position.clone();
}
if (this._deviceOrientationCamera) {
this._deviceOrientationCamera.position = this._position;
this._scene.activeCamera = this._deviceOrientationCamera;
if (this._canvas) {
this._scene.activeCamera.attachControl(this._canvas);
}
}
else if (this._existingCamera) {
this._existingCamera.position = this._position;
this._scene.activeCamera = this._existingCamera;
}
this.updateButtonVisibility();
if (this._interactionsEnabled) {
this._scene.unregisterBeforeRender(this.beforeRender);
}
};
Object.defineProperty(VRExperienceHelper.prototype, "position", {
/**
* The position of the vr experience helper.
*/
get: function () {
return this._position;
},
/**
* Sets the position of the vr experience helper.
*/
set: function (value) {
this._position = value;
if (this._scene.activeCamera) {
this._scene.activeCamera.position = value;
}
},
enumerable: true,
configurable: true
});
/**
* Enables controllers and user interactions suck as selecting and object or clicking on an object.
*/
VRExperienceHelper.prototype.enableInteractions = function () {
var _this = this;
if (!this._interactionsEnabled) {
this._interactionsRequested = true;
if (this.leftController) {
this._enableInteractionOnController(this.leftController);
}
if (this.rightController) {
this._enableInteractionOnController(this.rightController);
}
this.raySelectionPredicate = function (mesh) {
return mesh.isVisible;
};
this.meshSelectionPredicate = function (mesh) {
return true;
};
this._raySelectionPredicate = function (mesh) {
if (_this._isTeleportationFloor(mesh) || (mesh.name.indexOf("gazeTracker") === -1
&& mesh.name.indexOf("teleportationTarget") === -1
&& mesh.name.indexOf("torusTeleportation") === -1
&& mesh.name.indexOf("laserPointer") === -1)) {
return _this.raySelectionPredicate(mesh);
}
return false;
};
this._interactionsEnabled = true;
}
};
VRExperienceHelper.prototype._isTeleportationFloor = function (mesh) {
for (var i = 0; i < this._floorMeshesCollection.length; i++) {
if (this._floorMeshesCollection[i].id === mesh.id) {
return true;
}
}
if (this._floorMeshName && mesh.name === this._floorMeshName) {
return true;
}
return false;
};
/**
* Adds a floor mesh to be used for teleportation.
* @param floorMesh the mesh to be used for teleportation.
*/
VRExperienceHelper.prototype.addFloorMesh = function (floorMesh) {
if (!this._floorMeshesCollection) {
return;
}
if (this._floorMeshesCollection.indexOf(floorMesh) > -1) {
return;
}
this._floorMeshesCollection.push(floorMesh);
};
/**
* Removes a floor mesh from being used for teleportation.
* @param floorMesh the mesh to be removed.
*/
VRExperienceHelper.prototype.removeFloorMesh = function (floorMesh) {
if (!this._floorMeshesCollection) {
return;
}
var meshIndex = this._floorMeshesCollection.indexOf(floorMesh);
if (meshIndex !== -1) {
this._floorMeshesCollection.splice(meshIndex, 1);
}
};
/**
* Enables interactions and teleportation using the VR controllers and gaze.
* @param vrTeleportationOptions options to modify teleportation behavior.
*/
VRExperienceHelper.prototype.enableTeleportation = function (vrTeleportationOptions) {
if (vrTeleportationOptions === void 0) { vrTeleportationOptions = {}; }
if (!this._teleportationInitialized) {
this._teleportationRequested = true;
this.enableInteractions();
if (vrTeleportationOptions.floorMeshName) {
this._floorMeshName = vrTeleportationOptions.floorMeshName;
}
if (vrTeleportationOptions.floorMeshes) {
this._floorMeshesCollection = vrTeleportationOptions.floorMeshes;
}
if (this.leftController != null) {
this._enableTeleportationOnController(this.leftController);
}
if (this.rightController != null) {
this._enableTeleportationOnController(this.rightController);
}
// Creates an image processing post process for the vignette not relying
// on the main scene configuration for image processing to reduce setup and spaces
// (gamma/linear) conflicts.
var imageProcessingConfiguration = new BABYLON.ImageProcessingConfiguration();
imageProcessingConfiguration.vignetteColor = new BABYLON.Color4(0, 0, 0, 0);
imageProcessingConfiguration.vignetteEnabled = true;
this._postProcessMove = new BABYLON.ImageProcessingPostProcess("postProcessMove", 1.0, this._webVRCamera, undefined, undefined, undefined, undefined, imageProcessingConfiguration);
this._webVRCamera.detachPostProcess(this._postProcessMove);
this._teleportationInitialized = true;
if (this._isDefaultTeleportationTarget) {
this._createTeleportationCircles();
this._teleportationTarget.scaling.scaleInPlace(this._webVRCamera.deviceScaleFactor);
}
}
};
VRExperienceHelper.prototype._enableInteractionOnController = function (controller) {
var _this = this;
var controllerMesh = controller.webVRController.mesh;
if (controllerMesh) {
controller._interactionsEnabled = true;
controller._activatePointer();
controller.webVRController.onMainButtonStateChangedObservable.add(function (stateObject) {
// Enabling / disabling laserPointer
if (_this._displayLaserPointer && stateObject.value === 1) {
if (controller._activePointer) {
controller._deactivatePointer();
}
else {
controller._activatePointer();
}
if (_this.displayGaze) {
controller._gazeTracker.isVisible = controller._activePointer;
}
}
});
controller.webVRController.onTriggerStateChangedObservable.add(function (stateObject) {
if (!controller._pointerDownOnMeshAsked) {
if (stateObject.value > _this._padSensibilityUp) {
controller._selectionPointerDown();
}
}
else if (stateObject.value < _this._padSensibilityDown) {
controller._selectionPointerUp();
}
});
}
};
VRExperienceHelper.prototype._checkTeleportWithRay = function (stateObject, gazer) {
// Dont teleport if another gaze already requested teleportation
if (this._teleportationRequestInitiated && !gazer._teleportationRequestInitiated) {
return;
}
if (!gazer._teleportationRequestInitiated) {
if (stateObject.y < -this._padSensibilityUp && gazer._dpadPressed) {
gazer._activatePointer();
gazer._teleportationRequestInitiated = true;
}
}
else {
// Listening to the proper controller values changes to confirm teleportation
if (Math.sqrt(stateObject.y * stateObject.y + stateObject.x * stateObject.x) < this._padSensibilityDown) {
if (this._teleportActive) {
this._teleportCamera(this._haloCenter);
}
gazer._teleportationRequestInitiated = false;
}
}
};
VRExperienceHelper.prototype._checkRotate = function (stateObject, gazer) {
// Only rotate when user is not currently selecting a teleportation location
if (gazer._teleportationRequestInitiated) {
return;
}
if (!this._rotationLeftAsked) {
if (stateObject.x < -this._padSensibilityUp && gazer._dpadPressed) {
this._rotationLeftAsked = true;
if (this._rotationAllowed) {
this._rotateCamera(false);
}
}
}
else {
if (stateObject.x > -this._padSensibilityDown) {
this._rotationLeftAsked = false;
}
}
if (!this._rotationRightAsked) {
if (stateObject.x > this._padSensibilityUp && gazer._dpadPressed) {
this._rotationRightAsked = true;
if (this._rotationAllowed) {
this._rotateCamera(true);
}
}
}
else {
if (stateObject.x < this._padSensibilityDown) {
this._rotationRightAsked = false;
}
}
};
VRExperienceHelper.prototype._checkTeleportBackwards = function (stateObject, gazer) {
// Only teleport backwards when user is not currently selecting a teleportation location
if (gazer._teleportationRequestInitiated) {
return;
}
// Teleport backwards
if (stateObject.y > this._padSensibilityUp && gazer._dpadPressed) {
if (!gazer._teleportationBackRequestInitiated) {
if (!this.currentVRCamera) {
return;
}
// Get rotation and position of the current camera
var rotation = BABYLON.Quaternion.FromRotationMatrix(this.currentVRCamera.getWorldMatrix().getRotationMatrix());
var position = this.currentVRCamera.position;
// If the camera has device position, use that instead
if (this.currentVRCamera.devicePosition && this.currentVRCamera.deviceRotationQuaternion) {
rotation = this.currentVRCamera.deviceRotationQuaternion;
position = this.currentVRCamera.devicePosition;
}
// Get matrix with only the y rotation of the device rotation
rotation.toEulerAnglesToRef(this._workingVector);
this._workingVector.z = 0;
this._workingVector.x = 0;
BABYLON.Quaternion.RotationYawPitchRollToRef(this._workingVector.y, this._workingVector.x, this._workingVector.z, this._workingQuaternion);
this._workingQuaternion.toRotationMatrix(this._workingMatrix);
// Rotate backwards ray by device rotation to cast at the ground behind the user
BABYLON.Vector3.TransformCoordinatesToRef(this._teleportBackwardsVector, this._workingMatrix, this._workingVector);
// Teleport if ray hit the ground and is not to far away eg. backwards off a cliff
var ray = new BABYLON.Ray(position, this._workingVector);
var hit = this._scene.pickWithRay(ray, this._raySelectionPredicate);
if (hit && hit.pickedPoint && hit.pickedMesh && this._isTeleportationFloor(hit.pickedMesh) && hit.distance < 5) {
this._teleportCamera(hit.pickedPoint);
}
gazer._teleportationBackRequestInitiated = true;
}
}
else {
gazer._teleportationBackRequestInitiated = false;
}
};
VRExperienceHelper.prototype._enableTeleportationOnController = function (controller) {
var _this = this;
var controllerMesh = controller.webVRController.mesh;
if (controllerMesh) {
if (!controller._interactionsEnabled) {
this._enableInteractionOnController(controller);
}
controller._interactionsEnabled = true;
controller._teleportationEnabled = true;
if (controller.webVRController.controllerType === BABYLON.PoseEnabledControllerType.VIVE) {
controller._dpadPressed = false;
controller.webVRController.onPadStateChangedObservable.add(function (stateObject) {
controller._dpadPressed = stateObject.pressed;
if (!controller._dpadPressed) {
_this._rotationLeftAsked = false;
_this._rotationRightAsked = false;
controller._teleportationBackRequestInitiated = false;
}
});
}
controller.webVRController.onPadValuesChangedObservable.add(function (stateObject) {
if (_this.teleportationEnabled) {
_this._checkTeleportBackwards(stateObject, controller);
_this._checkTeleportWithRay(stateObject, controller);
}
_this._checkRotate(stateObject, controller);
});
}
};
VRExperienceHelper.prototype._createTeleportationCircles = function () {
this._teleportationTarget = BABYLON.Mesh.CreateGround("teleportationTarget", 2, 2, 2, this._scene);
this._teleportationTarget.isPickable = false;
var length = 512;
var dynamicTexture = new BABYLON.DynamicTexture("DynamicTexture", length, this._scene, true);
dynamicTexture.hasAlpha = true;
var context = dynamicTexture.getContext();
var centerX = length / 2;
var centerY = length / 2;
var radius = 200;
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = this._teleportationFillColor;
context.fill();
context.lineWidth = 10;
context.strokeStyle = this._teleportationBorderColor;
context.stroke();
context.closePath();
dynamicTexture.update();
var teleportationCircleMaterial = new BABYLON.StandardMaterial("TextPlaneMaterial", this._scene);
teleportationCircleMaterial.diffuseTexture = dynamicTexture;
this._teleportationTarget.material = teleportationCircleMaterial;
var torus = BABYLON.Mesh.CreateTorus("torusTeleportation", 0.75, 0.1, 25, this._scene, false);
torus.isPickable = false;
torus.parent = this._teleportationTarget;
var animationInnerCircle = new BABYLON.Animation("animationInnerCircle", "position.y", 30, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
var keys = [];
keys.push({
frame: 0,
value: 0
});
keys.push({
frame: 30,
value: 0.4
});
keys.push({
frame: 60,
value: 0
});
animationInnerCircle.setKeys(keys);
var easingFunction = new BABYLON.SineEase();
easingFunction.setEasingMode(BABYLON.EasingFunction.EASINGMODE_EASEINOUT);
animationInnerCircle.setEasingFunction(easingFunction);
torus.animations = [];
torus.animations.push(animationInnerCircle);
this._scene.beginAnimation(torus, 0, 60, true);
this._hideTeleportationTarget();
};
VRExperienceHelper.prototype._displayTeleportationTarget = function () {
this._teleportActive = true;
if (this._teleportationInitialized) {
this._teleportationTarget.isVisible = true;
if (this._isDefaultTeleportationTarget) {
this._teleportationTarget.getChildren()[0].isVisible = true;
}
}
};
VRExperienceHelper.prototype._hideTeleportationTarget = function () {
this._teleportActive = false;
if (this._teleportationInitialized) {
this._teleportationTarget.isVisible = false;
if (this._isDefaultTeleportationTarget) {
this._teleportationTarget.getChildren()[0].isVisible = false;
}
}
};
VRExperienceHelper.prototype._rotateCamera = function (right) {
var _this = this;
if (!(this.currentVRCamera instanceof BABYLON.FreeCamera)) {
return;
}
if (right) {
this._rotationAngle++;
}
else {
this._rotationAngle--;
}
this.currentVRCamera.animations = [];
var target = BABYLON.Quaternion.FromRotationMatrix(BABYLON.Matrix.RotationY(Math.PI / 4 * this._rotationAngle));
var animationRotation = new BABYLON.Animation("animationRotation", "rotationQuaternion", 90, BABYLON.Animation.ANIMATIONTYPE_QUATERNION, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
var animationRotationKeys = [];
animationRotationKeys.push({
frame: 0,
value: this.currentVRCamera.rotationQuaternion
});
animationRotationKeys.push({
frame: 6,
value: target
});
animationRotation.setKeys(animationRotationKeys);
animationRotation.setEasingFunction(this._circleEase);
this.currentVRCamera.animations.push(animationRotation);
this._postProcessMove.animations = [];
var animationPP = new BABYLON.Animation("animationPP", "vignetteWeight", 90, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
var vignetteWeightKeys = [];
vignetteWeightKeys.push({
frame: 0,
value: 0
});
vignetteWeightKeys.push({
frame: 3,
value: 4
});
vignetteWeightKeys.push({
frame: 6,
value: 0
});
animationPP.setKeys(vignetteWeightKeys);
animationPP.setEasingFunction(this._circleEase);
this._postProcessMove.animations.push(animationPP);
var animationPP2 = new BABYLON.Animation("animationPP2", "vignetteStretch", 90, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
var vignetteStretchKeys = [];
vignetteStretchKeys.push({
frame: 0,
value: 0
});
vignetteStretchKeys.push({
frame: 3,
value: 10
});
vignetteStretchKeys.push({
frame: 6,
value: 0
});
animationPP2.setKeys(vignetteStretchKeys);
animationPP2.setEasingFunction(this._circleEase);
this._postProcessMove.animations.push(animationPP2);
this._postProcessMove.imageProcessingConfiguration.vignetteWeight = 0;
this._postProcessMove.imageProcessingConfiguration.vignetteStretch = 0;
this._postProcessMove.samples = 4;
this._webVRCamera.attachPostProcess(this._postProcessMove);
this._scene.beginAnimation(this._postProcessMove, 0, 6, false, 1, function () {
_this._webVRCamera.detachPostProcess(_this._postProcessMove);
});
this._scene.beginAnimation(this.currentVRCamera, 0, 6, false, 1);
};
VRExperienceHelper.prototype._moveTeleportationSelectorTo = function (hit, gazer) {
if (hit.pickedPoint) {
if (gazer._teleportationRequestInitiated) {
this._displayTeleportationTarget();
this._haloCenter.copyFrom(hit.pickedPoint);
this._teleportationTarget.position.copyFrom(hit.pickedPoint);
}
var pickNormal = hit.getNormal(true, false);
if (pickNormal) {
var axis1 = BABYLON.Vector3.Cross(BABYLON.Axis.Y, pickNormal);
var axis2 = BABYLON.Vector3.Cross(pickNormal, axis1);
BABYLON.Vector3.RotationFromAxisToRef(axis2, pickNormal, axis1, this._teleportationTarget.rotation);
}
this._teleportationTarget.position.y += 0.1;
}
};
VRExperienceHelper.prototype._teleportCamera = function (location) {
var _this = this;
if (!(this.currentVRCamera instanceof BABYLON.FreeCamera)) {
return;
}
// Teleport the hmd to where the user is looking by moving the anchor to where they are looking minus the
// offset of the headset from the anchor.
if (this.webVRCamera.leftCamera) {
this._workingVector.copyFrom(this.webVRCamera.leftCamera.globalPosition);
this._workingVector.subtractInPlace(this.webVRCamera.position);
location.subtractToRef(this._workingVector, this._workingVector);
}
else {
this._workingVector.copyFrom(location);
}
// Add height to account for user's height offset
if (this.isInVRMode) {
this._workingVector.y += this.webVRCamera.deviceDistanceToRoomGround() * this._webVRCamera.deviceScaleFactor;
}
else {
this._workingVector.y += this._defaultHeight;
}
this.onBeforeCameraTeleport.notifyObservers(this._workingVector);
// Create animation from the camera's position to the new location
this.currentVRCamera.animations = [];
var animationCameraTeleportation = new BABYLON.Animation("animationCameraTeleportation", "position", 90, BABYLON.Animation.ANIMATIONTYPE_VECTOR3, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
var animationCameraTeleportationKeys = [{
frame: 0,
value: this.currentVRCamera.position
},
{
frame: 11,
value: this._workingVector
}
];
animationCameraTeleportation.setKeys(animationCameraTeleportationKeys);
animationCameraTeleportation.setEasingFunction(this._circleEase);
this.currentVRCamera.animations.push(animationCameraTeleportation);
this._postProcessMove.animations = [];
var animationPP = new BABYLON.Animation("animationPP", "vignetteWeight", 90, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
var vignetteWeightKeys = [];
vignetteWeightKeys.push({
frame: 0,
value: 0
});
vignetteWeightKeys.push({
frame: 5,
value: 8
});
vignetteWeightKeys.push({
frame: 11,
value: 0
});
animationPP.setKeys(vignetteWeightKeys);
this._postProcessMove.animations.push(animationPP);
var animationPP2 = new BABYLON.Animation("animationPP2", "vignetteStretch", 90, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
var vignetteStretchKeys = [];
vignetteStretchKeys.push({
frame: 0,
value: 0
});
vignetteStretchKeys.push({
frame: 5,
value: 10
});
vignetteStretchKeys.push({
frame: 11,
value: 0
});
animationPP2.setKeys(vignetteStretchKeys);
this._postProcessMove.animations.push(animationPP2);
this._postProcessMove.imageProcessingConfiguration.vignetteWeight = 0;
this._postProcessMove.imageProcessingConfiguration.vignetteStretch = 0;
this._webVRCamera.attachPostProcess(this._postProcessMove);
this._scene.beginAnimation(this._postProcessMove, 0, 11, false, 1, function () {
_this._webVRCamera.detachPostProcess(_this._postProcessMove);
});
this._scene.beginAnimation(this.currentVRCamera, 0, 11, false, 1, function () {
_this.onAfterCameraTeleport.notifyObservers(_this._workingVector);
});
this._hideTeleportationTarget();
};
VRExperienceHelper.prototype._castRayAndSelectObject = function (gazer) {
if (!(this.currentVRCamera instanceof BABYLON.FreeCamera)) {
return;
}
var hit = this._scene.pickWithRay(gazer._getForwardRay(this._rayLength), this._raySelectionPredicate);
// Moving the gazeTracker on the mesh face targetted
if (hit && hit.pickedPoint) {
if (this._displayGaze) {
var multiplier = 1;
gazer._gazeTracker.isVisible = true;
if (gazer._isActionableMesh) {
multiplier = 3;
}
gazer._gazeTracker.scaling.x = hit.distance * multiplier;
gazer._gazeTracker.scaling.y = hit.distance * multiplier;
gazer._gazeTracker.scaling.z = hit.distance * multiplier;
var pickNormal = hit.getNormal();
// To avoid z-fighting
var deltaFighting = 0.002;
if (pickNormal) {
var axis1 = BABYLON.Vector3.Cross(BABYLON.Axis.Y, pickNormal);
var axis2 = BABYLON.Vector3.Cross(pickNormal, axis1);
BABYLON.Vector3.RotationFromAxisToRef(axis2, pickNormal, axis1, gazer._gazeTracker.rotation);
}
gazer._gazeTracker.position.copyFrom(hit.pickedPoint);
if (gazer._gazeTracker.position.x < 0) {
gazer._gazeTracker.position.x += deltaFighting;
}
else {
gazer._gazeTracker.position.x -= deltaFighting;
}
if (gazer._gazeTracker.position.y < 0) {
gazer._gazeTracker.position.y += deltaFighting;
}
else {
gazer._gazeTracker.position.y -= deltaFighting;
}
if (gazer._gazeTracker.position.z < 0) {
gazer._gazeTracker.position.z += deltaFighting;
}
else {
gazer._gazeTracker.position.z -= deltaFighting;
}
}
// Changing the size of the laser pointer based on the distance from the targetted point
gazer._updatePointerDistance(hit.distance);
}
else {
gazer._gazeTracker.isVisible = false;
}
if (hit && hit.pickedMesh) {
gazer._currentHit = hit;
if (gazer._pointerDownOnMeshAsked) {
this._scene.simulatePointerMove(gazer._currentHit, { pointerId: gazer._id });
}
// The object selected is the floor, we're in a teleportation scenario
if (this._teleportationInitialized && this._isTeleportationFloor(hit.pickedMesh) && hit.pickedPoint) {
// Moving the teleportation area to this targetted point
//Raise onSelectedMeshUnselected observable if ray collided floor mesh/meshes and a non floor mesh was previously selected
if (gazer._currentMeshSelected && !this._isTeleportationFloor(gazer._currentMeshSelected)) {
this._notifySelectedMeshUnselected(gazer._currentMeshSelected);
}
gazer._currentMeshSelected = null;
if (gazer._teleportationRequestInitiated) {
this._moveTeleportationSelectorTo(hit, gazer);
}
return;
}
// If not, we're in a selection scenario
//this._teleportationAllowed = false;
if (hit.pickedMesh !== gazer._currentMeshSelected) {
if (this.meshSelectionPredicate(hit.pickedMesh)) {
this.onNewMeshPicked.notifyObservers(hit);
gazer._currentMeshSelected = hit.pickedMesh;
if (hit.pickedMesh.isPickable && hit.pickedMesh.actionManager) {
this.changeGazeColor(new BABYLON.Color3(0, 0, 1));
this.changeLaserColor(new BABYLON.Color3(0.2, 0.2, 1));
gazer._isActionableMesh = true;
}
else {
this.changeGazeColor(new BABYLON.Color3(0.7, 0.7, 0.7));
this.changeLaserColor(new BABYLON.Color3(0.7, 0.7, 0.7));
gazer._isActionableMesh = false;
}
try {
this.onNewMeshSelected.notifyObservers(hit.pickedMesh);
}
catch (err) {
BABYLON.Tools.Warn("Error in your custom logic onNewMeshSelected: " + err);
}
}
else {
this._notifySelectedMeshUnselected(gazer._currentMeshSelected);
gazer._currentMeshSelected = null;
this.changeGazeColor(new BABYLON.Color3(0.7, 0.7, 0.7));
this.changeLaserColor(new BABYLON.Color3(0.7, 0.7, 0.7));
}
}
}
else {
gazer._currentHit = null;
this._notifySelectedMeshUnselected(gazer._currentMeshSelected);
gazer._currentMeshSelected = null;
//this._teleportationAllowed = false;
this.changeGazeColor(new BABYLON.Color3(0.7, 0.7, 0.7));
this.changeLaserColor(new BABYLON.Color3(0.7, 0.7, 0.7));
}
};
VRExperienceHelper.prototype._notifySelectedMeshUnselected = function (mesh) {
if (mesh) {
this.onSelectedMeshUnselected.notifyObservers(mesh);
}
};
/**
* Sets the color of the laser ray from the vr controllers.
* @param color new color for the ray.
*/
VRExperienceHelper.prototype.changeLaserColor = function (color) {
if (this.leftController) {
this.leftController._setLaserPointerColor(color);
}
if (this.rightController) {
this.rightController._setLaserPointerColor(color);
}
};
/**
* Sets the color of the ray from the vr headsets gaze.
* @param color new color for the ray.
*/
VRExperienceHelper.prototype.changeGazeColor = function (color) {
if (!this._cameraGazer._gazeTracker.material) {
return;
}
this._cameraGazer._gazeTracker.material.emissiveColor = color;
if (this.leftController) {
this.leftController._gazeTracker.material.emissiveColor = color;
}
if (this.rightController) {
this.rightController._gazeTracker.material.emissiveColor = color;
}
};
/**
* Exits VR and disposes of the vr experience helper
*/
VRExperienceHelper.prototype.dispose = function () {
if (this.isInVRMode) {
this.exitVR();
}
if (this._postProcessMove) {
this._postProcessMove.dispose();
}
if (this._webVRCamera) {
this._webVRCamera.dispose();
}
if (this._vrDeviceOrientationCamera) {
this._vrDeviceOrientationCamera.dispose();
}
if (!this._useCustomVRButton && this._btnVR.parentNode) {
document.body.removeChild(this._btnVR);
}
if (this._deviceOrientationCamera && (this._scene.activeCamera != this._deviceOrientationCamera)) {
this._deviceOrientationCamera.dispose();
}
if (this._cameraGazer) {
this._cameraGazer.dispose();
}
if (this.leftController) {
this.leftController.dispose();
}
if (this.rightController) {
this.rightController.dispose();
}
if (this._teleportationTarget) {
this._teleportationTarget.dispose();
}
this._floorMeshesCollection = [];
document.removeEventListener("keydown", this._onKeyDown);
window.removeEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange);
window.removeEventListener("resize", this._onResize);
document.removeEventListener("fullscreenchange", this._onFullscreenChange);
document.removeEventListener("mozfullscreenchange", this._onFullscreenChange);
document.removeEventListener("webkitfullscreenchange", this._onFullscreenChange);
document.removeEventListener("msfullscreenchange", this._onFullscreenChange);
this._scene.getEngine().onVRDisplayChangedObservable.removeCallback(this._onVRDisplayChanged);
this._scene.getEngine().onVRRequestPresentStart.removeCallback(this._onVRRequestPresentStart);
this._scene.getEngine().onVRRequestPresentComplete.removeCallback(this._onVRRequestPresentComplete);
window.removeEventListener('vrdisplaypresentchange', this._onVrDisplayPresentChange);
this._scene.gamepadManager.onGamepadConnectedObservable.removeCallback(this._onNewGamepadConnected);
this._scene.gamepadManager.onGamepadDisconnectedObservable.removeCallback(this._onNewGamepadDisconnected);
this._scene.unregisterBeforeRender(this.beforeRender);
};
/**
* Gets the name of the VRExperienceHelper class
* @returns "VRExperienceHelper"
*/
VRExperienceHelper.prototype.getClassName = function () {
return "VRExperienceHelper";
};
return VRExperienceHelper;
}());
BABYLON.VRExperienceHelper = VRExperienceHelper;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.vrExperienceHelper.js.map
// Mainly based on these 2 articles :
// Creating an universal virtual touch joystick working for all Touch models thanks to Hand.JS : http://blogs.msdn.com/b/davrous/archive/2013/02/22/creating-an-universal-virtual-touch-joystick-working-for-all-touch-models-thanks-to-hand-js.aspx
// & on Seb Lee-Delisle original work: http://seb.ly/2011/04/multi-touch-game-controller-in-javascripthtml5-for-ipad/
var BABYLON;
(function (BABYLON) {
var JoystickAxis;
(function (JoystickAxis) {
JoystickAxis[JoystickAxis["X"] = 0] = "X";
JoystickAxis[JoystickAxis["Y"] = 1] = "Y";
JoystickAxis[JoystickAxis["Z"] = 2] = "Z";
})(JoystickAxis = BABYLON.JoystickAxis || (BABYLON.JoystickAxis = {}));
var VirtualJoystick = /** @class */ (function () {
function VirtualJoystick(leftJoystick) {
var _this = this;
if (leftJoystick) {
this._leftJoystick = true;
}
else {
this._leftJoystick = false;
}
VirtualJoystick._globalJoystickIndex++;
// By default left & right arrow keys are moving the X
// and up & down keys are moving the Y
this._axisTargetedByLeftAndRight = JoystickAxis.X;
this._axisTargetedByUpAndDown = JoystickAxis.Y;
this.reverseLeftRight = false;
this.reverseUpDown = false;
// collections of pointers
this._touches = new BABYLON.StringDictionary();
this.deltaPosition = BABYLON.Vector3.Zero();
this._joystickSensibility = 25;
this._inversedSensibility = 1 / (this._joystickSensibility / 1000);
this._onResize = function (evt) {
VirtualJoystick.vjCanvasWidth = window.innerWidth;
VirtualJoystick.vjCanvasHeight = window.innerHeight;
if (VirtualJoystick.vjCanvas) {
VirtualJoystick.vjCanvas.width = VirtualJoystick.vjCanvasWidth;
VirtualJoystick.vjCanvas.height = VirtualJoystick.vjCanvasHeight;
}
VirtualJoystick.halfWidth = VirtualJoystick.vjCanvasWidth / 2;
};
// injecting a canvas element on top of the canvas 3D game
if (!VirtualJoystick.vjCanvas) {
window.addEventListener("resize", this._onResize, false);
VirtualJoystick.vjCanvas = document.createElement("canvas");
VirtualJoystick.vjCanvasWidth = window.innerWidth;
VirtualJoystick.vjCanvasHeight = window.innerHeight;
VirtualJoystick.vjCanvas.width = window.innerWidth;
VirtualJoystick.vjCanvas.height = window.innerHeight;
VirtualJoystick.vjCanvas.style.width = "100%";
VirtualJoystick.vjCanvas.style.height = "100%";
VirtualJoystick.vjCanvas.style.position = "absolute";
VirtualJoystick.vjCanvas.style.backgroundColor = "transparent";
VirtualJoystick.vjCanvas.style.top = "0px";
VirtualJoystick.vjCanvas.style.left = "0px";
VirtualJoystick.vjCanvas.style.zIndex = "5";
VirtualJoystick.vjCanvas.style.msTouchAction = "none";
// Support for jQuery PEP polyfill
VirtualJoystick.vjCanvas.setAttribute("touch-action", "none");
var context = VirtualJoystick.vjCanvas.getContext('2d');
if (!context) {
throw new Error("Unable to create canvas for virtual joystick");
}
VirtualJoystick.vjCanvasContext = context;
VirtualJoystick.vjCanvasContext.strokeStyle = "#ffffff";
VirtualJoystick.vjCanvasContext.lineWidth = 2;
document.body.appendChild(VirtualJoystick.vjCanvas);
}
VirtualJoystick.halfWidth = VirtualJoystick.vjCanvas.width / 2;
this.pressed = false;
// default joystick color
this._joystickColor = "cyan";
this._joystickPointerID = -1;
// current joystick position
this._joystickPointerPos = new BABYLON.Vector2(0, 0);
this._joystickPreviousPointerPos = new BABYLON.Vector2(0, 0);
// origin joystick position
this._joystickPointerStartPos = new BABYLON.Vector2(0, 0);
this._deltaJoystickVector = new BABYLON.Vector2(0, 0);
this._onPointerDownHandlerRef = function (evt) {
_this._onPointerDown(evt);
};
this._onPointerMoveHandlerRef = function (evt) {
_this._onPointerMove(evt);
};
this._onPointerUpHandlerRef = function (evt) {
_this._onPointerUp(evt);
};
VirtualJoystick.vjCanvas.addEventListener('pointerdown', this._onPointerDownHandlerRef, false);
VirtualJoystick.vjCanvas.addEventListener('pointermove', this._onPointerMoveHandlerRef, false);
VirtualJoystick.vjCanvas.addEventListener('pointerup', this._onPointerUpHandlerRef, false);
VirtualJoystick.vjCanvas.addEventListener('pointerout', this._onPointerUpHandlerRef, false);
VirtualJoystick.vjCanvas.addEventListener("contextmenu", function (evt) {
evt.preventDefault(); // Disables system menu
}, false);
requestAnimationFrame(function () { _this._drawVirtualJoystick(); });
}
VirtualJoystick.prototype.setJoystickSensibility = function (newJoystickSensibility) {
this._joystickSensibility = newJoystickSensibility;
this._inversedSensibility = 1 / (this._joystickSensibility / 1000);
};
VirtualJoystick.prototype._onPointerDown = function (e) {
var positionOnScreenCondition;
e.preventDefault();
if (this._leftJoystick === true) {
positionOnScreenCondition = (e.clientX < VirtualJoystick.halfWidth);
}
else {
positionOnScreenCondition = (e.clientX > VirtualJoystick.halfWidth);
}
if (positionOnScreenCondition && this._joystickPointerID < 0) {
// First contact will be dedicated to the virtual joystick
this._joystickPointerID = e.pointerId;
this._joystickPointerStartPos.x = e.clientX;
this._joystickPointerStartPos.y = e.clientY;
this._joystickPointerPos = this._joystickPointerStartPos.clone();
this._joystickPreviousPointerPos = this._joystickPointerStartPos.clone();
this._deltaJoystickVector.x = 0;
this._deltaJoystickVector.y = 0;
this.pressed = true;
this._touches.add(e.pointerId.toString(), e);
}
else {
// You can only trigger the action buttons with a joystick declared
if (VirtualJoystick._globalJoystickIndex < 2 && this._action) {
this._action();
this._touches.add(e.pointerId.toString(), { x: e.clientX, y: e.clientY, prevX: e.clientX, prevY: e.clientY });
}
}
};
VirtualJoystick.prototype._onPointerMove = function (e) {
// If the current pointer is the one associated to the joystick (first touch contact)
if (this._joystickPointerID == e.pointerId) {
this._joystickPointerPos.x = e.clientX;
this._joystickPointerPos.y = e.clientY;
this._deltaJoystickVector = this._joystickPointerPos.clone();
this._deltaJoystickVector = this._deltaJoystickVector.subtract(this._joystickPointerStartPos);
var directionLeftRight = this.reverseLeftRight ? -1 : 1;
var deltaJoystickX = directionLeftRight * this._deltaJoystickVector.x / this._inversedSensibility;
switch (this._axisTargetedByLeftAndRight) {
case JoystickAxis.X:
this.deltaPosition.x = Math.min(1, Math.max(-1, deltaJoystickX));
break;
case JoystickAxis.Y:
this.deltaPosition.y = Math.min(1, Math.max(-1, deltaJoystickX));
break;
case JoystickAxis.Z:
this.deltaPosition.z = Math.min(1, Math.max(-1, deltaJoystickX));
break;
}
var directionUpDown = this.reverseUpDown ? 1 : -1;
var deltaJoystickY = directionUpDown * this._deltaJoystickVector.y / this._inversedSensibility;
switch (this._axisTargetedByUpAndDown) {
case JoystickAxis.X:
this.deltaPosition.x = Math.min(1, Math.max(-1, deltaJoystickY));
break;
case JoystickAxis.Y:
this.deltaPosition.y = Math.min(1, Math.max(-1, deltaJoystickY));
break;
case JoystickAxis.Z:
this.deltaPosition.z = Math.min(1, Math.max(-1, deltaJoystickY));
break;
}
}
else {
var data = this._touches.get(e.pointerId.toString());
if (data) {
data.x = e.clientX;
data.y = e.clientY;
}
}
};
VirtualJoystick.prototype._onPointerUp = function (e) {
if (this._joystickPointerID == e.pointerId) {
VirtualJoystick.vjCanvasContext.clearRect(this._joystickPointerStartPos.x - 64, this._joystickPointerStartPos.y - 64, 128, 128);
VirtualJoystick.vjCanvasContext.clearRect(this._joystickPreviousPointerPos.x - 42, this._joystickPreviousPointerPos.y - 42, 84, 84);
this._joystickPointerID = -1;
this.pressed = false;
}
else {
var touch = this._touches.get(e.pointerId.toString());
if (touch) {
VirtualJoystick.vjCanvasContext.clearRect(touch.prevX - 44, touch.prevY - 44, 88, 88);
}
}
this._deltaJoystickVector.x = 0;
this._deltaJoystickVector.y = 0;
this._touches.remove(e.pointerId.toString());
};
/**
* Change the color of the virtual joystick
* @param newColor a string that must be a CSS color value (like "red") or the hexa value (like "#FF0000")
*/
VirtualJoystick.prototype.setJoystickColor = function (newColor) {
this._joystickColor = newColor;
};
VirtualJoystick.prototype.setActionOnTouch = function (action) {
this._action = action;
};
// Define which axis you'd like to control for left & right
VirtualJoystick.prototype.setAxisForLeftRight = function (axis) {
switch (axis) {
case JoystickAxis.X:
case JoystickAxis.Y:
case JoystickAxis.Z:
this._axisTargetedByLeftAndRight = axis;
break;
default:
this._axisTargetedByLeftAndRight = JoystickAxis.X;
break;
}
};
// Define which axis you'd like to control for up & down
VirtualJoystick.prototype.setAxisForUpDown = function (axis) {
switch (axis) {
case JoystickAxis.X:
case JoystickAxis.Y:
case JoystickAxis.Z:
this._axisTargetedByUpAndDown = axis;
break;
default:
this._axisTargetedByUpAndDown = JoystickAxis.Y;
break;
}
};
VirtualJoystick.prototype._drawVirtualJoystick = function () {
var _this = this;
if (this.pressed) {
this._touches.forEach(function (key, touch) {
if (touch.pointerId === _this._joystickPointerID) {
VirtualJoystick.vjCanvasContext.clearRect(_this._joystickPointerStartPos.x - 64, _this._joystickPointerStartPos.y - 64, 128, 128);
VirtualJoystick.vjCanvasContext.clearRect(_this._joystickPreviousPointerPos.x - 42, _this._joystickPreviousPointerPos.y - 42, 84, 84);
VirtualJoystick.vjCanvasContext.beginPath();
VirtualJoystick.vjCanvasContext.lineWidth = 6;
VirtualJoystick.vjCanvasContext.strokeStyle = _this._joystickColor;
VirtualJoystick.vjCanvasContext.arc(_this._joystickPointerStartPos.x, _this._joystickPointerStartPos.y, 40, 0, Math.PI * 2, true);
VirtualJoystick.vjCanvasContext.stroke();
VirtualJoystick.vjCanvasContext.closePath();
VirtualJoystick.vjCanvasContext.beginPath();
VirtualJoystick.vjCanvasContext.strokeStyle = _this._joystickColor;
VirtualJoystick.vjCanvasContext.lineWidth = 2;
VirtualJoystick.vjCanvasContext.arc(_this._joystickPointerStartPos.x, _this._joystickPointerStartPos.y, 60, 0, Math.PI * 2, true);
VirtualJoystick.vjCanvasContext.stroke();
VirtualJoystick.vjCanvasContext.closePath();
VirtualJoystick.vjCanvasContext.beginPath();
VirtualJoystick.vjCanvasContext.strokeStyle = _this._joystickColor;
VirtualJoystick.vjCanvasContext.arc(_this._joystickPointerPos.x, _this._joystickPointerPos.y, 40, 0, Math.PI * 2, true);
VirtualJoystick.vjCanvasContext.stroke();
VirtualJoystick.vjCanvasContext.closePath();
_this._joystickPreviousPointerPos = _this._joystickPointerPos.clone();
}
else {
VirtualJoystick.vjCanvasContext.clearRect(touch.prevX - 44, touch.prevY - 44, 88, 88);
VirtualJoystick.vjCanvasContext.beginPath();
VirtualJoystick.vjCanvasContext.fillStyle = "white";
VirtualJoystick.vjCanvasContext.beginPath();
VirtualJoystick.vjCanvasContext.strokeStyle = "red";
VirtualJoystick.vjCanvasContext.lineWidth = 6;
VirtualJoystick.vjCanvasContext.arc(touch.x, touch.y, 40, 0, Math.PI * 2, true);
VirtualJoystick.vjCanvasContext.stroke();
VirtualJoystick.vjCanvasContext.closePath();
touch.prevX = touch.x;
touch.prevY = touch.y;
}
;
});
}
requestAnimationFrame(function () { _this._drawVirtualJoystick(); });
};
VirtualJoystick.prototype.releaseCanvas = function () {
if (VirtualJoystick.vjCanvas) {
VirtualJoystick.vjCanvas.removeEventListener('pointerdown', this._onPointerDownHandlerRef);
VirtualJoystick.vjCanvas.removeEventListener('pointermove', this._onPointerMoveHandlerRef);
VirtualJoystick.vjCanvas.removeEventListener('pointerup', this._onPointerUpHandlerRef);
VirtualJoystick.vjCanvas.removeEventListener('pointerout', this._onPointerUpHandlerRef);
window.removeEventListener("resize", this._onResize);
document.body.removeChild(VirtualJoystick.vjCanvas);
VirtualJoystick.vjCanvas = null;
}
};
// Used to draw the virtual joystick inside a 2D canvas on top of the WebGL rendering canvas
VirtualJoystick._globalJoystickIndex = 0;
return VirtualJoystick;
}());
BABYLON.VirtualJoystick = VirtualJoystick;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.virtualJoystick.js.map
var BABYLON;
(function (BABYLON) {
// We're mainly based on the logic defined into the FreeCamera code
var VirtualJoysticksCamera = /** @class */ (function (_super) {
__extends(VirtualJoysticksCamera, _super);
function VirtualJoysticksCamera(name, position, scene) {
var _this = _super.call(this, name, position, scene) || this;
_this.inputs.addVirtualJoystick();
return _this;
}
VirtualJoysticksCamera.prototype.getClassName = function () {
return "VirtualJoysticksCamera";
};
return VirtualJoysticksCamera;
}(BABYLON.FreeCamera));
BABYLON.VirtualJoysticksCamera = VirtualJoysticksCamera;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.virtualJoysticksCamera.js.map
var BABYLON;
(function (BABYLON) {
var FreeCameraVirtualJoystickInput = /** @class */ (function () {
function FreeCameraVirtualJoystickInput() {
}
FreeCameraVirtualJoystickInput.prototype.getLeftJoystick = function () {
return this._leftjoystick;
};
FreeCameraVirtualJoystickInput.prototype.getRightJoystick = function () {
return this._rightjoystick;
};
FreeCameraVirtualJoystickInput.prototype.checkInputs = function () {
if (this._leftjoystick) {
var camera = this.camera;
var speed = camera._computeLocalCameraSpeed() * 50;
var cameraTransform = BABYLON.Matrix.RotationYawPitchRoll(camera.rotation.y, camera.rotation.x, 0);
var deltaTransform = BABYLON.Vector3.TransformCoordinates(new BABYLON.Vector3(this._leftjoystick.deltaPosition.x * speed, this._leftjoystick.deltaPosition.y * speed, this._leftjoystick.deltaPosition.z * speed), cameraTransform);
camera.cameraDirection = camera.cameraDirection.add(deltaTransform);
camera.cameraRotation = camera.cameraRotation.addVector3(this._rightjoystick.deltaPosition);
if (!this._leftjoystick.pressed) {
this._leftjoystick.deltaPosition = this._leftjoystick.deltaPosition.scale(0.9);
}
if (!this._rightjoystick.pressed) {
this._rightjoystick.deltaPosition = this._rightjoystick.deltaPosition.scale(0.9);
}
}
};
FreeCameraVirtualJoystickInput.prototype.attachControl = function (element, noPreventDefault) {
this._leftjoystick = new BABYLON.VirtualJoystick(true);
this._leftjoystick.setAxisForUpDown(BABYLON.JoystickAxis.Z);
this._leftjoystick.setAxisForLeftRight(BABYLON.JoystickAxis.X);
this._leftjoystick.setJoystickSensibility(0.15);
this._rightjoystick = new BABYLON.VirtualJoystick(false);
this._rightjoystick.setAxisForUpDown(BABYLON.JoystickAxis.X);
this._rightjoystick.setAxisForLeftRight(BABYLON.JoystickAxis.Y);
this._rightjoystick.reverseUpDown = true;
this._rightjoystick.setJoystickSensibility(0.05);
this._rightjoystick.setJoystickColor("yellow");
};
FreeCameraVirtualJoystickInput.prototype.detachControl = function (element) {
this._leftjoystick.releaseCanvas();
this._rightjoystick.releaseCanvas();
};
FreeCameraVirtualJoystickInput.prototype.getClassName = function () {
return "FreeCameraVirtualJoystickInput";
};
FreeCameraVirtualJoystickInput.prototype.getSimpleName = function () {
return "virtualJoystick";
};
return FreeCameraVirtualJoystickInput;
}());
BABYLON.FreeCameraVirtualJoystickInput = FreeCameraVirtualJoystickInput;
BABYLON.CameraInputTypes["FreeCameraVirtualJoystickInput"] = FreeCameraVirtualJoystickInput;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.freeCameraVirtualJoystickInput.js.map
var BABYLON;
(function (BABYLON) {
var SimplificationSettings = /** @class */ (function () {
function SimplificationSettings(quality, distance, optimizeMesh) {
this.quality = quality;
this.distance = distance;
this.optimizeMesh = optimizeMesh;
}
return SimplificationSettings;
}());
BABYLON.SimplificationSettings = SimplificationSettings;
var SimplificationQueue = /** @class */ (function () {
function SimplificationQueue() {
this.running = false;
this._simplificationArray = [];
}
SimplificationQueue.prototype.addTask = function (task) {
this._simplificationArray.push(task);
};
SimplificationQueue.prototype.executeNext = function () {
var task = this._simplificationArray.pop();
if (task) {
this.running = true;
this.runSimplification(task);
}
else {
this.running = false;
}
};
SimplificationQueue.prototype.runSimplification = function (task) {
var _this = this;
if (task.parallelProcessing) {
//parallel simplifier
task.settings.forEach(function (setting) {
var simplifier = _this.getSimplifier(task);
simplifier.simplify(setting, function (newMesh) {
task.mesh.addLODLevel(setting.distance, newMesh);
newMesh.isVisible = true;
//check if it is the last
if (setting.quality === task.settings[task.settings.length - 1].quality && task.successCallback) {
//all done, run the success callback.
task.successCallback();
}
_this.executeNext();
});
});
}
else {
//single simplifier.
var simplifier = this.getSimplifier(task);
var runDecimation = function (setting, callback) {
simplifier.simplify(setting, function (newMesh) {
task.mesh.addLODLevel(setting.distance, newMesh);
newMesh.isVisible = true;
//run the next quality level
callback();
});
};
BABYLON.AsyncLoop.Run(task.settings.length, function (loop) {
runDecimation(task.settings[loop.index], function () {
loop.executeNext();
});
}, function () {
//execution ended, run the success callback.
if (task.successCallback) {
task.successCallback();
}
_this.executeNext();
});
}
};
SimplificationQueue.prototype.getSimplifier = function (task) {
switch (task.simplificationType) {
case SimplificationType.QUADRATIC:
default:
return new QuadraticErrorSimplification(task.mesh);
}
};
return SimplificationQueue;
}());
BABYLON.SimplificationQueue = SimplificationQueue;
/**
* The implemented types of simplification.
* At the moment only Quadratic Error Decimation is implemented.
*/
var SimplificationType;
(function (SimplificationType) {
SimplificationType[SimplificationType["QUADRATIC"] = 0] = "QUADRATIC";
})(SimplificationType = BABYLON.SimplificationType || (BABYLON.SimplificationType = {}));
var DecimationTriangle = /** @class */ (function () {
function DecimationTriangle(vertices) {
this.vertices = vertices;
this.error = new Array(4);
this.deleted = false;
this.isDirty = false;
this.deletePending = false;
this.borderFactor = 0;
}
return DecimationTriangle;
}());
BABYLON.DecimationTriangle = DecimationTriangle;
var DecimationVertex = /** @class */ (function () {
function DecimationVertex(position, id) {
this.position = position;
this.id = id;
this.isBorder = true;
this.q = new QuadraticMatrix();
this.triangleCount = 0;
this.triangleStart = 0;
this.originalOffsets = [];
}
DecimationVertex.prototype.updatePosition = function (newPosition) {
this.position.copyFrom(newPosition);
};
return DecimationVertex;
}());
BABYLON.DecimationVertex = DecimationVertex;
var QuadraticMatrix = /** @class */ (function () {
function QuadraticMatrix(data) {
this.data = new Array(10);
for (var i = 0; i < 10; ++i) {
if (data && data[i]) {
this.data[i] = data[i];
}
else {
this.data[i] = 0;
}
}
}
QuadraticMatrix.prototype.det = function (a11, a12, a13, a21, a22, a23, a31, a32, a33) {
var det = this.data[a11] * this.data[a22] * this.data[a33] + this.data[a13] * this.data[a21] * this.data[a32] +
this.data[a12] * this.data[a23] * this.data[a31] - this.data[a13] * this.data[a22] * this.data[a31] -
this.data[a11] * this.data[a23] * this.data[a32] - this.data[a12] * this.data[a21] * this.data[a33];
return det;
};
QuadraticMatrix.prototype.addInPlace = function (matrix) {
for (var i = 0; i < 10; ++i) {
this.data[i] += matrix.data[i];
}
};
QuadraticMatrix.prototype.addArrayInPlace = function (data) {
for (var i = 0; i < 10; ++i) {
this.data[i] += data[i];
}
};
QuadraticMatrix.prototype.add = function (matrix) {
var m = new QuadraticMatrix();
for (var i = 0; i < 10; ++i) {
m.data[i] = this.data[i] + matrix.data[i];
}
return m;
};
QuadraticMatrix.FromData = function (a, b, c, d) {
return new QuadraticMatrix(QuadraticMatrix.DataFromNumbers(a, b, c, d));
};
//returning an array to avoid garbage collection
QuadraticMatrix.DataFromNumbers = function (a, b, c, d) {
return [a * a, a * b, a * c, a * d, b * b, b * c, b * d, c * c, c * d, d * d];
};
return QuadraticMatrix;
}());
BABYLON.QuadraticMatrix = QuadraticMatrix;
var Reference = /** @class */ (function () {
function Reference(vertexId, triangleId) {
this.vertexId = vertexId;
this.triangleId = triangleId;
}
return Reference;
}());
BABYLON.Reference = Reference;
/**
* An implementation of the Quadratic Error simplification algorithm.
* Original paper : http://www1.cs.columbia.edu/~cs4162/html05s/garland97.pdf
* Ported mostly from QSlim and http://voxels.blogspot.de/2014/05/quadric-mesh-simplification-with-source.html to babylon JS
* @author RaananW
*/
var QuadraticErrorSimplification = /** @class */ (function () {
function QuadraticErrorSimplification(_mesh) {
this._mesh = _mesh;
this.syncIterations = 5000;
this.aggressiveness = 7;
this.decimationIterations = 100;
this.boundingBoxEpsilon = BABYLON.Epsilon;
}
QuadraticErrorSimplification.prototype.simplify = function (settings, successCallback) {
var _this = this;
this.initDecimatedMesh();
//iterating through the submeshes array, one after the other.
BABYLON.AsyncLoop.Run(this._mesh.subMeshes.length, function (loop) {
_this.initWithMesh(loop.index, function () {
_this.runDecimation(settings, loop.index, function () {
loop.executeNext();
});
}, settings.optimizeMesh);
}, function () {
setTimeout(function () {
successCallback(_this._reconstructedMesh);
}, 0);
});
};
QuadraticErrorSimplification.prototype.runDecimation = function (settings, submeshIndex, successCallback) {
var _this = this;
var targetCount = ~~(this.triangles.length * settings.quality);
var deletedTriangles = 0;
var triangleCount = this.triangles.length;
var iterationFunction = function (iteration, callback) {
setTimeout(function () {
if (iteration % 5 === 0) {
_this.updateMesh(iteration === 0);
}
for (var i = 0; i < _this.triangles.length; ++i) {
_this.triangles[i].isDirty = false;
}
var threshold = 0.000000001 * Math.pow((iteration + 3), _this.aggressiveness);
var trianglesIterator = function (i) {
var tIdx = ~~(((_this.triangles.length / 2) + i) % _this.triangles.length);
var t = _this.triangles[tIdx];
if (!t)
return;
if (t.error[3] > threshold || t.deleted || t.isDirty) {
return;
}
for (var j = 0; j < 3; ++j) {
if (t.error[j] < threshold) {
var deleted0 = [];
var deleted1 = [];
var v0 = t.vertices[j];
var v1 = t.vertices[(j + 1) % 3];
if (v0.isBorder || v1.isBorder)
continue;
var p = BABYLON.Vector3.Zero();
var n = BABYLON.Vector3.Zero();
var uv = BABYLON.Vector2.Zero();
var color = new BABYLON.Color4(0, 0, 0, 1);
_this.calculateError(v0, v1, p, n, uv, color);
var delTr = new Array();
if (_this.isFlipped(v0, v1, p, deleted0, t.borderFactor, delTr))
continue;
if (_this.isFlipped(v1, v0, p, deleted1, t.borderFactor, delTr))
continue;
if (deleted0.indexOf(true) < 0 || deleted1.indexOf(true) < 0)
continue;
var uniqueArray = new Array();
delTr.forEach(function (deletedT) {
if (uniqueArray.indexOf(deletedT) === -1) {
deletedT.deletePending = true;
uniqueArray.push(deletedT);
}
});
if (uniqueArray.length % 2 !== 0) {
continue;
}
v0.q = v1.q.add(v0.q);
v0.updatePosition(p);
var tStart = _this.references.length;
deletedTriangles = _this.updateTriangles(v0, v0, deleted0, deletedTriangles);
deletedTriangles = _this.updateTriangles(v0, v1, deleted1, deletedTriangles);
var tCount = _this.references.length - tStart;
if (tCount <= v0.triangleCount) {
if (tCount) {
for (var c = 0; c < tCount; c++) {
_this.references[v0.triangleStart + c] = _this.references[tStart + c];
}
}
}
else {
v0.triangleStart = tStart;
}
v0.triangleCount = tCount;
break;
}
}
};
BABYLON.AsyncLoop.SyncAsyncForLoop(_this.triangles.length, _this.syncIterations, trianglesIterator, callback, function () { return (triangleCount - deletedTriangles <= targetCount); });
}, 0);
};
BABYLON.AsyncLoop.Run(this.decimationIterations, function (loop) {
if (triangleCount - deletedTriangles <= targetCount)
loop.breakLoop();
else {
iterationFunction(loop.index, function () {
loop.executeNext();
});
}
}, function () {
setTimeout(function () {
//reconstruct this part of the mesh
_this.reconstructMesh(submeshIndex);
successCallback();
}, 0);
});
};
QuadraticErrorSimplification.prototype.initWithMesh = function (submeshIndex, callback, optimizeMesh) {
var _this = this;
this.vertices = [];
this.triangles = [];
var positionData = this._mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);
var indices = this._mesh.getIndices();
var submesh = this._mesh.subMeshes[submeshIndex];
var findInVertices = function (positionToSearch) {
if (optimizeMesh) {
for (var ii = 0; ii < _this.vertices.length; ++ii) {
if (_this.vertices[ii].position.equals(positionToSearch)) {
return _this.vertices[ii];
}
}
}
return null;
};
var vertexReferences = [];
var vertexInit = function (i) {
if (!positionData) {
return;
}
var offset = i + submesh.verticesStart;
var position = BABYLON.Vector3.FromArray(positionData, offset * 3);
var vertex = findInVertices(position) || new DecimationVertex(position, _this.vertices.length);
vertex.originalOffsets.push(offset);
if (vertex.id === _this.vertices.length) {
_this.vertices.push(vertex);
}
vertexReferences.push(vertex.id);
};
//var totalVertices = mesh.getTotalVertices();
var totalVertices = submesh.verticesCount;
BABYLON.AsyncLoop.SyncAsyncForLoop(totalVertices, (this.syncIterations / 4) >> 0, vertexInit, function () {
var indicesInit = function (i) {
if (!indices) {
return;
}
var offset = (submesh.indexStart / 3) + i;
var pos = (offset * 3);
var i0 = indices[pos + 0];
var i1 = indices[pos + 1];
var i2 = indices[pos + 2];
var v0 = _this.vertices[vertexReferences[i0 - submesh.verticesStart]];
var v1 = _this.vertices[vertexReferences[i1 - submesh.verticesStart]];
var v2 = _this.vertices[vertexReferences[i2 - submesh.verticesStart]];
var triangle = new DecimationTriangle([v0, v1, v2]);
triangle.originalOffset = pos;
_this.triangles.push(triangle);
};
BABYLON.AsyncLoop.SyncAsyncForLoop(submesh.indexCount / 3, _this.syncIterations, indicesInit, function () {
_this.init(callback);
});
});
};
QuadraticErrorSimplification.prototype.init = function (callback) {
var _this = this;
var triangleInit1 = function (i) {
var t = _this.triangles[i];
t.normal = BABYLON.Vector3.Cross(t.vertices[1].position.subtract(t.vertices[0].position), t.vertices[2].position.subtract(t.vertices[0].position)).normalize();
for (var j = 0; j < 3; j++) {
t.vertices[j].q.addArrayInPlace(QuadraticMatrix.DataFromNumbers(t.normal.x, t.normal.y, t.normal.z, -(BABYLON.Vector3.Dot(t.normal, t.vertices[0].position))));
}
};
BABYLON.AsyncLoop.SyncAsyncForLoop(this.triangles.length, this.syncIterations, triangleInit1, function () {
var triangleInit2 = function (i) {
var t = _this.triangles[i];
for (var j = 0; j < 3; ++j) {
t.error[j] = _this.calculateError(t.vertices[j], t.vertices[(j + 1) % 3]);
}
t.error[3] = Math.min(t.error[0], t.error[1], t.error[2]);
};
BABYLON.AsyncLoop.SyncAsyncForLoop(_this.triangles.length, _this.syncIterations, triangleInit2, function () {
callback();
});
});
};
QuadraticErrorSimplification.prototype.reconstructMesh = function (submeshIndex) {
var newTriangles = [];
var i;
for (i = 0; i < this.vertices.length; ++i) {
this.vertices[i].triangleCount = 0;
}
var t;
var j;
for (i = 0; i < this.triangles.length; ++i) {
if (!this.triangles[i].deleted) {
t = this.triangles[i];
for (j = 0; j < 3; ++j) {
t.vertices[j].triangleCount = 1;
}
newTriangles.push(t);
}
}
var newPositionData = (this._reconstructedMesh.getVerticesData(BABYLON.VertexBuffer.PositionKind) || []);
var newNormalData = (this._reconstructedMesh.getVerticesData(BABYLON.VertexBuffer.NormalKind) || []);
var newUVsData = (this._reconstructedMesh.getVerticesData(BABYLON.VertexBuffer.UVKind) || []);
var newColorsData = (this._reconstructedMesh.getVerticesData(BABYLON.VertexBuffer.ColorKind) || []);
var normalData = this._mesh.getVerticesData(BABYLON.VertexBuffer.NormalKind);
var uvs = this._mesh.getVerticesData(BABYLON.VertexBuffer.UVKind);
var colorsData = this._mesh.getVerticesData(BABYLON.VertexBuffer.ColorKind);
var vertexCount = 0;
for (i = 0; i < this.vertices.length; ++i) {
var vertex = this.vertices[i];
vertex.id = vertexCount;
if (vertex.triangleCount) {
vertex.originalOffsets.forEach(function (originalOffset) {
if (!normalData) {
return;
}
newPositionData.push(vertex.position.x);
newPositionData.push(vertex.position.y);
newPositionData.push(vertex.position.z);
newNormalData.push(normalData[originalOffset * 3]);
newNormalData.push(normalData[(originalOffset * 3) + 1]);
newNormalData.push(normalData[(originalOffset * 3) + 2]);
if (uvs && uvs.length) {
newUVsData.push(uvs[(originalOffset * 2)]);
newUVsData.push(uvs[(originalOffset * 2) + 1]);
}
else if (colorsData && colorsData.length) {
newColorsData.push(colorsData[(originalOffset * 4)]);
newColorsData.push(colorsData[(originalOffset * 4) + 1]);
newColorsData.push(colorsData[(originalOffset * 4) + 2]);
newColorsData.push(colorsData[(originalOffset * 4) + 3]);
}
++vertexCount;
});
}
}
var startingIndex = this._reconstructedMesh.getTotalIndices();
var startingVertex = this._reconstructedMesh.getTotalVertices();
var submeshesArray = this._reconstructedMesh.subMeshes;
this._reconstructedMesh.subMeshes = [];
var newIndicesArray = this._reconstructedMesh.getIndices(); //[];
var originalIndices = this._mesh.getIndices();
for (i = 0; i < newTriangles.length; ++i) {
t = newTriangles[i]; //now get the new referencing point for each vertex
[0, 1, 2].forEach(function (idx) {
var id = originalIndices[t.originalOffset + idx];
var offset = t.vertices[idx].originalOffsets.indexOf(id);
if (offset < 0)
offset = 0;
newIndicesArray.push(t.vertices[idx].id + offset + startingVertex);
});
}
//overwriting the old vertex buffers and indices.
this._reconstructedMesh.setIndices(newIndicesArray);
this._reconstructedMesh.setVerticesData(BABYLON.VertexBuffer.PositionKind, newPositionData);
this._reconstructedMesh.setVerticesData(BABYLON.VertexBuffer.NormalKind, newNormalData);
if (newUVsData.length > 0)
this._reconstructedMesh.setVerticesData(BABYLON.VertexBuffer.UVKind, newUVsData);
if (newColorsData.length > 0)
this._reconstructedMesh.setVerticesData(BABYLON.VertexBuffer.ColorKind, newColorsData);
//create submesh
var originalSubmesh = this._mesh.subMeshes[submeshIndex];
if (submeshIndex > 0) {
this._reconstructedMesh.subMeshes = [];
submeshesArray.forEach(function (submesh) {
BABYLON.SubMesh.AddToMesh(submesh.materialIndex, submesh.verticesStart, submesh.verticesCount, /* 0, newPositionData.length/3, */ submesh.indexStart, submesh.indexCount, submesh.getMesh());
});
BABYLON.SubMesh.AddToMesh(originalSubmesh.materialIndex, startingVertex, vertexCount, /* 0, newPositionData.length / 3, */ startingIndex, newTriangles.length * 3, this._reconstructedMesh);
}
};
QuadraticErrorSimplification.prototype.initDecimatedMesh = function () {
this._reconstructedMesh = new BABYLON.Mesh(this._mesh.name + "Decimated", this._mesh.getScene());
this._reconstructedMesh.material = this._mesh.material;
this._reconstructedMesh.parent = this._mesh.parent;
this._reconstructedMesh.isVisible = false;
this._reconstructedMesh.renderingGroupId = this._mesh.renderingGroupId;
};
QuadraticErrorSimplification.prototype.isFlipped = function (vertex1, vertex2, point, deletedArray, borderFactor, delTr) {
for (var i = 0; i < vertex1.triangleCount; ++i) {
var t = this.triangles[this.references[vertex1.triangleStart + i].triangleId];
if (t.deleted)
continue;
var s = this.references[vertex1.triangleStart + i].vertexId;
var v1 = t.vertices[(s + 1) % 3];
var v2 = t.vertices[(s + 2) % 3];
if ((v1 === vertex2 || v2 === vertex2)) {
deletedArray[i] = true;
delTr.push(t);
continue;
}
var d1 = v1.position.subtract(point);
d1 = d1.normalize();
var d2 = v2.position.subtract(point);
d2 = d2.normalize();
if (Math.abs(BABYLON.Vector3.Dot(d1, d2)) > 0.999)
return true;
var normal = BABYLON.Vector3.Cross(d1, d2).normalize();
deletedArray[i] = false;
if (BABYLON.Vector3.Dot(normal, t.normal) < 0.2)
return true;
}
return false;
};
QuadraticErrorSimplification.prototype.updateTriangles = function (origVertex, vertex, deletedArray, deletedTriangles) {
var newDeleted = deletedTriangles;
for (var i = 0; i < vertex.triangleCount; ++i) {
var ref = this.references[vertex.triangleStart + i];
var t = this.triangles[ref.triangleId];
if (t.deleted)
continue;
if (deletedArray[i] && t.deletePending) {
t.deleted = true;
newDeleted++;
continue;
}
t.vertices[ref.vertexId] = origVertex;
t.isDirty = true;
t.error[0] = this.calculateError(t.vertices[0], t.vertices[1]) + (t.borderFactor / 2);
t.error[1] = this.calculateError(t.vertices[1], t.vertices[2]) + (t.borderFactor / 2);
t.error[2] = this.calculateError(t.vertices[2], t.vertices[0]) + (t.borderFactor / 2);
t.error[3] = Math.min(t.error[0], t.error[1], t.error[2]);
this.references.push(ref);
}
return newDeleted;
};
QuadraticErrorSimplification.prototype.identifyBorder = function () {
for (var i = 0; i < this.vertices.length; ++i) {
var vCount = [];
var vId = [];
var v = this.vertices[i];
var j;
for (j = 0; j < v.triangleCount; ++j) {
var triangle = this.triangles[this.references[v.triangleStart + j].triangleId];
for (var ii = 0; ii < 3; ii++) {
var ofs = 0;
var vv = triangle.vertices[ii];
while (ofs < vCount.length) {
if (vId[ofs] === vv.id)
break;
++ofs;
}
if (ofs === vCount.length) {
vCount.push(1);
vId.push(vv.id);
}
else {
vCount[ofs]++;
}
}
}
for (j = 0; j < vCount.length; ++j) {
if (vCount[j] === 1) {
this.vertices[vId[j]].isBorder = true;
}
else {
this.vertices[vId[j]].isBorder = false;
}
}
}
};
QuadraticErrorSimplification.prototype.updateMesh = function (identifyBorders) {
if (identifyBorders === void 0) { identifyBorders = false; }
var i;
if (!identifyBorders) {
var newTrianglesVector = [];
for (i = 0; i < this.triangles.length; ++i) {
if (!this.triangles[i].deleted) {
newTrianglesVector.push(this.triangles[i]);
}
}
this.triangles = newTrianglesVector;
}
for (i = 0; i < this.vertices.length; ++i) {
this.vertices[i].triangleCount = 0;
this.vertices[i].triangleStart = 0;
}
var t;
var j;
var v;
for (i = 0; i < this.triangles.length; ++i) {
t = this.triangles[i];
for (j = 0; j < 3; ++j) {
v = t.vertices[j];
v.triangleCount++;
}
}
var tStart = 0;
for (i = 0; i < this.vertices.length; ++i) {
this.vertices[i].triangleStart = tStart;
tStart += this.vertices[i].triangleCount;
this.vertices[i].triangleCount = 0;
}
var newReferences = new Array(this.triangles.length * 3);
for (i = 0; i < this.triangles.length; ++i) {
t = this.triangles[i];
for (j = 0; j < 3; ++j) {
v = t.vertices[j];
newReferences[v.triangleStart + v.triangleCount] = new Reference(j, i);
v.triangleCount++;
}
}
this.references = newReferences;
if (identifyBorders) {
this.identifyBorder();
}
};
QuadraticErrorSimplification.prototype.vertexError = function (q, point) {
var x = point.x;
var y = point.y;
var z = point.z;
return q.data[0] * x * x + 2 * q.data[1] * x * y + 2 * q.data[2] * x * z + 2 * q.data[3] * x + q.data[4] * y * y
+ 2 * q.data[5] * y * z + 2 * q.data[6] * y + q.data[7] * z * z + 2 * q.data[8] * z + q.data[9];
};
QuadraticErrorSimplification.prototype.calculateError = function (vertex1, vertex2, pointResult, normalResult, uvResult, colorResult) {
var q = vertex1.q.add(vertex2.q);
var border = vertex1.isBorder && vertex2.isBorder;
var error = 0;
var qDet = q.det(0, 1, 2, 1, 4, 5, 2, 5, 7);
if (qDet !== 0 && !border) {
if (!pointResult) {
pointResult = BABYLON.Vector3.Zero();
}
pointResult.x = -1 / qDet * (q.det(1, 2, 3, 4, 5, 6, 5, 7, 8));
pointResult.y = 1 / qDet * (q.det(0, 2, 3, 1, 5, 6, 2, 7, 8));
pointResult.z = -1 / qDet * (q.det(0, 1, 3, 1, 4, 6, 2, 5, 8));
error = this.vertexError(q, pointResult);
}
else {
var p3 = (vertex1.position.add(vertex2.position)).divide(new BABYLON.Vector3(2, 2, 2));
//var norm3 = (vertex1.normal.add(vertex2.normal)).divide(new Vector3(2, 2, 2)).normalize();
var error1 = this.vertexError(q, vertex1.position);
var error2 = this.vertexError(q, vertex2.position);
var error3 = this.vertexError(q, p3);
error = Math.min(error1, error2, error3);
if (error === error1) {
if (pointResult) {
pointResult.copyFrom(vertex1.position);
}
}
else if (error === error2) {
if (pointResult) {
pointResult.copyFrom(vertex2.position);
}
}
else {
if (pointResult) {
pointResult.copyFrom(p3);
}
}
}
return error;
};
return QuadraticErrorSimplification;
}());
BABYLON.QuadraticErrorSimplification = QuadraticErrorSimplification;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.meshSimplification.js.map
var BABYLON;
(function (BABYLON) {
var MeshLODLevel = /** @class */ (function () {
function MeshLODLevel(distance, mesh) {
this.distance = distance;
this.mesh = mesh;
}
return MeshLODLevel;
}());
BABYLON.MeshLODLevel = MeshLODLevel;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.meshLODLevel.js.map
var BABYLON;
(function (BABYLON) {
/**
* Defines the root class used to create scene optimization to use with SceneOptimizer
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var SceneOptimization = /** @class */ (function () {
/**
* Creates the SceneOptimization object
* @param priority defines the priority of this optimization (0 by default which means first in the list)
* @param desc defines the description associated with the optimization
*/
function SceneOptimization(
/**
* Defines the priority of this optimization (0 by default which means first in the list)
*/
priority) {
if (priority === void 0) { priority = 0; }
this.priority = priority;
}
/**
* Gets a string describing the action executed by the current optimization
* @returns description string
*/
SceneOptimization.prototype.getDescription = function () {
return "";
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @returns true if everything that can be done was applied
*/
SceneOptimization.prototype.apply = function (scene, optimizer) {
return true;
};
;
return SceneOptimization;
}());
BABYLON.SceneOptimization = SceneOptimization;
/**
* Defines an optimization used to reduce the size of render target textures
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var TextureOptimization = /** @class */ (function (_super) {
__extends(TextureOptimization, _super);
/**
* Creates the TextureOptimization object
* @param priority defines the priority of this optimization (0 by default which means first in the list)
* @param maximumSize defines the maximum sized allowed for textures (1024 is the default value). If a texture is bigger, it will be scaled down using a factor defined by the step parameter
* @param step defines the factor (0.5 by default) used to scale down textures bigger than maximum sized allowed.
*/
function TextureOptimization(
/**
* Defines the priority of this optimization (0 by default which means first in the list)
*/
priority,
/**
* Defines the maximum sized allowed for textures (1024 is the default value). If a texture is bigger, it will be scaled down using a factor defined by the step parameter
*/
maximumSize,
/**
* Defines the factor (0.5 by default) used to scale down textures bigger than maximum sized allowed.
*/
step) {
if (priority === void 0) { priority = 0; }
if (maximumSize === void 0) { maximumSize = 1024; }
if (step === void 0) { step = 0.5; }
var _this = _super.call(this, priority) || this;
_this.priority = priority;
_this.maximumSize = maximumSize;
_this.step = step;
return _this;
}
/**
* Gets a string describing the action executed by the current optimization
* @returns description string
*/
TextureOptimization.prototype.getDescription = function () {
return "Reducing render target texture size to " + this.maximumSize;
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @returns true if everything that can be done was applied
*/
TextureOptimization.prototype.apply = function (scene, optimizer) {
var allDone = true;
for (var index = 0; index < scene.textures.length; index++) {
var texture = scene.textures[index];
if (!texture.canRescale || texture.getContext) {
continue;
}
var currentSize = texture.getSize();
var maxDimension = Math.max(currentSize.width, currentSize.height);
if (maxDimension > this.maximumSize) {
texture.scale(this.step);
allDone = false;
}
}
return allDone;
};
return TextureOptimization;
}(SceneOptimization));
BABYLON.TextureOptimization = TextureOptimization;
/**
* Defines an optimization used to increase or decrease the rendering resolution
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var HardwareScalingOptimization = /** @class */ (function (_super) {
__extends(HardwareScalingOptimization, _super);
/**
* Creates the HardwareScalingOptimization object
* @param priority defines the priority of this optimization (0 by default which means first in the list)
* @param maximumScale defines the maximum scale to use (2 by default)
* @param step defines the step to use between two passes (0.5 by default)
*/
function HardwareScalingOptimization(
/**
* Defines the priority of this optimization (0 by default which means first in the list)
*/
priority,
/**
* Defines the maximum scale to use (2 by default)
*/
maximumScale,
/**
* Defines the step to use between two passes (0.5 by default)
*/
step) {
if (priority === void 0) { priority = 0; }
if (maximumScale === void 0) { maximumScale = 2; }
if (step === void 0) { step = 0.25; }
var _this = _super.call(this, priority) || this;
_this.priority = priority;
_this.maximumScale = maximumScale;
_this.step = step;
_this._currentScale = -1;
_this._directionOffset = 1;
return _this;
}
/**
* Gets a string describing the action executed by the current optimization
* @return description string
*/
HardwareScalingOptimization.prototype.getDescription = function () {
return "Setting hardware scaling level to " + this._currentScale;
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @returns true if everything that can be done was applied
*/
HardwareScalingOptimization.prototype.apply = function (scene, optimizer) {
if (this._currentScale === -1) {
this._currentScale = scene.getEngine().getHardwareScalingLevel();
if (this._currentScale > this.maximumScale) {
this._directionOffset = -1;
}
}
this._currentScale += this._directionOffset * this.step;
scene.getEngine().setHardwareScalingLevel(this._currentScale);
return this._directionOffset === 1 ? this._currentScale >= this.maximumScale : this._currentScale <= this.maximumScale;
};
;
return HardwareScalingOptimization;
}(SceneOptimization));
BABYLON.HardwareScalingOptimization = HardwareScalingOptimization;
/**
* Defines an optimization used to remove shadows
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var ShadowsOptimization = /** @class */ (function (_super) {
__extends(ShadowsOptimization, _super);
function ShadowsOptimization() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Gets a string describing the action executed by the current optimization
* @return description string
*/
ShadowsOptimization.prototype.getDescription = function () {
return "Turning shadows on/off";
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @returns true if everything that can be done was applied
*/
ShadowsOptimization.prototype.apply = function (scene, optimizer) {
scene.shadowsEnabled = optimizer.isInImprovementMode;
return true;
};
;
return ShadowsOptimization;
}(SceneOptimization));
BABYLON.ShadowsOptimization = ShadowsOptimization;
/**
* Defines an optimization used to turn post-processes off
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var PostProcessesOptimization = /** @class */ (function (_super) {
__extends(PostProcessesOptimization, _super);
function PostProcessesOptimization() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Gets a string describing the action executed by the current optimization
* @return description string
*/
PostProcessesOptimization.prototype.getDescription = function () {
return "Turning post-processes on/off";
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @returns true if everything that can be done was applied
*/
PostProcessesOptimization.prototype.apply = function (scene, optimizer) {
scene.postProcessesEnabled = optimizer.isInImprovementMode;
return true;
};
;
return PostProcessesOptimization;
}(SceneOptimization));
BABYLON.PostProcessesOptimization = PostProcessesOptimization;
/**
* Defines an optimization used to turn lens flares off
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var LensFlaresOptimization = /** @class */ (function (_super) {
__extends(LensFlaresOptimization, _super);
function LensFlaresOptimization() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Gets a string describing the action executed by the current optimization
* @return description string
*/
LensFlaresOptimization.prototype.getDescription = function () {
return "Turning lens flares on/off";
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @returns true if everything that can be done was applied
*/
LensFlaresOptimization.prototype.apply = function (scene, optimizer) {
scene.lensFlaresEnabled = optimizer.isInImprovementMode;
return true;
};
;
return LensFlaresOptimization;
}(SceneOptimization));
BABYLON.LensFlaresOptimization = LensFlaresOptimization;
/**
* Defines an optimization based on user defined callback.
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var CustomOptimization = /** @class */ (function (_super) {
__extends(CustomOptimization, _super);
function CustomOptimization() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Gets a string describing the action executed by the current optimization
* @returns description string
*/
CustomOptimization.prototype.getDescription = function () {
if (this.onGetDescription) {
return this.onGetDescription();
}
return "Running user defined callback";
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @returns true if everything that can be done was applied
*/
CustomOptimization.prototype.apply = function (scene, optimizer) {
if (this.onApply) {
return this.onApply(scene, optimizer);
}
return true;
};
;
return CustomOptimization;
}(SceneOptimization));
BABYLON.CustomOptimization = CustomOptimization;
/**
* Defines an optimization used to turn particles off
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var ParticlesOptimization = /** @class */ (function (_super) {
__extends(ParticlesOptimization, _super);
function ParticlesOptimization() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Gets a string describing the action executed by the current optimization
* @return description string
*/
ParticlesOptimization.prototype.getDescription = function () {
return "Turning particles on/off";
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @returns true if everything that can be done was applied
*/
ParticlesOptimization.prototype.apply = function (scene, optimizer) {
scene.particlesEnabled = optimizer.isInImprovementMode;
return true;
};
;
return ParticlesOptimization;
}(SceneOptimization));
BABYLON.ParticlesOptimization = ParticlesOptimization;
/**
* Defines an optimization used to turn render targets off
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var RenderTargetsOptimization = /** @class */ (function (_super) {
__extends(RenderTargetsOptimization, _super);
function RenderTargetsOptimization() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Gets a string describing the action executed by the current optimization
* @return description string
*/
RenderTargetsOptimization.prototype.getDescription = function () {
return "Turning render targets off";
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @returns true if everything that can be done was applied
*/
RenderTargetsOptimization.prototype.apply = function (scene, optimizer) {
scene.renderTargetsEnabled = optimizer.isInImprovementMode;
return true;
};
;
return RenderTargetsOptimization;
}(SceneOptimization));
BABYLON.RenderTargetsOptimization = RenderTargetsOptimization;
/**
* Defines an optimization used to merge meshes with compatible materials
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var MergeMeshesOptimization = /** @class */ (function (_super) {
__extends(MergeMeshesOptimization, _super);
function MergeMeshesOptimization() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this._canBeMerged = function (abstractMesh) {
if (!(abstractMesh instanceof BABYLON.Mesh)) {
return false;
}
var mesh = abstractMesh;
if (!mesh.isVisible || !mesh.isEnabled()) {
return false;
}
if (mesh.instances.length > 0) {
return false;
}
if (mesh.skeleton || mesh.hasLODLevels) {
return false;
}
if (mesh.parent) {
return false;
}
return true;
};
return _this;
}
Object.defineProperty(MergeMeshesOptimization, "UpdateSelectionTree", {
/**
* Gets or sets a boolean which defines if optimization octree has to be updated
*/
get: function () {
return MergeMeshesOptimization._UpdateSelectionTree;
},
/**
* Gets or sets a boolean which defines if optimization octree has to be updated
*/
set: function (value) {
MergeMeshesOptimization._UpdateSelectionTree = value;
},
enumerable: true,
configurable: true
});
/**
* Gets a string describing the action executed by the current optimization
* @return description string
*/
MergeMeshesOptimization.prototype.getDescription = function () {
return "Merging similar meshes together";
};
/**
* This function will be called by the SceneOptimizer when its priority is reached in order to apply the change required by the current optimization
* @param scene defines the current scene where to apply this optimization
* @param optimizer defines the current optimizer
* @param updateSelectionTree defines that the selection octree has to be updated (false by default)
* @returns true if everything that can be done was applied
*/
MergeMeshesOptimization.prototype.apply = function (scene, optimizer, updateSelectionTree) {
var globalPool = scene.meshes.slice(0);
var globalLength = globalPool.length;
for (var index = 0; index < globalLength; index++) {
var currentPool = new Array();
var current = globalPool[index];
// Checks
if (!this._canBeMerged(current)) {
continue;
}
currentPool.push(current);
// Find compatible meshes
for (var subIndex = index + 1; subIndex < globalLength; subIndex++) {
var otherMesh = globalPool[subIndex];
if (!this._canBeMerged(otherMesh)) {
continue;
}
if (otherMesh.material !== current.material) {
continue;
}
if (otherMesh.checkCollisions !== current.checkCollisions) {
continue;
}
currentPool.push(otherMesh);
globalLength--;
globalPool.splice(subIndex, 1);
subIndex--;
}
if (currentPool.length < 2) {
continue;
}
// Merge meshes
BABYLON.Mesh.MergeMeshes(currentPool);
}
if (updateSelectionTree != undefined) {
if (updateSelectionTree) {
scene.createOrUpdateSelectionOctree();
}
}
else if (MergeMeshesOptimization.UpdateSelectionTree) {
scene.createOrUpdateSelectionOctree();
}
return true;
};
;
MergeMeshesOptimization._UpdateSelectionTree = false;
return MergeMeshesOptimization;
}(SceneOptimization));
BABYLON.MergeMeshesOptimization = MergeMeshesOptimization;
/**
* Defines a list of options used by SceneOptimizer
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var SceneOptimizerOptions = /** @class */ (function () {
/**
* Creates a new list of options used by SceneOptimizer
* @param targetFrameRate defines the target frame rate to reach (60 by default)
* @param trackerDuration defines the interval between two checkes (2000ms by default)
*/
function SceneOptimizerOptions(
/**
* Defines the target frame rate to reach (60 by default)
*/
targetFrameRate,
/**
* Defines the interval between two checkes (2000ms by default)
*/
trackerDuration) {
if (targetFrameRate === void 0) { targetFrameRate = 60; }
if (trackerDuration === void 0) { trackerDuration = 2000; }
this.targetFrameRate = targetFrameRate;
this.trackerDuration = trackerDuration;
/**
* Gets the list of optimizations to apply
*/
this.optimizations = new Array();
}
/**
* Add a new optimization
* @param optimization defines the SceneOptimization to add to the list of active optimizations
* @returns the current SceneOptimizerOptions
*/
SceneOptimizerOptions.prototype.addOptimization = function (optimization) {
this.optimizations.push(optimization);
return this;
};
/**
* Add a new custom optimization
* @param onApply defines the callback called to apply the custom optimization (true if everything that can be done was applied)
* @param onGetDescription defines the callback called to get the description attached with the optimization.
* @param priority defines the priority of this optimization (0 by default which means first in the list)
* @returns the current SceneOptimizerOptions
*/
SceneOptimizerOptions.prototype.addCustomOptimization = function (onApply, onGetDescription, priority) {
if (priority === void 0) { priority = 0; }
var optimization = new CustomOptimization(priority);
optimization.onApply = onApply;
optimization.onGetDescription = onGetDescription;
this.optimizations.push(optimization);
return this;
};
/**
* Creates a list of pre-defined optimizations aimed to reduce the visual impact on the scene
* @param targetFrameRate defines the target frame rate (60 by default)
* @returns a SceneOptimizerOptions object
*/
SceneOptimizerOptions.LowDegradationAllowed = function (targetFrameRate) {
var result = new SceneOptimizerOptions(targetFrameRate);
var priority = 0;
result.addOptimization(new MergeMeshesOptimization(priority));
result.addOptimization(new ShadowsOptimization(priority));
result.addOptimization(new LensFlaresOptimization(priority));
// Next priority
priority++;
result.addOptimization(new PostProcessesOptimization(priority));
result.addOptimization(new ParticlesOptimization(priority));
// Next priority
priority++;
result.addOptimization(new TextureOptimization(priority, 1024));
return result;
};
/**
* Creates a list of pre-defined optimizations aimed to have a moderate impact on the scene visual
* @param targetFrameRate defines the target frame rate (60 by default)
* @returns a SceneOptimizerOptions object
*/
SceneOptimizerOptions.ModerateDegradationAllowed = function (targetFrameRate) {
var result = new SceneOptimizerOptions(targetFrameRate);
var priority = 0;
result.addOptimization(new MergeMeshesOptimization(priority));
result.addOptimization(new ShadowsOptimization(priority));
result.addOptimization(new LensFlaresOptimization(priority));
// Next priority
priority++;
result.addOptimization(new PostProcessesOptimization(priority));
result.addOptimization(new ParticlesOptimization(priority));
// Next priority
priority++;
result.addOptimization(new TextureOptimization(priority, 512));
// Next priority
priority++;
result.addOptimization(new RenderTargetsOptimization(priority));
// Next priority
priority++;
result.addOptimization(new HardwareScalingOptimization(priority, 2));
return result;
};
/**
* Creates a list of pre-defined optimizations aimed to have a big impact on the scene visual
* @param targetFrameRate defines the target frame rate (60 by default)
* @returns a SceneOptimizerOptions object
*/
SceneOptimizerOptions.HighDegradationAllowed = function (targetFrameRate) {
var result = new SceneOptimizerOptions(targetFrameRate);
var priority = 0;
result.addOptimization(new MergeMeshesOptimization(priority));
result.addOptimization(new ShadowsOptimization(priority));
result.addOptimization(new LensFlaresOptimization(priority));
// Next priority
priority++;
result.addOptimization(new PostProcessesOptimization(priority));
result.addOptimization(new ParticlesOptimization(priority));
// Next priority
priority++;
result.addOptimization(new TextureOptimization(priority, 256));
// Next priority
priority++;
result.addOptimization(new RenderTargetsOptimization(priority));
// Next priority
priority++;
result.addOptimization(new HardwareScalingOptimization(priority, 4));
return result;
};
return SceneOptimizerOptions;
}());
BABYLON.SceneOptimizerOptions = SceneOptimizerOptions;
/**
* Class used to run optimizations in order to reach a target frame rate
* @description More details at http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer
*/
var SceneOptimizer = /** @class */ (function () {
/**
* Creates a new SceneOptimizer
* @param scene defines the scene to work on
* @param options defines the options to use with the SceneOptimizer
* @param autoGeneratePriorities defines if priorities must be generated and not read from SceneOptimization property (true by default)
* @param improvementMode defines if the scene optimizer must run the maximum optimization while staying over a target frame instead of trying to reach the target framerate (false by default)
*/
function SceneOptimizer(scene, options, autoGeneratePriorities, improvementMode) {
if (autoGeneratePriorities === void 0) { autoGeneratePriorities = true; }
if (improvementMode === void 0) { improvementMode = false; }
var _this = this;
this._isRunning = false;
this._currentPriorityLevel = 0;
this._targetFrameRate = 60;
this._trackerDuration = 2000;
this._currentFrameRate = 0;
this._improvementMode = false;
/**
* Defines an observable called when the optimizer reaches the target frame rate
*/
this.onSuccessObservable = new BABYLON.Observable();
/**
* Defines an observable called when the optimizer enables an optimization
*/
this.onNewOptimizationAppliedObservable = new BABYLON.Observable();
/**
* Defines an observable called when the optimizer is not able to reach the target frame rate
*/
this.onFailureObservable = new BABYLON.Observable();
if (!options) {
this._options = new SceneOptimizerOptions();
}
else {
this._options = options;
}
if (this._options.targetFrameRate) {
this._targetFrameRate = this._options.targetFrameRate;
}
if (this._options.trackerDuration) {
this._trackerDuration = this._options.trackerDuration;
}
if (autoGeneratePriorities) {
var priority = 0;
for (var _i = 0, _a = this._options.optimizations; _i < _a.length; _i++) {
var optim = _a[_i];
optim.priority = priority++;
}
}
this._improvementMode = improvementMode;
this._scene = scene || BABYLON.Engine.LastCreatedScene;
this._sceneDisposeObserver = this._scene.onDisposeObservable.add(function () {
_this._sceneDisposeObserver = null;
_this.dispose();
});
}
Object.defineProperty(SceneOptimizer.prototype, "isInImprovementMode", {
/**
* Gets a boolean indicating if the optimizer is in improvement mode
*/
get: function () {
return this._improvementMode;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneOptimizer.prototype, "currentPriorityLevel", {
/**
* Gets the current priority level (0 at start)
*/
get: function () {
return this._currentPriorityLevel;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneOptimizer.prototype, "currentFrameRate", {
/**
* Gets the current frame rate checked by the SceneOptimizer
*/
get: function () {
return this._currentFrameRate;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneOptimizer.prototype, "targetFrameRate", {
/**
* Gets or sets the current target frame rate (60 by default)
*/
get: function () {
return this._targetFrameRate;
},
/**
* Gets or sets the current target frame rate (60 by default)
*/
set: function (value) {
this._targetFrameRate = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneOptimizer.prototype, "trackerDuration", {
/**
* Gets or sets the current interval between two checks (every 2000ms by default)
*/
get: function () {
return this._trackerDuration;
},
/**
* Gets or sets the current interval between two checks (every 2000ms by default)
*/
set: function (value) {
this._trackerDuration = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneOptimizer.prototype, "optimizations", {
/**
* Gets the list of active optimizations
*/
get: function () {
return this._options.optimizations;
},
enumerable: true,
configurable: true
});
/**
* Stops the current optimizer
*/
SceneOptimizer.prototype.stop = function () {
this._isRunning = false;
};
/**
* Reset the optimizer to initial step (current priority level = 0)
*/
SceneOptimizer.prototype.reset = function () {
this._currentPriorityLevel = 0;
};
/**
* Start the optimizer. By default it will try to reach a specific framerate
* but if the optimizer is set with improvementMode === true then it will run all optimiatiation while frame rate is above the target frame rate
*/
SceneOptimizer.prototype.start = function () {
var _this = this;
if (this._isRunning) {
return;
}
this._isRunning = true;
// Let's wait for the scene to be ready before running our check
this._scene.executeWhenReady(function () {
setTimeout(function () {
_this._checkCurrentState();
}, _this._trackerDuration);
});
};
SceneOptimizer.prototype._checkCurrentState = function () {
var _this = this;
if (!this._isRunning) {
return;
}
var scene = this._scene;
var options = this._options;
this._currentFrameRate = Math.round(scene.getEngine().getFps());
if (this._improvementMode && this._currentFrameRate <= this._targetFrameRate ||
!this._improvementMode && this._currentFrameRate >= this._targetFrameRate) {
this._isRunning = false;
this.onSuccessObservable.notifyObservers(this);
return;
}
// Apply current level of optimizations
var allDone = true;
var noOptimizationApplied = true;
for (var index = 0; index < options.optimizations.length; index++) {
var optimization = options.optimizations[index];
if (optimization.priority === this._currentPriorityLevel) {
noOptimizationApplied = false;
allDone = allDone && optimization.apply(scene, this);
this.onNewOptimizationAppliedObservable.notifyObservers(optimization);
}
}
// If no optimization was applied, this is a failure :(
if (noOptimizationApplied) {
this._isRunning = false;
this.onFailureObservable.notifyObservers(this);
return;
}
// If all optimizations were done, move to next level
if (allDone) {
this._currentPriorityLevel++;
}
// Let's the system running for a specific amount of time before checking FPS
scene.executeWhenReady(function () {
setTimeout(function () {
_this._checkCurrentState();
}, _this._trackerDuration);
});
};
/**
* Release all resources
*/
SceneOptimizer.prototype.dispose = function () {
this.stop();
this.onSuccessObservable.clear();
this.onFailureObservable.clear();
this.onNewOptimizationAppliedObservable.clear();
if (this._sceneDisposeObserver) {
this._scene.onDisposeObservable.remove(this._sceneDisposeObserver);
}
};
/**
* Helper function to create a SceneOptimizer with one single line of code
* @param scene defines the scene to work on
* @param options defines the options to use with the SceneOptimizer
* @param onSuccess defines a callback to call on success
* @param onFailure defines a callback to call on failure
* @returns the new SceneOptimizer object
*/
SceneOptimizer.OptimizeAsync = function (scene, options, onSuccess, onFailure) {
var optimizer = new SceneOptimizer(scene, options || SceneOptimizerOptions.ModerateDegradationAllowed(), false);
if (onSuccess) {
optimizer.onSuccessObservable.add(function () {
onSuccess();
});
}
if (onFailure) {
optimizer.onFailureObservable.add(function () {
onFailure();
});
}
optimizer.start();
return optimizer;
};
return SceneOptimizer;
}());
BABYLON.SceneOptimizer = SceneOptimizer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.sceneOptimizer.js.map
var BABYLON;
(function (BABYLON) {
var OutlineRenderer = /** @class */ (function () {
function OutlineRenderer(scene) {
this.zOffset = 1;
this._scene = scene;
}
OutlineRenderer.prototype.render = function (subMesh, batch, useOverlay) {
var _this = this;
if (useOverlay === void 0) { useOverlay = false; }
var scene = this._scene;
var engine = this._scene.getEngine();
var hardwareInstancedRendering = (engine.getCaps().instancedArrays) && (batch.visibleInstances[subMesh._id] !== null) && (batch.visibleInstances[subMesh._id] !== undefined);
if (!this.isReady(subMesh, hardwareInstancedRendering)) {
return;
}
var mesh = subMesh.getRenderingMesh();
var material = subMesh.getMaterial();
if (!material || !scene.activeCamera) {
return;
}
engine.enableEffect(this._effect);
// Logarithmic depth
if (material.useLogarithmicDepth) {
this._effect.setFloat("logarithmicDepthConstant", 2.0 / (Math.log(scene.activeCamera.maxZ + 1.0) / Math.LN2));
}
this._effect.setFloat("offset", useOverlay ? 0 : mesh.outlineWidth);
this._effect.setColor4("color", useOverlay ? mesh.overlayColor : mesh.outlineColor, useOverlay ? mesh.overlayAlpha : material.alpha);
this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
// Bones
if (mesh.useBones && mesh.computeBonesUsingShaders && mesh.skeleton) {
this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices(mesh));
}
mesh._bind(subMesh, this._effect, BABYLON.Material.TriangleFillMode);
// Alpha test
if (material && material.needAlphaTesting()) {
var alphaTexture = material.getAlphaTestTexture();
if (alphaTexture) {
this._effect.setTexture("diffuseSampler", alphaTexture);
this._effect.setMatrix("diffuseMatrix", alphaTexture.getTextureMatrix());
}
}
engine.setZOffset(-this.zOffset);
mesh._processRendering(subMesh, this._effect, BABYLON.Material.TriangleFillMode, batch, hardwareInstancedRendering, function (isInstance, world) { _this._effect.setMatrix("world", world); });
engine.setZOffset(0);
};
OutlineRenderer.prototype.isReady = function (subMesh, useInstances) {
var defines = [];
var attribs = [BABYLON.VertexBuffer.PositionKind, BABYLON.VertexBuffer.NormalKind];
var mesh = subMesh.getMesh();
var material = subMesh.getMaterial();
if (material) {
// Alpha test
if (material.needAlphaTesting()) {
defines.push("#define ALPHATEST");
if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
attribs.push(BABYLON.VertexBuffer.UVKind);
defines.push("#define UV1");
}
if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind)) {
attribs.push(BABYLON.VertexBuffer.UV2Kind);
defines.push("#define UV2");
}
}
//Logarithmic depth
if (material.useLogarithmicDepth) {
defines.push("#define LOGARITHMICDEPTH");
}
}
// Bones
if (mesh.useBones && mesh.computeBonesUsingShaders) {
attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);
attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);
if (mesh.numBoneInfluencers > 4) {
attribs.push(BABYLON.VertexBuffer.MatricesIndicesExtraKind);
attribs.push(BABYLON.VertexBuffer.MatricesWeightsExtraKind);
}
defines.push("#define NUM_BONE_INFLUENCERS " + mesh.numBoneInfluencers);
defines.push("#define BonesPerMesh " + (mesh.skeleton ? mesh.skeleton.bones.length + 1 : 0));
}
else {
defines.push("#define NUM_BONE_INFLUENCERS 0");
}
// Instances
if (useInstances) {
defines.push("#define INSTANCES");
attribs.push("world0");
attribs.push("world1");
attribs.push("world2");
attribs.push("world3");
}
// Get correct effect
var join = defines.join("\n");
if (this._cachedDefines !== join) {
this._cachedDefines = join;
this._effect = this._scene.getEngine().createEffect("outline", attribs, ["world", "mBones", "viewProjection", "diffuseMatrix", "offset", "color", "logarithmicDepthConstant"], ["diffuseSampler"], join);
}
return this._effect.isReady();
};
return OutlineRenderer;
}());
BABYLON.OutlineRenderer = OutlineRenderer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.outlineRenderer.js.map
var BABYLON;
(function (BABYLON) {
var FaceAdjacencies = /** @class */ (function () {
function FaceAdjacencies() {
this.edges = new Array();
this.edgesConnectedCount = 0;
}
return FaceAdjacencies;
}());
var EdgesRenderer = /** @class */ (function () {
// Beware when you use this class with complex objects as the adjacencies computation can be really long
function EdgesRenderer(source, epsilon, checkVerticesInsteadOfIndices) {
if (epsilon === void 0) { epsilon = 0.95; }
if (checkVerticesInsteadOfIndices === void 0) { checkVerticesInsteadOfIndices = false; }
this.edgesWidthScalerForOrthographic = 1000.0;
this.edgesWidthScalerForPerspective = 50.0;
this._linesPositions = new Array();
this._linesNormals = new Array();
this._linesIndices = new Array();
this._buffers = {};
this._checkVerticesInsteadOfIndices = false;
this._source = source;
this._checkVerticesInsteadOfIndices = checkVerticesInsteadOfIndices;
this._epsilon = epsilon;
this._prepareRessources();
this._generateEdgesLines();
}
EdgesRenderer.prototype._prepareRessources = function () {
if (this._lineShader) {
return;
}
this._lineShader = new BABYLON.ShaderMaterial("lineShader", this._source.getScene(), "line", {
attributes: ["position", "normal"],
uniforms: ["worldViewProjection", "color", "width", "aspectRatio"]
});
this._lineShader.disableDepthWrite = true;
this._lineShader.backFaceCulling = false;
};
EdgesRenderer.prototype._rebuild = function () {
var buffer = this._buffers[BABYLON.VertexBuffer.PositionKind];
if (buffer) {
buffer._rebuild();
}
buffer = this._buffers[BABYLON.VertexBuffer.NormalKind];
if (buffer) {
buffer._rebuild();
}
var scene = this._source.getScene();
var engine = scene.getEngine();
this._ib = engine.createIndexBuffer(this._linesIndices);
};
EdgesRenderer.prototype.dispose = function () {
var buffer = this._buffers[BABYLON.VertexBuffer.PositionKind];
if (buffer) {
buffer.dispose();
this._buffers[BABYLON.VertexBuffer.PositionKind] = null;
}
buffer = this._buffers[BABYLON.VertexBuffer.NormalKind];
if (buffer) {
buffer.dispose();
this._buffers[BABYLON.VertexBuffer.NormalKind] = null;
}
this._source.getScene().getEngine()._releaseBuffer(this._ib);
this._lineShader.dispose();
};
EdgesRenderer.prototype._processEdgeForAdjacencies = function (pa, pb, p0, p1, p2) {
if (pa === p0 && pb === p1 || pa === p1 && pb === p0) {
return 0;
}
if (pa === p1 && pb === p2 || pa === p2 && pb === p1) {
return 1;
}
if (pa === p2 && pb === p0 || pa === p0 && pb === p2) {
return 2;
}
return -1;
};
EdgesRenderer.prototype._processEdgeForAdjacenciesWithVertices = function (pa, pb, p0, p1, p2) {
if (pa.equalsWithEpsilon(p0) && pb.equalsWithEpsilon(p1) || pa.equalsWithEpsilon(p1) && pb.equalsWithEpsilon(p0)) {
return 0;
}
if (pa.equalsWithEpsilon(p1) && pb.equalsWithEpsilon(p2) || pa.equalsWithEpsilon(p2) && pb.equalsWithEpsilon(p1)) {
return 1;
}
if (pa.equalsWithEpsilon(p2) && pb.equalsWithEpsilon(p0) || pa.equalsWithEpsilon(p0) && pb.equalsWithEpsilon(p2)) {
return 2;
}
return -1;
};
EdgesRenderer.prototype._checkEdge = function (faceIndex, edge, faceNormals, p0, p1) {
var needToCreateLine;
if (edge === undefined) {
needToCreateLine = true;
}
else {
var dotProduct = BABYLON.Vector3.Dot(faceNormals[faceIndex], faceNormals[edge]);
needToCreateLine = dotProduct < this._epsilon;
}
if (needToCreateLine) {
var offset = this._linesPositions.length / 3;
var normal = p0.subtract(p1);
normal.normalize();
// Positions
this._linesPositions.push(p0.x);
this._linesPositions.push(p0.y);
this._linesPositions.push(p0.z);
this._linesPositions.push(p0.x);
this._linesPositions.push(p0.y);
this._linesPositions.push(p0.z);
this._linesPositions.push(p1.x);
this._linesPositions.push(p1.y);
this._linesPositions.push(p1.z);
this._linesPositions.push(p1.x);
this._linesPositions.push(p1.y);
this._linesPositions.push(p1.z);
// Normals
this._linesNormals.push(p1.x);
this._linesNormals.push(p1.y);
this._linesNormals.push(p1.z);
this._linesNormals.push(-1);
this._linesNormals.push(p1.x);
this._linesNormals.push(p1.y);
this._linesNormals.push(p1.z);
this._linesNormals.push(1);
this._linesNormals.push(p0.x);
this._linesNormals.push(p0.y);
this._linesNormals.push(p0.z);
this._linesNormals.push(-1);
this._linesNormals.push(p0.x);
this._linesNormals.push(p0.y);
this._linesNormals.push(p0.z);
this._linesNormals.push(1);
// Indices
this._linesIndices.push(offset);
this._linesIndices.push(offset + 1);
this._linesIndices.push(offset + 2);
this._linesIndices.push(offset);
this._linesIndices.push(offset + 2);
this._linesIndices.push(offset + 3);
}
};
EdgesRenderer.prototype._generateEdgesLines = function () {
var positions = this._source.getVerticesData(BABYLON.VertexBuffer.PositionKind);
var indices = this._source.getIndices();
if (!indices || !positions) {
return;
}
// First let's find adjacencies
var adjacencies = new Array();
var faceNormals = new Array();
var index;
var faceAdjacencies;
// Prepare faces
for (index = 0; index < indices.length; index += 3) {
faceAdjacencies = new FaceAdjacencies();
var p0Index = indices[index];
var p1Index = indices[index + 1];
var p2Index = indices[index + 2];
faceAdjacencies.p0 = new BABYLON.Vector3(positions[p0Index * 3], positions[p0Index * 3 + 1], positions[p0Index * 3 + 2]);
faceAdjacencies.p1 = new BABYLON.Vector3(positions[p1Index * 3], positions[p1Index * 3 + 1], positions[p1Index * 3 + 2]);
faceAdjacencies.p2 = new BABYLON.Vector3(positions[p2Index * 3], positions[p2Index * 3 + 1], positions[p2Index * 3 + 2]);
var faceNormal = BABYLON.Vector3.Cross(faceAdjacencies.p1.subtract(faceAdjacencies.p0), faceAdjacencies.p2.subtract(faceAdjacencies.p1));
faceNormal.normalize();
faceNormals.push(faceNormal);
adjacencies.push(faceAdjacencies);
}
// Scan
for (index = 0; index < adjacencies.length; index++) {
faceAdjacencies = adjacencies[index];
for (var otherIndex = index + 1; otherIndex < adjacencies.length; otherIndex++) {
var otherFaceAdjacencies = adjacencies[otherIndex];
if (faceAdjacencies.edgesConnectedCount === 3) {
break;
}
if (otherFaceAdjacencies.edgesConnectedCount === 3) {
continue;
}
var otherP0 = indices[otherIndex * 3];
var otherP1 = indices[otherIndex * 3 + 1];
var otherP2 = indices[otherIndex * 3 + 2];
for (var edgeIndex = 0; edgeIndex < 3; edgeIndex++) {
var otherEdgeIndex = 0;
if (faceAdjacencies.edges[edgeIndex] !== undefined) {
continue;
}
switch (edgeIndex) {
case 0:
if (this._checkVerticesInsteadOfIndices) {
otherEdgeIndex = this._processEdgeForAdjacenciesWithVertices(faceAdjacencies.p0, faceAdjacencies.p1, otherFaceAdjacencies.p0, otherFaceAdjacencies.p1, otherFaceAdjacencies.p2);
}
else {
otherEdgeIndex = this._processEdgeForAdjacencies(indices[index * 3], indices[index * 3 + 1], otherP0, otherP1, otherP2);
}
break;
case 1:
if (this._checkVerticesInsteadOfIndices) {
otherEdgeIndex = this._processEdgeForAdjacenciesWithVertices(faceAdjacencies.p1, faceAdjacencies.p2, otherFaceAdjacencies.p0, otherFaceAdjacencies.p1, otherFaceAdjacencies.p2);
}
else {
otherEdgeIndex = this._processEdgeForAdjacencies(indices[index * 3 + 1], indices[index * 3 + 2], otherP0, otherP1, otherP2);
}
break;
case 2:
if (this._checkVerticesInsteadOfIndices) {
otherEdgeIndex = this._processEdgeForAdjacenciesWithVertices(faceAdjacencies.p2, faceAdjacencies.p0, otherFaceAdjacencies.p0, otherFaceAdjacencies.p1, otherFaceAdjacencies.p2);
}
else {
otherEdgeIndex = this._processEdgeForAdjacencies(indices[index * 3 + 2], indices[index * 3], otherP0, otherP1, otherP2);
}
break;
}
if (otherEdgeIndex === -1) {
continue;
}
faceAdjacencies.edges[edgeIndex] = otherIndex;
otherFaceAdjacencies.edges[otherEdgeIndex] = index;
faceAdjacencies.edgesConnectedCount++;
otherFaceAdjacencies.edgesConnectedCount++;
if (faceAdjacencies.edgesConnectedCount === 3) {
break;
}
}
}
}
// Create lines
for (index = 0; index < adjacencies.length; index++) {
// We need a line when a face has no adjacency on a specific edge or if all the adjacencies has an angle greater than epsilon
var current = adjacencies[index];
this._checkEdge(index, current.edges[0], faceNormals, current.p0, current.p1);
this._checkEdge(index, current.edges[1], faceNormals, current.p1, current.p2);
this._checkEdge(index, current.edges[2], faceNormals, current.p2, current.p0);
}
// Merge into a single mesh
var engine = this._source.getScene().getEngine();
this._buffers[BABYLON.VertexBuffer.PositionKind] = new BABYLON.VertexBuffer(engine, this._linesPositions, BABYLON.VertexBuffer.PositionKind, false);
this._buffers[BABYLON.VertexBuffer.NormalKind] = new BABYLON.VertexBuffer(engine, this._linesNormals, BABYLON.VertexBuffer.NormalKind, false, false, 4);
this._ib = engine.createIndexBuffer(this._linesIndices);
this._indicesCount = this._linesIndices.length;
};
EdgesRenderer.prototype.render = function () {
var scene = this._source.getScene();
if (!this._lineShader.isReady() || !scene.activeCamera) {
return;
}
var engine = scene.getEngine();
this._lineShader._preBind();
// VBOs
engine.bindBuffers(this._buffers, this._ib, this._lineShader.getEffect());
scene.resetCachedMaterial();
this._lineShader.setColor4("color", this._source.edgesColor);
if (scene.activeCamera.mode === BABYLON.Camera.ORTHOGRAPHIC_CAMERA) {
this._lineShader.setFloat("width", this._source.edgesWidth / this.edgesWidthScalerForOrthographic);
}
else {
this._lineShader.setFloat("width", this._source.edgesWidth / this.edgesWidthScalerForPerspective);
}
this._lineShader.setFloat("aspectRatio", engine.getAspectRatio(scene.activeCamera));
this._lineShader.bind(this._source.getWorldMatrix());
// Draw order
engine.drawElementsType(BABYLON.Material.TriangleFillMode, 0, this._indicesCount);
this._lineShader.unbind();
engine.setDepthWrite(true);
};
return EdgesRenderer;
}());
BABYLON.EdgesRenderer = EdgesRenderer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.edgesRenderer.js.map
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
var BABYLON;
(function (BABYLON) {
/**
* The effect layer Helps adding post process effect blended with the main pass.
*
* This can be for instance use to generate glow or higlight effects on the scene.
*
* The effect layer class can not be used directly and is intented to inherited from to be
* customized per effects.
*/
var EffectLayer = /** @class */ (function () {
/**
* Instantiates a new effect Layer and references it in the scene.
* @param name The name of the layer
* @param scene The scene to use the layer in
*/
function EffectLayer(
/** The Friendly of the effect in the scene */
name, scene) {
this.name = name;
this._vertexBuffers = {};
this._maxSize = 0;
this._mainTextureDesiredSize = { width: 0, height: 0 };
this._shouldRender = true;
this._postProcesses = [];
this._textures = [];
this._emissiveTextureAndColor = { texture: null, color: new BABYLON.Color4() };
/**
* The clear color of the texture used to generate the glow map.
*/
this.neutralColor = new BABYLON.Color4();
/**
* Specifies wether the highlight layer is enabled or not.
*/
this.isEnabled = true;
/**
* An event triggered when the effect layer has been disposed.
*/
this.onDisposeObservable = new BABYLON.Observable();
/**
* An event triggered when the effect layer is about rendering the main texture with the glowy parts.
*/
this.onBeforeRenderMainTextureObservable = new BABYLON.Observable();
/**
* An event triggered when the generated texture is being merged in the scene.
*/
this.onBeforeComposeObservable = new BABYLON.Observable();
/**
* An event triggered when the generated texture has been merged in the scene.
*/
this.onAfterComposeObservable = new BABYLON.Observable();
/**
* An event triggered when the efffect layer changes its size.
*/
this.onSizeChangedObservable = new BABYLON.Observable();
this._scene = scene || BABYLON.Engine.LastCreatedScene;
this._engine = scene.getEngine();
this._maxSize = this._engine.getCaps().maxTextureSize;
this._scene.effectLayers.push(this);
// Generate Buffers
this._generateIndexBuffer();
this._genrateVertexBuffer();
}
Object.defineProperty(EffectLayer.prototype, "camera", {
/**
* Gets the camera attached to the layer.
*/
get: function () {
return this._effectLayerOptions.camera;
},
enumerable: true,
configurable: true
});
/**
* Initializes the effect layer with the required options.
* @param options Sets of none mandatory options to use with the layer (see IEffectLayerOptions for more information)
*/
EffectLayer.prototype._init = function (options) {
// Adapt options
this._effectLayerOptions = __assign({ mainTextureRatio: 0.5, alphaBlendingMode: BABYLON.Engine.ALPHA_COMBINE, camera: null }, options);
this._setMainTextureSize();
this._createMainTexture();
this._createTextureAndPostProcesses();
this._mergeEffect = this._createMergeEffect();
};
/**
* Generates the index buffer of the full screen quad blending to the main canvas.
*/
EffectLayer.prototype._generateIndexBuffer = function () {
// Indices
var indices = [];
indices.push(0);
indices.push(1);
indices.push(2);
indices.push(0);
indices.push(2);
indices.push(3);
this._indexBuffer = this._engine.createIndexBuffer(indices);
};
/**
* Generates the vertex buffer of the full screen quad blending to the main canvas.
*/
EffectLayer.prototype._genrateVertexBuffer = function () {
// VBO
var vertices = [];
vertices.push(1, 1);
vertices.push(-1, 1);
vertices.push(-1, -1);
vertices.push(1, -1);
var vertexBuffer = new BABYLON.VertexBuffer(this._engine, vertices, BABYLON.VertexBuffer.PositionKind, false, false, 2);
this._vertexBuffers[BABYLON.VertexBuffer.PositionKind] = vertexBuffer;
};
/**
* Sets the main texture desired size which is the closest power of two
* of the engine canvas size.
*/
EffectLayer.prototype._setMainTextureSize = function () {
if (this._effectLayerOptions.mainTextureFixedSize) {
this._mainTextureDesiredSize.width = this._effectLayerOptions.mainTextureFixedSize;
this._mainTextureDesiredSize.height = this._effectLayerOptions.mainTextureFixedSize;
}
else {
this._mainTextureDesiredSize.width = this._engine.getRenderWidth() * this._effectLayerOptions.mainTextureRatio;
this._mainTextureDesiredSize.height = this._engine.getRenderHeight() * this._effectLayerOptions.mainTextureRatio;
this._mainTextureDesiredSize.width = this._engine.needPOTTextures ? BABYLON.Tools.GetExponentOfTwo(this._mainTextureDesiredSize.width, this._maxSize) : this._mainTextureDesiredSize.width;
this._mainTextureDesiredSize.height = this._engine.needPOTTextures ? BABYLON.Tools.GetExponentOfTwo(this._mainTextureDesiredSize.height, this._maxSize) : this._mainTextureDesiredSize.height;
}
this._mainTextureDesiredSize.width = Math.floor(this._mainTextureDesiredSize.width);
this._mainTextureDesiredSize.height = Math.floor(this._mainTextureDesiredSize.height);
};
/**
* Creates the main texture for the effect layer.
*/
EffectLayer.prototype._createMainTexture = function () {
var _this = this;
this._mainTexture = new BABYLON.RenderTargetTexture("HighlightLayerMainRTT", {
width: this._mainTextureDesiredSize.width,
height: this._mainTextureDesiredSize.height
}, this._scene, false, true, BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT);
this._mainTexture.activeCamera = this._effectLayerOptions.camera;
this._mainTexture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
this._mainTexture.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
this._mainTexture.anisotropicFilteringLevel = 1;
this._mainTexture.updateSamplingMode(BABYLON.Texture.BILINEAR_SAMPLINGMODE);
this._mainTexture.renderParticles = false;
this._mainTexture.renderList = null;
this._mainTexture.ignoreCameraViewport = true;
// Custom render function
this._mainTexture.customRenderFunction = function (opaqueSubMeshes, alphaTestSubMeshes, transparentSubMeshes, depthOnlySubMeshes) {
_this.onBeforeRenderMainTextureObservable.notifyObservers(_this);
var index;
var engine = _this._scene.getEngine();
if (depthOnlySubMeshes.length) {
engine.setColorWrite(false);
for (index = 0; index < depthOnlySubMeshes.length; index++) {
_this._renderSubMesh(depthOnlySubMeshes.data[index]);
}
engine.setColorWrite(true);
}
for (index = 0; index < opaqueSubMeshes.length; index++) {
_this._renderSubMesh(opaqueSubMeshes.data[index]);
}
for (index = 0; index < alphaTestSubMeshes.length; index++) {
_this._renderSubMesh(alphaTestSubMeshes.data[index]);
}
for (index = 0; index < transparentSubMeshes.length; index++) {
_this._renderSubMesh(transparentSubMeshes.data[index]);
}
};
this._mainTexture.onClearObservable.add(function (engine) {
engine.clear(_this.neutralColor, true, true, true);
});
};
/**
* Checks for the readiness of the element composing the layer.
* @param subMesh the mesh to check for
* @param useInstances specify wether or not to use instances to render the mesh
* @param emissiveTexture the associated emissive texture used to generate the glow
* @return true if ready otherwise, false
*/
EffectLayer.prototype._isReady = function (subMesh, useInstances, emissiveTexture) {
var material = subMesh.getMaterial();
if (!material) {
return false;
}
if (!material.isReady(subMesh.getMesh(), useInstances)) {
return false;
}
var defines = [];
var attribs = [BABYLON.VertexBuffer.PositionKind];
var mesh = subMesh.getMesh();
var uv1 = false;
var uv2 = false;
// Alpha test
if (material && material.needAlphaTesting()) {
var alphaTexture = material.getAlphaTestTexture();
if (alphaTexture) {
defines.push("#define ALPHATEST");
if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind) &&
alphaTexture.coordinatesIndex === 1) {
defines.push("#define DIFFUSEUV2");
uv2 = true;
}
else if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
defines.push("#define DIFFUSEUV1");
uv1 = true;
}
}
}
// Emissive
if (emissiveTexture) {
defines.push("#define EMISSIVE");
if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind) &&
emissiveTexture.coordinatesIndex === 1) {
defines.push("#define EMISSIVEUV2");
uv2 = true;
}
else if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
defines.push("#define EMISSIVEUV1");
uv1 = true;
}
}
if (uv1) {
attribs.push(BABYLON.VertexBuffer.UVKind);
defines.push("#define UV1");
}
if (uv2) {
attribs.push(BABYLON.VertexBuffer.UV2Kind);
defines.push("#define UV2");
}
// Bones
if (mesh.useBones && mesh.computeBonesUsingShaders) {
attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);
attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);
if (mesh.numBoneInfluencers > 4) {
attribs.push(BABYLON.VertexBuffer.MatricesIndicesExtraKind);
attribs.push(BABYLON.VertexBuffer.MatricesWeightsExtraKind);
}
defines.push("#define NUM_BONE_INFLUENCERS " + mesh.numBoneInfluencers);
defines.push("#define BonesPerMesh " + (mesh.skeleton ? (mesh.skeleton.bones.length + 1) : 0));
}
else {
defines.push("#define NUM_BONE_INFLUENCERS 0");
}
// Instances
if (useInstances) {
defines.push("#define INSTANCES");
attribs.push("world0");
attribs.push("world1");
attribs.push("world2");
attribs.push("world3");
}
// Get correct effect
var join = defines.join("\n");
if (this._cachedDefines !== join) {
this._cachedDefines = join;
this._effectLayerMapGenerationEffect = this._scene.getEngine().createEffect("glowMapGeneration", attribs, ["world", "mBones", "viewProjection", "diffuseMatrix", "color", "emissiveMatrix"], ["diffuseSampler", "emissiveSampler"], join);
}
return this._effectLayerMapGenerationEffect.isReady();
};
/**
* Renders the glowing part of the scene by blending the blurred glowing meshes on top of the rendered scene.
*/
EffectLayer.prototype.render = function () {
var currentEffect = this._mergeEffect;
// Check
if (!currentEffect.isReady())
return;
for (var i = 0; i < this._postProcesses.length; i++) {
if (!this._postProcesses[i].isReady()) {
return;
}
}
var engine = this._scene.getEngine();
this.onBeforeComposeObservable.notifyObservers(this);
// Render
engine.enableEffect(currentEffect);
engine.setState(false);
// VBOs
engine.bindBuffers(this._vertexBuffers, this._indexBuffer, currentEffect);
// Cache
var previousAlphaMode = engine.getAlphaMode();
// Go Blend.
engine.setAlphaMode(this._effectLayerOptions.alphaBlendingMode);
// Blends the map on the main canvas.
this._internalRender(currentEffect);
// Restore Alpha
engine.setAlphaMode(previousAlphaMode);
this.onAfterComposeObservable.notifyObservers(this);
// Handle size changes.
var size = this._mainTexture.getSize();
this._setMainTextureSize();
if (size.width !== this._mainTextureDesiredSize.width || size.height !== this._mainTextureDesiredSize.height) {
// Recreate RTT and post processes on size change.
this.onSizeChangedObservable.notifyObservers(this);
this._disposeTextureAndPostProcesses();
this._createMainTexture();
this._createTextureAndPostProcesses();
}
};
/**
* Determine if a given mesh will be used in the current effect.
* @param mesh mesh to test
* @returns true if the mesh will be used
*/
EffectLayer.prototype.hasMesh = function (mesh) {
return true;
};
/**
* Returns true if the layer contains information to display, otherwise false.
* @returns true if the glow layer should be rendered
*/
EffectLayer.prototype.shouldRender = function () {
return this.isEnabled && this._shouldRender;
};
/**
* Returns true if the mesh should render, otherwise false.
* @param mesh The mesh to render
* @returns true if it should render otherwise false
*/
EffectLayer.prototype._shouldRenderMesh = function (mesh) {
return true;
};
/**
* Returns true if the mesh should render, otherwise false.
* @param mesh The mesh to render
* @returns true if it should render otherwise false
*/
EffectLayer.prototype._shouldRenderEmissiveTextureForMesh = function (mesh) {
return true;
};
/**
* Renders the submesh passed in parameter to the generation map.
*/
EffectLayer.prototype._renderSubMesh = function (subMesh) {
var _this = this;
if (!this.shouldRender()) {
return;
}
var material = subMesh.getMaterial();
var mesh = subMesh.getRenderingMesh();
var scene = this._scene;
var engine = scene.getEngine();
if (!material) {
return;
}
// Do not block in blend mode.
if (material.needAlphaBlendingForMesh(mesh)) {
return;
}
// Culling
engine.setState(material.backFaceCulling);
// Managing instances
var batch = mesh._getInstancesRenderList(subMesh._id);
if (batch.mustReturn) {
return;
}
// Early Exit per mesh
if (!this._shouldRenderMesh(mesh)) {
return;
}
var hardwareInstancedRendering = (engine.getCaps().instancedArrays) && (batch.visibleInstances[subMesh._id] !== null) && (batch.visibleInstances[subMesh._id] !== undefined);
this._setEmissiveTextureAndColor(mesh, subMesh, material);
if (this._isReady(subMesh, hardwareInstancedRendering, this._emissiveTextureAndColor.texture)) {
engine.enableEffect(this._effectLayerMapGenerationEffect);
mesh._bind(subMesh, this._effectLayerMapGenerationEffect, BABYLON.Material.TriangleFillMode);
this._effectLayerMapGenerationEffect.setMatrix("viewProjection", scene.getTransformMatrix());
this._effectLayerMapGenerationEffect.setFloat4("color", this._emissiveTextureAndColor.color.r, this._emissiveTextureAndColor.color.g, this._emissiveTextureAndColor.color.b, this._emissiveTextureAndColor.color.a);
// Alpha test
if (material && material.needAlphaTesting()) {
var alphaTexture = material.getAlphaTestTexture();
if (alphaTexture) {
this._effectLayerMapGenerationEffect.setTexture("diffuseSampler", alphaTexture);
var textureMatrix = alphaTexture.getTextureMatrix();
if (textureMatrix) {
this._effectLayerMapGenerationEffect.setMatrix("diffuseMatrix", textureMatrix);
}
}
}
// Glow emissive only
if (this._emissiveTextureAndColor.texture) {
this._effectLayerMapGenerationEffect.setTexture("emissiveSampler", this._emissiveTextureAndColor.texture);
this._effectLayerMapGenerationEffect.setMatrix("emissiveMatrix", this._emissiveTextureAndColor.texture.getTextureMatrix());
}
// Bones
if (mesh.useBones && mesh.computeBonesUsingShaders && mesh.skeleton) {
this._effectLayerMapGenerationEffect.setMatrices("mBones", mesh.skeleton.getTransformMatrices(mesh));
}
// Draw
mesh._processRendering(subMesh, this._effectLayerMapGenerationEffect, BABYLON.Material.TriangleFillMode, batch, hardwareInstancedRendering, function (isInstance, world) { return _this._effectLayerMapGenerationEffect.setMatrix("world", world); });
}
else {
// Need to reset refresh rate of the shadowMap
this._mainTexture.resetRefreshCounter();
}
};
/**
* Rebuild the required buffers.
* @ignore Internal use only.
*/
EffectLayer.prototype._rebuild = function () {
var vb = this._vertexBuffers[BABYLON.VertexBuffer.PositionKind];
if (vb) {
vb._rebuild();
}
this._generateIndexBuffer();
};
/**
* Dispose only the render target textures and post process.
*/
EffectLayer.prototype._disposeTextureAndPostProcesses = function () {
this._mainTexture.dispose();
for (var i = 0; i < this._postProcesses.length; i++) {
if (this._postProcesses[i]) {
this._postProcesses[i].dispose();
}
}
this._postProcesses = [];
for (var i = 0; i < this._textures.length; i++) {
if (this._textures[i]) {
this._textures[i].dispose();
}
}
this._textures = [];
};
/**
* Dispose the highlight layer and free resources.
*/
EffectLayer.prototype.dispose = function () {
var vertexBuffer = this._vertexBuffers[BABYLON.VertexBuffer.PositionKind];
if (vertexBuffer) {
vertexBuffer.dispose();
this._vertexBuffers[BABYLON.VertexBuffer.PositionKind] = null;
}
if (this._indexBuffer) {
this._scene.getEngine()._releaseBuffer(this._indexBuffer);
this._indexBuffer = null;
}
// Clean textures and post processes
this._disposeTextureAndPostProcesses();
// Remove from scene
var index = this._scene.effectLayers.indexOf(this, 0);
if (index > -1) {
this._scene.effectLayers.splice(index, 1);
}
// Callback
this.onDisposeObservable.notifyObservers(this);
this.onDisposeObservable.clear();
this.onBeforeRenderMainTextureObservable.clear();
this.onBeforeComposeObservable.clear();
this.onAfterComposeObservable.clear();
this.onSizeChangedObservable.clear();
};
return EffectLayer;
}());
BABYLON.EffectLayer = EffectLayer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.effectLayer.js.map
var BABYLON;
(function (BABYLON) {
/**
* Special Glow Blur post process only blurring the alpha channel
* It enforces keeping the most luminous color in the color channel.
*/
var GlowBlurPostProcess = /** @class */ (function (_super) {
__extends(GlowBlurPostProcess, _super);
function GlowBlurPostProcess(name, direction, kernel, options, camera, samplingMode, engine, reusable) {
if (samplingMode === void 0) { samplingMode = BABYLON.Texture.BILINEAR_SAMPLINGMODE; }
var _this = _super.call(this, name, "glowBlurPostProcess", ["screenSize", "direction", "blurWidth"], null, options, camera, samplingMode, engine, reusable) || this;
_this.direction = direction;
_this.kernel = kernel;
_this.onApplyObservable.add(function (effect) {
effect.setFloat2("screenSize", _this.width, _this.height);
effect.setVector2("direction", _this.direction);
effect.setFloat("blurWidth", _this.kernel);
});
return _this;
}
return GlowBlurPostProcess;
}(BABYLON.PostProcess));
/**
* The highlight layer Helps adding a glow effect around a mesh.
*
* Once instantiated in a scene, simply use the pushMesh or removeMesh method to add or remove
* glowy meshes to your scene.
*
* !!! THIS REQUIRES AN ACTIVE STENCIL BUFFER ON THE CANVAS !!!
*/
var HighlightLayer = /** @class */ (function (_super) {
__extends(HighlightLayer, _super);
/**
* Instantiates a new highlight Layer and references it to the scene..
* @param name The name of the layer
* @param scene The scene to use the layer in
* @param options Sets of none mandatory options to use with the layer (see IHighlightLayerOptions for more information)
*/
function HighlightLayer(name, scene, options) {
var _this = _super.call(this, name, scene) || this;
_this.name = name;
/**
* Specifies whether or not the inner glow is ACTIVE in the layer.
*/
_this.innerGlow = true;
/**
* Specifies whether or not the outer glow is ACTIVE in the layer.
*/
_this.outerGlow = true;
/**
* An event triggered when the highlight layer is being blurred.
*/
_this.onBeforeBlurObservable = new BABYLON.Observable();
/**
* An event triggered when the highlight layer has been blurred.
*/
_this.onAfterBlurObservable = new BABYLON.Observable();
_this._instanceGlowingMeshStencilReference = HighlightLayer.GlowingMeshStencilReference++;
_this._meshes = {};
_this._excludedMeshes = {};
_this.neutralColor = HighlightLayer.NeutralColor;
// Warn on stencil
if (!_this._engine.isStencilEnable) {
BABYLON.Tools.Warn("Rendering the Highlight Layer requires the stencil to be active on the canvas. var engine = new BABYLON.Engine(canvas, antialias, { stencil: true }");
}
// Adapt options
_this._options = __assign({ mainTextureRatio: 0.5, blurTextureSizeRatio: 0.5, blurHorizontalSize: 1.0, blurVerticalSize: 1.0, alphaBlendingMode: BABYLON.Engine.ALPHA_COMBINE, camera: null }, options);
// Initialize the layer
_this._init({
alphaBlendingMode: _this._options.alphaBlendingMode,
camera: _this._options.camera,
mainTextureFixedSize: _this._options.mainTextureFixedSize,
mainTextureRatio: _this._options.mainTextureRatio
});
// Do not render as long as no meshes have been added
_this._shouldRender = false;
return _this;
}
Object.defineProperty(HighlightLayer.prototype, "blurHorizontalSize", {
/**
* Gets the horizontal size of the blur.
*/
get: function () {
return this._horizontalBlurPostprocess.kernel;
},
/**
* Specifies the horizontal size of the blur.
*/
set: function (value) {
this._horizontalBlurPostprocess.kernel = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(HighlightLayer.prototype, "blurVerticalSize", {
/**
* Gets the vertical size of the blur.
*/
get: function () {
return this._verticalBlurPostprocess.kernel;
},
/**
* Specifies the vertical size of the blur.
*/
set: function (value) {
this._verticalBlurPostprocess.kernel = value;
},
enumerable: true,
configurable: true
});
/**
* Get the effect name of the layer.
* @return The effect name
*/
HighlightLayer.prototype.getEffectName = function () {
return HighlightLayer.EffectName;
};
/**
* Create the merge effect. This is the shader use to blit the information back
* to the main canvas at the end of the scene rendering.
*/
HighlightLayer.prototype._createMergeEffect = function () {
// Effect
return this._engine.createEffect("glowMapMerge", [BABYLON.VertexBuffer.PositionKind], ["offset"], ["textureSampler"], this._options.isStroke ? "#define STROKE \n" : undefined);
};
/**
* Creates the render target textures and post processes used in the highlight layer.
*/
HighlightLayer.prototype._createTextureAndPostProcesses = function () {
var _this = this;
var blurTextureWidth = this._mainTextureDesiredSize.width * this._options.blurTextureSizeRatio;
var blurTextureHeight = this._mainTextureDesiredSize.height * this._options.blurTextureSizeRatio;
blurTextureWidth = this._engine.needPOTTextures ? BABYLON.Tools.GetExponentOfTwo(blurTextureWidth, this._maxSize) : blurTextureWidth;
blurTextureHeight = this._engine.needPOTTextures ? BABYLON.Tools.GetExponentOfTwo(blurTextureHeight, this._maxSize) : blurTextureHeight;
this._blurTexture = new BABYLON.RenderTargetTexture("HighlightLayerBlurRTT", {
width: blurTextureWidth,
height: blurTextureHeight
}, this._scene, false, true, BABYLON.Engine.TEXTURETYPE_HALF_FLOAT);
this._blurTexture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
this._blurTexture.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
this._blurTexture.anisotropicFilteringLevel = 16;
this._blurTexture.updateSamplingMode(BABYLON.Texture.TRILINEAR_SAMPLINGMODE);
this._blurTexture.renderParticles = false;
this._blurTexture.ignoreCameraViewport = true;
this._textures = [this._blurTexture];
if (this._options.alphaBlendingMode === BABYLON.Engine.ALPHA_COMBINE) {
this._downSamplePostprocess = new BABYLON.PassPostProcess("HighlightLayerPPP", this._options.blurTextureSizeRatio, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine());
this._downSamplePostprocess.onApplyObservable.add(function (effect) {
effect.setTexture("textureSampler", _this._mainTexture);
});
this._horizontalBlurPostprocess = new GlowBlurPostProcess("HighlightLayerHBP", new BABYLON.Vector2(1.0, 0), this._options.blurHorizontalSize, 1, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine());
this._horizontalBlurPostprocess.onApplyObservable.add(function (effect) {
effect.setFloat2("screenSize", blurTextureWidth, blurTextureHeight);
});
this._verticalBlurPostprocess = new GlowBlurPostProcess("HighlightLayerVBP", new BABYLON.Vector2(0, 1.0), this._options.blurVerticalSize, 1, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine());
this._verticalBlurPostprocess.onApplyObservable.add(function (effect) {
effect.setFloat2("screenSize", blurTextureWidth, blurTextureHeight);
});
this._postProcesses = [this._downSamplePostprocess, this._horizontalBlurPostprocess, this._verticalBlurPostprocess];
}
else {
this._horizontalBlurPostprocess = new BABYLON.BlurPostProcess("HighlightLayerHBP", new BABYLON.Vector2(1.0, 0), this._options.blurHorizontalSize / 2, {
width: blurTextureWidth,
height: blurTextureHeight
}, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, BABYLON.Engine.TEXTURETYPE_HALF_FLOAT);
this._horizontalBlurPostprocess.width = blurTextureWidth;
this._horizontalBlurPostprocess.height = blurTextureHeight;
this._horizontalBlurPostprocess.onApplyObservable.add(function (effect) {
effect.setTexture("textureSampler", _this._mainTexture);
});
this._verticalBlurPostprocess = new BABYLON.BlurPostProcess("HighlightLayerVBP", new BABYLON.Vector2(0, 1.0), this._options.blurVerticalSize / 2, {
width: blurTextureWidth,
height: blurTextureHeight
}, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, BABYLON.Engine.TEXTURETYPE_HALF_FLOAT);
this._postProcesses = [this._horizontalBlurPostprocess, this._verticalBlurPostprocess];
}
this._mainTexture.onAfterUnbindObservable.add(function () {
_this.onBeforeBlurObservable.notifyObservers(_this);
var internalTexture = _this._blurTexture.getInternalTexture();
if (internalTexture) {
_this._scene.postProcessManager.directRender(_this._postProcesses, internalTexture, true);
}
_this.onAfterBlurObservable.notifyObservers(_this);
});
// Prevent autoClear.
this._postProcesses.map(function (pp) { pp.autoClear = false; });
};
/**
* Returns wether or nood the layer needs stencil enabled during the mesh rendering.
*/
HighlightLayer.prototype.needStencil = function () {
return true;
};
/**
* Checks for the readiness of the element composing the layer.
* @param subMesh the mesh to check for
* @param useInstances specify wether or not to use instances to render the mesh
* @param emissiveTexture the associated emissive texture used to generate the glow
* @return true if ready otherwise, false
*/
HighlightLayer.prototype.isReady = function (subMesh, useInstances) {
var material = subMesh.getMaterial();
var mesh = subMesh.getRenderingMesh();
if (!material || !mesh || !this._meshes) {
return false;
}
var emissiveTexture = null;
var highlightLayerMesh = this._meshes[mesh.uniqueId];
if (highlightLayerMesh && highlightLayerMesh.glowEmissiveOnly && material) {
emissiveTexture = material.emissiveTexture;
}
return _super.prototype._isReady.call(this, subMesh, useInstances, emissiveTexture);
};
/**
* Implementation specific of rendering the generating effect on the main canvas.
* @param effect The effect used to render through
*/
HighlightLayer.prototype._internalRender = function (effect) {
// Texture
effect.setTexture("textureSampler", this._blurTexture);
// Cache
var engine = this._engine;
var previousStencilBuffer = engine.getStencilBuffer();
var previousStencilFunction = engine.getStencilFunction();
var previousStencilMask = engine.getStencilMask();
var previousStencilOperationPass = engine.getStencilOperationPass();
var previousStencilOperationFail = engine.getStencilOperationFail();
var previousStencilOperationDepthFail = engine.getStencilOperationDepthFail();
var previousStencilReference = engine.getStencilFunctionReference();
// Stencil operations
engine.setStencilOperationPass(BABYLON.Engine.REPLACE);
engine.setStencilOperationFail(BABYLON.Engine.KEEP);
engine.setStencilOperationDepthFail(BABYLON.Engine.KEEP);
// Draw order
engine.setStencilMask(0x00);
engine.setStencilBuffer(true);
engine.setStencilFunctionReference(this._instanceGlowingMeshStencilReference);
// 2 passes inner outer
if (this.outerGlow) {
effect.setFloat("offset", 0);
engine.setStencilFunction(BABYLON.Engine.NOTEQUAL);
engine.drawElementsType(BABYLON.Material.TriangleFillMode, 0, 6);
}
if (this.innerGlow) {
effect.setFloat("offset", 1);
engine.setStencilFunction(BABYLON.Engine.EQUAL);
engine.drawElementsType(BABYLON.Material.TriangleFillMode, 0, 6);
}
// Restore Cache
engine.setStencilFunction(previousStencilFunction);
engine.setStencilMask(previousStencilMask);
engine.setStencilBuffer(previousStencilBuffer);
engine.setStencilOperationPass(previousStencilOperationPass);
engine.setStencilOperationFail(previousStencilOperationFail);
engine.setStencilOperationDepthFail(previousStencilOperationDepthFail);
engine.setStencilFunctionReference(previousStencilReference);
};
/**
* Returns true if the layer contains information to display, otherwise false.
*/
HighlightLayer.prototype.shouldRender = function () {
if (_super.prototype.shouldRender.call(this)) {
return this._meshes ? true : false;
}
return false;
};
/**
* Returns true if the mesh should render, otherwise false.
* @param mesh The mesh to render
* @returns true if it should render otherwise false
*/
HighlightLayer.prototype._shouldRenderMesh = function (mesh) {
// Excluded Mesh
if (this._excludedMeshes && this._excludedMeshes[mesh.uniqueId]) {
return false;
}
;
return true;
};
/**
* Sets the required values for both the emissive texture and and the main color.
*/
HighlightLayer.prototype._setEmissiveTextureAndColor = function (mesh, subMesh, material) {
var highlightLayerMesh = this._meshes[mesh.uniqueId];
if (highlightLayerMesh) {
this._emissiveTextureAndColor.color.set(highlightLayerMesh.color.r, highlightLayerMesh.color.g, highlightLayerMesh.color.b, 1.0);
}
else {
this._emissiveTextureAndColor.color.set(this.neutralColor.r, this.neutralColor.g, this.neutralColor.b, this.neutralColor.a);
}
if (highlightLayerMesh && highlightLayerMesh.glowEmissiveOnly && material) {
this._emissiveTextureAndColor.texture = material.emissiveTexture;
this._emissiveTextureAndColor.color.set(1.0, 1.0, 1.0, 1.0);
}
else {
this._emissiveTextureAndColor.texture = null;
}
};
/**
* Add a mesh in the exclusion list to prevent it to impact or being impacted by the highlight layer.
* @param mesh The mesh to exclude from the highlight layer
*/
HighlightLayer.prototype.addExcludedMesh = function (mesh) {
if (!this._excludedMeshes) {
return;
}
var meshExcluded = this._excludedMeshes[mesh.uniqueId];
if (!meshExcluded) {
this._excludedMeshes[mesh.uniqueId] = {
mesh: mesh,
beforeRender: mesh.onBeforeRenderObservable.add(function (mesh) {
mesh.getEngine().setStencilBuffer(false);
}),
afterRender: mesh.onAfterRenderObservable.add(function (mesh) {
mesh.getEngine().setStencilBuffer(true);
}),
};
}
};
/**
* Remove a mesh from the exclusion list to let it impact or being impacted by the highlight layer.
* @param mesh The mesh to highlight
*/
HighlightLayer.prototype.removeExcludedMesh = function (mesh) {
if (!this._excludedMeshes) {
return;
}
var meshExcluded = this._excludedMeshes[mesh.uniqueId];
if (meshExcluded) {
if (meshExcluded.beforeRender) {
mesh.onBeforeRenderObservable.remove(meshExcluded.beforeRender);
}
if (meshExcluded.afterRender) {
mesh.onAfterRenderObservable.remove(meshExcluded.afterRender);
}
}
this._excludedMeshes[mesh.uniqueId] = null;
};
/**
* Determine if a given mesh will be highlighted by the current HighlightLayer
* @param mesh mesh to test
* @returns true if the mesh will be highlighted by the current HighlightLayer
*/
HighlightLayer.prototype.hasMesh = function (mesh) {
if (!this._meshes) {
return false;
}
return this._meshes[mesh.uniqueId] !== undefined && this._meshes[mesh.uniqueId] !== null;
};
/**
* Add a mesh in the highlight layer in order to make it glow with the chosen color.
* @param mesh The mesh to highlight
* @param color The color of the highlight
* @param glowEmissiveOnly Extract the glow from the emissive texture
*/
HighlightLayer.prototype.addMesh = function (mesh, color, glowEmissiveOnly) {
var _this = this;
if (glowEmissiveOnly === void 0) { glowEmissiveOnly = false; }
if (!this._meshes) {
return;
}
var meshHighlight = this._meshes[mesh.uniqueId];
if (meshHighlight) {
meshHighlight.color = color;
}
else {
this._meshes[mesh.uniqueId] = {
mesh: mesh,
color: color,
// Lambda required for capture due to Observable this context
observerHighlight: mesh.onBeforeRenderObservable.add(function (mesh) {
if (_this._excludedMeshes && _this._excludedMeshes[mesh.uniqueId]) {
_this._defaultStencilReference(mesh);
}
else {
mesh.getScene().getEngine().setStencilFunctionReference(_this._instanceGlowingMeshStencilReference);
}
}),
observerDefault: mesh.onAfterRenderObservable.add(this._defaultStencilReference),
glowEmissiveOnly: glowEmissiveOnly
};
}
this._shouldRender = true;
};
/**
* Remove a mesh from the highlight layer in order to make it stop glowing.
* @param mesh The mesh to highlight
*/
HighlightLayer.prototype.removeMesh = function (mesh) {
if (!this._meshes) {
return;
}
var meshHighlight = this._meshes[mesh.uniqueId];
if (meshHighlight) {
if (meshHighlight.observerHighlight) {
mesh.onBeforeRenderObservable.remove(meshHighlight.observerHighlight);
}
if (meshHighlight.observerDefault) {
mesh.onAfterRenderObservable.remove(meshHighlight.observerDefault);
}
delete this._meshes[mesh.uniqueId];
}
this._shouldRender = false;
for (var meshHighlightToCheck in this._meshes) {
if (this._meshes[meshHighlightToCheck]) {
this._shouldRender = true;
break;
}
}
};
/**
* Force the stencil to the normal expected value for none glowing parts
*/
HighlightLayer.prototype._defaultStencilReference = function (mesh) {
mesh.getScene().getEngine().setStencilFunctionReference(HighlightLayer.NormalMeshStencilReference);
};
/**
* Free any resources and references associated to a mesh.
* Internal use
* @param mesh The mesh to free.
*/
HighlightLayer.prototype._disposeMesh = function (mesh) {
this.removeMesh(mesh);
this.removeExcludedMesh(mesh);
};
/**
* Dispose the highlight layer and free resources.
*/
HighlightLayer.prototype.dispose = function () {
if (this._meshes) {
// Clean mesh references
for (var id in this._meshes) {
var meshHighlight = this._meshes[id];
if (meshHighlight && meshHighlight.mesh) {
if (meshHighlight.observerHighlight) {
meshHighlight.mesh.onBeforeRenderObservable.remove(meshHighlight.observerHighlight);
}
if (meshHighlight.observerDefault) {
meshHighlight.mesh.onAfterRenderObservable.remove(meshHighlight.observerDefault);
}
}
}
this._meshes = null;
}
if (this._excludedMeshes) {
for (var id in this._excludedMeshes) {
var meshHighlight = this._excludedMeshes[id];
if (meshHighlight) {
if (meshHighlight.beforeRender) {
meshHighlight.mesh.onBeforeRenderObservable.remove(meshHighlight.beforeRender);
}
if (meshHighlight.afterRender) {
meshHighlight.mesh.onAfterRenderObservable.remove(meshHighlight.afterRender);
}
}
}
this._excludedMeshes = null;
}
_super.prototype.dispose.call(this);
};
/**
* Effect Name of the highlight layer.
*/
HighlightLayer.EffectName = "HighlightLayer";
/**
* The neutral color used during the preparation of the glow effect.
* This is black by default as the blend operation is a blend operation.
*/
HighlightLayer.NeutralColor = new BABYLON.Color4(0, 0, 0, 0);
/**
* Stencil value used for glowing meshes.
*/
HighlightLayer.GlowingMeshStencilReference = 0x02;
/**
* Stencil value used for the other meshes in the scene.
*/
HighlightLayer.NormalMeshStencilReference = 0x01;
return HighlightLayer;
}(BABYLON.EffectLayer));
BABYLON.HighlightLayer = HighlightLayer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.highlightLayer.js.map
var BABYLON;
(function (BABYLON) {
/**
* The glow layer Helps adding a glow effect around the emissive parts of a mesh.
*
* Once instantiated in a scene, simply use the pushMesh or removeMesh method to add or remove
* glowy meshes to your scene.
*
* Documentation: https://doc.babylonjs.com/how_to/glow_layer
*/
var GlowLayer = /** @class */ (function (_super) {
__extends(GlowLayer, _super);
/**
* Instantiates a new glow Layer and references it to the scene.
* @param name The name of the layer
* @param scene The scene to use the layer in
* @param options Sets of none mandatory options to use with the layer (see IGlowLayerOptions for more information)
*/
function GlowLayer(name, scene, options) {
var _this = _super.call(this, name, scene) || this;
_this.name = name;
_this._intensity = 1.0;
_this._includedOnlyMeshes = [];
_this._excludedMeshes = [];
_this.neutralColor = new BABYLON.Color4(0, 0, 0, 1);
// Adapt options
_this._options = __assign({ mainTextureRatio: GlowLayer.DefaultTextureRatio, blurKernelSize: 32, mainTextureFixedSize: undefined, camera: null, mainTextureSamples: 1 }, options);
// Initialize the layer
_this._init({
alphaBlendingMode: BABYLON.Engine.ALPHA_ADD,
camera: _this._options.camera,
mainTextureFixedSize: _this._options.mainTextureFixedSize,
mainTextureRatio: _this._options.mainTextureRatio
});
return _this;
}
Object.defineProperty(GlowLayer.prototype, "blurKernelSize", {
/**
* Gets the kernel size of the blur.
*/
get: function () {
return this._horizontalBlurPostprocess1.kernel;
},
/**
* Sets the kernel size of the blur.
*/
set: function (value) {
this._horizontalBlurPostprocess1.kernel = value;
this._verticalBlurPostprocess1.kernel = value;
this._horizontalBlurPostprocess2.kernel = value;
this._verticalBlurPostprocess2.kernel = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GlowLayer.prototype, "intensity", {
/**
* Gets the glow intensity.
*/
get: function () {
return this._intensity;
},
/**
* Sets the glow intensity.
*/
set: function (value) {
this._intensity = value;
},
enumerable: true,
configurable: true
});
/**
* Get the effect name of the layer.
* @return The effect name
*/
GlowLayer.prototype.getEffectName = function () {
return GlowLayer.EffectName;
};
/**
* Create the merge effect. This is the shader use to blit the information back
* to the main canvas at the end of the scene rendering.
*/
GlowLayer.prototype._createMergeEffect = function () {
// Effect
return this._engine.createEffect("glowMapMerge", [BABYLON.VertexBuffer.PositionKind], ["offset"], ["textureSampler", "textureSampler2"], "#define EMISSIVE \n");
};
/**
* Creates the render target textures and post processes used in the glow layer.
*/
GlowLayer.prototype._createTextureAndPostProcesses = function () {
var _this = this;
var blurTextureWidth = this._mainTextureDesiredSize.width;
var blurTextureHeight = this._mainTextureDesiredSize.height;
blurTextureWidth = this._engine.needPOTTextures ? BABYLON.Tools.GetExponentOfTwo(blurTextureWidth, this._maxSize) : blurTextureWidth;
blurTextureHeight = this._engine.needPOTTextures ? BABYLON.Tools.GetExponentOfTwo(blurTextureHeight, this._maxSize) : blurTextureHeight;
this._blurTexture1 = new BABYLON.RenderTargetTexture("GlowLayerBlurRTT", {
width: blurTextureWidth,
height: blurTextureHeight
}, this._scene, false, true, BABYLON.Engine.TEXTURETYPE_HALF_FLOAT);
this._blurTexture1.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
this._blurTexture1.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
this._blurTexture1.updateSamplingMode(BABYLON.Texture.BILINEAR_SAMPLINGMODE);
this._blurTexture1.renderParticles = false;
this._blurTexture1.ignoreCameraViewport = true;
var blurTextureWidth2 = Math.floor(blurTextureWidth / 2);
var blurTextureHeight2 = Math.floor(blurTextureHeight / 2);
this._blurTexture2 = new BABYLON.RenderTargetTexture("GlowLayerBlurRTT2", {
width: blurTextureWidth2,
height: blurTextureHeight2
}, this._scene, false, true, BABYLON.Engine.TEXTURETYPE_HALF_FLOAT);
this._blurTexture2.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
this._blurTexture2.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
this._blurTexture2.updateSamplingMode(BABYLON.Texture.BILINEAR_SAMPLINGMODE);
this._blurTexture2.renderParticles = false;
this._blurTexture2.ignoreCameraViewport = true;
this._textures = [this._blurTexture1, this._blurTexture2];
this._horizontalBlurPostprocess1 = new BABYLON.BlurPostProcess("GlowLayerHBP1", new BABYLON.Vector2(1.0, 0), this._options.blurKernelSize / 2, {
width: blurTextureWidth,
height: blurTextureHeight
}, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, BABYLON.Engine.TEXTURETYPE_HALF_FLOAT);
this._horizontalBlurPostprocess1.width = blurTextureWidth;
this._horizontalBlurPostprocess1.height = blurTextureHeight;
this._horizontalBlurPostprocess1.onApplyObservable.add(function (effect) {
effect.setTexture("textureSampler", _this._mainTexture);
});
this._verticalBlurPostprocess1 = new BABYLON.BlurPostProcess("GlowLayerVBP1", new BABYLON.Vector2(0, 1.0), this._options.blurKernelSize / 2, {
width: blurTextureWidth,
height: blurTextureHeight
}, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, BABYLON.Engine.TEXTURETYPE_HALF_FLOAT);
this._horizontalBlurPostprocess2 = new BABYLON.BlurPostProcess("GlowLayerHBP2", new BABYLON.Vector2(1.0, 0), this._options.blurKernelSize / 2, {
width: blurTextureWidth2,
height: blurTextureHeight2
}, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, BABYLON.Engine.TEXTURETYPE_HALF_FLOAT);
this._horizontalBlurPostprocess2.width = blurTextureWidth2;
this._horizontalBlurPostprocess2.height = blurTextureHeight2;
this._horizontalBlurPostprocess2.onApplyObservable.add(function (effect) {
effect.setTexture("textureSampler", _this._blurTexture1);
});
this._verticalBlurPostprocess2 = new BABYLON.BlurPostProcess("GlowLayerVBP2", new BABYLON.Vector2(0, 1.0), this._options.blurKernelSize / 2, {
width: blurTextureWidth2,
height: blurTextureHeight2
}, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, BABYLON.Engine.TEXTURETYPE_HALF_FLOAT);
this._postProcesses = [this._horizontalBlurPostprocess1, this._verticalBlurPostprocess1, this._horizontalBlurPostprocess2, this._verticalBlurPostprocess2];
this._postProcesses1 = [this._horizontalBlurPostprocess1, this._verticalBlurPostprocess1];
this._postProcesses2 = [this._horizontalBlurPostprocess2, this._verticalBlurPostprocess2];
this._mainTexture.samples = this._options.mainTextureSamples;
this._mainTexture.onAfterUnbindObservable.add(function () {
var internalTexture = _this._blurTexture1.getInternalTexture();
if (internalTexture) {
_this._scene.postProcessManager.directRender(_this._postProcesses1, internalTexture, true);
internalTexture = _this._blurTexture2.getInternalTexture();
if (internalTexture) {
_this._scene.postProcessManager.directRender(_this._postProcesses2, internalTexture, true);
}
}
});
// Prevent autoClear.
this._postProcesses.map(function (pp) { pp.autoClear = false; });
};
/**
* Checks for the readiness of the element composing the layer.
* @param subMesh the mesh to check for
* @param useInstances specify wether or not to use instances to render the mesh
* @param emissiveTexture the associated emissive texture used to generate the glow
* @return true if ready otherwise, false
*/
GlowLayer.prototype.isReady = function (subMesh, useInstances) {
var material = subMesh.getMaterial();
var mesh = subMesh.getRenderingMesh();
if (!material || !mesh) {
return false;
}
var emissiveTexture = material.emissiveTexture;
return _super.prototype._isReady.call(this, subMesh, useInstances, emissiveTexture);
};
/**
* Returns wether or nood the layer needs stencil enabled during the mesh rendering.
*/
GlowLayer.prototype.needStencil = function () {
return false;
};
/**
* Implementation specific of rendering the generating effect on the main canvas.
* @param effect The effect used to render through
*/
GlowLayer.prototype._internalRender = function (effect) {
// Texture
effect.setTexture("textureSampler", this._blurTexture1);
effect.setTexture("textureSampler2", this._blurTexture2);
effect.setFloat("offset", this._intensity);
// Cache
var engine = this._engine;
var previousStencilBuffer = engine.getStencilBuffer();
// Draw order
engine.setStencilBuffer(false);
engine.drawElementsType(BABYLON.Material.TriangleFillMode, 0, 6);
// Draw order
engine.setStencilBuffer(previousStencilBuffer);
};
/**
* Sets the required values for both the emissive texture and and the main color.
*/
GlowLayer.prototype._setEmissiveTextureAndColor = function (mesh, subMesh, material) {
var textureLevel = 1.0;
if (this.customEmissiveTextureSelector) {
this._emissiveTextureAndColor.texture = this.customEmissiveTextureSelector(mesh, subMesh, material);
}
else {
if (material) {
this._emissiveTextureAndColor.texture = material.emissiveTexture;
if (this._emissiveTextureAndColor.texture) {
textureLevel = this._emissiveTextureAndColor.texture.level;
}
}
else {
this._emissiveTextureAndColor.texture = null;
}
}
if (this.customEmissiveColorSelector) {
this.customEmissiveColorSelector(mesh, subMesh, material, this._emissiveTextureAndColor.color);
}
else {
if (material.emissiveColor) {
this._emissiveTextureAndColor.color.set(material.emissiveColor.r * textureLevel, material.emissiveColor.g * textureLevel, material.emissiveColor.b * textureLevel, 1.0);
}
else {
this._emissiveTextureAndColor.color.set(this.neutralColor.r, this.neutralColor.g, this.neutralColor.b, this.neutralColor.a);
}
}
};
/**
* Returns true if the mesh should render, otherwise false.
* @param mesh The mesh to render
* @returns true if it should render otherwise false
*/
GlowLayer.prototype._shouldRenderMesh = function (mesh) {
return this.hasMesh(mesh);
};
/**
* Add a mesh in the exclusion list to prevent it to impact or being impacted by the glow layer.
* @param mesh The mesh to exclude from the glow layer
*/
GlowLayer.prototype.addExcludedMesh = function (mesh) {
if (this._excludedMeshes.indexOf(mesh.uniqueId) === -1) {
this._excludedMeshes.push(mesh.uniqueId);
}
};
/**
* Remove a mesh from the exclusion list to let it impact or being impacted by the glow layer.
* @param mesh The mesh to remove
*/
GlowLayer.prototype.removeExcludedMesh = function (mesh) {
var index = this._excludedMeshes.indexOf(mesh.uniqueId);
if (index !== -1) {
this._excludedMeshes.splice(index, 1);
}
};
/**
* Add a mesh in the inclusion list to impact or being impacted by the glow layer.
* @param mesh The mesh to include in the glow layer
*/
GlowLayer.prototype.addIncludedOnlyMesh = function (mesh) {
if (this._includedOnlyMeshes.indexOf(mesh.uniqueId) === -1) {
this._includedOnlyMeshes.push(mesh.uniqueId);
}
};
/**
* Remove a mesh from the Inclusion list to prevent it to impact or being impacted by the glow layer.
* @param mesh The mesh to remove
*/
GlowLayer.prototype.removeIncludedOnlyMesh = function (mesh) {
var index = this._includedOnlyMeshes.indexOf(mesh.uniqueId);
if (index !== -1) {
this._includedOnlyMeshes.splice(index, 1);
}
};
/**
* Determine if a given mesh will be used in the glow layer
* @param mesh The mesh to test
* @returns true if the mesh will be highlighted by the current glow layer
*/
GlowLayer.prototype.hasMesh = function (mesh) {
// Included Mesh
if (this._includedOnlyMeshes.length) {
return this._includedOnlyMeshes.indexOf(mesh.uniqueId) !== -1;
}
;
// Excluded Mesh
if (this._excludedMeshes.length) {
return this._excludedMeshes.indexOf(mesh.uniqueId) === -1;
}
;
return true;
};
/**
* Free any resources and references associated to a mesh.
* Internal use
* @param mesh The mesh to free.
*/
GlowLayer.prototype._disposeMesh = function (mesh) {
this.removeIncludedOnlyMesh(mesh);
this.removeExcludedMesh(mesh);
};
/**
* Effect Name of the layer.
*/
GlowLayer.EffectName = "GlowLayer";
/**
* The default blur kernel size used for the glow.
*/
GlowLayer.DefaultBlurKernelSize = 32;
/**
* The default texture size ratio used for the glow.
*/
GlowLayer.DefaultTextureRatio = 0.5;
return GlowLayer;
}(BABYLON.EffectLayer));
BABYLON.GlowLayer = GlowLayer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.glowLayer.js.map
var BABYLON;
(function (BABYLON) {
/**
* Defines the list of states available for a task inside a {BABYLON.AssetsManager}
*/
var AssetTaskState;
(function (AssetTaskState) {
/**
* Initialization
*/
AssetTaskState[AssetTaskState["INIT"] = 0] = "INIT";
/**
* Running
*/
AssetTaskState[AssetTaskState["RUNNING"] = 1] = "RUNNING";
/**
* Done
*/
AssetTaskState[AssetTaskState["DONE"] = 2] = "DONE";
/**
* Error
*/
AssetTaskState[AssetTaskState["ERROR"] = 3] = "ERROR";
})(AssetTaskState = BABYLON.AssetTaskState || (BABYLON.AssetTaskState = {}));
/**
* Define an abstract asset task used with a {BABYLON.AssetsManager} class to load assets into a scene
*/
var AbstractAssetTask = /** @class */ (function () {
/**
* Creates a new {BABYLON.AssetsManager}
* @param name defines the name of the task
*/
function AbstractAssetTask(
/**
* Task name
*/ name) {
this.name = name;
this._isCompleted = false;
this._taskState = AssetTaskState.INIT;
}
Object.defineProperty(AbstractAssetTask.prototype, "isCompleted", {
/**
* Get if the task is completed
*/
get: function () {
return this._isCompleted;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractAssetTask.prototype, "taskState", {
/**
* Gets the current state of the task
*/
get: function () {
return this._taskState;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AbstractAssetTask.prototype, "errorObject", {
/**
* Gets the current error object (if task is in error)
*/
get: function () {
return this._errorObject;
},
enumerable: true,
configurable: true
});
/**
* Internal only
* @ignore
*/
AbstractAssetTask.prototype._setErrorObject = function (message, exception) {
if (this._errorObject) {
return;
}
this._errorObject = {
message: message,
exception: exception
};
};
/**
* Execute the current task
* @param scene defines the scene where you want your assets to be loaded
* @param onSuccess is a callback called when the task is successfully executed
* @param onError is a callback called if an error occurs
*/
AbstractAssetTask.prototype.run = function (scene, onSuccess, onError) {
var _this = this;
this._taskState = AssetTaskState.RUNNING;
this.runTask(scene, function () {
_this.onDoneCallback(onSuccess, onError);
}, function (msg, exception) {
_this.onErrorCallback(onError, msg, exception);
});
};
/**
* Execute the current task
* @param scene defines the scene where you want your assets to be loaded
* @param onSuccess is a callback called when the task is successfully executed
* @param onError is a callback called if an error occurs
*/
AbstractAssetTask.prototype.runTask = function (scene, onSuccess, onError) {
throw new Error("runTask is not implemented");
};
AbstractAssetTask.prototype.onErrorCallback = function (onError, message, exception) {
this._taskState = AssetTaskState.ERROR;
this._errorObject = {
message: message,
exception: exception
};
if (this.onError) {
this.onError(this, message, exception);
}
onError();
};
AbstractAssetTask.prototype.onDoneCallback = function (onSuccess, onError) {
try {
this._taskState = AssetTaskState.DONE;
this._isCompleted = true;
if (this.onSuccess) {
this.onSuccess(this);
}
onSuccess();
}
catch (e) {
this.onErrorCallback(onError, "Task is done, error executing success callback(s)", e);
}
};
return AbstractAssetTask;
}());
BABYLON.AbstractAssetTask = AbstractAssetTask;
/**
* Class used to share progress information about assets loading
*/
var AssetsProgressEvent = /** @class */ (function () {
/**
* Creates a {BABYLON.AssetsProgressEvent}
* @param remainingCount defines the number of remaining tasks to process
* @param totalCount defines the total number of tasks
* @param task defines the task that was just processed
*/
function AssetsProgressEvent(remainingCount, totalCount, task) {
this.remainingCount = remainingCount;
this.totalCount = totalCount;
this.task = task;
}
return AssetsProgressEvent;
}());
BABYLON.AssetsProgressEvent = AssetsProgressEvent;
/**
* Define a task used by {BABYLON.AssetsManager} to load meshes
*/
var MeshAssetTask = /** @class */ (function (_super) {
__extends(MeshAssetTask, _super);
/**
* Creates a new {BABYLON.MeshAssetTask}
* @param name defines the name of the task
* @param meshesNames defines the list of mesh's names you want to load
* @param rootUrl defines the root url to use as a base to load your meshes and associated resources
* @param sceneFilename defines the filename of the scene to load from
*/
function MeshAssetTask(
/**
* Defines the name of the task
*/
name,
/**
* Defines the list of mesh's names you want to load
*/
meshesNames,
/**
* Defines the root url to use as a base to load your meshes and associated resources
*/
rootUrl,
/**
* Defines the filename of the scene to load from
*/
sceneFilename) {
var _this = _super.call(this, name) || this;
_this.name = name;
_this.meshesNames = meshesNames;
_this.rootUrl = rootUrl;
_this.sceneFilename = sceneFilename;
return _this;
}
/**
* Execute the current task
* @param scene defines the scene where you want your assets to be loaded
* @param onSuccess is a callback called when the task is successfully executed
* @param onError is a callback called if an error occurs
*/
MeshAssetTask.prototype.runTask = function (scene, onSuccess, onError) {
var _this = this;
BABYLON.SceneLoader.ImportMesh(this.meshesNames, this.rootUrl, this.sceneFilename, scene, function (meshes, particleSystems, skeletons) {
_this.loadedMeshes = meshes;
_this.loadedParticleSystems = particleSystems;
_this.loadedSkeletons = skeletons;
onSuccess();
}, null, function (scene, message, exception) {
onError(message, exception);
});
};
return MeshAssetTask;
}(AbstractAssetTask));
BABYLON.MeshAssetTask = MeshAssetTask;
/**
* Define a task used by {BABYLON.AssetsManager} to load text content
*/
var TextFileAssetTask = /** @class */ (function (_super) {
__extends(TextFileAssetTask, _super);
/**
* Creates a new TextFileAssetTask object
* @param name defines the name of the task
* @param url defines the location of the file to load
*/
function TextFileAssetTask(
/**
* Defines the name of the task
*/
name,
/**
* Defines the location of the file to load
*/
url) {
var _this = _super.call(this, name) || this;
_this.name = name;
_this.url = url;
return _this;
}
/**
* Execute the current task
* @param scene defines the scene where you want your assets to be loaded
* @param onSuccess is a callback called when the task is successfully executed
* @param onError is a callback called if an error occurs
*/
TextFileAssetTask.prototype.runTask = function (scene, onSuccess, onError) {
var _this = this;
scene._loadFile(this.url, function (data) {
_this.text = data;
onSuccess();
}, undefined, false, false, function (request, exception) {
if (request) {
onError(request.status + " " + request.statusText, exception);
}
});
};
return TextFileAssetTask;
}(AbstractAssetTask));
BABYLON.TextFileAssetTask = TextFileAssetTask;
/**
* Define a task used by {BABYLON.AssetsManager} to load binary data
*/
var BinaryFileAssetTask = /** @class */ (function (_super) {
__extends(BinaryFileAssetTask, _super);
/**
* Creates a new BinaryFileAssetTask object
* @param name defines the name of the new task
* @param url defines the location of the file to load
*/
function BinaryFileAssetTask(
/**
* Defines the name of the task
*/
name,
/**
* Defines the location of the file to load
*/
url) {
var _this = _super.call(this, name) || this;
_this.name = name;
_this.url = url;
return _this;
}
/**
* Execute the current task
* @param scene defines the scene where you want your assets to be loaded
* @param onSuccess is a callback called when the task is successfully executed
* @param onError is a callback called if an error occurs
*/
BinaryFileAssetTask.prototype.runTask = function (scene, onSuccess, onError) {
var _this = this;
scene._loadFile(this.url, function (data) {
_this.data = data;
onSuccess();
}, undefined, true, true, function (request, exception) {
if (request) {
onError(request.status + " " + request.statusText, exception);
}
});
};
return BinaryFileAssetTask;
}(AbstractAssetTask));
BABYLON.BinaryFileAssetTask = BinaryFileAssetTask;
/**
* Define a task used by {BABYLON.AssetsManager} to load images
*/
var ImageAssetTask = /** @class */ (function (_super) {
__extends(ImageAssetTask, _super);
/**
* Creates a new ImageAssetTask
* @param name defines the name of the task
* @param url defines the location of the image to load
*/
function ImageAssetTask(
/**
* Defines the name of the task
*/
name,
/**
* Defines the location of the image to load
*/
url) {
var _this = _super.call(this, name) || this;
_this.name = name;
_this.url = url;
return _this;
}
/**
* Execute the current task
* @param scene defines the scene where you want your assets to be loaded
* @param onSuccess is a callback called when the task is successfully executed
* @param onError is a callback called if an error occurs
*/
ImageAssetTask.prototype.runTask = function (scene, onSuccess, onError) {
var _this = this;
var img = new Image();
BABYLON.Tools.SetCorsBehavior(this.url, img);
img.onload = function () {
_this.image = img;
onSuccess();
};
img.onerror = function (err) {
onError("Error loading image", err);
};
img.src = this.url;
};
return ImageAssetTask;
}(AbstractAssetTask));
BABYLON.ImageAssetTask = ImageAssetTask;
/**
* Define a task used by {BABYLON.AssetsManager} to load 2D textures
*/
var TextureAssetTask = /** @class */ (function (_super) {
__extends(TextureAssetTask, _super);
/**
* Creates a new TextureAssetTask object
* @param name defines the name of the task
* @param url defines the location of the file to load
* @param noMipmap defines if mipmap should not be generated (default is false)
* @param invertY defines if texture must be inverted on Y axis (default is false)
* @param samplingMode defines the sampling mode to use (default is BABYLON.Texture.TRILINEAR_SAMPLINGMODE)
*/
function TextureAssetTask(
/**
* Defines the name of the task
*/
name,
/**
* Defines the location of the file to load
*/
url,
/**
* Defines if mipmap should not be generated (default is false)
*/
noMipmap,
/**
* Defines if texture must be inverted on Y axis (default is false)
*/
invertY,
/**
* Defines the sampling mode to use (default is BABYLON.Texture.TRILINEAR_SAMPLINGMODE)
*/
samplingMode) {
if (samplingMode === void 0) { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
var _this = _super.call(this, name) || this;
_this.name = name;
_this.url = url;
_this.noMipmap = noMipmap;
_this.invertY = invertY;
_this.samplingMode = samplingMode;
return _this;
}
/**
* Execute the current task
* @param scene defines the scene where you want your assets to be loaded
* @param onSuccess is a callback called when the task is successfully executed
* @param onError is a callback called if an error occurs
*/
TextureAssetTask.prototype.runTask = function (scene, onSuccess, onError) {
var onload = function () {
onSuccess();
};
var onerror = function (message, exception) {
onError(message, exception);
};
this.texture = new BABYLON.Texture(this.url, scene, this.noMipmap, this.invertY, this.samplingMode, onload, onerror);
};
return TextureAssetTask;
}(AbstractAssetTask));
BABYLON.TextureAssetTask = TextureAssetTask;
/**
* Define a task used by {BABYLON.AssetsManager} to load cube textures
*/
var CubeTextureAssetTask = /** @class */ (function (_super) {
__extends(CubeTextureAssetTask, _super);
/**
* Creates a new CubeTextureAssetTask
* @param name defines the name of the task
* @param url defines the location of the files to load (You have to specify the folder where the files are + filename with no extension)
* @param extensions defines the extensions to use to load files (["_px", "_py", "_pz", "_nx", "_ny", "_nz"] by default)
* @param noMipmap defines if mipmaps should not be generated (default is false)
* @param files defines the explicit list of files (undefined by default)
*/
function CubeTextureAssetTask(
/**
* Defines the name of the task
*/
name,
/**
* Defines the location of the files to load (You have to specify the folder where the files are + filename with no extension)
*/
url,
/**
* Defines the extensions to use to load files (["_px", "_py", "_pz", "_nx", "_ny", "_nz"] by default)
*/
extensions,
/**
* Defines if mipmaps should not be generated (default is false)
*/
noMipmap,
/**
* Defines the explicit list of files (undefined by default)
*/
files) {
var _this = _super.call(this, name) || this;
_this.name = name;
_this.url = url;
_this.extensions = extensions;
_this.noMipmap = noMipmap;
_this.files = files;
return _this;
}
/**
* Execute the current task
* @param scene defines the scene where you want your assets to be loaded
* @param onSuccess is a callback called when the task is successfully executed
* @param onError is a callback called if an error occurs
*/
CubeTextureAssetTask.prototype.runTask = function (scene, onSuccess, onError) {
var onload = function () {
onSuccess();
};
var onerror = function (message, exception) {
onError(message, exception);
};
this.texture = new BABYLON.CubeTexture(this.url, scene, this.extensions, this.noMipmap, this.files, onload, onerror);
};
return CubeTextureAssetTask;
}(AbstractAssetTask));
BABYLON.CubeTextureAssetTask = CubeTextureAssetTask;
/**
* Define a task used by {BABYLON.AssetsManager} to load HDR cube textures
*/
var HDRCubeTextureAssetTask = /** @class */ (function (_super) {
__extends(HDRCubeTextureAssetTask, _super);
/**
* Creates a new HDRCubeTextureAssetTask object
* @param name defines the name of the task
* @param url defines the location of the file to load
* @param size defines the desired size (the more it increases the longer the generation will be) If the size is omitted this implies you are using a preprocessed cubemap.
* @param noMipmap defines if mipmaps should not be generated (default is false)
* @param generateHarmonics specifies whether you want to extract the polynomial harmonics during the generation process (default is true)
* @param useInGammaSpace specifies if the texture will be use in gamma or linear space (the PBR material requires those texture in linear space, but the standard material would require them in Gamma space) (default is false)
* @param usePMREMGenerator specifies whether or not to generate the CubeMap through CubeMapGen to avoid seams issue at run time (default is false)
*/
function HDRCubeTextureAssetTask(
/**
* Defines the name of the task
*/
name,
/**
* Defines the location of the file to load
*/
url,
/**
* Defines the desired size (the more it increases the longer the generation will be) If the size is omitted this implies you are using a preprocessed cubemap.
*/
size,
/**
* Defines if mipmaps should not be generated (default is false)
*/
noMipmap,
/**
* Specifies whether you want to extract the polynomial harmonics during the generation process (default is true)
*/
generateHarmonics,
/**
* Specifies if the texture will be use in gamma or linear space (the PBR material requires those texture in linear space, but the standard material would require them in Gamma space) (default is false)
*/
useInGammaSpace,
/**
* Specifies whether or not to generate the CubeMap through CubeMapGen to avoid seams issue at run time (default is false)
*/
usePMREMGenerator) {
if (noMipmap === void 0) { noMipmap = false; }
if (generateHarmonics === void 0) { generateHarmonics = true; }
if (useInGammaSpace === void 0) { useInGammaSpace = false; }
if (usePMREMGenerator === void 0) { usePMREMGenerator = false; }
var _this = _super.call(this, name) || this;
_this.name = name;
_this.url = url;
_this.size = size;
_this.noMipmap = noMipmap;
_this.generateHarmonics = generateHarmonics;
_this.useInGammaSpace = useInGammaSpace;
_this.usePMREMGenerator = usePMREMGenerator;
return _this;
}
/**
* Execute the current task
* @param scene defines the scene where you want your assets to be loaded
* @param onSuccess is a callback called when the task is successfully executed
* @param onError is a callback called if an error occurs
*/
HDRCubeTextureAssetTask.prototype.run = function (scene, onSuccess, onError) {
var onload = function () {
onSuccess();
};
var onerror = function (message, exception) {
onError(message, exception);
};
this.texture = new BABYLON.HDRCubeTexture(this.url, scene, this.size, this.noMipmap, this.generateHarmonics, this.useInGammaSpace, this.usePMREMGenerator, onload, onerror);
};
return HDRCubeTextureAssetTask;
}(AbstractAssetTask));
BABYLON.HDRCubeTextureAssetTask = HDRCubeTextureAssetTask;
/**
* This class can be used to easily import assets into a scene
* @see http://doc.babylonjs.com/how_to/how_to_use_assetsmanager
*/
var AssetsManager = /** @class */ (function () {
/**
* Creates a new AssetsManager
* @param scene defines the scene to work on
*/
function AssetsManager(scene) {
this._isLoading = false;
this._tasks = new Array();
this._waitingTasksCount = 0;
this._totalTasksCount = 0;
/**
* Observable called when all tasks are processed
*/
this.onTaskSuccessObservable = new BABYLON.Observable();
/**
* Observable called when a task had an error
*/
this.onTaskErrorObservable = new BABYLON.Observable();
/**
* Observable called when a task is successful
*/
this.onTasksDoneObservable = new BABYLON.Observable();
/**
* Observable called when a task is done (whatever the result is)
*/
this.onProgressObservable = new BABYLON.Observable();
/**
* Gets or sets a boolean defining if the {BABYLON.AssetsManager} should use the default loading screen
* @see http://doc.babylonjs.com/how_to/creating_a_custom_loading_screen
*/
this.useDefaultLoadingScreen = true;
this._scene = scene;
}
/**
* Add a {BABYLON.MeshAssetTask} to the list of active tasks
* @param taskName defines the name of the new task
* @param meshesNames defines the name of meshes to load
* @param rootUrl defines the root url to use to locate files
* @param sceneFilename defines the filename of the scene file
* @returns a new {BABYLON.MeshAssetTask} object
*/
AssetsManager.prototype.addMeshTask = function (taskName, meshesNames, rootUrl, sceneFilename) {
var task = new MeshAssetTask(taskName, meshesNames, rootUrl, sceneFilename);
this._tasks.push(task);
return task;
};
/**
* Add a {BABYLON.TextFileAssetTask} to the list of active tasks
* @param taskName defines the name of the new task
* @param url defines the url of the file to load
* @returns a new {BABYLON.TextFileAssetTask} object
*/
AssetsManager.prototype.addTextFileTask = function (taskName, url) {
var task = new TextFileAssetTask(taskName, url);
this._tasks.push(task);
return task;
};
/**
* Add a {BABYLON.BinaryFileAssetTask} to the list of active tasks
* @param taskName defines the name of the new task
* @param url defines the url of the file to load
* @returns a new {BABYLON.BinaryFileAssetTask} object
*/
AssetsManager.prototype.addBinaryFileTask = function (taskName, url) {
var task = new BinaryFileAssetTask(taskName, url);
this._tasks.push(task);
return task;
};
/**
* Add a {BABYLON.ImageAssetTask} to the list of active tasks
* @param taskName defines the name of the new task
* @param url defines the url of the file to load
* @returns a new {BABYLON.ImageAssetTask} object
*/
AssetsManager.prototype.addImageTask = function (taskName, url) {
var task = new ImageAssetTask(taskName, url);
this._tasks.push(task);
return task;
};
/**
* Add a {BABYLON.TextureAssetTask} to the list of active tasks
* @param taskName defines the name of the new task
* @param url defines the url of the file to load
* @param noMipmap defines if the texture must not receive mipmaps (false by default)
* @param invertY defines if you want to invert Y axis of the loaded texture (false by default)
* @param samplingMode defines the sampling mode to use (BABYLON.Texture.TRILINEAR_SAMPLINGMODE by default)
* @returns a new {BABYLON.TextureAssetTask} object
*/
AssetsManager.prototype.addTextureTask = function (taskName, url, noMipmap, invertY, samplingMode) {
if (samplingMode === void 0) { samplingMode = BABYLON.Texture.TRILINEAR_SAMPLINGMODE; }
var task = new TextureAssetTask(taskName, url, noMipmap, invertY, samplingMode);
this._tasks.push(task);
return task;
};
/**
* Add a {BABYLON.CubeTextureAssetTask} to the list of active tasks
* @param taskName defines the name of the new task
* @param url defines the url of the file to load
* @param extensions defines the extension to use to load the cube map (can be null)
* @param noMipmap defines if the texture must not receive mipmaps (false by default)
* @param files defines the list of files to load (can be null)
* @returns a new {BABYLON.CubeTextureAssetTask} object
*/
AssetsManager.prototype.addCubeTextureTask = function (taskName, url, extensions, noMipmap, files) {
var task = new CubeTextureAssetTask(taskName, url, extensions, noMipmap, files);
this._tasks.push(task);
return task;
};
/**
*
* Add a {BABYLON.HDRCubeTextureAssetTask} to the list of active tasks
* @param taskName defines the name of the new task
* @param url defines the url of the file to load
* @param size defines the size you want for the cubemap (can be null)
* @param noMipmap defines if the texture must not receive mipmaps (false by default)
* @param generateHarmonics defines if you want to automatically generate (true by default)
* @param useInGammaSpace defines if the texture must be considered in gamma space (false by default)
* @param usePMREMGenerator is a reserved parameter and must be set to false or ignored
* @returns a new {BABYLON.HDRCubeTextureAssetTask} object
*/
AssetsManager.prototype.addHDRCubeTextureTask = function (taskName, url, size, noMipmap, generateHarmonics, useInGammaSpace, usePMREMGenerator) {
if (noMipmap === void 0) { noMipmap = false; }
if (generateHarmonics === void 0) { generateHarmonics = true; }
if (useInGammaSpace === void 0) { useInGammaSpace = false; }
if (usePMREMGenerator === void 0) { usePMREMGenerator = false; }
var task = new HDRCubeTextureAssetTask(taskName, url, size, noMipmap, generateHarmonics, useInGammaSpace, usePMREMGenerator);
this._tasks.push(task);
return task;
};
AssetsManager.prototype._decreaseWaitingTasksCount = function (task) {
var _this = this;
this._waitingTasksCount--;
try {
if (task.taskState === AssetTaskState.DONE) {
// Let's remove successfull tasks
BABYLON.Tools.SetImmediate(function () {
var index = _this._tasks.indexOf(task);
if (index > -1) {
_this._tasks.splice(index, 1);
}
});
}
if (this.onProgress) {
this.onProgress(this._waitingTasksCount, this._totalTasksCount, task);
}
this.onProgressObservable.notifyObservers(new AssetsProgressEvent(this._waitingTasksCount, this._totalTasksCount, task));
}
catch (e) {
BABYLON.Tools.Error("Error running progress callbacks.");
console.log(e);
}
if (this._waitingTasksCount === 0) {
try {
if (this.onFinish) {
this.onFinish(this._tasks);
}
this.onTasksDoneObservable.notifyObservers(this._tasks);
}
catch (e) {
BABYLON.Tools.Error("Error running tasks-done callbacks.");
console.log(e);
}
this._isLoading = false;
this._scene.getEngine().hideLoadingUI();
}
};
AssetsManager.prototype._runTask = function (task) {
var _this = this;
var done = function () {
try {
if (_this.onTaskSuccess) {
_this.onTaskSuccess(task);
}
_this.onTaskSuccessObservable.notifyObservers(task);
_this._decreaseWaitingTasksCount(task);
}
catch (e) {
error("Error executing task success callbacks", e);
}
};
var error = function (message, exception) {
task._setErrorObject(message, exception);
if (_this.onTaskError) {
_this.onTaskError(task);
}
_this.onTaskErrorObservable.notifyObservers(task);
_this._decreaseWaitingTasksCount(task);
};
task.run(this._scene, done, error);
};
/**
* Reset the {BABYLON.AssetsManager} and remove all tasks
* @return the current instance of the {BABYLON.AssetsManager}
*/
AssetsManager.prototype.reset = function () {
this._isLoading = false;
this._tasks = new Array();
return this;
};
/**
* Start the loading process
* @return the current instance of the {BABYLON.AssetsManager}
*/
AssetsManager.prototype.load = function () {
if (this._isLoading) {
return this;
}
this._isLoading = true;
this._waitingTasksCount = this._tasks.length;
this._totalTasksCount = this._tasks.length;
if (this._waitingTasksCount === 0) {
this._isLoading = false;
if (this.onFinish) {
this.onFinish(this._tasks);
}
this.onTasksDoneObservable.notifyObservers(this._tasks);
return this;
}
if (this.useDefaultLoadingScreen) {
this._scene.getEngine().displayLoadingUI();
}
for (var index = 0; index < this._tasks.length; index++) {
var task = this._tasks[index];
this._runTask(task);
}
return this;
};
return AssetsManager;
}());
BABYLON.AssetsManager = AssetsManager;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.assetsManager.js.map
var BABYLON;
(function (BABYLON) {
var serializedGeometries = [];
var serializeGeometry = function (geometry, serializationGeometries) {
if (serializedGeometries[geometry.id]) {
return;
}
if (geometry.doNotSerialize) {
return;
}
if (geometry instanceof BABYLON.BoxGeometry) {
serializationGeometries.boxes.push(geometry.serialize());
}
else if (geometry instanceof BABYLON.SphereGeometry) {
serializationGeometries.spheres.push(geometry.serialize());
}
else if (geometry instanceof BABYLON.CylinderGeometry) {
serializationGeometries.cylinders.push(geometry.serialize());
}
else if (geometry instanceof BABYLON.TorusGeometry) {
serializationGeometries.toruses.push(geometry.serialize());
}
else if (geometry instanceof BABYLON.GroundGeometry) {
serializationGeometries.grounds.push(geometry.serialize());
}
else if (geometry instanceof BABYLON.Plane) {
serializationGeometries.planes.push(geometry.serialize());
}
else if (geometry instanceof BABYLON.TorusKnotGeometry) {
serializationGeometries.torusKnots.push(geometry.serialize());
}
else if (geometry instanceof BABYLON._PrimitiveGeometry) {
throw new Error("Unknown primitive type");
}
else {
serializationGeometries.vertexData.push(geometry.serializeVerticeData());
}
serializedGeometries[geometry.id] = true;
};
var serializeMesh = function (mesh, serializationScene) {
var serializationObject = {};
// Geometry
var geometry = mesh._geometry;
if (geometry) {
if (!mesh.getScene().getGeometryByID(geometry.id)) {
// Geometry was in the memory but not added to the scene, nevertheless it's better to serialize to be able to reload the mesh with its geometry
serializeGeometry(geometry, serializationScene.geometries);
}
}
// Custom
if (mesh.serialize) {
mesh.serialize(serializationObject);
}
return serializationObject;
};
var finalizeSingleMesh = function (mesh, serializationObject) {
//only works if the mesh is already loaded
if (mesh.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_LOADED || mesh.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_NONE) {
//serialize material
if (mesh.material) {
if (mesh.material instanceof BABYLON.StandardMaterial) {
serializationObject.materials = serializationObject.materials || [];
if (!serializationObject.materials.some(function (mat) { return (mat.id === mesh.material.id); })) {
serializationObject.materials.push(mesh.material.serialize());
}
}
else if (mesh.material instanceof BABYLON.MultiMaterial) {
serializationObject.multiMaterials = serializationObject.multiMaterials || [];
if (!serializationObject.multiMaterials.some(function (mat) { return (mat.id === mesh.material.id); })) {
serializationObject.multiMaterials.push(mesh.material.serialize());
}
}
}
//serialize geometry
var geometry = mesh._geometry;
if (geometry) {
if (!serializationObject.geometries) {
serializationObject.geometries = {};
serializationObject.geometries.boxes = [];
serializationObject.geometries.spheres = [];
serializationObject.geometries.cylinders = [];
serializationObject.geometries.toruses = [];
serializationObject.geometries.grounds = [];
serializationObject.geometries.planes = [];
serializationObject.geometries.torusKnots = [];
serializationObject.geometries.vertexData = [];
}
serializeGeometry(geometry, serializationObject.geometries);
}
// Skeletons
if (mesh.skeleton) {
serializationObject.skeletons = serializationObject.skeletons || [];
serializationObject.skeletons.push(mesh.skeleton.serialize());
}
//serialize the actual mesh
serializationObject.meshes = serializationObject.meshes || [];
serializationObject.meshes.push(serializeMesh(mesh, serializationObject));
}
};
var SceneSerializer = /** @class */ (function () {
function SceneSerializer() {
}
SceneSerializer.ClearCache = function () {
serializedGeometries = [];
};
SceneSerializer.Serialize = function (scene) {
var serializationObject = {};
SceneSerializer.ClearCache();
// Scene
serializationObject.useDelayedTextureLoading = scene.useDelayedTextureLoading;
serializationObject.autoClear = scene.autoClear;
serializationObject.clearColor = scene.clearColor.asArray();
serializationObject.ambientColor = scene.ambientColor.asArray();
serializationObject.gravity = scene.gravity.asArray();
serializationObject.collisionsEnabled = scene.collisionsEnabled;
serializationObject.workerCollisions = scene.workerCollisions;
// Fog
if (scene.fogMode && scene.fogMode !== 0) {
serializationObject.fogMode = scene.fogMode;
serializationObject.fogColor = scene.fogColor.asArray();
serializationObject.fogStart = scene.fogStart;
serializationObject.fogEnd = scene.fogEnd;
serializationObject.fogDensity = scene.fogDensity;
}
//Physics
if (scene.isPhysicsEnabled()) {
var physicEngine = scene.getPhysicsEngine();
if (physicEngine) {
serializationObject.physicsEnabled = true;
serializationObject.physicsGravity = physicEngine.gravity.asArray();
serializationObject.physicsEngine = physicEngine.getPhysicsPluginName();
}
}
// Metadata
if (scene.metadata) {
serializationObject.metadata = scene.metadata;
}
// Morph targets
serializationObject.morphTargetManagers = [];
for (var _i = 0, _a = scene.meshes; _i < _a.length; _i++) {
var abstractMesh = _a[_i];
var manager = abstractMesh.morphTargetManager;
if (manager) {
serializationObject.morphTargetManagers.push(manager.serialize());
}
}
// Lights
serializationObject.lights = [];
var index;
var light;
for (index = 0; index < scene.lights.length; index++) {
light = scene.lights[index];
if (!light.doNotSerialize) {
serializationObject.lights.push(light.serialize());
}
}
// Cameras
serializationObject.cameras = [];
for (index = 0; index < scene.cameras.length; index++) {
var camera = scene.cameras[index];
if (!camera.doNotSerialize) {
serializationObject.cameras.push(camera.serialize());
}
}
if (scene.activeCamera) {
serializationObject.activeCameraID = scene.activeCamera.id;
}
// Animations
BABYLON.Animation.AppendSerializedAnimations(scene, serializationObject);
// Materials
serializationObject.materials = [];
serializationObject.multiMaterials = [];
var material;
for (index = 0; index < scene.materials.length; index++) {
material = scene.materials[index];
if (!material.doNotSerialize) {
serializationObject.materials.push(material.serialize());
}
}
// MultiMaterials
serializationObject.multiMaterials = [];
for (index = 0; index < scene.multiMaterials.length; index++) {
var multiMaterial = scene.multiMaterials[index];
serializationObject.multiMaterials.push(multiMaterial.serialize());
}
// Environment texture
if (scene.environmentTexture) {
serializationObject.environmentTexture = scene.environmentTexture.name;
}
// Skeletons
serializationObject.skeletons = [];
for (index = 0; index < scene.skeletons.length; index++) {
var skeleton = scene.skeletons[index];
if (!skeleton.doNotSerialize) {
serializationObject.skeletons.push(skeleton.serialize());
}
}
// Transform nodes
serializationObject.transformNodes = [];
for (index = 0; index < scene.transformNodes.length; index++) {
serializationObject.transformNodes.push(scene.transformNodes[index].serialize());
}
// Geometries
serializationObject.geometries = {};
serializationObject.geometries.boxes = [];
serializationObject.geometries.spheres = [];
serializationObject.geometries.cylinders = [];
serializationObject.geometries.toruses = [];
serializationObject.geometries.grounds = [];
serializationObject.geometries.planes = [];
serializationObject.geometries.torusKnots = [];
serializationObject.geometries.vertexData = [];
serializedGeometries = [];
var geometries = scene.getGeometries();
for (index = 0; index < geometries.length; index++) {
var geometry = geometries[index];
if (geometry.isReady()) {
serializeGeometry(geometry, serializationObject.geometries);
}
}
// Meshes
serializationObject.meshes = [];
for (index = 0; index < scene.meshes.length; index++) {
var abstractMesh = scene.meshes[index];
if (abstractMesh instanceof BABYLON.Mesh) {
var mesh = abstractMesh;
if (!mesh.doNotSerialize) {
if (mesh.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_LOADED || mesh.delayLoadState === BABYLON.Engine.DELAYLOADSTATE_NONE) {
serializationObject.meshes.push(serializeMesh(mesh, serializationObject));
}
}
}
}
// Particles Systems
serializationObject.particleSystems = [];
for (index = 0; index < scene.particleSystems.length; index++) {
serializationObject.particleSystems.push(scene.particleSystems[index].serialize());
}
// Lens flares
serializationObject.lensFlareSystems = [];
for (index = 0; index < scene.lensFlareSystems.length; index++) {
serializationObject.lensFlareSystems.push(scene.lensFlareSystems[index].serialize());
}
// Shadows
serializationObject.shadowGenerators = [];
for (index = 0; index < scene.lights.length; index++) {
light = scene.lights[index];
var shadowGenerator = light.getShadowGenerator();
if (shadowGenerator) {
serializationObject.shadowGenerators.push(shadowGenerator.serialize());
}
}
// Action Manager
if (scene.actionManager) {
serializationObject.actions = scene.actionManager.serialize("scene");
}
// Audio
serializationObject.sounds = [];
for (index = 0; index < scene.soundTracks.length; index++) {
var soundtrack = scene.soundTracks[index];
for (var soundId = 0; soundId < soundtrack.soundCollection.length; soundId++) {
serializationObject.sounds.push(soundtrack.soundCollection[soundId].serialize());
}
}
return serializationObject;
};
SceneSerializer.SerializeMesh = function (toSerialize /* Mesh || Mesh[] */, withParents, withChildren) {
if (withParents === void 0) { withParents = false; }
if (withChildren === void 0) { withChildren = false; }
var serializationObject = {};
SceneSerializer.ClearCache();
toSerialize = (toSerialize instanceof Array) ? toSerialize : [toSerialize];
if (withParents || withChildren) {
//deliberate for loop! not for each, appended should be processed as well.
for (var i = 0; i < toSerialize.length; ++i) {
if (withChildren) {
toSerialize[i].getDescendants().forEach(function (node) {
if (node instanceof BABYLON.Mesh && (toSerialize.indexOf(node) < 0)) {
toSerialize.push(node);
}
});
}
//make sure the array doesn't contain the object already
if (withParents && toSerialize[i].parent && (toSerialize.indexOf(toSerialize[i].parent) < 0)) {
toSerialize.push(toSerialize[i].parent);
}
}
}
toSerialize.forEach(function (mesh) {
finalizeSingleMesh(mesh, serializationObject);
});
return serializationObject;
};
return SceneSerializer;
}());
BABYLON.SceneSerializer = SceneSerializer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.sceneSerializer.js.map
var BABYLON;
(function (BABYLON) {
var ReflectionProbe = /** @class */ (function () {
function ReflectionProbe(name, size, scene, generateMipMaps) {
if (generateMipMaps === void 0) { generateMipMaps = true; }
var _this = this;
this.name = name;
this._viewMatrix = BABYLON.Matrix.Identity();
this._target = BABYLON.Vector3.Zero();
this._add = BABYLON.Vector3.Zero();
this._invertYAxis = false;
this.position = BABYLON.Vector3.Zero();
this._scene = scene;
this._scene.reflectionProbes.push(this);
this._renderTargetTexture = new BABYLON.RenderTargetTexture(name, size, scene, generateMipMaps, true, BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT, true);
this._renderTargetTexture.onBeforeRenderObservable.add(function (faceIndex) {
switch (faceIndex) {
case 0:
_this._add.copyFromFloats(1, 0, 0);
break;
case 1:
_this._add.copyFromFloats(-1, 0, 0);
break;
case 2:
_this._add.copyFromFloats(0, _this._invertYAxis ? 1 : -1, 0);
break;
case 3:
_this._add.copyFromFloats(0, _this._invertYAxis ? -1 : 1, 0);
break;
case 4:
_this._add.copyFromFloats(0, 0, 1);
break;
case 5:
_this._add.copyFromFloats(0, 0, -1);
break;
}
if (_this._attachedMesh) {
_this.position.copyFrom(_this._attachedMesh.getAbsolutePosition());
}
_this.position.addToRef(_this._add, _this._target);
BABYLON.Matrix.LookAtLHToRef(_this.position, _this._target, BABYLON.Vector3.Up(), _this._viewMatrix);
scene.setTransformMatrix(_this._viewMatrix, _this._projectionMatrix);
scene._forcedViewPosition = _this.position;
});
this._renderTargetTexture.onAfterUnbindObservable.add(function () {
scene._forcedViewPosition = null;
scene.updateTransformMatrix(true);
});
if (scene.activeCamera) {
this._projectionMatrix = BABYLON.Matrix.PerspectiveFovLH(Math.PI / 2, 1, scene.activeCamera.minZ, scene.activeCamera.maxZ);
}
}
Object.defineProperty(ReflectionProbe.prototype, "samples", {
get: function () {
return this._renderTargetTexture.samples;
},
set: function (value) {
this._renderTargetTexture.samples = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ReflectionProbe.prototype, "refreshRate", {
get: function () {
return this._renderTargetTexture.refreshRate;
},
set: function (value) {
this._renderTargetTexture.refreshRate = value;
},
enumerable: true,
configurable: true
});
ReflectionProbe.prototype.getScene = function () {
return this._scene;
};
Object.defineProperty(ReflectionProbe.prototype, "cubeTexture", {
get: function () {
return this._renderTargetTexture;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ReflectionProbe.prototype, "renderList", {
get: function () {
return this._renderTargetTexture.renderList;
},
enumerable: true,
configurable: true
});
ReflectionProbe.prototype.attachToMesh = function (mesh) {
this._attachedMesh = mesh;
};
/**
* Specifies whether or not the stencil and depth buffer are cleared between two rendering groups.
*
* @param renderingGroupId The rendering group id corresponding to its index
* @param autoClearDepthStencil Automatically clears depth and stencil between groups if true.
*/
ReflectionProbe.prototype.setRenderingAutoClearDepthStencil = function (renderingGroupId, autoClearDepthStencil) {
this._renderTargetTexture.setRenderingAutoClearDepthStencil(renderingGroupId, autoClearDepthStencil);
};
ReflectionProbe.prototype.dispose = function () {
var index = this._scene.reflectionProbes.indexOf(this);
if (index !== -1) {
// Remove from the scene if found
this._scene.reflectionProbes.splice(index, 1);
}
if (this._renderTargetTexture) {
this._renderTargetTexture.dispose();
this._renderTargetTexture = null;
}
};
return ReflectionProbe;
}());
BABYLON.ReflectionProbe = ReflectionProbe;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.reflectionProbe.js.map
var BABYLON;
(function (BABYLON) {
var Layer = /** @class */ (function () {
function Layer(name, imgUrl, scene, isBackground, color) {
this.name = name;
this.scale = new BABYLON.Vector2(1, 1);
this.offset = new BABYLON.Vector2(0, 0);
this.alphaBlendingMode = BABYLON.Engine.ALPHA_COMBINE;
this.layerMask = 0x0FFFFFFF;
this._vertexBuffers = {};
// Events
/**
* An event triggered when the layer is disposed.
* @type {BABYLON.Observable}
*/
this.onDisposeObservable = new BABYLON.Observable();
/**
* An event triggered before rendering the scene
* @type {BABYLON.Observable}
*/
this.onBeforeRenderObservable = new BABYLON.Observable();
/**
* An event triggered after rendering the scene
* @type {BABYLON.Observable}
*/
this.onAfterRenderObservable = new BABYLON.Observable();
this.texture = imgUrl ? new BABYLON.Texture(imgUrl, scene, true) : null;
this.isBackground = isBackground === undefined ? true : isBackground;
this.color = color === undefined ? new BABYLON.Color4(1, 1, 1, 1) : color;
this._scene = (scene || BABYLON.Engine.LastCreatedScene);
this._scene.layers.push(this);
var engine = this._scene.getEngine();
// VBO
var vertices = [];
vertices.push(1, 1);
vertices.push(-1, 1);
vertices.push(-1, -1);
vertices.push(1, -1);
var vertexBuffer = new BABYLON.VertexBuffer(engine, vertices, BABYLON.VertexBuffer.PositionKind, false, false, 2);
this._vertexBuffers[BABYLON.VertexBuffer.PositionKind] = vertexBuffer;
this._createIndexBuffer();
// Effects
this._effect = engine.createEffect("layer", [BABYLON.VertexBuffer.PositionKind], ["textureMatrix", "color", "scale", "offset"], ["textureSampler"], "");
this._alphaTestEffect = engine.createEffect("layer", [BABYLON.VertexBuffer.PositionKind], ["textureMatrix", "color", "scale", "offset"], ["textureSampler"], "#define ALPHATEST");
}
Object.defineProperty(Layer.prototype, "onDispose", {
set: function (callback) {
if (this._onDisposeObserver) {
this.onDisposeObservable.remove(this._onDisposeObserver);
}
this._onDisposeObserver = this.onDisposeObservable.add(callback);
},
enumerable: true,
configurable: true
});
Object.defineProperty(Layer.prototype, "onBeforeRender", {
set: function (callback) {
if (this._onBeforeRenderObserver) {
this.onBeforeRenderObservable.remove(this._onBeforeRenderObserver);
}
this._onBeforeRenderObserver = this.onBeforeRenderObservable.add(callback);
},
enumerable: true,
configurable: true
});
Object.defineProperty(Layer.prototype, "onAfterRender", {
set: function (callback) {
if (this._onAfterRenderObserver) {
this.onAfterRenderObservable.remove(this._onAfterRenderObserver);
}
this._onAfterRenderObserver = this.onAfterRenderObservable.add(callback);
},
enumerable: true,
configurable: true
});
Layer.prototype._createIndexBuffer = function () {
var engine = this._scene.getEngine();
// Indices
var indices = [];
indices.push(0);
indices.push(1);
indices.push(2);
indices.push(0);
indices.push(2);
indices.push(3);
this._indexBuffer = engine.createIndexBuffer(indices);
};
Layer.prototype._rebuild = function () {
var vb = this._vertexBuffers[BABYLON.VertexBuffer.PositionKind];
if (vb) {
vb._rebuild();
}
this._createIndexBuffer();
};
Layer.prototype.render = function () {
var currentEffect = this.alphaTest ? this._alphaTestEffect : this._effect;
// Check
if (!currentEffect.isReady() || !this.texture || !this.texture.isReady())
return;
var engine = this._scene.getEngine();
this.onBeforeRenderObservable.notifyObservers(this);
// Render
engine.enableEffect(currentEffect);
engine.setState(false);
// Texture
currentEffect.setTexture("textureSampler", this.texture);
currentEffect.setMatrix("textureMatrix", this.texture.getTextureMatrix());
// Color
currentEffect.setFloat4("color", this.color.r, this.color.g, this.color.b, this.color.a);
// Scale / offset
currentEffect.setVector2("offset", this.offset);
currentEffect.setVector2("scale", this.scale);
// VBOs
engine.bindBuffers(this._vertexBuffers, this._indexBuffer, currentEffect);
// Draw order
if (!this.alphaTest) {
engine.setAlphaMode(this.alphaBlendingMode);
engine.drawElementsType(BABYLON.Material.TriangleFillMode, 0, 6);
engine.setAlphaMode(BABYLON.Engine.ALPHA_DISABLE);
}
else {
engine.drawElementsType(BABYLON.Material.TriangleFillMode, 0, 6);
}
this.onAfterRenderObservable.notifyObservers(this);
};
Layer.prototype.dispose = function () {
var vertexBuffer = this._vertexBuffers[BABYLON.VertexBuffer.PositionKind];
if (vertexBuffer) {
vertexBuffer.dispose();
this._vertexBuffers[BABYLON.VertexBuffer.PositionKind] = null;
}
if (this._indexBuffer) {
this._scene.getEngine()._releaseBuffer(this._indexBuffer);
this._indexBuffer = null;
}
if (this.texture) {
this.texture.dispose();
this.texture = null;
}
// Remove from scene
var index = this._scene.layers.indexOf(this);
this._scene.layers.splice(index, 1);
// Callback
this.onDisposeObservable.notifyObservers(this);
this.onDisposeObservable.clear();
this.onAfterRenderObservable.clear();
this.onBeforeRenderObservable.clear();
};
return Layer;
}());
BABYLON.Layer = Layer;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.layer.js.map
var BABYLON;
(function (BABYLON) {
var TextureTools = /** @class */ (function () {
function TextureTools() {
}
/**
* Uses the GPU to create a copy texture rescaled at a given size
* @param texture Texture to copy from
* @param width Desired width
* @param height Desired height
* @return Generated texture
*/
TextureTools.CreateResizedCopy = function (texture, width, height, useBilinearMode) {
if (useBilinearMode === void 0) { useBilinearMode = true; }
var scene = texture.getScene();
var engine = scene.getEngine();
var rtt = new BABYLON.RenderTargetTexture('resized' + texture.name, { width: width, height: height }, scene, !texture.noMipmap, true, texture._texture.type, false, texture._samplingMode, false);
rtt.wrapU = texture.wrapU;
rtt.wrapV = texture.wrapV;
rtt.uOffset = texture.uOffset;
rtt.vOffset = texture.vOffset;
rtt.uScale = texture.uScale;
rtt.vScale = texture.vScale;
rtt.uAng = texture.uAng;
rtt.vAng = texture.vAng;
rtt.wAng = texture.wAng;
rtt.coordinatesIndex = texture.coordinatesIndex;
rtt.level = texture.level;
rtt.anisotropicFilteringLevel = texture.anisotropicFilteringLevel;
rtt._texture.isReady = false;
texture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
texture.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
var passPostProcess = new BABYLON.PassPostProcess("pass", 1, null, useBilinearMode ? BABYLON.Texture.BILINEAR_SAMPLINGMODE : BABYLON.Texture.NEAREST_SAMPLINGMODE, engine, false, BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT);
passPostProcess.getEffect().executeWhenCompiled(function () {
passPostProcess.onApply = function (effect) {
effect.setTexture("textureSampler", texture);
};
var internalTexture = rtt.getInternalTexture();
if (internalTexture) {
scene.postProcessManager.directRender([passPostProcess], internalTexture);
engine.unBindFramebuffer(internalTexture);
rtt.disposeFramebufferObjects();
passPostProcess.dispose();
internalTexture.isReady = true;
}
});
return rtt;
};
TextureTools.GetEnvironmentBRDFTexture = function (scene) {
if (!scene._environmentBRDFTexture) {
var texture = BABYLON.Texture.CreateFromBase64String(this._environmentBRDFBase64Texture, "EnvironmentBRDFTexture", scene, true, false, BABYLON.Texture.BILINEAR_SAMPLINGMODE);
texture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
texture.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
scene._environmentBRDFTexture = texture;
}
return scene._environmentBRDFTexture;
};
TextureTools._environmentBRDFBase64Texture = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAgAElEQVR4Xu19Z7PtTHbW1g3jMMbGmGDAZAMm5xxMLDAU0WSKWOQcCoqccw6eGdtgk4yNbZxnvvAL+Af8Af6AsQl+06ako9X36dXPSi3pnPu+cz/cOntL3S1pq5+w1mrpLs/eud9fvn27rf9evPPwFz+v22S7fGZ/n7/70G79J5/Xv/qzbLP+Pnvvoc/6Tz7jX/15/c62LfeH7fofbpfP3l/ct36Wf+u4+D37+XYb++G26LPsr/zFttnPuh37bm1bt0f7MvtlnOx4uv0H4fty8UUsz77rfn/57u32cgXvDv72eQf0tl0+G38b0Nf9K4Dl704MEfA16KsE8Gw9JgD+DQE8EA0DT2b7GwK4GHnF4a8iguXZt9/vL5/dbisJbEq/uwD5vIK/fbbAv4N9U/8nJIDNCazKvBLBGwdwu62OhajxmQSAx6gqNp5HCg9wPan2nwSNjhLD8ux/3u8vP3y7vbwDAYjtR8AzFyDqLu1Q+YEINnew23rPCYiKb+q/K7o4AVT4tg0t/h4ydJZfkQASQ/d5b9fZ/Z1ENmuPn/cwYCYEELBguKC3nRkCnE0AFOwOKCOAR/sH/L4hgFMpbSWP5dn/uN9ffs7t9mJ5cAHoBLTyszBAFJ/F/xIKdASw5wgaEWDMLySxAk4svf6L+4QAGPiJCziNAPb4f3UZ2dh/m+z7BK4SAPYrxf5FB6ABPgCUAfANAZwKyscc7IEA/vv9/uLzbreXzx9cQCMACAl00m8jAlF7ov6SCMQ8gJsMFFBnCECSg5H6TxJAU3vPAbwhgFfz9AABeOEDBcIbB3AqPzwQwH+731/8sNvt5Ydut5e3B2C/fG9P+jESgGz/RgxG9r9VAwTUUh0goQDafUz+DYnAnSha5l99Z1l/yQVswAZSGIAugNd/9xBgCw9E8aECkHUB22QPHIAVDlQdQAMWAibhBgZAasAVHUAI8Cqg96Tm0bj3VBS9jwd7IIBvuN9ffMHt9vLTbreXy+32QlwAhgMIeuNzKwOqCoB2Aa00KHE+EsIeDuj4H2N+Hf/TfAC6A4nhgQCQDDwiaKDXiq9KgBEJNPArAtCk0AEd2mpAizW3/lYIoANpBPg3BPA+hjs/9eXZV+0E8Bm32wsJA9aEoBCAuAABPiEAC/yDC4gSgRgKRHkAlgsI6v7iEFqJEMgBwb4BGkEfEEDnDlReoAP/SQRgOYIB+IYDMEE/SQBbXoLNr0jhq4qOZc0PHBSf5oKW519xvz//kbfby8+83V68ABfwniIBgwgQ/HoRUMv8w5qAoQqgk4DWQiCw+63eD8k/XAPQgK5s/5a5xzAAqgR6wY9k+ZEMtCOoJABb230hEHMFWQdgAl0Ap/+uc6tKBrrP/n0AuwfiNwTwNKguHHV5/qX3+/M1B/Ddb7cXax7g2e324vaQB3hhkMAW92tHoFb96cVAbimwkgQ0Vv7R+D8iACfuxzKfLvnNlAAjAsBwwP2MwLQAD9sbYJME0AFcg5uBPSAA0x0AobhtcDKDA0j3KYDhk7Hp8uKj9/vzH3C7vfget9uLT9nDgDUZuOYCLBJA8MNKPyGGIftPrL+4gy3eh5p/lwRUYYAs9Fn7tM/E9lvJwCH2DxJ/mPTr4nyyLiDtBgTAGCrgNuPzNuETgN+suEEAFhng9lkCoICMLH7V0isCeEMCxylrefkl9/uzz90J4NNUGLDmAnYXINUBrf5dCCAuQCcCvYVAYPk3G++VAveVfkIAFRLolgbr2F9ifP33pAqAV/fHRF4HcAS7AKlAAEIYFNwITOszs/wMsB6II4BXFZ0QwBsSOEYCDwTw2TsBfPrt9uLlqzCgcwFABI0EVCiANl8Uvq0JWNsi2JPZ/0YKsOiHxftsW4v51ZqAaBWgZf91PsBL/jFHwEqBR1cCiuJ3gAfCmCEA3cf8rmz8AMZHIoA3JDBPAsuHVgL4jNvt+UoCH34ggK0asIYBGArsAB7AD+reQgCl+GwZ8LaNlP3MEEDaSg4ACMGr/+ulwV4JsAEfLH42/vdKgWElAJ4QpBl+LAlKErHwt+oGMgTA2ngE4IUIOH3dGr/hAKT/m/UBdSJYPuVL7vflU26352sScCWAD+0EsCcDVxewKjfmAzAsENVn4EfgdySgnYB81yEAgL4RA8T8mTUASAAYBgylQAkL8K/+zL6rsl8qF6ArAeS7WRGoAB8Sf7isN/VZqTs6jQ5wXlweWfyqpQ8I4I0TmCCAT/3I/b48u92ef9bt9nwNAdZE4FoOFALYXcAGegkDMByAzzQEgJh+cAIs/legH0IA5QTCPADE+7ISkD0TgA/8sBIgLQfOgF/F9kPcr+J8fIYguyCILQRKgV4DNviOzoKqeJS0u4AA3pBAjQSWT//I/b5OmC0MWB3ASgBrGLA+IryvDNxCgRXo+wKhjgwk8bcTwUACsJ09ANRVAALwCxmEoFcrAUsuAJ4M1E8BDuHABAHomJ8RgACrZfQLyT9dBWi2OOEG9NJd/TDQ8HAQuBE97ZhjGKy6o+imnU+4gDckkCeB5cMfud/v6zr9Dz84gOdCAM/3JwQhF9CAD25gBWWz/8wNgMpj3K9Lfy0foMMBVffXyT4r+cceC9bvCcDFP0311QrATPkvWgosYQFLAuoqQEcQuw3v2si25F+M1RkZXLUU+CgBmCBOEsCbvECOBJbP+Oj9fv+u2+3Zp91uz9cy4Kfebs/3ROD6iPD2b10YJCXB+0PyrgsHdtBuRACfBeTN+uM+suJPSEDbfh3/oxPoHgwiC3/06j8Eutj69sAQqj++I0CUfvIpwCEvYCT90O4Pn1XsT5Ve1/+dcp9FBh3woqXBSEJkvjHHEOUPqJPAjUUCeOMGfCJYPvOj9/t7//d2e7YmAlcS2B3A8xcPYcBm/7ULEDIQew+5gS0EIEA31R8Uf6gAoBsgKwBd9ddvBBJAs6XARgLQXQ2o7T8+IETe+9eRACg7rhCMVgCiE8D4O9wOCb2ubOht1/vYd2ubzLlgKbBHEDSnAMfL6durVm8qBPwXWz7rY/f7/X/fbsvL2+3Zqv4QAjzfw4COAMAJbEC3wC8koBJ9lAhgxZ+4hi3Oh/f8dU8EqtV/JhHgWn9cC4CJQZXZp6GAk/1nawMkrrcqAiwPIIA2FwOB2oaAF5UkcX+GADBs0I5gsNbBQqCorJcFJjqWKvhNMjky0Aek7/LZH7vf3/vO2215vruAD91uz/dSYCOAPQzYkoD7vw34sFIQw4LNymNSUKk8Wv0hCYhkoJ74Q6BboO9eDKoWAHXvBiCvAdPZf4nt3QqA924AbfXV8t8uN4Bt2We029WkoErWpSoCSm11TM8AOYA5uRS4RAITIQDDavaYHxCcm5exfM7H7vd3v2N9McDt9uxDD//WKsAG/ue32/M1DEACuO3g1jkBsf57fqCL/7UbIISAio85AAG0VQEYiIC9DJTYfy/+Dx8HlpeDRK8G90IBHQbgWgD2WT8LoOJ7NyeA5JEkAwwxmuqzur5X6y+sBEwDMggrqoBNH7c68Puk/fI9Vwfwvx4e6H724oEA1iSg5AAaAewlweeyLmAnAHQCTfU1CTAH4GyTMt+QDMRFQFEYQB71lXUAOjHYlvTqh4N2xe5yASoh2PpaJUGDBDrLr9cGIDlY1l+vDlQOAQHckYMiA68KMFsGtOy65RCGsMIDT+QqJoD3yUwCy/f+6P3+7koAt50AXrwigM0FrIuEoBrwHMMAUhmQUKAlAwHo7VmAPURo9h/r//ozLv1V7/5v6wGMV4B3rwYPXEBqIZAQwp4TYDE+LQlqtQfw6my/LgsyZaeLg7wVgmDnWQ5AA5ZWCDRx7ECzyn3udgFptFCIgTlyFRMEUCKgA+O/jl2Xz/3o/f7Otz88QvpszQOsLmAPARoBSDVgud02AthdwPZ5BSxUBVr8L3kAVHrvs076KSLQi3/M9QCJ7H/G/rf4n8X41XIgcwHecuBMDgAe+BHA6uQgqnvbF5DB5hwUQM3vQgIWkKOVftH+gAC6cz0RXZ9MjmD5fh/ZCWCd1CsB7CSwhgArAUgIIC5AQoDOCewJwab+CH79WR4C0mQAZT4hEQS9DgfEztNkoEECDfi6FAhZflb6Q1XXqwHDEECpvZX4a0qP1l7bfAS98cQfzQUo9a4mASMC0CsIm6JGK/2i/QkCuFK9PxmIYPm8nQDu795uy3K7LTvwVyJAB7ARwJoAVLkA7QIkJ9A5AQS95Ad2YmgvAJWwQFcBpB38pUuB9wVKbAWgCXwV86Mz2ICKTwUWFgOxMEBicr0eoBwCGBUADfxsDsAiA+zflNay31ZcfnAdAAXgDGkcdAcfZCJYfuCX3O9vf/vtthHAmgcQF7ATwOoAtn9IACsRSDkQ/wqIIUGoXYEQQ/sL5IDJP539776DwodVAGlr5QBgP8sDdApP3gSUXQa8/rZsRaBeHmy+HwDyCI1MUNlZzX9iJSBO9igJGJYCo4RdIqMfJQ4Ztq8C7FXjHuSnQ92XH/yvdwJ4Z68ErOXAlQRW0O9/JRG42v9GBHsuAImAqv+uzDo30C3yAfVHoHeg9xyAp/7wlp+WFCSWv1sOTBb+0EoAZP5DImBrApAUMFHolQG19c+EAkbpjyUEdQ6gm/QEsCzZFxKDlWNwprJVWfBm/1WAvWrcQ0ie7Lz80H91v7/9v263+9sPI2zrAZAEdvXvXMBKBJIIFDcgyUAEvHICg/o7wA/Bvyt35wCc2F9Cg03RvRyAA34N8hD0xsIfXP7bQgDMFSgyYO8GsF4N/hQ5ALak1yUGRQDZZJ5VWXgKEsie8yQuH63b8vn/8oEA3lsJYJ2EQgD73xX4z9bs/74gaHMBQgA7+DsXAJWBBniHCLTtNx2AUnkG/LYNiUCpvX7wp6sIOHF/lwgkNf8UGagwYMgLMBdgLQCyVgOyciCGCs5nz/Jr8EXOQOcQZEbrfjjTU8qaCBseMyx4vxPB8iP+RU8A24Kg9R8Qgaj/av8lDBgcwApQ+QdVgW0bKr3+jsk//AztzBKgtv4K+Kj08rl7JFgt9BnCAIsQcD2AsQAolQj0CAGAqhOFCK5u3cA+84dyIJLCPm6buAgoBa5qDoDF6wzUkZ13iSDKKwTamSKZSf29cuzJUwq7LV/wz18RwH2Nl9dKABLArv6bC5B/+9OBGxmsIIR1AQ3w2gk4RECTfwBulgC0rP96/FYJUOv9SzkAB/xuKTBY/qsTgZ0LILF/s/RW9v81ywEwhbeAwUIH6hRwGp+wEOhqoF49fojqQoPlR/+z+/3t77jd3n3rdru999CzEYAQAYJfXACEAqL8W5lQgA5uoJUK9zxBB3ii9ALiYT2AjvuN72wFILP+XdlP8gLKFeg6f5QM3AC+VlMMZ9ABGuN+VePHWL6tHVD23or3tQPo2iWfBRgShDp0ELcBjmIAbwTWqEzIJvLM6kEDEFcD9erxCzg3my4/9p/e7299x+323lu32+oAtjwAhgE7Cazqv7mAvRLQcgG7A9B5AAwHus87CWBYsIKFfe+eCSBgt2J+7QBQ+VsogOU/9fIPBvLhASEF8AHwlhPQ2wVYFhmo/Wby74QyYLcmQAEbbbue2FcnAb28QTmHQKBwNVCvHv8IESw//h/f7299pyIA7QIE/LsTeIbqL59hPUADvHIBG8jBIWgn0L4rsKMj2Noomz8QgZELsCoAAnh0Caj8lup7ib9tX+ZBoKgUmFkWTGJ8S/UHZa/kAHT+QGaeoeQmMUC/CoAzVYAjYDvSNwPCq8fPnINus/zEfwQE8O7tdt8dwGZjIQQQ9Y9cwAB+RQIC4I4MdvvdLL+O//E7LgLykn6q3Efjf6X8bOUfkoNYcQZ8z/KzBUBYCqT/YQgjBuOBHxPs7JHh7JoAy/IzWz+xEtBKBEYg8fIGw+SeQQQ+CzHZP+oWXWPU/8z9y0/+h/f729/5kAN4791X/6/cpl4SCsDfLRQwHEBLCmJFYH92vssNgBPo7D8qv4CekIHpAjKgx1iffGbKb5UAQwdguIAtz2KsEWj7vIQggNON91lYoIFN2mznYKj9UBmwQgXLLcDstRTdBchEFWAWcLP9MgC9cuzM8aXN8lP//v3+9v/uCUDyAM0FIBFADqAjAsgFiAvYwK3/MfAL8InSd/Yfy37Qpyv3OSTgxf8C5vZXPfF3aB2AA3hJGg5LghMOgCUBo8SgEAyC3Irvh5xAwhW0cT1iQBKYWds/QQLdeVUQcrEjeGoiWH7633sggHfWJOAaAkglYL/wLQyQf3tYsCp9CwmgFIgOgIJ/JwMdBuB3cQTDX4z9wR2whN+WE9idh67761p/F/8bpb8O/OotQCsJDhZfji0qT9p0LsCI83X9H8E9KH8iCSiTrQO29bwAAbvlCipPAw4T/oRKQAVElbaMJ472t7jnqnEjrlt+1t+539/6P4oAxLquawIkF7Bb/40M9hAAHcD2GVzABmBYKSgxfyMGAbROCipl1w6gs/8ZF0Cy/UIOOr7vHAIu9iHP/2v77yX9ROUt29+AHVUCnDJgtvSn8wXsnQGzIUAW3F27qFS4z2CrD07wCogqbR8LtGecUwR4vX/5OX/7FQFsOYC9FCiToBGAEAH83ZwA5AM06BspiPKrNQIt/kcg69iffBegNqVXb/wdQgIMC0DltUuQ+L+Bmz0OrNTdK/91+4JVf15SEPMCYRkwEfc3stBxurMS0AoTMKRocaV8cKw6jpcFsdUn2/8qRT8buGeP55HC8vP+5v3+1v99cADvvfNQBZB4dO24Kv5GAntSUOz/+n1wAis4wAnoMAC/N9svSUKsBABgmwPAbQTwWzsW/2vAI6j14h+1CEjnBYZFQWSxj+sEVFyPjgBBrhf+aOtPY39vRaBVJlQ2vyOGIATQsb6etBguDMSQyAF4IMhUAmZANNNnUNSqBDvtzzif6HSWL/wbuwN4eycA4gDEBQgRYPzfSGC3/BYBdOCHxKBHBAJoAbdWfIz1I9XXsf5g9y0yAJB7iUDPCaC6e2EA2ngMGyIHwAgBldncf4ID0EDXVp1NYmbnrclOtyfDhiPOoCO4CEXB/rOBfOZ4yy/8a7sDAALY1gKAfWMEgOovoNdk0IArKr+7gwH02gWQ2L4t/sEEoLL2IQnoFX96HYC4CIz/jcSgAJSVAtu2RPZ/SPRBHkC7AkYEqceC2fqBfdKaCcHAAeAkpKVBCANcElBVgBQRTC4HngHOTJ+rQo2jhEbP6xf/VU4AmBza7L+EAZgLgGSgxP8dGQDwmQOQbS2xp6oEWAnQn1seIEMCJO4fsv8Q2w/JQU0IJMvPiCCT/NPuQP/noJ0rAFBa23VSr1N/vQhIgxzzB9odMMIAkGvFZPF6JkyIlJeFFl6IcRYYX0ciOOOcll/6l+/3t/7fngPYy4BSCmyT0SGAlgvY4/+BAET10fZjUhAWCg2AV8nBEPQ6D6DJgSUAoQ/G+Dr+T9l/pfg0HxAs/e3WBUhbsihIgHKkHGiGCQHYO/UHomDgdd0BcRkZlYtyAFlgZNtlzqkSJcwc1xr/6FjLL/tLPQG8t+YA3tuXBKPiqISgAB//bjZdkoNE/Rs5EAIYXIAKCwYHYJADlvhalp8RgS4PogNwFN8jgo1A2LoALxRw1gA09TbCAjckQHBZlQEFwEoS0Iv1S3mAYFGPlwOIJn+0v+ocPohEsHzRX9gJYM0BvPvwTyoB2gGsP6iEAowANsBJWAAVgRYeAPCb/WdkAKEAttNJwRbzM+UPQI8K36k9Kf3RagBTe2vhj3o8uAFXLxUGxTdXBrK1AIltTZ2JzUe7Lp/Ralvxvrb5kcWP9nv2fwBzIRF4FRFkx/XcwRljHCGm5Vf++fv9re+63d4xCABVRhOAJoOtRCguQKoCmghwv7L/mBPQwB/KfMQhCEF0ym8RAUkIToUAxrP/gxOwSoDGmn9WCjTzASw3kHQA5poA7Q4g3n+MEMAChiadiopXwHZV26usvB43e/7Lr/pznADakmBdDcB8AFj+5ggcF4AhgAlwwyUM6m+pPgF8U3BS6jOdAAkJ3HUAO5C7ZKBT99/IVDsGhwyY3e8qNfhCERXDa5BrlW/ftaoqe265Ar0U+PIQQCUzqwqYBYfnSK4AcuW8sjmHaMzl1/zZnQDeud3eXRcCrfH/ngNYbyxzAKL8nQNAMiC5gI0gBNz42XIBAnAkBACwqDyWByPlp2BPWP7WD0Crs/5ewq+1JaBnWX8rEajbDiVAlbNpwHRyAJ4D6EqECQcQWfxo/0wI4E3wcPJnUbSLXqH5A26qHaD9kb7ssKaj+nV/ZiSALRG4rwhsJLBfUKt/k3yAJMGwEtCFBGD/PTIY4n6d8ANyaEk/Q/nPUv8h+WeRgXYCVgIwSwbK3osKi4PonEGUC2C2Pngc2LL73Xanlj9bBTg7BIgAFe2vuoxZS14B7wy/DCT8xX/qfn/rrYccwLtrElA7AJkgkrDSJUHJfO/Z/wZ4Kx8g4IXyYKfm0i9QfkoSJK5HghALr51Ce2Jwv0ad9BvAj1WCidKfZf1x3UDnvPQ90HYf7o1WfSQMGbOpU1D3H6oCynpjPE7VfSccpoalMEHNdAxFKkDLgDzTRo5ZaXukz1E34f1Gy2/8kzEB6MUlsjCoCwWMEAAdgOcGTECrnECn+JYTgPyABn0U82vwt7hfJft0rK9DAlHooTSolH94GxBUAnTSL/reAbz6UBADt344SDkIJBIT5E62HgnEAwgFmjq3ChFkAJUFd7Zd9fwsdZ89nnX85Tf/8Z0A1hwAOgDJAxBbuU1usboYCoiCKvWX+L/lAUDlNUG0bD8Bt7dviP9Vf0v9LbV3XQCz/3qbZf2d0h8D+JAPYDb/RAfArL1l92W7Z/OjEICpOZvkw7bES0EisET7M0RxRNkzx78qJGj37rf+MUUA+zoAnQjs1gTAhJNyFy4X7kBtkYHKB0ifDMgrLiADfJMESGa/Cwe0/a+CHsmA5QQ8N6ByAzJZh1IhEobOAegsvwaVDhEKDkCre0cielYbau4SQfIZggyIM0DMtMkc6ywnMHMsduzlt/+R+/2tt2+3d8QBiAtQSUBaEVDxPyYB22cEuiYDQgJtLUFk7539ke1vgAeAR05gC3ekbAclwuaEjEVA3XoAAnLpT6sBCuStrUrIpqsBHhkwcBOVTecFJAteCAFSyk/GzapwBOJofwV0mbEQkNX2p/X9HX9IEcB7eyLw3q8IlPgSbV/LBThEIMreQJkhAeYOIsDrsELV8VmIgHX9ITGo1L+BnxGB5wQY6IvKLzZZCKD7nsj8m+sADjoAVHk9ga19tF1CzSk5GO8T9MCUAdpZbSqEUW17lpNYfucfvN/fBgfwLlQBcEnwdkA9cdGiCjCgGrCpZhACDMSA6wL28dewgKl6GzuI963EXwtf1Nr/wQ0YMb+bCJwAPgKc5gPIPeiImeUC4B5J2zbZnGXBQjI4Mdk2HFNPYqv9MNlJCJByAzPPEezIiUAe7a8ANjPWGYpePc52Db/799/vb7/zKgQQAnhvDwH0cwFWLqBluwkRYJ7AqgoMTiHjApTqR9ZfbLxbCbCUX1wOKQGiO8ASn7XdKgMimL2SoG4nkxGVnqk+OoeBDHR4AN87EmCWnlULBGiBuiNJMFC5RJB8HsACRgYwZ7WpEEY2pNEuYOoYv/f37Q7g3dvtnT3+39YC6BBAv3IK1wVA9p8SAYC5gRDBqz53QDasvag/dQboGMCy0zBA7e/CgoTyszX/VeA35QeH1YGc2Hwr2YchGn5mJNGVd8FdoEOIHEBo9VkeQc3cqFJgEkPhxSBHwoIMCVTAlx1vlggq4y+/7/fe72+tDuDdV2XARgD7isDtd95BpZWjKRUov4Acwa6BT5OEsEjICg1aBUAl8DpwA2kgQeCYbHsjL0zygfKbll9XC5xk3zYGgM1yA0IKERGgI2PJQJ20M13CAQfgWv1kEjBj+Yc2zlqAGdWPgBPtrwI2O16FXMrn8Ad+z04AaxVgTwDiasAtBNgnrK4E6HBgSApichCBBHkBCnQNbmb1iTPoSEXlDXCfTv6x0EAA2OUDtCPA70bMT6sAXjVAlf4sIhieC8BYXy0CYk5gIPKCA8CJGzoAI5QYJqoRzx8NAZ6KCLLgzra7igSWP/i79hzA6gCAAMQFrBMNSUCrFypUm+x78k/cQRffY45AqatOGDJy0CDHkh5dDERielFhWvrTIYHO+icy/jK+qe6sCkCAH70erLsXylXMWv5GFowQrLyACISU6HZ0W+RALX0Qz2ug4NgYUWScRNQ+q6IZ8GbaVMCdHS99jX/4dwIBCAmsoNd5AHAB1sRDArByAV1YgLkBnfRDF6AtPbP4LNY32lkOgMX/tPynSKFzC466Y2JP+mT+mk8BOiVAVP2MA9COgH4nQGcgHxyCAe5uMicqARTcJ+QBIlB5+6O+V4E7c9wMCSx/9HfkCEDyAMPDJiQZ2AABqtZUVwG7s+ZWMlCDO/F9iPFZso9l/IkDaMRgxPqe4g8JQa30yg14pdaM7TddgWHxXcUPVgLqvnqyWw6AqrlT0jPV33AekYJb4IlAdfX+6LwR0BVi8Yhg+WO//X5/e68AyLMAawlwCAEwF2BkpTfgqwlu5QU6G45KrdYNsNi9qwAQMgjBnyEDI77XYGcxfjXut1wAhlfSptsGoNHJPab6XkLwTAeAk1MIidp+mJlRJYCqPxCABwizr0aUDl3I/ogEMsDMjJEZp0oYjECWP/HbSA4ACEDWAbA8gJ6MjADWbYP6i5LqvyRROBBABHgjXEAV14k963s7d0koOkm/s+J+FiaERADqbjkAHKNNrsRCoE7lmYsQ0HjlPm+dgMzKRLmQkkgyBJhR/SPWPwPyTJuriWD5U78FHMB7eyJQ5QDaYiBhXL0mgGWumRNQAO/KbieTASMOL8bvVgUSq2/lAvAaOvDiwiEjs6/BThdZ6bUBJNvfuQN0Z+pzVzI09nXqrT3UMRMAACAASURBVJcKg+J6xKAnLao7Tvruc6ZcyBS6EDpUXUIEvgyAz2oTnQuqe+aYzT386d98v69rALZ1AEIAazVgz/4zBzC8aorlAdS2rkIgC4e8v2TxkOsGMLeA45I6vgZ7ygFg4g8JQhOdl+FPZv+ZnRey0CQhE4PtH1TfCBmkXQd+S+1ZXkCTiQZq0gG4sb6qMHSAKFYQHpsIMoDMtKla/syYy5/9Tb0DWGP/7R8QgOUA2NtnzEw3LhRS6hjlA9CK6/gfS4XU5rOk427p9bg02cfATtS9CwGcSsB6/taTf9Zvx0ItvQ2JgH7WgEYyMMA+5AwmHMBMDsAjAhrPTz5M9H4mggy4M65g+XO/YSeAXf1lLYAsBca/24D7MwKdakBIYOUBxKYyJ0BDAeIOTOW2QI75AgVkXNVH7b+VBFTgDisAQda/gd5LrCrlZpa/WXJrEVBk+cGxNWAkqwDMQWiFNq2/zNKgDOi6A2NFICULRAV8rrSN7HgEzmh/NH4G2MZlDi8qXf78Fz8QgNj/thjIcADtvw9HNcgQwGxIwPIGLHTQVj8BfszWmzkAlZsQwFrlPbcCYOUCjBwKKwl6pUBRWyFhukxY7LmO7414X8f61BVY4YLY9iDBhy6BTX6LPJCoPHtcAXelbQRUD+gZEojGZyCvjrv8hV/fOwArBGBLgnFpcGdJYUJ0gNknxLDNCwm8xKEV6xtqPwt4DWpm92kIQICN7bSNF2Xv/pLfUgNd5wxoCEAA34GbqL0VAmhSuMIBuIqv8wGJRUQWmCzAfNIQwV/8tff7O+9BEhBKgEMiUIUAXjLQinMbAAAcCIruFWMVgBPFX28iLhW2Yvzu+JCo06A21wAQm69XRVJwk+RpaiEQCxeQKEDlaWhgtEWQWEqvt7vhwoQDKAFfjR+5hytdgjf20X1HLH/kIpa//GtUCLATgE4CogOQz628IwzslKx0gosuG1bWnuUGotJhyzUYYUIjBSsnoJKVXZnPCAeYo3EBH1UDDIA38CniiBR/CA1I1r5VEQBUg/1XVt8jjG7iWZUD5WEz5UIK8sRagIhYquQQgfqI/a/aeBYKZMOD5a/86r0MCGsApAqQcQDbgTQBMNuqJ70GE/nuOgMSGjDFj7ZZhNABnxBTIxon459Vfa9yYpUEEfRU5RXounEUkJEgGJlEYNb9O2IQ16hsO07y9nk2ETjzJKG4JIKUSlgQKqyDzgzQM22ic/AcxPLXflXSAew30no8eDsJvBGWyhmJsKojQOAOi3R0yRFtPcvuqxo/tf7qeryYv2T/mZqT0IARgfzmG9Eg6erP8Jvr+4Tk4Sk6IwnWfgA/IxsCPhmfKWuk3ugcqENIgLwC+hl1j4Ac7c+CPDNOd4/++q/ccwCRA1iFHkqAtBrA3ICh/J46Yp7AjM+DHIK27t1aA0YIbKGPIisrw59NAOqSH/0NEKyMCBS4qwnAtNpnk4JGnN8pfKYKoIgiA2R2DEYglW1XE8FZQI6AHu1vv8nf+BUPBNDKgFYOgDkAsHdmQhAnkhP74kNDg72OwgMP0CRuN90GW+CTdCwWoVluQKv3EAYQ1cZjuOpv9JXJNyT49KIgliMwlByVu7kJUFwvPBjcQuaxYSuUOBAGZMjGIxEP1BEQn3z/3/oi4gA0CQD4uxAACMBLCKLNjFSPJd3Q7rtJOWu1oZNcHMgmE+8H5T3P3Xj7OlCzCgEeN+sEVDs8Rpu4Ol9ggd1ScuYWkAQIsDv1lrYqB+BZ/2FfsBqQAe3sbZG6Xwn2aGzr3Ja//cuJA8CnAXfr314SajgBkwBwAs6EAwmwWWFChThY0s8iI297B3DDPYRtCLi3Psb2AdRAHrKvqb9BCEyNtaKXS4OkoqAnomXjKUEo9e/GSjqAs0HvAS8C5WzfaNwKES1/95cZDmAlAbIacPudIRcgi4H0oqBuUirgU6WDSVtJsHnJw8gtZNyGWeJLEJNn61vZzYjzo/3dQ0Ea1DgmUXMWAqTAbil9UOaLynttQj+iAzibCCLQRfstUM+ShJiqqP/y937p7gDuex5gBz5bByD23woDMA9ACeCAG8jkCLTis+8ZUhjCAisZOKvwySw/OoWONFWMrmv4ZsWAqX+wrXMGbLkwnMvgIowEIWuHTsV1CTKz978WeViA88IKDzRnA/Ts8TyCcUng7/+SngC2twFZJLBPljIB4IQ1wgA9waPM+rCfJApN9Tae1beOGZ1LO06CEKj7UbF9A7CVB7AShIa9R3Uf1gOwhF9V6S1iEEQFDqFN3my14IJEYNYRTANNERd+PZMMIsXXp7H8g198v68VgHf2uP9dBX5xAtvbgaUUqEqCg/1HKweAlx9vsLeGIlqxchWojCyqY1RCgXK5jxGHofIsD9B+V92nSAgIxCEkgLEGBU8mAaO4PgoVmEJbOQQG1CzIs+08Msg6kAwRzJBOlgiWf/SLRgewksCq8l0YAKBveQAgBGb/t4vDhJQmAwf4a9dQeZPWnJbiHMfgOYeNlAKlx3BFOxs3L6B+LySS8EUg6rzwuEgQ3luBGugDqx/lCzyCGPbtCBBi05M9Io2OFB4hEXgmGLMgzZDEjIvYruUf/0I7BGgkAJWAbY46SUArGThMyAIZVADH2ppEkiCBir2n5xmpu5ME1I5pUH+LYEnFICKEDpiFEADPSSu0JhQX/MphTBFBIYnI3MRjgLviLs48H9OR/JNf4IcAK9bxPwoV9TerAXgj4T0BOJk9MhAQDZOfACUCNgIy0zbTJpPZpyGAQwTiKug7AYkr0L+N991Vf00gpGyHINbK3yZVMQQwVT2xEMh1BEZ/Nvk1EKsKmgXyGeOeTQQdEf/TL3wggNX2b/H//jqwLRGo1gC0HMCeD9AlQPw+WDqZJEZIoCdaNY6OgOmFAVq5u7ae3Y9AHam7sd8kApUsZHaekclAvrv86eoBcwkZkFvrA1hf1wU4Cu4Btu1T/c8G/hWgrxDEmSFDc0D//OdDCEAqADoPIMnA7a8wrv6LpSEFfJlkoQtAdfKShEmAWlUDN7xgOYYE6DPuBY+Lv0W0HRXdK/cN2X6l0jqcsICubbx2AVeFAK7Sy+zV1YDiasAjgH6MvqZth+vXH6sksfyLn/eKAFaw6yoA5gEE9FYScDsZZfsR8CwhSJNb2Tq5UVLsQO0lE5Pk4bqRiBDU/oEcHFVn9X1T4dFZ6TKhYfWZcltqbm6HsZm6D07QKuGRcqQGgEUKSF5N2QySYPutbZkw4SmJwCIIJIXIYSz/8uf2BEDXAWAosN/w7gUhAHwhge7GY2wGBKFtf5oMGKgcl1Cx/wKwKKQY2hWB3oHbqver7ab6J8t/2L9VbaR6sM8auk4gArlRNbBchQnSaBw5RyV7lRCAgSYCerS/otRZwqiMmSECc7x/9XNUDkCvAyB5AAwDtrlBQgG8KegCOsvolQgrgPKcQKTQSReBhOCquBP3a8LTToXF/vpY8ls2J6AdBFH/rNJfov4YDoL6UzVP5gDc8MBJBFbBnwHrWW08EEcqrvhw+5oNBZZ//bMLBCDqb7kAcAJtUQeyOuQDcGIPnzFeJQClSbJqngBULW3xIzKpkBYe3wGxkISn/u5zASwccLbh5NHhht43ELsFcGeFXwfmA1UAdBsZ9YxU/ej+zDkwJ+RtO5Mkmhh9yc+637cKwJ79lxyAlP/kKcC1IqBzAJgL0K4AQwC0m7hgyAsBrAVEaL0HJU6SQKeiyT6dWictOwsTsqW+9ttosAax/pA3AKJBEqEhQLX+T+J2PG9GEIxEPPC6ag/SNzhOtm/fZo3JABYpfLT/KBFU+leUvxHNR37mSAAC/lYBUDkA76EgIYWOAHASKnXHm4/hwaB8pIxIV8oFFpxlziNws/0diSgF91bwuQQmE7QQ+2fUvwO+pf7KkXRA9db6W6QB1+KCHu1qMgTQE70DoTOG24/Y5qMuIEMOFYBXQ4FM++WjP2MnAFUClGTg5gCEAMhy4M4F7JNou/eZ0qBWELD7qO6D0uNkZXmEwKqb4HXI4wzAa8ejLTYSjb5mfXz8jgCvlP86YrhC/ZH4lfpSFU4SgAfMo88TZFxAlRgyY1aI4Iy2zQF87KfbBLCVAAP199YCaBJAV9AlnAxX0NqwnIBSrHSSziAPa/VeJt/ACMp0AY6l1+CNvofqb6h6NikoJMMUHN2apayZNt3YxRwAPa6Tb2iTXj4cVP2MwkdkUQFz5njsGt1tX/rTHghArwHY7P++DBhdwDanYCWgzgPIfh2TtfUB+6QcJhcBedfGUXoGwAaOyXhdKy4rC1rxPAtlymqfjP0x5h6ArVSdARJdiQa6BWC8t3h8RhQ616AnY+cEigRQdREWUZ1NDBnFz4I5Y+OroMf2y5f9VE4ACH50AS4B7OD28gDtxyEVgW6yOIQwWGlg/Uz8bQLXcBoa/AM56Dq8FcMbCTyx/o3ISF3fsvaMWPRv7JLEPht08nC4TyTDb5UNI1VnwO3coaHQFPBKxa0QwAO/G1LAucwA+2oHkDkny2Vs27/8pygCANUXF9D+h2CdC1CA334rcQf7Z7yxsp8qiFpBOKhPQAiW6jIlN9UdzllAKQBjdtxT9eF8HJLQ5xNae6Lska1nSu+pfyMjb3GOlxwEYrHANwA6sO/abdBxyRiPAf4ZoGf6WOA9y0Es/+YnAwHs4JfsP4v/JSEoTgD/is1veYFZEsB+xAp7gDEX0yRU2asQaHX2wD8QjEEsCDKt0pZqM2LpSqaiiNpteCW7mQSgukc4UTWxsH0Z8EaKT/erRGIW/E/pAo6AOdt35+Pxvwf/t0gA8BKQFfzZMiDmAYakoJ4oUB2gE4UtHDLiYQSa9bnsDEhJj4HfdBYHF/V4Vn8gvh3sh9Rfk60ot7c9Uf+Xc80AkDnCNGng+RrnzCa/RS6Z8zXBJDv0ORnf9bHY96Pbov7LV/ykMQfQrQMgVQABvP67//60BKgXA7UTU9Z/mDgk+TeAndjrBtpCBcEF9Wz23on7j1p9TW74mzaH4jgC/Vtri20uDdakzvIDbTL0y1I9Gx+V8CJHgNeTBfIMEXhjz5LDU5HB8pU/ccwByBOAXQ6AxP9sQVBL5EJGF8uByPYDCehJE1UGAuB7JKD3MadA22iFx9DCiPPpeZAFOZWyH46Jk2cDPiZFRX1IvI7XrMdg2fsOvCRsYGMM25QadgC8KAeQIg5BblAajOL26v5Z4DPrb6m95wKWf/cTxhwAPgJskQAu/aUhAIB5+22J9aelQa0uOuFFQoRBCY2Soc4PNBDBMQVAGJ50amqVI8kYOH4F3FTZsyU9EvuLMs4q/NBP3SNT1Y2FPQyQcs0RYYT7JxYTZQgiAmoE/Ki/8E80DgO+RQYe8Nvx/v2P3wng9updALgAyEoEYrY/ejS4katyBegG2OfOEqpSX7s4K0QohgVUpSft+5VgR7BFsb/nEkxScByD/s31pB2IIOMSIETRE9YLF0wiOGMtwcUu4EoyyIAe79uyEsDwIhAsBSrrT6sAuyJ0i4KU6p9CAkpl9boBNuHT7iCw9vThJBJfe8erKrt2IZZjoWSIcTkLCTwVt6oC6nojwLKYvuoWIsUf1DsZRljn7m3PAPcMBY/GqIK8YU/IHTYs/+HHKQLYAd+tBCQkMIQA7L0AQAxo8bbjI1MXPiOIqMJNOgIEly4HmvsUIaUA7oQ0tD/LuBsAzTqC7XosUnAy/MwBZADtKTl1fjhB2aT19j9RCHAGOWTGyII/Gyos//HHAgEo5c8kAbv4X6m+lRDEmy73EtViSEA5pcFOIVTSMHIEAgTLVuvVceXVeFWwO3F+ByIW5zuxv1ZRRqL6d2TK64E1Y/9dIiDWfVB3veqPEcEThAARcDNgPKtNdC6Dw/lPP+Z+fxcWAOHbgM2FQKDsQ/wP+7TSo+qzsiAqk1apLmGoVUor4kTpcCCDALzZen1EQpbNp+QEjgNdiZWxN8t4pCKQUXeLOChZOFacEoFxTmzsYRIjEZwQAnjjRwCL7Hu0PxofLnVc1IM7gzxGE96vWgkAHwUWF8AWAuGDQOyhIAQ/KwPu+9t5KmVvJwXtMHSgE9BQfU0g7oMy2g4byb9ZMFtkwUCMhNDtJ2VDDVoNLBoSEBLpQBYB18kPpElkv9HM1XRzwFB85gzw2BaArX4uoRRAFYG7up+RQYYgKm5i+aof/RACiPK39wAAEbB3ArSq3v4Bl//qpcAa8Nt3QhAM7N0FE7DTSWc4goEUAAwm8Ky1CNYCG69syWr/BJBWLkArvWflL1H/iDwE2I6dH0hKJkeyYtCRFYCThSdZYLuEwo6hCGwGlE9FBsNx//OP2gkAwwBJBBoVgK4SsE8KyQWwuJ8RAoIdCQJvpMXqVnlQA3z4TpRdjsHA1IEo6hss7JFzQQDQYwaE0AHAUmMrSWgAmJKomuRH7D8DmOVWGMAjgHb7T8oBeORR2XcFOcyMyfps2776C/ocwPr7df8rkEMC23xS/0uQLgVm3IBOAHYni1ldneHVcSMJKdbJEYYOQU7BDR+M8VMZeQZUY1tHVNYxlQJnQgJNKNbk9tzGAFovx0CWDXurDkPF1+MVcgBZhzDbbgaoVWdQsftNaIHcNwLQIYCQgCh9SwaC2jfgQ/lPg92qAnQnokIB6gCUcrlVAqNsZqqco+xMtTM2/FTwVxyBofAsvGGgNe25UxqskgxV+ETIkCaCAgFEzkLmqdXuqZ1ARBam6gMAl6/5kSoEUPYfwa/fBNSeBQBi2MZW7wRox8skBgnYTUfgKLeA11O4KDk3gJ0pWzI00BOYxuhOeU9fhwXWqdg/Io7MfuJKKNhBfRrAJisAFJgH1wF4oPYAF4HxyP6oLwN6xhls/f7Lj7jf5dHf9hdeBNoRgJH5L4UB+2TSpBDmBADsCG5U9izYq+Sg25uKqqsJhnJ64JdrcC13Mfan14tAdDL76MhM0qmOFdh2fRxGJBZQoycKI7BkQZ5tFx0v2h+BPw30BrhXH7bweCOA/eWf+kUgFvjxKcChGqAAbuYADCLQ4N5O14j9I/DjftcGe1UDpn7Ogh2LhCrHfyzw098Hwews/aVkkMzkD8qd7JciggNJQItUjoC0CuAjxMLOMzz3r/3h4ADgLcDM+ktOwKwC4HJg9ZmV/RoXWaGBUv1TiYABO8ofWLHwRDLPBd8JCn8quLMWPeMkiPozK5/dNpBCkAPIgnwWiLP9QqAqBc8of6rN1/3wh4VA8gRg9AxARwI7iFgJUCcAKwlBFg50lQIdDoCbMC1rpYKQrBygW+kUMcjkR+CsxvHus/sReCPQRvsR0A74rPCBnXtK6ZVTsdzgYwK+ovaVthE5zCi/8MnydZ+vQgC1AIiFARveINHnJQMbNlHlAbDbiTj7NBmUiYCoNqsiDBNUT+YjoHaSh3Lz3BDBcivedkaSjvqa8X2ypBe+QEQBVl9vBHrmCCi4H7EKcJban00GFcJYvv6H9UlA+i4AXAuAZT/1WWf/LdXv8G6VAQkxlMHPMsJFJ3CJylugstTaU2FPdT3wZpQ9UZ4LiYvU/TswJ1xDRsWZ88v0a0oIFjtDNt7YEQCPEEc0dnX/AwGQ2P9oDkDCAvld9XdP9dEV4I3tbpaenMZ3V2lIn0yCSlv0wyTh1Nkz9p6ppxVGoFU2VV/UOqn+6NKiMbtzdQgmcgRv1P/hJlXdw/C7/dcfajsAifeFDESU27MB+wa5jzoUaOB3LD4SA4v9NVF4LgAnd3ehgeozAHugHianEx6wCR+FG2YeA294whVQYtjvWQRUMw9BlDIkG7b6j4VmVrusOp9s/y0ncJX6R+POAD4kiI0A4L8BQ+Uf3gfg2H/2MBBTfdP+C7vAzdaPAFfIwLSERHVoIoqUBjNKm3EDGVIwx8kAOFLuaL86hkkkxcU/jDgrSh8CUhG9B6iMzc+0iUB7xO6H4EWszLqBb/ghJARgTwKytwI7OYAhBHBcQDYckOtlTmFYABIA3XILbCEJ3QaE1ampsRItHTbsF+mqqpUryCzZzYA/QzJJN+ICPLFqLwPCI/F/aXy5N4YjiRT6akB7BGmd2/INP/ghBGjJPwL+1QnIfGf2X8CuQ4GGEZXoO9UFEOdwhAxYDiCtXE79ngKh2t7LFWTAHwAbSTEKEby2kaqznEHUJ6XmCUJJjaPUdFbFK4CvtI2IprJ/+caVAHQSkD0ObL0MxCgJbnNNqb7+XlX+KATYLlwdky4NZVaRxY/ZcMGLZwNHkCaXCPwZ1bbOBZXNyS0wkJruSKmll1w9CsrHdACzZOBdYwWwYj7CcAhcijf+8o0/KHYAkgzs/u4Trqm+/g7gKYUDRNG7F4jKhTlAbz+SbgNjdz+g0S5yA0wFO5AQAnHVzwOoZ/vPAn8yMeclKSMlPwOspm1nhO2oeRZEM+0qgH8q9d/O8ZtWAig4AMGQuRDIWQ48JAUBkO3eRcDWuQSi+pETQOBSdpxQ/kjJI7IYljkrVXaBlajpZxbqeGrOQEDzGqA8OoywfvdqHP5+IICznEKFSDJOYhjvm35g0QEkFwIh2Bm4w3AgcAJ6MrV5R+y9BpcmCFQl+oOz8MByE0qNu/EK4UDkJBihWHF7Bvz4m5jAJct+I8Wn+6+I1a8YE0k4+OwBtaLwlbYZwIfjrQQwrP4jK/82+6+2y8q/IQmolR2SiNvvqFUc3x/A9jOwESfAgB6BnxGJFR6E9tWbhJ499ey9FUbIhDT6ejadAjwKMbSVtkgxY7kvAOuZjwFn1fvq0CACeAhucGPycejzzT9gdABYERheCLqDUQhh+0qeC2iYNcBvWf4wMWgQhE7+CdHoC04TAlFy0zkY6+41udAJkyANar8JKVIHEBFEspYfOZLIxofkmSEOr82B+H9WvWcIoALaStuILNj+bdtKAF4JUKu+uQpQx/5AFKj6NBwQeiLOYCCxKEegCELb++GHcCoCA2taYHXU0IrtXTJhjsd5kKcDpziDBEEgQZkkg+MBWVigiYjA/T3gZofjGI4kC+azwTszXgTaqwlgHX/5ls97tRRYVL2tADRCgUH1yYKgDofE4nc4VqDG/EGbE0ZiziMIF/yGYlCHYJEKKzviJLaOEWTbQ5CQpN9AAhcoP5JWGaBA8lmyKYHZI+FgldwMeLNhgncNlX0RWczufyAAWQqcjP2tCgACV+Z+t0RYAUmIpAOxEdtHTmDbTybBsHaAnIMmiuHmatcBk9m8iexcEgrqVgP2c6cxvFL+LMii2HkYJ5Er8H6TaeL4ANj/CKSPofiIowcH8P23COBGnwHQhOBVALxHg1l4kCED0mbIEVjqTIhk+4GT26dJIXAF0yGBQR4U6MR5ZNsNTkIRS0mVsa8ir+o4LnF4ZKvPYXKV3xWK/1o4gG/9/ioJKC8E9dyAAXaM75sDANDp+N8LA7p3CyjF1Y5B3xxKEsZ6AVo5SIDYZHMvGRUlqqLseLCSbzunpBVGMsy6hTA0icAWXf9sIjC45irZyPzKuJUjIH4KxR8cwLd+v50A1PMAmOzTnwXTYvkld7Bth5uM+9uBo3yAodKR8uP4HUEQ5dFtGYEM25QCDwQQqVAEzAgcQdx/JvipC4jICX50Cpxk/wzoorCkAsrM8WbHM0WCEGXU9qr9y0oAWwiglH8LCYz1/w3wqvznqr5BDhqsUwuEqg5BkUwHdgOI2yGsx02tHIHcaGd/pMQIbArMRF7hCGAwFMqAxWwTEdys+sO9zJzfjBuoKPVVba8lgGISsFsApElivyE45wdXADdNhwUdlkm8nnYCCeWXY+l439tecgvG5OxuZqSMjnPoJnwWYJETYUoenWOkaBP9M2C2yDML8my72fg/Am2FLKKxZvZvfb7t+77KAWxOwEj8NXUHp7DNb3QBCvwSAnSCq0MAQhiitugOcCzcbsX71qrAri9OXEY21nMGHUu9GnG4oQVncMg2Z8FPSDEFNMcVHemf6ssIidw3a6wsyM9oVwXhUQLwznkQMVIKbQRAV/45RKDJoAHcIQMhiwjUQwjQscer3hYh0BWBxhhCNCzej/ZZx9FuIsolHLbMFUWfAXIUviAY2ecKOUVjMTIoXH8EmAwhRSA/Cuoj/c255pHot33uQw6A5QFku5cLQGAjMSDmLCcw4BImixUaCDCZkntuwGtPCcABCx6nHBJkVDg7qSuvwEoAcQDIBPi9MTIAKyt59rcKyGWWHCr9IvJ4kv2NAII8gIC1Wwqs1wUAoi0yEABrx82UP+sGziCFDsgkHLDyBN1N80gjqCLg+CkQJOPqdn4BUOhEniENVJtE/2x8TduRa/IAmT1WBMSzxomO8yj7P/65r1YCotIPn0m8j28BFpVvwGdkoCRf2/gOd1k3MNgImIEEyBZZYEKJugVrHYEoi3EsTSzu5HEIZCCFyuQPnMIl4If7kgVMtt0hUkOCMj5XgVex7VM2XU3IlEAQxyPDdP0//n3GlYAh+FWs370OXBbbqWSfblNxAlbbsuUPyMLLBeA9YLafTZruB8+AO2vps+32650Flqem4b4T1d881oyreWICqJLL1e2XjQDkjUDkmX+d5WffEVeWE0CBNJU/qfq6f0eQBdVv/Qw1tdyCBWzGsDJGqBIZgiCAzjqK0kQ6A1hnjOGBNUEwIUmd5AAqxyndB0PFw7nkOAY9R5ePf+9XSUBGBAJudAVt234Ttn37xi4ESGyTE0rnAIBtBqwfAD/+Zl68r8nGdA3RykEsy2TtfJYkKsfWk+wM4GavJwnA2fj/CDCPgqzSPwoLov1HSOUVAeBKwGgtgJH80+AfbL8OC9A66Od0gFy0UiuCa+Sjt0cKboYQRGmHsR0w4vmGE0GRltk+AapuIlTbG9dcDh8mxpkCauL6wt/eUcojfY8AUiv0Wd+tc3ogAA/8xsKfDuykTVP2/YO1GlCLNnUCiii0Cpu7LUfgjUf2WTG/JgXLORwFtbkE2VLQRNKPTgiHjNKASBw7PZZ2J0Vnc+Q4ugsk6gAAG0BJREFUVVKKQH/muZxKCp/4Xv3DQGLn0fI3sEerAPVTghAaaFyllgcDi1Asq43t6yzwI2IIKgHiOFKWjZyjZ3XZBMuAOJqYbTJVwwuDfIb/l8FR2cy5VX6Ts0HmZdunz90i7eClJZnjZdoMv1EjAMcFbLiYAT+x8TpX0DCeAHPXxAA5XTug7YiW7on9NPYPwgLtEEKiSNjcTg2y4YSehCeBv+xUZid98ne5khCmwHaQDGeOGfVZVgKwqgAiiBH4U2XAfTCco1qxNcAZxiOAm+J/kSvwEoYU4Anl325ath0hr5BYNPDYq9Sr4LzY+reJfBZZVa/vhPYRGGf2Z/p4bZZPfM++CmCFAF4YIETR/upnApw3AqUJAQ4ShQPD/ovA3wjdANDwwxvKZbVjN45uSwI427eqnIywpsbIKOT7iAAy4Ix+p5kxMn2kzSsCCKoA+AiwJoOOAJTtF8vPSAK3NSFLhAJdPwLuTKiwHc8jhsx+1YaGBSRxJdeadQgWETBVTJNG0mVEE3TbXww9yg6lmPzL/gapawNSitpXgIdcF40783tlzmUd94EAEiVAuc8m+HWOoCH61fxAy19R/mplAElHicqrryeD3wM1fVkpm1gBkOgxHEV0gZA4VnpiFlQ5MzHNNoXjpM+9APBozKuI59BvpgAwJgE/B0KA6CWgrP7vZP4bWcBJZJYEI1FYQuzlAtw8gTFg2jXs12I+diz7gQA9tu/2GaRkOQvrfYapiZgNR6znyMn1zQCkpG7GOZfG0PenQAAZIM6cS2bcq9osnxAC0C6AgH14+Ie9EIQQwoY5FRo0HAbbKY5In3Yf2QtHEGVWiGEAVhHow1cHPHgeJnAZqAIll3GrSUdKBkdyBmQF41WTsxv3LMK6mAAe5bdwSKt6/AcCMEIAmevrbz88A7Dv1CofVQQ66w9ftAJrMdSuAHD46ucIiEGDeRDcKCwgB43KgZYa47l4biIav0QyybjfOufhWGcRiQHK7nivKQFUATcQ+Ylgnhl7+cT3sEOARgDO038dATjZ/w74AKTM9q05AScjBY8YEHRVy4/Kr4mEKZXbRnaSa/IAvR3HISk3CZkkr3AMOPeM3c2SiTtWAfyzgDyz3+xYZ/6e6XPoCMBZ9tuAboB8cALKIbT5x54H2CeVBrkGOHUFHjFQNlBJ6wnVZ+AWgogA3Fg6cVymuJ1zME/kYQdT0CwgXTUpEFdmUodtCgQQjrVf2NXtMuNn2lTu18x4rxyACgO8sp+n+ts+A+Rs+a+0Z1jFfXS/ASLLGQxjJEAYlgpn1FwdN0UazloDD6wR4aQVH4GTPP+ZCUkn/MmhxtWgsu7H7O9x5fkun/hsFQKw5B+AGsGfjfc9UrDIYjukmmjatlv4taoAFduvyccFWYJIvOSdFvIo7s8Avps0ScBaE606VoVUdFvL9byO4Inc2PvhnEcC2CfL+mf7p+P//ar1dgTsEA7AmJ1gFrZ36k36tXEjV8CshFwT3tEsqBPt2rDQNqX68GNl2kfEUQGmpcQR+VSOkQJIQf2vUMorxkxdd1R+hbl6aLzmAMhCnuEZAKPmrxW+EYAFcGtpsLM9dATgUrSiMvLQbSruYArQCaKIAJxyCjgxnGN6hGLuyy55npicFuEcJZSjAD7aPwvOK46TGfPBAej4nz3959T8B8VXYMR5aK4HIACOLD8DLZvzlp2nZiAB1G1+J9pVbD8jrdR6Awts5PymQL+Pf6j6EBCCNVHN/7iV/lgq6XkWCcn1k2NmwX2UxLLHyQBeLkPGXD7x3cccQGbdP1P9UPmt5CAAqiMLOVvD8re2XkjggHXASALUWfAzl4BzKLT0wblk+kdt0vuNc6lMbBPkhtU9tMpRgfUogGaApfmi8lsdPd9S/44ASLyPQEelZwlATQqIPU/56ctB1MtEGI61slP1NybvU4LfELBXmxMZfzZGxnGkQY8HgB9rxkVM9XkK0imqfYUYqgRYAnHBEelxXzkAJwcg4EOFz9p+5hSasBPlZuGCMgIPIkwmiN50RjWg+22zDsFxHRnwR21cEKtzjADvTUx0OzMgjsY2VbEI/iq4ps+L3JiKslfPszJ2pS2exwMBZHMA+8Re709HAGxxELTtnACgWZNIa5ew/APY9c0xngno+qlBXHxfDP7tBlaOwSZjsn+GFLZJciAMOUQYRQI4dKxHBvWVJDAz9vKJz4rXAYjidiHA/sPRtQDWE4LGOwIt1e+2KxvgEsD7DPyotNPqXwQNO84ApIkxI3IJwXryMcPjnUAAVeCd1f6MaxsJgNX9WXjgKbzlCIwyX7vn3jJhpZCUAGBjRBCKTzjukoraOlfbp04iooTk04mFic4I6QiwvQkvp+XlL44cewYkZwF0uDZ1D2Ztu76VR8ZZPv5ZDxpOwwDr+X9P4ZV9b66B2HodRmgXnHEGrc8Tgz98B4GF4wJp0Bud7B+BqDu9fcxMn6hNaT+5llL/IsnNkMNMn9eZUDYC0M/5I2jXzxqowzaw9l1bZzsCl1p9I1zQJCHkhffeVH+HJBgA9HwysZYE4TA/Z/sZziECi+clPAXOKg62y5xLFHJMjZFU2ciVnA30GRJ4jD7Lxz/zVQ5AwFVa/rt3osAv5gIQ3A+25OFuenbefV6AlBLZeBb4U/hMNSLQC8gonPyzx7Xq7gapyObwfKJx4SfIOJmzjveYQM78VlW7PktU2eseCSCI9wegW5Y/SQwakDpksPYLM1juofVTQHFxE71NKGkJQmyGDTyt9qsFGeCYo8N5ZcfJtnMnsvo9smNm2mWBUHU50bFnjvvYY67H6wiAvvLLyQPgk3xWqKCFRZSdAbdti5KBilws8YrcAd70cgxfJYtAYQPI97uPEog62DbxCmNGE7UKJjx2duwz2kVjXLl/hiAihzEz5isCCFYByhzRCj0A37H92xjE1neuwtmP/V1nQBYKWfMbQ40MCKvtD5EMO6ErgBqMGQGBnWa6z37sdPujoUYUipy4f9a+R0A/c9zl277bXgXYRQABjsDUIK0Anym7DiW0m2CCaS0ZHsggafuzYO6GSwCQNkn0CwnojDESYUwFjDjcTL9osVHZTTwigCMgvu77txCAEkCy7s9IAcHI3IIGNoJwIAV0ppmwYD+4xgn9HoCpAuIQl0aDsF9nH0J6KDWo2v5DKk86zxy/QjCZtq9Tm+hcrtq/EUCn9M4LQIYwYL+x5mpABUgK8H0jgmH47IC/U38Sl1fBnwV+GryzuYILwd+GTl5ENPmyzNONkzx2xg7PklP2ujLtHqtNdJxov3YljQBEibW1t7Y34CVW/Wngt3vv9MXxB4sPd5w5CBY+6PESTvihCUzU7JzF68uCwzrnSnKudCx1MZmJUxo/itWTP+bMeWX7PEW7s46ZGSdq00IA+uYfou4DkEG9vX2W7Weqz8gBccjcAQNPRfnNuUjcCQPB6a7BZIMqBI32SfBVjhZNtm6sxPFL48HglX5XtM2OeWa7zFhWm+VbP6NPAgrYXOX3VH8fwFT9qEqg+rvq76izRxQZfEVlQXcOJ4nDBdgZY6TZKoZ6ZpLFo4iq8JZHj1Htf1X7K8bNjDnTZiCAyPLPxvs4LnUEiaW/HaifCPyReEXEkSGfM22/nO82OaKTTyP4QMOLQo/M5NdnfXWf6viZ9pk263Vm2m0hwOoAUK3NxUCBsrvEkFH9YI1AN3+zFYHki0M6UBog8bCDYcth0SUHOgW3pwxyAPiJ9wvMjp6Z7Gzsx+pXPU62/RntGgFYyt/IQVnS9au3DwHL6vc6RIjWASDIBntvOMvsSkAPwBZuuu0HQBuNUwUFPd+LwZ+diFc4kPSxyQ/52H2rx6u0z7bV7ZZvkRyAEddr694BP3IFmXyAE/NHlt8iAv2fjXju1wJ/Cvhq4AzOzDZO58y4mXxClUxObX/4IvqzyU547xqOjnGkf7VvpX2p7bd8eCIJKIpLXAFTfq322jl0feCOee00qC2HYIHfUt408GFgb26n5v0JawVmiOVUgHuDpX6E+GwqEzseLRcnXz3OzDVV+3jtl5UAEKAIOhO40WO+mZifOA5KBEG7DuCJhUADIcDkZPPUJIQDil21/dP4KXYsNs9g46HNgYGrkz1/UucRwHrMo+c527/abwwBdgLoSIAou1bjSNU98jD/81Ct/t7/IyAuRPocAH9F9be2pEM0x+l+tTEag03u11H55Zy2yTZzURUUH2xbBVDmcEfGfOy+yzfrEMBaCrzfTAbsiBwyYcGg/oSEAOu9sKi2oe2fUP3WJQnacN4XbH84lp6VB9xJZoKn25RPPD3yaQ2PAC5zEkfHP9I/03cjAAbgAegHFv9YBMEsPyqsPgcNbNaWgb+bh4QsNLHgjWV9Q4IxZoZFIubxghmWcRWZSVrgj/xwb8Df/VYZMEY/7hVjPBAAgIIqvKHGkfJ3Y0UEsl99+L4AaQcoxLmm593Z4Gfz2pvrw76kg5giBXIiV+EwHDdsEE336/efAaiZszzzuEfHWr7508k7ARXIEMjMGZhKnnkpKGnDxhu2ESWfAX8K0Jn/ZwBmgjn3E7Y/i5uIWDITM3uszFgdYV01cPVEgvZHwXP0dK46fmXc5Zs+nZcBN8BFqn10v7H8V5NMZ7kTVYHBoicBTMkgqaqhC3AaRHiJ9m8TccJZeBM4dUw2wIHrjABVmdjkJ2nDV8eJzuus/VeelzX2RgCDwnuLghxV74CbedQ3Uy5MvBQkUn53P7odreIJUFnzvdueGKdq+b3xLwF2NqE/zRxnweiDNc6VpLD+Uo0AGnjBWg92f6dVur2yNFhA59h4nEfb5+T6fw2MCPxU9ZV8mG3UXKNzn1yjnqIRZtz9RXIpinaIplkiCgd+08D9Bc4ihuUbMQRQkzXrDBAv4UNBcllR+IDK/Ejgb5MZZnVEIJ7V9J4M9EAdEUI7ZqZhVrkzZJawFslTegPvR/gFMiSxEYBW2PX7oPIROWTe+JsIHzoygS/6fDTwjiq/Bv8s8BmJAOfR2x6BxnMW1dDBIyxrTkbnt/VzGqX6PwIgjhxCX0MGXEeO9xh912t4IIAo5nfAj2o0kAaqeDLb341hHNcDf/QEoAvsI8lCA4nW5D/iAE5558ABxR/O/SDCD3a/DCuZ83q/E8HyDZ/mVAF2pCEoKcizdj5DJEIaVfAnlgJXwT/lApxS3wzoM2DLTNSK8mfHE+UvtS/A9apxM6fwlMeW81vJ5WrnsREAA/W2LQHsVMyfGKez/gr8Q1ignEXm8V8PzFXXYIHJUmY2mWbIwPq/EvWEzkzeTJuQNMgg2XEzIJwJb6rjHgp7zjrYI43D3MryX8EBWHZ+VvUtEmGAbseAGUSPWwT/2apvglntOAv0bRwDWRnAXdYmM/BkEvKpgZm8tEeC7nWH6QhgRvVdkColt9rKcT1ioC4gsP0V8LttjUnMwFkBvjXJhu2EFGcBEk3saL8cN5uHmD3PaMpnzzMax9v/GMc4cn5n9N0IANXXBWnmPQCi0Enwb8AO2mbAXwFw1fJXiKQBxLg7FYJAR8aGiyboZfvVwNFxMhN1ZoyZPplzie5hZYzXve3y9RICEBAOZJAEdQnQxpiuG3DWBWA//RnJhu5TdyskFTIDKwBPtU2qfwQGb3/Ut/utEo0TTUxczPSd6ZMF5pVjZ88hanfkHDcCiAC7HSAqFQJthi4icAlU8YMyImPtAcAOmLBtCHzCHikwR6GEvtMnVxQY6ZFD2vMt8TDTjFN5yj5Xgisa29t/BNSV4y5f/6nj04ADABNZfI8kqJor5XcVPwF+D7RybimSgF/PHDNQ5YhAPCC2vkl3EYF6VvlpP7VxZpJW+lTasntbAYLVduYcKse9evzoXJav+9RX6wBkMnUKfgH4U+VFDcTkcmANCAR/SBIF8M+CPOUUCDnijZwB9UyfDlSJmZpo0s3HTPtMm7McRMkNRcgK9s9e18HDDt03AugArx7qMfftQ0XKP+MmvD4U4HguhDi8PpV9mfUGTJFToJdrMGaGNWHO2u46iYCQjgAwC4RsuyxRZoA0c8xo3CvGjI7p3dvla4kD2Dqom06JIOsOEs8A4A9jOZCzwV9yBKpxBtSZNt01JY5h3cwzicA7p84VZGZech1AFhjZdjPneYTIop+iet7ReGed60YAFuBc9T8R/IPiF2N+Rh6RWtM+xEmIw/EmlEckacA6KnsGuL0JaO5LJv2ykztqF+2fBXV23LNApcc5cnyPCM4Yd/kv6ACyoM62q7wSTD+BaDiQlAuYLBNSIBeAGRGBSQbkTlZAf0bb4dySbqQ62TOTNtPGDVkIarJjnkkCR45Z/V1nHMPa5xUBwEQ/TfnhF3DHJC8TYa7gKPhLqg8Hi4Bd3W9ZbDZhzgB3ZYx2bs7szUzsqM3R/Y/pBqJzPZM0HgP4eD0bAaTi/WxeoBDvD6SQIAzG/K1bslJgEUF3o48+XUhi32EiFev8WYKYAjzOPBCDSFkicHj7o75Zlc+MQy4vurS2vzp+9ryvtveZ81i+5lPGMiBT3zRJ7J3Tig9UHvVxHYC6SxmQm22csVwC2q8lcgTbGGRWHQF4tq83KbYxjNkegWAW6NG4mUk84wYyx50Zt3K+FgFUzu2o+9gIIALeVeBHuxmdQxb8VeAP48IAEZCn9zvHsCZQFuDZdvQ4CeWPJudTE0F0fjNOoDLmEQKoHmfmWjRhLF8dOQA1KVygFpKDrwP4B7IwgDkNdOYIDJBlgXt2O7wPenJEE3IG7DN9qhM9Ou8rx5slgMo5zzoT5hY2AjBBfTL48cfZhs6+OhzOvANtArBpR5AA5mEiIHc5GjPrCLLEcIXyW5O3uj07sTNgybTJgjU7Vna8KtEebe/1X/6z5QAmwT+AnL1g9CD4hTzcsMAiDba9mPCLQEv3G2RlTfoMoDNtvEnZ+quBZlR6Buwzx7lCvTMAz7SZIYDsuFlyZCrvnddGAIMDCMDfgbxCFIkKgUcg2q6m1X3/VWj7yTUD7Ec1iSHhLrJEcAT0dLIVKxHRRKwSQQSAq/dH15PdX2030z76LRj4oz7LV2kHQJRqIAgB1GOD31DRChF0bR3lM8GcKO91fYvuwmJr73y8yeQSRlL5zwL1rOJHk/jo/oxyR8e4GtDZ41fPoyeAQhKvVBk4Q/kD8FdIYLvhCTLxQozIAWzDBwCLQB3tj87BnQwTyl8hgkrbzKSNAHD1/gxJZNtkrhfVPLo2rfyV9hsBlMH8RMpfBjn8MpbyZ8asEEEbT/1GFZWOgB/tD13EBcpfBfwVbiCa+FfvrwA7OpfKWLNksZ7D8p8+lFwI9AS2H1U0A1Rp47YlwLTaTwF/7xSB9Oj+I+pfeX15SCYGyWYm5etGAhlQPmabqxwFjrsRgAaO+f0k5ccTcI+dBGuaHJLjReByCSNQ16PAj/qHgIUBKqrN2h7tH6ncFQQRgSoCeLQ/Gj+65gxxasufPSZrt/zHrAN4jcCfBjyG4RPPCZQdgAOuCLgeqUSEFIIeZt0VQD46pjeBryCBCMRX788CNjqPCplYx9wIIHQAB8GfVvwT3gNAgTQBflflme0l7qJCIDMgzwCvtQmcSZpECi82rTiECBTVsWbHi/pl9kdtzgT20bGW/xA5gNcc/K4bOAh8D8DdD3/kPygplhVLoL9Q+TPnESlUFdTV9rPOIgLw0f1HQRv9rjpE8I63EYDpAF5D8LuAP2j5o7GpSkMn/UNXvlfaZtxCa3Oh8lcAWWk7C9yzjpEFmAes2X3ZY2dIKNNm+feWA3hC8FeASNuS9QxZNbeOTfur38i6edkxI2BnVFc7kyPWPnO8yvhntI0m9WOSwBGQRy7g6P4skWwEMDiASfDjzTFdxX5m3f4CYCNyyCzwicZIkQUBv6fiFYWvtDVB9cjKnyWLqrqfBehZsM4CcbZfFrjR+BFRynGWf6cdwCT4GahSJBCAPwJrtx++6GOnQK3icVO5T3p+oAL0qG13fYScvImVAW/p+CoIzYxfPb8qkUSAuIIgZseMzjWzP9NmPb+NABpYXgPwlwAPE02vZjwT8BHJsMn7ZG6AzLoMAM9qU7H5Z6j7GWNkVLd6nCwAFVe2r5HCn7V/+crVAVSeAUALbyjhrPJ7LsIC9NaHKN4lDsBQVtMpOI7CIyg2ebxjzKr/DOgzfSok8NhtI2CeCfQjID3SN7pG3L985cvEOgAE/ZFXfSceCio7AMO1uIShriflFhySqQL2DMKgx0yofwbAnnupALYCpsx5PUaY8H4ILSoAjxzG8hUvi88C7Ee3VB5PjrZJuA02BgVp4EBSwM7E/cn1BBVV90A2tQ86RQCOCCuz/ygRZAF/lETOBLSnypXz9Igssy8igIp7WP7tTgAhcCfVuyOBE8DfLq4A/shVuERhAGsKpBeFBNH/gmRNqogoov2PRQJHj/MYJDBDDkeAPHs8fcxGAJaiVwHMwLZtS4Df7Kst+8HKgQX44fj7hizYz24XKbH8rmjzItAe3R+dU9WmZ53AB5UEZoE8228ggH+TdQAFADMgpQhGAZ0SAlHkSOGj/VZ4MRNCZPvMtuv6JQgqA9gqKWTBmAV3tl32uGcpvgWy6vZZpT8L5CgQlAA85a2qtwZ6RflDB5AEfwT4aL+21Fb7LIhn+kfAzfzHIhVgR22j8zmq/BVQZc61SgKV41fH9n6bWXI4q9/y5SoJiAMfBb9Xm7ccwXB8cQVE7QayIW8groI0s5KwOmYEHm9Cm/suUP+MEp/V5oiaV8B6VdsZEphR9Jk+FXLYCMAE0oTtb2OpCZoBq+kAjLFMsgDP4x33TOsfugohMnJuEUEM56lmRaSIV+/PnP8RwGfHrxzjyrZnksPlBPBlRhlwxrpnwW8CnWXJC0RymBCS5b4zwV5Wf+hwBNhH+lqW9rHdwVF1P9r/dQZ6ljiWlQC0SjIbPLRRilYFv0cC7Yc9WOrLAFWf94y9n+ljnZurdie8YnzquMS9PAUJHAVshqCs63oMsFeuzzvPaB8eZ/lS7QCU4jJVNckgUGurH1XuiVJfilSYFTdUtUIgR0nA67/tU7OjouBll2GEKVnQZ4EWXUPFps8es3KM15EEskoPt3T7KP02AojUO0UCk+CnoCWAzII7Au2w3yG8o6COzoUBioKCnKPrFBjJqRlQcQLVY2WJIjNuBaCvIwlUVX0G0NVjdATwMXEAAYBdEnhC8Ecgc/efGPNH5xFNdhOQRdt/ptpHCh3tj675CFE8JTFUjv2UriFz7GUlgOp/DNKRwUHwdxPfUeMjDoCCq5BfOOoEZvpr2x+BLavolXEyAM6obnTMzHEqoMuc09HxKv2rbTPAVYZO/ydUbXfkKP4/BnecprBuissAAAAASUVORK5CYII=";
return TextureTools;
}());
BABYLON.TextureTools = TextureTools;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.textureTools.js.map
var BABYLON;
(function (BABYLON) {
var FramingBehavior = /** @class */ (function () {
function FramingBehavior() {
this._mode = FramingBehavior.FitFrustumSidesMode;
this._radiusScale = 1.0;
this._positionScale = 0.5;
this._defaultElevation = 0.3;
this._elevationReturnTime = 1500;
this._elevationReturnWaitTime = 1000;
this._zoomStopsAnimation = false;
this._framingTime = 1500;
this._isPointerDown = false;
this._lastInteractionTime = -Infinity;
// Framing control
this._animatables = new Array();
this._betaIsAnimating = false;
}
Object.defineProperty(FramingBehavior.prototype, "name", {
get: function () {
return "Framing";
},
enumerable: true,
configurable: true
});
Object.defineProperty(FramingBehavior.prototype, "mode", {
/**
* Gets current mode used by the behavior.
*/
get: function () {
return this._mode;
},
/**
* Sets the current mode used by the behavior
*/
set: function (mode) {
this._mode = mode;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FramingBehavior.prototype, "radiusScale", {
/**
* Gets the scale applied to the radius
*/
get: function () {
return this._radiusScale;
},
/**
* Sets the scale applied to the radius (1 by default)
*/
set: function (radius) {
this._radiusScale = radius;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FramingBehavior.prototype, "positionScale", {
/**
* Gets the scale to apply on Y axis to position camera focus. 0.5 by default which means the center of the bounding box.
*/
get: function () {
return this._positionScale;
},
/**
* Sets the scale to apply on Y axis to position camera focus. 0.5 by default which means the center of the bounding box.
*/
set: function (scale) {
this._positionScale = scale;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FramingBehavior.prototype, "defaultElevation", {
/**
* Gets the angle above/below the horizontal plane to return to when the return to default elevation idle
* behaviour is triggered, in radians.
*/
get: function () {
return this._defaultElevation;
},
/**
* Sets the angle above/below the horizontal plane to return to when the return to default elevation idle
* behaviour is triggered, in radians.
*/
set: function (elevation) {
this._defaultElevation = elevation;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FramingBehavior.prototype, "elevationReturnTime", {
/**
* Gets the time (in milliseconds) taken to return to the default beta position.
* Negative value indicates camera should not return to default.
*/
get: function () {
return this._elevationReturnTime;
},
/**
* Sets the time (in milliseconds) taken to return to the default beta position.
* Negative value indicates camera should not return to default.
*/
set: function (speed) {
this._elevationReturnTime = speed;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FramingBehavior.prototype, "elevationReturnWaitTime", {
/**
* Gets the delay (in milliseconds) taken before the camera returns to the default beta position.
*/
get: function () {
return this._elevationReturnWaitTime;
},
/**
* Sets the delay (in milliseconds) taken before the camera returns to the default beta position.
*/
set: function (time) {
this._elevationReturnWaitTime = time;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FramingBehavior.prototype, "zoomStopsAnimation", {
/**
* Gets the flag that indicates if user zooming should stop animation.
*/
get: function () {
return this._zoomStopsAnimation;
},
/**
* Sets the flag that indicates if user zooming should stop animation.
*/
set: function (flag) {
this._zoomStopsAnimation = flag;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FramingBehavior.prototype, "framingTime", {
/**
* Gets the transition time when framing the mesh, in milliseconds
*/
get: function () {
return this._framingTime;
},
/**
* Sets the transition time when framing the mesh, in milliseconds
*/
set: function (time) {
this._framingTime = time;
},
enumerable: true,
configurable: true
});
FramingBehavior.prototype.init = function () {
// Do notihng
};
FramingBehavior.prototype.attach = function (camera) {
var _this = this;
this._attachedCamera = camera;
var scene = this._attachedCamera.getScene();
FramingBehavior.EasingFunction.setEasingMode(FramingBehavior.EasingMode);
this._onPrePointerObservableObserver = scene.onPrePointerObservable.add(function (pointerInfoPre) {
if (pointerInfoPre.type === BABYLON.PointerEventTypes.POINTERDOWN) {
_this._isPointerDown = true;
return;
}
if (pointerInfoPre.type === BABYLON.PointerEventTypes.POINTERUP) {
_this._isPointerDown = false;
}
});
this._onMeshTargetChangedObserver = camera.onMeshTargetChangedObservable.add(function (mesh) {
if (mesh) {
_this.zoomOnMesh(mesh);
}
});
this._onAfterCheckInputsObserver = camera.onAfterCheckInputsObservable.add(function () {
// Stop the animation if there is user interaction and the animation should stop for this interaction
_this._applyUserInteraction();
// Maintain the camera above the ground. If the user pulls the camera beneath the ground plane, lift it
// back to the default position after a given timeout
_this._maintainCameraAboveGround();
});
};
FramingBehavior.prototype.detach = function () {
if (!this._attachedCamera) {
return;
}
var scene = this._attachedCamera.getScene();
if (this._onPrePointerObservableObserver) {
scene.onPrePointerObservable.remove(this._onPrePointerObservableObserver);
}
if (this._onAfterCheckInputsObserver) {
this._attachedCamera.onAfterCheckInputsObservable.remove(this._onAfterCheckInputsObserver);
}
if (this._onMeshTargetChangedObserver) {
this._attachedCamera.onMeshTargetChangedObservable.remove(this._onMeshTargetChangedObserver);
}
this._attachedCamera = null;
};
/**
* Targets the given mesh and updates zoom level accordingly.
* @param mesh The mesh to target.
* @param radius Optional. If a cached radius position already exists, overrides default.
* @param framingPositionY Position on mesh to center camera focus where 0 corresponds bottom of its bounding box and 1, the top
* @param focusOnOriginXZ Determines if the camera should focus on 0 in the X and Z axis instead of the mesh
* @param onAnimationEnd Callback triggered at the end of the framing animation
*/
FramingBehavior.prototype.zoomOnMesh = function (mesh, focusOnOriginXZ, onAnimationEnd) {
if (focusOnOriginXZ === void 0) { focusOnOriginXZ = false; }
if (onAnimationEnd === void 0) { onAnimationEnd = null; }
mesh.computeWorldMatrix(true);
var boundingBox = mesh.getBoundingInfo().boundingBox;
this.zoomOnBoundingInfo(boundingBox.minimumWorld, boundingBox.maximumWorld, focusOnOriginXZ, onAnimationEnd);
};
/**
* Targets the given mesh with its children and updates zoom level accordingly.
* @param mesh The mesh to target.
* @param radius Optional. If a cached radius position already exists, overrides default.
* @param framingPositionY Position on mesh to center camera focus where 0 corresponds bottom of its bounding box and 1, the top
* @param focusOnOriginXZ Determines if the camera should focus on 0 in the X and Z axis instead of the mesh
* @param onAnimationEnd Callback triggered at the end of the framing animation
*/
FramingBehavior.prototype.zoomOnMeshHierarchy = function (mesh, focusOnOriginXZ, onAnimationEnd) {
if (focusOnOriginXZ === void 0) { focusOnOriginXZ = false; }
if (onAnimationEnd === void 0) { onAnimationEnd = null; }
mesh.computeWorldMatrix(true);
var boundingBox = mesh.getHierarchyBoundingVectors(true);
this.zoomOnBoundingInfo(boundingBox.min, boundingBox.max, focusOnOriginXZ, onAnimationEnd);
};
/**
* Targets the given meshes with their children and updates zoom level accordingly.
* @param meshes The mesh to target.
* @param radius Optional. If a cached radius position already exists, overrides default.
* @param framingPositionY Position on mesh to center camera focus where 0 corresponds bottom of its bounding box and 1, the top
* @param focusOnOriginXZ Determines if the camera should focus on 0 in the X and Z axis instead of the mesh
* @param onAnimationEnd Callback triggered at the end of the framing animation
*/
FramingBehavior.prototype.zoomOnMeshesHierarchy = function (meshes, focusOnOriginXZ, onAnimationEnd) {
if (focusOnOriginXZ === void 0) { focusOnOriginXZ = false; }
if (onAnimationEnd === void 0) { onAnimationEnd = null; }
var min = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
var max = new BABYLON.Vector3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
for (var i = 0; i < meshes.length; i++) {
var boundingInfo = meshes[i].getHierarchyBoundingVectors(true);
BABYLON.Tools.CheckExtends(boundingInfo.min, min, max);
BABYLON.Tools.CheckExtends(boundingInfo.max, min, max);
}
this.zoomOnBoundingInfo(min, max, focusOnOriginXZ, onAnimationEnd);
};
/**
* Targets the given mesh and updates zoom level accordingly.
* @param mesh The mesh to target.
* @param radius Optional. If a cached radius position already exists, overrides default.
* @param framingPositionY Position on mesh to center camera focus where 0 corresponds bottom of its bounding box and 1, the top
* @param focusOnOriginXZ Determines if the camera should focus on 0 in the X and Z axis instead of the mesh
* @param onAnimationEnd Callback triggered at the end of the framing animation
*/
FramingBehavior.prototype.zoomOnBoundingInfo = function (minimumWorld, maximumWorld, focusOnOriginXZ, onAnimationEnd) {
var _this = this;
if (focusOnOriginXZ === void 0) { focusOnOriginXZ = false; }
if (onAnimationEnd === void 0) { onAnimationEnd = null; }
var zoomTarget;
if (!this._attachedCamera) {
return;
}
// Find target by interpolating from bottom of bounding box in world-space to top via framingPositionY
var bottom = minimumWorld.y;
var top = maximumWorld.y;
var zoomTargetY = bottom + (top - bottom) * this._positionScale;
var radiusWorld = maximumWorld.subtract(minimumWorld).scale(0.5);
if (focusOnOriginXZ) {
zoomTarget = new BABYLON.Vector3(0, zoomTargetY, 0);
}
else {
var centerWorld = minimumWorld.add(radiusWorld);
zoomTarget = new BABYLON.Vector3(centerWorld.x, zoomTargetY, centerWorld.z);
}
if (!this._vectorTransition) {
this._vectorTransition = BABYLON.Animation.CreateAnimation("target", BABYLON.Animation.ANIMATIONTYPE_VECTOR3, 60, FramingBehavior.EasingFunction);
}
this._betaIsAnimating = true;
var animatable = BABYLON.Animation.TransitionTo("target", zoomTarget, this._attachedCamera, this._attachedCamera.getScene(), 60, this._vectorTransition, this._framingTime);
if (animatable) {
this._animatables.push(animatable);
}
// sets the radius and lower radius bounds
// Small delta ensures camera is not always at lower zoom limit.
var radius = 0;
if (this._mode === FramingBehavior.FitFrustumSidesMode) {
var position = this._calculateLowerRadiusFromModelBoundingSphere(minimumWorld, maximumWorld);
this._attachedCamera.lowerRadiusLimit = radiusWorld.length() + this._attachedCamera.minZ;
radius = position;
}
else if (this._mode === FramingBehavior.IgnoreBoundsSizeMode) {
radius = this._calculateLowerRadiusFromModelBoundingSphere(minimumWorld, maximumWorld);
if (this._attachedCamera.lowerRadiusLimit === null) {
this._attachedCamera.lowerRadiusLimit = this._attachedCamera.minZ;
}
}
// Set sensibilities
var extend = maximumWorld.subtract(minimumWorld).length();
this._attachedCamera.panningSensibility = 5000 / extend;
this._attachedCamera.wheelPrecision = 100 / radius;
// transition to new radius
if (!this._radiusTransition) {
this._radiusTransition = BABYLON.Animation.CreateAnimation("radius", BABYLON.Animation.ANIMATIONTYPE_FLOAT, 60, FramingBehavior.EasingFunction);
}
animatable = BABYLON.Animation.TransitionTo("radius", radius, this._attachedCamera, this._attachedCamera.getScene(), 60, this._radiusTransition, this._framingTime, function () {
_this.stopAllAnimations();
if (onAnimationEnd) {
onAnimationEnd();
}
if (_this._attachedCamera) {
_this._attachedCamera.storeState();
}
});
if (animatable) {
this._animatables.push(animatable);
}
};
/**
* Calculates the lowest radius for the camera based on the bounding box of the mesh.
* @param mesh The mesh on which to base the calculation. mesh boundingInfo used to estimate necessary
* frustum width.
* @return The minimum distance from the primary mesh's center point at which the camera must be kept in order
* to fully enclose the mesh in the viewing frustum.
*/
FramingBehavior.prototype._calculateLowerRadiusFromModelBoundingSphere = function (minimumWorld, maximumWorld) {
var size = maximumWorld.subtract(minimumWorld);
var boxVectorGlobalDiagonal = size.length();
var frustumSlope = this._getFrustumSlope();
// Formula for setting distance
// (Good explanation: http://stackoverflow.com/questions/2866350/move-camera-to-fit-3d-scene)
var radiusWithoutFraming = boxVectorGlobalDiagonal * 0.5;
// Horizon distance
var radius = radiusWithoutFraming * this._radiusScale;
var distanceForHorizontalFrustum = radius * Math.sqrt(1.0 + 1.0 / (frustumSlope.x * frustumSlope.x));
var distanceForVerticalFrustum = radius * Math.sqrt(1.0 + 1.0 / (frustumSlope.y * frustumSlope.y));
var distance = Math.max(distanceForHorizontalFrustum, distanceForVerticalFrustum);
var camera = this._attachedCamera;
if (!camera) {
return 0;
}
if (camera.lowerRadiusLimit && this._mode === FramingBehavior.IgnoreBoundsSizeMode) {
// Don't exceed the requested limit
distance = distance < camera.lowerRadiusLimit ? camera.lowerRadiusLimit : distance;
}
// Don't exceed the upper radius limit
if (camera.upperRadiusLimit) {
distance = distance > camera.upperRadiusLimit ? camera.upperRadiusLimit : distance;
}
return distance;
};
/**
* Keeps the camera above the ground plane. If the user pulls the camera below the ground plane, the camera
* is automatically returned to its default position (expected to be above ground plane).
*/
FramingBehavior.prototype._maintainCameraAboveGround = function () {
var _this = this;
if (this._elevationReturnTime < 0) {
return;
}
var timeSinceInteraction = BABYLON.Tools.Now - this._lastInteractionTime;
var defaultBeta = Math.PI * 0.5 - this._defaultElevation;
var limitBeta = Math.PI * 0.5;
// Bring the camera back up if below the ground plane
if (this._attachedCamera && !this._betaIsAnimating && this._attachedCamera.beta > limitBeta && timeSinceInteraction >= this._elevationReturnWaitTime) {
this._betaIsAnimating = true;
//Transition to new position
this.stopAllAnimations();
if (!this._betaTransition) {
this._betaTransition = BABYLON.Animation.CreateAnimation("beta", BABYLON.Animation.ANIMATIONTYPE_FLOAT, 60, FramingBehavior.EasingFunction);
}
var animatabe = BABYLON.Animation.TransitionTo("beta", defaultBeta, this._attachedCamera, this._attachedCamera.getScene(), 60, this._betaTransition, this._elevationReturnTime, function () {
_this._clearAnimationLocks();
_this.stopAllAnimations();
});
if (animatabe) {
this._animatables.push(animatabe);
}
}
};
/**
* Returns the frustum slope based on the canvas ratio and camera FOV
* @returns The frustum slope represented as a Vector2 with X and Y slopes
*/
FramingBehavior.prototype._getFrustumSlope = function () {
// Calculate the viewport ratio
// Aspect Ratio is Height/Width.
var camera = this._attachedCamera;
if (!camera) {
return BABYLON.Vector2.Zero();
}
var engine = camera.getScene().getEngine();
var aspectRatio = engine.getAspectRatio(camera);
// Camera FOV is the vertical field of view (top-bottom) in radians.
// Slope of the frustum top/bottom planes in view space, relative to the forward vector.
var frustumSlopeY = Math.tan(camera.fov / 2);
// Slope of the frustum left/right planes in view space, relative to the forward vector.
// Provides the amount that one side (e.g. left) of the frustum gets wider for every unit
// along the forward vector.
var frustumSlopeX = frustumSlopeY * aspectRatio;
return new BABYLON.Vector2(frustumSlopeX, frustumSlopeY);
};
/**
* Removes all animation locks. Allows new animations to be added to any of the arcCamera properties.
*/
FramingBehavior.prototype._clearAnimationLocks = function () {
this._betaIsAnimating = false;
};
/**
* Applies any current user interaction to the camera. Takes into account maximum alpha rotation.
*/
FramingBehavior.prototype._applyUserInteraction = function () {
if (this.isUserIsMoving) {
this._lastInteractionTime = BABYLON.Tools.Now;
this.stopAllAnimations();
this._clearAnimationLocks();
}
};
/**
* Stops and removes all animations that have been applied to the camera
*/
FramingBehavior.prototype.stopAllAnimations = function () {
if (this._attachedCamera) {
this._attachedCamera.animations = [];
}
while (this._animatables.length) {
if (this._animatables[0]) {
this._animatables[0].onAnimationEnd = null;
this._animatables[0].stop();
}
this._animatables.shift();
}
};
Object.defineProperty(FramingBehavior.prototype, "isUserIsMoving", {
/**
* Gets a value indicating if the user is moving the camera
*/
get: function () {
if (!this._attachedCamera) {
return false;
}
return this._attachedCamera.inertialAlphaOffset !== 0 ||
this._attachedCamera.inertialBetaOffset !== 0 ||
this._attachedCamera.inertialRadiusOffset !== 0 ||
this._attachedCamera.inertialPanningX !== 0 ||
this._attachedCamera.inertialPanningY !== 0 ||
this._isPointerDown;
},
enumerable: true,
configurable: true
});
/**
* The easing function used by animations
*/
FramingBehavior.EasingFunction = new BABYLON.ExponentialEase();
/**
* The easing mode used by animations
*/
FramingBehavior.EasingMode = BABYLON.EasingFunction.EASINGMODE_EASEINOUT;
// Statics
/**
* The camera can move all the way towards the mesh.
*/
FramingBehavior.IgnoreBoundsSizeMode = 0;
/**
* The camera is not allowed to zoom closer to the mesh than the point at which the adjusted bounding sphere touches the frustum sides
*/
FramingBehavior.FitFrustumSidesMode = 1;
return FramingBehavior;
}());
BABYLON.FramingBehavior = FramingBehavior;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.framingBehavior.js.map
var BABYLON;
(function (BABYLON) {
/**
* Add a bouncing effect to an ArcRotateCamera when reaching a specified minimum and maximum radius
*/
var BouncingBehavior = /** @class */ (function () {
function BouncingBehavior() {
/**
* The duration of the animation, in milliseconds
*/
this.transitionDuration = 450;
/**
* Length of the distance animated by the transition when lower radius is reached
*/
this.lowerRadiusTransitionRange = 2;
/**
* Length of the distance animated by the transition when upper radius is reached
*/
this.upperRadiusTransitionRange = -2;
this._autoTransitionRange = false;
// Animations
this._radiusIsAnimating = false;
this._radiusBounceTransition = null;
this._animatables = new Array();
}
Object.defineProperty(BouncingBehavior.prototype, "name", {
get: function () {
return "Bouncing";
},
enumerable: true,
configurable: true
});
Object.defineProperty(BouncingBehavior.prototype, "autoTransitionRange", {
/**
* Gets a value indicating if the lowerRadiusTransitionRange and upperRadiusTransitionRange are defined automatically
*/
get: function () {
return this._autoTransitionRange;
},
/**
* Sets a value indicating if the lowerRadiusTransitionRange and upperRadiusTransitionRange are defined automatically
* Transition ranges will be set to 5% of the bounding box diagonal in world space
*/
set: function (value) {
var _this = this;
if (this._autoTransitionRange === value) {
return;
}
this._autoTransitionRange = value;
var camera = this._attachedCamera;
if (!camera) {
return;
}
if (value) {
this._onMeshTargetChangedObserver = camera.onMeshTargetChangedObservable.add(function (mesh) {
if (!mesh) {
return;
}
mesh.computeWorldMatrix(true);
var diagonal = mesh.getBoundingInfo().diagonalLength;
_this.lowerRadiusTransitionRange = diagonal * 0.05;
_this.upperRadiusTransitionRange = diagonal * 0.05;
});
}
else if (this._onMeshTargetChangedObserver) {
camera.onMeshTargetChangedObservable.remove(this._onMeshTargetChangedObserver);
}
},
enumerable: true,
configurable: true
});
BouncingBehavior.prototype.init = function () {
// Do notihng
};
BouncingBehavior.prototype.attach = function (camera) {
var _this = this;
this._attachedCamera = camera;
this._onAfterCheckInputsObserver = camera.onAfterCheckInputsObservable.add(function () {
if (!_this._attachedCamera) {
return;
}
// Add the bounce animation to the lower radius limit
if (_this._isRadiusAtLimit(_this._attachedCamera.lowerRadiusLimit)) {
_this._applyBoundRadiusAnimation(_this.lowerRadiusTransitionRange);
}
// Add the bounce animation to the upper radius limit
if (_this._isRadiusAtLimit(_this._attachedCamera.upperRadiusLimit)) {
_this._applyBoundRadiusAnimation(_this.upperRadiusTransitionRange);
}
});
};
BouncingBehavior.prototype.detach = function () {
if (!this._attachedCamera) {
return;
}
if (this._onAfterCheckInputsObserver) {
this._attachedCamera.onAfterCheckInputsObservable.remove(this._onAfterCheckInputsObserver);
}
if (this._onMeshTargetChangedObserver) {
this._attachedCamera.onMeshTargetChangedObservable.remove(this._onMeshTargetChangedObserver);
}
this._attachedCamera = null;
};
/**
* Checks if the camera radius is at the specified limit. Takes into account animation locks.
* @param radiusLimit The limit to check against.
* @return Bool to indicate if at limit.
*/
BouncingBehavior.prototype._isRadiusAtLimit = function (radiusLimit) {
if (!this._attachedCamera) {
return false;
}
if (this._attachedCamera.radius === radiusLimit && !this._radiusIsAnimating) {
return true;
}
return false;
};
/**
* Applies an animation to the radius of the camera, extending by the radiusDelta.
* @param radiusDelta The delta by which to animate to. Can be negative.
*/
BouncingBehavior.prototype._applyBoundRadiusAnimation = function (radiusDelta) {
var _this = this;
if (!this._attachedCamera) {
return;
}
if (!this._radiusBounceTransition) {
BouncingBehavior.EasingFunction.setEasingMode(BouncingBehavior.EasingMode);
this._radiusBounceTransition = BABYLON.Animation.CreateAnimation("radius", BABYLON.Animation.ANIMATIONTYPE_FLOAT, 60, BouncingBehavior.EasingFunction);
}
// Prevent zoom until bounce has completed
this._cachedWheelPrecision = this._attachedCamera.wheelPrecision;
this._attachedCamera.wheelPrecision = Infinity;
this._attachedCamera.inertialRadiusOffset = 0;
// Animate to the radius limit
this.stopAllAnimations();
this._radiusIsAnimating = true;
var animatable = BABYLON.Animation.TransitionTo("radius", this._attachedCamera.radius + radiusDelta, this._attachedCamera, this._attachedCamera.getScene(), 60, this._radiusBounceTransition, this.transitionDuration, function () { return _this._clearAnimationLocks(); });
if (animatable) {
this._animatables.push(animatable);
}
};
/**
* Removes all animation locks. Allows new animations to be added to any of the camera properties.
*/
BouncingBehavior.prototype._clearAnimationLocks = function () {
this._radiusIsAnimating = false;
if (this._attachedCamera) {
this._attachedCamera.wheelPrecision = this._cachedWheelPrecision;
}
};
/**
* Stops and removes all animations that have been applied to the camera
*/
BouncingBehavior.prototype.stopAllAnimations = function () {
if (this._attachedCamera) {
this._attachedCamera.animations = [];
}
while (this._animatables.length) {
this._animatables[0].onAnimationEnd = null;
this._animatables[0].stop();
this._animatables.shift();
}
};
/**
* The easing function used by animations
*/
BouncingBehavior.EasingFunction = new BABYLON.BackEase(0.3);
/**
* The easing mode used by animations
*/
BouncingBehavior.EasingMode = BABYLON.EasingFunction.EASINGMODE_EASEOUT;
return BouncingBehavior;
}());
BABYLON.BouncingBehavior = BouncingBehavior;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.bouncingBehavior.js.map
var BABYLON;
(function (BABYLON) {
var AutoRotationBehavior = /** @class */ (function () {
function AutoRotationBehavior() {
this._zoomStopsAnimation = false;
this._idleRotationSpeed = 0.05;
this._idleRotationWaitTime = 2000;
this._idleRotationSpinupTime = 2000;
this._isPointerDown = false;
this._lastFrameTime = null;
this._lastInteractionTime = -Infinity;
this._cameraRotationSpeed = 0;
this._lastFrameRadius = 0;
}
Object.defineProperty(AutoRotationBehavior.prototype, "name", {
get: function () {
return "AutoRotation";
},
enumerable: true,
configurable: true
});
Object.defineProperty(AutoRotationBehavior.prototype, "zoomStopsAnimation", {
/**
* Gets the flag that indicates if user zooming should stop animation.
*/
get: function () {
return this._zoomStopsAnimation;
},
/**
* Sets the flag that indicates if user zooming should stop animation.
*/
set: function (flag) {
this._zoomStopsAnimation = flag;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AutoRotationBehavior.prototype, "idleRotationSpeed", {
/**
* Gets the default speed at which the camera rotates around the model.
*/
get: function () {
return this._idleRotationSpeed;
},
/**
* Sets the default speed at which the camera rotates around the model.
*/
set: function (speed) {
this._idleRotationSpeed = speed;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AutoRotationBehavior.prototype, "idleRotationWaitTime", {
/**
* Gets the time (milliseconds) to wait after user interaction before the camera starts rotating.
*/
get: function () {
return this._idleRotationWaitTime;
},
/**
* Sets the time (in milliseconds) to wait after user interaction before the camera starts rotating.
*/
set: function (time) {
this._idleRotationWaitTime = time;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AutoRotationBehavior.prototype, "idleRotationSpinupTime", {
/**
* Gets the time (milliseconds) to take to spin up to the full idle rotation speed.
*/
get: function () {
return this._idleRotationSpinupTime;
},
/**
* Sets the time (milliseconds) to take to spin up to the full idle rotation speed.
*/
set: function (time) {
this._idleRotationSpinupTime = time;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AutoRotationBehavior.prototype, "rotationInProgress", {
/**
* Gets a value indicating if the camera is currently rotating because of this behavior
*/
get: function () {
return Math.abs(this._cameraRotationSpeed) > 0;
},
enumerable: true,
configurable: true
});
AutoRotationBehavior.prototype.init = function () {
// Do notihng
};
AutoRotationBehavior.prototype.attach = function (camera) {
var _this = this;
this._attachedCamera = camera;
var scene = this._attachedCamera.getScene();
this._onPrePointerObservableObserver = scene.onPrePointerObservable.add(function (pointerInfoPre) {
if (pointerInfoPre.type === BABYLON.PointerEventTypes.POINTERDOWN) {
_this._isPointerDown = true;
return;
}
if (pointerInfoPre.type === BABYLON.PointerEventTypes.POINTERUP) {
_this._isPointerDown = false;
}
});
this._onAfterCheckInputsObserver = camera.onAfterCheckInputsObservable.add(function () {
var now = BABYLON.Tools.Now;
var dt = 0;
if (_this._lastFrameTime != null) {
dt = now - _this._lastFrameTime;
}
_this._lastFrameTime = now;
// Stop the animation if there is user interaction and the animation should stop for this interaction
_this._applyUserInteraction();
var timeToRotation = now - _this._lastInteractionTime - _this._idleRotationWaitTime;
var scale = Math.max(Math.min(timeToRotation / (_this._idleRotationSpinupTime), 1), 0);
_this._cameraRotationSpeed = _this._idleRotationSpeed * scale;
// Step camera rotation by rotation speed
if (_this._attachedCamera) {
_this._attachedCamera.alpha -= _this._cameraRotationSpeed * (dt / 1000);
}
});
};
AutoRotationBehavior.prototype.detach = function () {
if (!this._attachedCamera) {
return;
}
var scene = this._attachedCamera.getScene();
if (this._onPrePointerObservableObserver) {
scene.onPrePointerObservable.remove(this._onPrePointerObservableObserver);
}
this._attachedCamera.onAfterCheckInputsObservable.remove(this._onAfterCheckInputsObserver);
this._attachedCamera = null;
};
/**
* Returns true if user is scrolling.
* @return true if user is scrolling.
*/
AutoRotationBehavior.prototype._userIsZooming = function () {
if (!this._attachedCamera) {
return false;
}
return this._attachedCamera.inertialRadiusOffset !== 0;
};
AutoRotationBehavior.prototype._shouldAnimationStopForInteraction = function () {
if (!this._attachedCamera) {
return false;
}
var zoomHasHitLimit = false;
if (this._lastFrameRadius === this._attachedCamera.radius && this._attachedCamera.inertialRadiusOffset !== 0) {
zoomHasHitLimit = true;
}
// Update the record of previous radius - works as an approx. indicator of hitting radius limits
this._lastFrameRadius = this._attachedCamera.radius;
return this._zoomStopsAnimation ? zoomHasHitLimit : this._userIsZooming();
};
/**
* Applies any current user interaction to the camera. Takes into account maximum alpha rotation.
*/
AutoRotationBehavior.prototype._applyUserInteraction = function () {
if (this._userIsMoving() && !this._shouldAnimationStopForInteraction()) {
this._lastInteractionTime = BABYLON.Tools.Now;
}
};
// Tools
AutoRotationBehavior.prototype._userIsMoving = function () {
if (!this._attachedCamera) {
return false;
}
return this._attachedCamera.inertialAlphaOffset !== 0 ||
this._attachedCamera.inertialBetaOffset !== 0 ||
this._attachedCamera.inertialRadiusOffset !== 0 ||
this._attachedCamera.inertialPanningX !== 0 ||
this._attachedCamera.inertialPanningY !== 0 ||
this._isPointerDown;
};
return AutoRotationBehavior;
}());
BABYLON.AutoRotationBehavior = AutoRotationBehavior;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.autoRotationBehavior.js.map
var BABYLON;
(function (BABYLON) {
/**
* This class can be used to get instrumentation data from a Babylon engine
*/
var EngineInstrumentation = /** @class */ (function () {
function EngineInstrumentation(engine) {
this.engine = engine;
this._captureGPUFrameTime = false;
this._gpuFrameTime = new BABYLON.PerfCounter();
this._captureShaderCompilationTime = false;
this._shaderCompilationTime = new BABYLON.PerfCounter();
// Observers
this._onBeginFrameObserver = null;
this._onEndFrameObserver = null;
this._onBeforeShaderCompilationObserver = null;
this._onAfterShaderCompilationObserver = null;
}
Object.defineProperty(EngineInstrumentation.prototype, "gpuFrameTimeCounter", {
// Properties
/**
* Gets the perf counter used for GPU frame time
*/
get: function () {
return this._gpuFrameTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EngineInstrumentation.prototype, "captureGPUFrameTime", {
/**
* Gets the GPU frame time capture status
*/
get: function () {
return this._captureGPUFrameTime;
},
/**
* Enable or disable the GPU frame time capture
*/
set: function (value) {
var _this = this;
if (value === this._captureGPUFrameTime) {
return;
}
this._captureGPUFrameTime = value;
if (value) {
this._onBeginFrameObserver = this.engine.onBeginFrameObservable.add(function () {
if (!_this._gpuFrameTimeToken) {
_this._gpuFrameTimeToken = _this.engine.startTimeQuery();
}
});
this._onEndFrameObserver = this.engine.onEndFrameObservable.add(function () {
if (!_this._gpuFrameTimeToken) {
return;
}
var time = _this.engine.endTimeQuery(_this._gpuFrameTimeToken);
if (time > -1) {
_this._gpuFrameTimeToken = null;
_this._gpuFrameTime.fetchNewFrame();
_this._gpuFrameTime.addCount(time, true);
}
});
}
else {
this.engine.onBeginFrameObservable.remove(this._onBeginFrameObserver);
this._onBeginFrameObserver = null;
this.engine.onEndFrameObservable.remove(this._onEndFrameObserver);
this._onEndFrameObserver = null;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(EngineInstrumentation.prototype, "shaderCompilationTimeCounter", {
/**
* Gets the perf counter used for shader compilation time
*/
get: function () {
return this._shaderCompilationTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EngineInstrumentation.prototype, "captureShaderCompilationTime", {
/**
* Gets the shader compilation time capture status
*/
get: function () {
return this._captureShaderCompilationTime;
},
/**
* Enable or disable the shader compilation time capture
*/
set: function (value) {
var _this = this;
if (value === this._captureShaderCompilationTime) {
return;
}
this._captureShaderCompilationTime = value;
if (value) {
this._onBeforeShaderCompilationObserver = this.engine.onBeforeShaderCompilationObservable.add(function () {
_this._shaderCompilationTime.fetchNewFrame();
_this._shaderCompilationTime.beginMonitoring();
});
this._onAfterShaderCompilationObserver = this.engine.onAfterShaderCompilationObservable.add(function () {
_this._shaderCompilationTime.endMonitoring();
});
}
else {
this.engine.onBeforeShaderCompilationObservable.remove(this._onBeforeShaderCompilationObserver);
this._onBeforeShaderCompilationObserver = null;
this.engine.onAfterShaderCompilationObservable.remove(this._onAfterShaderCompilationObserver);
this._onAfterShaderCompilationObserver = null;
}
},
enumerable: true,
configurable: true
});
EngineInstrumentation.prototype.dispose = function () {
this.engine.onBeginFrameObservable.remove(this._onBeginFrameObserver);
this._onBeginFrameObserver = null;
this.engine.onEndFrameObservable.remove(this._onEndFrameObserver);
this._onEndFrameObserver = null;
this.engine.onBeforeShaderCompilationObservable.remove(this._onBeforeShaderCompilationObserver);
this._onBeforeShaderCompilationObserver = null;
this.engine.onAfterShaderCompilationObservable.remove(this._onAfterShaderCompilationObserver);
this._onAfterShaderCompilationObserver = null;
this.engine = null;
};
return EngineInstrumentation;
}());
BABYLON.EngineInstrumentation = EngineInstrumentation;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.engineInstrumentation.js.map
var BABYLON;
(function (BABYLON) {
/**
* This class can be used to get instrumentation data from a Babylon engine
*/
var SceneInstrumentation = /** @class */ (function () {
function SceneInstrumentation(scene) {
var _this = this;
this.scene = scene;
this._captureActiveMeshesEvaluationTime = false;
this._activeMeshesEvaluationTime = new BABYLON.PerfCounter();
this._captureRenderTargetsRenderTime = false;
this._renderTargetsRenderTime = new BABYLON.PerfCounter();
this._captureFrameTime = false;
this._frameTime = new BABYLON.PerfCounter();
this._captureRenderTime = false;
this._renderTime = new BABYLON.PerfCounter();
this._captureInterFrameTime = false;
this._interFrameTime = new BABYLON.PerfCounter();
this._captureParticlesRenderTime = false;
this._particlesRenderTime = new BABYLON.PerfCounter();
this._captureSpritesRenderTime = false;
this._spritesRenderTime = new BABYLON.PerfCounter();
this._capturePhysicsTime = false;
this._physicsTime = new BABYLON.PerfCounter();
this._captureAnimationsTime = false;
this._animationsTime = new BABYLON.PerfCounter();
// Observers
this._onBeforeActiveMeshesEvaluationObserver = null;
this._onAfterActiveMeshesEvaluationObserver = null;
this._onBeforeRenderTargetsRenderObserver = null;
this._onAfterRenderTargetsRenderObserver = null;
this._onAfterRenderObserver = null;
this._onBeforeDrawPhaseObserver = null;
this._onAfterDrawPhaseObserver = null;
this._onBeforeAnimationsObserver = null;
this._onBeforeParticlesRenderingObserver = null;
this._onAfterParticlesRenderingObserver = null;
this._onBeforeSpritesRenderingObserver = null;
this._onAfterSpritesRenderingObserver = null;
this._onBeforePhysicsObserver = null;
this._onAfterPhysicsObserver = null;
this._onAfterAnimationsObserver = null;
// Before render
this._onBeforeAnimationsObserver = scene.onBeforeAnimationsObservable.add(function () {
if (_this._captureActiveMeshesEvaluationTime) {
_this._activeMeshesEvaluationTime.fetchNewFrame();
}
if (_this._captureRenderTargetsRenderTime) {
_this._renderTargetsRenderTime.fetchNewFrame();
}
if (_this._captureFrameTime) {
BABYLON.Tools.StartPerformanceCounter("Scene rendering");
_this._frameTime.beginMonitoring();
}
if (_this._captureInterFrameTime) {
_this._interFrameTime.endMonitoring();
}
if (_this._captureParticlesRenderTime) {
_this._particlesRenderTime.fetchNewFrame();
}
if (_this._captureSpritesRenderTime) {
_this._spritesRenderTime.fetchNewFrame();
}
if (_this._captureAnimationsTime) {
_this._animationsTime.beginMonitoring();
}
_this.scene.getEngine()._drawCalls.fetchNewFrame();
_this.scene.getEngine()._textureCollisions.fetchNewFrame();
});
// After render
this._onAfterRenderObserver = scene.onAfterRenderObservable.add(function () {
if (_this._captureFrameTime) {
BABYLON.Tools.EndPerformanceCounter("Scene rendering");
_this._frameTime.endMonitoring();
}
if (_this._captureRenderTime) {
_this._renderTime.endMonitoring(false);
}
if (_this._captureInterFrameTime) {
_this._interFrameTime.beginMonitoring();
}
});
}
Object.defineProperty(SceneInstrumentation.prototype, "activeMeshesEvaluationTimeCounter", {
// Properties
/**
* Gets the perf counter used for active meshes evaluation time
*/
get: function () {
return this._activeMeshesEvaluationTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "captureActiveMeshesEvaluationTime", {
/**
* Gets the active meshes evaluation time capture status
*/
get: function () {
return this._captureActiveMeshesEvaluationTime;
},
/**
* Enable or disable the active meshes evaluation time capture
*/
set: function (value) {
var _this = this;
if (value === this._captureActiveMeshesEvaluationTime) {
return;
}
this._captureActiveMeshesEvaluationTime = value;
if (value) {
this._onBeforeActiveMeshesEvaluationObserver = this.scene.onBeforeActiveMeshesEvaluationObservable.add(function () {
BABYLON.Tools.StartPerformanceCounter("Active meshes evaluation");
_this._activeMeshesEvaluationTime.beginMonitoring();
});
this._onAfterActiveMeshesEvaluationObserver = this.scene.onAfterActiveMeshesEvaluationObservable.add(function () {
BABYLON.Tools.EndPerformanceCounter("Active meshes evaluation");
_this._activeMeshesEvaluationTime.endMonitoring();
});
}
else {
this.scene.onBeforeActiveMeshesEvaluationObservable.remove(this._onBeforeActiveMeshesEvaluationObserver);
this._onBeforeActiveMeshesEvaluationObserver = null;
this.scene.onAfterActiveMeshesEvaluationObservable.remove(this._onAfterActiveMeshesEvaluationObserver);
this._onAfterActiveMeshesEvaluationObserver = null;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "renderTargetsRenderTimeCounter", {
/**
* Gets the perf counter used for render targets render time
*/
get: function () {
return this._renderTargetsRenderTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "captureRenderTargetsRenderTime", {
/**
* Gets the render targets render time capture status
*/
get: function () {
return this._captureRenderTargetsRenderTime;
},
/**
* Enable or disable the render targets render time capture
*/
set: function (value) {
var _this = this;
if (value === this._captureRenderTargetsRenderTime) {
return;
}
this._captureRenderTargetsRenderTime = value;
if (value) {
this._onBeforeRenderTargetsRenderObserver = this.scene.OnBeforeRenderTargetsRenderObservable.add(function () {
BABYLON.Tools.StartPerformanceCounter("Render targets rendering");
_this._renderTargetsRenderTime.beginMonitoring();
});
this._onAfterRenderTargetsRenderObserver = this.scene.OnAfterRenderTargetsRenderObservable.add(function () {
BABYLON.Tools.EndPerformanceCounter("Render targets rendering");
_this._renderTargetsRenderTime.endMonitoring(false);
});
}
else {
this.scene.OnBeforeRenderTargetsRenderObservable.remove(this._onBeforeRenderTargetsRenderObserver);
this._onBeforeRenderTargetsRenderObserver = null;
this.scene.OnAfterRenderTargetsRenderObservable.remove(this._onAfterRenderTargetsRenderObserver);
this._onAfterRenderTargetsRenderObserver = null;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "particlesRenderTimeCounter", {
/**
* Gets the perf counter used for particles render time
*/
get: function () {
return this._particlesRenderTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "captureParticlesRenderTime", {
/**
* Gets the particles render time capture status
*/
get: function () {
return this._captureParticlesRenderTime;
},
/**
* Enable or disable the particles render time capture
*/
set: function (value) {
var _this = this;
if (value === this._captureParticlesRenderTime) {
return;
}
this._captureParticlesRenderTime = value;
if (value) {
this._onBeforeParticlesRenderingObserver = this.scene.onBeforeParticlesRenderingObservable.add(function () {
BABYLON.Tools.StartPerformanceCounter("Particles");
_this._particlesRenderTime.beginMonitoring();
});
this._onAfterParticlesRenderingObserver = this.scene.onAfterParticlesRenderingObservable.add(function () {
BABYLON.Tools.EndPerformanceCounter("Particles");
_this._particlesRenderTime.endMonitoring(false);
});
}
else {
this.scene.onBeforeParticlesRenderingObservable.remove(this._onBeforeParticlesRenderingObserver);
this._onBeforeParticlesRenderingObserver = null;
this.scene.onAfterParticlesRenderingObservable.remove(this._onAfterParticlesRenderingObserver);
this._onAfterParticlesRenderingObserver = null;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "spritesRenderTimeCounter", {
/**
* Gets the perf counter used for sprites render time
*/
get: function () {
return this._spritesRenderTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "captureSpritesRenderTime", {
/**
* Gets the sprites render time capture status
*/
get: function () {
return this._captureSpritesRenderTime;
},
/**
* Enable or disable the sprites render time capture
*/
set: function (value) {
var _this = this;
if (value === this._captureSpritesRenderTime) {
return;
}
this._captureSpritesRenderTime = value;
if (value) {
this._onBeforeSpritesRenderingObserver = this.scene.onBeforeSpritesRenderingObservable.add(function () {
BABYLON.Tools.StartPerformanceCounter("Sprites");
_this._spritesRenderTime.beginMonitoring();
});
this._onAfterSpritesRenderingObserver = this.scene.onAfterSpritesRenderingObservable.add(function () {
BABYLON.Tools.EndPerformanceCounter("Sprites");
_this._spritesRenderTime.endMonitoring(false);
});
}
else {
this.scene.onBeforeSpritesRenderingObservable.remove(this._onBeforeSpritesRenderingObserver);
this._onBeforeSpritesRenderingObserver = null;
this.scene.onAfterSpritesRenderingObservable.remove(this._onAfterSpritesRenderingObserver);
this._onAfterSpritesRenderingObserver = null;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "physicsTimeCounter", {
/**
* Gets the perf counter used for physics time
*/
get: function () {
return this._physicsTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "capturePhysicsTime", {
/**
* Gets the physics time capture status
*/
get: function () {
return this._capturePhysicsTime;
},
/**
* Enable or disable the physics time capture
*/
set: function (value) {
var _this = this;
if (value === this._capturePhysicsTime) {
return;
}
this._capturePhysicsTime = value;
if (value) {
this._onBeforePhysicsObserver = this.scene.onBeforePhysicsObservable.add(function () {
BABYLON.Tools.StartPerformanceCounter("Physics");
_this._physicsTime.beginMonitoring();
});
this._onAfterPhysicsObserver = this.scene.onAfterPhysicsObservable.add(function () {
BABYLON.Tools.EndPerformanceCounter("Physics");
_this._physicsTime.endMonitoring();
});
}
else {
this.scene.onBeforePhysicsObservable.remove(this._onBeforePhysicsObserver);
this._onBeforePhysicsObserver = null;
this.scene.onAfterPhysicsObservable.remove(this._onAfterPhysicsObserver);
this._onAfterPhysicsObserver = null;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "animationsTimeCounter", {
/**
* Gets the perf counter used for animations time
*/
get: function () {
return this._animationsTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "captureAnimationsTime", {
/**
* Gets the animations time capture status
*/
get: function () {
return this._captureAnimationsTime;
},
/**
* Enable or disable the animations time capture
*/
set: function (value) {
var _this = this;
if (value === this._captureAnimationsTime) {
return;
}
this._captureAnimationsTime = value;
if (value) {
this._onAfterAnimationsObserver = this.scene.onAfterAnimationsObservable.add(function () {
_this._animationsTime.endMonitoring();
});
}
else {
this.scene.onAfterAnimationsObservable.remove(this._onAfterAnimationsObserver);
this._onAfterAnimationsObserver = null;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "frameTimeCounter", {
/**
* Gets the perf counter used for frame time capture
*/
get: function () {
return this._frameTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "captureFrameTime", {
/**
* Gets the frame time capture status
*/
get: function () {
return this._captureFrameTime;
},
/**
* Enable or disable the frame time capture
*/
set: function (value) {
this._captureFrameTime = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "interFrameTimeCounter", {
/**
* Gets the perf counter used for inter-frames time capture
*/
get: function () {
return this._interFrameTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "captureInterFrameTime", {
/**
* Gets the inter-frames time capture status
*/
get: function () {
return this._captureInterFrameTime;
},
/**
* Enable or disable the inter-frames time capture
*/
set: function (value) {
this._captureInterFrameTime = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "renderTimeCounter", {
/**
* Gets the perf counter used for render time capture
*/
get: function () {
return this._renderTime;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "captureRenderTime", {
/**
* Gets the render time capture status
*/
get: function () {
return this._captureRenderTime;
},
/**
* Enable or disable the render time capture
*/
set: function (value) {
var _this = this;
if (value === this._captureRenderTime) {
return;
}
this._captureRenderTime = value;
if (value) {
this._onBeforeDrawPhaseObserver = this.scene.onBeforeDrawPhaseObservable.add(function () {
_this._renderTime.beginMonitoring();
BABYLON.Tools.StartPerformanceCounter("Main render");
});
this._onAfterDrawPhaseObserver = this.scene.onAfterDrawPhaseObservable.add(function () {
_this._renderTime.endMonitoring(false);
BABYLON.Tools.EndPerformanceCounter("Main render");
});
}
else {
this.scene.onBeforeDrawPhaseObservable.remove(this._onBeforeDrawPhaseObserver);
this._onBeforeDrawPhaseObserver = null;
this.scene.onAfterDrawPhaseObservable.remove(this._onAfterDrawPhaseObserver);
this._onAfterDrawPhaseObserver = null;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "drawCallsCounter", {
/**
* Gets the perf counter used for draw calls
*/
get: function () {
return this.scene.getEngine()._drawCalls;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SceneInstrumentation.prototype, "textureCollisionsCounter", {
/**
* Gets the perf counter used for texture collisions
*/
get: function () {
return this.scene.getEngine()._textureCollisions;
},
enumerable: true,
configurable: true
});
SceneInstrumentation.prototype.dispose = function () {
this.scene.onAfterRenderObservable.remove(this._onAfterRenderObserver);
this._onAfterRenderObserver = null;
this.scene.onBeforeActiveMeshesEvaluationObservable.remove(this._onBeforeActiveMeshesEvaluationObserver);
this._onBeforeActiveMeshesEvaluationObserver = null;
this.scene.onAfterActiveMeshesEvaluationObservable.remove(this._onAfterActiveMeshesEvaluationObserver);
this._onAfterActiveMeshesEvaluationObserver = null;
this.scene.OnBeforeRenderTargetsRenderObservable.remove(this._onBeforeRenderTargetsRenderObserver);
this._onBeforeRenderTargetsRenderObserver = null;
this.scene.OnAfterRenderTargetsRenderObservable.remove(this._onAfterRenderTargetsRenderObserver);
this._onAfterRenderTargetsRenderObserver = null;
this.scene.onBeforeAnimationsObservable.remove(this._onBeforeAnimationsObserver);
this._onBeforeAnimationsObserver = null;
this.scene.onBeforeParticlesRenderingObservable.remove(this._onBeforeParticlesRenderingObserver);
this._onBeforeParticlesRenderingObserver = null;
this.scene.onAfterParticlesRenderingObservable.remove(this._onAfterParticlesRenderingObserver);
this._onAfterParticlesRenderingObserver = null;
this.scene.onBeforeSpritesRenderingObservable.remove(this._onBeforeSpritesRenderingObserver);
this._onBeforeSpritesRenderingObserver = null;
this.scene.onAfterSpritesRenderingObservable.remove(this._onAfterSpritesRenderingObserver);
this._onAfterSpritesRenderingObserver = null;
this.scene.onBeforeDrawPhaseObservable.remove(this._onBeforeDrawPhaseObserver);
this._onBeforeDrawPhaseObserver = null;
this.scene.onAfterDrawPhaseObservable.remove(this._onAfterDrawPhaseObserver);
this._onAfterDrawPhaseObserver = null;
this.scene.onBeforePhysicsObservable.remove(this._onBeforePhysicsObserver);
this._onBeforePhysicsObserver = null;
this.scene.onAfterPhysicsObservable.remove(this._onAfterPhysicsObserver);
this._onAfterPhysicsObserver = null;
this.scene.onAfterAnimationsObservable.remove(this._onAfterAnimationsObserver);
this._onAfterAnimationsObserver = null;
this.scene = null;
};
return SceneInstrumentation;
}());
BABYLON.SceneInstrumentation = SceneInstrumentation;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.sceneInstrumentation.js.map
var BABYLON;
(function (BABYLON) {
var _TimeToken = /** @class */ (function () {
function _TimeToken() {
this._timeElapsedQueryEnded = false;
}
return _TimeToken;
}());
BABYLON._TimeToken = _TimeToken;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.timeToken.js.map
var BABYLON;
(function (BABYLON) {
/**
* Background material defines definition.
* @ignore Mainly internal Use
*/
var BackgroundMaterialDefines = /** @class */ (function (_super) {
__extends(BackgroundMaterialDefines, _super);
/**
* Constructor of the defines.
*/
function BackgroundMaterialDefines() {
var _this = _super.call(this) || this;
/**
* True if the diffuse texture is in use.
*/
_this.DIFFUSE = false;
/**
* The direct UV channel to use.
*/
_this.DIFFUSEDIRECTUV = 0;
/**
* True if the diffuse texture is in gamma space.
*/
_this.GAMMADIFFUSE = false;
/**
* True if the diffuse texture has opacity in the alpha channel.
*/
_this.DIFFUSEHASALPHA = false;
/**
* True if you want the material to fade to transparent at grazing angle.
*/
_this.OPACITYFRESNEL = false;
/**
* True if an extra blur needs to be added in the reflection.
*/
_this.REFLECTIONBLUR = false;
/**
* True if you want the material to fade to reflection at grazing angle.
*/
_this.REFLECTIONFRESNEL = false;
/**
* True if you want the material to falloff as far as you move away from the scene center.
*/
_this.REFLECTIONFALLOFF = false;
/**
* False if the current Webgl implementation does not support the texture lod extension.
*/
_this.TEXTURELODSUPPORT = false;
/**
* True to ensure the data are premultiplied.
*/
_this.PREMULTIPLYALPHA = false;
/**
* True if the texture contains cooked RGB values and not gray scaled multipliers.
*/
_this.USERGBCOLOR = false;
/**
* True to add noise in order to reduce the banding effect.
*/
_this.NOISE = false;
/**
* is the reflection texture in BGR color scheme?
* Mainly used to solve a bug in ios10 video tag
*/
_this.REFLECTIONBGR = false;
_this.IMAGEPROCESSING = false;
_this.VIGNETTE = false;
_this.VIGNETTEBLENDMODEMULTIPLY = false;
_this.VIGNETTEBLENDMODEOPAQUE = false;
_this.TONEMAPPING = false;
_this.CONTRAST = false;
_this.COLORCURVES = false;
_this.COLORGRADING = false;
_this.COLORGRADING3D = false;
_this.SAMPLER3DGREENDEPTH = false;
_this.SAMPLER3DBGRMAP = false;
_this.IMAGEPROCESSINGPOSTPROCESS = false;
_this.EXPOSURE = false;
_this.GRAIN = false;
// Reflection.
_this.REFLECTION = false;
_this.REFLECTIONMAP_3D = false;
_this.REFLECTIONMAP_SPHERICAL = false;
_this.REFLECTIONMAP_PLANAR = false;
_this.REFLECTIONMAP_CUBIC = false;
_this.REFLECTIONMAP_PROJECTION = false;
_this.REFLECTIONMAP_SKYBOX = false;
_this.REFLECTIONMAP_EXPLICIT = false;
_this.REFLECTIONMAP_EQUIRECTANGULAR = false;
_this.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false;
_this.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false;
_this.INVERTCUBICMAP = false;
_this.REFLECTIONMAP_OPPOSITEZ = false;
_this.LODINREFLECTIONALPHA = false;
_this.GAMMAREFLECTION = false;
_this.EQUIRECTANGULAR_RELFECTION_FOV = false;
// Default BJS.
_this.MAINUV1 = false;
_this.MAINUV2 = false;
_this.UV1 = false;
_this.UV2 = false;
_this.CLIPPLANE = false;
_this.POINTSIZE = false;
_this.FOG = false;
_this.NORMAL = false;
_this.NUM_BONE_INFLUENCERS = 0;
_this.BonesPerMesh = 0;
_this.INSTANCES = false;
_this.SHADOWFLOAT = false;
_this.rebuild();
return _this;
}
return BackgroundMaterialDefines;
}(BABYLON.MaterialDefines));
/**
* Background material used to create an efficient environement around your scene.
*/
var BackgroundMaterial = /** @class */ (function (_super) {
__extends(BackgroundMaterial, _super);
/**
* Instantiates a Background Material in the given scene
* @param name The friendly name of the material
* @param scene The scene to add the material to
*/
function BackgroundMaterial(name, scene) {
var _this = _super.call(this, name, scene) || this;
/**
* Key light Color (multiply against the R channel of the environement texture)
*/
_this.primaryColor = BABYLON.Color3.White();
/**
* Key light Level (allowing HDR output of the background)
*/
_this.primaryLevel = 1;
/**
* Secondary light Color (multiply against the G channel of the environement texture)
*/
_this.secondaryColor = BABYLON.Color3.Gray();
/**
* Secondary light Level (allowing HDR output of the background)
*/
_this.secondaryLevel = 1;
/**
* Tertiary light Color (multiply against the B channel of the environement texture)
*/
_this.tertiaryColor = BABYLON.Color3.Black();
/**
* Tertiary light Level (allowing HDR output of the background)
*/
_this.tertiaryLevel = 1;
/**
* Reflection Texture used in the material.
* Should be author in a specific way for the best result (refer to the documentation).
*/
_this.reflectionTexture = null;
/**
* Reflection Texture level of blur.
*
* Can be use to reuse an existing HDR Texture and target a specific LOD to prevent authoring the
* texture twice.
*/
_this.reflectionBlur = 0;
/**
* Diffuse Texture used in the material.
* Should be author in a specific way for the best result (refer to the documentation).
*/
_this.diffuseTexture = null;
_this._shadowLights = null;
/**
* Specify the list of lights casting shadow on the material.
* All scene shadow lights will be included if null.
*/
_this.shadowLights = null;
/**
* For the lights having a blurred shadow generator, this can add a second blur pass in order to reach
* soft lighting on the background.
*/
_this.shadowBlurScale = 1;
/**
* Helps adjusting the shadow to a softer level if required.
* 0 means black shadows and 1 means no shadows.
*/
_this.shadowLevel = 0;
/**
* In case of opacity Fresnel or reflection falloff, this is use as a scene center.
* It is usually zero but might be interesting to modify according to your setup.
*/
_this.sceneCenter = BABYLON.Vector3.Zero();
/**
* This helps specifying that the material is falling off to the sky box at grazing angle.
* This helps ensuring a nice transition when the camera goes under the ground.
*/
_this.opacityFresnel = true;
/**
* This helps specifying that the material is falling off from diffuse to the reflection texture at grazing angle.
* This helps adding a mirror texture on the ground.
*/
_this.reflectionFresnel = false;
/**
* This helps specifying the falloff radius off the reflection texture from the sceneCenter.
* This helps adding a nice falloff effect to the reflection if used as a mirror for instance.
*/
_this.reflectionFalloffDistance = 0.0;
/**
* This specifies the weight of the reflection against the background in case of reflection Fresnel.
*/
_this.reflectionAmount = 1.0;
/**
* This specifies the weight of the reflection at grazing angle.
*/
_this.reflectionReflectance0 = 0.05;
/**
* This specifies the weight of the reflection at a perpendicular point of view.
*/
_this.reflectionReflectance90 = 0.5;
/**
* Helps to directly use the maps channels instead of their level.
*/
_this.useRGBColor = true;
/**
* This helps reducing the banding effect that could occur on the background.
*/
_this.enableNoise = false;
_this._fovMultiplier = 1.0;
/**
* Enable the FOV adjustment feature controlled by fovMultiplier.
* @type {boolean}
*/
_this.useEquirectangularFOV = false;
_this._maxSimultaneousLights = 4;
/**
* Number of Simultaneous lights allowed on the material.
*/
_this.maxSimultaneousLights = 4;
/**
* Keep track of the image processing observer to allow dispose and replace.
*/
_this._imageProcessingObserver = null;
/**
* Due to a bug in iOS10, video tags (which are using the background material) are in BGR and not RGB.
* Setting this flag to true (not done automatically!) will convert it back to RGB.
*/
_this.switchToBGR = false;
// Temp values kept as cache in the material.
_this._renderTargets = new BABYLON.SmartArray(16);
_this._reflectionControls = BABYLON.Vector4.Zero();
// Setup the default processing configuration to the scene.
_this._attachImageProcessingConfiguration(null);
_this.getRenderTargetTextures = function () {
_this._renderTargets.reset();
if (_this._diffuseTexture && _this._diffuseTexture.isRenderTarget) {
_this._renderTargets.push(_this._diffuseTexture);
}
if (_this._reflectionTexture && _this._reflectionTexture.isRenderTarget) {
_this._renderTargets.push(_this._reflectionTexture);
}
return _this._renderTargets;
};
return _this;
}
Object.defineProperty(BackgroundMaterial.prototype, "reflectionStandardFresnelWeight", {
/**
* Sets the reflection reflectance fresnel values according to the default standard
* empirically know to work well :-)
*/
set: function (value) {
var reflectionWeight = value;
if (reflectionWeight < 0.5) {
reflectionWeight = reflectionWeight * 2.0;
this.reflectionReflectance0 = BackgroundMaterial.StandardReflectance0 * reflectionWeight;
this.reflectionReflectance90 = BackgroundMaterial.StandardReflectance90 * reflectionWeight;
}
else {
reflectionWeight = reflectionWeight * 2.0 - 1.0;
this.reflectionReflectance0 = BackgroundMaterial.StandardReflectance0 + (1.0 - BackgroundMaterial.StandardReflectance0) * reflectionWeight;
this.reflectionReflectance90 = BackgroundMaterial.StandardReflectance90 + (1.0 - BackgroundMaterial.StandardReflectance90) * reflectionWeight;
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(BackgroundMaterial.prototype, "fovMultiplier", {
/**
* The current fov(field of view) multiplier, 0.0 - 2.0. Defaults to 1.0. Lower values "zoom in" and higher values "zoom out".
* Best used when trying to implement visual zoom effects like fish-eye or binoculars while not adjusting camera fov.
* Recommended to be keep at 1.0 except for special cases.
*/
get: function () {
return this._fovMultiplier;
},
set: function (value) {
if (isNaN(value)) {
value = 1.0;
}
this._fovMultiplier = Math.max(0.0, Math.min(2.0, value));
},
enumerable: true,
configurable: true
});
/**
* Attaches a new image processing configuration to the PBR Material.
* @param configuration (if null the scene configuration will be use)
*/
BackgroundMaterial.prototype._attachImageProcessingConfiguration = function (configuration) {
var _this = this;
if (configuration === this._imageProcessingConfiguration) {
return;
}
// Detaches observer.
if (this._imageProcessingConfiguration && this._imageProcessingObserver) {
this._imageProcessingConfiguration.onUpdateParameters.remove(this._imageProcessingObserver);
}
// Pick the scene configuration if needed.
if (!configuration) {
this._imageProcessingConfiguration = this.getScene().imageProcessingConfiguration;
}
else {
this._imageProcessingConfiguration = configuration;
}
// Attaches observer.
this._imageProcessingObserver = this._imageProcessingConfiguration.onUpdateParameters.add(function (conf) {
_this._markAllSubMeshesAsImageProcessingDirty();
});
};
Object.defineProperty(BackgroundMaterial.prototype, "imageProcessingConfiguration", {
/**
* Gets the image processing configuration used either in this material.
*/
get: function () {
return this._imageProcessingConfiguration;
},
/**
* Sets the Default image processing configuration used either in the this material.
*
* If sets to null, the scene one is in use.
*/
set: function (value) {
this._attachImageProcessingConfiguration(value);
// Ensure the effect will be rebuilt.
this._markAllSubMeshesAsTexturesDirty();
},
enumerable: true,
configurable: true
});
Object.defineProperty(BackgroundMaterial.prototype, "cameraColorCurvesEnabled", {
/**
* Gets wether the color curves effect is enabled.
*/
get: function () {
return this.imageProcessingConfiguration.colorCurvesEnabled;
},
/**
* Sets wether the color curves effect is enabled.
*/
set: function (value) {
this.imageProcessingConfiguration.colorCurvesEnabled = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BackgroundMaterial.prototype, "cameraColorGradingEnabled", {
/**
* Gets wether the color grading effect is enabled.
*/
get: function () {
return this.imageProcessingConfiguration.colorGradingEnabled;
},
/**
* Gets wether the color grading effect is enabled.
*/
set: function (value) {
this.imageProcessingConfiguration.colorGradingEnabled = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BackgroundMaterial.prototype, "cameraToneMappingEnabled", {
/**
* Gets wether tonemapping is enabled or not.
*/
get: function () {
return this._imageProcessingConfiguration.toneMappingEnabled;
},
/**
* Sets wether tonemapping is enabled or not
*/
set: function (value) {
this._imageProcessingConfiguration.toneMappingEnabled = value;
},
enumerable: true,
configurable: true
});
;
;
Object.defineProperty(BackgroundMaterial.prototype, "cameraExposure", {
/**
* The camera exposure used on this material.
* This property is here and not in the camera to allow controlling exposure without full screen post process.
* This corresponds to a photographic exposure.
*/
get: function () {
return this._imageProcessingConfiguration.exposure;
},
/**
* The camera exposure used on this material.
* This property is here and not in the camera to allow controlling exposure without full screen post process.
* This corresponds to a photographic exposure.
*/
set: function (value) {
this._imageProcessingConfiguration.exposure = value;
},
enumerable: true,
configurable: true
});
;
;
Object.defineProperty(BackgroundMaterial.prototype, "cameraContrast", {
/**
* Gets The camera contrast used on this material.
*/
get: function () {
return this._imageProcessingConfiguration.contrast;
},
/**
* Sets The camera contrast used on this material.
*/
set: function (value) {
this._imageProcessingConfiguration.contrast = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BackgroundMaterial.prototype, "cameraColorGradingTexture", {
/**
* Gets the Color Grading 2D Lookup Texture.
*/
get: function () {
return this._imageProcessingConfiguration.colorGradingTexture;
},
/**
* Sets the Color Grading 2D Lookup Texture.
*/
set: function (value) {
this.imageProcessingConfiguration.colorGradingTexture = value;
},
enumerable: true,
configurable: true
});
Object.defineProperty(BackgroundMaterial.prototype, "cameraColorCurves", {
/**
* The color grading curves provide additional color adjustmnent that is applied after any color grading transform (3D LUT).
* They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects.
* These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image;
* corresponding to low luminance, medium luminance, and high luminance areas respectively.
*/
get: function () {
return this.imageProcessingConfiguration.colorCurves;
},
/**
* The color grading curves provide additional color adjustmnent that is applied after any color grading transform (3D LUT).
* They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects.
* These are similar to controls found in many professional imaging or colorist software. The global controls are applied to the entire image. For advanced tuning, extra controls are provided to adjust the shadow, midtone and highlight areas of the image;
* corresponding to low luminance, medium luminance, and high luminance areas respectively.
*/
set: function (value) {
this.imageProcessingConfiguration.colorCurves = value;
},
enumerable: true,
configurable: true
});
/**
* The entire material has been created in order to prevent overdraw.
* @returns false
*/
BackgroundMaterial.prototype.needAlphaTesting = function () {
return true;
};
/**
* The entire material has been created in order to prevent overdraw.
* @returns true if blending is enable
*/
BackgroundMaterial.prototype.needAlphaBlending = function () {
return ((this.alpha < 0) || (this._diffuseTexture != null && this._diffuseTexture.hasAlpha));
};
/**
* Checks wether the material is ready to be rendered for a given mesh.
* @param mesh The mesh to render
* @param subMesh The submesh to check against
* @param useInstances Specify wether or not the material is used with instances
* @returns true if all the dependencies are ready (Textures, Effects...)
*/
BackgroundMaterial.prototype.isReadyForSubMesh = function (mesh, subMesh, useInstances) {
var _this = this;
if (useInstances === void 0) { useInstances = false; }
if (subMesh.effect && this.isFrozen) {
if (this._wasPreviouslyReady) {
return true;
}
}
if (!subMesh._materialDefines) {
subMesh._materialDefines = new BackgroundMaterialDefines();
}
var scene = this.getScene();
var defines = subMesh._materialDefines;
if (!this.checkReadyOnEveryCall && subMesh.effect) {
if (defines._renderId === scene.getRenderId()) {
return true;
}
}
var engine = scene.getEngine();
// Lights
BABYLON.MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, this._maxSimultaneousLights);
defines._needNormals = true;
// Textures
if (defines._areTexturesDirty) {
defines._needUVs = false;
if (scene.texturesEnabled) {
if (scene.getEngine().getCaps().textureLOD) {
defines.TEXTURELODSUPPORT = true;
}
if (this._diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
if (!this._diffuseTexture.isReadyOrNotBlocking()) {
return false;
}
BABYLON.MaterialHelper.PrepareDefinesForMergedUV(this._diffuseTexture, defines, "DIFFUSE");
defines.DIFFUSEHASALPHA = this._diffuseTexture.hasAlpha;
defines.GAMMADIFFUSE = this._diffuseTexture.gammaSpace;
defines.OPACITYFRESNEL = this._opacityFresnel;
}
else {
defines.DIFFUSE = false;
defines.DIFFUSEHASALPHA = false;
defines.GAMMADIFFUSE = false;
defines.OPACITYFRESNEL = false;
}
var reflectionTexture = this._reflectionTexture;
if (reflectionTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
if (!reflectionTexture.isReadyOrNotBlocking()) {
return false;
}
defines.REFLECTION = true;
defines.GAMMAREFLECTION = reflectionTexture.gammaSpace;
defines.REFLECTIONBLUR = this._reflectionBlur > 0;
defines.REFLECTIONMAP_OPPOSITEZ = this.getScene().useRightHandedSystem ? !reflectionTexture.invertZ : reflectionTexture.invertZ;
defines.LODINREFLECTIONALPHA = reflectionTexture.lodLevelInAlpha;
defines.EQUIRECTANGULAR_RELFECTION_FOV = this.useEquirectangularFOV;
defines.REFLECTIONBGR = this.switchToBGR;
if (reflectionTexture.coordinatesMode === BABYLON.Texture.INVCUBIC_MODE) {
defines.INVERTCUBICMAP = true;
}
defines.REFLECTIONMAP_3D = reflectionTexture.isCube;
switch (reflectionTexture.coordinatesMode) {
case BABYLON.Texture.CUBIC_MODE:
case BABYLON.Texture.INVCUBIC_MODE:
defines.REFLECTIONMAP_CUBIC = true;
break;
case BABYLON.Texture.EXPLICIT_MODE:
defines.REFLECTIONMAP_EXPLICIT = true;
break;
case BABYLON.Texture.PLANAR_MODE:
defines.REFLECTIONMAP_PLANAR = true;
break;
case BABYLON.Texture.PROJECTION_MODE:
defines.REFLECTIONMAP_PROJECTION = true;
break;
case BABYLON.Texture.SKYBOX_MODE:
defines.REFLECTIONMAP_SKYBOX = true;
break;
case BABYLON.Texture.SPHERICAL_MODE:
defines.REFLECTIONMAP_SPHERICAL = true;
break;
case BABYLON.Texture.EQUIRECTANGULAR_MODE:
defines.REFLECTIONMAP_EQUIRECTANGULAR = true;
break;
case BABYLON.Texture.FIXED_EQUIRECTANGULAR_MODE:
defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = true;
break;
case BABYLON.Texture.FIXED_EQUIRECTANGULAR_MIRRORED_MODE:
defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = true;
break;
}
if (this.reflectionFresnel) {
defines.REFLECTIONFRESNEL = true;
defines.REFLECTIONFALLOFF = this.reflectionFalloffDistance > 0;
this._reflectionControls.x = this.reflectionAmount;
this._reflectionControls.y = this.reflectionReflectance0;
this._reflectionControls.z = this.reflectionReflectance90;
this._reflectionControls.w = 1 / this.reflectionFalloffDistance;
}
else {
defines.REFLECTIONFRESNEL = false;
defines.REFLECTIONFALLOFF = false;
}
}
else {
defines.REFLECTION = false;
defines.REFLECTIONFALLOFF = false;
defines.REFLECTIONBLUR = false;
defines.REFLECTIONMAP_3D = false;
defines.REFLECTIONMAP_SPHERICAL = false;
defines.REFLECTIONMAP_PLANAR = false;
defines.REFLECTIONMAP_CUBIC = false;
defines.REFLECTIONMAP_PROJECTION = false;
defines.REFLECTIONMAP_SKYBOX = false;
defines.REFLECTIONMAP_EXPLICIT = false;
defines.REFLECTIONMAP_EQUIRECTANGULAR = false;
defines.REFLECTIONMAP_EQUIRECTANGULAR_FIXED = false;
defines.REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED = false;
defines.INVERTCUBICMAP = false;
defines.REFLECTIONMAP_OPPOSITEZ = false;
defines.LODINREFLECTIONALPHA = false;
defines.GAMMAREFLECTION = false;
}
}
defines.PREMULTIPLYALPHA = (this.alphaMode === BABYLON.Engine.ALPHA_PREMULTIPLIED || this.alphaMode === BABYLON.Engine.ALPHA_PREMULTIPLIED_PORTERDUFF);
defines.USERGBCOLOR = this._useRGBColor;
defines.NOISE = this._enableNoise;
}
if (defines._areImageProcessingDirty) {
if (!this._imageProcessingConfiguration.isReady()) {
return false;
}
this._imageProcessingConfiguration.prepareDefines(defines);
}
// Misc.
BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, this.pointsCloud, this.fogEnabled, this._shouldTurnAlphaTestOn(mesh), defines);
// Values that need to be evaluated on every frame
BABYLON.MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances);
// Attribs
if (BABYLON.MaterialHelper.PrepareDefinesForAttributes(mesh, defines, false, true, false)) {
if (mesh) {
if (!scene.getEngine().getCaps().standardDerivatives && !mesh.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
mesh.createNormals(true);
BABYLON.Tools.Warn("BackgroundMaterial: Normals have been created for the mesh: " + mesh.name);
}
}
}
// Get correct effect
if (defines.isDirty) {
defines.markAsProcessed();
scene.resetCachedMaterial();
// Fallbacks
var fallbacks = new BABYLON.EffectFallbacks();
if (defines.FOG) {
fallbacks.addFallback(0, "FOG");
}
if (defines.POINTSIZE) {
fallbacks.addFallback(1, "POINTSIZE");
}
BABYLON.MaterialHelper.HandleFallbacksForShadows(defines, fallbacks, this._maxSimultaneousLights);
if (defines.NUM_BONE_INFLUENCERS > 0) {
fallbacks.addCPUSkinningFallback(0, mesh);
}
//Attributes
var attribs = [BABYLON.VertexBuffer.PositionKind];
if (defines.NORMAL) {
attribs.push(BABYLON.VertexBuffer.NormalKind);
}
if (defines.UV1) {
attribs.push(BABYLON.VertexBuffer.UVKind);
}
if (defines.UV2) {
attribs.push(BABYLON.VertexBuffer.UV2Kind);
}
BABYLON.MaterialHelper.PrepareAttributesForBones(attribs, mesh, defines, fallbacks);
BABYLON.MaterialHelper.PrepareAttributesForInstances(attribs, defines);
var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType",
"vFogInfos", "vFogColor", "pointSize",
"vClipPlane", "mBones",
"vPrimaryColor", "vSecondaryColor", "vTertiaryColor",
"vReflectionInfos", "reflectionMatrix", "vReflectionMicrosurfaceInfos", "fFovMultiplier",
"shadowLevel", "alpha",
"vBackgroundCenter", "vReflectionControl",
"vDiffuseInfos", "diffuseMatrix",
];
var samplers = ["diffuseSampler", "reflectionSampler", "reflectionSamplerLow", "reflectionSamplerHigh"];
var uniformBuffers = ["Material", "Scene"];
BABYLON.ImageProcessingConfiguration.PrepareUniforms(uniforms, defines);
BABYLON.ImageProcessingConfiguration.PrepareSamplers(samplers, defines);
BABYLON.MaterialHelper.PrepareUniformsAndSamplersList({
uniformsNames: uniforms,
uniformBuffersNames: uniformBuffers,
samplers: samplers,
defines: defines,
maxSimultaneousLights: this._maxSimultaneousLights
});
var onCompiled = function (effect) {
if (_this.onCompiled) {
_this.onCompiled(effect);
}
_this.bindSceneUniformBuffer(effect, scene.getSceneUniformBuffer());
};
var join = defines.toString();
subMesh.setEffect(scene.getEngine().createEffect("background", {
attributes: attribs,
uniformsNames: uniforms,
uniformBuffersNames: uniformBuffers,
samplers: samplers,
defines: join,
fallbacks: fallbacks,
onCompiled: onCompiled,
onError: this.onError,
indexParameters: { maxSimultaneousLights: this._maxSimultaneousLights }
}, engine), defines);
this.buildUniformLayout();
}
if (!subMesh.effect || !subMesh.effect.isReady()) {
return false;
}
defines._renderId = scene.getRenderId();
this._wasPreviouslyReady = true;
return true;
};
/**
* Build the uniform buffer used in the material.
*/
BackgroundMaterial.prototype.buildUniformLayout = function () {
// Order is important !
this._uniformBuffer.addUniform("vPrimaryColor", 4);
this._uniformBuffer.addUniform("vSecondaryColor", 4);
this._uniformBuffer.addUniform("vTertiaryColor", 4);
this._uniformBuffer.addUniform("vDiffuseInfos", 2);
this._uniformBuffer.addUniform("vReflectionInfos", 2);
this._uniformBuffer.addUniform("diffuseMatrix", 16);
this._uniformBuffer.addUniform("reflectionMatrix", 16);
this._uniformBuffer.addUniform("vReflectionMicrosurfaceInfos", 3);
this._uniformBuffer.addUniform("fFovMultiplier", 1);
this._uniformBuffer.addUniform("pointSize", 1);
this._uniformBuffer.addUniform("shadowLevel", 1);
this._uniformBuffer.addUniform("alpha", 1);
this._uniformBuffer.addUniform("vBackgroundCenter", 3);
this._uniformBuffer.addUniform("vReflectionControl", 4);
this._uniformBuffer.create();
};
/**
* Unbind the material.
*/
BackgroundMaterial.prototype.unbind = function () {
if (this._diffuseTexture && this._diffuseTexture.isRenderTarget) {
this._uniformBuffer.setTexture("diffuseSampler", null);
}
if (this._reflectionTexture && this._reflectionTexture.isRenderTarget) {
this._uniformBuffer.setTexture("reflectionSampler", null);
}
_super.prototype.unbind.call(this);
};
/**
* Bind only the world matrix to the material.
* @param world The world matrix to bind.
*/
BackgroundMaterial.prototype.bindOnlyWorldMatrix = function (world) {
this._activeEffect.setMatrix("world", world);
};
/**
* Bind the material for a dedicated submeh (every used meshes will be considered opaque).
* @param world The world matrix to bind.
* @param subMesh The submesh to bind for.
*/
BackgroundMaterial.prototype.bindForSubMesh = function (world, mesh, subMesh) {
var scene = this.getScene();
var defines = subMesh._materialDefines;
if (!defines) {
return;
}
var effect = subMesh.effect;
if (!effect) {
return;
}
this._activeEffect = effect;
// Matrices
this.bindOnlyWorldMatrix(world);
// Bones
BABYLON.MaterialHelper.BindBonesParameters(mesh, this._activeEffect);
var mustRebind = this._mustRebind(scene, effect, mesh.visibility);
if (mustRebind) {
this._uniformBuffer.bindToEffect(effect, "Material");
this.bindViewProjection(effect);
var reflectionTexture = this._reflectionTexture;
if (!this._uniformBuffer.useUbo || !this.isFrozen || !this._uniformBuffer.isSync) {
// Texture uniforms
if (scene.texturesEnabled) {
if (this._diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
this._uniformBuffer.updateFloat2("vDiffuseInfos", this._diffuseTexture.coordinatesIndex, this._diffuseTexture.level);
BABYLON.MaterialHelper.BindTextureMatrix(this._diffuseTexture, this._uniformBuffer, "diffuse");
}
if (reflectionTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
this._uniformBuffer.updateMatrix("reflectionMatrix", reflectionTexture.getReflectionTextureMatrix());
this._uniformBuffer.updateFloat2("vReflectionInfos", reflectionTexture.level, this._reflectionBlur);
this._uniformBuffer.updateFloat3("vReflectionMicrosurfaceInfos", reflectionTexture.getSize().width, reflectionTexture.lodGenerationScale, reflectionTexture.lodGenerationOffset);
}
}
if (this.shadowLevel > 0) {
this._uniformBuffer.updateFloat("shadowLevel", this.shadowLevel);
}
this._uniformBuffer.updateFloat("alpha", this.alpha);
// Point size
if (this.pointsCloud) {
this._uniformBuffer.updateFloat("pointSize", this.pointSize);
}
this._uniformBuffer.updateColor4("vPrimaryColor", this._primaryColor, this._primaryLevel);
this._uniformBuffer.updateColor4("vSecondaryColor", this._secondaryColor, this._secondaryLevel);
this._uniformBuffer.updateColor4("vTertiaryColor", this._tertiaryColor, this._tertiaryLevel);
}
this._uniformBuffer.updateFloat("fFovMultiplier", this._fovMultiplier);
// Textures
if (scene.texturesEnabled) {
if (this._diffuseTexture && BABYLON.StandardMaterial.DiffuseTextureEnabled) {
this._uniformBuffer.setTexture("diffuseSampler", this._diffuseTexture);
}
if (reflectionTexture && BABYLON.StandardMaterial.ReflectionTextureEnabled) {
if (defines.REFLECTIONBLUR && defines.TEXTURELODSUPPORT) {
this._uniformBuffer.setTexture("reflectionSampler", reflectionTexture);
}
else if (!defines.REFLECTIONBLUR) {
this._uniformBuffer.setTexture("reflectionSampler", reflectionTexture);
}
else {
this._uniformBuffer.setTexture("reflectionSampler", reflectionTexture._lodTextureMid || reflectionTexture);
this._uniformBuffer.setTexture("reflectionSamplerLow", reflectionTexture._lodTextureLow || reflectionTexture);
this._uniformBuffer.setTexture("reflectionSamplerHigh", reflectionTexture._lodTextureHigh || reflectionTexture);
}
if (defines.REFLECTIONFRESNEL) {
this._uniformBuffer.updateFloat3("vBackgroundCenter", this.sceneCenter.x, this.sceneCenter.y, this.sceneCenter.z);
this._uniformBuffer.updateFloat4("vReflectionControl", this._reflectionControls.x, this._reflectionControls.y, this._reflectionControls.z, this._reflectionControls.w);
}
}
}
// Clip plane
BABYLON.MaterialHelper.BindClipPlane(this._activeEffect, scene);
BABYLON.MaterialHelper.BindEyePosition(effect, scene);
}
if (mustRebind || !this.isFrozen) {
if (scene.lightsEnabled) {
BABYLON.MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, this._maxSimultaneousLights, false);
}
// View
this.bindView(effect);
// Fog
BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
// image processing
this._imageProcessingConfiguration.bind(this._activeEffect);
}
this._uniformBuffer.update();
this._afterBind(mesh);
};
/**
* Dispose the material.
* @param forceDisposeEffect Force disposal of the associated effect.
* @param forceDisposeTextures Force disposal of the associated textures.
*/
BackgroundMaterial.prototype.dispose = function (forceDisposeEffect, forceDisposeTextures) {
if (forceDisposeEffect === void 0) { forceDisposeEffect = false; }
if (forceDisposeTextures === void 0) { forceDisposeTextures = false; }
if (forceDisposeTextures) {
if (this.diffuseTexture) {
this.diffuseTexture.dispose();
}
if (this.reflectionTexture) {
this.reflectionTexture.dispose();
}
}
this._renderTargets.dispose();
if (this._imageProcessingConfiguration && this._imageProcessingObserver) {
this._imageProcessingConfiguration.onUpdateParameters.remove(this._imageProcessingObserver);
}
_super.prototype.dispose.call(this, forceDisposeEffect);
};
/**
* Clones the material.
* @param name The cloned name.
* @returns The cloned material.
*/
BackgroundMaterial.prototype.clone = function (name) {
var _this = this;
return BABYLON.SerializationHelper.Clone(function () { return new BackgroundMaterial(name, _this.getScene()); }, this);
};
/**
* Serializes the current material to its JSON representation.
* @returns The JSON representation.
*/
BackgroundMaterial.prototype.serialize = function () {
var serializationObject = BABYLON.SerializationHelper.Serialize(this);
serializationObject.customType = "BABYLON.BackgroundMaterial";
return serializationObject;
};
/**
* Gets the class name of the material
* @returns "BackgroundMaterial"
*/
BackgroundMaterial.prototype.getClassName = function () {
return "BackgroundMaterial";
};
/**
* Parse a JSON input to create back a background material.
* @param source The JSON data to parse
* @param scene The scene to create the parsed material in
* @param rootUrl The root url of the assets the material depends upon
* @returns the instantiated BackgroundMaterial.
*/
BackgroundMaterial.Parse = function (source, scene, rootUrl) {
return BABYLON.SerializationHelper.Parse(function () { return new BackgroundMaterial(source.name, scene); }, source, scene, rootUrl);
};
/**
* Standard reflectance value at parallel view angle.
*/
BackgroundMaterial.StandardReflectance0 = 0.05;
/**
* Standard reflectance value at grazing angle.
*/
BackgroundMaterial.StandardReflectance90 = 0.5;
__decorate([
BABYLON.serializeAsColor3()
], BackgroundMaterial.prototype, "_primaryColor", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
], BackgroundMaterial.prototype, "primaryColor", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_primaryLevel", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
], BackgroundMaterial.prototype, "primaryLevel", void 0);
__decorate([
BABYLON.serializeAsColor3()
], BackgroundMaterial.prototype, "_secondaryColor", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
], BackgroundMaterial.prototype, "secondaryColor", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_secondaryLevel", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
], BackgroundMaterial.prototype, "secondaryLevel", void 0);
__decorate([
BABYLON.serializeAsColor3()
], BackgroundMaterial.prototype, "_tertiaryColor", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
], BackgroundMaterial.prototype, "tertiaryColor", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_tertiaryLevel", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsLightsDirty")
], BackgroundMaterial.prototype, "tertiaryLevel", void 0);
__decorate([
BABYLON.serializeAsTexture()
], BackgroundMaterial.prototype, "_reflectionTexture", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "reflectionTexture", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_reflectionBlur", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "reflectionBlur", void 0);
__decorate([
BABYLON.serializeAsTexture()
], BackgroundMaterial.prototype, "_diffuseTexture", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "diffuseTexture", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "shadowLights", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_shadowBlurScale", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "shadowBlurScale", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_shadowLevel", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "shadowLevel", void 0);
__decorate([
BABYLON.serializeAsVector3()
], BackgroundMaterial.prototype, "_sceneCenter", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "sceneCenter", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_opacityFresnel", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "opacityFresnel", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_reflectionFresnel", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "reflectionFresnel", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_reflectionFalloffDistance", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "reflectionFalloffDistance", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_reflectionAmount", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "reflectionAmount", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_reflectionReflectance0", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "reflectionReflectance0", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_reflectionReflectance90", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "reflectionReflectance90", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_useRGBColor", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "useRGBColor", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_enableNoise", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "enableNoise", void 0);
__decorate([
BABYLON.serialize()
], BackgroundMaterial.prototype, "_maxSimultaneousLights", void 0);
__decorate([
BABYLON.expandToProperty("_markAllSubMeshesAsTexturesDirty")
], BackgroundMaterial.prototype, "maxSimultaneousLights", void 0);
__decorate([
BABYLON.serializeAsImageProcessingConfiguration()
], BackgroundMaterial.prototype, "_imageProcessingConfiguration", void 0);
return BackgroundMaterial;
}(BABYLON.PushMaterial));
BABYLON.BackgroundMaterial = BackgroundMaterial;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.backgroundMaterial.js.map
var __assign = (this && this.__assign) || Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
var BABYLON;
(function (BABYLON) {
/**
* The Environment helper class can be used to add a fully featuread none expensive background to your scene.
* It includes by default a skybox and a ground relying on the BackgroundMaterial.
* It also helps with the default setup of your imageProcessing configuration.
*/
var EnvironmentHelper = /** @class */ (function () {
/**
* constructor
* @param options
* @param scene The scene to add the material to
*/
function EnvironmentHelper(options, scene) {
var _this = this;
this._errorHandler = function (message, exception) {
_this.onErrorObservable.notifyObservers({ message: message, exception: exception });
};
this._options = __assign({}, EnvironmentHelper._getDefaultOptions(), options);
this._scene = scene;
this.onErrorObservable = new BABYLON.Observable();
this._setupBackground();
this._setupImageProcessing();
}
/**
* Creates the default options for the helper.
*/
EnvironmentHelper._getDefaultOptions = function () {
return {
createGround: true,
groundSize: 15,
groundTexture: this._groundTextureCDNUrl,
groundColor: new BABYLON.Color3(0.2, 0.2, 0.3).toLinearSpace().scale(3),
groundOpacity: 0.9,
enableGroundShadow: true,
groundShadowLevel: 0.5,
enableGroundMirror: false,
groundMirrorSizeRatio: 0.3,
groundMirrorBlurKernel: 64,
groundMirrorAmount: 1,
groundMirrorFresnelWeight: 1,
groundMirrorFallOffDistance: 0,
groundMirrorTextureType: BABYLON.Engine.TEXTURETYPE_UNSIGNED_INT,
groundYBias: 0.00001,
createSkybox: true,
skyboxSize: 20,
skyboxTexture: this._skyboxTextureCDNUrl,
skyboxColor: new BABYLON.Color3(0.2, 0.2, 0.3).toLinearSpace().scale(3),
backgroundYRotation: 0,
sizeAuto: true,
rootPosition: BABYLON.Vector3.Zero(),
setupImageProcessing: true,
environmentTexture: this._environmentTextureCDNUrl,
cameraExposure: 0.8,
cameraContrast: 1.2,
toneMappingEnabled: true,
};
};
Object.defineProperty(EnvironmentHelper.prototype, "rootMesh", {
/**
* Gets the root mesh created by the helper.
*/
get: function () {
return this._rootMesh;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EnvironmentHelper.prototype, "skybox", {
/**
* Gets the skybox created by the helper.
*/
get: function () {
return this._skybox;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EnvironmentHelper.prototype, "skyboxTexture", {
/**
* Gets the skybox texture created by the helper.
*/
get: function () {
return this._skyboxTexture;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EnvironmentHelper.prototype, "skyboxMaterial", {
/**
* Gets the skybox material created by the helper.
*/
get: function () {
return this._skyboxMaterial;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EnvironmentHelper.prototype, "ground", {
/**
* Gets the ground mesh created by the helper.
*/
get: function () {
return this._ground;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EnvironmentHelper.prototype, "groundTexture", {
/**
* Gets the ground texture created by the helper.
*/
get: function () {
return this._groundTexture;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EnvironmentHelper.prototype, "groundMirror", {
/**
* Gets the ground mirror created by the helper.
*/
get: function () {
return this._groundMirror;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EnvironmentHelper.prototype, "groundMirrorRenderList", {
/**
* Gets the ground mirror render list to helps pushing the meshes
* you wish in the ground reflection.
*/
get: function () {
if (this._groundMirror) {
return this._groundMirror.renderList;
}
return null;
},
enumerable: true,
configurable: true
});
Object.defineProperty(EnvironmentHelper.prototype, "groundMaterial", {
/**
* Gets the ground material created by the helper.
*/
get: function () {
return this._groundMaterial;
},
enumerable: true,
configurable: true
});
/**
* Updates the background according to the new options
* @param options
*/
EnvironmentHelper.prototype.updateOptions = function (options) {
var newOptions = __assign({}, this._options, options);
if (this._ground && !newOptions.createGround) {
this._ground.dispose();
this._ground = null;
}
if (this._groundMaterial && !newOptions.createGround) {
this._groundMaterial.dispose();
this._groundMaterial = null;
}
if (this._groundTexture) {
if (this._options.groundTexture != newOptions.groundTexture) {
this._groundTexture.dispose();
this._groundTexture = null;
}
}
if (this._skybox && !newOptions.createSkybox) {
this._skybox.dispose();
this._skybox = null;
}
if (this._skyboxMaterial && !newOptions.createSkybox) {
this._skyboxMaterial.dispose();
this._skyboxMaterial = null;
}
if (this._skyboxTexture) {
if (this._options.skyboxTexture != newOptions.skyboxTexture) {
this._skyboxTexture.dispose();
this._skyboxTexture = null;
}
}
if (this._groundMirror && !newOptions.enableGroundMirror) {
this._groundMirror.dispose();
this._groundMirror = null;
}
if (this._scene.environmentTexture) {
if (this._options.environmentTexture != newOptions.environmentTexture) {
this._scene.environmentTexture.dispose();
}
}
this._options = newOptions;
this._setupBackground();
this._setupImageProcessing();
};
/**
* Sets the primary color of all the available elements.
* @param color
*/
EnvironmentHelper.prototype.setMainColor = function (color) {
if (this.groundMaterial) {
this.groundMaterial.primaryColor = color;
}
if (this.skyboxMaterial) {
this.skyboxMaterial.primaryColor = color;
}
if (this.groundMirror) {
this.groundMirror.clearColor = new BABYLON.Color4(color.r, color.g, color.b, 1.0);
}
};
/**
* Setup the image processing according to the specified options.
*/
EnvironmentHelper.prototype._setupImageProcessing = function () {
if (this._options.setupImageProcessing) {
this._scene.imageProcessingConfiguration.contrast = this._options.cameraContrast;
this._scene.imageProcessingConfiguration.exposure = this._options.cameraExposure;
this._scene.imageProcessingConfiguration.toneMappingEnabled = this._options.toneMappingEnabled;
this._setupEnvironmentTexture();
}
};
/**
* Setup the environment texture according to the specified options.
*/
EnvironmentHelper.prototype._setupEnvironmentTexture = function () {
if (this._scene.environmentTexture) {
return;
}
if (this._options.environmentTexture instanceof BABYLON.BaseTexture) {
this._scene.environmentTexture = this._options.environmentTexture;
return;
}
var environmentTexture = BABYLON.CubeTexture.CreateFromPrefilteredData(this._options.environmentTexture, this._scene);
this._scene.environmentTexture = environmentTexture;
};
/**
* Setup the background according to the specified options.
*/
EnvironmentHelper.prototype._setupBackground = function () {
if (!this._rootMesh) {
this._rootMesh = new BABYLON.Mesh("BackgroundHelper", this._scene);
}
this._rootMesh.rotation.y = this._options.backgroundYRotation;
var sceneSize = this._getSceneSize();
if (this._options.createGround) {
this._setupGround(sceneSize);
this._setupGroundMaterial();
this._setupGroundDiffuseTexture();
if (this._options.enableGroundMirror) {
this._setupGroundMirrorTexture(sceneSize);
}
this._setupMirrorInGroundMaterial();
}
if (this._options.createSkybox) {
this._setupSkybox(sceneSize);
this._setupSkyboxMaterial();
this._setupSkyboxReflectionTexture();
}
this._rootMesh.position.x = sceneSize.rootPosition.x;
this._rootMesh.position.z = sceneSize.rootPosition.z;
this._rootMesh.position.y = sceneSize.rootPosition.y;
};
/**
* Get the scene sizes according to the setup.
*/
EnvironmentHelper.prototype._getSceneSize = function () {
var _this = this;
var groundSize = this._options.groundSize;
var skyboxSize = this._options.skyboxSize;
var rootPosition = this._options.rootPosition;
if (!this._scene.meshes || this._scene.meshes.length === 1) {
return { groundSize: groundSize, skyboxSize: skyboxSize, rootPosition: rootPosition };
}
var sceneExtends = this._scene.getWorldExtends(function (mesh) {
return (mesh !== _this._ground && mesh !== _this._rootMesh && mesh !== _this._skybox);
});
var sceneDiagonal = sceneExtends.max.subtract(sceneExtends.min);
if (this._options.sizeAuto) {
if (this._scene.activeCamera instanceof BABYLON.ArcRotateCamera &&
this._scene.activeCamera.upperRadiusLimit) {
groundSize = this._scene.activeCamera.upperRadiusLimit * 2;
skyboxSize = groundSize;
}
var sceneDiagonalLenght = sceneDiagonal.length();
if (sceneDiagonalLenght > groundSize) {
groundSize = sceneDiagonalLenght * 2;
skyboxSize = groundSize;
}
// 10 % bigger.
groundSize *= 1.1;
skyboxSize *= 1.5;
rootPosition = sceneExtends.min.add(sceneDiagonal.scale(0.5));
rootPosition.y = sceneExtends.min.y - this._options.groundYBias;
}
return { groundSize: groundSize, skyboxSize: skyboxSize, rootPosition: rootPosition };
};
/**
* Setup the ground according to the specified options.
*/
EnvironmentHelper.prototype._setupGround = function (sceneSize) {
var _this = this;
if (!this._ground) {
this._ground = BABYLON.Mesh.CreatePlane("BackgroundPlane", sceneSize.groundSize, this._scene);
this._ground.rotation.x = Math.PI / 2; // Face up by default.
this._ground.parent = this._rootMesh;
this._ground.onDisposeObservable.add(function () { _this._ground = null; });
}
this._ground.receiveShadows = this._options.enableGroundShadow;
};
/**
* Setup the ground material according to the specified options.
*/
EnvironmentHelper.prototype._setupGroundMaterial = function () {
if (!this._groundMaterial) {
this._groundMaterial = new BABYLON.BackgroundMaterial("BackgroundPlaneMaterial", this._scene);
}
this._groundMaterial.alpha = this._options.groundOpacity;
this._groundMaterial.alphaMode = BABYLON.Engine.ALPHA_PREMULTIPLIED_PORTERDUFF;
this._groundMaterial.shadowLevel = this._options.groundShadowLevel;
this._groundMaterial.primaryLevel = 1;
this._groundMaterial.primaryColor = this._options.groundColor;
this._groundMaterial.secondaryLevel = 0;
this._groundMaterial.tertiaryLevel = 0;
this._groundMaterial.useRGBColor = false;
this._groundMaterial.enableNoise = true;
if (this._ground) {
this._ground.material = this._groundMaterial;
}
};
/**
* Setup the ground diffuse texture according to the specified options.
*/
EnvironmentHelper.prototype._setupGroundDiffuseTexture = function () {
if (!this._groundMaterial) {
return;
}
if (this._groundTexture) {
return;
}
if (this._options.groundTexture instanceof BABYLON.BaseTexture) {
this._groundMaterial.diffuseTexture = this._options.groundTexture;
return;
}
var diffuseTexture = new BABYLON.Texture(this._options.groundTexture, this._scene, undefined, undefined, undefined, undefined, this._errorHandler);
diffuseTexture.gammaSpace = false;
diffuseTexture.hasAlpha = true;
this._groundMaterial.diffuseTexture = diffuseTexture;
};
/**
* Setup the ground mirror texture according to the specified options.
*/
EnvironmentHelper.prototype._setupGroundMirrorTexture = function (sceneSize) {
var wrapping = BABYLON.Texture.CLAMP_ADDRESSMODE;
if (!this._groundMirror) {
this._groundMirror = new BABYLON.MirrorTexture("BackgroundPlaneMirrorTexture", { ratio: this._options.groundMirrorSizeRatio }, this._scene, false, this._options.groundMirrorTextureType, BABYLON.Texture.BILINEAR_SAMPLINGMODE, true);
this._groundMirror.mirrorPlane = new BABYLON.Plane(0, -1, 0, sceneSize.rootPosition.y);
this._groundMirror.anisotropicFilteringLevel = 1;
this._groundMirror.wrapU = wrapping;
this._groundMirror.wrapV = wrapping;
this._groundMirror.gammaSpace = false;
if (this._groundMirror.renderList) {
for (var i = 0; i < this._scene.meshes.length; i++) {
var mesh = this._scene.meshes[i];
if (mesh !== this._ground &&
mesh !== this._skybox &&
mesh !== this._rootMesh) {
this._groundMirror.renderList.push(mesh);
}
}
}
}
this._groundMirror.clearColor = new BABYLON.Color4(this._options.groundColor.r, this._options.groundColor.g, this._options.groundColor.b, 1);
this._groundMirror.adaptiveBlurKernel = this._options.groundMirrorBlurKernel;
};
/**
* Setup the ground to receive the mirror texture.
*/
EnvironmentHelper.prototype._setupMirrorInGroundMaterial = function () {
if (this._groundMaterial) {
this._groundMaterial.reflectionTexture = this._groundMirror;
this._groundMaterial.reflectionFresnel = true;
this._groundMaterial.reflectionAmount = this._options.groundMirrorAmount;
this._groundMaterial.reflectionStandardFresnelWeight = this._options.groundMirrorFresnelWeight;
this._groundMaterial.reflectionFalloffDistance = this._options.groundMirrorFallOffDistance;
}
};
/**
* Setup the skybox according to the specified options.
*/
EnvironmentHelper.prototype._setupSkybox = function (sceneSize) {
var _this = this;
if (!this._skybox) {
this._skybox = BABYLON.Mesh.CreateBox("BackgroundSkybox", sceneSize.skyboxSize, this._scene, undefined, BABYLON.Mesh.BACKSIDE);
this._skybox.onDisposeObservable.add(function () { _this._skybox = null; });
}
this._skybox.parent = this._rootMesh;
};
/**
* Setup the skybox material according to the specified options.
*/
EnvironmentHelper.prototype._setupSkyboxMaterial = function () {
if (!this._skybox) {
return;
}
if (!this._skyboxMaterial) {
this._skyboxMaterial = new BABYLON.BackgroundMaterial("BackgroundSkyboxMaterial", this._scene);
}
this._skyboxMaterial.useRGBColor = false;
this._skyboxMaterial.primaryLevel = 1;
this._skyboxMaterial.primaryColor = this._options.skyboxColor;
this._skyboxMaterial.secondaryLevel = 0;
this._skyboxMaterial.tertiaryLevel = 0;
this._skyboxMaterial.enableNoise = true;
this._skybox.material = this._skyboxMaterial;
};
/**
* Setup the skybox reflection texture according to the specified options.
*/
EnvironmentHelper.prototype._setupSkyboxReflectionTexture = function () {
if (!this._skyboxMaterial) {
return;
}
if (this._skyboxTexture) {
return;
}
if (this._options.skyboxTexture instanceof BABYLON.BaseTexture) {
this._skyboxMaterial.reflectionTexture = this._skyboxTexture;
return;
}
this._skyboxTexture = new BABYLON.CubeTexture(this._options.skyboxTexture, this._scene, undefined, undefined, undefined, undefined, this._errorHandler);
this._skyboxTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
this._skyboxTexture.gammaSpace = false;
this._skyboxMaterial.reflectionTexture = this._skyboxTexture;
};
/**
* Dispose all the elements created by the Helper.
*/
EnvironmentHelper.prototype.dispose = function () {
if (this._groundMaterial) {
this._groundMaterial.dispose(true, true);
}
if (this._skyboxMaterial) {
this._skyboxMaterial.dispose(true, true);
}
this._rootMesh.dispose(false);
};
/**
* Default ground texture URL.
*/
EnvironmentHelper._groundTextureCDNUrl = "https://assets.babylonjs.com/environments/backgroundGround.png";
/**
* Default skybox texture URL.
*/
EnvironmentHelper._skyboxTextureCDNUrl = "https://assets.babylonjs.com/environments/backgroundSkybox.dds";
/**
* Default environment texture URL.
*/
EnvironmentHelper._environmentTextureCDNUrl = "https://assets.babylonjs.com/environments/environmentSpecular.dds";
return EnvironmentHelper;
}());
BABYLON.EnvironmentHelper = EnvironmentHelper;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.environmentHelper.js.map
BABYLON.Effect.ShadersStore={"defaultVertexShader":"#include<__decl__defaultVertex>\n\n#define CUSTOM_VERTEX_BEGIN\nattribute vec3 position;\n#ifdef NORMAL\nattribute vec3 normal;\n#endif\n#ifdef TANGENT\nattribute vec4 tangent;\n#endif\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#ifdef VERTEXCOLOR\nattribute vec4 color;\n#endif\n#include\n#include\n\n#include\n#ifdef MAINUV1\nvarying vec2 vMainUV1;\n#endif\n#ifdef MAINUV2\nvarying vec2 vMainUV2;\n#endif\n#if defined(DIFFUSE) && DIFFUSEDIRECTUV == 0\nvarying vec2 vDiffuseUV;\n#endif\n#if defined(AMBIENT) && AMBIENTDIRECTUV == 0\nvarying vec2 vAmbientUV;\n#endif\n#if defined(OPACITY) && OPACITYDIRECTUV == 0\nvarying vec2 vOpacityUV;\n#endif\n#if defined(EMISSIVE) && EMISSIVEDIRECTUV == 0\nvarying vec2 vEmissiveUV;\n#endif\n#if defined(LIGHTMAP) && LIGHTMAPDIRECTUV == 0\nvarying vec2 vLightmapUV;\n#endif\n#if defined(SPECULAR) && defined(SPECULARTERM) && SPECULARDIRECTUV == 0\nvarying vec2 vSpecularUV;\n#endif\n#if defined(BUMP) && BUMPDIRECTUV == 0\nvarying vec2 vBumpUV;\n#endif\n\nvarying vec3 vPositionW;\n#ifdef NORMAL\nvarying vec3 vNormalW;\n#endif\n#ifdef VERTEXCOLOR\nvarying vec4 vColor;\n#endif\n#include\n#include\n#include\n#include<__decl__lightFragment>[0..maxSimultaneousLights]\n#include\n#include[0..maxSimultaneousMorphTargets]\n#ifdef REFLECTIONMAP_SKYBOX\nvarying vec3 vPositionUVW;\n#endif\n#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\nvarying vec3 vDirectionW;\n#endif\n#include\n#define CUSTOM_VERTEX_DEFINITIONS\nvoid main(void) {\n#define CUSTOM_VERTEX_MAIN_BEGIN\nvec3 positionUpdated=position;\n#ifdef NORMAL \nvec3 normalUpdated=normal;\n#endif\n#ifdef TANGENT\nvec4 tangentUpdated=tangent;\n#endif\n#include[0..maxSimultaneousMorphTargets]\n#ifdef REFLECTIONMAP_SKYBOX\nvPositionUVW=positionUpdated;\n#endif \n#define CUSTOM_VERTEX_UPDATE_POSITION\n#define CUSTOM_VERTEX_UPDATE_NORMAL\n#include\n#include\ngl_Position=viewProjection*finalWorld*vec4(positionUpdated,1.0);\nvec4 worldPos=finalWorld*vec4(positionUpdated,1.0);\nvPositionW=vec3(worldPos);\n#ifdef NORMAL\nmat3 normalWorld=mat3(finalWorld);\n#ifdef NONUNIFORMSCALING\nnormalWorld=transposeMat3(inverseMat3(normalWorld));\n#endif\nvNormalW=normalize(normalWorld*normalUpdated);\n#endif\n#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\nvDirectionW=normalize(vec3(finalWorld*vec4(positionUpdated,0.0)));\n#endif\n\n#ifndef UV1\nvec2 uv=vec2(0.,0.);\n#endif\n#ifndef UV2\nvec2 uv2=vec2(0.,0.);\n#endif\n#ifdef MAINUV1\nvMainUV1=uv;\n#endif\n#ifdef MAINUV2\nvMainUV2=uv2;\n#endif\n#if defined(DIFFUSE) && DIFFUSEDIRECTUV == 0\nif (vDiffuseInfos.x == 0.)\n{\nvDiffuseUV=vec2(diffuseMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvDiffuseUV=vec2(diffuseMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(AMBIENT) && AMBIENTDIRECTUV == 0\nif (vAmbientInfos.x == 0.)\n{\nvAmbientUV=vec2(ambientMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvAmbientUV=vec2(ambientMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(OPACITY) && OPACITYDIRECTUV == 0\nif (vOpacityInfos.x == 0.)\n{\nvOpacityUV=vec2(opacityMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvOpacityUV=vec2(opacityMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(EMISSIVE) && EMISSIVEDIRECTUV == 0\nif (vEmissiveInfos.x == 0.)\n{\nvEmissiveUV=vec2(emissiveMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvEmissiveUV=vec2(emissiveMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(LIGHTMAP) && LIGHTMAPDIRECTUV == 0\nif (vLightmapInfos.x == 0.)\n{\nvLightmapUV=vec2(lightmapMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvLightmapUV=vec2(lightmapMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(SPECULAR) && defined(SPECULARTERM) && SPECULARDIRECTUV == 0\nif (vSpecularInfos.x == 0.)\n{\nvSpecularUV=vec2(specularMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvSpecularUV=vec2(specularMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(BUMP) && BUMPDIRECTUV == 0\nif (vBumpInfos.x == 0.)\n{\nvBumpUV=vec2(bumpMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvBumpUV=vec2(bumpMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#include\n#include\n#include\n#include[0..maxSimultaneousLights]\n#ifdef VERTEXCOLOR\n\nvColor=color;\n#endif\n#include\n#include\n#define CUSTOM_VERTEX_MAIN_END\n}\n","defaultPixelShader":"#include<__decl__defaultFragment>\n#if defined(BUMP) || !defined(NORMAL)\n#extension GL_OES_standard_derivatives : enable\n#endif\n#define CUSTOM_FRAGMENT_BEGIN\n#ifdef LOGARITHMICDEPTH\n#extension GL_EXT_frag_depth : enable\n#endif\n\n#define RECIPROCAL_PI2 0.15915494\nuniform vec3 vEyePosition;\nuniform vec3 vAmbientColor;\n\nvarying vec3 vPositionW;\n#ifdef NORMAL\nvarying vec3 vNormalW;\n#endif\n#ifdef VERTEXCOLOR\nvarying vec4 vColor;\n#endif\n#ifdef MAINUV1\nvarying vec2 vMainUV1;\n#endif\n#ifdef MAINUV2\nvarying vec2 vMainUV2;\n#endif\n\n#include\n\n#include<__decl__lightFragment>[0..maxSimultaneousLights]\n#include\n#include\n\n#ifdef DIFFUSE\n#if DIFFUSEDIRECTUV == 1\n#define vDiffuseUV vMainUV1\n#elif DIFFUSEDIRECTUV == 2\n#define vDiffuseUV vMainUV2\n#else\nvarying vec2 vDiffuseUV;\n#endif\nuniform sampler2D diffuseSampler;\n#endif\n#ifdef AMBIENT\n#if AMBIENTDIRECTUV == 1\n#define vAmbientUV vMainUV1\n#elif AMBIENTDIRECTUV == 2\n#define vAmbientUV vMainUV2\n#else\nvarying vec2 vAmbientUV;\n#endif\nuniform sampler2D ambientSampler;\n#endif\n#ifdef OPACITY \n#if OPACITYDIRECTUV == 1\n#define vOpacityUV vMainUV1\n#elif OPACITYDIRECTUV == 2\n#define vOpacityUV vMainUV2\n#else\nvarying vec2 vOpacityUV;\n#endif\nuniform sampler2D opacitySampler;\n#endif\n#ifdef EMISSIVE\n#if EMISSIVEDIRECTUV == 1\n#define vEmissiveUV vMainUV1\n#elif EMISSIVEDIRECTUV == 2\n#define vEmissiveUV vMainUV2\n#else\nvarying vec2 vEmissiveUV;\n#endif\nuniform sampler2D emissiveSampler;\n#endif\n#ifdef LIGHTMAP\n#if LIGHTMAPDIRECTUV == 1\n#define vLightmapUV vMainUV1\n#elif LIGHTMAPDIRECTUV == 2\n#define vLightmapUV vMainUV2\n#else\nvarying vec2 vLightmapUV;\n#endif\nuniform sampler2D lightmapSampler;\n#endif\n#ifdef REFRACTION\n#ifdef REFRACTIONMAP_3D\nuniform samplerCube refractionCubeSampler;\n#else\nuniform sampler2D refraction2DSampler;\n#endif\n#endif\n#if defined(SPECULAR) && defined(SPECULARTERM)\n#if SPECULARDIRECTUV == 1\n#define vSpecularUV vMainUV1\n#elif SPECULARDIRECTUV == 2\n#define vSpecularUV vMainUV2\n#else\nvarying vec2 vSpecularUV;\n#endif\nuniform sampler2D specularSampler;\n#endif\n\n#include\n\n#ifdef REFLECTION\n#ifdef REFLECTIONMAP_3D\nuniform samplerCube reflectionCubeSampler;\n#else\nuniform sampler2D reflection2DSampler;\n#endif\n#ifdef REFLECTIONMAP_SKYBOX\nvarying vec3 vPositionUVW;\n#else\n#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\nvarying vec3 vDirectionW;\n#endif\n#endif\n#include\n#endif\n#include\n#include\n#include\n#include\n#include\n#include\n#define CUSTOM_FRAGMENT_DEFINITIONS\nvoid main(void) {\n#define CUSTOM_FRAGMENT_MAIN_BEGIN\n#include\nvec3 viewDirectionW=normalize(vEyePosition-vPositionW);\n\nvec4 baseColor=vec4(1.,1.,1.,1.);\nvec3 diffuseColor=vDiffuseColor.rgb;\n\nfloat alpha=vDiffuseColor.a;\n\n#ifdef NORMAL\nvec3 normalW=normalize(vNormalW);\n#else\nvec3 normalW=normalize(-cross(dFdx(vPositionW),dFdy(vPositionW)));\n#endif\n#include\n#ifdef TWOSIDEDLIGHTING\nnormalW=gl_FrontFacing ? normalW : -normalW;\n#endif\n#ifdef DIFFUSE\nbaseColor=texture2D(diffuseSampler,vDiffuseUV+uvOffset);\n#ifdef ALPHATEST\nif (baseColor.a<0.4)\ndiscard;\n#endif\n#ifdef ALPHAFROMDIFFUSE\nalpha*=baseColor.a;\n#endif\n#define CUSTOM_FRAGMENT_UPDATE_ALPHA\nbaseColor.rgb*=vDiffuseInfos.y;\n#endif\n#include\n#ifdef VERTEXCOLOR\nbaseColor.rgb*=vColor.rgb;\n#endif\n#define CUSTOM_FRAGMENT_UPDATE_DIFFUSE\n\nvec3 baseAmbientColor=vec3(1.,1.,1.);\n#ifdef AMBIENT\nbaseAmbientColor=texture2D(ambientSampler,vAmbientUV+uvOffset).rgb*vAmbientInfos.y;\n#endif\n#define CUSTOM_FRAGMENT_BEFORE_LIGHTS\n\n#ifdef SPECULARTERM\nfloat glossiness=vSpecularColor.a;\nvec3 specularColor=vSpecularColor.rgb;\n#ifdef SPECULAR\nvec4 specularMapColor=texture2D(specularSampler,vSpecularUV+uvOffset);\nspecularColor=specularMapColor.rgb;\n#ifdef GLOSSINESS\nglossiness=glossiness*specularMapColor.a;\n#endif\n#endif\n#else\nfloat glossiness=0.;\n#endif\n\nvec3 diffuseBase=vec3(0.,0.,0.);\nlightingInfo info;\n#ifdef SPECULARTERM\nvec3 specularBase=vec3(0.,0.,0.);\n#endif\nfloat shadow=1.;\n#ifdef LIGHTMAP\nvec3 lightmapColor=texture2D(lightmapSampler,vLightmapUV+uvOffset).rgb*vLightmapInfos.y;\n#endif\n#include[0..maxSimultaneousLights]\n\nvec3 refractionColor=vec3(0.,0.,0.);\n#ifdef REFRACTION\nvec3 refractionVector=normalize(refract(-viewDirectionW,normalW,vRefractionInfos.y));\n#ifdef REFRACTIONMAP_3D\nrefractionVector.y=refractionVector.y*vRefractionInfos.w;\nif (dot(refractionVector,viewDirectionW)<1.0)\n{\nrefractionColor=textureCube(refractionCubeSampler,refractionVector).rgb*vRefractionInfos.x;\n}\n#else\nvec3 vRefractionUVW=vec3(refractionMatrix*(view*vec4(vPositionW+refractionVector*vRefractionInfos.z,1.0)));\nvec2 refractionCoords=vRefractionUVW.xy/vRefractionUVW.z;\nrefractionCoords.y=1.0-refractionCoords.y;\nrefractionColor=texture2D(refraction2DSampler,refractionCoords).rgb*vRefractionInfos.x;\n#endif\n#endif\n\nvec3 reflectionColor=vec3(0.,0.,0.);\n#ifdef REFLECTION\nvec3 vReflectionUVW=computeReflectionCoords(vec4(vPositionW,1.0),normalW);\n#ifdef REFLECTIONMAP_3D\n#ifdef ROUGHNESS\nfloat bias=vReflectionInfos.y;\n#ifdef SPECULARTERM\n#ifdef SPECULAR\n#ifdef GLOSSINESS\nbias*=(1.0-specularMapColor.a);\n#endif\n#endif\n#endif\nreflectionColor=textureCube(reflectionCubeSampler,vReflectionUVW,bias).rgb*vReflectionInfos.x;\n#else\nreflectionColor=textureCube(reflectionCubeSampler,vReflectionUVW).rgb*vReflectionInfos.x;\n#endif\n#else\nvec2 coords=vReflectionUVW.xy;\n#ifdef REFLECTIONMAP_PROJECTION\ncoords/=vReflectionUVW.z;\n#endif\ncoords.y=1.0-coords.y;\nreflectionColor=texture2D(reflection2DSampler,coords).rgb*vReflectionInfos.x;\n#endif\n#ifdef REFLECTIONFRESNEL\nfloat reflectionFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,reflectionRightColor.a,reflectionLeftColor.a);\n#ifdef REFLECTIONFRESNELFROMSPECULAR\n#ifdef SPECULARTERM\nreflectionColor*=specularColor.rgb*(1.0-reflectionFresnelTerm)+reflectionFresnelTerm*reflectionRightColor.rgb;\n#else\nreflectionColor*=reflectionLeftColor.rgb*(1.0-reflectionFresnelTerm)+reflectionFresnelTerm*reflectionRightColor.rgb;\n#endif\n#else\nreflectionColor*=reflectionLeftColor.rgb*(1.0-reflectionFresnelTerm)+reflectionFresnelTerm*reflectionRightColor.rgb;\n#endif\n#endif\n#endif\n#ifdef REFRACTIONFRESNEL\nfloat refractionFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,refractionRightColor.a,refractionLeftColor.a);\nrefractionColor*=refractionLeftColor.rgb*(1.0-refractionFresnelTerm)+refractionFresnelTerm*refractionRightColor.rgb;\n#endif\n#ifdef OPACITY\nvec4 opacityMap=texture2D(opacitySampler,vOpacityUV+uvOffset);\n#ifdef OPACITYRGB\nopacityMap.rgb=opacityMap.rgb*vec3(0.3,0.59,0.11);\nalpha*=(opacityMap.x+opacityMap.y+opacityMap.z)* vOpacityInfos.y;\n#else\nalpha*=opacityMap.a*vOpacityInfos.y;\n#endif\n#endif\n#ifdef VERTEXALPHA\nalpha*=vColor.a;\n#endif\n#ifdef OPACITYFRESNEL\nfloat opacityFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,opacityParts.z,opacityParts.w);\nalpha+=opacityParts.x*(1.0-opacityFresnelTerm)+opacityFresnelTerm*opacityParts.y;\n#endif\n\nvec3 emissiveColor=vEmissiveColor;\n#ifdef EMISSIVE\nemissiveColor+=texture2D(emissiveSampler,vEmissiveUV+uvOffset).rgb*vEmissiveInfos.y;\n#endif\n#ifdef EMISSIVEFRESNEL\nfloat emissiveFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,emissiveRightColor.a,emissiveLeftColor.a);\nemissiveColor*=emissiveLeftColor.rgb*(1.0-emissiveFresnelTerm)+emissiveFresnelTerm*emissiveRightColor.rgb;\n#endif\n\n#ifdef DIFFUSEFRESNEL\nfloat diffuseFresnelTerm=computeFresnelTerm(viewDirectionW,normalW,diffuseRightColor.a,diffuseLeftColor.a);\ndiffuseBase*=diffuseLeftColor.rgb*(1.0-diffuseFresnelTerm)+diffuseFresnelTerm*diffuseRightColor.rgb;\n#endif\n\n#ifdef EMISSIVEASILLUMINATION\nvec3 finalDiffuse=clamp(diffuseBase*diffuseColor+vAmbientColor,0.0,1.0)*baseColor.rgb;\n#else\n#ifdef LINKEMISSIVEWITHDIFFUSE\nvec3 finalDiffuse=clamp((diffuseBase+emissiveColor)*diffuseColor+vAmbientColor,0.0,1.0)*baseColor.rgb;\n#else\nvec3 finalDiffuse=clamp(diffuseBase*diffuseColor+emissiveColor+vAmbientColor,0.0,1.0)*baseColor.rgb;\n#endif\n#endif\n#ifdef SPECULARTERM\nvec3 finalSpecular=specularBase*specularColor;\n#ifdef SPECULAROVERALPHA\nalpha=clamp(alpha+dot(finalSpecular,vec3(0.3,0.59,0.11)),0.,1.);\n#endif\n#else\nvec3 finalSpecular=vec3(0.0);\n#endif\n#ifdef REFLECTIONOVERALPHA\nalpha=clamp(alpha+dot(reflectionColor,vec3(0.3,0.59,0.11)),0.,1.);\n#endif\n\n#ifdef EMISSIVEASILLUMINATION\nvec4 color=vec4(clamp(finalDiffuse*baseAmbientColor+finalSpecular+reflectionColor+emissiveColor+refractionColor,0.0,1.0),alpha);\n#else\nvec4 color=vec4(finalDiffuse*baseAmbientColor+finalSpecular+reflectionColor+refractionColor,alpha);\n#endif\n\n#ifdef LIGHTMAP\n#ifndef LIGHTMAPEXCLUDED\n#ifdef USELIGHTMAPASSHADOWMAP\ncolor.rgb*=lightmapColor;\n#else\ncolor.rgb+=lightmapColor;\n#endif\n#endif\n#endif\n#define CUSTOM_FRAGMENT_BEFORE_FOG\ncolor.rgb=max(color.rgb,0.);\n#include\n#include\n\n\n#ifdef IMAGEPROCESSINGPOSTPROCESS\ncolor.rgb=toLinearSpace(color.rgb);\n#else\n#ifdef IMAGEPROCESSING\ncolor.rgb=toLinearSpace(color.rgb);\ncolor=applyImageProcessing(color);\n#endif\n#endif\n#ifdef PREMULTIPLYALPHA\n\ncolor.rgb*=color.a;\n#endif\n#define CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR\ngl_FragColor=color;\n}\n","pbrVertexShader":"precision highp float;\n#include<__decl__pbrVertex>\n\nattribute vec3 position;\n#ifdef NORMAL\nattribute vec3 normal;\n#endif\n#ifdef TANGENT\nattribute vec4 tangent;\n#endif\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#ifdef MAINUV1\nvarying vec2 vMainUV1;\n#endif\n#ifdef MAINUV2\nvarying vec2 vMainUV2; \n#endif \n#ifdef VERTEXCOLOR\nattribute vec4 color;\n#endif\n#include\n#include\n\n#include\n#if defined(ALBEDO) && ALBEDODIRECTUV == 0\nvarying vec2 vAlbedoUV;\n#endif\n#if defined(AMBIENT) && AMBIENTDIRECTUV == 0\nvarying vec2 vAmbientUV;\n#endif\n#if defined(OPACITY) && OPACITYDIRECTUV == 0\nvarying vec2 vOpacityUV;\n#endif\n#if defined(EMISSIVE) && EMISSIVEDIRECTUV == 0\nvarying vec2 vEmissiveUV;\n#endif\n#if defined(LIGHTMAP) && LIGHTMAPDIRECTUV == 0\nvarying vec2 vLightmapUV;\n#endif\n#if defined(REFLECTIVITY) && REFLECTIVITYDIRECTUV == 0\nvarying vec2 vReflectivityUV;\n#endif\n#if defined(MICROSURFACEMAP) && MICROSURFACEMAPDIRECTUV == 0\nvarying vec2 vMicroSurfaceSamplerUV;\n#endif\n#if defined(BUMP) && BUMPDIRECTUV == 0\nvarying vec2 vBumpUV;\n#endif\n\nvarying vec3 vPositionW;\n#ifdef NORMAL\nvarying vec3 vNormalW;\n#if defined(USESPHERICALFROMREFLECTIONMAP) && defined(USESPHERICALINVERTEX)\nvarying vec3 vEnvironmentIrradiance;\n#include\n#endif\n#endif\n#ifdef VERTEXCOLOR\nvarying vec4 vColor;\n#endif\n#include\n#include\n#include\n#include<__decl__lightFragment>[0..maxSimultaneousLights]\n#include\n#include[0..maxSimultaneousMorphTargets]\n#ifdef REFLECTIONMAP_SKYBOX\nvarying vec3 vPositionUVW;\n#endif\n#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\nvarying vec3 vDirectionW;\n#endif\n#include\nvoid main(void) {\nvec3 positionUpdated=position;\n#ifdef NORMAL\nvec3 normalUpdated=normal;\n#endif\n#ifdef TANGENT\nvec4 tangentUpdated=tangent;\n#endif\n#include[0..maxSimultaneousMorphTargets]\n#ifdef REFLECTIONMAP_SKYBOX\nvPositionUVW=positionUpdated;\n#endif \n#include\n#include\ngl_Position=viewProjection*finalWorld*vec4(positionUpdated,1.0);\nvec4 worldPos=finalWorld*vec4(positionUpdated,1.0);\nvPositionW=vec3(worldPos);\n#ifdef NORMAL\nmat3 normalWorld=mat3(finalWorld);\n#ifdef NONUNIFORMSCALING\nnormalWorld=transposeMat3(inverseMat3(normalWorld));\n#endif\nvNormalW=normalize(normalWorld*normalUpdated);\n#if defined(USESPHERICALFROMREFLECTIONMAP) && defined(USESPHERICALINVERTEX)\nvec3 reflectionVector=vec3(reflectionMatrix*vec4(vNormalW,0)).xyz;\n#ifdef REFLECTIONMAP_OPPOSITEZ\nreflectionVector.z*=-1.0;\n#endif\nvEnvironmentIrradiance=environmentIrradianceJones(reflectionVector);\n#endif\n#endif\n#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\nvDirectionW=normalize(vec3(finalWorld*vec4(positionUpdated,0.0)));\n#endif\n\n#ifndef UV1\nvec2 uv=vec2(0.,0.);\n#endif\n#ifndef UV2\nvec2 uv2=vec2(0.,0.);\n#endif\n#ifdef MAINUV1\nvMainUV1=uv;\n#endif \n#ifdef MAINUV2\nvMainUV2=uv2;\n#endif \n#if defined(ALBEDO) && ALBEDODIRECTUV == 0 \nif (vAlbedoInfos.x == 0.)\n{\nvAlbedoUV=vec2(albedoMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvAlbedoUV=vec2(albedoMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(AMBIENT) && AMBIENTDIRECTUV == 0 \nif (vAmbientInfos.x == 0.)\n{\nvAmbientUV=vec2(ambientMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvAmbientUV=vec2(ambientMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(OPACITY) && OPACITYDIRECTUV == 0 \nif (vOpacityInfos.x == 0.)\n{\nvOpacityUV=vec2(opacityMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvOpacityUV=vec2(opacityMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(EMISSIVE) && EMISSIVEDIRECTUV == 0 \nif (vEmissiveInfos.x == 0.)\n{\nvEmissiveUV=vec2(emissiveMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvEmissiveUV=vec2(emissiveMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(LIGHTMAP) && LIGHTMAPDIRECTUV == 0 \nif (vLightmapInfos.x == 0.)\n{\nvLightmapUV=vec2(lightmapMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvLightmapUV=vec2(lightmapMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(REFLECTIVITY) && REFLECTIVITYDIRECTUV == 0 \nif (vReflectivityInfos.x == 0.)\n{\nvReflectivityUV=vec2(reflectivityMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvReflectivityUV=vec2(reflectivityMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(MICROSURFACEMAP) && MICROSURFACEMAPDIRECTUV == 0 \nif (vMicroSurfaceSamplerInfos.x == 0.)\n{\nvMicroSurfaceSamplerUV=vec2(microSurfaceSamplerMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvMicroSurfaceSamplerUV=vec2(microSurfaceSamplerMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n#if defined(BUMP) && BUMPDIRECTUV == 0 \nif (vBumpInfos.x == 0.)\n{\nvBumpUV=vec2(bumpMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvBumpUV=vec2(bumpMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n\n#include\n\n#include\n\n#include\n\n#include[0..maxSimultaneousLights]\n\n#ifdef VERTEXCOLOR\nvColor=color;\n#endif\n\n#ifdef POINTSIZE\ngl_PointSize=pointSize;\n#endif\n\n#include\n}","pbrPixelShader":"#if defined(BUMP) || !defined(NORMAL) || defined(FORCENORMALFORWARD)\n#extension GL_OES_standard_derivatives : enable\n#endif\n#ifdef LODBASEDMICROSFURACE\n#extension GL_EXT_shader_texture_lod : enable\n#endif\n#ifdef LOGARITHMICDEPTH\n#extension GL_EXT_frag_depth : enable\n#endif\nprecision highp float;\n#include<__decl__pbrFragment>\nuniform vec4 vEyePosition;\nuniform vec3 vAmbientColor;\nuniform vec4 vCameraInfos;\n\nvarying vec3 vPositionW;\n#ifdef MAINUV1\nvarying vec2 vMainUV1;\n#endif \n#ifdef MAINUV2 \nvarying vec2 vMainUV2;\n#endif \n#ifdef NORMAL\nvarying vec3 vNormalW;\n#if defined(USESPHERICALFROMREFLECTIONMAP) && defined(USESPHERICALINVERTEX)\nvarying vec3 vEnvironmentIrradiance;\n#endif\n#endif\n#ifdef VERTEXCOLOR\nvarying vec4 vColor;\n#endif\n\n#include<__decl__lightFragment>[0..maxSimultaneousLights]\n\n#ifdef ALBEDO\n#if ALBEDODIRECTUV == 1\n#define vAlbedoUV vMainUV1\n#elif ALBEDODIRECTUV == 2\n#define vAlbedoUV vMainUV2\n#else\nvarying vec2 vAlbedoUV;\n#endif\nuniform sampler2D albedoSampler;\n#endif\n#ifdef AMBIENT\n#if AMBIENTDIRECTUV == 1\n#define vAmbientUV vMainUV1\n#elif AMBIENTDIRECTUV == 2\n#define vAmbientUV vMainUV2\n#else\nvarying vec2 vAmbientUV;\n#endif\nuniform sampler2D ambientSampler;\n#endif\n#ifdef OPACITY\n#if OPACITYDIRECTUV == 1\n#define vOpacityUV vMainUV1\n#elif OPACITYDIRECTUV == 2\n#define vOpacityUV vMainUV2\n#else\nvarying vec2 vOpacityUV;\n#endif\nuniform sampler2D opacitySampler;\n#endif\n#ifdef EMISSIVE\n#if EMISSIVEDIRECTUV == 1\n#define vEmissiveUV vMainUV1\n#elif EMISSIVEDIRECTUV == 2\n#define vEmissiveUV vMainUV2\n#else\nvarying vec2 vEmissiveUV;\n#endif\nuniform sampler2D emissiveSampler;\n#endif\n#ifdef LIGHTMAP\n#if LIGHTMAPDIRECTUV == 1\n#define vLightmapUV vMainUV1\n#elif LIGHTMAPDIRECTUV == 2\n#define vLightmapUV vMainUV2\n#else\nvarying vec2 vLightmapUV;\n#endif\nuniform sampler2D lightmapSampler;\n#endif\n#ifdef REFLECTIVITY\n#if REFLECTIVITYDIRECTUV == 1\n#define vReflectivityUV vMainUV1\n#elif REFLECTIVITYDIRECTUV == 2\n#define vReflectivityUV vMainUV2\n#else\nvarying vec2 vReflectivityUV;\n#endif\nuniform sampler2D reflectivitySampler;\n#endif\n#ifdef MICROSURFACEMAP\n#if MICROSURFACEMAPDIRECTUV == 1\n#define vMicroSurfaceSamplerUV vMainUV1\n#elif MICROSURFACEMAPDIRECTUV == 2\n#define vMicroSurfaceSamplerUV vMainUV2\n#else\nvarying vec2 vMicroSurfaceSamplerUV;\n#endif\nuniform sampler2D microSurfaceSampler;\n#endif\n\n#ifdef REFRACTION\n#ifdef REFRACTIONMAP_3D\n#define sampleRefraction(s,c) textureCube(s,c)\nuniform samplerCube refractionSampler;\n#ifdef LODBASEDMICROSFURACE\n#define sampleRefractionLod(s,c,l) textureCubeLodEXT(s,c,l)\n#else\nuniform samplerCube refractionSamplerLow;\nuniform samplerCube refractionSamplerHigh;\n#endif\n#else\n#define sampleRefraction(s,c) texture2D(s,c)\nuniform sampler2D refractionSampler;\n#ifdef LODBASEDMICROSFURACE\n#define sampleRefractionLod(s,c,l) texture2DLodEXT(s,c,l)\n#else\nuniform samplerCube refractionSamplerLow;\nuniform samplerCube refractionSamplerHigh;\n#endif\n#endif\n#endif\n\n#ifdef REFLECTION\n#ifdef REFLECTIONMAP_3D\n#define sampleReflection(s,c) textureCube(s,c)\nuniform samplerCube reflectionSampler;\n#ifdef LODBASEDMICROSFURACE\n#define sampleReflectionLod(s,c,l) textureCubeLodEXT(s,c,l)\n#else\nuniform samplerCube reflectionSamplerLow;\nuniform samplerCube reflectionSamplerHigh;\n#endif\n#else\n#define sampleReflection(s,c) texture2D(s,c)\nuniform sampler2D reflectionSampler;\n#ifdef LODBASEDMICROSFURACE\n#define sampleReflectionLod(s,c,l) texture2DLodEXT(s,c,l)\n#else\nuniform samplerCube reflectionSamplerLow;\nuniform samplerCube reflectionSamplerHigh;\n#endif\n#endif\n#ifdef REFLECTIONMAP_SKYBOX\nvarying vec3 vPositionUVW;\n#else\n#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\nvarying vec3 vDirectionW;\n#endif\n#endif\n#include\n#endif\n#ifdef ENVIRONMENTBRDF\nuniform sampler2D environmentBrdfSampler;\n#endif\n\n#ifndef FROMLINEARSPACE\n#define FROMLINEARSPACE;\n#endif\n#include\n#include\n#include\n\n#include\n#include\n#include\n#include\n#include\n#include\n#include\n\n#include\nvoid main(void) {\n#include\n\n\nvec3 viewDirectionW=normalize(vEyePosition.xyz-vPositionW);\n#ifdef NORMAL\nvec3 normalW=normalize(vNormalW);\n#else\nvec3 normalW=normalize(cross(dFdx(vPositionW),dFdy(vPositionW)))*vEyePosition.w;\n#endif\n#include\n#if defined(FORCENORMALFORWARD) && defined(NORMAL)\nvec3 faceNormal=normalize(cross(dFdx(vPositionW),dFdy(vPositionW)))*vEyePosition.w;\n#if defined(TWOSIDEDLIGHTING)\nfaceNormal=gl_FrontFacing ? faceNormal : -faceNormal;\n#endif\nnormalW*=sign(dot(normalW,faceNormal));\n#endif\n#if defined(TWOSIDEDLIGHTING) && defined(NORMAL)\nnormalW=gl_FrontFacing ? normalW : -normalW;\n#endif\n\n\nvec3 surfaceAlbedo=vAlbedoColor.rgb;\n\nfloat alpha=vAlbedoColor.a;\n#ifdef ALBEDO\nvec4 albedoTexture=texture2D(albedoSampler,vAlbedoUV+uvOffset);\n#if defined(ALPHAFROMALBEDO) || defined(ALPHATEST)\nalpha*=albedoTexture.a;\n#endif\nsurfaceAlbedo*=toLinearSpace(albedoTexture.rgb);\nsurfaceAlbedo*=vAlbedoInfos.y;\n#endif\n\n#ifdef OPACITY\nvec4 opacityMap=texture2D(opacitySampler,vOpacityUV+uvOffset);\n#ifdef OPACITYRGB\nalpha=getLuminance(opacityMap.rgb);\n#else\nalpha*=opacityMap.a;\n#endif\nalpha*=vOpacityInfos.y;\n#endif\n#ifdef VERTEXALPHA\nalpha*=vColor.a;\n#endif\n#if !defined(LINKREFRACTIONTOTRANSPARENCY) && !defined(ALPHAFRESNEL)\n#ifdef ALPHATEST\nif (alpha<=ALPHATESTVALUE)\ndiscard;\n#ifndef ALPHABLEND\n\nalpha=1.0;\n#endif\n#endif\n#endif\n#include\n#ifdef VERTEXCOLOR\nsurfaceAlbedo*=vColor.rgb;\n#endif\n\nvec3 ambientOcclusionColor=vec3(1.,1.,1.);\n#ifdef AMBIENT\nvec3 ambientOcclusionColorMap=texture2D(ambientSampler,vAmbientUV+uvOffset).rgb*vAmbientInfos.y;\n#ifdef AMBIENTINGRAYSCALE\nambientOcclusionColorMap=vec3(ambientOcclusionColorMap.r,ambientOcclusionColorMap.r,ambientOcclusionColorMap.r);\n#endif\nambientOcclusionColor=mix(ambientOcclusionColor,ambientOcclusionColorMap,vAmbientInfos.z);\n#endif\n\nfloat microSurface=vReflectivityColor.a;\nvec3 surfaceReflectivityColor=vReflectivityColor.rgb;\n#ifdef METALLICWORKFLOW\nvec2 metallicRoughness=surfaceReflectivityColor.rg;\n#ifdef REFLECTIVITY\nvec4 surfaceMetallicColorMap=texture2D(reflectivitySampler,vReflectivityUV+uvOffset);\n#ifdef AOSTOREINMETALMAPRED\nvec3 aoStoreInMetalMap=vec3(surfaceMetallicColorMap.r,surfaceMetallicColorMap.r,surfaceMetallicColorMap.r);\nambientOcclusionColor=mix(ambientOcclusionColor,aoStoreInMetalMap,vReflectivityInfos.z);\n#endif\n#ifdef METALLNESSSTOREINMETALMAPBLUE\nmetallicRoughness.r*=surfaceMetallicColorMap.b;\n#else\nmetallicRoughness.r*=surfaceMetallicColorMap.r;\n#endif\n#ifdef ROUGHNESSSTOREINMETALMAPALPHA\nmetallicRoughness.g*=surfaceMetallicColorMap.a;\n#else\n#ifdef ROUGHNESSSTOREINMETALMAPGREEN\nmetallicRoughness.g*=surfaceMetallicColorMap.g;\n#endif\n#endif\n#endif\n#ifdef MICROSURFACEMAP\nvec4 microSurfaceTexel=texture2D(microSurfaceSampler,vMicroSurfaceSamplerUV+uvOffset)*vMicroSurfaceSamplerInfos.y;\nmetallicRoughness.g*=microSurfaceTexel.r;\n#endif\n\nmicroSurface=1.0-metallicRoughness.g;\n\nvec3 baseColor=surfaceAlbedo;\n\n\nconst vec3 DefaultSpecularReflectanceDielectric=vec3(0.04,0.04,0.04);\n\nsurfaceAlbedo=mix(baseColor.rgb*(1.0-DefaultSpecularReflectanceDielectric.r),vec3(0.,0.,0.),metallicRoughness.r);\n\nsurfaceReflectivityColor=mix(DefaultSpecularReflectanceDielectric,baseColor,metallicRoughness.r);\n#else\n#ifdef REFLECTIVITY\nvec4 surfaceReflectivityColorMap=texture2D(reflectivitySampler,vReflectivityUV+uvOffset);\nsurfaceReflectivityColor*=toLinearSpace(surfaceReflectivityColorMap.rgb);\nsurfaceReflectivityColor*=vReflectivityInfos.y;\n#ifdef MICROSURFACEFROMREFLECTIVITYMAP\nmicroSurface*=surfaceReflectivityColorMap.a;\nmicroSurface*=vReflectivityInfos.z;\n#else\n#ifdef MICROSURFACEAUTOMATIC\nmicroSurface*=computeDefaultMicroSurface(microSurface,surfaceReflectivityColor);\n#endif\n#ifdef MICROSURFACEMAP\nvec4 microSurfaceTexel=texture2D(microSurfaceSampler,vMicroSurfaceSamplerUV+uvOffset)*vMicroSurfaceSamplerInfos.y;\nmicroSurface*=microSurfaceTexel.r;\n#endif\n#endif\n#endif\n#endif\n\nmicroSurface=clamp(microSurface,0.,1.);\n\nfloat roughness=1.-microSurface;\n\n#ifdef ALPHAFRESNEL\n#if defined(ALPHATEST) || defined(ALPHABLEND)\n\n\n\nfloat opacityPerceptual=alpha;\n#ifdef LINEARALPHAFRESNEL\nfloat opacity0=opacityPerceptual;\n#else\nfloat opacity0=opacityPerceptual*opacityPerceptual;\n#endif\nfloat opacity90=fresnelGrazingReflectance(opacity0);\nvec3 normalForward=faceforward(normalW,-viewDirectionW,normalW);\n\nalpha=fresnelSchlickEnvironmentGGX(clamp(dot(viewDirectionW,normalForward),0.0,1.0),vec3(opacity0),vec3(opacity90),sqrt(microSurface)).x;\n#ifdef ALPHATEST\nif (alpha<=ALPHATESTVALUE)\ndiscard;\n#ifndef ALPHABLEND\n\nalpha=1.0;\n#endif\n#endif\n#endif\n#endif\n\n\nfloat NdotVUnclamped=dot(normalW,viewDirectionW);\nfloat NdotV=clamp(NdotVUnclamped,0.,1.)+0.00001;\nfloat alphaG=convertRoughnessToAverageSlope(roughness);\n\n#ifdef REFRACTION\nvec3 environmentRefraction=vec3(0.,0.,0.);\nvec3 refractionVector=refract(-viewDirectionW,normalW,vRefractionInfos.y);\n#ifdef REFRACTIONMAP_OPPOSITEZ\nrefractionVector.z*=-1.0;\n#endif\n\n#ifdef REFRACTIONMAP_3D\nrefractionVector.y=refractionVector.y*vRefractionInfos.w;\nvec3 refractionCoords=refractionVector;\nrefractionCoords=vec3(refractionMatrix*vec4(refractionCoords,0));\n#else\nvec3 vRefractionUVW=vec3(refractionMatrix*(view*vec4(vPositionW+refractionVector*vRefractionInfos.z,1.0)));\nvec2 refractionCoords=vRefractionUVW.xy/vRefractionUVW.z;\nrefractionCoords.y=1.0-refractionCoords.y;\n#endif\n#ifdef LODINREFRACTIONALPHA\nfloat refractionLOD=getLodFromAlphaG(vRefractionMicrosurfaceInfos.x,alphaG,NdotVUnclamped);\n#else\nfloat refractionLOD=getLodFromAlphaG(vRefractionMicrosurfaceInfos.x,alphaG,1.0);\n#endif\n#ifdef LODBASEDMICROSFURACE\n\nrefractionLOD=refractionLOD*vRefractionMicrosurfaceInfos.y+vRefractionMicrosurfaceInfos.z;\n#ifdef LODINREFRACTIONALPHA\n\n\n\n\n\n\n\n\n\nfloat automaticRefractionLOD=UNPACK_LOD(sampleRefraction(refractionSampler,refractionCoords).a);\nfloat requestedRefractionLOD=max(automaticRefractionLOD,refractionLOD);\n#else\nfloat requestedRefractionLOD=refractionLOD;\n#endif\nenvironmentRefraction=sampleRefractionLod(refractionSampler,refractionCoords,requestedRefractionLOD).rgb;\n#else\nfloat lodRefractionNormalized=clamp(refractionLOD/log2(vRefractionMicrosurfaceInfos.x),0.,1.);\nfloat lodRefractionNormalizedDoubled=lodRefractionNormalized*2.0;\nvec3 environmentRefractionMid=sampleRefraction(refractionSampler,refractionCoords).rgb;\nif(lodRefractionNormalizedDoubled<1.0){\nenvironmentRefraction=mix(\nsampleRefraction(refractionSamplerHigh,refractionCoords).rgb,\nenvironmentRefractionMid,\nlodRefractionNormalizedDoubled\n);\n}else{\nenvironmentRefraction=mix(\nenvironmentRefractionMid,\nsampleRefraction(refractionSamplerLow,refractionCoords).rgb,\nlodRefractionNormalizedDoubled-1.0\n);\n}\n#endif\n#ifdef GAMMAREFRACTION\nenvironmentRefraction=toLinearSpace(environmentRefraction.rgb);\n#endif\n\nenvironmentRefraction*=vRefractionInfos.x;\n#endif\n\n#ifdef REFLECTION\nvec3 environmentRadiance=vec3(0.,0.,0.);\nvec3 environmentIrradiance=vec3(0.,0.,0.);\nvec3 reflectionVector=computeReflectionCoords(vec4(vPositionW,1.0),normalW);\n#ifdef REFLECTIONMAP_OPPOSITEZ\nreflectionVector.z*=-1.0;\n#endif\n\n#ifdef REFLECTIONMAP_3D\nvec3 reflectionCoords=reflectionVector;\n#else\nvec2 reflectionCoords=reflectionVector.xy;\n#ifdef REFLECTIONMAP_PROJECTION\nreflectionCoords/=reflectionVector.z;\n#endif\nreflectionCoords.y=1.0-reflectionCoords.y;\n#endif\n#if defined(LODINREFLECTIONALPHA) && !defined(REFLECTIONMAP_SKYBOX)\nfloat reflectionLOD=getLodFromAlphaG(vReflectionMicrosurfaceInfos.x,alphaG,NdotVUnclamped);\n#else\nfloat reflectionLOD=getLodFromAlphaG(vReflectionMicrosurfaceInfos.x,alphaG,1.);\n#endif\n#ifdef LODBASEDMICROSFURACE\n\nreflectionLOD=reflectionLOD*vReflectionMicrosurfaceInfos.y+vReflectionMicrosurfaceInfos.z;\n#ifdef LODINREFLECTIONALPHA\n\n\n\n\n\n\n\n\n\nfloat automaticReflectionLOD=UNPACK_LOD(sampleReflection(reflectionSampler,reflectionCoords).a);\nfloat requestedReflectionLOD=max(automaticReflectionLOD,reflectionLOD);\n#else\nfloat requestedReflectionLOD=reflectionLOD;\n#endif\nenvironmentRadiance=sampleReflectionLod(reflectionSampler,reflectionCoords,requestedReflectionLOD).rgb;\n#else\nfloat lodReflectionNormalized=clamp(reflectionLOD/log2(vReflectionMicrosurfaceInfos.x),0.,1.);\nfloat lodReflectionNormalizedDoubled=lodReflectionNormalized*2.0;\nvec3 environmentSpecularMid=sampleReflection(reflectionSampler,reflectionCoords).rgb;\nif(lodReflectionNormalizedDoubled<1.0){\nenvironmentRadiance=mix(\nsampleReflection(reflectionSamplerHigh,reflectionCoords).rgb,\nenvironmentSpecularMid,\nlodReflectionNormalizedDoubled\n);\n}else{\nenvironmentRadiance=mix(\nenvironmentSpecularMid,\nsampleReflection(reflectionSamplerLow,reflectionCoords).rgb,\nlodReflectionNormalizedDoubled-1.0\n);\n}\n#endif\n#ifdef GAMMAREFLECTION\nenvironmentRadiance=toLinearSpace(environmentRadiance.rgb);\n#endif\n\n#ifdef USESPHERICALFROMREFLECTIONMAP\n#if defined(NORMAL) && defined(USESPHERICALINVERTEX)\nenvironmentIrradiance=vEnvironmentIrradiance;\n#else\nvec3 irradianceVector=vec3(reflectionMatrix*vec4(normalW,0)).xyz;\n#ifdef REFLECTIONMAP_OPPOSITEZ\nirradianceVector.z*=-1.0;\n#endif\nenvironmentIrradiance=environmentIrradianceJones(irradianceVector);\n#endif\n#endif\n\nenvironmentRadiance*=vReflectionInfos.x;\nenvironmentRadiance*=vReflectionColor.rgb;\nenvironmentIrradiance*=vReflectionColor.rgb;\n#endif\n\n\n\nfloat reflectance=max(max(surfaceReflectivityColor.r,surfaceReflectivityColor.g),surfaceReflectivityColor.b);\nfloat reflectance90=fresnelGrazingReflectance(reflectance);\nvec3 specularEnvironmentR0=surfaceReflectivityColor.rgb;\nvec3 specularEnvironmentR90=vec3(1.0,1.0,1.0)*reflectance90;\n\nvec3 diffuseBase=vec3(0.,0.,0.);\n#ifdef SPECULARTERM\nvec3 specularBase=vec3(0.,0.,0.);\n#endif\n#ifdef LIGHTMAP\nvec3 lightmapColor=toLinearSpace(texture2D(lightmapSampler,vLightmapUV+uvOffset).rgb)*vLightmapInfos.y;\n#endif\nlightingInfo info;\nfloat shadow=1.; \nfloat NdotL=-1.;\n#include[0..maxSimultaneousLights]\n\n#if defined(ENVIRONMENTBRDF) && !defined(REFLECTIONMAP_SKYBOX)\n\nvec2 brdfSamplerUV=vec2(NdotV,roughness);\n\nvec4 environmentBrdf=texture2D(environmentBrdfSampler,brdfSamplerUV);\nvec3 specularEnvironmentReflectance=specularEnvironmentR0*environmentBrdf.x+environmentBrdf.y;\n#ifdef RADIANCEOCCLUSION\n#ifdef AMBIENTINGRAYSCALE\nfloat ambientMonochrome=ambientOcclusionColor.r;\n#else\nfloat ambientMonochrome=getLuminance(ambientOcclusionColor);\n#endif\nfloat seo=environmentRadianceOcclusion(ambientMonochrome,NdotVUnclamped);\nspecularEnvironmentReflectance*=seo;\n#endif\n#ifdef HORIZONOCCLUSION\n#ifdef BUMP\n#ifdef REFLECTIONMAP_3D\nfloat eho=environmentHorizonOcclusion(reflectionCoords,normalW);\nspecularEnvironmentReflectance*=eho;\n#endif\n#endif\n#endif\n#else\n\nvec3 specularEnvironmentReflectance=fresnelSchlickEnvironmentGGX(NdotV,specularEnvironmentR0,specularEnvironmentR90,sqrt(microSurface));\n#endif\n\n#ifdef REFRACTION\nvec3 refractance=vec3(0.0,0.0,0.0);\nvec3 transmission=vec3(1.0,1.0,1.0);\n#ifdef LINKREFRACTIONTOTRANSPARENCY\n\ntransmission*=(1.0-alpha);\n\n\nvec3 mixedAlbedo=surfaceAlbedo;\nfloat maxChannel=max(max(mixedAlbedo.r,mixedAlbedo.g),mixedAlbedo.b);\nvec3 tint=clamp(maxChannel*mixedAlbedo,0.0,1.0);\n\nsurfaceAlbedo*=alpha;\n\nenvironmentIrradiance*=alpha;\n\nenvironmentRefraction*=tint;\n\nalpha=1.0;\n#endif\n\nvec3 bounceSpecularEnvironmentReflectance=(2.0*specularEnvironmentReflectance)/(1.0+specularEnvironmentReflectance);\nspecularEnvironmentReflectance=mix(bounceSpecularEnvironmentReflectance,specularEnvironmentReflectance,alpha);\n\ntransmission*=1.0-specularEnvironmentReflectance;\n\nrefractance=transmission;\n#endif\n\n\n\n\nsurfaceAlbedo.rgb=(1.-reflectance)*surfaceAlbedo.rgb;\n\nvec3 finalDiffuse=diffuseBase;\nfinalDiffuse.rgb+=vAmbientColor;\nfinalDiffuse*=surfaceAlbedo.rgb;\nfinalDiffuse=max(finalDiffuse,0.0);\n\n#ifdef REFLECTION\nvec3 finalIrradiance=environmentIrradiance;\nfinalIrradiance*=surfaceAlbedo.rgb;\n#endif\n\n#ifdef SPECULARTERM\nvec3 finalSpecular=specularBase;\nfinalSpecular=max(finalSpecular,0.0);\n\nvec3 finalSpecularScaled=finalSpecular*vLightingIntensity.x*vLightingIntensity.w;\n#endif\n\n#ifdef REFLECTION\nvec3 finalRadiance=environmentRadiance;\nfinalRadiance*=specularEnvironmentReflectance;\n\nvec3 finalRadianceScaled=finalRadiance*vLightingIntensity.z;\n#endif\n\n#ifdef REFRACTION\nvec3 finalRefraction=environmentRefraction;\nfinalRefraction*=refractance;\n#endif\n\nvec3 finalEmissive=vEmissiveColor;\n#ifdef EMISSIVE\nvec3 emissiveColorTex=texture2D(emissiveSampler,vEmissiveUV+uvOffset).rgb;\nfinalEmissive*=toLinearSpace(emissiveColorTex.rgb);\nfinalEmissive*=vEmissiveInfos.y;\n#endif\n\n#ifdef ALPHABLEND\nfloat luminanceOverAlpha=0.0;\n#if defined(REFLECTION) && defined(RADIANCEOVERALPHA)\nluminanceOverAlpha+=getLuminance(finalRadianceScaled);\n#endif\n#if defined(SPECULARTERM) && defined(SPECULAROVERALPHA)\nluminanceOverAlpha+=getLuminance(finalSpecularScaled);\n#endif\n#if defined(RADIANCEOVERALPHA) || defined(SPECULAROVERALPHA)\nalpha=clamp(alpha+luminanceOverAlpha*luminanceOverAlpha,0.,1.);\n#endif\n#endif\n\n\n\nvec4 finalColor=vec4(finalDiffuse*ambientOcclusionColor*vLightingIntensity.x +\n#ifdef REFLECTION\nfinalIrradiance*ambientOcclusionColor*vLightingIntensity.z +\n#endif\n#ifdef SPECULARTERM\n\n\nfinalSpecularScaled +\n#endif\n#ifdef REFLECTION\n\n\nfinalRadianceScaled +\n#endif\n#ifdef REFRACTION\nfinalRefraction*vLightingIntensity.z +\n#endif\nfinalEmissive*vLightingIntensity.y,\nalpha);\n\n#ifdef LIGHTMAP\n#ifndef LIGHTMAPEXCLUDED\n#ifdef USELIGHTMAPASSHADOWMAP\nfinalColor.rgb*=lightmapColor;\n#else\nfinalColor.rgb+=lightmapColor;\n#endif\n#endif\n#endif\n\nfinalColor=max(finalColor,0.0);\n#include\n#include(color,finalColor)\n#ifdef IMAGEPROCESSINGPOSTPROCESS\n\n\nfinalColor.rgb=clamp(finalColor.rgb,0.,30.0);\n#else\n\nfinalColor=applyImageProcessing(finalColor);\n#endif\n#ifdef PREMULTIPLYALPHA\n\nfinalColor.rgb*=finalColor.a;\n#endif\ngl_FragColor=finalColor;\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n}","spritesVertexShader":"\nattribute vec4 position;\nattribute vec4 options;\nattribute vec4 cellInfo;\nattribute vec4 color;\n\nuniform vec2 textureInfos;\nuniform mat4 view;\nuniform mat4 projection;\n\nvarying vec2 vUV;\nvarying vec4 vColor;\n#include\nvoid main(void) { \nvec3 viewPos=(view*vec4(position.xyz,1.0)).xyz; \nvec2 cornerPos;\nfloat angle=position.w;\nvec2 size=vec2(options.x,options.y);\nvec2 offset=options.zw;\nvec2 uvScale=textureInfos.xy;\ncornerPos=vec2(offset.x-0.5,offset.y-0.5)*size;\n\nvec3 rotatedCorner;\nrotatedCorner.x=cornerPos.x*cos(angle)-cornerPos.y*sin(angle);\nrotatedCorner.y=cornerPos.x*sin(angle)+cornerPos.y*cos(angle);\nrotatedCorner.z=0.;\n\nviewPos+=rotatedCorner;\ngl_Position=projection*vec4(viewPos,1.0); \n\nvColor=color;\n\nvec2 uvOffset=vec2(abs(offset.x-cellInfo.x),1.0-abs(offset.y-cellInfo.y));\nvUV=(uvOffset+cellInfo.zw)*uvScale;\n\n#ifdef FOG\nvFogDistance=viewPos;\n#endif\n}","spritesPixelShader":"uniform bool alphaTest;\nvarying vec4 vColor;\n\nvarying vec2 vUV;\nuniform sampler2D diffuseSampler;\n\n#include\nvoid main(void) {\nvec4 color=texture2D(diffuseSampler,vUV);\nif (alphaTest) \n{\nif (color.a<0.95)\ndiscard;\n}\ncolor*=vColor;\n#include\ngl_FragColor=color;\n}","particlesVertexShader":"\nattribute vec3 position;\nattribute vec4 color;\nattribute vec4 options;\nattribute float cellIndex;\n\nuniform mat4 view;\nuniform mat4 projection;\nuniform vec3 particlesInfos; \n\nvarying vec2 vUV;\nvarying vec4 vColor;\n#ifdef CLIPPLANE\nuniform vec4 vClipPlane;\nuniform mat4 invView;\nvarying float fClipDistance;\n#endif\nvoid main(void) { \nvec3 viewPos=(view*vec4(position,1.0)).xyz; \nvec3 cornerPos;\nfloat size=options.y;\nfloat angle=options.x;\nvec2 offset=options.zw;\ncornerPos=vec3(offset.x-0.5,offset.y-0.5,0.)*size;\n\nvec3 rotatedCorner;\nrotatedCorner.x=cornerPos.x*cos(angle)-cornerPos.y*sin(angle);\nrotatedCorner.y=cornerPos.x*sin(angle)+cornerPos.y*cos(angle);\nrotatedCorner.z=0.;\n\nviewPos+=rotatedCorner;\ngl_Position=projection*vec4(viewPos,1.0); \nvColor=color;\n#ifdef ANIMATESHEET\nfloat rowOffset=floor(cellIndex/particlesInfos.z);\nfloat columnOffset=cellIndex-rowOffset*particlesInfos.z;\nvec2 uvScale=particlesInfos.xy;\nvec2 uvOffset=vec2(offset.x ,1.0-offset.y);\nvUV=(uvOffset+vec2(columnOffset,rowOffset))*uvScale;\n#else\nvUV=offset;\n#endif\n\n#ifdef CLIPPLANE\nvec4 worldPos=invView*vec4(viewPos,1.0);\nfClipDistance=dot(worldPos,vClipPlane);\n#endif\n}","particlesPixelShader":"\nvarying vec2 vUV;\nvarying vec4 vColor;\nuniform vec4 textureMask;\nuniform sampler2D diffuseSampler;\n#ifdef CLIPPLANE\nvarying float fClipDistance;\n#endif\nvoid main(void) {\n#ifdef CLIPPLANE\nif (fClipDistance>0.0)\ndiscard;\n#endif\nvec4 baseColor=texture2D(diffuseSampler,vUV);\ngl_FragColor=(baseColor*textureMask+(vec4(1.,1.,1.,1.)-textureMask))*vColor;\n}","colorVertexShader":"\nattribute vec3 position;\n#ifdef VERTEXCOLOR\nattribute vec4 color;\n#endif\n#include\n\nuniform mat4 viewProjection;\nuniform mat4 world;\n\n#ifdef VERTEXCOLOR\nvarying vec4 vColor;\n#endif\nvoid main(void) {\nmat4 finalWorld=world;\n#include\ngl_Position=viewProjection*finalWorld*vec4(position,1.0);\n#ifdef VERTEXCOLOR\n\nvColor=color;\n#endif\n}","colorPixelShader":"#ifdef VERTEXCOLOR\nvarying vec4 vColor;\n#else\nuniform vec4 color;\n#endif\nvoid main(void) {\n#ifdef VERTEXCOLOR\ngl_FragColor=vColor;\n#else\ngl_FragColor=color;\n#endif\n}","postprocessVertexShader":"\nattribute vec2 position;\nuniform vec2 scale;\n\nvarying vec2 vUV;\nconst vec2 madd=vec2(0.5,0.5);\nvoid main(void) { \nvUV=(position*madd+madd)*scale;\ngl_Position=vec4(position,0.0,1.0);\n}","passPixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nvoid main(void) \n{\ngl_FragColor=texture2D(textureSampler,vUV);\n}","shadowMapVertexShader":"\nattribute vec3 position;\n#include\n\n#include\nuniform mat4 viewProjection;\nuniform vec2 biasAndScale;\nuniform vec2 depthValues;\nvarying float vDepthMetric;\n#ifdef ALPHATEST\nvarying vec2 vUV;\nuniform mat4 diffuseMatrix;\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#endif\nvoid main(void)\n{\n#include\n#include\nvec4 worldPos=finalWorld*vec4(position,1.0);\ngl_Position=viewProjection*worldPos;\nvDepthMetric=((gl_Position.z+depthValues.x)/(depthValues.y))+biasAndScale.x;\n#ifdef ALPHATEST\n#ifdef UV1\nvUV=vec2(diffuseMatrix*vec4(uv,1.0,0.0));\n#endif\n#ifdef UV2\nvUV=vec2(diffuseMatrix*vec4(uv2,1.0,0.0));\n#endif\n#endif\n}","shadowMapPixelShader":"#ifndef FLOAT\nvec4 pack(float depth)\n{\nconst vec4 bit_shift=vec4(255.0*255.0*255.0,255.0*255.0,255.0,1.0);\nconst vec4 bit_mask=vec4(0.0,1.0/255.0,1.0/255.0,1.0/255.0);\nvec4 res=fract(depth*bit_shift);\nres-=res.xxyz*bit_mask;\nreturn res;\n}\n#endif\nvarying float vDepthMetric;\n#ifdef ALPHATEST\nvarying vec2 vUV;\nuniform sampler2D diffuseSampler;\n#endif\nuniform vec2 biasAndScale;\nuniform vec2 depthValues;\nvoid main(void)\n{\n#ifdef ALPHATEST\nif (texture2D(diffuseSampler,vUV).a<0.4)\ndiscard;\n#endif\nfloat depth=vDepthMetric;\n#ifdef ESM\ndepth=clamp(exp(-min(87.,biasAndScale.y*depth)),0.,1.);\n#endif\n#ifdef FLOAT\ngl_FragColor=vec4(depth,1.0,1.0,1.0);\n#else\ngl_FragColor=pack(depth);\n#endif\n}","depthBoxBlurPixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\n\nuniform vec2 screenSize;\nvoid main(void)\n{\nvec4 colorDepth=vec4(0.0);\nfor (int x=-OFFSET; x<=OFFSET; x++)\nfor (int y=-OFFSET; y<=OFFSET; y++)\ncolorDepth+=texture2D(textureSampler,vUV+vec2(x,y)/screenSize);\ngl_FragColor=(colorDepth/float((OFFSET*2+1)*(OFFSET*2+1)));\n}","proceduralVertexShader":"\nattribute vec2 position;\n\nvarying vec2 vPosition;\nvarying vec2 vUV;\nconst vec2 madd=vec2(0.5,0.5);\nvoid main(void) { \nvPosition=position;\nvUV=position*madd+madd;\ngl_Position=vec4(position,0.0,1.0);\n}","depthVertexShader":"\nattribute vec3 position;\n#include\n\n#include\nuniform mat4 viewProjection;\nuniform vec2 depthValues;\n#if defined(ALPHATEST) || defined(NEED_UV)\nvarying vec2 vUV;\nuniform mat4 diffuseMatrix;\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#endif\nvarying float vDepthMetric;\nvoid main(void)\n{\n#include\n#include\ngl_Position=viewProjection*finalWorld*vec4(position,1.0);\nvDepthMetric=((gl_Position.z+depthValues.x)/(depthValues.y));\n#if defined(ALPHATEST) || defined(BASIC_RENDER)\n#ifdef UV1\nvUV=vec2(diffuseMatrix*vec4(uv,1.0,0.0));\n#endif\n#ifdef UV2\nvUV=vec2(diffuseMatrix*vec4(uv2,1.0,0.0));\n#endif\n#endif\n}","depthPixelShader":"#ifdef ALPHATEST\nvarying vec2 vUV;\nuniform sampler2D diffuseSampler;\n#endif\nvarying float vDepthMetric;\nvoid main(void)\n{\n#ifdef ALPHATEST\nif (texture2D(diffuseSampler,vUV).a<0.4)\ndiscard;\n#endif\ngl_FragColor=vec4(vDepthMetric,vDepthMetric*vDepthMetric,0.0,1.0);\n}","ssaoPixelShader":"\nuniform sampler2D textureSampler;\nvarying vec2 vUV;\n#ifdef SSAO\nuniform sampler2D randomSampler;\nuniform float randTextureTiles;\nuniform float samplesFactor;\nuniform vec3 sampleSphere[SAMPLES];\nuniform float totalStrength;\nuniform float radius;\nuniform float area;\nuniform float fallOff;\nuniform float base;\nvec3 normalFromDepth(float depth,vec2 coords)\n{\nvec2 offset1=vec2(0.0,radius);\nvec2 offset2=vec2(radius,0.0);\nfloat depth1=texture2D(textureSampler,coords+offset1).r;\nfloat depth2=texture2D(textureSampler,coords+offset2).r;\nvec3 p1=vec3(offset1,depth1-depth);\nvec3 p2=vec3(offset2,depth2-depth);\nvec3 normal=cross(p1,p2);\nnormal.z=-normal.z;\nreturn normalize(normal);\n}\nvoid main()\n{\nvec3 random=normalize(texture2D(randomSampler,vUV*randTextureTiles).rgb);\nfloat depth=texture2D(textureSampler,vUV).r;\nvec3 position=vec3(vUV,depth);\nvec3 normal=normalFromDepth(depth,vUV);\nfloat radiusDepth=radius/depth;\nfloat occlusion=0.0;\nvec3 ray;\nvec3 hemiRay;\nfloat occlusionDepth;\nfloat difference;\nfor (int i=0; imaxZ) {\ngl_FragColor=vec4(1.0,1.0,1.0,1.0);\nreturn;\n}\nfor (int i=0; i1.0 || offset.y>1.0) {\ncontinue;\n}\n\nfloat sampleDepth=abs(texture2D(textureSampler,offset.xy).r);\n\nfloat rangeCheck=abs(depth-sampleDepth)=1e-5 ? 1.0 : 0.0)*rangeCheck;\n}\n\nfloat ao=1.0-totalStrength*occlusion*samplesFactor;\nfloat result=clamp(ao+base,0.0,1.0);\ngl_FragColor=vec4(vec3(result),1.0);\n}\n#endif\n#ifdef BILATERAL_BLUR\nuniform sampler2D depthSampler;\nuniform float outSize;\nuniform float samplerOffsets[SAMPLES];\nvec4 blur9(sampler2D image,vec2 uv,float resolution,vec2 direction) {\nvec4 color=vec4(0.0);\nvec2 off1=vec2(1.3846153846)*direction;\nvec2 off2=vec2(3.2307692308)*direction;\ncolor+=texture2D(image,uv)*0.2270270270;\ncolor+=texture2D(image,uv+(off1/resolution))*0.3162162162;\ncolor+=texture2D(image,uv-(off1/resolution))*0.3162162162;\ncolor+=texture2D(image,uv+(off2/resolution))*0.0702702703;\ncolor+=texture2D(image,uv-(off2/resolution))*0.0702702703;\nreturn color;\n}\nvec4 blur13(sampler2D image,vec2 uv,float resolution,vec2 direction) {\nvec4 color=vec4(0.0);\nvec2 off1=vec2(1.411764705882353)*direction;\nvec2 off2=vec2(3.2941176470588234)*direction;\nvec2 off3=vec2(5.176470588235294)*direction;\ncolor+=texture2D(image,uv)*0.1964825501511404;\ncolor+=texture2D(image,uv+(off1/resolution))*0.2969069646728344;\ncolor+=texture2D(image,uv-(off1/resolution))*0.2969069646728344;\ncolor+=texture2D(image,uv+(off2/resolution))*0.09447039785044732;\ncolor+=texture2D(image,uv-(off2/resolution))*0.09447039785044732;\ncolor+=texture2D(image,uv+(off3/resolution))*0.010381362401148057;\ncolor+=texture2D(image,uv-(off3/resolution))*0.010381362401148057;\nreturn color;\n}\nvec4 blur13Bilateral(sampler2D image,vec2 uv,float resolution,vec2 direction) {\nvec4 color=vec4(0.0);\nvec2 off1=vec2(1.411764705882353)*direction;\nvec2 off2=vec2(3.2941176470588234)*direction;\nvec2 off3=vec2(5.176470588235294)*direction;\nfloat compareDepth=abs(texture2D(depthSampler,uv).r);\nfloat sampleDepth;\nfloat weight;\nfloat weightSum=30.0;\ncolor+=texture2D(image,uv)*30.0;\nsampleDepth=abs(texture2D(depthSampler,uv+(off1/resolution)).r);\nweight=clamp(1.0/( 0.003+abs(compareDepth-sampleDepth)),0.0,30.0);\nweightSum+=weight;\ncolor+=texture2D(image,uv+(off1/resolution))*weight;\nsampleDepth=abs(texture2D(depthSampler,uv-(off1/resolution)).r);\nweight=clamp(1.0/( 0.003+abs(compareDepth-sampleDepth)),0.0,30.0);\nweightSum+=weight;\ncolor+=texture2D(image,uv-(off1/resolution))*weight;\nsampleDepth=abs(texture2D(depthSampler,uv+(off2/resolution)).r);\nweight=clamp(1.0/( 0.003+abs(compareDepth-sampleDepth)),0.0,30.0);\nweightSum+=weight;\ncolor+=texture2D(image,uv+(off2/resolution))*weight;\nsampleDepth=abs(texture2D(depthSampler,uv-(off2/resolution)).r);\nweight=clamp(1.0/( 0.003+abs(compareDepth-sampleDepth)),0.0,30.0);\nweightSum+=weight;\ncolor+=texture2D(image,uv-(off2/resolution))*weight;\nsampleDepth=abs(texture2D(depthSampler,uv+(off3/resolution)).r);\nweight=clamp(1.0/( 0.003+abs(compareDepth-sampleDepth)),0.0,30.0);\nweightSum+=weight;\ncolor+=texture2D(image,uv+(off3/resolution))*weight;\nsampleDepth=abs(texture2D(depthSampler,uv-(off3/resolution)).r);\nweight=clamp(1.0/( 0.003+abs(compareDepth-sampleDepth)),0.0,30.0);\nweightSum+=weight;\ncolor+=texture2D(image,uv-(off3/resolution))*weight;\nreturn color/weightSum;\n}\nvoid main()\n{\n#if EXPENSIVE\nfloat compareDepth=abs(texture2D(depthSampler,vUV).r);\nfloat texelsize=1.0/outSize;\nfloat result=0.0;\nfloat weightSum=0.0;\nfor (int i=0; i1.0) { lum_threshold=0.94+0.01*threshold; }\nelse { lum_threshold=0.5+0.44*threshold; }\nluminance=clamp((luminance-lum_threshold)*(1.0/(1.0-lum_threshold)),0.0,1.0);\nhighlight*=luminance*gain;\nhighlight.a=1.0;\nreturn highlight;\n}\nvoid main(void)\n{\nvec4 original=texture2D(textureSampler,vUV);\n\nif (gain == -1.0) {\ngl_FragColor=vec4(0.0,0.0,0.0,1.0);\nreturn;\n}\nfloat w=2.0/screen_width;\nfloat h=2.0/screen_height;\nfloat weight=1.0;\n\nvec4 blurred=vec4(0.0,0.0,0.0,0.0);\n#ifdef PENTAGON\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.84*w,0.43*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(0.48*w,-1.29*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(0.61*w,1.51*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.55*w,-0.74*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.71*w,-0.52*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.94*w,1.59*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.40*w,-1.87*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.62*w,1.16*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.09*w,0.25*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.46*w,-1.71*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(0.08*w,2.42*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.85*w,-1.89*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.89*w,0.16*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.29*w,1.88*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(0.40*w,-2.81*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.54*w,2.26*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.60*w,-0.61*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.31*w,-1.30*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.83*w,2.53*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.12*w,-2.48*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.60*w,1.11*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.82*w,0.99*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.50*w,-2.81*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(0.85*w,3.33*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.94*w,-1.92*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(3.27*w,-0.53*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.95*w,2.48*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.23*w,-3.04*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.17*w,2.05*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.97*w,-0.04*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.25*w,-2.00*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.31*w,3.08*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.94*w,-2.59*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(3.37*w,0.64*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-3.13*w,1.93*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.03*w,-3.65*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.60*w,3.17*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-3.14*w,-1.19*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(3.00*w,-1.19*h)));\n#else\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.85*w,0.36*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(0.52*w,-1.14*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(0.46*w,1.42*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.46*w,-0.83*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.79*w,-0.42*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.11*w,1.62*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.29*w,-2.07*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.69*w,1.39*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.28*w,0.12*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.65*w,-1.69*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.08*w,2.44*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.63*w,-1.90*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.55*w,0.31*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.13*w,1.52*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(0.56*w,-2.61*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.38*w,2.34*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.64*w,-0.81*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.53*w,-1.21*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.06*w,2.63*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.00*w,-2.69*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.59*w,1.32*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.82*w,0.78*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.57*w,-2.50*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(0.54*w,2.93*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.39*w,-1.81*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(3.01*w,-0.28*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.04*w,2.25*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.02*w,-3.05*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.09*w,2.25*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-3.07*w,-0.25*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.44*w,-1.90*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-0.52*w,3.05*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-1.68*w,-2.61*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(3.01*w,0.79*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.76*w,1.46*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.05*w,-2.94*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(1.21*w,2.88*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(-2.84*w,-1.30*h)));\nblurred+=highlightColor(texture2D(textureSampler,vUV+vec2(2.98*w,-0.96*h)));\n#endif\nblurred/=39.0;\ngl_FragColor=blurred;\n\n}","depthOfFieldPixelShader":"\n\n\n\n\nuniform sampler2D textureSampler;\nuniform sampler2D highlightsSampler;\nuniform sampler2D depthSampler;\nuniform sampler2D grainSampler;\n\nuniform float grain_amount;\nuniform bool blur_noise;\nuniform float screen_width;\nuniform float screen_height;\nuniform float distortion;\nuniform bool dof_enabled;\n\nuniform float screen_distance; \nuniform float aperture;\nuniform float darken;\nuniform float edge_blur;\nuniform bool highlights;\n\nuniform float near;\nuniform float far;\n\nvarying vec2 vUV;\n\n#define PI 3.14159265\n#define TWOPI 6.28318530\n#define inverse_focal_length 0.1 \n\nvec2 centered_screen_pos;\nvec2 distorted_coords;\nfloat radius2;\nfloat radius;\n\nvec2 rand(vec2 co)\n{\nfloat noise1=(fract(sin(dot(co,vec2(12.9898,78.233)))*43758.5453));\nfloat noise2=(fract(sin(dot(co,vec2(12.9898,78.233)*2.0))*43758.5453));\nreturn clamp(vec2(noise1,noise2),0.0,1.0);\n}\n\nvec2 getDistortedCoords(vec2 coords) {\nif (distortion == 0.0) { return coords; }\nvec2 direction=1.0*normalize(centered_screen_pos);\nvec2 dist_coords=vec2(0.5,0.5);\ndist_coords.x=0.5+direction.x*radius2*1.0;\ndist_coords.y=0.5+direction.y*radius2*1.0;\nfloat dist_amount=clamp(distortion*0.23,0.0,1.0);\ndist_coords=mix(coords,dist_coords,dist_amount);\nreturn dist_coords;\n}\n\nfloat sampleScreen(inout vec4 color,const in vec2 offset,const in float weight) {\n\nvec2 coords=distorted_coords;\nfloat angle=rand(coords*100.0).x*TWOPI;\ncoords+=vec2(offset.x*cos(angle)-offset.y*sin(angle),offset.x*sin(angle)+offset.y*cos(angle));\ncolor+=texture2D(textureSampler,coords)*weight;\nreturn weight;\n}\n\nfloat getBlurLevel(float size) {\nreturn min(3.0,ceil(size/1.0));\n}\n\nvec4 getBlurColor(float size) {\nvec4 col=texture2D(textureSampler,distorted_coords);\nif (size == 0.0) { return col; }\n\n\nfloat blur_level=getBlurLevel(size);\nfloat w=(size/screen_width);\nfloat h=(size/screen_height);\nfloat total_weight=1.0;\nvec2 sample_coords;\ntotal_weight+=sampleScreen(col,vec2(-0.50*w,0.24*h),0.93);\ntotal_weight+=sampleScreen(col,vec2(0.30*w,-0.75*h),0.90);\ntotal_weight+=sampleScreen(col,vec2(0.36*w,0.96*h),0.87);\ntotal_weight+=sampleScreen(col,vec2(-1.08*w,-0.55*h),0.85);\ntotal_weight+=sampleScreen(col,vec2(1.33*w,-0.37*h),0.83);\ntotal_weight+=sampleScreen(col,vec2(-0.82*w,1.31*h),0.80);\ntotal_weight+=sampleScreen(col,vec2(-0.31*w,-1.67*h),0.78);\ntotal_weight+=sampleScreen(col,vec2(1.47*w,1.11*h),0.76);\ntotal_weight+=sampleScreen(col,vec2(-1.97*w,0.19*h),0.74);\ntotal_weight+=sampleScreen(col,vec2(1.42*w,-1.57*h),0.72);\nif (blur_level>1.0) {\ntotal_weight+=sampleScreen(col,vec2(0.01*w,2.25*h),0.70);\ntotal_weight+=sampleScreen(col,vec2(-1.62*w,-1.74*h),0.67);\ntotal_weight+=sampleScreen(col,vec2(2.49*w,0.20*h),0.65);\ntotal_weight+=sampleScreen(col,vec2(-2.07*w,1.61*h),0.63);\ntotal_weight+=sampleScreen(col,vec2(0.46*w,-2.70*h),0.61);\ntotal_weight+=sampleScreen(col,vec2(1.55*w,2.40*h),0.59);\ntotal_weight+=sampleScreen(col,vec2(-2.88*w,-0.75*h),0.56);\ntotal_weight+=sampleScreen(col,vec2(2.73*w,-1.44*h),0.54);\ntotal_weight+=sampleScreen(col,vec2(-1.08*w,3.02*h),0.52);\ntotal_weight+=sampleScreen(col,vec2(-1.28*w,-3.05*h),0.49);\n}\nif (blur_level>2.0) {\ntotal_weight+=sampleScreen(col,vec2(3.11*w,1.43*h),0.46);\ntotal_weight+=sampleScreen(col,vec2(-3.36*w,1.08*h),0.44);\ntotal_weight+=sampleScreen(col,vec2(1.80*w,-3.16*h),0.41);\ntotal_weight+=sampleScreen(col,vec2(0.83*w,3.65*h),0.38);\ntotal_weight+=sampleScreen(col,vec2(-3.16*w,-2.19*h),0.34);\ntotal_weight+=sampleScreen(col,vec2(3.92*w,-0.53*h),0.31);\ntotal_weight+=sampleScreen(col,vec2(-2.59*w,3.12*h),0.26);\ntotal_weight+=sampleScreen(col,vec2(-0.20*w,-4.15*h),0.22);\ntotal_weight+=sampleScreen(col,vec2(3.02*w,3.00*h),0.15);\n}\ncol/=total_weight; \n\nif (darken>0.0) {\ncol.rgb*=clamp(0.3,1.0,1.05-size*0.5*darken);\n}\n\n\n\n\nreturn col;\n}\nvoid main(void)\n{\n\ncentered_screen_pos=vec2(vUV.x-0.5,vUV.y-0.5);\nradius2=centered_screen_pos.x*centered_screen_pos.x+centered_screen_pos.y*centered_screen_pos.y;\nradius=sqrt(radius2);\ndistorted_coords=getDistortedCoords(vUV); \nvec2 texels_coords=vec2(vUV.x*screen_width,vUV.y*screen_height); \nfloat depth=texture2D(depthSampler,distorted_coords).r; \nfloat distance=near+(far-near)*depth; \nvec4 color=texture2D(textureSampler,vUV); \n\n\nfloat coc=abs(aperture*(screen_distance*(inverse_focal_length-1.0/distance)-1.0));\n\nif (dof_enabled == false || coc<0.07) { coc=0.0; }\n\nfloat edge_blur_amount=0.0;\nif (edge_blur>0.0) {\nedge_blur_amount=clamp((radius*2.0-1.0+0.15*edge_blur)*1.5,0.0,1.0)*1.3;\n}\n\nfloat blur_amount=max(edge_blur_amount,coc);\n\nif (blur_amount == 0.0) {\ngl_FragColor=texture2D(textureSampler,distorted_coords);\n}\nelse {\n\ngl_FragColor=getBlurColor(blur_amount*1.7);\n\nif (highlights) {\ngl_FragColor.rgb+=clamp(coc,0.0,1.0)*texture2D(highlightsSampler,distorted_coords).rgb;\n}\nif (blur_noise) {\n\nvec2 noise=rand(distorted_coords)*0.01*blur_amount;\nvec2 blurred_coord=vec2(distorted_coords.x+noise.x,distorted_coords.y+noise.y);\ngl_FragColor=0.04*texture2D(textureSampler,blurred_coord)+0.96*gl_FragColor;\n}\n}\n\nif (grain_amount>0.0) {\nvec4 grain_color=texture2D(grainSampler,texels_coords*0.003);\ngl_FragColor.rgb+=(-0.5+grain_color.rgb)*0.30*grain_amount;\n}\n}\n","standardPixelShader":"uniform sampler2D textureSampler;\nvarying vec2 vUV;\n#if defined(PASS_POST_PROCESS)\nvoid main(void)\n{\nvec4 color=texture2D(textureSampler,vUV);\ngl_FragColor=color;\n}\n#endif\n#if defined(DOWN_SAMPLE_X4)\nuniform vec2 dsOffsets[16];\nvoid main(void)\n{\nvec4 average=vec4(0.0,0.0,0.0,0.0);\naverage=texture2D(textureSampler,vUV+dsOffsets[0]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[1]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[2]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[3]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[4]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[5]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[6]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[7]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[8]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[9]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[10]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[11]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[12]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[13]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[14]);\naverage+=texture2D(textureSampler,vUV+dsOffsets[15]);\naverage/=16.0;\ngl_FragColor=average;\n}\n#endif\n#if defined(BRIGHT_PASS)\nuniform vec2 dsOffsets[4];\nuniform float brightThreshold;\nvoid main(void)\n{\nvec4 average=vec4(0.0,0.0,0.0,0.0);\naverage=texture2D(textureSampler,vUV+vec2(dsOffsets[0].x,dsOffsets[0].y));\naverage+=texture2D(textureSampler,vUV+vec2(dsOffsets[1].x,dsOffsets[1].y));\naverage+=texture2D(textureSampler,vUV+vec2(dsOffsets[2].x,dsOffsets[2].y));\naverage+=texture2D(textureSampler,vUV+vec2(dsOffsets[3].x,dsOffsets[3].y));\naverage*=0.25;\nfloat luminance=length(average.rgb);\nif (luminanceshadowPixelDepth)\naccumFog+=sunColor*computeScattering(dot(rayDirection,sunDirection));\ncurrentPosition+=stepL;\n}\naccumFog/=NB_STEPS;\nvec3 color=accumFog*scatteringPower;\ngl_FragColor=vec4(color*exp(color) ,1.0);\n}\n#endif\n#if defined(VLSMERGE)\nuniform sampler2D originalSampler;\nvoid main(void)\n{\ngl_FragColor=texture2D(originalSampler,vUV)+texture2D(textureSampler,vUV);\n}\n#endif\n#if defined(LUMINANCE)\nuniform vec2 lumOffsets[4];\nvoid main()\n{\nfloat average=0.0;\nvec4 color=vec4(0.0);\nfloat maximum=-1e20;\nvec3 weight=vec3(0.299,0.587,0.114);\nfor (int i=0; i<4; i++)\n{\ncolor=texture2D(textureSampler,vUV+ lumOffsets[i]);\n\nfloat GreyValue=dot(color.rgb,vec3(0.33,0.33,0.33));\n\n#ifdef WEIGHTED_AVERAGE\nfloat GreyValue=dot(color.rgb,weight);\n#endif\n#ifdef BRIGHTNESS\nfloat GreyValue=max(color.r,max(color.g,color.b));\n#endif\n#ifdef HSL_COMPONENT\nfloat GreyValue=0.5*(max(color.r,max(color.g,color.b))+min(color.r,min(color.g,color.b)));\n#endif\n#ifdef MAGNITUDE\nfloat GreyValue=length(color.rgb);\n#endif\nmaximum=max(maximum,GreyValue);\naverage+=(0.25*log(1e-5+GreyValue));\n}\naverage=exp(average);\ngl_FragColor=vec4(average,maximum,0.0,1.0);\n}\n#endif\n#if defined(LUMINANCE_DOWN_SAMPLE)\nuniform vec2 dsOffsets[9];\nuniform float halfDestPixelSize;\n#ifdef FINAL_DOWN_SAMPLER\nvec4 pack(float value) {\nconst vec4 bit_shift=vec4(255.0*255.0*255.0,255.0*255.0,255.0,1.0);\nconst vec4 bit_mask=vec4(0.0,1.0/255.0,1.0/255.0,1.0/255.0);\nvec4 res=fract(value*bit_shift);\nres-=res.xxyz*bit_mask;\nreturn res;\n}\n#endif\nvoid main()\n{\nvec4 color=vec4(0.0);\nfloat average=0.0;\nfor (int i=0; i<9; i++)\n{\ncolor=texture2D(textureSampler,vUV+vec2(halfDestPixelSize,halfDestPixelSize)+dsOffsets[i]);\naverage+=color.r;\n}\naverage/=9.0;\n#ifdef FINAL_DOWN_SAMPLER\ngl_FragColor=pack(average);\n#else\ngl_FragColor=vec4(average,average,0.0,1.0);\n#endif\n}\n#endif\n#if defined(HDR)\nuniform sampler2D textureAdderSampler;\nuniform float averageLuminance;\nvoid main()\n{\nvec4 color=texture2D(textureAdderSampler,vUV);\nvec4 adjustedColor=color/averageLuminance;\ncolor=adjustedColor;\ncolor.a=1.0;\ngl_FragColor=color;\n}\n#endif\n#if defined(LENS_FLARE)\n#define GHOSTS 3\nuniform sampler2D lensColorSampler;\nuniform float strength;\nuniform float ghostDispersal;\nuniform float haloWidth;\nuniform vec2 resolution;\nuniform float distortionStrength;\nfloat hash(vec2 p)\n{\nfloat h=dot(p,vec2(127.1,311.7));\nreturn -1.0+2.0*fract(sin(h)*43758.5453123);\n}\nfloat noise(in vec2 p)\n{\nvec2 i=floor(p);\nvec2 f=fract(p);\nvec2 u=f*f*(3.0-2.0*f);\nreturn mix(mix(hash(i+vec2(0.0,0.0)),\nhash(i+vec2(1.0,0.0)),u.x),\nmix(hash(i+vec2(0.0,1.0)),\nhash(i+vec2(1.0,1.0)),u.x),u.y);\n}\nfloat fbm(vec2 p)\n{\nfloat f=0.0;\nf+=0.5000*noise(p); p*=2.02;\nf+=0.2500*noise(p); p*=2.03;\nf+=0.1250*noise(p); p*=2.01;\nf+=0.0625*noise(p); p*=2.04;\nf/=0.9375;\nreturn f;\n}\nvec3 pattern(vec2 uv)\n{\nvec2 p=-1.0+2.0*uv;\nfloat p2=dot(p,p);\nfloat f=fbm(vec2(15.0*p2))/2.0;\nfloat r=0.2+0.6*sin(12.5*length(uv-vec2(0.5)));\nfloat g=0.2+0.6*sin(20.5*length(uv-vec2(0.5)));\nfloat b=0.2+0.6*sin(17.2*length(uv-vec2(0.5)));\nreturn (1.0-f)*vec3(r,g,b);\n}\nfloat luminance(vec3 color)\n{\nreturn dot(color.rgb,vec3(0.2126,0.7152,0.0722));\n}\nvec4 textureDistorted(sampler2D tex,vec2 texcoord,vec2 direction,vec3 distortion)\n{\nreturn vec4(\ntexture2D(tex,texcoord+direction*distortion.r).r,\ntexture2D(tex,texcoord+direction*distortion.g).g,\ntexture2D(tex,texcoord+direction*distortion.b).b,\n1.0\n);\n}\nvoid main(void)\n{\nvec2 uv=-vUV+vec2(1.0);\nvec2 ghostDir=(vec2(0.5)-uv)*ghostDispersal;\nvec2 texelSize=1.0/resolution;\nvec3 distortion=vec3(-texelSize.x*distortionStrength,0.0,texelSize.x*distortionStrength);\nvec4 result=vec4(0.0);\nfloat ghostIndice=1.0;\nfor (int i=0; i=nSamples)\nbreak;\nvec2 offset1=vUV+velocity*(float(i)/float(nSamples-1)-0.5);\nresult+=texture2D(textureSampler,offset1);\n}\ngl_FragColor=result/float(nSamples);\n}\n#endif\n","fxaaVertexShader":"\nattribute vec2 position;\nuniform vec2 texelSize;\n\nvarying vec2 vUV;\nvarying vec2 sampleCoordS;\nvarying vec2 sampleCoordE;\nvarying vec2 sampleCoordN;\nvarying vec2 sampleCoordW;\nvarying vec2 sampleCoordNW;\nvarying vec2 sampleCoordSE;\nvarying vec2 sampleCoordNE;\nvarying vec2 sampleCoordSW;\nconst vec2 madd=vec2(0.5,0.5);\nvoid main(void) { \nvUV=(position*madd+madd);\nsampleCoordS=vUV+vec2( 0.0,1.0)*texelSize;\nsampleCoordE=vUV+vec2( 1.0,0.0)*texelSize;\nsampleCoordN=vUV+vec2( 0.0,-1.0)*texelSize;\nsampleCoordW=vUV+vec2(-1.0,0.0)*texelSize;\nsampleCoordNW=vUV+vec2(-1.0,-1.0)*texelSize;\nsampleCoordSE=vUV+vec2( 1.0,1.0)*texelSize;\nsampleCoordNE=vUV+vec2( 1.0,-1.0)*texelSize;\nsampleCoordSW=vUV+vec2(-1.0,1.0)*texelSize;\ngl_Position=vec4(position,0.0,1.0);\n}","fxaaPixelShader":"uniform sampler2D textureSampler;\nuniform vec2 texelSize;\nvarying vec2 vUV;\nvarying vec2 sampleCoordS;\nvarying vec2 sampleCoordE;\nvarying vec2 sampleCoordN;\nvarying vec2 sampleCoordW;\nvarying vec2 sampleCoordNW;\nvarying vec2 sampleCoordSE;\nvarying vec2 sampleCoordNE;\nvarying vec2 sampleCoordSW;\nconst float fxaaQualitySubpix=1.0;\nconst float fxaaQualityEdgeThreshold=0.166;\nconst float fxaaQualityEdgeThresholdMin=0.0833;\nconst vec3 kLumaCoefficients=vec3(0.2126,0.7152,0.0722);\n#define FxaaLuma(rgba) dot(rgba.rgb,kLumaCoefficients)\nvoid main(){\nvec2 posM;\nposM.x=vUV.x;\nposM.y=vUV.y;\nvec4 rgbyM=texture2D(textureSampler,vUV,0.0);\nfloat lumaM=FxaaLuma(rgbyM);\nfloat lumaS=FxaaLuma(texture2D(textureSampler,sampleCoordS,0.0));\nfloat lumaE=FxaaLuma(texture2D(textureSampler,sampleCoordE,0.0));\nfloat lumaN=FxaaLuma(texture2D(textureSampler,sampleCoordN,0.0));\nfloat lumaW=FxaaLuma(texture2D(textureSampler,sampleCoordW,0.0));\nfloat maxSM=max(lumaS,lumaM);\nfloat minSM=min(lumaS,lumaM);\nfloat maxESM=max(lumaE,maxSM);\nfloat minESM=min(lumaE,minSM);\nfloat maxWN=max(lumaN,lumaW);\nfloat minWN=min(lumaN,lumaW);\nfloat rangeMax=max(maxWN,maxESM);\nfloat rangeMin=min(minWN,minESM);\nfloat rangeMaxScaled=rangeMax*fxaaQualityEdgeThreshold;\nfloat range=rangeMax-rangeMin;\nfloat rangeMaxClamped=max(fxaaQualityEdgeThresholdMin,rangeMaxScaled);\nif(range=edgeVert;\nfloat subpixA=subpixNSWE*2.0+subpixNWSWNESE;\nif (!horzSpan)\n{\nlumaN=lumaW;\n}\nif (!horzSpan) \n{\nlumaS=lumaE;\n}\nif (horzSpan) \n{\nlengthSign=texelSize.y;\n}\nfloat subpixB=(subpixA*(1.0/12.0))-lumaM;\nfloat gradientN=lumaN-lumaM;\nfloat gradientS=lumaS-lumaM;\nfloat lumaNN=lumaN+lumaM;\nfloat lumaSS=lumaS+lumaM;\nbool pairN=abs(gradientN)>=abs(gradientS);\nfloat gradient=max(abs(gradientN),abs(gradientS));\nif (pairN)\n{\nlengthSign=-lengthSign;\n}\nfloat subpixC=clamp(abs(subpixB)*subpixRcpRange,0.0,1.0);\nvec2 posB;\nposB.x=posM.x;\nposB.y=posM.y;\nvec2 offNP;\noffNP.x=(!horzSpan) ? 0.0 : texelSize.x;\noffNP.y=(horzSpan) ? 0.0 : texelSize.y;\nif (!horzSpan) \n{\nposB.x+=lengthSign*0.5;\n}\nif (horzSpan)\n{\nposB.y+=lengthSign*0.5;\n}\nvec2 posN;\nposN.x=posB.x-offNP.x*1.5;\nposN.y=posB.y-offNP.y*1.5;\nvec2 posP;\nposP.x=posB.x+offNP.x*1.5;\nposP.y=posB.y+offNP.y*1.5;\nfloat subpixD=((-2.0)*subpixC)+3.0;\nfloat lumaEndN=FxaaLuma(texture2D(textureSampler,posN,0.0));\nfloat subpixE=subpixC*subpixC;\nfloat lumaEndP=FxaaLuma(texture2D(textureSampler,posP,0.0));\nif (!pairN) \n{\nlumaNN=lumaSS;\n}\nfloat gradientScaled=gradient*1.0/4.0;\nfloat lumaMM=lumaM-lumaNN*0.5;\nfloat subpixF=subpixD*subpixE;\nbool lumaMLTZero=lumaMM<0.0;\nlumaEndN-=lumaNN*0.5;\nlumaEndP-=lumaNN*0.5;\nbool doneN=abs(lumaEndN)>=gradientScaled;\nbool doneP=abs(lumaEndP)>=gradientScaled;\nif (!doneN) \n{\nposN.x-=offNP.x*3.0;\n}\nif (!doneN) \n{\nposN.y-=offNP.y*3.0;\n}\nbool doneNP=(!doneN) || (!doneP);\nif (!doneP) \n{\nposP.x+=offNP.x*3.0;\n}\nif (!doneP)\n{\nposP.y+=offNP.y*3.0;\n}\nif (doneNP)\n{\nif (!doneN) lumaEndN=FxaaLuma(texture2D(textureSampler,posN.xy,0.0));\nif (!doneP) lumaEndP=FxaaLuma(texture2D(textureSampler,posP.xy,0.0));\nif (!doneN) lumaEndN=lumaEndN-lumaNN*0.5;\nif (!doneP) lumaEndP=lumaEndP-lumaNN*0.5;\ndoneN=abs(lumaEndN)>=gradientScaled;\ndoneP=abs(lumaEndP)>=gradientScaled;\nif (!doneN) posN.x-=offNP.x*12.0;\nif (!doneN) posN.y-=offNP.y*12.0;\ndoneNP=(!doneN) || (!doneP);\nif (!doneP) posP.x+=offNP.x*12.0;\nif (!doneP) posP.y+=offNP.y*12.0;\n}\nfloat dstN=posM.x-posN.x;\nfloat dstP=posP.x-posM.x;\nif (!horzSpan)\n{\ndstN=posM.y-posN.y;\n}\nif (!horzSpan) \n{\ndstP=posP.y-posM.y;\n}\nbool goodSpanN=(lumaEndN<0.0) != lumaMLTZero;\nfloat spanLength=(dstP+dstN);\nbool goodSpanP=(lumaEndP<0.0) != lumaMLTZero;\nfloat spanLengthRcp=1.0/spanLength;\nbool directionN=dstN[0..varyingCount]\nconst vec2 madd=vec2(0.5,0.5);\nvoid main(void) { \nsampleCenter=(position*madd+madd);\n#include[0..varyingCount]\ngl_Position=vec4(position,0.0,1.0);\n}","kernelBlurPixelShader":"\nuniform sampler2D textureSampler;\nuniform vec2 delta;\n\nvarying vec2 sampleCenter;\n#ifdef DOF\nuniform sampler2D circleOfConfusionSampler;\nuniform vec2 cameraMinMaxZ;\nfloat sampleDistance(const in vec2 offset) {\nfloat depth=texture2D(circleOfConfusionSampler,offset).g; \nreturn cameraMinMaxZ.x+(cameraMinMaxZ.y-cameraMinMaxZ.x)*depth; \n}\n#endif\n#include[0..varyingCount]\n#ifdef PACKEDFLOAT\nvec4 pack(float depth)\n{\nconst vec4 bit_shift=vec4(255.0*255.0*255.0,255.0*255.0,255.0,1.0);\nconst vec4 bit_mask=vec4(0.0,1.0/255.0,1.0/255.0,1.0/255.0);\nvec4 res=fract(depth*bit_shift);\nres-=res.xxyz*bit_mask;\nreturn res;\n}\nfloat unpack(vec4 color)\n{\nconst vec4 bit_shift=vec4(1.0/(255.0*255.0*255.0),1.0/(255.0*255.0),1.0/255.0,1.0);\nreturn dot(color,bit_shift);\n}\n#endif\nvoid main(void)\n{\n#ifdef DOF\nfloat sumOfWeights=0.0; \nfloat sampleDepth=0.0;\nfloat factor=0.0;\nfloat centerSampleDepth=sampleDistance(sampleCenter);\n#endif\nfloat computedWeight=0.0;\n#ifdef PACKEDFLOAT \nfloat blend=0.;\n#else\nvec4 blend=vec4(0.);\n#endif\n#include[0..varyingCount]\n#include[0..depCount]\n#ifdef PACKEDFLOAT\ngl_FragColor=pack(blend);\n#else\ngl_FragColor=blend;\n#endif\n#ifdef DOF\n\nif(sumOfWeights == 0.0){\ngl_FragColor=vec4(0.0,0.0,0.0,1.0);\n}\ngl_FragColor/=sumOfWeights;\n#endif\n}","depthOfFieldMergePixelShader":"\nuniform sampler2D textureSampler;\nuniform sampler2D originalSampler;\nuniform sampler2D circleOfConfusionSampler;\n#if BLUR_LEVEL>0\nuniform sampler2D blurStep1;\n#endif\n#if BLUR_LEVEL>1\nuniform sampler2D blurStep2;\n#endif\n\nvarying vec2 vUV;\nvoid main(void)\n{\nfloat coc=texture2D(circleOfConfusionSampler,vUV).r;\nvec4 original=texture2D(originalSampler,vUV);\n#if BLUR_LEVEL == 0\nvec4 blurred1=texture2D(textureSampler,vUV);\ngl_FragColor=mix(original,blurred1,coc);\n#endif\n#if BLUR_LEVEL == 1\nvec4 blurred1=texture2D(blurStep1,vUV);\nvec4 blurred2=texture2D(textureSampler,vUV); \nif(coc<0.5){\ngl_FragColor=mix(original,blurred1,coc/0.5);\n}else{\ngl_FragColor=mix(blurred1,blurred2,(coc-0.5)/0.5);\n}\n#endif\n#if BLUR_LEVEL == 2\nvec4 blurred1=texture2D(blurStep1,vUV);\nvec4 blurred2=texture2D(blurStep2,vUV);\nvec4 blurred3=texture2D(textureSampler,vUV);\nif(coc<0.33){\ngl_FragColor=mix(original,blurred1,coc/0.33);\n}else if(coc<0.66){\ngl_FragColor=mix(blurred1,blurred2,(coc-0.33)/0.33);\n}else{\ngl_FragColor=mix(blurred2,blurred3,(coc-0.66)/0.34);\n}\n#endif\n}\n","circleOfConfusionPixelShader":"\nuniform sampler2D depthSampler;\n\nvarying vec2 vUV;\n\nuniform vec2 cameraMinMaxZ;\n\nuniform float focusDistance;\nuniform float cocPrecalculation;\nfloat sampleDistance(const in vec2 offset) {\nfloat depth=texture2D(depthSampler,offset).r; \nreturn (cameraMinMaxZ.x+(cameraMinMaxZ.y-cameraMinMaxZ.x)*depth)*1000.0; \n}\nvoid main(void)\n{\nfloat pixelDistance=sampleDistance(vUV);\nfloat coc=abs(cocPrecalculation* ((focusDistance-pixelDistance)/pixelDistance));\ncoc=clamp(coc,0.0,1.0);\ngl_FragColor=vec4(coc,texture2D(depthSampler,vUV).r,coc,1.0);\n}\n","geometryVertexShader":"precision highp float;\nprecision highp int;\n#include\n#include\nattribute vec3 position;\nattribute vec3 normal;\n#if defined(ALPHATEST) || defined(NEED_UV)\nvarying vec2 vUV;\nuniform mat4 diffuseMatrix;\n#ifdef UV1\nvarying vec2 uv;\n#endif\n#ifdef UV2\nvarying vec2 uv2;\n#endif\n#endif\n\nuniform mat4 viewProjection;\nuniform mat4 view;\nvarying vec3 vNormalV;\nvarying vec4 vViewPos;\n#ifdef POSITION\nvarying vec3 vPosition;\n#endif\nvoid main(void)\n{\n#include\n#include\nvec4 pos=vec4(finalWorld*vec4(position,1.0));\nvNormalV=normalize(vec3((view*finalWorld)*vec4(normal,0.0)));\nvViewPos=view*pos;\n#ifdef POSITION\nvPosition=pos.xyz/pos.w;\n#endif\ngl_Position=viewProjection*finalWorld*vec4(position,1.0);\n#if defined(ALPHATEST) || defined(BASIC_RENDER)\n#ifdef UV1\nvUV=vec2(diffuseMatrix*vec4(uv,1.0,0.0));\n#endif\n#ifdef UV2\nvUV=vec2(diffuseMatrix*vec4(uv2,1.0,0.0));\n#endif\n#endif\n}","geometryPixelShader":"#extension GL_EXT_draw_buffers : require\nprecision highp float;\nprecision highp int;\nvarying vec3 vNormalV;\nvarying vec4 vViewPos;\n#ifdef POSITION\nvarying vec3 vPosition;\n#endif\n#ifdef ALPHATEST\nvarying vec2 vUV;\nuniform sampler2D diffuseSampler;\n#endif\n#ifdef POSITION\n#include[3]\n#else\n#include[2]\n#endif\nvoid main() {\n#ifdef ALPHATEST\nif (texture2D(diffuseSampler,vUV).a<0.4)\ndiscard;\n#endif\ngl_FragData[0]=vec4(vViewPos.z/vViewPos.w,0.0,0.0,1.0);\n\ngl_FragData[1]=vec4(normalize(vNormalV),1.0);\n\n#ifdef POSITION\ngl_FragData[2]=vec4(vPosition,1.0);\n#endif\n}","refractionPixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform sampler2D refractionSampler;\n\nuniform vec3 baseColor;\nuniform float depth;\nuniform float colorLevel;\nvoid main() {\nfloat ref=1.0-texture2D(refractionSampler,vUV).r;\nvec2 uv=vUV-vec2(0.5);\nvec2 offset=uv*depth*ref;\nvec3 sourceColor=texture2D(textureSampler,vUV-offset).rgb;\ngl_FragColor=vec4(sourceColor+sourceColor*ref*colorLevel,1.0);\n}","blackAndWhitePixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform float degree;\nvoid main(void) \n{\nvec3 color=texture2D(textureSampler,vUV).rgb;\nfloat luminance=dot(color,vec3(0.3,0.59,0.11)); \nvec3 blackAndWhite=vec3(luminance,luminance,luminance);\ngl_FragColor=vec4(color-((color-blackAndWhite)*degree),1.0);\n}","convolutionPixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform vec2 screenSize;\nuniform float kernel[9];\nvoid main(void)\n{\nvec2 onePixel=vec2(1.0,1.0)/screenSize;\nvec4 colorSum =\ntexture2D(textureSampler,vUV+onePixel*vec2(-1,-1))*kernel[0] +\ntexture2D(textureSampler,vUV+onePixel*vec2(0,-1))*kernel[1] +\ntexture2D(textureSampler,vUV+onePixel*vec2(1,-1))*kernel[2] +\ntexture2D(textureSampler,vUV+onePixel*vec2(-1,0))*kernel[3] +\ntexture2D(textureSampler,vUV+onePixel*vec2(0,0))*kernel[4] +\ntexture2D(textureSampler,vUV+onePixel*vec2(1,0))*kernel[5] +\ntexture2D(textureSampler,vUV+onePixel*vec2(-1,1))*kernel[6] +\ntexture2D(textureSampler,vUV+onePixel*vec2(0,1))*kernel[7] +\ntexture2D(textureSampler,vUV+onePixel*vec2(1,1))*kernel[8];\nfloat kernelWeight =\nkernel[0] +\nkernel[1] +\nkernel[2] +\nkernel[3] +\nkernel[4] +\nkernel[5] +\nkernel[6] +\nkernel[7] +\nkernel[8];\nif (kernelWeight<=0.0) {\nkernelWeight=1.0;\n}\ngl_FragColor=vec4((colorSum/kernelWeight).rgb,1);\n}","filterPixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform mat4 kernelMatrix;\nvoid main(void)\n{\nvec3 baseColor=texture2D(textureSampler,vUV).rgb;\nvec3 updatedColor=(kernelMatrix*vec4(baseColor,1.0)).rgb;\ngl_FragColor=vec4(updatedColor,1.0);\n}","volumetricLightScatteringPixelShader":"uniform sampler2D textureSampler;\nuniform sampler2D lightScatteringSampler;\nuniform float decay;\nuniform float exposure;\nuniform float weight;\nuniform float density;\nuniform vec2 meshPositionOnScreen;\nvarying vec2 vUV;\nvoid main(void) {\nvec2 tc=vUV;\nvec2 deltaTexCoord=(tc-meshPositionOnScreen.xy);\ndeltaTexCoord*=1.0/float(NUM_SAMPLES)*density;\nfloat illuminationDecay=1.0;\nvec4 color=texture2D(lightScatteringSampler,tc)*0.4;\nfor(int i=0; i\n#include\n#include\nvoid main(void)\n{\nvec4 result=texture2D(textureSampler,vUV);\n#ifdef IMAGEPROCESSING\n#ifndef FROMLINEARSPACE\n\nresult.rgb=toLinearSpace(result.rgb);\n#endif\n#ifdef GRAIN\nvec2 seed=vUV*(grainAnimatedSeed);\nfloat grain=dither(seed,grainVarianceAmount);\n\nfloat lum=getLuminance(result.rgb);\nfloat grainAmount=(cos(-PI+(lum*PI*2.))+1.)/2.;\nresult.rgb+=grain*grainAmount;\nresult.rgb=max(result.rgb,0.0);\n#endif\nresult=applyImageProcessing(result);\n#else\n\n#ifdef FROMLINEARSPACE\nresult=applyImageProcessing(result);\n#endif\n#endif\ngl_FragColor=result;\n}","lensFlareVertexShader":"\nattribute vec2 position;\n\nuniform mat4 viewportMatrix;\n\nvarying vec2 vUV;\nconst vec2 madd=vec2(0.5,0.5);\nvoid main(void) { \nvUV=position*madd+madd;\ngl_Position=viewportMatrix*vec4(position,0.0,1.0);\n}","lensFlarePixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\n\nuniform vec4 color;\nvoid main(void) {\nvec4 baseColor=texture2D(textureSampler,vUV);\ngl_FragColor=baseColor*color;\n}","anaglyphPixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform sampler2D leftSampler;\nvoid main(void)\n{\nvec4 leftFrag=texture2D(leftSampler,vUV);\nleftFrag=vec4(1.0,leftFrag.g,leftFrag.b,1.0);\nvec4 rightFrag=texture2D(textureSampler,vUV);\nrightFrag=vec4(rightFrag.r,1.0,1.0,1.0);\ngl_FragColor=vec4(rightFrag.rgb*leftFrag.rgb,1.0);\n}","stereoscopicInterlacePixelShader":"const vec3 TWO=vec3(2.0,2.0,2.0);\nvarying vec2 vUV;\nuniform sampler2D camASampler;\nuniform sampler2D textureSampler;\nuniform vec2 stepSize;\nvoid main(void)\n{\nbool useCamB;\nvec2 texCoord1;\nvec2 texCoord2;\nvec3 frag1;\nvec3 frag2;\n#ifdef IS_STEREOSCOPIC_HORIZ\nuseCamB=vUV.x>0.5;\ntexCoord1=vec2(useCamB ? (vUV.x-0.5)*2.0 : vUV.x*2.0,vUV.y);\ntexCoord2=vec2(texCoord1.x+stepSize.x,vUV.y);\n#else\nuseCamB=vUV.y>0.5;\ntexCoord1=vec2(vUV.x,useCamB ? (vUV.y-0.5)*2.0 : vUV.y*2.0);\ntexCoord2=vec2(vUV.x,texCoord1.y+stepSize.y);\n#endif\n\nif (useCamB){\nfrag1=texture2D(textureSampler,texCoord1).rgb;\nfrag2=texture2D(textureSampler,texCoord2).rgb;\n}else{\nfrag1=texture2D(camASampler ,texCoord1).rgb;\nfrag2=texture2D(camASampler ,texCoord2).rgb;\n}\ngl_FragColor=vec4((frag1+frag2)/TWO,1.0);\n}","vrDistortionCorrectionPixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\nuniform vec2 LensCenter;\nuniform vec2 Scale;\nuniform vec2 ScaleIn;\nuniform vec4 HmdWarpParam;\nvec2 HmdWarp(vec2 in01) {\nvec2 theta=(in01-LensCenter)*ScaleIn; \nfloat rSq=theta.x*theta.x+theta.y*theta.y;\nvec2 rvector=theta*(HmdWarpParam.x+HmdWarpParam.y*rSq+HmdWarpParam.z*rSq*rSq+HmdWarpParam.w*rSq*rSq*rSq);\nreturn LensCenter+Scale*rvector;\n}\nvoid main(void)\n{\nvec2 tc=HmdWarp(vUV);\nif (tc.x <0.0 || tc.x>1.0 || tc.y<0.0 || tc.y>1.0)\ngl_FragColor=vec4(0.0,0.0,0.0,0.0);\nelse{\ngl_FragColor=texture2D(textureSampler,tc);\n}\n}","glowBlurPostProcessPixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\n\nuniform vec2 screenSize;\nuniform vec2 direction;\nuniform float blurWidth;\n\nfloat getLuminance(vec3 color)\n{\nreturn dot(color,vec3(0.2126,0.7152,0.0722));\n}\nvoid main(void)\n{\nfloat weights[7];\nweights[0]=0.05;\nweights[1]=0.1;\nweights[2]=0.2;\nweights[3]=0.3;\nweights[4]=0.2;\nweights[5]=0.1;\nweights[6]=0.05;\nvec2 texelSize=vec2(1.0/screenSize.x,1.0/screenSize.y);\nvec2 texelStep=texelSize*direction*blurWidth;\nvec2 start=vUV-3.0*texelStep;\nvec4 baseColor=vec4(0.,0.,0.,0.);\nvec2 texelOffset=vec2(0.,0.);\nfor (int i=0; i<7; i++)\n{\n\nvec4 texel=texture2D(textureSampler,start+texelOffset);\nbaseColor.a+=texel.a*weights[i];\n\nfloat luminance=getLuminance(baseColor.rgb);\nfloat luminanceTexel=getLuminance(texel.rgb);\nfloat choice=step(luminanceTexel,luminance);\nbaseColor.rgb=choice*baseColor.rgb+(1.0-choice)*texel.rgb;\ntexelOffset+=texelStep;\n}\ngl_FragColor=baseColor;\n}","glowMapGenerationPixelShader":"#ifdef ALPHATEST\nvarying vec2 vUVDiffuse;\nuniform sampler2D diffuseSampler;\n#endif\n#ifdef EMISSIVE\nvarying vec2 vUVEmissive;\nuniform sampler2D emissiveSampler;\n#endif\nuniform vec4 color;\nvoid main(void)\n{\n#ifdef ALPHATEST\nif (texture2D(diffuseSampler,vUVDiffuse).a<0.4)\ndiscard;\n#endif\n#ifdef EMISSIVE\ngl_FragColor=texture2D(emissiveSampler,vUVEmissive)*color;\n#else\ngl_FragColor=color;\n#endif\n}","glowMapGenerationVertexShader":"\nattribute vec3 position;\n#include\n\n#include\nuniform mat4 viewProjection;\nvarying vec4 vPosition;\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#ifdef ALPHATEST\nvarying vec2 vUVDiffuse;\nuniform mat4 diffuseMatrix;\n#endif\n#ifdef EMISSIVE\nvarying vec2 vUVEmissive;\nuniform mat4 emissiveMatrix;\n#endif\nvoid main(void)\n{\n#include\n#include\n#ifdef CUBEMAP\nvPosition=finalWorld*vec4(position,1.0);\ngl_Position=viewProjection*finalWorld*vec4(position,1.0);\n#else\nvPosition=viewProjection*finalWorld*vec4(position,1.0);\ngl_Position=vPosition;\n#endif\n#ifdef ALPHATEST\n#ifdef DIFFUSEUV1\nvUVDiffuse=vec2(diffuseMatrix*vec4(uv,1.0,0.0));\n#endif\n#ifdef DIFFUSEUV2\nvUVDiffuse=vec2(diffuseMatrix*vec4(uv2,1.0,0.0));\n#endif\n#endif\n#ifdef EMISSIVE\n#ifdef EMISSIVEUV1\nvUVEmissive=vec2(emissiveMatrix*vec4(uv,1.0,0.0));\n#endif\n#ifdef EMISSIVEUV2\nvUVEmissive=vec2(emissiveMatrix*vec4(uv2,1.0,0.0));\n#endif\n#endif\n}","glowMapMergePixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\n#ifdef EMISSIVE\nuniform sampler2D textureSampler2;\n#endif\n\nuniform float offset;\nvoid main(void) {\nvec4 baseColor=texture2D(textureSampler,vUV);\n#ifdef EMISSIVE\nbaseColor+=texture2D(textureSampler2,vUV);\nbaseColor*=offset;\n#else\nbaseColor.a=abs(offset-baseColor.a);\n#ifdef STROKE\nfloat alpha=smoothstep(.0,.1,baseColor.a);\nbaseColor.a=alpha;\nbaseColor.rgb=baseColor.rgb*alpha;\n#endif\n#endif\ngl_FragColor=baseColor;\n}","glowMapMergeVertexShader":"\nattribute vec2 position;\n\nvarying vec2 vUV;\nconst vec2 madd=vec2(0.5,0.5);\nvoid main(void) {\nvUV=position*madd+madd;\ngl_Position=vec4(position,0.0,1.0);\n}","lineVertexShader":"\nattribute vec3 position;\nattribute vec4 normal;\n\nuniform mat4 worldViewProjection;\nuniform float width;\nuniform float aspectRatio;\nvoid main(void) {\nvec4 viewPosition=worldViewProjection*vec4(position,1.0);\nvec4 viewPositionNext=worldViewProjection*vec4(normal.xyz,1.0);\nvec2 currentScreen=viewPosition.xy/viewPosition.w;\nvec2 nextScreen=viewPositionNext.xy/viewPositionNext.w;\ncurrentScreen.x*=aspectRatio;\nnextScreen.x*=aspectRatio;\nvec2 dir=normalize(nextScreen-currentScreen);\nvec2 normalDir=vec2(-dir.y,dir.x);\nnormalDir*=width/2.0;\nnormalDir.x/=aspectRatio;\nvec4 offset=vec4(normalDir*normal.w,0.0,0.0);\ngl_Position=viewPosition+offset;\n}","linePixelShader":"uniform vec4 color;\nvoid main(void) {\ngl_FragColor=color;\n}","outlineVertexShader":"\nattribute vec3 position;\nattribute vec3 normal;\n#include\n\nuniform float offset;\n#include\nuniform mat4 viewProjection;\n#ifdef ALPHATEST\nvarying vec2 vUV;\nuniform mat4 diffuseMatrix;\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#endif\n#include\nvoid main(void)\n{\nvec3 offsetPosition=position+normal*offset;\n#include\n#include\ngl_Position=viewProjection*finalWorld*vec4(offsetPosition,1.0);\n#ifdef ALPHATEST\n#ifdef UV1\nvUV=vec2(diffuseMatrix*vec4(uv,1.0,0.0));\n#endif\n#ifdef UV2\nvUV=vec2(diffuseMatrix*vec4(uv2,1.0,0.0));\n#endif\n#endif\n#include\n}\n","outlinePixelShader":"#ifdef LOGARITHMICDEPTH\n#extension GL_EXT_frag_depth : enable\n#endif\nuniform vec4 color;\n#ifdef ALPHATEST\nvarying vec2 vUV;\nuniform sampler2D diffuseSampler;\n#endif\n#include\nvoid main(void) {\n#ifdef ALPHATEST\nif (texture2D(diffuseSampler,vUV).a<0.4)\ndiscard;\n#endif\n#include\ngl_FragColor=color;\n}","layerVertexShader":"\nattribute vec2 position;\n\nuniform vec2 scale;\nuniform vec2 offset;\nuniform mat4 textureMatrix;\n\nvarying vec2 vUV;\nconst vec2 madd=vec2(0.5,0.5);\nvoid main(void) { \nvec2 shiftedPosition=position*scale+offset;\nvUV=vec2(textureMatrix*vec4(shiftedPosition*madd+madd,1.0,0.0));\ngl_Position=vec4(shiftedPosition,0.0,1.0);\n}","layerPixelShader":"\nvarying vec2 vUV;\nuniform sampler2D textureSampler;\n\nuniform vec4 color;\nvoid main(void) {\nvec4 baseColor=texture2D(textureSampler,vUV);\n#ifdef ALPHATEST\nif (baseColor.a<0.4)\ndiscard;\n#endif\ngl_FragColor=baseColor*color;\n}","backgroundVertexShader":"precision highp float;\n#include<__decl__backgroundVertex>\n#include\n\nattribute vec3 position;\n#ifdef NORMAL\nattribute vec3 normal;\n#endif\n#include\n\n#include\n#ifdef POINTSIZE\nuniform float pointSize;\n#endif\n\nvarying vec3 vPositionW;\n#ifdef NORMAL\nvarying vec3 vNormalW;\n#endif\n#ifdef UV1\nattribute vec2 uv;\n#endif\n#ifdef UV2\nattribute vec2 uv2;\n#endif\n#ifdef MAINUV1\nvarying vec2 vMainUV1;\n#endif\n#ifdef MAINUV2\nvarying vec2 vMainUV2; \n#endif\n#if defined(DIFFUSE) && DIFFUSEDIRECTUV == 0\nvarying vec2 vDiffuseUV;\n#endif\n#include\n#include\n#include<__decl__lightFragment>[0..maxSimultaneousLights]\n#ifdef REFLECTIONMAP_SKYBOX\nvarying vec3 vPositionUVW;\n#endif\n#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\nvarying vec3 vDirectionW;\n#endif\nvoid main(void) {\n#ifdef REFLECTIONMAP_SKYBOX\nvPositionUVW=position;\n#endif \n#include\n#include\ngl_Position=viewProjection*finalWorld*vec4(position,1.0);\nvec4 worldPos=finalWorld*vec4(position,1.0);\nvPositionW=vec3(worldPos);\n#ifdef NORMAL\nmat3 normalWorld=mat3(finalWorld);\n#ifdef NONUNIFORMSCALING\nnormalWorld=transposeMat3(inverseMat3(normalWorld));\n#endif\nvNormalW=normalize(normalWorld*normal);\n#endif\n#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\nvDirectionW=normalize(vec3(finalWorld*vec4(position,0.0)));\n#ifdef EQUIRECTANGULAR_RELFECTION_FOV\nmat3 screenToWorld=inverseMat3(mat3(finalWorld*viewProjection));\nvec3 segment=mix(vDirectionW,screenToWorld*vec3(0.0,0.0,1.0),abs(fFovMultiplier-1.0));\nif (fFovMultiplier<=1.0) {\nvDirectionW=normalize(segment);\n} else {\nvDirectionW=normalize(vDirectionW+(vDirectionW-segment));\n}\n#endif\n#endif\n#ifndef UV1\nvec2 uv=vec2(0.,0.);\n#endif\n#ifndef UV2\nvec2 uv2=vec2(0.,0.);\n#endif\n#ifdef MAINUV1\nvMainUV1=uv;\n#endif \n#ifdef MAINUV2\nvMainUV2=uv2;\n#endif\n#if defined(DIFFUSE) && DIFFUSEDIRECTUV == 0 \nif (vDiffuseInfos.x == 0.)\n{\nvDiffuseUV=vec2(diffuseMatrix*vec4(uv,1.0,0.0));\n}\nelse\n{\nvDiffuseUV=vec2(diffuseMatrix*vec4(uv2,1.0,0.0));\n}\n#endif\n\n#include\n\n#include\n\n#include[0..maxSimultaneousLights]\n\n#ifdef VERTEXCOLOR\nvColor=color;\n#endif\n\n#ifdef POINTSIZE\ngl_PointSize=pointSize;\n#endif\n}\n","backgroundPixelShader":"#ifdef TEXTURELODSUPPORT\n#extension GL_EXT_shader_texture_lod : enable\n#endif\nprecision highp float;\n#include<__decl__backgroundFragment>\n#define RECIPROCAL_PI2 0.15915494\n\nuniform vec3 vEyePosition;\n\nvarying vec3 vPositionW;\n#ifdef MAINUV1\nvarying vec2 vMainUV1;\n#endif \n#ifdef MAINUV2 \nvarying vec2 vMainUV2; \n#endif \n#ifdef NORMAL\nvarying vec3 vNormalW;\n#endif\n#ifdef DIFFUSE\n#if DIFFUSEDIRECTUV == 1\n#define vDiffuseUV vMainUV1\n#elif DIFFUSEDIRECTUV == 2\n#define vDiffuseUV vMainUV2\n#else\nvarying vec2 vDiffuseUV;\n#endif\nuniform sampler2D diffuseSampler;\n#endif\n\n#ifdef REFLECTION\n#ifdef REFLECTIONMAP_3D\n#define sampleReflection(s,c) textureCube(s,c)\nuniform samplerCube reflectionSampler;\n#ifdef TEXTURELODSUPPORT\n#define sampleReflectionLod(s,c,l) textureCubeLodEXT(s,c,l)\n#else\nuniform samplerCube reflectionSamplerLow;\nuniform samplerCube reflectionSamplerHigh;\n#endif\n#else\n#define sampleReflection(s,c) texture2D(s,c)\nuniform sampler2D reflectionSampler;\n#ifdef TEXTURELODSUPPORT\n#define sampleReflectionLod(s,c,l) texture2DLodEXT(s,c,l)\n#else\nuniform samplerCube reflectionSamplerLow;\nuniform samplerCube reflectionSamplerHigh;\n#endif\n#endif\n#ifdef REFLECTIONMAP_SKYBOX\nvarying vec3 vPositionUVW;\n#else\n#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\nvarying vec3 vDirectionW;\n#endif\n#endif\n#include\n#endif\n\n#ifndef FROMLINEARSPACE\n#define FROMLINEARSPACE;\n#endif\n\n#ifndef SHADOWONLY\n#define SHADOWONLY;\n#endif\n#include\n\n#include<__decl__lightFragment>[0..maxSimultaneousLights]\n#include\n#include\n#include\n#include\n#include\n\n#include\n#ifdef REFLECTIONFRESNEL\n#define FRESNEL_MAXIMUM_ON_ROUGH 0.25\nvec3 fresnelSchlickEnvironmentGGX(float VdotN,vec3 reflectance0,vec3 reflectance90,float smoothness)\n{\n\nfloat weight=mix(FRESNEL_MAXIMUM_ON_ROUGH,1.0,smoothness);\nreturn reflectance0+weight*(reflectance90-reflectance0)*pow(clamp(1.0-VdotN,0.,1.),5.0);\n}\n#endif\nvoid main(void) {\n#include\nvec3 viewDirectionW=normalize(vEyePosition-vPositionW);\n\n#ifdef NORMAL\nvec3 normalW=normalize(vNormalW);\n#else\nvec3 normalW=vec3(0.0,1.0,0.0);\n#endif\n\nfloat shadow=1.;\nfloat globalShadow=0.;\nfloat shadowLightCount=0.;\n#include[0..maxSimultaneousLights]\n#ifdef SHADOWINUSE\nglobalShadow/=shadowLightCount;\n#else\nglobalShadow=1.0;\n#endif\n\nvec3 reflectionColor=vec3(1.,1.,1.);\n#ifdef REFLECTION\nvec3 reflectionVector=computeReflectionCoords(vec4(vPositionW,1.0),normalW);\n#ifdef REFLECTIONMAP_OPPOSITEZ\nreflectionVector.z*=-1.0;\n#endif\n\n#ifdef REFLECTIONMAP_3D\nvec3 reflectionCoords=reflectionVector;\n#else\nvec2 reflectionCoords=reflectionVector.xy;\n#ifdef REFLECTIONMAP_PROJECTION\nreflectionCoords/=reflectionVector.z;\n#endif\nreflectionCoords.y=1.0-reflectionCoords.y;\n#endif\n#ifdef REFLECTIONBLUR\nfloat reflectionLOD=vReflectionInfos.y;\n#ifdef TEXTURELODSUPPORT\n\nreflectionLOD=reflectionLOD*log2(vReflectionMicrosurfaceInfos.x)*vReflectionMicrosurfaceInfos.y+vReflectionMicrosurfaceInfos.z;\nreflectionColor=sampleReflectionLod(reflectionSampler,reflectionCoords,reflectionLOD).rgb;\n#else\nfloat lodReflectionNormalized=clamp(reflectionLOD,0.,1.);\nfloat lodReflectionNormalizedDoubled=lodReflectionNormalized*2.0;\nvec3 reflectionSpecularMid=sampleReflection(reflectionSampler,reflectionCoords).rgb;\nif(lodReflectionNormalizedDoubled<1.0){\nreflectionColor=mix(\nsampleReflection(reflectionSamplerHigh,reflectionCoords).rgb,\nreflectionSpecularMid,\nlodReflectionNormalizedDoubled\n);\n} else {\nreflectionColor=mix(\nreflectionSpecularMid,\nsampleReflection(reflectionSamplerLow,reflectionCoords).rgb,\nlodReflectionNormalizedDoubled-1.0\n);\n}\n#endif\n#else\nvec4 reflectionSample=sampleReflection(reflectionSampler,reflectionCoords);\nreflectionColor=reflectionSample.rgb;\n#endif\n#ifdef GAMMAREFLECTION\nreflectionColor=toLinearSpace(reflectionColor.rgb);\n#endif\n#ifdef REFLECTIONBGR\nreflectionColor=reflectionColor.bgr;\n#endif\n\nreflectionColor*=vReflectionInfos.x;\n#endif\n\nvec3 diffuseColor=vec3(1.,1.,1.);\nfloat finalAlpha=alpha;\n#ifdef DIFFUSE\nvec4 diffuseMap=texture2D(diffuseSampler,vDiffuseUV);\n#ifdef GAMMADIFFUSE\ndiffuseMap.rgb=toLinearSpace(diffuseMap.rgb);\n#endif\n\ndiffuseMap.rgb*=vDiffuseInfos.y;\n#ifdef DIFFUSEHASALPHA\nfinalAlpha*=diffuseMap.a;\n#endif\ndiffuseColor=diffuseMap.rgb;\n#endif\n\n#ifdef REFLECTIONFRESNEL\nvec3 colorBase=diffuseColor;\n#else\nvec3 colorBase=reflectionColor*diffuseColor;\n#endif\ncolorBase=max(colorBase,0.0);\n\n#ifdef USERGBCOLOR\nvec3 finalColor=colorBase;\n#else\nvec3 finalColor=colorBase.r*vPrimaryColor.rgb*vPrimaryColor.a;\nfinalColor+=colorBase.g*vSecondaryColor.rgb*vSecondaryColor.a;\nfinalColor+=colorBase.b*vTertiaryColor.rgb*vTertiaryColor.a;\n#endif\n\n#ifdef REFLECTIONFRESNEL\nvec3 reflectionAmount=vReflectionControl.xxx;\nvec3 reflectionReflectance0=vReflectionControl.yyy;\nvec3 reflectionReflectance90=vReflectionControl.zzz;\nfloat VdotN=dot(normalize(vEyePosition),normalW);\nvec3 planarReflectionFresnel=fresnelSchlickEnvironmentGGX(clamp(VdotN,0.0,1.0),reflectionReflectance0,reflectionReflectance90,1.0);\nreflectionAmount*=planarReflectionFresnel;\n#ifdef REFLECTIONFALLOFF\nfloat reflectionDistanceFalloff=1.0-clamp(length(vPositionW.xyz-vBackgroundCenter)*vReflectionControl.w,0.0,1.0);\nreflectionDistanceFalloff*=reflectionDistanceFalloff;\nreflectionAmount*=reflectionDistanceFalloff;\n#endif\nfinalColor=mix(finalColor,reflectionColor,clamp(reflectionAmount,0.,1.));\n#endif\n#ifdef OPACITYFRESNEL\nfloat viewAngleToFloor=dot(normalW,normalize(vEyePosition-vBackgroundCenter));\n\nconst float startAngle=0.1;\nfloat fadeFactor=clamp(viewAngleToFloor/startAngle,0.0,1.0);\nfinalAlpha*=fadeFactor*fadeFactor;\n#endif\n\n#ifdef SHADOWINUSE\nfinalColor=mix(finalColor*shadowLevel,finalColor,globalShadow);\n#endif\n\nvec4 color=vec4(finalColor,finalAlpha);\n#include\n#ifdef IMAGEPROCESSINGPOSTPROCESS\n\n\ncolor.rgb=clamp(color.rgb,0.,30.0);\n#else\n\ncolor=applyImageProcessing(color);\n#endif\n#ifdef PREMULTIPLYALPHA\n\ncolor.rgb*=color.a;\n#endif\n#ifndef GRAIN \n#ifdef NOISE\ncolor.rgb+=dither(vPositionW.xy,0.5);\ncolor=max(color,0.0);\n#endif\n#endif\ngl_FragColor=color;\n}\n"};
BABYLON.Effect.IncludesShadersStore={"depthPrePass":"#ifdef DEPTHPREPASS\ngl_FragColor=vec4(0.,0.,0.,1.0);\nreturn;\n#endif","bonesDeclaration":"#if NUM_BONE_INFLUENCERS>0\nuniform mat4 mBones[BonesPerMesh];\nattribute vec4 matricesIndices;\nattribute vec4 matricesWeights;\n#if NUM_BONE_INFLUENCERS>4\nattribute vec4 matricesIndicesExtra;\nattribute vec4 matricesWeightsExtra;\n#endif\n#endif","instancesDeclaration":"#ifdef INSTANCES\nattribute vec4 world0;\nattribute vec4 world1;\nattribute vec4 world2;\nattribute vec4 world3;\n#else\nuniform mat4 world;\n#endif","pointCloudVertexDeclaration":"#ifdef POINTSIZE\nuniform float pointSize;\n#endif","bumpVertexDeclaration":"#if defined(BUMP) || defined(PARALLAX)\n#if defined(TANGENT) && defined(NORMAL) \nvarying mat3 vTBN;\n#endif\n#endif\n","clipPlaneVertexDeclaration":"#ifdef CLIPPLANE\nuniform vec4 vClipPlane;\nvarying float fClipDistance;\n#endif","fogVertexDeclaration":"#ifdef FOG\nvarying vec3 vFogDistance;\n#endif","morphTargetsVertexGlobalDeclaration":"#ifdef MORPHTARGETS\nuniform float morphTargetInfluences[NUM_MORPH_INFLUENCERS];\n#endif","morphTargetsVertexDeclaration":"#ifdef MORPHTARGETS\nattribute vec3 position{X};\n#ifdef MORPHTARGETS_NORMAL\nattribute vec3 normal{X};\n#endif\n#ifdef MORPHTARGETS_TANGENT\nattribute vec3 tangent{X};\n#endif\n#endif","logDepthDeclaration":"#ifdef LOGARITHMICDEPTH\nuniform float logarithmicDepthConstant;\nvarying float vFragmentDepth;\n#endif","morphTargetsVertex":"#ifdef MORPHTARGETS\npositionUpdated+=(position{X}-position)*morphTargetInfluences[{X}];\n#ifdef MORPHTARGETS_NORMAL\nnormalUpdated+=(normal{X}-normal)*morphTargetInfluences[{X}];\n#endif\n#ifdef MORPHTARGETS_TANGENT\ntangentUpdated.xyz+=(tangent{X}-tangent.xyz)*morphTargetInfluences[{X}];\n#endif\n#endif","instancesVertex":"#ifdef INSTANCES\nmat4 finalWorld=mat4(world0,world1,world2,world3);\n#else\nmat4 finalWorld=world;\n#endif","bonesVertex":"#if NUM_BONE_INFLUENCERS>0\nmat4 influence;\ninfluence=mBones[int(matricesIndices[0])]*matricesWeights[0];\n#if NUM_BONE_INFLUENCERS>1\ninfluence+=mBones[int(matricesIndices[1])]*matricesWeights[1];\n#endif \n#if NUM_BONE_INFLUENCERS>2\ninfluence+=mBones[int(matricesIndices[2])]*matricesWeights[2];\n#endif \n#if NUM_BONE_INFLUENCERS>3\ninfluence+=mBones[int(matricesIndices[3])]*matricesWeights[3];\n#endif \n#if NUM_BONE_INFLUENCERS>4\ninfluence+=mBones[int(matricesIndicesExtra[0])]*matricesWeightsExtra[0];\n#endif \n#if NUM_BONE_INFLUENCERS>5\ninfluence+=mBones[int(matricesIndicesExtra[1])]*matricesWeightsExtra[1];\n#endif \n#if NUM_BONE_INFLUENCERS>6\ninfluence+=mBones[int(matricesIndicesExtra[2])]*matricesWeightsExtra[2];\n#endif \n#if NUM_BONE_INFLUENCERS>7\ninfluence+=mBones[int(matricesIndicesExtra[3])]*matricesWeightsExtra[3];\n#endif \nfinalWorld=finalWorld*influence;\n#endif","bumpVertex":"#if defined(BUMP) || defined(PARALLAX)\n#if defined(TANGENT) && defined(NORMAL)\nvec3 tbnNormal=normalize(normalUpdated);\nvec3 tbnTangent=normalize(tangentUpdated.xyz);\nvec3 tbnBitangent=cross(tbnNormal,tbnTangent)*tangentUpdated.w;\nvTBN=mat3(finalWorld)*mat3(tbnTangent,tbnBitangent,tbnNormal);\n#endif\n#endif","clipPlaneVertex":"#ifdef CLIPPLANE\nfClipDistance=dot(worldPos,vClipPlane);\n#endif","fogVertex":"#ifdef FOG\nvFogDistance=(view*worldPos).xyz;\n#endif","shadowsVertex":"#ifdef SHADOWS\n#if defined(SHADOW{X}) && !defined(SHADOWCUBE{X})\nvPositionFromLight{X}=lightMatrix{X}*worldPos;\nvDepthMetric{X}=((vPositionFromLight{X}.z+light{X}.depthValues.x)/(light{X}.depthValues.y));\n#endif\n#endif","pointCloudVertex":"#ifdef POINTSIZE\ngl_PointSize=pointSize;\n#endif","logDepthVertex":"#ifdef LOGARITHMICDEPTH\nvFragmentDepth=1.0+gl_Position.w;\ngl_Position.z=log2(max(0.000001,vFragmentDepth))*logarithmicDepthConstant;\n#endif","helperFunctions":"const float PI=3.1415926535897932384626433832795;\nconst float LinearEncodePowerApprox=2.2;\nconst float GammaEncodePowerApprox=1.0/LinearEncodePowerApprox;\nconst vec3 LuminanceEncodeApprox=vec3(0.2126,0.7152,0.0722);\nmat3 transposeMat3(mat3 inMatrix) {\nvec3 i0=inMatrix[0];\nvec3 i1=inMatrix[1];\nvec3 i2=inMatrix[2];\nmat3 outMatrix=mat3(\nvec3(i0.x,i1.x,i2.x),\nvec3(i0.y,i1.y,i2.y),\nvec3(i0.z,i1.z,i2.z)\n);\nreturn outMatrix;\n}\n\nmat3 inverseMat3(mat3 inMatrix) {\nfloat a00=inMatrix[0][0],a01=inMatrix[0][1],a02=inMatrix[0][2];\nfloat a10=inMatrix[1][0],a11=inMatrix[1][1],a12=inMatrix[1][2];\nfloat a20=inMatrix[2][0],a21=inMatrix[2][1],a22=inMatrix[2][2];\nfloat b01=a22*a11-a12*a21;\nfloat b11=-a22*a10+a12*a20;\nfloat b21=a21*a10-a11*a20;\nfloat det=a00*b01+a01*b11+a02*b21;\nreturn mat3(b01,(-a22*a01+a02*a21),(a12*a01-a02*a11),\nb11,(a22*a00-a02*a20),(-a12*a00+a02*a10),\nb21,(-a21*a00+a01*a20),(a11*a00-a01*a10))/det;\n}\nfloat computeFallOff(float value,vec2 clipSpace,float frustumEdgeFalloff)\n{\nfloat mask=smoothstep(1.0-frustumEdgeFalloff,1.0,clamp(dot(clipSpace,clipSpace),0.,1.));\nreturn mix(value,1.0,mask);\n}\nvec3 applyEaseInOut(vec3 x){\nreturn x*x*(3.0-2.0*x);\n}\nvec3 toLinearSpace(vec3 color)\n{\nreturn pow(color,vec3(LinearEncodePowerApprox));\n}\nvec3 toGammaSpace(vec3 color)\n{\nreturn pow(color,vec3(GammaEncodePowerApprox));\n}\nfloat square(float value)\n{\nreturn value*value;\n}\nfloat getLuminance(vec3 color)\n{\nreturn clamp(dot(color,LuminanceEncodeApprox),0.,1.);\n}\n\nfloat getRand(vec2 seed) {\nreturn fract(sin(dot(seed.xy ,vec2(12.9898,78.233)))*43758.5453);\n}\nfloat dither(vec2 seed,float varianceAmount) {\nfloat rand=getRand(seed);\nfloat dither=mix(-varianceAmount/255.0,varianceAmount/255.0,rand);\nreturn dither;\n}","lightFragmentDeclaration":"#ifdef LIGHT{X}\nuniform vec4 vLightData{X};\nuniform vec4 vLightDiffuse{X};\n#ifdef SPECULARTERM\nuniform vec3 vLightSpecular{X};\n#else\nvec3 vLightSpecular{X}=vec3(0.);\n#endif\n#ifdef SHADOW{X}\n#if defined(SHADOWCUBE{X})\nuniform samplerCube shadowSampler{X};\n#else\nvarying vec4 vPositionFromLight{X};\nvarying float vDepthMetric{X};\nuniform sampler2D shadowSampler{X};\nuniform mat4 lightMatrix{X};\n#endif\nuniform vec4 shadowsInfo{X};\nuniform vec2 depthValues{X};\n#endif\n#ifdef SPOTLIGHT{X}\nuniform vec4 vLightDirection{X};\n#endif\n#ifdef HEMILIGHT{X}\nuniform vec3 vLightGround{X};\n#endif\n#ifdef PROJECTEDLIGHTTEXTURE{X}\nuniform mat4 textureProjectionMatrix{X};\nuniform sampler2D projectionLightSampler{X};\n#endif\n#endif","lightsFragmentFunctions":"\nstruct lightingInfo\n{\nvec3 diffuse;\n#ifdef SPECULARTERM\nvec3 specular;\n#endif\n#ifdef NDOTL\nfloat ndl;\n#endif\n};\nlightingInfo computeLighting(vec3 viewDirectionW,vec3 vNormal,vec4 lightData,vec3 diffuseColor,vec3 specularColor,float range,float glossiness) {\nlightingInfo result;\nvec3 lightVectorW;\nfloat attenuation=1.0;\nif (lightData.w == 0.)\n{\nvec3 direction=lightData.xyz-vPositionW;\nattenuation=max(0.,1.0-length(direction)/range);\nlightVectorW=normalize(direction);\n}\nelse\n{\nlightVectorW=normalize(-lightData.xyz);\n}\n\nfloat ndl=max(0.,dot(vNormal,lightVectorW));\n#ifdef NDOTL\nresult.ndl=ndl;\n#endif\nresult.diffuse=ndl*diffuseColor*attenuation;\n#ifdef SPECULARTERM\n\nvec3 angleW=normalize(viewDirectionW+lightVectorW);\nfloat specComp=max(0.,dot(vNormal,angleW));\nspecComp=pow(specComp,max(1.,glossiness));\nresult.specular=specComp*specularColor*attenuation;\n#endif\nreturn result;\n}\nlightingInfo computeSpotLighting(vec3 viewDirectionW,vec3 vNormal,vec4 lightData,vec4 lightDirection,vec3 diffuseColor,vec3 specularColor,float range,float glossiness) {\nlightingInfo result;\nvec3 direction=lightData.xyz-vPositionW;\nvec3 lightVectorW=normalize(direction);\nfloat attenuation=max(0.,1.0-length(direction)/range);\n\nfloat cosAngle=max(0.,dot(lightDirection.xyz,-lightVectorW));\nif (cosAngle>=lightDirection.w)\n{\ncosAngle=max(0.,pow(cosAngle,lightData.w));\nattenuation*=cosAngle;\n\nfloat ndl=max(0.,dot(vNormal,lightVectorW));\n#ifdef NDOTL\nresult.ndl=ndl;\n#endif\nresult.diffuse=ndl*diffuseColor*attenuation;\n#ifdef SPECULARTERM\n\nvec3 angleW=normalize(viewDirectionW+lightVectorW);\nfloat specComp=max(0.,dot(vNormal,angleW));\nspecComp=pow(specComp,max(1.,glossiness));\nresult.specular=specComp*specularColor*attenuation;\n#endif\nreturn result;\n}\nresult.diffuse=vec3(0.);\n#ifdef SPECULARTERM\nresult.specular=vec3(0.);\n#endif\n#ifdef NDOTL\nresult.ndl=0.;\n#endif\nreturn result;\n}\nlightingInfo computeHemisphericLighting(vec3 viewDirectionW,vec3 vNormal,vec4 lightData,vec3 diffuseColor,vec3 specularColor,vec3 groundColor,float glossiness) {\nlightingInfo result;\n\nfloat ndl=dot(vNormal,lightData.xyz)*0.5+0.5;\n#ifdef NDOTL\nresult.ndl=ndl;\n#endif\nresult.diffuse=mix(groundColor,diffuseColor,ndl);\n#ifdef SPECULARTERM\n\nvec3 angleW=normalize(viewDirectionW+lightData.xyz);\nfloat specComp=max(0.,dot(vNormal,angleW));\nspecComp=pow(specComp,max(1.,glossiness));\nresult.specular=specComp*specularColor;\n#endif\nreturn result;\n}\nvec3 computeProjectionTextureDiffuseLighting(sampler2D projectionLightSampler,mat4 textureProjectionMatrix){\nvec4 strq=textureProjectionMatrix*vec4(vPositionW,1.0);\nstrq/=strq.w;\nvec3 textureColor=texture2D(projectionLightSampler,strq.xy).rgb;\n#ifdef PBR\ntextureColor=toLinearSpace(textureColor);\n#endif\nreturn textureColor;\n}","lightUboDeclaration":"#ifdef LIGHT{X}\nuniform Light{X}\n{\nvec4 vLightData;\nvec4 vLightDiffuse;\nvec3 vLightSpecular;\n#ifdef SPOTLIGHT{X}\nvec4 vLightDirection;\n#endif\n#ifdef HEMILIGHT{X}\nvec3 vLightGround;\n#endif\nvec4 shadowsInfo;\nvec2 depthValues;\n} light{X};\n#ifdef PROJECTEDLIGHTTEXTURE{X}\nuniform mat4 textureProjectionMatrix{X};\nuniform sampler2D projectionLightSampler{X};\n#endif\n#ifdef SHADOW{X}\n#if defined(SHADOWCUBE{X})\nuniform samplerCube shadowSampler{X};\n#else\nvarying vec4 vPositionFromLight{X};\nvarying float vDepthMetric{X};\nuniform sampler2D shadowSampler{X};\nuniform mat4 lightMatrix{X};\n#endif\n#endif\n#endif","defaultVertexDeclaration":"\nuniform mat4 viewProjection;\nuniform mat4 view;\n#ifdef DIFFUSE\nuniform mat4 diffuseMatrix;\nuniform vec2 vDiffuseInfos;\n#endif\n#ifdef AMBIENT\nuniform mat4 ambientMatrix;\nuniform vec2 vAmbientInfos;\n#endif\n#ifdef OPACITY\nuniform mat4 opacityMatrix;\nuniform vec2 vOpacityInfos;\n#endif\n#ifdef EMISSIVE\nuniform vec2 vEmissiveInfos;\nuniform mat4 emissiveMatrix;\n#endif\n#ifdef LIGHTMAP\nuniform vec2 vLightmapInfos;\nuniform mat4 lightmapMatrix;\n#endif\n#if defined(SPECULAR) && defined(SPECULARTERM)\nuniform vec2 vSpecularInfos;\nuniform mat4 specularMatrix;\n#endif\n#ifdef BUMP\nuniform vec3 vBumpInfos;\nuniform mat4 bumpMatrix;\n#endif\n#ifdef POINTSIZE\nuniform float pointSize;\n#endif\n","defaultFragmentDeclaration":"uniform vec4 vDiffuseColor;\n#ifdef SPECULARTERM\nuniform vec4 vSpecularColor;\n#endif\nuniform vec3 vEmissiveColor;\n\n#ifdef DIFFUSE\nuniform vec2 vDiffuseInfos;\n#endif\n#ifdef AMBIENT\nuniform vec2 vAmbientInfos;\n#endif\n#ifdef OPACITY \nuniform vec2 vOpacityInfos;\n#endif\n#ifdef EMISSIVE\nuniform vec2 vEmissiveInfos;\n#endif\n#ifdef LIGHTMAP\nuniform vec2 vLightmapInfos;\n#endif\n#ifdef BUMP\nuniform vec3 vBumpInfos;\nuniform vec2 vTangentSpaceParams;\n#endif\n#if defined(REFLECTIONMAP_SPHERICAL) || defined(REFLECTIONMAP_PROJECTION) || defined(REFRACTION)\nuniform mat4 view;\n#endif\n#ifdef REFRACTION\nuniform vec4 vRefractionInfos;\n#ifndef REFRACTIONMAP_3D\nuniform mat4 refractionMatrix;\n#endif\n#ifdef REFRACTIONFRESNEL\nuniform vec4 refractionLeftColor;\nuniform vec4 refractionRightColor;\n#endif\n#endif\n#if defined(SPECULAR) && defined(SPECULARTERM)\nuniform vec2 vSpecularInfos;\n#endif\n#ifdef DIFFUSEFRESNEL\nuniform vec4 diffuseLeftColor;\nuniform vec4 diffuseRightColor;\n#endif\n#ifdef OPACITYFRESNEL\nuniform vec4 opacityParts;\n#endif\n#ifdef EMISSIVEFRESNEL\nuniform vec4 emissiveLeftColor;\nuniform vec4 emissiveRightColor;\n#endif\n\n#ifdef REFLECTION\nuniform vec2 vReflectionInfos;\n#ifdef REFLECTIONMAP_SKYBOX\n#else\n#if defined(REFLECTIONMAP_PLANAR) || defined(REFLECTIONMAP_CUBIC) || defined(REFLECTIONMAP_PROJECTION)\nuniform mat4 reflectionMatrix;\n#endif\n#if defined(USE_LOCAL_REFLECTIONMAP_CUBIC) && defined(REFLECTIONMAP_CUBIC)\nuniform vec3 vReflectionPosition;\nuniform vec3 vReflectionSize; \n#endif\n#endif\n#ifdef REFLECTIONFRESNEL\nuniform vec4 reflectionLeftColor;\nuniform vec4 reflectionRightColor;\n#endif\n#endif","defaultUboDeclaration":"layout(std140,column_major) uniform;\nuniform Material\n{\nvec4 diffuseLeftColor;\nvec4 diffuseRightColor;\nvec4 opacityParts;\nvec4 reflectionLeftColor;\nvec4 reflectionRightColor;\nvec4 refractionLeftColor;\nvec4 refractionRightColor;\nvec4 emissiveLeftColor; \nvec4 emissiveRightColor;\nvec2 vDiffuseInfos;\nvec2 vAmbientInfos;\nvec2 vOpacityInfos;\nvec2 vReflectionInfos;\nvec3 vReflectionPosition;\nvec3 vReflectionSize;\nvec2 vEmissiveInfos;\nvec2 vLightmapInfos;\nvec2 vSpecularInfos;\nvec3 vBumpInfos;\nmat4 diffuseMatrix;\nmat4 ambientMatrix;\nmat4 opacityMatrix;\nmat4 reflectionMatrix;\nmat4 emissiveMatrix;\nmat4 lightmapMatrix;\nmat4 specularMatrix;\nmat4 bumpMatrix; \nvec4 vTangentSpaceParams;\nmat4 refractionMatrix;\nvec4 vRefractionInfos;\nvec4 vSpecularColor;\nvec3 vEmissiveColor;\nvec4 vDiffuseColor;\nfloat pointSize; \n};\nuniform Scene {\nmat4 viewProjection;\nmat4 view;\n};","shadowsFragmentFunctions":"#ifdef SHADOWS\n#ifndef SHADOWFLOAT\nfloat unpack(vec4 color)\n{\nconst vec4 bit_shift=vec4(1.0/(255.0*255.0*255.0),1.0/(255.0*255.0),1.0/255.0,1.0);\nreturn dot(color,bit_shift);\n}\n#endif\nfloat computeShadowCube(vec3 lightPosition,samplerCube shadowSampler,float darkness,vec2 depthValues)\n{\nvec3 directionToLight=vPositionW-lightPosition;\nfloat depth=length(directionToLight);\ndepth=(depth+depthValues.x)/(depthValues.y);\ndepth=clamp(depth,0.,1.0);\ndirectionToLight=normalize(directionToLight);\ndirectionToLight.y=-directionToLight.y;\n#ifndef SHADOWFLOAT\nfloat shadow=unpack(textureCube(shadowSampler,directionToLight));\n#else\nfloat shadow=textureCube(shadowSampler,directionToLight).x;\n#endif\nif (depth>shadow)\n{\nreturn darkness;\n}\nreturn 1.0;\n}\nfloat computeShadowWithPCFCube(vec3 lightPosition,samplerCube shadowSampler,float mapSize,float darkness,vec2 depthValues)\n{\nvec3 directionToLight=vPositionW-lightPosition;\nfloat depth=length(directionToLight);\ndepth=(depth+depthValues.x)/(depthValues.y);\ndepth=clamp(depth,0.,1.0);\ndirectionToLight=normalize(directionToLight);\ndirectionToLight.y=-directionToLight.y;\nfloat visibility=1.;\nvec3 poissonDisk[4];\npoissonDisk[0]=vec3(-1.0,1.0,-1.0);\npoissonDisk[1]=vec3(1.0,-1.0,-1.0);\npoissonDisk[2]=vec3(-1.0,-1.0,-1.0);\npoissonDisk[3]=vec3(1.0,-1.0,1.0);\n\n#ifndef SHADOWFLOAT\nif (unpack(textureCube(shadowSampler,directionToLight+poissonDisk[0]*mapSize))1.0 || uv.y<0. || uv.y>1.0)\n{\nreturn 1.0;\n}\nfloat shadowPixelDepth=clamp(depthMetric,0.,1.0);\n#ifndef SHADOWFLOAT\nfloat shadow=unpack(texture2D(shadowSampler,uv));\n#else\nfloat shadow=texture2D(shadowSampler,uv).x;\n#endif\nif (shadowPixelDepth>shadow)\n{\nreturn computeFallOff(darkness,clipSpace.xy,frustumEdgeFalloff);\n}\nreturn 1.;\n}\nfloat computeShadowWithPCF(vec4 vPositionFromLight,float depthMetric,sampler2D shadowSampler,float mapSize,float darkness,float frustumEdgeFalloff)\n{\nvec3 clipSpace=vPositionFromLight.xyz/vPositionFromLight.w;\nvec2 uv=0.5*clipSpace.xy+vec2(0.5);\nif (uv.x<0. || uv.x>1.0 || uv.y<0. || uv.y>1.0)\n{\nreturn 1.0;\n}\nfloat shadowPixelDepth=clamp(depthMetric,0.,1.0);\nfloat visibility=1.;\nvec2 poissonDisk[4];\npoissonDisk[0]=vec2(-0.94201624,-0.39906216);\npoissonDisk[1]=vec2(0.94558609,-0.76890725);\npoissonDisk[2]=vec2(-0.094184101,-0.92938870);\npoissonDisk[3]=vec2(0.34495938,0.29387760);\n\n#ifndef SHADOWFLOAT\nif (unpack(texture2D(shadowSampler,uv+poissonDisk[0]*mapSize))1.0 || uv.y<0. || uv.y>1.0)\n{\nreturn 1.0;\n}\nfloat shadowPixelDepth=clamp(depthMetric,0.,1.0);\n#ifndef SHADOWFLOAT\nfloat shadowMapSample=unpack(texture2D(shadowSampler,uv));\n#else\nfloat shadowMapSample=texture2D(shadowSampler,uv).x;\n#endif\nfloat esm=1.0-clamp(exp(min(87.,depthScale*shadowPixelDepth))*shadowMapSample,0.,1.-darkness);\nreturn computeFallOff(esm,clipSpace.xy,frustumEdgeFalloff);\n}\nfloat computeShadowWithCloseESM(vec4 vPositionFromLight,float depthMetric,sampler2D shadowSampler,float darkness,float depthScale,float frustumEdgeFalloff)\n{\nvec3 clipSpace=vPositionFromLight.xyz/vPositionFromLight.w;\nvec2 uv=0.5*clipSpace.xy+vec2(0.5);\nif (uv.x<0. || uv.x>1.0 || uv.y<0. || uv.y>1.0)\n{\nreturn 1.0;\n}\nfloat shadowPixelDepth=clamp(depthMetric,0.,1.0); \n#ifndef SHADOWFLOAT\nfloat shadowMapSample=unpack(texture2D(shadowSampler,uv));\n#else\nfloat shadowMapSample=texture2D(shadowSampler,uv).x;\n#endif\nfloat esm=clamp(exp(min(87.,-depthScale*(shadowPixelDepth-shadowMapSample))),darkness,1.);\nreturn computeFallOff(esm,clipSpace.xy,frustumEdgeFalloff);\n}\n#endif\n","fresnelFunction":"#ifdef FRESNEL\nfloat computeFresnelTerm(vec3 viewDirection,vec3 worldNormal,float bias,float power)\n{\nfloat fresnelTerm=pow(bias+abs(dot(viewDirection,worldNormal)),power);\nreturn clamp(fresnelTerm,0.,1.);\n}\n#endif","reflectionFunction":"#ifdef USE_LOCAL_REFLECTIONMAP_CUBIC\nvec3 parallaxCorrectNormal( vec3 vertexPos,vec3 origVec,vec3 cubeSize,vec3 cubePos ) {\n\nvec3 invOrigVec=vec3(1.0,1.0,1.0)/origVec;\nvec3 halfSize=cubeSize*0.5;\nvec3 intersecAtMaxPlane=(cubePos+halfSize-vertexPos)*invOrigVec;\nvec3 intersecAtMinPlane=(cubePos-halfSize-vertexPos)*invOrigVec;\n\nvec3 largestIntersec=max(intersecAtMaxPlane,intersecAtMinPlane);\n\nfloat distance=min(min(largestIntersec.x,largestIntersec.y),largestIntersec.z);\n\nvec3 intersectPositionWS=vertexPos+origVec*distance;\n\nreturn intersectPositionWS-cubePos;\n}\n#endif\nvec3 computeReflectionCoords(vec4 worldPos,vec3 worldNormal)\n{\n#if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)\nvec3 direction=vDirectionW;\nfloat t=clamp(direction.y*-0.5+0.5,0.,1.0);\nfloat s=atan(direction.z,direction.x)*RECIPROCAL_PI2+0.5;\n#ifdef REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED\nreturn vec3(1.0-s,t,0);\n#else\nreturn vec3(s,t,0);\n#endif\n#endif\n#ifdef REFLECTIONMAP_EQUIRECTANGULAR\nvec3 cameraToVertex=normalize(worldPos.xyz-vEyePosition.xyz);\nvec3 r=reflect(cameraToVertex,worldNormal);\nfloat t=clamp(r.y*-0.5+0.5,0.,1.0);\nfloat s=atan(r.z,r.x)*RECIPROCAL_PI2+0.5;\nreturn vec3(s,t,0);\n#endif\n#ifdef REFLECTIONMAP_SPHERICAL\nvec3 viewDir=normalize(vec3(view*worldPos));\nvec3 viewNormal=normalize(vec3(view*vec4(worldNormal,0.0)));\nvec3 r=reflect(viewDir,viewNormal);\nr.z=r.z-1.0;\nfloat m=2.0*length(r);\nreturn vec3(r.x/m+0.5,1.0-r.y/m-0.5,0);\n#endif\n#ifdef REFLECTIONMAP_PLANAR\nvec3 viewDir=worldPos.xyz-vEyePosition.xyz;\nvec3 coords=normalize(reflect(viewDir,worldNormal));\nreturn vec3(reflectionMatrix*vec4(coords,1));\n#endif\n#ifdef REFLECTIONMAP_CUBIC\nvec3 viewDir=normalize(worldPos.xyz-vEyePosition.xyz);\n\nvec3 coords=reflect(viewDir,worldNormal);\n#ifdef USE_LOCAL_REFLECTIONMAP_CUBIC\ncoords=parallaxCorrectNormal(worldPos.xyz,coords,vReflectionSize,vReflectionPosition);\n#endif\ncoords=vec3(reflectionMatrix*vec4(coords,0));\n#ifdef INVERTCUBICMAP\ncoords.y*=-1.0;\n#endif\nreturn coords;\n#endif\n#ifdef REFLECTIONMAP_PROJECTION\nreturn vec3(reflectionMatrix*(view*worldPos));\n#endif\n#ifdef REFLECTIONMAP_SKYBOX\nreturn vPositionUVW;\n#endif\n#ifdef REFLECTIONMAP_EXPLICIT\nreturn vec3(0,0,0);\n#endif\n}","imageProcessingDeclaration":"#ifdef EXPOSURE\nuniform float exposureLinear;\n#endif\n#ifdef CONTRAST\nuniform float contrast;\n#endif\n#ifdef VIGNETTE\nuniform vec2 vInverseScreenSize;\nuniform vec4 vignetteSettings1;\nuniform vec4 vignetteSettings2;\n#endif\n#ifdef COLORCURVES\nuniform vec4 vCameraColorCurveNegative;\nuniform vec4 vCameraColorCurveNeutral;\nuniform vec4 vCameraColorCurvePositive;\n#endif\n#ifdef COLORGRADING\n#ifdef COLORGRADING3D\nuniform highp sampler3D txColorTransform;\n#else\nuniform sampler2D txColorTransform;\n#endif\nuniform vec4 colorTransformSettings;\n#endif\n#ifdef GRAIN\nuniform float grainVarianceAmount;\nuniform float grainAnimatedSeed;\n#endif","imageProcessingFunctions":"#if defined(COLORGRADING) && !defined(COLORGRADING3D)\n\nvec3 sampleTexture3D(sampler2D colorTransform,vec3 color,vec2 sampler3dSetting)\n{\nfloat sliceSize=2.0*sampler3dSetting.x; \n#ifdef SAMPLER3DGREENDEPTH\nfloat sliceContinuous=(color.g-sampler3dSetting.x)*sampler3dSetting.y;\n#else\nfloat sliceContinuous=(color.b-sampler3dSetting.x)*sampler3dSetting.y;\n#endif\nfloat sliceInteger=floor(sliceContinuous);\n\n\nfloat sliceFraction=sliceContinuous-sliceInteger;\n#ifdef SAMPLER3DGREENDEPTH\nvec2 sliceUV=color.rb;\n#else\nvec2 sliceUV=color.rg;\n#endif\nsliceUV.x*=sliceSize;\nsliceUV.x+=sliceInteger*sliceSize;\nsliceUV=clamp(sliceUV,0.,1.);\nvec4 slice0Color=texture2D(colorTransform,sliceUV);\nsliceUV.x+=sliceSize;\nsliceUV=clamp(sliceUV,0.,1.);\nvec4 slice1Color=texture2D(colorTransform,sliceUV);\nvec3 result=mix(slice0Color.rgb,slice1Color.rgb,sliceFraction);\n#ifdef SAMPLER3DBGRMAP\ncolor.rgb=result.rgb;\n#else\ncolor.rgb=result.bgr;\n#endif\nreturn color;\n}\n#endif\nvec4 applyImageProcessing(vec4 result) {\n#ifdef EXPOSURE\nresult.rgb*=exposureLinear;\n#endif\n#ifdef VIGNETTE\n\nvec2 viewportXY=gl_FragCoord.xy*vInverseScreenSize;\nviewportXY=viewportXY*2.0-1.0;\nvec3 vignetteXY1=vec3(viewportXY*vignetteSettings1.xy+vignetteSettings1.zw,1.0);\nfloat vignetteTerm=dot(vignetteXY1,vignetteXY1);\nfloat vignette=pow(vignetteTerm,vignetteSettings2.w);\n\nvec3 vignetteColor=vignetteSettings2.rgb;\n#ifdef VIGNETTEBLENDMODEMULTIPLY\nvec3 vignetteColorMultiplier=mix(vignetteColor,vec3(1,1,1),vignette);\nresult.rgb*=vignetteColorMultiplier;\n#endif\n#ifdef VIGNETTEBLENDMODEOPAQUE\nresult.rgb=mix(vignetteColor,result.rgb,vignette);\n#endif\n#endif\n#ifdef TONEMAPPING\nconst float tonemappingCalibration=1.590579;\nresult.rgb=1.0-exp2(-tonemappingCalibration*result.rgb);\n#endif\n\nresult.rgb=toGammaSpace(result.rgb);\nresult.rgb=clamp(result.rgb,0.0,1.0);\n#ifdef CONTRAST\n\nvec3 resultHighContrast=applyEaseInOut(result.rgb);\nif (contrast<1.0) {\n\nresult.rgb=mix(vec3(0.5,0.5,0.5),result.rgb,contrast);\n} else {\n\nresult.rgb=mix(result.rgb,resultHighContrast,contrast-1.0);\n}\n#endif\n\n#ifdef COLORGRADING\nvec3 colorTransformInput=result.rgb*colorTransformSettings.xxx+colorTransformSettings.yyy;\n#ifdef COLORGRADING3D\nvec3 colorTransformOutput=texture(txColorTransform,colorTransformInput).rgb;\n#else\nvec3 colorTransformOutput=sampleTexture3D(txColorTransform,colorTransformInput,colorTransformSettings.yz).rgb;\n#endif\nresult.rgb=mix(result.rgb,colorTransformOutput,colorTransformSettings.www);\n#endif\n#ifdef COLORCURVES\n\nfloat luma=getLuminance(result.rgb);\nvec2 curveMix=clamp(vec2(luma*3.0-1.5,luma*-3.0+1.5),vec2(0.0),vec2(1.0));\nvec4 colorCurve=vCameraColorCurveNeutral+curveMix.x*vCameraColorCurvePositive-curveMix.y*vCameraColorCurveNegative;\nresult.rgb*=colorCurve.rgb;\nresult.rgb=mix(vec3(luma),result.rgb,colorCurve.a);\n#endif\nreturn result;\n}","bumpFragmentFunctions":"#ifdef BUMP\n#if BUMPDIRECTUV == 1\n#define vBumpUV vMainUV1\n#elif BUMPDIRECTUV == 2\n#define vBumpUV vMainUV2\n#else\nvarying vec2 vBumpUV;\n#endif\nuniform sampler2D bumpSampler;\n#if defined(TANGENT) && defined(NORMAL) \nvarying mat3 vTBN;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\nuniform mat4 normalMatrix;\n#endif\n\nmat3 cotangent_frame(vec3 normal,vec3 p,vec2 uv)\n{\n\nuv=gl_FrontFacing ? uv : -uv;\n\nvec3 dp1=dFdx(p);\nvec3 dp2=dFdy(p);\nvec2 duv1=dFdx(uv);\nvec2 duv2=dFdy(uv);\n\nvec3 dp2perp=cross(dp2,normal);\nvec3 dp1perp=cross(normal,dp1);\nvec3 tangent=dp2perp*duv1.x+dp1perp*duv2.x;\nvec3 bitangent=dp2perp*duv1.y+dp1perp*duv2.y;\n\ntangent*=vTangentSpaceParams.x;\nbitangent*=vTangentSpaceParams.y;\n\nfloat invmax=inversesqrt(max(dot(tangent,tangent),dot(bitangent,bitangent)));\nreturn mat3(tangent*invmax,bitangent*invmax,normal);\n}\nvec3 perturbNormal(mat3 cotangentFrame,vec2 uv)\n{\nvec3 map=texture2D(bumpSampler,uv).xyz;\nmap=map*2.0-1.0;\n#ifdef NORMALXYSCALE\nmap=normalize(map*vec3(vBumpInfos.y,vBumpInfos.y,1.0));\n#endif\nreturn normalize(cotangentFrame*map);\n}\n#ifdef PARALLAX\nconst float minSamples=4.;\nconst float maxSamples=15.;\nconst int iMaxSamples=15;\n\nvec2 parallaxOcclusion(vec3 vViewDirCoT,vec3 vNormalCoT,vec2 texCoord,float parallaxScale) {\nfloat parallaxLimit=length(vViewDirCoT.xy)/vViewDirCoT.z;\nparallaxLimit*=parallaxScale;\nvec2 vOffsetDir=normalize(vViewDirCoT.xy);\nvec2 vMaxOffset=vOffsetDir*parallaxLimit;\nfloat numSamples=maxSamples+(dot(vViewDirCoT,vNormalCoT)*(minSamples-maxSamples));\nfloat stepSize=1.0/numSamples;\n\nfloat currRayHeight=1.0;\nvec2 vCurrOffset=vec2(0,0);\nvec2 vLastOffset=vec2(0,0);\nfloat lastSampledHeight=1.0;\nfloat currSampledHeight=1.0;\nfor (int i=0; icurrRayHeight)\n{\nfloat delta1=currSampledHeight-currRayHeight;\nfloat delta2=(currRayHeight+stepSize)-lastSampledHeight;\nfloat ratio=delta1/(delta1+delta2);\nvCurrOffset=(ratio)* vLastOffset+(1.0-ratio)*vCurrOffset;\n\nbreak;\n}\nelse\n{\ncurrRayHeight-=stepSize;\nvLastOffset=vCurrOffset;\nvCurrOffset+=stepSize*vMaxOffset;\nlastSampledHeight=currSampledHeight;\n}\n}\nreturn vCurrOffset;\n}\nvec2 parallaxOffset(vec3 viewDir,float heightScale)\n{\n\nfloat height=texture2D(bumpSampler,vBumpUV).w;\nvec2 texCoordOffset=heightScale*viewDir.xy*height;\nreturn -texCoordOffset;\n}\n#endif\n#endif","clipPlaneFragmentDeclaration":"#ifdef CLIPPLANE\nvarying float fClipDistance;\n#endif","fogFragmentDeclaration":"#ifdef FOG\n#define FOGMODE_NONE 0.\n#define FOGMODE_EXP 1.\n#define FOGMODE_EXP2 2.\n#define FOGMODE_LINEAR 3.\n#define E 2.71828\nuniform vec4 vFogInfos;\nuniform vec3 vFogColor;\nvarying vec3 vFogDistance;\nfloat CalcFogFactor()\n{\nfloat fogCoeff=1.0;\nfloat fogStart=vFogInfos.y;\nfloat fogEnd=vFogInfos.z;\nfloat fogDensity=vFogInfos.w;\nfloat fogDistance=length(vFogDistance);\nif (FOGMODE_LINEAR == vFogInfos.x)\n{\nfogCoeff=(fogEnd-fogDistance)/(fogEnd-fogStart);\n}\nelse if (FOGMODE_EXP == vFogInfos.x)\n{\nfogCoeff=1.0/pow(E,fogDistance*fogDensity);\n}\nelse if (FOGMODE_EXP2 == vFogInfos.x)\n{\nfogCoeff=1.0/pow(E,fogDistance*fogDistance*fogDensity*fogDensity);\n}\nreturn clamp(fogCoeff,0.0,1.0);\n}\n#endif","clipPlaneFragment":"#ifdef CLIPPLANE\nif (fClipDistance>0.0)\n{\ndiscard;\n}\n#endif","bumpFragment":"vec2 uvOffset=vec2(0.0,0.0);\n#if defined(BUMP) || defined(PARALLAX)\n#ifdef NORMALXYSCALE\nfloat normalScale=1.0;\n#else \nfloat normalScale=vBumpInfos.y;\n#endif\n#if defined(TANGENT) && defined(NORMAL)\nmat3 TBN=vTBN;\n#else\nmat3 TBN=cotangent_frame(normalW*normalScale,vPositionW,vBumpUV);\n#endif\n#endif\n#ifdef PARALLAX\nmat3 invTBN=transposeMat3(TBN);\n#ifdef PARALLAXOCCLUSION\nuvOffset=parallaxOcclusion(invTBN*-viewDirectionW,invTBN*normalW,vBumpUV,vBumpInfos.z);\n#else\nuvOffset=parallaxOffset(invTBN*viewDirectionW,vBumpInfos.z);\n#endif\n#endif\n#ifdef BUMP\n#ifdef OBJECTSPACE_NORMALMAP\nnormalW=normalize(texture2D(bumpSampler,vBumpUV).xyz*2.0-1.0);\nnormalW=normalize(mat3(normalMatrix)*normalW); \n#else\nnormalW=perturbNormal(TBN,vBumpUV+uvOffset);\n#endif\n#endif","lightFragment":"#ifdef LIGHT{X}\n#if defined(SHADOWONLY) || (defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X}) && defined(LIGHTMAPNOSPECULAR{X}))\n\n#else\n#ifdef PBR\n#ifdef SPOTLIGHT{X}\ninfo=computeSpotLighting(viewDirectionW,normalW,light{X}.vLightData,light{X}.vLightDirection,light{X}.vLightDiffuse.rgb,light{X}.vLightSpecular,light{X}.vLightDiffuse.a,roughness,NdotV,specularEnvironmentR0,specularEnvironmentR90,NdotL);\n#endif\n#ifdef HEMILIGHT{X}\ninfo=computeHemisphericLighting(viewDirectionW,normalW,light{X}.vLightData,light{X}.vLightDiffuse.rgb,light{X}.vLightSpecular,light{X}.vLightGround,roughness,NdotV,specularEnvironmentR0,specularEnvironmentR90,NdotL);\n#endif\n#if defined(POINTLIGHT{X}) || defined(DIRLIGHT{X})\ninfo=computeLighting(viewDirectionW,normalW,light{X}.vLightData,light{X}.vLightDiffuse.rgb,light{X}.vLightSpecular,light{X}.vLightDiffuse.a,roughness,NdotV,specularEnvironmentR0,specularEnvironmentR90,NdotL);\n#endif\n#else\n#ifdef SPOTLIGHT{X}\ninfo=computeSpotLighting(viewDirectionW,normalW,light{X}.vLightData,light{X}.vLightDirection,light{X}.vLightDiffuse.rgb,light{X}.vLightSpecular,light{X}.vLightDiffuse.a,glossiness);\n#endif\n#ifdef HEMILIGHT{X}\ninfo=computeHemisphericLighting(viewDirectionW,normalW,light{X}.vLightData,light{X}.vLightDiffuse.rgb,light{X}.vLightSpecular,light{X}.vLightGround,glossiness);\n#endif\n#if defined(POINTLIGHT{X}) || defined(DIRLIGHT{X})\ninfo=computeLighting(viewDirectionW,normalW,light{X}.vLightData,light{X}.vLightDiffuse.rgb,light{X}.vLightSpecular,light{X}.vLightDiffuse.a,glossiness);\n#endif\n#endif\n#ifdef PROJECTEDLIGHTTEXTURE{X}\ninfo.diffuse*=computeProjectionTextureDiffuseLighting(projectionLightSampler{X},textureProjectionMatrix{X});\n#endif\n#endif\n#ifdef SHADOW{X}\n#ifdef SHADOWCLOSEESM{X}\n#if defined(SHADOWCUBE{X})\nshadow=computeShadowWithCloseESMCube(light{X}.vLightData.xyz,shadowSampler{X},light{X}.shadowsInfo.x,light{X}.shadowsInfo.z,light{X}.depthValues);\n#else\nshadow=computeShadowWithCloseESM(vPositionFromLight{X},vDepthMetric{X},shadowSampler{X},light{X}.shadowsInfo.x,light{X}.shadowsInfo.z,light{X}.shadowsInfo.w);\n#endif\n#else\n#ifdef SHADOWESM{X}\n#if defined(SHADOWCUBE{X})\nshadow=computeShadowWithESMCube(light{X}.vLightData.xyz,shadowSampler{X},light{X}.shadowsInfo.x,light{X}.shadowsInfo.z,light{X}.depthValues);\n#else\nshadow=computeShadowWithESM(vPositionFromLight{X},vDepthMetric{X},shadowSampler{X},light{X}.shadowsInfo.x,light{X}.shadowsInfo.z,light{X}.shadowsInfo.w);\n#endif\n#else \n#ifdef SHADOWPCF{X}\n#if defined(SHADOWCUBE{X})\nshadow=computeShadowWithPCFCube(light{X}.vLightData.xyz,shadowSampler{X},light{X}.shadowsInfo.y,light{X}.shadowsInfo.x,light{X}.depthValues);\n#else\nshadow=computeShadowWithPCF(vPositionFromLight{X},vDepthMetric{X},shadowSampler{X},light{X}.shadowsInfo.y,light{X}.shadowsInfo.x,light{X}.shadowsInfo.w);\n#endif\n#else\n#if defined(SHADOWCUBE{X})\nshadow=computeShadowCube(light{X}.vLightData.xyz,shadowSampler{X},light{X}.shadowsInfo.x,light{X}.depthValues);\n#else\nshadow=computeShadow(vPositionFromLight{X},vDepthMetric{X},shadowSampler{X},light{X}.shadowsInfo.x,light{X}.shadowsInfo.w);\n#endif\n#endif\n#endif\n#endif\n#ifdef SHADOWONLY\n#ifndef SHADOWINUSE\n#define SHADOWINUSE\n#endif\nglobalShadow+=shadow;\nshadowLightCount+=1.0;\n#endif\n#else\nshadow=1.;\n#endif\n#ifndef SHADOWONLY\n#ifdef CUSTOMUSERLIGHTING\ndiffuseBase+=computeCustomDiffuseLighting(info,diffuseBase,shadow);\n#ifdef SPECULARTERM\nspecularBase+=computeCustomSpecularLighting(info,specularBase,shadow);\n#endif\n#elif defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X})\ndiffuseBase+=lightmapColor*shadow;\n#ifdef SPECULARTERM\n#ifndef LIGHTMAPNOSPECULAR{X}\nspecularBase+=info.specular*shadow*lightmapColor;\n#endif\n#endif\n#else\ndiffuseBase+=info.diffuse*shadow;\n#ifdef SPECULARTERM\nspecularBase+=info.specular*shadow;\n#endif\n#endif\n#endif\n#endif","logDepthFragment":"#ifdef LOGARITHMICDEPTH\ngl_FragDepthEXT=log2(vFragmentDepth)*logarithmicDepthConstant*0.5;\n#endif","fogFragment":"#ifdef FOG\nfloat fog=CalcFogFactor();\ncolor.rgb=fog*color.rgb+(1.0-fog)*vFogColor;\n#endif","pbrVertexDeclaration":"uniform mat4 view;\nuniform mat4 viewProjection;\n#ifdef ALBEDO\nuniform mat4 albedoMatrix;\nuniform vec2 vAlbedoInfos;\n#endif\n#ifdef AMBIENT\nuniform mat4 ambientMatrix;\nuniform vec3 vAmbientInfos;\n#endif\n#ifdef OPACITY\nuniform mat4 opacityMatrix;\nuniform vec2 vOpacityInfos;\n#endif\n#ifdef EMISSIVE\nuniform vec2 vEmissiveInfos;\nuniform mat4 emissiveMatrix;\n#endif\n#ifdef LIGHTMAP\nuniform vec2 vLightmapInfos;\nuniform mat4 lightmapMatrix;\n#endif\n#ifdef REFLECTIVITY \nuniform vec3 vReflectivityInfos;\nuniform mat4 reflectivityMatrix;\n#endif\n#ifdef MICROSURFACEMAP\nuniform vec2 vMicroSurfaceSamplerInfos;\nuniform mat4 microSurfaceSamplerMatrix;\n#endif\n#ifdef BUMP\nuniform vec3 vBumpInfos;\nuniform mat4 bumpMatrix;\n#endif\n#ifdef POINTSIZE\nuniform float pointSize;\n#endif\n\n#ifdef REFRACTION\nuniform vec4 vRefractionInfos;\nuniform mat4 refractionMatrix;\nuniform vec3 vRefractionMicrosurfaceInfos;\n#endif\n\n#ifdef REFLECTION\nuniform vec2 vReflectionInfos;\nuniform mat4 reflectionMatrix;\nuniform vec3 vReflectionMicrosurfaceInfos;\n#endif\n","pbrFragmentDeclaration":"uniform vec3 vReflectionColor;\nuniform vec4 vAlbedoColor;\n\nuniform vec4 vLightingIntensity;\nuniform vec4 vReflectivityColor;\nuniform vec3 vEmissiveColor;\n\n#ifdef ALBEDO\nuniform vec2 vAlbedoInfos;\n#endif\n#ifdef AMBIENT\nuniform vec3 vAmbientInfos;\n#endif\n#ifdef BUMP\nuniform vec3 vBumpInfos;\nuniform vec2 vTangentSpaceParams;\n#endif\n#ifdef OPACITY \nuniform vec2 vOpacityInfos;\n#endif\n#ifdef EMISSIVE\nuniform vec2 vEmissiveInfos;\n#endif\n#ifdef LIGHTMAP\nuniform vec2 vLightmapInfos;\n#endif\n#ifdef REFLECTIVITY\nuniform vec3 vReflectivityInfos;\n#endif\n#ifdef MICROSURFACEMAP\nuniform vec2 vMicroSurfaceSamplerInfos;\n#endif\n\n#if defined(REFLECTIONMAP_SPHERICAL) || defined(REFLECTIONMAP_PROJECTION) || defined(REFRACTION)\nuniform mat4 view;\n#endif\n\n#ifdef REFRACTION\nuniform vec4 vRefractionInfos;\nuniform mat4 refractionMatrix;\nuniform vec3 vRefractionMicrosurfaceInfos;\n#endif\n\n#ifdef REFLECTION\nuniform vec2 vReflectionInfos;\nuniform mat4 reflectionMatrix;\nuniform vec3 vReflectionMicrosurfaceInfos;\n#if defined(USE_LOCAL_REFLECTIONMAP_CUBIC) && defined(REFLECTIONMAP_CUBIC)\nuniform vec3 vReflectionPosition;\nuniform vec3 vReflectionSize; \n#endif\n#endif","pbrUboDeclaration":"layout(std140,column_major) uniform;\nuniform Material\n{\nuniform vec2 vAlbedoInfos;\nuniform vec3 vAmbientInfos;\nuniform vec2 vOpacityInfos;\nuniform vec2 vEmissiveInfos;\nuniform vec2 vLightmapInfos;\nuniform vec3 vReflectivityInfos;\nuniform vec2 vMicroSurfaceSamplerInfos;\nuniform vec4 vRefractionInfos;\nuniform vec2 vReflectionInfos;\nuniform vec3 vReflectionPosition;\nuniform vec3 vReflectionSize; \nuniform vec3 vBumpInfos;\nuniform mat4 albedoMatrix;\nuniform mat4 ambientMatrix;\nuniform mat4 opacityMatrix;\nuniform mat4 emissiveMatrix;\nuniform mat4 lightmapMatrix;\nuniform mat4 reflectivityMatrix;\nuniform mat4 microSurfaceSamplerMatrix;\nuniform mat4 bumpMatrix;\nuniform vec2 vTangentSpaceParams;\nuniform mat4 refractionMatrix;\nuniform mat4 reflectionMatrix;\nuniform vec3 vReflectionColor;\nuniform vec4 vAlbedoColor;\nuniform vec4 vLightingIntensity;\nuniform vec3 vRefractionMicrosurfaceInfos;\nuniform vec3 vReflectionMicrosurfaceInfos;\nuniform vec4 vReflectivityColor;\nuniform vec3 vEmissiveColor;\nuniform float pointSize;\n};\nuniform Scene {\nmat4 viewProjection;\nmat4 view;\n};","pbrFunctions":"\n#define RECIPROCAL_PI2 0.15915494\n#define FRESNEL_MAXIMUM_ON_ROUGH 0.25\n\nconst float kRougnhessToAlphaScale=0.1;\nconst float kRougnhessToAlphaOffset=0.29248125;\nfloat convertRoughnessToAverageSlope(float roughness)\n{\n\nconst float kMinimumVariance=0.0005;\nfloat alphaG=square(roughness)+kMinimumVariance;\nreturn alphaG;\n}\n\nfloat smithVisibilityG1_TrowbridgeReitzGGX(float dot,float alphaG)\n{\nfloat tanSquared=(1.0-dot*dot)/(dot*dot);\nreturn 2.0/(1.0+sqrt(1.0+alphaG*alphaG*tanSquared));\n}\nfloat smithVisibilityG_TrowbridgeReitzGGX_Walter(float NdotL,float NdotV,float alphaG)\n{\nreturn smithVisibilityG1_TrowbridgeReitzGGX(NdotL,alphaG)*smithVisibilityG1_TrowbridgeReitzGGX(NdotV,alphaG);\n}\n\n\nfloat normalDistributionFunction_TrowbridgeReitzGGX(float NdotH,float alphaG)\n{\n\n\n\nfloat a2=square(alphaG);\nfloat d=NdotH*NdotH*(a2-1.0)+1.0;\nreturn a2/(PI*d*d);\n}\nvec3 fresnelSchlickGGX(float VdotH,vec3 reflectance0,vec3 reflectance90)\n{\nreturn reflectance0+(reflectance90-reflectance0)*pow(clamp(1.0-VdotH,0.,1.),5.0);\n}\nvec3 fresnelSchlickEnvironmentGGX(float VdotN,vec3 reflectance0,vec3 reflectance90,float smoothness)\n{\n\nfloat weight=mix(FRESNEL_MAXIMUM_ON_ROUGH,1.0,smoothness);\nreturn reflectance0+weight*(reflectance90-reflectance0)*pow(clamp(1.0-VdotN,0.,1.),5.0);\n}\n\nvec3 computeSpecularTerm(float NdotH,float NdotL,float NdotV,float VdotH,float roughness,vec3 reflectance0,vec3 reflectance90)\n{\nfloat alphaG=convertRoughnessToAverageSlope(roughness);\nfloat distribution=normalDistributionFunction_TrowbridgeReitzGGX(NdotH,alphaG);\nfloat visibility=smithVisibilityG_TrowbridgeReitzGGX_Walter(NdotL,NdotV,alphaG);\nvisibility/=(4.0*NdotL*NdotV); \nfloat specTerm=max(0.,visibility*distribution)*NdotL;\nvec3 fresnel=fresnelSchlickGGX(VdotH,reflectance0,reflectance90);\nreturn fresnel*specTerm;\n}\nfloat computeDiffuseTerm(float NdotL,float NdotV,float VdotH,float roughness)\n{\n\n\nfloat diffuseFresnelNV=pow(clamp(1.0-NdotL,0.000001,1.),5.0);\nfloat diffuseFresnelNL=pow(clamp(1.0-NdotV,0.000001,1.),5.0);\nfloat diffuseFresnel90=0.5+2.0*VdotH*VdotH*roughness;\nfloat fresnel =\n(1.0+(diffuseFresnel90-1.0)*diffuseFresnelNL) *\n(1.0+(diffuseFresnel90-1.0)*diffuseFresnelNV);\nreturn fresnel*NdotL/PI;\n}\nfloat adjustRoughnessFromLightProperties(float roughness,float lightRadius,float lightDistance)\n{\n#ifdef USEPHYSICALLIGHTFALLOFF\n\nfloat lightRoughness=lightRadius/lightDistance;\n\nfloat totalRoughness=clamp(lightRoughness+roughness,0.,1.);\nreturn totalRoughness;\n#else\nreturn roughness;\n#endif\n}\nfloat computeDefaultMicroSurface(float microSurface,vec3 reflectivityColor)\n{\nconst float kReflectivityNoAlphaWorkflow_SmoothnessMax=0.95;\nfloat reflectivityLuminance=getLuminance(reflectivityColor);\nfloat reflectivityLuma=sqrt(reflectivityLuminance);\nmicroSurface=reflectivityLuma*kReflectivityNoAlphaWorkflow_SmoothnessMax;\nreturn microSurface;\n}\n\n\nfloat fresnelGrazingReflectance(float reflectance0) {\nfloat reflectance90=clamp(reflectance0*25.0,0.0,1.0);\nreturn reflectance90;\n}\n\n\n#define UNPACK_LOD(x) (1.0-x)*255.0\nfloat getLodFromAlphaG(float cubeMapDimensionPixels,float alphaG,float NdotV) {\nfloat microsurfaceAverageSlope=alphaG;\n\n\n\n\n\n\nmicrosurfaceAverageSlope*=sqrt(abs(NdotV));\nfloat microsurfaceAverageSlopeTexels=microsurfaceAverageSlope*cubeMapDimensionPixels;\nfloat lod=log2(microsurfaceAverageSlopeTexels);\nreturn lod;\n}\nfloat environmentRadianceOcclusion(float ambientOcclusion,float NdotVUnclamped) {\n\n\nfloat temp=NdotVUnclamped+ambientOcclusion;\nreturn clamp(square(temp)-1.0+ambientOcclusion,0.0,1.0);\n}\nfloat environmentHorizonOcclusion(vec3 reflection,vec3 normal) {\n\n#ifdef REFLECTIONMAP_OPPOSITEZ\nreflection.z*=-1.0;\n#endif\nfloat temp=clamp( 1.0+1.1*dot(reflection,normal),0.0,1.0);\nreturn square(temp);\n}","harmonicsFunctions":"#ifdef USESPHERICALFROMREFLECTIONMAP\nuniform vec3 vSphericalX;\nuniform vec3 vSphericalY;\nuniform vec3 vSphericalZ;\nuniform vec3 vSphericalXX_ZZ;\nuniform vec3 vSphericalYY_ZZ;\nuniform vec3 vSphericalZZ;\nuniform vec3 vSphericalXY;\nuniform vec3 vSphericalYZ;\nuniform vec3 vSphericalZX;\nvec3 quaternionVectorRotation_ScaledSqrtTwo(vec4 Q,vec3 V){\nvec3 T=cross(Q.xyz,V);\nT+=Q.www*V;\nreturn cross(Q.xyz,T)+V;\n}\nvec3 environmentIrradianceJones(vec3 normal)\n{\n\n\n\n\n\n\n\n\n\nfloat Nx=normal.x;\nfloat Ny=normal.y;\nfloat Nz=normal.z;\nvec3 C1=vSphericalZZ.rgb;\nvec3 Cx=vSphericalX.rgb;\nvec3 Cy=vSphericalY.rgb;\nvec3 Cz=vSphericalZ.rgb;\nvec3 Cxx_zz=vSphericalXX_ZZ.rgb;\nvec3 Cyy_zz=vSphericalYY_ZZ.rgb;\nvec3 Cxy=vSphericalXY.rgb;\nvec3 Cyz=vSphericalYZ.rgb;\nvec3 Czx=vSphericalZX.rgb;\nvec3 a1=Cyy_zz*Ny+Cy;\nvec3 a2=Cyz*Nz+a1;\nvec3 b1=Czx*Nz+Cx;\nvec3 b2=Cxy*Ny+b1;\nvec3 b3=Cxx_zz*Nx+b2;\nvec3 t1=Cz*Nz+C1;\nvec3 t2=a2*Ny+t1;\nvec3 t3=b3*Nx+t2;\nreturn t3;\n}\n#endif","pbrLightFunctions":"\nstruct lightingInfo\n{\nvec3 diffuse;\n#ifdef SPECULARTERM\nvec3 specular;\n#endif\n};\nfloat computeDistanceLightFalloff(vec3 lightOffset,float lightDistanceSquared,float range)\n{ \n#ifdef USEPHYSICALLIGHTFALLOFF\nfloat lightDistanceFalloff=1.0/((lightDistanceSquared+0.001));\n#else\nfloat lightDistanceFalloff=max(0.,1.0-length(lightOffset)/range);\n#endif\nreturn lightDistanceFalloff;\n}\nfloat computeDirectionalLightFalloff(vec3 lightDirection,vec3 directionToLightCenterW,float cosHalfAngle,float exponent)\n{\nfloat falloff=0.0;\n#ifdef USEPHYSICALLIGHTFALLOFF\nconst float kMinusLog2ConeAngleIntensityRatio=6.64385618977; \n\n\n\n\n\nfloat concentrationKappa=kMinusLog2ConeAngleIntensityRatio/(1.0-cosHalfAngle);\n\n\nvec4 lightDirectionSpreadSG=vec4(-lightDirection*concentrationKappa,-concentrationKappa);\nfalloff=exp2(dot(vec4(directionToLightCenterW,1.0),lightDirectionSpreadSG));\n#else\nfloat cosAngle=max(0.000000000000001,dot(-lightDirection,directionToLightCenterW));\nif (cosAngle>=cosHalfAngle)\n{\nfalloff=max(0.,pow(cosAngle,exponent));\n}\n#endif\nreturn falloff;\n}\nlightingInfo computeLighting(vec3 viewDirectionW,vec3 vNormal,vec4 lightData,vec3 diffuseColor,vec3 specularColor,float rangeRadius,float roughness,float NdotV,vec3 reflectance0,vec3 reflectance90,out float NdotL) {\nlightingInfo result;\nvec3 lightDirection;\nfloat attenuation=1.0;\nfloat lightDistance;\n\nif (lightData.w == 0.)\n{\nvec3 lightOffset=lightData.xyz-vPositionW;\nfloat lightDistanceSquared=dot(lightOffset,lightOffset);\nattenuation=computeDistanceLightFalloff(lightOffset,lightDistanceSquared,rangeRadius);\nlightDistance=sqrt(lightDistanceSquared);\nlightDirection=normalize(lightOffset);\n}\n\nelse\n{\nlightDistance=length(-lightData.xyz);\nlightDirection=normalize(-lightData.xyz);\n}\n\nroughness=adjustRoughnessFromLightProperties(roughness,rangeRadius,lightDistance);\n\nvec3 H=normalize(viewDirectionW+lightDirection);\nNdotL=clamp(dot(vNormal,lightDirection),0.00000000001,1.0);\nfloat VdotH=clamp(dot(viewDirectionW,H),0.0,1.0);\nfloat diffuseTerm=computeDiffuseTerm(NdotL,NdotV,VdotH,roughness);\nresult.diffuse=diffuseTerm*diffuseColor*attenuation;\n#ifdef SPECULARTERM\n\nfloat NdotH=clamp(dot(vNormal,H),0.000000000001,1.0);\nvec3 specTerm=computeSpecularTerm(NdotH,NdotL,NdotV,VdotH,roughness,reflectance0,reflectance90);\nresult.specular=specTerm*diffuseColor*attenuation;\n#endif\nreturn result;\n}\nlightingInfo computeSpotLighting(vec3 viewDirectionW,vec3 vNormal,vec4 lightData,vec4 lightDirection,vec3 diffuseColor,vec3 specularColor,float rangeRadius,float roughness,float NdotV,vec3 reflectance0,vec3 reflectance90,out float NdotL) {\nlightingInfo result;\nvec3 lightOffset=lightData.xyz-vPositionW;\nvec3 directionToLightCenterW=normalize(lightOffset);\n\nfloat lightDistanceSquared=dot(lightOffset,lightOffset);\nfloat attenuation=computeDistanceLightFalloff(lightOffset,lightDistanceSquared,rangeRadius);\n\nfloat directionalAttenuation=computeDirectionalLightFalloff(lightDirection.xyz,directionToLightCenterW,lightDirection.w,lightData.w);\nattenuation*=directionalAttenuation;\n\nfloat lightDistance=sqrt(lightDistanceSquared);\nroughness=adjustRoughnessFromLightProperties(roughness,rangeRadius,lightDistance);\n\nvec3 H=normalize(viewDirectionW+directionToLightCenterW);\nNdotL=clamp(dot(vNormal,directionToLightCenterW),0.000000000001,1.0);\nfloat VdotH=clamp(dot(viewDirectionW,H),0.0,1.0);\nfloat diffuseTerm=computeDiffuseTerm(NdotL,NdotV,VdotH,roughness);\nresult.diffuse=diffuseTerm*diffuseColor*attenuation;\n#ifdef SPECULARTERM\n\nfloat NdotH=clamp(dot(vNormal,H),0.000000000001,1.0);\nvec3 specTerm=computeSpecularTerm(NdotH,NdotL,NdotV,VdotH,roughness,reflectance0,reflectance90);\nresult.specular=specTerm*diffuseColor*attenuation;\n#endif\nreturn result;\n}\nlightingInfo computeHemisphericLighting(vec3 viewDirectionW,vec3 vNormal,vec4 lightData,vec3 diffuseColor,vec3 specularColor,vec3 groundColor,float roughness,float NdotV,vec3 reflectance0,vec3 reflectance90,out float NdotL) {\nlightingInfo result;\n\n\n\nNdotL=dot(vNormal,lightData.xyz)*0.5+0.5;\nresult.diffuse=mix(groundColor,diffuseColor,NdotL);\n#ifdef SPECULARTERM\n\nvec3 lightVectorW=normalize(lightData.xyz);\nvec3 H=normalize(viewDirectionW+lightVectorW);\nfloat NdotH=clamp(dot(vNormal,H),0.000000000001,1.0);\nNdotL=clamp(NdotL,0.000000000001,1.0);\nfloat VdotH=clamp(dot(viewDirectionW,H),0.0,1.0);\nvec3 specTerm=computeSpecularTerm(NdotH,NdotL,NdotV,VdotH,roughness,reflectance0,reflectance90);\nresult.specular=specTerm*diffuseColor;\n#endif\nreturn result;\n}","kernelBlurFragment":"#ifdef DOF\nsampleDepth=sampleDistance(sampleCoord{X});\nfactor=clamp(1.0-((centerSampleDepth-sampleDepth)/centerSampleDepth),0.0,1.0);\ncomputedWeight=KERNEL_WEIGHT{X}*factor;\nsumOfWeights+=computedWeight;\n#else\ncomputedWeight=KERNEL_WEIGHT{X};\n#endif\n#ifdef PACKEDFLOAT\nblend+=unpack(texture2D(textureSampler,sampleCoord{X}))*computedWeight;\n#else\nblend+=texture2D(textureSampler,sampleCoord{X})*computedWeight;\n#endif","kernelBlurFragment2":"#ifdef DOF\nsampleDepth=sampleDistance(sampleCoord{X});\nfactor=clamp(1.0-((centerSampleDepth-sampleDepth)/centerSampleDepth),0.0,1.0);\ncomputedWeight=KERNEL_DEP_WEIGHT{X}*factor;\nsumOfWeights+=computedWeight;\n#else\ncomputedWeight=KERNEL_DEP_WEIGHT{X};\n#endif\n#ifdef PACKEDFLOAT\nblend+=unpack(texture2D(textureSampler,sampleCenter+delta*KERNEL_DEP_OFFSET{X}))*computedWeight;\n#else\nblend+=texture2D(textureSampler,sampleCenter+delta*KERNEL_DEP_OFFSET{X})*computedWeight;\n#endif","kernelBlurVaryingDeclaration":"varying vec2 sampleCoord{X};","kernelBlurVertex":"sampleCoord{X}=sampleCenter+delta*KERNEL_OFFSET{X};","mrtFragmentDeclaration":"#if __VERSION__>=200\nlayout(location=0) out vec4 glFragData[{X}];\n#endif\n","bones300Declaration":"#if NUM_BONE_INFLUENCERS>0\nuniform mat4 mBones[BonesPerMesh];\nin vec4 matricesIndices;\nin vec4 matricesWeights;\n#if NUM_BONE_INFLUENCERS>4\nin vec4 matricesIndicesExtra;\nin vec4 matricesWeightsExtra;\n#endif\n#endif","instances300Declaration":"#ifdef INSTANCES\nin vec4 world0;\nin vec4 world1;\nin vec4 world2;\nin vec4 world3;\n#else\nuniform mat4 world;\n#endif","backgroundVertexDeclaration":"uniform mat4 view;\nuniform mat4 viewProjection;\nuniform float shadowLevel;\n#ifdef DIFFUSE\nuniform mat4 diffuseMatrix;\nuniform vec2 vDiffuseInfos;\n#endif\n#ifdef REFLECTION\nuniform vec2 vReflectionInfos;\nuniform mat4 reflectionMatrix;\nuniform vec3 vReflectionMicrosurfaceInfos;\nuniform float fFovMultiplier;\n#endif\n#ifdef POINTSIZE\nuniform float pointSize;\n#endif","backgroundFragmentDeclaration":" uniform vec4 vPrimaryColor;\nuniform vec4 vSecondaryColor;\nuniform vec4 vTertiaryColor;\nuniform float shadowLevel;\nuniform float alpha;\n#ifdef DIFFUSE\nuniform vec2 vDiffuseInfos;\n#endif\n#ifdef REFLECTION\nuniform vec2 vReflectionInfos;\nuniform mat4 reflectionMatrix;\nuniform vec3 vReflectionMicrosurfaceInfos;\n#endif\n#if defined(REFLECTIONFRESNEL) || defined(OPACITYFRESNEL)\nuniform vec3 vBackgroundCenter;\n#endif\n#ifdef REFLECTIONFRESNEL\nuniform vec4 vReflectionControl;\n#endif\n#if defined(REFLECTIONMAP_SPHERICAL) || defined(REFLECTIONMAP_PROJECTION) || defined(REFRACTION)\nuniform mat4 view;\n#endif","backgroundUboDeclaration":"layout(std140,column_major) uniform;\nuniform Material\n{\nuniform vec4 vPrimaryColor;\nuniform vec4 vSecondaryColor;\nuniform vec4 vTertiaryColor;\nuniform vec2 vDiffuseInfos;\nuniform vec2 vReflectionInfos;\nuniform mat4 diffuseMatrix;\nuniform mat4 reflectionMatrix;\nuniform vec3 vReflectionMicrosurfaceInfos;\nuniform float fFovMultiplier;\nuniform float pointSize;\nuniform float shadowLevel;\nuniform float alpha;\n#if defined(REFLECTIONFRESNEL) || defined(OPACITYFRESNEL)\nuniform vec3 vBackgroundCenter;\n#endif\n#ifdef REFLECTIONFRESNEL\nuniform vec4 vReflectionControl;\n#endif\n};\nuniform Scene {\nmat4 viewProjection;\nmat4 view;\n};"};
///
var BABYLON;
(function (BABYLON) {
var GridMaterialDefines = /** @class */ (function (_super) {
__extends(GridMaterialDefines, _super);
function GridMaterialDefines() {
var _this = _super.call(this) || this;
_this.TRANSPARENT = false;
_this.FOG = false;
_this.PREMULTIPLYALPHA = false;
_this.rebuild();
return _this;
}
return GridMaterialDefines;
}(BABYLON.MaterialDefines));
/**
* The grid materials allows you to wrap any shape with a grid.
* Colors are customizable.
*/
var GridMaterial = /** @class */ (function (_super) {
__extends(GridMaterial, _super);
/**
* constructor
* @param name The name given to the material in order to identify it afterwards.
* @param scene The scene the material is used in.
*/
function GridMaterial(name, scene) {
var _this = _super.call(this, name, scene) || this;
/**
* Main color of the grid (e.g. between lines)
*/
_this.mainColor = BABYLON.Color3.Black();
/**
* Color of the grid lines.
*/
_this.lineColor = BABYLON.Color3.Teal();
/**
* The scale of the grid compared to unit.
*/
_this.gridRatio = 1.0;
/**
* Allows setting an offset for the grid lines.
*/
_this.gridOffset = BABYLON.Vector3.Zero();
/**
* The frequency of thicker lines.
*/
_this.majorUnitFrequency = 10;
/**
* The visibility of minor units in the grid.
*/
_this.minorUnitVisibility = 0.33;
/**
* The grid opacity outside of the lines.
*/
_this.opacity = 1.0;
/**
* Determine RBG output is premultiplied by alpha value.
*/
_this.preMultiplyAlpha = false;
_this._gridControl = new BABYLON.Vector4(_this.gridRatio, _this.majorUnitFrequency, _this.minorUnitVisibility, _this.opacity);
return _this;
}
/**
* Returns wehter or not the grid requires alpha blending.
*/
GridMaterial.prototype.needAlphaBlending = function () {
return this.opacity < 1.0;
};
GridMaterial.prototype.needAlphaBlendingForMesh = function (mesh) {
return this.needAlphaBlending();
};
GridMaterial.prototype.isReadyForSubMesh = function (mesh, subMesh, useInstances) {
if (this.isFrozen) {
if (this._wasPreviouslyReady && subMesh.effect) {
return true;
}
}
if (!subMesh._materialDefines) {
subMesh._materialDefines = new GridMaterialDefines();
}
var defines = subMesh._materialDefines;
var scene = this.getScene();
if (!this.checkReadyOnEveryCall && subMesh.effect) {
if (this._renderId === scene.getRenderId()) {
return true;
}
}
if (defines.TRANSPARENT !== (this.opacity < 1.0)) {
defines.TRANSPARENT = !defines.TRANSPARENT;
defines.markAsUnprocessed();
}
if (defines.PREMULTIPLYALPHA != this.preMultiplyAlpha) {
defines.PREMULTIPLYALPHA = !defines.PREMULTIPLYALPHA;
defines.markAsUnprocessed();
}
BABYLON.MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, false, this.fogEnabled, false, defines);
// Get correct effect
if (defines.isDirty) {
defines.markAsProcessed();
scene.resetCachedMaterial();
// Attributes
var attribs = [BABYLON.VertexBuffer.PositionKind, BABYLON.VertexBuffer.NormalKind];
// Defines
var join = defines.toString();
subMesh.setEffect(scene.getEngine().createEffect("grid", attribs, ["projection", "worldView", "mainColor", "lineColor", "gridControl", "gridOffset", "vFogInfos", "vFogColor", "world", "view"], [], join, undefined, this.onCompiled, this.onError), defines);
}
if (!subMesh.effect || !subMesh.effect.isReady()) {
return false;
}
this._renderId = scene.getRenderId();
this._wasPreviouslyReady = true;
return true;
};
GridMaterial.prototype.bindForSubMesh = function (world, mesh, subMesh) {
var scene = this.getScene();
var defines = subMesh._materialDefines;
if (!defines) {
return;
}
var effect = subMesh.effect;
if (!effect) {
return;
}
this._activeEffect = effect;
// Matrices
this.bindOnlyWorldMatrix(world);
this._activeEffect.setMatrix("worldView", world.multiply(scene.getViewMatrix()));
this._activeEffect.setMatrix("view", scene.getViewMatrix());
this._activeEffect.setMatrix("projection", scene.getProjectionMatrix());
// Uniforms
if (this._mustRebind(scene, effect)) {
this._activeEffect.setColor3("mainColor", this.mainColor);
this._activeEffect.setColor3("lineColor", this.lineColor);
this._activeEffect.setVector3("gridOffset", this.gridOffset);
this._gridControl.x = this.gridRatio;
this._gridControl.y = Math.round(this.majorUnitFrequency);
this._gridControl.z = this.minorUnitVisibility;
this._gridControl.w = this.opacity;
this._activeEffect.setVector4("gridControl", this._gridControl);
}
// Fog
BABYLON.MaterialHelper.BindFogParameters(scene, mesh, this._activeEffect);
this._afterBind(mesh, this._activeEffect);
};
GridMaterial.prototype.dispose = function (forceDisposeEffect) {
_super.prototype.dispose.call(this, forceDisposeEffect);
};
GridMaterial.prototype.clone = function (name) {
var _this = this;
return BABYLON.SerializationHelper.Clone(function () { return new GridMaterial(name, _this.getScene()); }, this);
};
GridMaterial.prototype.serialize = function () {
var serializationObject = BABYLON.SerializationHelper.Serialize(this);
serializationObject.customType = "BABYLON.GridMaterial";
return serializationObject;
};
GridMaterial.prototype.getClassName = function () {
return "GridMaterial";
};
GridMaterial.Parse = function (source, scene, rootUrl) {
return BABYLON.SerializationHelper.Parse(function () { return new GridMaterial(source.name, scene); }, source, scene, rootUrl);
};
__decorate([
BABYLON.serializeAsColor3()
], GridMaterial.prototype, "mainColor", void 0);
__decorate([
BABYLON.serializeAsColor3()
], GridMaterial.prototype, "lineColor", void 0);
__decorate([
BABYLON.serialize()
], GridMaterial.prototype, "gridRatio", void 0);
__decorate([
BABYLON.serializeAsColor3()
], GridMaterial.prototype, "gridOffset", void 0);
__decorate([
BABYLON.serialize()
], GridMaterial.prototype, "majorUnitFrequency", void 0);
__decorate([
BABYLON.serialize()
], GridMaterial.prototype, "minorUnitVisibility", void 0);
__decorate([
BABYLON.serialize()
], GridMaterial.prototype, "opacity", void 0);
__decorate([
BABYLON.serialize()
], GridMaterial.prototype, "preMultiplyAlpha", void 0);
return GridMaterial;
}(BABYLON.PushMaterial));
BABYLON.GridMaterial = GridMaterial;
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.gridmaterial.js.map
BABYLON.Effect.ShadersStore['gridVertexShader'] = "precision highp float;\n\nattribute vec3 position;\nattribute vec3 normal;\n\nuniform mat4 projection;\nuniform mat4 world;\nuniform mat4 view;\nuniform mat4 worldView;\n\n#ifdef TRANSPARENT\nvarying vec4 vCameraSpacePosition;\n#endif\nvarying vec3 vPosition;\nvarying vec3 vNormal;\n#include\nvoid main(void) {\n#ifdef FOG\nvec4 worldPos=world*vec4(position,1.0);\n#endif\n#include\nvec4 cameraSpacePosition=worldView*vec4(position,1.0);\ngl_Position=projection*cameraSpacePosition;\n#ifdef TRANSPARENT\nvCameraSpacePosition=cameraSpacePosition;\n#endif\nvPosition=position;\nvNormal=normal;\n}";
BABYLON.Effect.ShadersStore['gridPixelShader'] = "#extension GL_OES_standard_derivatives : enable\n#define SQRT2 1.41421356\n#define PI 3.14159\nprecision highp float;\nuniform vec3 mainColor;\nuniform vec3 lineColor;\nuniform vec4 gridControl;\nuniform vec3 gridOffset;\n\n#ifdef TRANSPARENT\nvarying vec4 vCameraSpacePosition;\n#endif\nvarying vec3 vPosition;\nvarying vec3 vNormal;\n#include\nfloat getVisibility(float position) {\n\nfloat majorGridFrequency=gridControl.y;\nif (floor(position+0.5) == floor(position/majorGridFrequency+0.5)*majorGridFrequency)\n{\nreturn 1.0;\n} \nreturn gridControl.z;\n}\nfloat getAnisotropicAttenuation(float differentialLength) {\nconst float maxNumberOfLines=10.0;\nreturn clamp(1.0/(differentialLength+1.0)-1.0/maxNumberOfLines,0.0,1.0);\n}\nfloat isPointOnLine(float position,float differentialLength) {\nfloat fractionPartOfPosition=position-floor(position+0.5); \nfractionPartOfPosition/=differentialLength; \nfractionPartOfPosition=clamp(fractionPartOfPosition,-1.,1.);\nfloat result=0.5+0.5*cos(fractionPartOfPosition*PI); \nreturn result; \n}\nfloat contributionOnAxis(float position) {\nfloat differentialLength=length(vec2(dFdx(position),dFdy(position)));\ndifferentialLength*=SQRT2; \n\nfloat result=isPointOnLine(position,differentialLength);\n\nfloat visibility=getVisibility(position);\nresult*=visibility;\n\nfloat anisotropicAttenuation=getAnisotropicAttenuation(differentialLength);\nresult*=anisotropicAttenuation;\nreturn result;\n}\nfloat normalImpactOnAxis(float x) {\nfloat normalImpact=clamp(1.0-3.0*abs(x*x*x),0.0,1.0);\nreturn normalImpact;\n}\nvoid main(void) {\n\nfloat gridRatio=gridControl.x;\nvec3 gridPos=(vPosition+gridOffset)/gridRatio;\n\nfloat x=contributionOnAxis(gridPos.x);\nfloat y=contributionOnAxis(gridPos.y);\nfloat z=contributionOnAxis(gridPos.z);\n\nvec3 normal=normalize(vNormal);\nx*=normalImpactOnAxis(normal.x);\ny*=normalImpactOnAxis(normal.y);\nz*=normalImpactOnAxis(normal.z);\n\nfloat grid=clamp(x+y+z,0.,1.);\n\nvec3 color=mix(mainColor,lineColor,grid);\n#ifdef FOG\n#include\n#endif\n#ifdef TRANSPARENT\nfloat distanceToFragment=length(vCameraSpacePosition.xyz);\nfloat cameraPassThrough=clamp(distanceToFragment-0.25,0.0,1.0);\nfloat opacity=clamp(grid,0.08,cameraPassThrough*gridControl.w*grid);\ngl_FragColor=vec4(color.rgb,opacity);\n#ifdef PREMULTIPLYALPHA\ngl_FragColor.rgb*=opacity;\n#endif\n#else\n\ngl_FragColor=vec4(color.rgb,1.0);\n#endif\n}";
///
var BABYLON;
(function (BABYLON) {
var GLTFLoaderCoordinateSystemMode;
(function (GLTFLoaderCoordinateSystemMode) {
/**
* Automatically convert the glTF right-handed data to the appropriate system based on the current coordinate system mode of the scene.
*/
GLTFLoaderCoordinateSystemMode[GLTFLoaderCoordinateSystemMode["AUTO"] = 0] = "AUTO";
/**
* Sets the useRightHandedSystem flag on the scene.
*/
GLTFLoaderCoordinateSystemMode[GLTFLoaderCoordinateSystemMode["FORCE_RIGHT_HANDED"] = 1] = "FORCE_RIGHT_HANDED";
})(GLTFLoaderCoordinateSystemMode = BABYLON.GLTFLoaderCoordinateSystemMode || (BABYLON.GLTFLoaderCoordinateSystemMode = {}));
var GLTFLoaderAnimationStartMode;
(function (GLTFLoaderAnimationStartMode) {
/**
* No animation will start.
*/
GLTFLoaderAnimationStartMode[GLTFLoaderAnimationStartMode["NONE"] = 0] = "NONE";
/**
* The first animation will start.
*/
GLTFLoaderAnimationStartMode[GLTFLoaderAnimationStartMode["FIRST"] = 1] = "FIRST";
/**
* All animations will start.
*/
GLTFLoaderAnimationStartMode[GLTFLoaderAnimationStartMode["ALL"] = 2] = "ALL";
})(GLTFLoaderAnimationStartMode = BABYLON.GLTFLoaderAnimationStartMode || (BABYLON.GLTFLoaderAnimationStartMode = {}));
var GLTFLoaderState;
(function (GLTFLoaderState) {
GLTFLoaderState[GLTFLoaderState["Loading"] = 0] = "Loading";
GLTFLoaderState[GLTFLoaderState["Ready"] = 1] = "Ready";
GLTFLoaderState[GLTFLoaderState["Complete"] = 2] = "Complete";
})(GLTFLoaderState = BABYLON.GLTFLoaderState || (BABYLON.GLTFLoaderState = {}));
var GLTFFileLoader = /** @class */ (function () {
function GLTFFileLoader() {
// #region Common options
/**
* Raised when the asset has been parsed.
* The data.json property stores the glTF JSON.
* The data.bin property stores the BIN chunk from a glTF binary or null if the input is not a glTF binary.
*/
this.onParsedObservable = new BABYLON.Observable();
// #endregion
// #region V2 options
/**
* The coordinate system mode (AUTO, FORCE_RIGHT_HANDED).
*/
this.coordinateSystemMode = GLTFLoaderCoordinateSystemMode.AUTO;
/**
* The animation start mode (NONE, FIRST, ALL).
*/
this.animationStartMode = GLTFLoaderAnimationStartMode.FIRST;
/**
* Set to true to compile materials before raising the success callback.
*/
this.compileMaterials = false;
/**
* Set to true to also compile materials with clip planes.
*/
this.useClipPlane = false;
/**
* Set to true to compile shadow generators before raising the success callback.
*/
this.compileShadowGenerators = false;
/**
* Raised when the loader creates a mesh after parsing the glTF properties of the mesh.
*/
this.onMeshLoadedObservable = new BABYLON.Observable();
/**
* Raised when the loader creates a texture after parsing the glTF properties of the texture.
*/
this.onTextureLoadedObservable = new BABYLON.Observable();
/**
* Raised when the loader creates a material after parsing the glTF properties of the material.
*/
this.onMaterialLoadedObservable = new BABYLON.Observable();
/**
* Raised when the loader creates an animation group after parsing the glTF properties of the animation.
*/
this.onAnimationGroupLoadedObservable = new BABYLON.Observable();
/**
* Raised when the asset is completely loaded, immediately before the loader is disposed.
* For assets with LODs, raised when all of the LODs are complete.
* For assets without LODs, raised when the model is complete, immediately after onSuccess.
*/
this.onCompleteObservable = new BABYLON.Observable();
/**
* Raised when the loader is disposed.
*/
this.onDisposeObservable = new BABYLON.Observable();
/**
* Raised after a loader extension is created.
* Set additional options for a loader extension in this event.
*/
this.onExtensionLoadedObservable = new BABYLON.Observable();
// #endregion
this._loader = null;
this.name = "gltf";
this.extensions = {
".gltf": { isBinary: false },
".glb": { isBinary: true }
};
}
Object.defineProperty(GLTFFileLoader.prototype, "onParsed", {
set: function (callback) {
if (this._onParsedObserver) {
this.onParsedObservable.remove(this._onParsedObserver);
}
this._onParsedObserver = this.onParsedObservable.add(callback);
},
enumerable: true,
configurable: true
});
Object.defineProperty(GLTFFileLoader.prototype, "onMeshLoaded", {
set: function (callback) {
if (this._onMeshLoadedObserver) {
this.onMeshLoadedObservable.remove(this._onMeshLoadedObserver);
}
this._onMeshLoadedObserver = this.onMeshLoadedObservable.add(callback);
},
enumerable: true,
configurable: true
});
Object.defineProperty(GLTFFileLoader.prototype, "onTextureLoaded", {
set: function (callback) {
if (this._onTextureLoadedObserver) {
this.onTextureLoadedObservable.remove(this._onTextureLoadedObserver);
}
this._onTextureLoadedObserver = this.onTextureLoadedObservable.add(callback);
},
enumerable: true,
configurable: true
});
Object.defineProperty(GLTFFileLoader.prototype, "onMaterialLoaded", {
set: function (callback) {
if (this._onMaterialLoadedObserver) {
this.onMaterialLoadedObservable.remove(this._onMaterialLoadedObserver);
}
this._onMaterialLoadedObserver = this.onMaterialLoadedObservable.add(callback);
},
enumerable: true,
configurable: true
});
Object.defineProperty(GLTFFileLoader.prototype, "onAnimationGroupLoaded", {
set: function (callback) {
if (this._onAnimationGroupLoadedObserver) {
this.onAnimationGroupLoadedObservable.remove(this._onAnimationGroupLoadedObserver);
}
this._onAnimationGroupLoadedObserver = this.onAnimationGroupLoadedObservable.add(callback);
},
enumerable: true,
configurable: true
});
Object.defineProperty(GLTFFileLoader.prototype, "onComplete", {
set: function (callback) {
if (this._onCompleteObserver) {
this.onCompleteObservable.remove(this._onCompleteObserver);
}
this._onCompleteObserver = this.onCompleteObservable.add(callback);
},
enumerable: true,
configurable: true
});
Object.defineProperty(GLTFFileLoader.prototype, "onDispose", {
set: function (callback) {
if (this._onDisposeObserver) {
this.onDisposeObservable.remove(this._onDisposeObserver);
}
this._onDisposeObserver = this.onDisposeObservable.add(callback);
},
enumerable: true,
configurable: true
});
Object.defineProperty(GLTFFileLoader.prototype, "onExtensionLoaded", {
set: function (callback) {
if (this._onExtensionLoadedObserver) {
this.onExtensionLoadedObservable.remove(this._onExtensionLoadedObserver);
}
this._onExtensionLoadedObserver = this.onExtensionLoadedObservable.add(callback);
},
enumerable: true,
configurable: true
});
/**
* Gets a promise that resolves when the asset is completely loaded.
* @returns A promise that resolves when the asset is completely loaded.
*/
GLTFFileLoader.prototype.whenCompleteAsync = function () {
var _this = this;
return new Promise(function (resolve) {
_this.onCompleteObservable.add(function () {
resolve();
}, undefined, undefined, undefined, true);
});
};
Object.defineProperty(GLTFFileLoader.prototype, "loaderState", {
/**
* The loader state or null if not active.
*/
get: function () {
return this._loader ? this._loader.state : null;
},
enumerable: true,
configurable: true
});
/**
* Disposes the loader, releases resources during load, and cancels any outstanding requests.
*/
GLTFFileLoader.prototype.dispose = function () {
if (this._loader) {
this._loader.dispose();
this._loader = null;
}
this.onMeshLoadedObservable.clear();
this.onTextureLoadedObservable.clear();
this.onMaterialLoadedObservable.clear();
this.onDisposeObservable.notifyObservers(this);
this.onDisposeObservable.clear();
};
GLTFFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress) {
var _this = this;
return Promise.resolve().then(function () {
var loaderData = _this._parse(data);
_this._loader = _this._getLoader(loaderData);
return _this._loader.importMeshAsync(meshesNames, scene, loaderData, rootUrl, onProgress);
});
};
GLTFFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress) {
var _this = this;
return Promise.resolve().then(function () {
var loaderData = _this._parse(data);
_this._loader = _this._getLoader(loaderData);
return _this._loader.loadAsync(scene, loaderData, rootUrl, onProgress);
});
};
GLTFFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress) {
var _this = this;
return Promise.resolve().then(function () {
var loaderData = _this._parse(data);
_this._loader = _this._getLoader(loaderData);
return _this._loader.importMeshAsync(null, scene, loaderData, rootUrl, onProgress).then(function (result) {
var container = new BABYLON.AssetContainer(scene);
Array.prototype.push.apply(container.meshes, result.meshes);
Array.prototype.push.apply(container.particleSystems, result.particleSystems);
Array.prototype.push.apply(container.skeletons, result.skeletons);
container.removeAllFromScene();
return container;
});
});
};
GLTFFileLoader.prototype.canDirectLoad = function (data) {
return ((data.indexOf("scene") !== -1) && (data.indexOf("node") !== -1));
};
GLTFFileLoader.prototype.createPlugin = function () {
return new GLTFFileLoader();
};
GLTFFileLoader.prototype._parse = function (data) {
var parsedData;
if (data instanceof ArrayBuffer) {
parsedData = GLTFFileLoader._parseBinary(data);
}
else {
parsedData = {
json: JSON.parse(data),
bin: null
};
}
this.onParsedObservable.notifyObservers(parsedData);
this.onParsedObservable.clear();
return parsedData;
};
GLTFFileLoader.prototype._getLoader = function (loaderData) {
var _this = this;
var loaderVersion = { major: 2, minor: 0 };
var asset = loaderData.json.asset || {};
var version = GLTFFileLoader._parseVersion(asset.version);
if (!version) {
throw new Error("Invalid version: " + asset.version);
}
if (asset.minVersion !== undefined) {
var minVersion = GLTFFileLoader._parseVersion(asset.minVersion);
if (!minVersion) {
throw new Error("Invalid minimum version: " + asset.minVersion);
}
if (GLTFFileLoader._compareVersion(minVersion, loaderVersion) > 0) {
throw new Error("Incompatible minimum version: " + asset.minVersion);
}
}
var createLoaders = {
1: GLTFFileLoader.CreateGLTFLoaderV1,
2: GLTFFileLoader.CreateGLTFLoaderV2
};
var createLoader = createLoaders[version.major];
if (!createLoader) {
throw new Error("Unsupported version: " + asset.version);
}
var loader = createLoader();
loader.coordinateSystemMode = this.coordinateSystemMode;
loader.animationStartMode = this.animationStartMode;
loader.compileMaterials = this.compileMaterials;
loader.useClipPlane = this.useClipPlane;
loader.compileShadowGenerators = this.compileShadowGenerators;
loader.onMeshLoadedObservable.add(function (mesh) { return _this.onMeshLoadedObservable.notifyObservers(mesh); });
loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
loader.onExtensionLoadedObservable.add(function (extension) { return _this.onExtensionLoadedObservable.notifyObservers(extension); });
loader.onCompleteObservable.add(function () {
_this.onMeshLoadedObservable.clear();
_this.onTextureLoadedObservable.clear();
_this.onMaterialLoadedObservable.clear();
_this.onCompleteObservable.notifyObservers(_this);
_this.onCompleteObservable.clear();
});
return loader;
};
GLTFFileLoader._parseBinary = function (data) {
var Binary = {
Magic: 0x46546C67
};
var binaryReader = new BinaryReader(data);
var magic = binaryReader.readUint32();
if (magic !== Binary.Magic) {
throw new Error("Unexpected magic: " + magic);
}
var version = binaryReader.readUint32();
switch (version) {
case 1: return GLTFFileLoader._parseV1(binaryReader);
case 2: return GLTFFileLoader._parseV2(binaryReader);
}
throw new Error("Unsupported version: " + version);
};
GLTFFileLoader._parseV1 = function (binaryReader) {
var ContentFormat = {
JSON: 0
};
var length = binaryReader.readUint32();
if (length != binaryReader.getLength()) {
throw new Error("Length in header does not match actual data length: " + length + " != " + binaryReader.getLength());
}
var contentLength = binaryReader.readUint32();
var contentFormat = binaryReader.readUint32();
var content;
switch (contentFormat) {
case ContentFormat.JSON: {
content = JSON.parse(GLTFFileLoader._decodeBufferToText(binaryReader.readUint8Array(contentLength)));
break;
}
default: {
throw new Error("Unexpected content format: " + contentFormat);
}
}
var bytesRemaining = binaryReader.getLength() - binaryReader.getPosition();
var body = binaryReader.readUint8Array(bytesRemaining);
return {
json: content,
bin: body
};
};
GLTFFileLoader._parseV2 = function (binaryReader) {
var ChunkFormat = {
JSON: 0x4E4F534A,
BIN: 0x004E4942
};
var length = binaryReader.readUint32();
if (length !== binaryReader.getLength()) {
throw new Error("Length in header does not match actual data length: " + length + " != " + binaryReader.getLength());
}
// JSON chunk
var chunkLength = binaryReader.readUint32();
var chunkFormat = binaryReader.readUint32();
if (chunkFormat !== ChunkFormat.JSON) {
throw new Error("First chunk format is not JSON");
}
var json = JSON.parse(GLTFFileLoader._decodeBufferToText(binaryReader.readUint8Array(chunkLength)));
// Look for BIN chunk
var bin = null;
while (binaryReader.getPosition() < binaryReader.getLength()) {
var chunkLength_1 = binaryReader.readUint32();
var chunkFormat_1 = binaryReader.readUint32();
switch (chunkFormat_1) {
case ChunkFormat.JSON: {
throw new Error("Unexpected JSON chunk");
}
case ChunkFormat.BIN: {
bin = binaryReader.readUint8Array(chunkLength_1);
break;
}
default: {
// ignore unrecognized chunkFormat
binaryReader.skipBytes(chunkLength_1);
break;
}
}
}
return {
json: json,
bin: bin
};
};
GLTFFileLoader._parseVersion = function (version) {
if (version === "1.0" || version === "1.0.1") {
return {
major: 1,
minor: 0
};
}
var match = (version + "").match(/^(\d+)\.(\d+)/);
if (!match) {
return null;
}
return {
major: parseInt(match[1]),
minor: parseInt(match[2])
};
};
GLTFFileLoader._compareVersion = function (a, b) {
if (a.major > b.major)
return 1;
if (a.major < b.major)
return -1;
if (a.minor > b.minor)
return 1;
if (a.minor < b.minor)
return -1;
return 0;
};
GLTFFileLoader._decodeBufferToText = function (buffer) {
var result = "";
var length = buffer.byteLength;
for (var i = 0; i < length; i++) {
result += String.fromCharCode(buffer[i]);
}
return result;
};
// #endregion
// #region V1 options
GLTFFileLoader.IncrementalLoading = true;
GLTFFileLoader.HomogeneousCoordinates = false;
return GLTFFileLoader;
}());
BABYLON.GLTFFileLoader = GLTFFileLoader;
var BinaryReader = /** @class */ (function () {
function BinaryReader(arrayBuffer) {
this._arrayBuffer = arrayBuffer;
this._dataView = new DataView(arrayBuffer);
this._byteOffset = 0;
}
BinaryReader.prototype.getPosition = function () {
return this._byteOffset;
};
BinaryReader.prototype.getLength = function () {
return this._arrayBuffer.byteLength;
};
BinaryReader.prototype.readUint32 = function () {
var value = this._dataView.getUint32(this._byteOffset, true);
this._byteOffset += 4;
return value;
};
BinaryReader.prototype.readUint8Array = function (length) {
var value = new Uint8Array(this._arrayBuffer, this._byteOffset, length);
this._byteOffset += length;
return value;
};
BinaryReader.prototype.skipBytes = function (length) {
this._byteOffset += length;
};
return BinaryReader;
}());
if (BABYLON.SceneLoader) {
BABYLON.SceneLoader.RegisterPlugin(new GLTFFileLoader());
}
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.glTFFileLoader.js.map
///
var BABYLON;
(function (BABYLON) {
var GLTF1;
(function (GLTF1) {
/**
* Enums
*/
var EComponentType;
(function (EComponentType) {
EComponentType[EComponentType["BYTE"] = 5120] = "BYTE";
EComponentType[EComponentType["UNSIGNED_BYTE"] = 5121] = "UNSIGNED_BYTE";
EComponentType[EComponentType["SHORT"] = 5122] = "SHORT";
EComponentType[EComponentType["UNSIGNED_SHORT"] = 5123] = "UNSIGNED_SHORT";
EComponentType[EComponentType["FLOAT"] = 5126] = "FLOAT";
})(EComponentType = GLTF1.EComponentType || (GLTF1.EComponentType = {}));
var EShaderType;
(function (EShaderType) {
EShaderType[EShaderType["FRAGMENT"] = 35632] = "FRAGMENT";
EShaderType[EShaderType["VERTEX"] = 35633] = "VERTEX";
})(EShaderType = GLTF1.EShaderType || (GLTF1.EShaderType = {}));
var EParameterType;
(function (EParameterType) {
EParameterType[EParameterType["BYTE"] = 5120] = "BYTE";
EParameterType[EParameterType["UNSIGNED_BYTE"] = 5121] = "UNSIGNED_BYTE";
EParameterType[EParameterType["SHORT"] = 5122] = "SHORT";
EParameterType[EParameterType["UNSIGNED_SHORT"] = 5123] = "UNSIGNED_SHORT";
EParameterType[EParameterType["INT"] = 5124] = "INT";
EParameterType[EParameterType["UNSIGNED_INT"] = 5125] = "UNSIGNED_INT";
EParameterType[EParameterType["FLOAT"] = 5126] = "FLOAT";
EParameterType[EParameterType["FLOAT_VEC2"] = 35664] = "FLOAT_VEC2";
EParameterType[EParameterType["FLOAT_VEC3"] = 35665] = "FLOAT_VEC3";
EParameterType[EParameterType["FLOAT_VEC4"] = 35666] = "FLOAT_VEC4";
EParameterType[EParameterType["INT_VEC2"] = 35667] = "INT_VEC2";
EParameterType[EParameterType["INT_VEC3"] = 35668] = "INT_VEC3";
EParameterType[EParameterType["INT_VEC4"] = 35669] = "INT_VEC4";
EParameterType[EParameterType["BOOL"] = 35670] = "BOOL";
EParameterType[EParameterType["BOOL_VEC2"] = 35671] = "BOOL_VEC2";
EParameterType[EParameterType["BOOL_VEC3"] = 35672] = "BOOL_VEC3";
EParameterType[EParameterType["BOOL_VEC4"] = 35673] = "BOOL_VEC4";
EParameterType[EParameterType["FLOAT_MAT2"] = 35674] = "FLOAT_MAT2";
EParameterType[EParameterType["FLOAT_MAT3"] = 35675] = "FLOAT_MAT3";
EParameterType[EParameterType["FLOAT_MAT4"] = 35676] = "FLOAT_MAT4";
EParameterType[EParameterType["SAMPLER_2D"] = 35678] = "SAMPLER_2D";
})(EParameterType = GLTF1.EParameterType || (GLTF1.EParameterType = {}));
var ETextureWrapMode;
(function (ETextureWrapMode) {
ETextureWrapMode[ETextureWrapMode["CLAMP_TO_EDGE"] = 33071] = "CLAMP_TO_EDGE";
ETextureWrapMode[ETextureWrapMode["MIRRORED_REPEAT"] = 33648] = "MIRRORED_REPEAT";
ETextureWrapMode[ETextureWrapMode["REPEAT"] = 10497] = "REPEAT";
})(ETextureWrapMode = GLTF1.ETextureWrapMode || (GLTF1.ETextureWrapMode = {}));
var ETextureFilterType;
(function (ETextureFilterType) {
ETextureFilterType[ETextureFilterType["NEAREST"] = 9728] = "NEAREST";
ETextureFilterType[ETextureFilterType["LINEAR"] = 9728] = "LINEAR";
ETextureFilterType[ETextureFilterType["NEAREST_MIPMAP_NEAREST"] = 9984] = "NEAREST_MIPMAP_NEAREST";
ETextureFilterType[ETextureFilterType["LINEAR_MIPMAP_NEAREST"] = 9985] = "LINEAR_MIPMAP_NEAREST";
ETextureFilterType[ETextureFilterType["NEAREST_MIPMAP_LINEAR"] = 9986] = "NEAREST_MIPMAP_LINEAR";
ETextureFilterType[ETextureFilterType["LINEAR_MIPMAP_LINEAR"] = 9987] = "LINEAR_MIPMAP_LINEAR";
})(ETextureFilterType = GLTF1.ETextureFilterType || (GLTF1.ETextureFilterType = {}));
var ETextureFormat;
(function (ETextureFormat) {
ETextureFormat[ETextureFormat["ALPHA"] = 6406] = "ALPHA";
ETextureFormat[ETextureFormat["RGB"] = 6407] = "RGB";
ETextureFormat[ETextureFormat["RGBA"] = 6408] = "RGBA";
ETextureFormat[ETextureFormat["LUMINANCE"] = 6409] = "LUMINANCE";
ETextureFormat[ETextureFormat["LUMINANCE_ALPHA"] = 6410] = "LUMINANCE_ALPHA";
})(ETextureFormat = GLTF1.ETextureFormat || (GLTF1.ETextureFormat = {}));
var ECullingType;
(function (ECullingType) {
ECullingType[ECullingType["FRONT"] = 1028] = "FRONT";
ECullingType[ECullingType["BACK"] = 1029] = "BACK";
ECullingType[ECullingType["FRONT_AND_BACK"] = 1032] = "FRONT_AND_BACK";
})(ECullingType = GLTF1.ECullingType || (GLTF1.ECullingType = {}));
var EBlendingFunction;
(function (EBlendingFunction) {
EBlendingFunction[EBlendingFunction["ZERO"] = 0] = "ZERO";
EBlendingFunction[EBlendingFunction["ONE"] = 1] = "ONE";
EBlendingFunction[EBlendingFunction["SRC_COLOR"] = 768] = "SRC_COLOR";
EBlendingFunction[EBlendingFunction["ONE_MINUS_SRC_COLOR"] = 769] = "ONE_MINUS_SRC_COLOR";
EBlendingFunction[EBlendingFunction["DST_COLOR"] = 774] = "DST_COLOR";
EBlendingFunction[EBlendingFunction["ONE_MINUS_DST_COLOR"] = 775] = "ONE_MINUS_DST_COLOR";
EBlendingFunction[EBlendingFunction["SRC_ALPHA"] = 770] = "SRC_ALPHA";
EBlendingFunction[EBlendingFunction["ONE_MINUS_SRC_ALPHA"] = 771] = "ONE_MINUS_SRC_ALPHA";
EBlendingFunction[EBlendingFunction["DST_ALPHA"] = 772] = "DST_ALPHA";
EBlendingFunction[EBlendingFunction["ONE_MINUS_DST_ALPHA"] = 773] = "ONE_MINUS_DST_ALPHA";
EBlendingFunction[EBlendingFunction["CONSTANT_COLOR"] = 32769] = "CONSTANT_COLOR";
EBlendingFunction[EBlendingFunction["ONE_MINUS_CONSTANT_COLOR"] = 32770] = "ONE_MINUS_CONSTANT_COLOR";
EBlendingFunction[EBlendingFunction["CONSTANT_ALPHA"] = 32771] = "CONSTANT_ALPHA";
EBlendingFunction[EBlendingFunction["ONE_MINUS_CONSTANT_ALPHA"] = 32772] = "ONE_MINUS_CONSTANT_ALPHA";
EBlendingFunction[EBlendingFunction["SRC_ALPHA_SATURATE"] = 776] = "SRC_ALPHA_SATURATE";
})(EBlendingFunction = GLTF1.EBlendingFunction || (GLTF1.EBlendingFunction = {}));
})(GLTF1 = BABYLON.GLTF1 || (BABYLON.GLTF1 = {}));
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.glTFLoaderInterfaces.js.map
///
var BABYLON;
(function (BABYLON) {
var GLTF1;
(function (GLTF1) {
/**
* Tokenizer. Used for shaders compatibility
* Automatically map world, view, projection, worldViewProjection, attributes and so on
*/
var ETokenType;
(function (ETokenType) {
ETokenType[ETokenType["IDENTIFIER"] = 1] = "IDENTIFIER";
ETokenType[ETokenType["UNKNOWN"] = 2] = "UNKNOWN";
ETokenType[ETokenType["END_OF_INPUT"] = 3] = "END_OF_INPUT";
})(ETokenType || (ETokenType = {}));
var Tokenizer = /** @class */ (function () {
function Tokenizer(toParse) {
this._pos = 0;
this.isLetterOrDigitPattern = /^[a-zA-Z0-9]+$/;
this._toParse = toParse;
this._maxPos = toParse.length;
}
Tokenizer.prototype.getNextToken = function () {
if (this.isEnd())
return ETokenType.END_OF_INPUT;
this.currentString = this.read();
this.currentToken = ETokenType.UNKNOWN;
if (this.currentString === "_" || this.isLetterOrDigitPattern.test(this.currentString)) {
this.currentToken = ETokenType.IDENTIFIER;
this.currentIdentifier = this.currentString;
while (!this.isEnd() && (this.isLetterOrDigitPattern.test(this.currentString = this.peek()) || this.currentString === "_")) {
this.currentIdentifier += this.currentString;
this.forward();
}
}
return this.currentToken;
};
Tokenizer.prototype.peek = function () {
return this._toParse[this._pos];
};
Tokenizer.prototype.read = function () {
return this._toParse[this._pos++];
};
Tokenizer.prototype.forward = function () {
this._pos++;
};
Tokenizer.prototype.isEnd = function () {
return this._pos >= this._maxPos;
};
return Tokenizer;
}());
/**
* Values
*/
var glTFTransforms = ["MODEL", "VIEW", "PROJECTION", "MODELVIEW", "MODELVIEWPROJECTION", "JOINTMATRIX"];
var babylonTransforms = ["world", "view", "projection", "worldView", "worldViewProjection", "mBones"];
var glTFAnimationPaths = ["translation", "rotation", "scale"];
var babylonAnimationPaths = ["position", "rotationQuaternion", "scaling"];
/**
* Parse
*/
var parseBuffers = function (parsedBuffers, gltfRuntime) {
for (var buf in parsedBuffers) {
var parsedBuffer = parsedBuffers[buf];
gltfRuntime.buffers[buf] = parsedBuffer;
gltfRuntime.buffersCount++;
}
};
var parseShaders = function (parsedShaders, gltfRuntime) {
for (var sha in parsedShaders) {
var parsedShader = parsedShaders[sha];
gltfRuntime.shaders[sha] = parsedShader;
gltfRuntime.shaderscount++;
}
};
var parseObject = function (parsedObjects, runtimeProperty, gltfRuntime) {
for (var object in parsedObjects) {
var parsedObject = parsedObjects[object];
gltfRuntime[runtimeProperty][object] = parsedObject;
}
};
/**
* Utils
*/
var normalizeUVs = function (buffer) {
if (!buffer) {
return;
}
for (var i = 0; i < buffer.length / 2; i++) {
buffer[i * 2 + 1] = 1.0 - buffer[i * 2 + 1];
}
};
var getAttribute = function (attributeParameter) {
if (attributeParameter.semantic === "NORMAL") {
return "normal";
}
else if (attributeParameter.semantic === "POSITION") {
return "position";
}
else if (attributeParameter.semantic === "JOINT") {
return "matricesIndices";
}
else if (attributeParameter.semantic === "WEIGHT") {
return "matricesWeights";
}
else if (attributeParameter.semantic === "COLOR") {
return "color";
}
else if (attributeParameter.semantic && attributeParameter.semantic.indexOf("TEXCOORD_") !== -1) {
var channel = Number(attributeParameter.semantic.split("_")[1]);
return "uv" + (channel === 0 ? "" : channel + 1);
}
return null;
};
/**
* Loads and creates animations
*/
var loadAnimations = function (gltfRuntime) {
for (var anim in gltfRuntime.animations) {
var animation = gltfRuntime.animations[anim];
if (!animation.channels || !animation.samplers) {
continue;
}
var lastAnimation = null;
for (var i = 0; i < animation.channels.length; i++) {
// Get parameters and load buffers
var channel = animation.channels[i];
var sampler = animation.samplers[channel.sampler];
if (!sampler) {
continue;
}
var inputData = null;
var outputData = null;
if (animation.parameters) {
inputData = animation.parameters[sampler.input];
outputData = animation.parameters[sampler.output];
}
else {
inputData = sampler.input;
outputData = sampler.output;
}
var bufferInput = GLTF1.GLTFUtils.GetBufferFromAccessor(gltfRuntime, gltfRuntime.accessors[inputData]);
var bufferOutput = GLTF1.GLTFUtils.GetBufferFromAccessor(gltfRuntime, gltfRuntime.accessors[outputData]);
var targetID = channel.target.id;
var targetNode = gltfRuntime.scene.getNodeByID(targetID);
if (targetNode === null) {
targetNode = gltfRuntime.scene.getNodeByName(targetID);
}
if (targetNode === null) {
BABYLON.Tools.Warn("Creating animation named " + anim + ". But cannot find node named " + targetID + " to attach to");
continue;
}
var isBone = targetNode instanceof BABYLON.Bone;
// Get target path (position, rotation or scaling)
var targetPath = channel.target.path;
var targetPathIndex = glTFAnimationPaths.indexOf(targetPath);
if (targetPathIndex !== -1) {
targetPath = babylonAnimationPaths[targetPathIndex];
}
// Determine animation type
var animationType = BABYLON.Animation.ANIMATIONTYPE_MATRIX;
if (!isBone) {
if (targetPath === "rotationQuaternion") {
animationType = BABYLON.Animation.ANIMATIONTYPE_QUATERNION;
targetNode.rotationQuaternion = new BABYLON.Quaternion();
}
else {
animationType = BABYLON.Animation.ANIMATIONTYPE_VECTOR3;
}
}
// Create animation and key frames
var babylonAnimation = null;
var keys = [];
var arrayOffset = 0;
var modifyKey = false;
if (isBone && lastAnimation && lastAnimation.getKeys().length === bufferInput.length) {
babylonAnimation = lastAnimation;
modifyKey = true;
}
if (!modifyKey) {
babylonAnimation = new BABYLON.Animation(anim, isBone ? "_matrix" : targetPath, 1, animationType, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
}
// For each frame
for (var j = 0; j < bufferInput.length; j++) {
var value = null;
if (targetPath === "rotationQuaternion") {
value = BABYLON.Quaternion.FromArray([bufferOutput[arrayOffset], bufferOutput[arrayOffset + 1], bufferOutput[arrayOffset + 2], bufferOutput[arrayOffset + 3]]);
arrayOffset += 4;
}
else {
value = BABYLON.Vector3.FromArray([bufferOutput[arrayOffset], bufferOutput[arrayOffset + 1], bufferOutput[arrayOffset + 2]]);
arrayOffset += 3;
}
if (isBone) {
var bone = targetNode;
var translation = BABYLON.Vector3.Zero();
var rotationQuaternion = new BABYLON.Quaternion();
var scaling = BABYLON.Vector3.Zero();
// Warning on decompose
var mat = bone.getBaseMatrix();
if (modifyKey && lastAnimation) {
mat = lastAnimation.getKeys()[j].value;
}
mat.decompose(scaling, rotationQuaternion, translation);
if (targetPath === "position") {
translation = value;
}
else if (targetPath === "rotationQuaternion") {
rotationQuaternion = value;
}
else {
scaling = value;
}
value = BABYLON.Matrix.Compose(scaling, rotationQuaternion, translation);
}
if (!modifyKey) {
keys.push({
frame: bufferInput[j],
value: value
});
}
else if (lastAnimation) {
lastAnimation.getKeys()[j].value = value;
}
}
// Finish
if (!modifyKey && babylonAnimation) {
babylonAnimation.setKeys(keys);
targetNode.animations.push(babylonAnimation);
}
lastAnimation = babylonAnimation;
gltfRuntime.scene.stopAnimation(targetNode);
gltfRuntime.scene.beginAnimation(targetNode, 0, bufferInput[bufferInput.length - 1], true, 1.0);
}
}
};
/**
* Returns the bones transformation matrix
*/
var configureBoneTransformation = function (node) {
var mat = null;
if (node.translation || node.rotation || node.scale) {
var scale = BABYLON.Vector3.FromArray(node.scale || [1, 1, 1]);
var rotation = BABYLON.Quaternion.FromArray(node.rotation || [0, 0, 0, 1]);
var position = BABYLON.Vector3.FromArray(node.translation || [0, 0, 0]);
mat = BABYLON.Matrix.Compose(scale, rotation, position);
}
else {
mat = BABYLON.Matrix.FromArray(node.matrix);
}
return mat;
};
/**
* Returns the parent bone
*/
var getParentBone = function (gltfRuntime, skins, jointName, newSkeleton) {
// Try to find
for (var i = 0; i < newSkeleton.bones.length; i++) {
if (newSkeleton.bones[i].name === jointName) {
return newSkeleton.bones[i];
}
}
// Not found, search in gltf nodes
var nodes = gltfRuntime.nodes;
for (var nde in nodes) {
var node = nodes[nde];
if (!node.jointName) {
continue;
}
var children = node.children;
for (var i = 0; i < children.length; i++) {
var child = gltfRuntime.nodes[children[i]];
if (!child.jointName) {
continue;
}
if (child.jointName === jointName) {
var mat = configureBoneTransformation(node);
var bone = new BABYLON.Bone(node.name || "", newSkeleton, getParentBone(gltfRuntime, skins, node.jointName, newSkeleton), mat);
bone.id = nde;
return bone;
}
}
}
return null;
};
/**
* Returns the appropriate root node
*/
var getNodeToRoot = function (nodesToRoot, id) {
for (var i = 0; i < nodesToRoot.length; i++) {
var nodeToRoot = nodesToRoot[i];
for (var j = 0; j < nodeToRoot.node.children.length; j++) {
var child = nodeToRoot.node.children[j];
if (child === id) {
return nodeToRoot.bone;
}
}
}
return null;
};
/**
* Returns the node with the joint name
*/
var getJointNode = function (gltfRuntime, jointName) {
var nodes = gltfRuntime.nodes;
var node = nodes[jointName];
if (node) {
return {
node: node,
id: jointName
};
}
for (var nde in nodes) {
node = nodes[nde];
if (node.jointName === jointName) {
return {
node: node,
id: nde
};
}
}
return null;
};
/**
* Checks if a nodes is in joints
*/
var nodeIsInJoints = function (skins, id) {
for (var i = 0; i < skins.jointNames.length; i++) {
if (skins.jointNames[i] === id) {
return true;
}
}
return false;
};
/**
* Fills the nodes to root for bones and builds hierarchy
*/
var getNodesToRoot = function (gltfRuntime, newSkeleton, skins, nodesToRoot) {
// Creates nodes for root
for (var nde in gltfRuntime.nodes) {
var node = gltfRuntime.nodes[nde];
var id = nde;
if (!node.jointName || nodeIsInJoints(skins, node.jointName)) {
continue;
}
// Create node to root bone
var mat = configureBoneTransformation(node);
var bone = new BABYLON.Bone(node.name || "", newSkeleton, null, mat);
bone.id = id;
nodesToRoot.push({ bone: bone, node: node, id: id });
}
// Parenting
for (var i = 0; i < nodesToRoot.length; i++) {
var nodeToRoot = nodesToRoot[i];
var children = nodeToRoot.node.children;
for (var j = 0; j < children.length; j++) {
var child = null;
for (var k = 0; k < nodesToRoot.length; k++) {
if (nodesToRoot[k].id === children[j]) {
child = nodesToRoot[k];
break;
}
}
if (child) {
child.bone._parent = nodeToRoot.bone;
nodeToRoot.bone.children.push(child.bone);
}
}
}
};
/**
* Imports a skeleton
*/
var importSkeleton = function (gltfRuntime, skins, mesh, newSkeleton, id) {
if (!newSkeleton) {
newSkeleton = new BABYLON.Skeleton(skins.name || "", "", gltfRuntime.scene);
}
if (!skins.babylonSkeleton) {
return newSkeleton;
}
// Find the root bones
var nodesToRoot = [];
var nodesToRootToAdd = [];
getNodesToRoot(gltfRuntime, newSkeleton, skins, nodesToRoot);
newSkeleton.bones = [];
// Joints
for (var i = 0; i < skins.jointNames.length; i++) {
var jointNode = getJointNode(gltfRuntime, skins.jointNames[i]);
if (!jointNode) {
continue;
}
var node = jointNode.node;
if (!node) {
BABYLON.Tools.Warn("Joint named " + skins.jointNames[i] + " does not exist");
continue;
}
var id = jointNode.id;
// Optimize, if the bone already exists...
var existingBone = gltfRuntime.scene.getBoneByID(id);
if (existingBone) {
newSkeleton.bones.push(existingBone);
continue;
}
// Search for parent bone
var foundBone = false;
var parentBone = null;
for (var j = 0; j < i; j++) {
var jointNode_1 = getJointNode(gltfRuntime, skins.jointNames[j]);
if (!jointNode_1) {
continue;
}
var joint = jointNode_1.node;
if (!joint) {
BABYLON.Tools.Warn("Joint named " + skins.jointNames[j] + " does not exist when looking for parent");
continue;
}
var children = joint.children;
if (!children) {
continue;
}
foundBone = false;
for (var k = 0; k < children.length; k++) {
if (children[k] === id) {
parentBone = getParentBone(gltfRuntime, skins, skins.jointNames[j], newSkeleton);
foundBone = true;
break;
}
}
if (foundBone) {
break;
}
}
// Create bone
var mat = configureBoneTransformation(node);
if (!parentBone && nodesToRoot.length > 0) {
parentBone = getNodeToRoot(nodesToRoot, id);
if (parentBone) {
if (nodesToRootToAdd.indexOf(parentBone) === -1) {
nodesToRootToAdd.push(parentBone);
}
}
}
var bone = new BABYLON.Bone(node.jointName || "", newSkeleton, parentBone, mat);
bone.id = id;
}
// Polish
var bones = newSkeleton.bones;
newSkeleton.bones = [];
for (var i = 0; i < skins.jointNames.length; i++) {
var jointNode = getJointNode(gltfRuntime, skins.jointNames[i]);
if (!jointNode) {
continue;
}
for (var j = 0; j < bones.length; j++) {
if (bones[j].id === jointNode.id) {
newSkeleton.bones.push(bones[j]);
break;
}
}
}
newSkeleton.prepare();
// Finish
for (var i = 0; i < nodesToRootToAdd.length; i++) {
newSkeleton.bones.push(nodesToRootToAdd[i]);
}
return newSkeleton;
};
/**
* Imports a mesh and its geometries
*/
var importMesh = function (gltfRuntime, node, meshes, id, newMesh) {
if (!newMesh) {
newMesh = new BABYLON.Mesh(node.name || "", gltfRuntime.scene);
newMesh.id = id;
}
if (!node.babylonNode) {
return newMesh;
}
var subMaterials = [];
var vertexData = null;
var verticesStarts = new Array();
var verticesCounts = new Array();
var indexStarts = new Array();
var indexCounts = new Array();
for (var meshIndex = 0; meshIndex < meshes.length; meshIndex++) {
var meshID = meshes[meshIndex];
var mesh = gltfRuntime.meshes[meshID];
if (!mesh) {
continue;
}
// Positions, normals and UVs
for (var i = 0; i < mesh.primitives.length; i++) {
// Temporary vertex data
var tempVertexData = new BABYLON.VertexData();
var primitive = mesh.primitives[i];
if (primitive.mode !== 4) {
// continue;
}
var attributes = primitive.attributes;
var accessor = null;
var buffer = null;
// Set positions, normal and uvs
for (var semantic in attributes) {
// Link accessor and buffer view
accessor = gltfRuntime.accessors[attributes[semantic]];
buffer = GLTF1.GLTFUtils.GetBufferFromAccessor(gltfRuntime, accessor);
if (semantic === "NORMAL") {
tempVertexData.normals = new Float32Array(buffer.length);
tempVertexData.normals.set(buffer);
}
else if (semantic === "POSITION") {
if (BABYLON.GLTFFileLoader.HomogeneousCoordinates) {
tempVertexData.positions = new Float32Array(buffer.length - buffer.length / 4);
for (var j = 0; j < buffer.length; j += 4) {
tempVertexData.positions[j] = buffer[j];
tempVertexData.positions[j + 1] = buffer[j + 1];
tempVertexData.positions[j + 2] = buffer[j + 2];
}
}
else {
tempVertexData.positions = new Float32Array(buffer.length);
tempVertexData.positions.set(buffer);
}
verticesCounts.push(tempVertexData.positions.length);
}
else if (semantic.indexOf("TEXCOORD_") !== -1) {
var channel = Number(semantic.split("_")[1]);
var uvKind = BABYLON.VertexBuffer.UVKind + (channel === 0 ? "" : (channel + 1));
var uvs = new Float32Array(buffer.length);
uvs.set(buffer);
normalizeUVs(uvs);
tempVertexData.set(uvs, uvKind);
}
else if (semantic === "JOINT") {
tempVertexData.matricesIndices = new Float32Array(buffer.length);
tempVertexData.matricesIndices.set(buffer);
}
else if (semantic === "WEIGHT") {
tempVertexData.matricesWeights = new Float32Array(buffer.length);
tempVertexData.matricesWeights.set(buffer);
}
else if (semantic === "COLOR") {
tempVertexData.colors = new Float32Array(buffer.length);
tempVertexData.colors.set(buffer);
}
}
// Indices
accessor = gltfRuntime.accessors[primitive.indices];
if (accessor) {
buffer = GLTF1.GLTFUtils.GetBufferFromAccessor(gltfRuntime, accessor);
tempVertexData.indices = new Int32Array(buffer.length);
tempVertexData.indices.set(buffer);
indexCounts.push(tempVertexData.indices.length);
}
else {
// Set indices on the fly
var indices = [];
for (var j = 0; j < tempVertexData.positions.length / 3; j++) {
indices.push(j);
}
tempVertexData.indices = new Int32Array(indices);
indexCounts.push(tempVertexData.indices.length);
}
if (!vertexData) {
vertexData = tempVertexData;
}
else {
vertexData.merge(tempVertexData);
}
// Sub material
var material_1 = gltfRuntime.scene.getMaterialByID(primitive.material);
subMaterials.push(material_1 === null ? GLTF1.GLTFUtils.GetDefaultMaterial(gltfRuntime.scene) : material_1);
// Update vertices start and index start
verticesStarts.push(verticesStarts.length === 0 ? 0 : verticesStarts[verticesStarts.length - 1] + verticesCounts[verticesCounts.length - 2]);
indexStarts.push(indexStarts.length === 0 ? 0 : indexStarts[indexStarts.length - 1] + indexCounts[indexCounts.length - 2]);
}
}
var material;
if (subMaterials.length > 1) {
material = new BABYLON.MultiMaterial("multimat" + id, gltfRuntime.scene);
material.subMaterials = subMaterials;
}
else {
material = new BABYLON.StandardMaterial("multimat" + id, gltfRuntime.scene);
}
if (subMaterials.length === 1) {
material = subMaterials[0];
}
if (!newMesh.material) {
newMesh.material = material;
}
// Apply geometry
new BABYLON.Geometry(id, gltfRuntime.scene, vertexData, false, newMesh);
newMesh.computeWorldMatrix(true);
// Apply submeshes
newMesh.subMeshes = [];
var index = 0;
for (var meshIndex = 0; meshIndex < meshes.length; meshIndex++) {
var meshID = meshes[meshIndex];
var mesh = gltfRuntime.meshes[meshID];
if (!mesh) {
continue;
}
for (var i = 0; i < mesh.primitives.length; i++) {
if (mesh.primitives[i].mode !== 4) {
//continue;
}
BABYLON.SubMesh.AddToMesh(index, verticesStarts[index], verticesCounts[index], indexStarts[index], indexCounts[index], newMesh, newMesh, true);
index++;
}
}
// Finish
return newMesh;
};
/**
* Configure node transformation from position, rotation and scaling
*/
var configureNode = function (newNode, position, rotation, scaling) {
if (newNode.position) {
newNode.position = position;
}
if (newNode.rotationQuaternion || newNode.rotation) {
newNode.rotationQuaternion = rotation;
}
if (newNode.scaling) {
newNode.scaling = scaling;
}
};
/**
* Configures node from transformation matrix
*/
var configureNodeFromMatrix = function (newNode, node, parent) {
if (node.matrix) {
var position = new BABYLON.Vector3(0, 0, 0);
var rotation = new BABYLON.Quaternion();
var scaling = new BABYLON.Vector3(0, 0, 0);
var mat = BABYLON.Matrix.FromArray(node.matrix);
mat.decompose(scaling, rotation, position);
configureNode(newNode, position, rotation, scaling);
}
else if (node.translation && node.rotation && node.scale) {
configureNode(newNode, BABYLON.Vector3.FromArray(node.translation), BABYLON.Quaternion.FromArray(node.rotation), BABYLON.Vector3.FromArray(node.scale));
}
newNode.computeWorldMatrix(true);
};
/**
* Imports a node
*/
var importNode = function (gltfRuntime, node, id, parent) {
var lastNode = null;
if (gltfRuntime.importOnlyMeshes && (node.skin || node.meshes)) {
if (gltfRuntime.importMeshesNames && gltfRuntime.importMeshesNames.length > 0 && gltfRuntime.importMeshesNames.indexOf(node.name || "") === -1) {
return null;
}
}
// Meshes
if (node.skin) {
if (node.meshes) {
var skin = gltfRuntime.skins[node.skin];
var newMesh = importMesh(gltfRuntime, node, node.meshes, id, node.babylonNode);
newMesh.skeleton = gltfRuntime.scene.getLastSkeletonByID(node.skin);
if (newMesh.skeleton === null) {
newMesh.skeleton = importSkeleton(gltfRuntime, skin, newMesh, skin.babylonSkeleton, node.skin);
if (!skin.babylonSkeleton) {
skin.babylonSkeleton = newMesh.skeleton;
}
}
lastNode = newMesh;
}
}
else if (node.meshes) {
/**
* Improve meshes property
*/
var newMesh = importMesh(gltfRuntime, node, node.mesh ? [node.mesh] : node.meshes, id, node.babylonNode);
lastNode = newMesh;
}
else if (node.light && !node.babylonNode && !gltfRuntime.importOnlyMeshes) {
var light = gltfRuntime.lights[node.light];
if (light) {
if (light.type === "ambient") {
var ambienLight = light[light.type];
var hemiLight = new BABYLON.HemisphericLight(node.light, BABYLON.Vector3.Zero(), gltfRuntime.scene);
hemiLight.name = node.name || "";
if (ambienLight.color) {
hemiLight.diffuse = BABYLON.Color3.FromArray(ambienLight.color);
}
lastNode = hemiLight;
}
else if (light.type === "directional") {
var directionalLight = light[light.type];
var dirLight = new BABYLON.DirectionalLight(node.light, BABYLON.Vector3.Zero(), gltfRuntime.scene);
dirLight.name = node.name || "";
if (directionalLight.color) {
dirLight.diffuse = BABYLON.Color3.FromArray(directionalLight.color);
}
lastNode = dirLight;
}
else if (light.type === "point") {
var pointLight = light[light.type];
var ptLight = new BABYLON.PointLight(node.light, BABYLON.Vector3.Zero(), gltfRuntime.scene);
ptLight.name = node.name || "";
if (pointLight.color) {
ptLight.diffuse = BABYLON.Color3.FromArray(pointLight.color);
}
lastNode = ptLight;
}
else if (light.type === "spot") {
var spotLight = light[light.type];
var spLight = new BABYLON.SpotLight(node.light, BABYLON.Vector3.Zero(), BABYLON.Vector3.Zero(), 0, 0, gltfRuntime.scene);
spLight.name = node.name || "";
if (spotLight.color) {
spLight.diffuse = BABYLON.Color3.FromArray(spotLight.color);
}
if (spotLight.fallOfAngle) {
spLight.angle = spotLight.fallOfAngle;
}
if (spotLight.fallOffExponent) {
spLight.exponent = spotLight.fallOffExponent;
}
lastNode = spLight;
}
}
}
else if (node.camera && !node.babylonNode && !gltfRuntime.importOnlyMeshes) {
var camera = gltfRuntime.cameras[node.camera];
if (camera) {
if (camera.type === "orthographic") {
var orthoCamera = new BABYLON.FreeCamera(node.camera, BABYLON.Vector3.Zero(), gltfRuntime.scene);
orthoCamera.name = node.name || "";
orthoCamera.mode = BABYLON.Camera.ORTHOGRAPHIC_CAMERA;
orthoCamera.attachControl(gltfRuntime.scene.getEngine().getRenderingCanvas());
lastNode = orthoCamera;
}
else if (camera.type === "perspective") {
var perspectiveCamera = camera[camera.type];
var persCamera = new BABYLON.FreeCamera(node.camera, BABYLON.Vector3.Zero(), gltfRuntime.scene);
persCamera.name = node.name || "";
persCamera.attachControl(gltfRuntime.scene.getEngine().getRenderingCanvas());
if (!perspectiveCamera.aspectRatio) {
perspectiveCamera.aspectRatio = gltfRuntime.scene.getEngine().getRenderWidth() / gltfRuntime.scene.getEngine().getRenderHeight();
}
if (perspectiveCamera.znear && perspectiveCamera.zfar) {
persCamera.maxZ = perspectiveCamera.zfar;
persCamera.minZ = perspectiveCamera.znear;
}
lastNode = persCamera;
}
}
}
// Empty node
if (!node.jointName) {
if (node.babylonNode) {
return node.babylonNode;
}
else if (lastNode === null) {
var dummy = new BABYLON.Mesh(node.name || "", gltfRuntime.scene);
node.babylonNode = dummy;
lastNode = dummy;
}
}
if (lastNode !== null) {
if (node.matrix && lastNode instanceof BABYLON.Mesh) {
configureNodeFromMatrix(lastNode, node, parent);
}
else {
var translation = node.translation || [0, 0, 0];
var rotation = node.rotation || [0, 0, 0, 1];
var scale = node.scale || [1, 1, 1];
configureNode(lastNode, BABYLON.Vector3.FromArray(translation), BABYLON.Quaternion.FromArray(rotation), BABYLON.Vector3.FromArray(scale));
}
lastNode.updateCache(true);
node.babylonNode = lastNode;
}
return lastNode;
};
/**
* Traverses nodes and creates them
*/
var traverseNodes = function (gltfRuntime, id, parent, meshIncluded) {
if (meshIncluded === void 0) { meshIncluded = false; }
var node = gltfRuntime.nodes[id];
var newNode = null;
if (gltfRuntime.importOnlyMeshes && !meshIncluded && gltfRuntime.importMeshesNames) {
if (gltfRuntime.importMeshesNames.indexOf(node.name || "") !== -1 || gltfRuntime.importMeshesNames.length === 0) {
meshIncluded = true;
}
else {
meshIncluded = false;
}
}
else {
meshIncluded = true;
}
if (!node.jointName && meshIncluded) {
newNode = importNode(gltfRuntime, node, id, parent);
if (newNode !== null) {
newNode.id = id;
newNode.parent = parent;
}
}
if (node.children) {
for (var i = 0; i < node.children.length; i++) {
traverseNodes(gltfRuntime, node.children[i], newNode, meshIncluded);
}
}
};
/**
* do stuff after buffers, shaders are loaded (e.g. hook up materials, load animations, etc.)
*/
var postLoad = function (gltfRuntime) {
// Nodes
var currentScene = gltfRuntime.currentScene;
if (currentScene) {
for (var i = 0; i < currentScene.nodes.length; i++) {
traverseNodes(gltfRuntime, currentScene.nodes[i], null);
}
}
else {
for (var thing in gltfRuntime.scenes) {
currentScene = gltfRuntime.scenes[thing];
for (var i = 0; i < currentScene.nodes.length; i++) {
traverseNodes(gltfRuntime, currentScene.nodes[i], null);
}
}
}
// Set animations
loadAnimations(gltfRuntime);
for (var i = 0; i < gltfRuntime.scene.skeletons.length; i++) {
var skeleton = gltfRuntime.scene.skeletons[i];
gltfRuntime.scene.beginAnimation(skeleton, 0, Number.MAX_VALUE, true, 1.0);
}
};
/**
* onBind shaderrs callback to set uniforms and matrices
*/
var onBindShaderMaterial = function (mesh, gltfRuntime, unTreatedUniforms, shaderMaterial, technique, material, onSuccess) {
var materialValues = material.values || technique.parameters;
for (var unif in unTreatedUniforms) {
var uniform = unTreatedUniforms[unif];
var type = uniform.type;
if (type === GLTF1.EParameterType.FLOAT_MAT2 || type === GLTF1.EParameterType.FLOAT_MAT3 || type === GLTF1.EParameterType.FLOAT_MAT4) {
if (uniform.semantic && !uniform.source && !uniform.node) {
GLTF1.GLTFUtils.SetMatrix(gltfRuntime.scene, mesh, uniform, unif, shaderMaterial.getEffect());
}
else if (uniform.semantic && (uniform.source || uniform.node)) {
var source = gltfRuntime.scene.getNodeByName(uniform.source || uniform.node || "");
if (source === null) {
source = gltfRuntime.scene.getNodeByID(uniform.source || uniform.node || "");
}
if (source === null) {
continue;
}
GLTF1.GLTFUtils.SetMatrix(gltfRuntime.scene, source, uniform, unif, shaderMaterial.getEffect());
}
}
else {
var value = materialValues[technique.uniforms[unif]];
if (!value) {
continue;
}
if (type === GLTF1.EParameterType.SAMPLER_2D) {
var texture = gltfRuntime.textures[material.values ? value : uniform.value].babylonTexture;
if (texture === null || texture === undefined) {
continue;
}
shaderMaterial.getEffect().setTexture(unif, texture);
}
else {
GLTF1.GLTFUtils.SetUniform((shaderMaterial.getEffect()), unif, value, type);
}
}
}
onSuccess(shaderMaterial);
};
/**
* Prepare uniforms to send the only one time
* Loads the appropriate textures
*/
var prepareShaderMaterialUniforms = function (gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms) {
var materialValues = material.values || technique.parameters;
var techniqueUniforms = technique.uniforms;
/**
* Prepare values here (not matrices)
*/
for (var unif in unTreatedUniforms) {
var uniform = unTreatedUniforms[unif];
var type = uniform.type;
var value = materialValues[techniqueUniforms[unif]];
if (value === undefined) {
// In case the value is the same for all materials
value = uniform.value;
}
if (!value) {
continue;
}
var onLoadTexture = function (uniformName) {
return function (texture) {
if (uniform.value && uniformName) {
// Static uniform
shaderMaterial.setTexture(uniformName, texture);
delete unTreatedUniforms[uniformName];
}
};
};
// Texture (sampler2D)
if (type === GLTF1.EParameterType.SAMPLER_2D) {
GLTF1.GLTFLoaderExtension.LoadTextureAsync(gltfRuntime, material.values ? value : uniform.value, onLoadTexture(unif), function () { return onLoadTexture(null); });
}
else {
if (uniform.value && GLTF1.GLTFUtils.SetUniform(shaderMaterial, unif, material.values ? value : uniform.value, type)) {
// Static uniform
delete unTreatedUniforms[unif];
}
}
}
};
/**
* Shader compilation failed
*/
var onShaderCompileError = function (program, shaderMaterial, onError) {
return function (effect, error) {
shaderMaterial.dispose(true);
onError("Cannot compile program named " + program.name + ". Error: " + error + ". Default material will be applied");
};
};
/**
* Shader compilation success
*/
var onShaderCompileSuccess = function (gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms, onSuccess) {
return function (_) {
prepareShaderMaterialUniforms(gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms);
shaderMaterial.onBind = function (mesh) {
onBindShaderMaterial(mesh, gltfRuntime, unTreatedUniforms, shaderMaterial, technique, material, onSuccess);
};
};
};
/**
* Returns the appropriate uniform if already handled by babylon
*/
var parseShaderUniforms = function (tokenizer, technique, unTreatedUniforms) {
for (var unif in technique.uniforms) {
var uniform = technique.uniforms[unif];
var uniformParameter = technique.parameters[uniform];
if (tokenizer.currentIdentifier === unif) {
if (uniformParameter.semantic && !uniformParameter.source && !uniformParameter.node) {
var transformIndex = glTFTransforms.indexOf(uniformParameter.semantic);
if (transformIndex !== -1) {
delete unTreatedUniforms[unif];
return babylonTransforms[transformIndex];
}
}
}
}
return tokenizer.currentIdentifier;
};
/**
* All shaders loaded. Create materials one by one
*/
var importMaterials = function (gltfRuntime) {
// Create materials
for (var mat in gltfRuntime.materials) {
GLTF1.GLTFLoaderExtension.LoadMaterialAsync(gltfRuntime, mat, function (material) { }, function () { });
}
};
/**
* Implementation of the base glTF spec
*/
var GLTFLoaderBase = /** @class */ (function () {
function GLTFLoaderBase() {
}
GLTFLoaderBase.CreateRuntime = function (parsedData, scene, rootUrl) {
var gltfRuntime = {
extensions: {},
accessors: {},
buffers: {},
bufferViews: {},
meshes: {},
lights: {},
cameras: {},
nodes: {},
images: {},
textures: {},
shaders: {},
programs: {},
samplers: {},
techniques: {},
materials: {},
animations: {},
skins: {},
extensionsUsed: [],
scenes: {},
buffersCount: 0,
shaderscount: 0,
scene: scene,
rootUrl: rootUrl,
loadedBufferCount: 0,
loadedBufferViews: {},
loadedShaderCount: 0,
importOnlyMeshes: false,
dummyNodes: []
};
// Parse
if (parsedData.extensions) {
parseObject(parsedData.extensions, "extensions", gltfRuntime);
}
if (parsedData.extensionsUsed) {
parseObject(parsedData.extensionsUsed, "extensionsUsed", gltfRuntime);
}
if (parsedData.buffers) {
parseBuffers(parsedData.buffers, gltfRuntime);
}
if (parsedData.bufferViews) {
parseObject(parsedData.bufferViews, "bufferViews", gltfRuntime);
}
if (parsedData.accessors) {
parseObject(parsedData.accessors, "accessors", gltfRuntime);
}
if (parsedData.meshes) {
parseObject(parsedData.meshes, "meshes", gltfRuntime);
}
if (parsedData.lights) {
parseObject(parsedData.lights, "lights", gltfRuntime);
}
if (parsedData.cameras) {
parseObject(parsedData.cameras, "cameras", gltfRuntime);
}
if (parsedData.nodes) {
parseObject(parsedData.nodes, "nodes", gltfRuntime);
}
if (parsedData.images) {
parseObject(parsedData.images, "images", gltfRuntime);
}
if (parsedData.textures) {
parseObject(parsedData.textures, "textures", gltfRuntime);
}
if (parsedData.shaders) {
parseShaders(parsedData.shaders, gltfRuntime);
}
if (parsedData.programs) {
parseObject(parsedData.programs, "programs", gltfRuntime);
}
if (parsedData.samplers) {
parseObject(parsedData.samplers, "samplers", gltfRuntime);
}
if (parsedData.techniques) {
parseObject(parsedData.techniques, "techniques", gltfRuntime);
}
if (parsedData.materials) {
parseObject(parsedData.materials, "materials", gltfRuntime);
}
if (parsedData.animations) {
parseObject(parsedData.animations, "animations", gltfRuntime);
}
if (parsedData.skins) {
parseObject(parsedData.skins, "skins", gltfRuntime);
}
if (parsedData.scenes) {
gltfRuntime.scenes = parsedData.scenes;
}
if (parsedData.scene && parsedData.scenes) {
gltfRuntime.currentScene = parsedData.scenes[parsedData.scene];
}
return gltfRuntime;
};
GLTFLoaderBase.LoadBufferAsync = function (gltfRuntime, id, onSuccess, onError, onProgress) {
var buffer = gltfRuntime.buffers[id];
if (BABYLON.Tools.IsBase64(buffer.uri)) {
setTimeout(function () { return onSuccess(new Uint8Array(BABYLON.Tools.DecodeBase64(buffer.uri))); });
}
else {
BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + buffer.uri, function (data) { return onSuccess(new Uint8Array(data)); }, onProgress, undefined, true, function (request) {
if (request) {
onError(request.status + " " + request.statusText);
}
});
}
};
GLTFLoaderBase.LoadTextureBufferAsync = function (gltfRuntime, id, onSuccess, onError) {
var texture = gltfRuntime.textures[id];
if (!texture || !texture.source) {
onError("");
return;
}
if (texture.babylonTexture) {
onSuccess(null);
return;
}
var source = gltfRuntime.images[texture.source];
if (BABYLON.Tools.IsBase64(source.uri)) {
setTimeout(function () { return onSuccess(new Uint8Array(BABYLON.Tools.DecodeBase64(source.uri))); });
}
else {
BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + source.uri, function (data) { return onSuccess(new Uint8Array(data)); }, undefined, undefined, true, function (request) {
if (request) {
onError(request.status + " " + request.statusText);
}
});
}
};
GLTFLoaderBase.CreateTextureAsync = function (gltfRuntime, id, buffer, onSuccess, onError) {
var texture = gltfRuntime.textures[id];
if (texture.babylonTexture) {
onSuccess(texture.babylonTexture);
return;
}
var sampler = gltfRuntime.samplers[texture.sampler];
var createMipMaps = (sampler.minFilter === GLTF1.ETextureFilterType.NEAREST_MIPMAP_NEAREST) ||
(sampler.minFilter === GLTF1.ETextureFilterType.NEAREST_MIPMAP_LINEAR) ||
(sampler.minFilter === GLTF1.ETextureFilterType.LINEAR_MIPMAP_NEAREST) ||
(sampler.minFilter === GLTF1.ETextureFilterType.LINEAR_MIPMAP_LINEAR);
var samplingMode = BABYLON.Texture.BILINEAR_SAMPLINGMODE;
var blob = new Blob([buffer]);
var blobURL = URL.createObjectURL(blob);
var revokeBlobURL = function () { return URL.revokeObjectURL(blobURL); };
var newTexture = new BABYLON.Texture(blobURL, gltfRuntime.scene, !createMipMaps, true, samplingMode, revokeBlobURL, revokeBlobURL);
if (sampler.wrapS !== undefined) {
newTexture.wrapU = GLTF1.GLTFUtils.GetWrapMode(sampler.wrapS);
}
if (sampler.wrapT !== undefined) {
newTexture.wrapV = GLTF1.GLTFUtils.GetWrapMode(sampler.wrapT);
}
newTexture.name = id;
texture.babylonTexture = newTexture;
onSuccess(newTexture);
};
GLTFLoaderBase.LoadShaderStringAsync = function (gltfRuntime, id, onSuccess, onError) {
var shader = gltfRuntime.shaders[id];
if (BABYLON.Tools.IsBase64(shader.uri)) {
var shaderString = atob(shader.uri.split(",")[1]);
onSuccess(shaderString);
}
else {
BABYLON.Tools.LoadFile(gltfRuntime.rootUrl + shader.uri, onSuccess, undefined, undefined, false, function (request) {
if (request) {
onError(request.status + " " + request.statusText);
}
});
}
};
GLTFLoaderBase.LoadMaterialAsync = function (gltfRuntime, id, onSuccess, onError) {
var material = gltfRuntime.materials[id];
if (!material.technique) {
if (onError) {
onError("No technique found.");
}
return;
}
var technique = gltfRuntime.techniques[material.technique];
if (!technique) {
var defaultMaterial = new BABYLON.StandardMaterial(id, gltfRuntime.scene);
defaultMaterial.diffuseColor = new BABYLON.Color3(0.5, 0.5, 0.5);
defaultMaterial.sideOrientation = BABYLON.Material.CounterClockWiseSideOrientation;
onSuccess(defaultMaterial);
return;
}
var program = gltfRuntime.programs[technique.program];
var states = technique.states;
var vertexShader = BABYLON.Effect.ShadersStore[program.vertexShader + "VertexShader"];
var pixelShader = BABYLON.Effect.ShadersStore[program.fragmentShader + "PixelShader"];
var newVertexShader = "";
var newPixelShader = "";
var vertexTokenizer = new Tokenizer(vertexShader);
var pixelTokenizer = new Tokenizer(pixelShader);
var unTreatedUniforms = {};
var uniforms = [];
var attributes = [];
var samplers = [];
// Fill uniform, sampler2D and attributes
for (var unif in technique.uniforms) {
var uniform = technique.uniforms[unif];
var uniformParameter = technique.parameters[uniform];
unTreatedUniforms[unif] = uniformParameter;
if (uniformParameter.semantic && !uniformParameter.node && !uniformParameter.source) {
var transformIndex = glTFTransforms.indexOf(uniformParameter.semantic);
if (transformIndex !== -1) {
uniforms.push(babylonTransforms[transformIndex]);
delete unTreatedUniforms[unif];
}
else {
uniforms.push(unif);
}
}
else if (uniformParameter.type === GLTF1.EParameterType.SAMPLER_2D) {
samplers.push(unif);
}
else {
uniforms.push(unif);
}
}
for (var attr in technique.attributes) {
var attribute = technique.attributes[attr];
var attributeParameter = technique.parameters[attribute];
if (attributeParameter.semantic) {
attributes.push(getAttribute(attributeParameter));
}
}
// Configure vertex shader
while (!vertexTokenizer.isEnd() && vertexTokenizer.getNextToken()) {
var tokenType = vertexTokenizer.currentToken;
if (tokenType !== ETokenType.IDENTIFIER) {
newVertexShader += vertexTokenizer.currentString;
continue;
}
var foundAttribute = false;
for (var attr in technique.attributes) {
var attribute = technique.attributes[attr];
var attributeParameter = technique.parameters[attribute];
if (vertexTokenizer.currentIdentifier === attr && attributeParameter.semantic) {
newVertexShader += getAttribute(attributeParameter);
foundAttribute = true;
break;
}
}
if (foundAttribute) {
continue;
}
newVertexShader += parseShaderUniforms(vertexTokenizer, technique, unTreatedUniforms);
}
// Configure pixel shader
while (!pixelTokenizer.isEnd() && pixelTokenizer.getNextToken()) {
var tokenType = pixelTokenizer.currentToken;
if (tokenType !== ETokenType.IDENTIFIER) {
newPixelShader += pixelTokenizer.currentString;
continue;
}
newPixelShader += parseShaderUniforms(pixelTokenizer, technique, unTreatedUniforms);
}
// Create shader material
var shaderPath = {
vertex: program.vertexShader + id,
fragment: program.fragmentShader + id
};
var options = {
attributes: attributes,
uniforms: uniforms,
samplers: samplers,
needAlphaBlending: states && states.enable && states.enable.indexOf(3042) !== -1
};
BABYLON.Effect.ShadersStore[program.vertexShader + id + "VertexShader"] = newVertexShader;
BABYLON.Effect.ShadersStore[program.fragmentShader + id + "PixelShader"] = newPixelShader;
var shaderMaterial = new BABYLON.ShaderMaterial(id, gltfRuntime.scene, shaderPath, options);
shaderMaterial.onError = onShaderCompileError(program, shaderMaterial, onError);
shaderMaterial.onCompiled = onShaderCompileSuccess(gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms, onSuccess);
shaderMaterial.sideOrientation = BABYLON.Material.CounterClockWiseSideOrientation;
if (states && states.functions) {
var functions = states.functions;
if (functions.cullFace && functions.cullFace[0] !== GLTF1.ECullingType.BACK) {
shaderMaterial.backFaceCulling = false;
}
var blendFunc = functions.blendFuncSeparate;
if (blendFunc) {
if (blendFunc[0] === GLTF1.EBlendingFunction.SRC_ALPHA && blendFunc[1] === GLTF1.EBlendingFunction.ONE_MINUS_SRC_ALPHA && blendFunc[2] === GLTF1.EBlendingFunction.ONE && blendFunc[3] === GLTF1.EBlendingFunction.ONE) {
shaderMaterial.alphaMode = BABYLON.Engine.ALPHA_COMBINE;
}
else if (blendFunc[0] === GLTF1.EBlendingFunction.ONE && blendFunc[1] === GLTF1.EBlendingFunction.ONE && blendFunc[2] === GLTF1.EBlendingFunction.ZERO && blendFunc[3] === GLTF1.EBlendingFunction.ONE) {
shaderMaterial.alphaMode = BABYLON.Engine.ALPHA_ONEONE;
}
else if (blendFunc[0] === GLTF1.EBlendingFunction.SRC_ALPHA && blendFunc[1] === GLTF1.EBlendingFunction.ONE && blendFunc[2] === GLTF1.EBlendingFunction.ZERO && blendFunc[3] === GLTF1.EBlendingFunction.ONE) {
shaderMaterial.alphaMode = BABYLON.Engine.ALPHA_ADD;
}
else if (blendFunc[0] === GLTF1.EBlendingFunction.ZERO && blendFunc[1] === GLTF1.EBlendingFunction.ONE_MINUS_SRC_COLOR && blendFunc[2] === GLTF1.EBlendingFunction.ONE && blendFunc[3] === GLTF1.EBlendingFunction.ONE) {
shaderMaterial.alphaMode = BABYLON.Engine.ALPHA_SUBTRACT;
}
else if (blendFunc[0] === GLTF1.EBlendingFunction.DST_COLOR && blendFunc[1] === GLTF1.EBlendingFunction.ZERO && blendFunc[2] === GLTF1.EBlendingFunction.ONE && blendFunc[3] === GLTF1.EBlendingFunction.ONE) {
shaderMaterial.alphaMode = BABYLON.Engine.ALPHA_MULTIPLY;
}
else if (blendFunc[0] === GLTF1.EBlendingFunction.SRC_ALPHA && blendFunc[1] === GLTF1.EBlendingFunction.ONE_MINUS_SRC_COLOR && blendFunc[2] === GLTF1.EBlendingFunction.ONE && blendFunc[3] === GLTF1.EBlendingFunction.ONE) {
shaderMaterial.alphaMode = BABYLON.Engine.ALPHA_MAXIMIZED;
}
}
}
};
return GLTFLoaderBase;
}());
GLTF1.GLTFLoaderBase = GLTFLoaderBase;
/**
* glTF V1 Loader
*/
var GLTFLoader = /** @class */ (function () {
function GLTFLoader() {
// #region Stubs for IGLTFLoader interface
this.coordinateSystemMode = BABYLON.GLTFLoaderCoordinateSystemMode.AUTO;
this.animationStartMode = BABYLON.GLTFLoaderAnimationStartMode.FIRST;
this.compileMaterials = false;
this.useClipPlane = false;
this.compileShadowGenerators = false;
this.onDisposeObservable = new BABYLON.Observable();
this.onMeshLoadedObservable = new BABYLON.Observable();
this.onTextureLoadedObservable = new BABYLON.Observable();
this.onMaterialLoadedObservable = new BABYLON.Observable();
this.onAnimationGroupLoadedObservable = new BABYLON.Observable();
this.onCompleteObservable = new BABYLON.Observable();
this.onExtensionLoadedObservable = new BABYLON.Observable();
this.state = null;
}
GLTFLoader.RegisterExtension = function (extension) {
if (GLTFLoader.Extensions[extension.name]) {
BABYLON.Tools.Error("Tool with the same name \"" + extension.name + "\" already exists");
return;
}
GLTFLoader.Extensions[extension.name] = extension;
};
GLTFLoader.prototype.dispose = function () { };
// #endregion
GLTFLoader.prototype._importMeshAsync = function (meshesNames, scene, data, rootUrl, onSuccess, onProgress, onError) {
var _this = this;
scene.useRightHandedSystem = true;
GLTF1.GLTFLoaderExtension.LoadRuntimeAsync(scene, data, rootUrl, function (gltfRuntime) {
gltfRuntime.importOnlyMeshes = true;
if (meshesNames === "") {
gltfRuntime.importMeshesNames = [];
}
else if (typeof meshesNames === "string") {
gltfRuntime.importMeshesNames = [meshesNames];
}
else if (meshesNames && !(meshesNames instanceof Array)) {
gltfRuntime.importMeshesNames = [meshesNames];
}
else {
gltfRuntime.importMeshesNames = [];
BABYLON.Tools.Warn("Argument meshesNames must be of type string or string[]");
}
// Create nodes
_this._createNodes(gltfRuntime);
var meshes = new Array();
var skeletons = new Array();
// Fill arrays of meshes and skeletons
for (var nde in gltfRuntime.nodes) {
var node = gltfRuntime.nodes[nde];
if (node.babylonNode instanceof BABYLON.AbstractMesh) {
meshes.push(node.babylonNode);
}
}
for (var skl in gltfRuntime.skins) {
var skin = gltfRuntime.skins[skl];
if (skin.babylonSkeleton instanceof BABYLON.Skeleton) {
skeletons.push(skin.babylonSkeleton);
}
}
// Load buffers, shaders, materials, etc.
_this._loadBuffersAsync(gltfRuntime, function () {
_this._loadShadersAsync(gltfRuntime, function () {
importMaterials(gltfRuntime);
postLoad(gltfRuntime);
if (!BABYLON.GLTFFileLoader.IncrementalLoading && onSuccess) {
onSuccess(meshes, [], skeletons);
}
});
}, onProgress);
if (BABYLON.GLTFFileLoader.IncrementalLoading && onSuccess) {
onSuccess(meshes, [], skeletons);
}
}, onError);
return true;
};
GLTFLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress) {
var _this = this;
return new Promise(function (resolve, reject) {
_this._importMeshAsync(meshesNames, scene, data, rootUrl, function (meshes, particleSystems, skeletons) {
resolve({
meshes: meshes,
particleSystems: particleSystems,
skeletons: skeletons
});
}, onProgress, function (message) {
reject(new Error(message));
});
});
};
GLTFLoader.prototype._loadAsync = function (scene, data, rootUrl, onSuccess, onProgress, onError) {
var _this = this;
scene.useRightHandedSystem = true;
GLTF1.GLTFLoaderExtension.LoadRuntimeAsync(scene, data, rootUrl, function (gltfRuntime) {
// Load runtime extensios
GLTF1.GLTFLoaderExtension.LoadRuntimeExtensionsAsync(gltfRuntime, function () {
// Create nodes
_this._createNodes(gltfRuntime);
// Load buffers, shaders, materials, etc.
_this._loadBuffersAsync(gltfRuntime, function () {
_this._loadShadersAsync(gltfRuntime, function () {
importMaterials(gltfRuntime);
postLoad(gltfRuntime);
if (!BABYLON.GLTFFileLoader.IncrementalLoading) {
onSuccess();
}
});
});
if (BABYLON.GLTFFileLoader.IncrementalLoading) {
onSuccess();
}
}, onError);
}, onError);
};
GLTFLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress) {
var _this = this;
return new Promise(function (resolve, reject) {
_this._loadAsync(scene, data, rootUrl, function () {
resolve();
}, onProgress, function (message) {
reject(new Error(message));
});
});
};
GLTFLoader.prototype._loadShadersAsync = function (gltfRuntime, onload) {
var hasShaders = false;
var processShader = function (sha, shader) {
GLTF1.GLTFLoaderExtension.LoadShaderStringAsync(gltfRuntime, sha, function (shaderString) {
gltfRuntime.loadedShaderCount++;
if (shaderString) {
BABYLON.Effect.ShadersStore[sha + (shader.type === GLTF1.EShaderType.VERTEX ? "VertexShader" : "PixelShader")] = shaderString;
}
if (gltfRuntime.loadedShaderCount === gltfRuntime.shaderscount) {
onload();
}
}, function () {
BABYLON.Tools.Error("Error when loading shader program named " + sha + " located at " + shader.uri);
});
};
for (var sha in gltfRuntime.shaders) {
hasShaders = true;
var shader = gltfRuntime.shaders[sha];
if (shader) {
processShader.bind(this, sha, shader)();
}
else {
BABYLON.Tools.Error("No shader named: " + sha);
}
}
if (!hasShaders) {
onload();
}
};
;
GLTFLoader.prototype._loadBuffersAsync = function (gltfRuntime, onLoad, onProgress) {
var hasBuffers = false;
var processBuffer = function (buf, buffer) {
GLTF1.GLTFLoaderExtension.LoadBufferAsync(gltfRuntime, buf, function (bufferView) {
gltfRuntime.loadedBufferCount++;
if (bufferView) {
if (bufferView.byteLength != gltfRuntime.buffers[buf].byteLength) {
BABYLON.Tools.Error("Buffer named " + buf + " is length " + bufferView.byteLength + ". Expected: " + buffer.byteLength); // Improve error message
}
gltfRuntime.loadedBufferViews[buf] = bufferView;
}
if (gltfRuntime.loadedBufferCount === gltfRuntime.buffersCount) {
onLoad();
}
}, function () {
BABYLON.Tools.Error("Error when loading buffer named " + buf + " located at " + buffer.uri);
});
};
for (var buf in gltfRuntime.buffers) {
hasBuffers = true;
var buffer = gltfRuntime.buffers[buf];
if (buffer) {
processBuffer.bind(this, buf, buffer)();
}
else {
BABYLON.Tools.Error("No buffer named: " + buf);
}
}
if (!hasBuffers) {
onLoad();
}
};
GLTFLoader.prototype._createNodes = function (gltfRuntime) {
var currentScene = gltfRuntime.currentScene;
if (currentScene) {
// Only one scene even if multiple scenes are defined
for (var i = 0; i < currentScene.nodes.length; i++) {
traverseNodes(gltfRuntime, currentScene.nodes[i], null);
}
}
else {
// Load all scenes
for (var thing in gltfRuntime.scenes) {
currentScene = gltfRuntime.scenes[thing];
for (var i = 0; i < currentScene.nodes.length; i++) {
traverseNodes(gltfRuntime, currentScene.nodes[i], null);
}
}
}
};
GLTFLoader.Extensions = {};
return GLTFLoader;
}());
GLTF1.GLTFLoader = GLTFLoader;
;
BABYLON.GLTFFileLoader.CreateGLTFLoaderV1 = function () { return new GLTFLoader(); };
})(GLTF1 = BABYLON.GLTF1 || (BABYLON.GLTF1 = {}));
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.glTFLoader.js.map
///
var BABYLON;
(function (BABYLON) {
var GLTF1;
(function (GLTF1) {
/**
* Utils functions for GLTF
*/
var GLTFUtils = /** @class */ (function () {
function GLTFUtils() {
}
/**
* Sets the given "parameter" matrix
* @param scene: the {BABYLON.Scene} object
* @param source: the source node where to pick the matrix
* @param parameter: the GLTF technique parameter
* @param uniformName: the name of the shader's uniform
* @param shaderMaterial: the shader material
*/
GLTFUtils.SetMatrix = function (scene, source, parameter, uniformName, shaderMaterial) {
var mat = null;
if (parameter.semantic === "MODEL") {
mat = source.getWorldMatrix();
}
else if (parameter.semantic === "PROJECTION") {
mat = scene.getProjectionMatrix();
}
else if (parameter.semantic === "VIEW") {
mat = scene.getViewMatrix();
}
else if (parameter.semantic === "MODELVIEWINVERSETRANSPOSE") {
mat = BABYLON.Matrix.Transpose(source.getWorldMatrix().multiply(scene.getViewMatrix()).invert());
}
else if (parameter.semantic === "MODELVIEW") {
mat = source.getWorldMatrix().multiply(scene.getViewMatrix());
}
else if (parameter.semantic === "MODELVIEWPROJECTION") {
mat = source.getWorldMatrix().multiply(scene.getTransformMatrix());
}
else if (parameter.semantic === "MODELINVERSE") {
mat = source.getWorldMatrix().invert();
}
else if (parameter.semantic === "VIEWINVERSE") {
mat = scene.getViewMatrix().invert();
}
else if (parameter.semantic === "PROJECTIONINVERSE") {
mat = scene.getProjectionMatrix().invert();
}
else if (parameter.semantic === "MODELVIEWINVERSE") {
mat = source.getWorldMatrix().multiply(scene.getViewMatrix()).invert();
}
else if (parameter.semantic === "MODELVIEWPROJECTIONINVERSE") {
mat = source.getWorldMatrix().multiply(scene.getTransformMatrix()).invert();
}
else if (parameter.semantic === "MODELINVERSETRANSPOSE") {
mat = BABYLON.Matrix.Transpose(source.getWorldMatrix().invert());
}
else {
debugger;
}
if (mat) {
switch (parameter.type) {
case GLTF1.EParameterType.FLOAT_MAT2:
shaderMaterial.setMatrix2x2(uniformName, BABYLON.Matrix.GetAsMatrix2x2(mat));
break;
case GLTF1.EParameterType.FLOAT_MAT3:
shaderMaterial.setMatrix3x3(uniformName, BABYLON.Matrix.GetAsMatrix3x3(mat));
break;
case GLTF1.EParameterType.FLOAT_MAT4:
shaderMaterial.setMatrix(uniformName, mat);
break;
default: break;
}
}
};
/**
* Sets the given "parameter" matrix
* @param shaderMaterial: the shader material
* @param uniform: the name of the shader's uniform
* @param value: the value of the uniform
* @param type: the uniform's type (EParameterType FLOAT, VEC2, VEC3 or VEC4)
*/
GLTFUtils.SetUniform = function (shaderMaterial, uniform, value, type) {
switch (type) {
case GLTF1.EParameterType.FLOAT:
shaderMaterial.setFloat(uniform, value);
return true;
case GLTF1.EParameterType.FLOAT_VEC2:
shaderMaterial.setVector2(uniform, BABYLON.Vector2.FromArray(value));
return true;
case GLTF1.EParameterType.FLOAT_VEC3:
shaderMaterial.setVector3(uniform, BABYLON.Vector3.FromArray(value));
return true;
case GLTF1.EParameterType.FLOAT_VEC4:
shaderMaterial.setVector4(uniform, BABYLON.Vector4.FromArray(value));
return true;
default: return false;
}
};
/**
* Returns the wrap mode of the texture
* @param mode: the mode value
*/
GLTFUtils.GetWrapMode = function (mode) {
switch (mode) {
case GLTF1.ETextureWrapMode.CLAMP_TO_EDGE: return BABYLON.Texture.CLAMP_ADDRESSMODE;
case GLTF1.ETextureWrapMode.MIRRORED_REPEAT: return BABYLON.Texture.MIRROR_ADDRESSMODE;
case GLTF1.ETextureWrapMode.REPEAT: return BABYLON.Texture.WRAP_ADDRESSMODE;
default: return BABYLON.Texture.WRAP_ADDRESSMODE;
}
};
/**
* Returns the byte stride giving an accessor
* @param accessor: the GLTF accessor objet
*/
GLTFUtils.GetByteStrideFromType = function (accessor) {
// Needs this function since "byteStride" isn't requiered in glTF format
var type = accessor.type;
switch (type) {
case "VEC2": return 2;
case "VEC3": return 3;
case "VEC4": return 4;
case "MAT2": return 4;
case "MAT3": return 9;
case "MAT4": return 16;
default: return 1;
}
};
/**
* Returns the texture filter mode giving a mode value
* @param mode: the filter mode value
*/
GLTFUtils.GetTextureFilterMode = function (mode) {
switch (mode) {
case GLTF1.ETextureFilterType.LINEAR:
case GLTF1.ETextureFilterType.LINEAR_MIPMAP_NEAREST:
case GLTF1.ETextureFilterType.LINEAR_MIPMAP_LINEAR: return BABYLON.Texture.TRILINEAR_SAMPLINGMODE;
case GLTF1.ETextureFilterType.NEAREST:
case GLTF1.ETextureFilterType.NEAREST_MIPMAP_NEAREST: return BABYLON.Texture.NEAREST_SAMPLINGMODE;
default: return BABYLON.Texture.BILINEAR_SAMPLINGMODE;
}
};
GLTFUtils.GetBufferFromBufferView = function (gltfRuntime, bufferView, byteOffset, byteLength, componentType) {
var byteOffset = bufferView.byteOffset + byteOffset;
var loadedBufferView = gltfRuntime.loadedBufferViews[bufferView.buffer];
if (byteOffset + byteLength > loadedBufferView.byteLength) {
throw new Error("Buffer access is out of range");
}
var buffer = loadedBufferView.buffer;
byteOffset += loadedBufferView.byteOffset;
switch (componentType) {
case GLTF1.EComponentType.BYTE: return new Int8Array(buffer, byteOffset, byteLength);
case GLTF1.EComponentType.UNSIGNED_BYTE: return new Uint8Array(buffer, byteOffset, byteLength);
case GLTF1.EComponentType.SHORT: return new Int16Array(buffer, byteOffset, byteLength);
case GLTF1.EComponentType.UNSIGNED_SHORT: return new Uint16Array(buffer, byteOffset, byteLength);
default: return new Float32Array(buffer, byteOffset, byteLength);
}
};
/**
* Returns a buffer from its accessor
* @param gltfRuntime: the GLTF runtime
* @param accessor: the GLTF accessor
*/
GLTFUtils.GetBufferFromAccessor = function (gltfRuntime, accessor) {
var bufferView = gltfRuntime.bufferViews[accessor.bufferView];
var byteLength = accessor.count * GLTFUtils.GetByteStrideFromType(accessor);
return GLTFUtils.GetBufferFromBufferView(gltfRuntime, bufferView, accessor.byteOffset, byteLength, accessor.componentType);
};
/**
* Decodes a buffer view into a string
* @param view: the buffer view
*/
GLTFUtils.DecodeBufferToText = function (view) {
var result = "";
var length = view.byteLength;
for (var i = 0; i < length; ++i) {
result += String.fromCharCode(view[i]);
}
return result;
};
/**
* Returns the default material of gltf. Related to
* https://github.com/KhronosGroup/glTF/tree/master/specification/1.0#appendix-a-default-material
* @param scene: the Babylon.js scene
*/
GLTFUtils.GetDefaultMaterial = function (scene) {
if (!GLTFUtils._DefaultMaterial) {
BABYLON.Effect.ShadersStore["GLTFDefaultMaterialVertexShader"] = [
"precision highp float;",
"",
"uniform mat4 worldView;",
"uniform mat4 projection;",
"",
"attribute vec3 position;",
"",
"void main(void)",
"{",
" gl_Position = projection * worldView * vec4(position, 1.0);",
"}"
].join("\n");
BABYLON.Effect.ShadersStore["GLTFDefaultMaterialPixelShader"] = [
"precision highp float;",
"",
"uniform vec4 u_emission;",
"",
"void main(void)",
"{",
" gl_FragColor = u_emission;",
"}"
].join("\n");
var shaderPath = {
vertex: "GLTFDefaultMaterial",
fragment: "GLTFDefaultMaterial"
};
var options = {
attributes: ["position"],
uniforms: ["worldView", "projection", "u_emission"],
samplers: new Array(),
needAlphaBlending: false
};
GLTFUtils._DefaultMaterial = new BABYLON.ShaderMaterial("GLTFDefaultMaterial", scene, shaderPath, options);
GLTFUtils._DefaultMaterial.setColor4("u_emission", new BABYLON.Color4(0.5, 0.5, 0.5, 1.0));
}
return GLTFUtils._DefaultMaterial;
};
// The GLTF default material
GLTFUtils._DefaultMaterial = null;
return GLTFUtils;
}());
GLTF1.GLTFUtils = GLTFUtils;
})(GLTF1 = BABYLON.GLTF1 || (BABYLON.GLTF1 = {}));
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.glTFLoaderUtils.js.map
///
var BABYLON;
(function (BABYLON) {
var GLTF1;
(function (GLTF1) {
var GLTFLoaderExtension = /** @class */ (function () {
function GLTFLoaderExtension(name) {
this._name = name;
}
Object.defineProperty(GLTFLoaderExtension.prototype, "name", {
get: function () {
return this._name;
},
enumerable: true,
configurable: true
});
/**
* Defines an override for loading the runtime
* Return true to stop further extensions from loading the runtime
*/
GLTFLoaderExtension.prototype.loadRuntimeAsync = function (scene, data, rootUrl, onSuccess, onError) {
return false;
};
/**
* Defines an onverride for creating gltf runtime
* Return true to stop further extensions from creating the runtime
*/
GLTFLoaderExtension.prototype.loadRuntimeExtensionsAsync = function (gltfRuntime, onSuccess, onError) {
return false;
};
/**
* Defines an override for loading buffers
* Return true to stop further extensions from loading this buffer
*/
GLTFLoaderExtension.prototype.loadBufferAsync = function (gltfRuntime, id, onSuccess, onError, onProgress) {
return false;
};
/**
* Defines an override for loading texture buffers
* Return true to stop further extensions from loading this texture data
*/
GLTFLoaderExtension.prototype.loadTextureBufferAsync = function (gltfRuntime, id, onSuccess, onError) {
return false;
};
/**
* Defines an override for creating textures
* Return true to stop further extensions from loading this texture
*/
GLTFLoaderExtension.prototype.createTextureAsync = function (gltfRuntime, id, buffer, onSuccess, onError) {
return false;
};
/**
* Defines an override for loading shader strings
* Return true to stop further extensions from loading this shader data
*/
GLTFLoaderExtension.prototype.loadShaderStringAsync = function (gltfRuntime, id, onSuccess, onError) {
return false;
};
/**
* Defines an override for loading materials
* Return true to stop further extensions from loading this material
*/
GLTFLoaderExtension.prototype.loadMaterialAsync = function (gltfRuntime, id, onSuccess, onError) {
return false;
};
// ---------
// Utilities
// ---------
GLTFLoaderExtension.LoadRuntimeAsync = function (scene, data, rootUrl, onSuccess, onError) {
GLTFLoaderExtension.ApplyExtensions(function (loaderExtension) {
return loaderExtension.loadRuntimeAsync(scene, data, rootUrl, onSuccess, onError);
}, function () {
setTimeout(function () {
onSuccess(GLTF1.GLTFLoaderBase.CreateRuntime(data.json, scene, rootUrl));
});
});
};
GLTFLoaderExtension.LoadRuntimeExtensionsAsync = function (gltfRuntime, onSuccess, onError) {
GLTFLoaderExtension.ApplyExtensions(function (loaderExtension) {
return loaderExtension.loadRuntimeExtensionsAsync(gltfRuntime, onSuccess, onError);
}, function () {
setTimeout(function () {
onSuccess();
});
});
};
GLTFLoaderExtension.LoadBufferAsync = function (gltfRuntime, id, onSuccess, onError, onProgress) {
GLTFLoaderExtension.ApplyExtensions(function (loaderExtension) {
return loaderExtension.loadBufferAsync(gltfRuntime, id, onSuccess, onError, onProgress);
}, function () {
GLTF1.GLTFLoaderBase.LoadBufferAsync(gltfRuntime, id, onSuccess, onError, onProgress);
});
};
GLTFLoaderExtension.LoadTextureAsync = function (gltfRuntime, id, onSuccess, onError) {
GLTFLoaderExtension.LoadTextureBufferAsync(gltfRuntime, id, function (buffer) { return GLTFLoaderExtension.CreateTextureAsync(gltfRuntime, id, buffer, onSuccess, onError); }, onError);
};
GLTFLoaderExtension.LoadShaderStringAsync = function (gltfRuntime, id, onSuccess, onError) {
GLTFLoaderExtension.ApplyExtensions(function (loaderExtension) {
return loaderExtension.loadShaderStringAsync(gltfRuntime, id, onSuccess, onError);
}, function () {
GLTF1.GLTFLoaderBase.LoadShaderStringAsync(gltfRuntime, id, onSuccess, onError);
});
};
GLTFLoaderExtension.LoadMaterialAsync = function (gltfRuntime, id, onSuccess, onError) {
GLTFLoaderExtension.ApplyExtensions(function (loaderExtension) {
return loaderExtension.loadMaterialAsync(gltfRuntime, id, onSuccess, onError);
}, function () {
GLTF1.GLTFLoaderBase.LoadMaterialAsync(gltfRuntime, id, onSuccess, onError);
});
};
GLTFLoaderExtension.LoadTextureBufferAsync = function (gltfRuntime, id, onSuccess, onError) {
GLTFLoaderExtension.ApplyExtensions(function (loaderExtension) {
return loaderExtension.loadTextureBufferAsync(gltfRuntime, id, onSuccess, onError);
}, function () {
GLTF1.GLTFLoaderBase.LoadTextureBufferAsync(gltfRuntime, id, onSuccess, onError);
});
};
GLTFLoaderExtension.CreateTextureAsync = function (gltfRuntime, id, buffer, onSuccess, onError) {
GLTFLoaderExtension.ApplyExtensions(function (loaderExtension) {
return loaderExtension.createTextureAsync(gltfRuntime, id, buffer, onSuccess, onError);
}, function () {
GLTF1.GLTFLoaderBase.CreateTextureAsync(gltfRuntime, id, buffer, onSuccess, onError);
});
};
GLTFLoaderExtension.ApplyExtensions = function (func, defaultFunc) {
for (var extensionName in GLTF1.GLTFLoader.Extensions) {
var loaderExtension = GLTF1.GLTFLoader.Extensions[extensionName];
if (func(loaderExtension)) {
return;
}
}
defaultFunc();
};
return GLTFLoaderExtension;
}());
GLTF1.GLTFLoaderExtension = GLTFLoaderExtension;
})(GLTF1 = BABYLON.GLTF1 || (BABYLON.GLTF1 = {}));
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.glTFLoaderExtension.js.map
///
var BABYLON;
(function (BABYLON) {
var GLTF1;
(function (GLTF1) {
var BinaryExtensionBufferName = "binary_glTF";
;
;
var GLTFBinaryExtension = /** @class */ (function (_super) {
__extends(GLTFBinaryExtension, _super);
function GLTFBinaryExtension() {
return _super.call(this, "KHR_binary_glTF") || this;
}
GLTFBinaryExtension.prototype.loadRuntimeAsync = function (scene, data, rootUrl, onSuccess, onError) {
var extensionsUsed = data.json.extensionsUsed;
if (!extensionsUsed || extensionsUsed.indexOf(this.name) === -1 || !data.bin) {
return false;
}
this._bin = data.bin;
onSuccess(GLTF1.GLTFLoaderBase.CreateRuntime(data.json, scene, rootUrl));
return true;
};
GLTFBinaryExtension.prototype.loadBufferAsync = function (gltfRuntime, id, onSuccess, onError) {
if (gltfRuntime.extensionsUsed.indexOf(this.name) === -1) {
return false;
}
if (id !== BinaryExtensionBufferName) {
return false;
}
onSuccess(this._bin);
return true;
};
GLTFBinaryExtension.prototype.loadTextureBufferAsync = function (gltfRuntime, id, onSuccess, onError) {
var texture = gltfRuntime.textures[id];
var source = gltfRuntime.images[texture.source];
if (!source.extensions || !(this.name in source.extensions)) {
return false;
}
var sourceExt = source.extensions[this.name];
var bufferView = gltfRuntime.bufferViews[sourceExt.bufferView];
var buffer = GLTF1.GLTFUtils.GetBufferFromBufferView(gltfRuntime, bufferView, 0, bufferView.byteLength, GLTF1.EComponentType.UNSIGNED_BYTE);
onSuccess(buffer);
return true;
};
GLTFBinaryExtension.prototype.loadShaderStringAsync = function (gltfRuntime, id, onSuccess, onError) {
var shader = gltfRuntime.shaders[id];
if (!shader.extensions || !(this.name in shader.extensions)) {
return false;
}
var binaryExtensionShader = shader.extensions[this.name];
var bufferView = gltfRuntime.bufferViews[binaryExtensionShader.bufferView];
var shaderBytes = GLTF1.GLTFUtils.GetBufferFromBufferView(gltfRuntime, bufferView, 0, bufferView.byteLength, GLTF1.EComponentType.UNSIGNED_BYTE);
setTimeout(function () {
var shaderString = GLTF1.GLTFUtils.DecodeBufferToText(shaderBytes);
onSuccess(shaderString);
});
return true;
};
return GLTFBinaryExtension;
}(GLTF1.GLTFLoaderExtension));
GLTF1.GLTFBinaryExtension = GLTFBinaryExtension;
GLTF1.GLTFLoader.RegisterExtension(new GLTFBinaryExtension());
})(GLTF1 = BABYLON.GLTF1 || (BABYLON.GLTF1 = {}));
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.glTFBinaryExtension.js.map
///
var BABYLON;
(function (BABYLON) {
var GLTF1;
(function (GLTF1) {
;
;
;
var GLTFMaterialsCommonExtension = /** @class */ (function (_super) {
__extends(GLTFMaterialsCommonExtension, _super);
function GLTFMaterialsCommonExtension() {
return _super.call(this, "KHR_materials_common") || this;
}
GLTFMaterialsCommonExtension.prototype.loadRuntimeExtensionsAsync = function (gltfRuntime, onSuccess, onError) {
if (!gltfRuntime.extensions)
return false;
var extension = gltfRuntime.extensions[this.name];
if (!extension)
return false;
// Create lights
var lights = extension.lights;
if (lights) {
for (var thing in lights) {
var light = lights[thing];
switch (light.type) {
case "ambient":
var ambientLight = new BABYLON.HemisphericLight(light.name, new BABYLON.Vector3(0, 1, 0), gltfRuntime.scene);
var ambient = light.ambient;
if (ambient) {
ambientLight.diffuse = BABYLON.Color3.FromArray(ambient.color || [1, 1, 1]);
}
break;
case "point":
var pointLight = new BABYLON.PointLight(light.name, new BABYLON.Vector3(10, 10, 10), gltfRuntime.scene);
var point = light.point;
if (point) {
pointLight.diffuse = BABYLON.Color3.FromArray(point.color || [1, 1, 1]);
}
break;
case "directional":
var dirLight = new BABYLON.DirectionalLight(light.name, new BABYLON.Vector3(0, -1, 0), gltfRuntime.scene);
var directional = light.directional;
if (directional) {
dirLight.diffuse = BABYLON.Color3.FromArray(directional.color || [1, 1, 1]);
}
break;
case "spot":
var spot = light.spot;
if (spot) {
var spotLight = new BABYLON.SpotLight(light.name, new BABYLON.Vector3(0, 10, 0), new BABYLON.Vector3(0, -1, 0), spot.fallOffAngle || Math.PI, spot.fallOffExponent || 0.0, gltfRuntime.scene);
spotLight.diffuse = BABYLON.Color3.FromArray(spot.color || [1, 1, 1]);
}
break;
default:
BABYLON.Tools.Warn("GLTF Material Common extension: light type \"" + light.type + "\” not supported");
break;
}
}
}
return false;
};
GLTFMaterialsCommonExtension.prototype.loadMaterialAsync = function (gltfRuntime, id, onSuccess, onError) {
var material = gltfRuntime.materials[id];
if (!material || !material.extensions)
return false;
var extension = material.extensions[this.name];
if (!extension)
return false;
var standardMaterial = new BABYLON.StandardMaterial(id, gltfRuntime.scene);
standardMaterial.sideOrientation = BABYLON.Material.CounterClockWiseSideOrientation;
if (extension.technique === "CONSTANT") {
standardMaterial.disableLighting = true;
}
standardMaterial.backFaceCulling = extension.doubleSided === undefined ? false : !extension.doubleSided;
standardMaterial.alpha = extension.values.transparency === undefined ? 1.0 : extension.values.transparency;
standardMaterial.specularPower = extension.values.shininess === undefined ? 0.0 : extension.values.shininess;
// Ambient
if (typeof extension.values.ambient === "string") {
this._loadTexture(gltfRuntime, extension.values.ambient, standardMaterial, "ambientTexture", onError);
}
else {
standardMaterial.ambientColor = BABYLON.Color3.FromArray(extension.values.ambient || [0, 0, 0]);
}
// Diffuse
if (typeof extension.values.diffuse === "string") {
this._loadTexture(gltfRuntime, extension.values.diffuse, standardMaterial, "diffuseTexture", onError);
}
else {
standardMaterial.diffuseColor = BABYLON.Color3.FromArray(extension.values.diffuse || [0, 0, 0]);
}
// Emission
if (typeof extension.values.emission === "string") {
this._loadTexture(gltfRuntime, extension.values.emission, standardMaterial, "emissiveTexture", onError);
}
else {
standardMaterial.emissiveColor = BABYLON.Color3.FromArray(extension.values.emission || [0, 0, 0]);
}
// Specular
if (typeof extension.values.specular === "string") {
this._loadTexture(gltfRuntime, extension.values.specular, standardMaterial, "specularTexture", onError);
}
else {
standardMaterial.specularColor = BABYLON.Color3.FromArray(extension.values.specular || [0, 0, 0]);
}
return true;
};
GLTFMaterialsCommonExtension.prototype._loadTexture = function (gltfRuntime, id, material, propertyPath, onError) {
// Create buffer from texture url
GLTF1.GLTFLoaderBase.LoadTextureBufferAsync(gltfRuntime, id, function (buffer) {
// Create texture from buffer
GLTF1.GLTFLoaderBase.CreateTextureAsync(gltfRuntime, id, buffer, function (texture) { return material[propertyPath] = texture; }, onError);
}, onError);
};
return GLTFMaterialsCommonExtension;
}(GLTF1.GLTFLoaderExtension));
GLTF1.GLTFMaterialsCommonExtension = GLTFMaterialsCommonExtension;
GLTF1.GLTFLoader.RegisterExtension(new GLTFMaterialsCommonExtension());
})(GLTF1 = BABYLON.GLTF1 || (BABYLON.GLTF1 = {}));
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.glTFMaterialsCommonExtension.js.map
///
var BABYLON;
(function (BABYLON) {
var GLTF2;
(function (GLTF2) {
var ArrayItem = /** @class */ (function () {
function ArrayItem() {
}
ArrayItem.Assign = function (values) {
if (values) {
for (var index = 0; index < values.length; index++) {
values[index]._index = index;
}
}
};
return ArrayItem;
}());
GLTF2.ArrayItem = ArrayItem;
})(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.glTFLoaderUtilities.js.map
///
///
//# sourceMappingURL=babylon.glTFLoaderInterfaces.js.map
///
var BABYLON;
(function (BABYLON) {
var GLTF2;
(function (GLTF2) {
var GLTFLoader = /** @class */ (function () {
function GLTFLoader() {
this._completePromises = new Array();
this._disposed = false;
this._state = null;
this._extensions = {};
this._defaultSampler = {};
this._requests = new Array();
this.coordinateSystemMode = BABYLON.GLTFLoaderCoordinateSystemMode.AUTO;
this.animationStartMode = BABYLON.GLTFLoaderAnimationStartMode.FIRST;
this.compileMaterials = false;
this.useClipPlane = false;
this.compileShadowGenerators = false;
this.onDisposeObservable = new BABYLON.Observable();
this.onMeshLoadedObservable = new BABYLON.Observable();
this.onTextureLoadedObservable = new BABYLON.Observable();
this.onMaterialLoadedObservable = new BABYLON.Observable();
this.onAnimationGroupLoadedObservable = new BABYLON.Observable();
this.onExtensionLoadedObservable = new BABYLON.Observable();
this.onCompleteObservable = new BABYLON.Observable();
}
GLTFLoader._Register = function (name, factory) {
if (GLTFLoader._Factories[name]) {
BABYLON.Tools.Error("Extension with the name '" + name + "' already exists");
return;
}
GLTFLoader._Factories[name] = factory;
// Keep the order of registration so that extensions registered first are called first.
GLTFLoader._Names.push(name);
};
Object.defineProperty(GLTFLoader.prototype, "state", {
get: function () {
return this._state;
},
enumerable: true,
configurable: true
});
GLTFLoader.prototype.dispose = function () {
if (this._disposed) {
return;
}
this._disposed = true;
this.onDisposeObservable.notifyObservers(this);
this.onDisposeObservable.clear();
this._clear();
};
GLTFLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress) {
var _this = this;
return Promise.resolve().then(function () {
var nodes = null;
if (meshesNames) {
var nodeMap_1 = {};
if (_this._gltf.nodes) {
for (var _i = 0, _a = _this._gltf.nodes; _i < _a.length; _i++) {
var node = _a[_i];
if (node.name) {
nodeMap_1[node.name] = node;
}
}
}
var names = (meshesNames instanceof Array) ? meshesNames : [meshesNames];
nodes = names.map(function (name) {
var node = nodeMap_1[name];
if (!node) {
throw new Error("Failed to find node '" + name + "'");
}
return node;
});
}
return _this._loadAsync(nodes, scene, data, rootUrl, onProgress).then(function () {
return {
meshes: _this._getMeshes(),
particleSystems: [],
skeletons: _this._getSkeletons(),
};
});
});
};
GLTFLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress) {
return this._loadAsync(null, scene, data, rootUrl, onProgress);
};
GLTFLoader.prototype._loadAsync = function (nodes, scene, data, rootUrl, onProgress) {
var _this = this;
return Promise.resolve().then(function () {
_this._loadExtensions();
_this._babylonScene = scene;
_this._rootUrl = rootUrl;
_this._progressCallback = onProgress;
_this._state = BABYLON.GLTFLoaderState.Loading;
_this._loadData(data);
_this._checkExtensions();
var promises = new Array();
if (nodes) {
promises.push(_this._loadNodesAsync(nodes));
}
else {
var scene_1 = GLTFLoader._GetProperty("#/scene", _this._gltf.scenes, _this._gltf.scene || 0);
promises.push(_this._loadSceneAsync("#/scenes/" + scene_1._index, scene_1));
}
if (_this.compileMaterials) {
promises.push(_this._compileMaterialsAsync());
}
if (_this.compileShadowGenerators) {
promises.push(_this._compileShadowGeneratorsAsync());
}
var resultPromise = Promise.all(promises).then(function () {
_this._state = BABYLON.GLTFLoaderState.Ready;
_this._startAnimations();
});
resultPromise.then(function () {
_this._rootBabylonMesh.setEnabled(true);
BABYLON.Tools.SetImmediate(function () {
if (!_this._disposed) {
Promise.all(_this._completePromises).then(function () {
_this._state = BABYLON.GLTFLoaderState.Complete;
_this.onCompleteObservable.notifyObservers(_this);
_this.onCompleteObservable.clear();
_this._clear();
}).catch(function (error) {
BABYLON.Tools.Error("glTF Loader: " + error.message);
_this._clear();
});
}
});
});
return resultPromise;
}).catch(function (error) {
BABYLON.Tools.Error("glTF Loader: " + error.message);
_this._clear();
throw error;
});
};
GLTFLoader.prototype._loadExtensions = function () {
for (var _i = 0, _a = GLTFLoader._Names; _i < _a.length; _i++) {
var name_1 = _a[_i];
var extension = GLTFLoader._Factories[name_1](this);
this._extensions[name_1] = extension;
this.onExtensionLoadedObservable.notifyObservers(extension);
}
this.onExtensionLoadedObservable.clear();
};
GLTFLoader.prototype._loadData = function (data) {
this._gltf = data.json;
this._setupData();
if (data.bin) {
var buffers = this._gltf.buffers;
if (buffers && buffers[0] && !buffers[0].uri) {
var binaryBuffer = buffers[0];
if (binaryBuffer.byteLength < data.bin.byteLength - 3 || binaryBuffer.byteLength > data.bin.byteLength) {
BABYLON.Tools.Warn("Binary buffer length (" + binaryBuffer.byteLength + ") from JSON does not match chunk length (" + data.bin.byteLength + ")");
}
binaryBuffer._data = Promise.resolve(data.bin);
}
else {
BABYLON.Tools.Warn("Unexpected BIN chunk");
}
}
};
GLTFLoader.prototype._setupData = function () {
GLTF2.ArrayItem.Assign(this._gltf.accessors);
GLTF2.ArrayItem.Assign(this._gltf.animations);
GLTF2.ArrayItem.Assign(this._gltf.buffers);
GLTF2.ArrayItem.Assign(this._gltf.bufferViews);
GLTF2.ArrayItem.Assign(this._gltf.cameras);
GLTF2.ArrayItem.Assign(this._gltf.images);
GLTF2.ArrayItem.Assign(this._gltf.materials);
GLTF2.ArrayItem.Assign(this._gltf.meshes);
GLTF2.ArrayItem.Assign(this._gltf.nodes);
GLTF2.ArrayItem.Assign(this._gltf.samplers);
GLTF2.ArrayItem.Assign(this._gltf.scenes);
GLTF2.ArrayItem.Assign(this._gltf.skins);
GLTF2.ArrayItem.Assign(this._gltf.textures);
if (this._gltf.nodes) {
var nodeParents = {};
for (var _i = 0, _a = this._gltf.nodes; _i < _a.length; _i++) {
var node = _a[_i];
if (node.children) {
for (var _b = 0, _c = node.children; _b < _c.length; _b++) {
var index = _c[_b];
nodeParents[index] = node._index;
}
}
}
var rootNode = this._createRootNode();
for (var _d = 0, _e = this._gltf.nodes; _d < _e.length; _d++) {
var node = _e[_d];
var parentIndex = nodeParents[node._index];
node._parent = parentIndex === undefined ? rootNode : this._gltf.nodes[parentIndex];
}
}
};
GLTFLoader.prototype._checkExtensions = function () {
if (this._gltf.extensionsRequired) {
for (var _i = 0, _a = this._gltf.extensionsRequired; _i < _a.length; _i++) {
var name_2 = _a[_i];
var extension = this._extensions[name_2];
if (!extension || !extension.enabled) {
throw new Error("Require extension " + name_2 + " is not available");
}
}
}
};
GLTFLoader.prototype._createRootNode = function () {
this._rootBabylonMesh = new BABYLON.Mesh("__root__", this._babylonScene);
this._rootBabylonMesh.setEnabled(false);
var rootNode = { _babylonMesh: this._rootBabylonMesh };
switch (this.coordinateSystemMode) {
case BABYLON.GLTFLoaderCoordinateSystemMode.AUTO: {
if (!this._babylonScene.useRightHandedSystem) {
rootNode.rotation = [0, 1, 0, 0];
rootNode.scale = [1, 1, -1];
GLTFLoader._LoadTransform(rootNode, this._rootBabylonMesh);
}
break;
}
case BABYLON.GLTFLoaderCoordinateSystemMode.FORCE_RIGHT_HANDED: {
this._babylonScene.useRightHandedSystem = true;
break;
}
default: {
throw new Error("Invalid coordinate system mode (" + this.coordinateSystemMode + ")");
}
}
this.onMeshLoadedObservable.notifyObservers(this._rootBabylonMesh);
return rootNode;
};
GLTFLoader.prototype._loadNodesAsync = function (nodes) {
var promises = new Array();
for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) {
var node = nodes_1[_i];
promises.push(this._loadNodeAsync("#/nodes/" + node._index, node));
}
promises.push(this._loadAnimationsAsync());
return Promise.all(promises).then(function () { });
};
GLTFLoader.prototype._loadSceneAsync = function (context, scene) {
var promise = GLTF2.GLTFLoaderExtension._LoadSceneAsync(this, context, scene);
if (promise) {
return promise;
}
var promises = new Array();
for (var _i = 0, _a = scene.nodes; _i < _a.length; _i++) {
var index = _a[_i];
var node = GLTFLoader._GetProperty(context + "/nodes/" + index, this._gltf.nodes, index);
promises.push(this._loadNodeAsync("#/nodes/" + node._index, node));
}
promises.push(this._loadAnimationsAsync());
return Promise.all(promises).then(function () { });
};
GLTFLoader.prototype._forEachNodeMesh = function (node, callback) {
if (node._babylonMesh) {
callback(node._babylonMesh);
}
if (node._primitiveBabylonMeshes) {
for (var _i = 0, _a = node._primitiveBabylonMeshes; _i < _a.length; _i++) {
var babylonMesh = _a[_i];
callback(babylonMesh);
}
}
};
GLTFLoader.prototype._getMeshes = function () {
var meshes = new Array();
// Root mesh is always first.
meshes.push(this._rootBabylonMesh);
var nodes = this._gltf.nodes;
if (nodes) {
for (var _i = 0, nodes_2 = nodes; _i < nodes_2.length; _i++) {
var node = nodes_2[_i];
this._forEachNodeMesh(node, function (mesh) {
meshes.push(mesh);
});
}
}
return meshes;
};
GLTFLoader.prototype._getSkeletons = function () {
var skeletons = new Array();
var skins = this._gltf.skins;
if (skins) {
for (var _i = 0, skins_1 = skins; _i < skins_1.length; _i++) {
var skin = skins_1[_i];
if (skin._babylonSkeleton) {
skeletons.push(skin._babylonSkeleton);
}
}
}
return skeletons;
};
GLTFLoader.prototype._startAnimations = function () {
var animations = this._gltf.animations;
if (!animations) {
return;
}
switch (this.animationStartMode) {
case BABYLON.GLTFLoaderAnimationStartMode.NONE: {
// do nothing
break;
}
case BABYLON.GLTFLoaderAnimationStartMode.FIRST: {
var animation = animations[0];
animation._babylonAnimationGroup.start(true);
break;
}
case BABYLON.GLTFLoaderAnimationStartMode.ALL: {
for (var _i = 0, animations_1 = animations; _i < animations_1.length; _i++) {
var animation = animations_1[_i];
animation._babylonAnimationGroup.start(true);
}
break;
}
default: {
BABYLON.Tools.Error("Invalid animation start mode (" + this.animationStartMode + ")");
return;
}
}
};
GLTFLoader.prototype._loadNodeAsync = function (context, node) {
var promise = GLTF2.GLTFLoaderExtension._LoadNodeAsync(this, context, node);
if (promise) {
return promise;
}
if (node._babylonMesh) {
throw new Error(context + ": Invalid recursive node hierarchy");
}
var promises = new Array();
var babylonMesh = new BABYLON.Mesh(node.name || "node" + node._index, this._babylonScene, node._parent._babylonMesh);
node._babylonMesh = babylonMesh;
node._babylonAnimationTargets = node._babylonAnimationTargets || [];
node._babylonAnimationTargets.push(babylonMesh);
GLTFLoader._LoadTransform(node, babylonMesh);
if (node.mesh != undefined) {
var mesh = GLTFLoader._GetProperty(context + "/mesh", this._gltf.meshes, node.mesh);
promises.push(this._loadMeshAsync("#/meshes/" + mesh._index, node, mesh, babylonMesh));
}
if (node.children) {
for (var _i = 0, _a = node.children; _i < _a.length; _i++) {
var index = _a[_i];
var childNode = GLTFLoader._GetProperty(context + "/children/" + index, this._gltf.nodes, index);
promises.push(this._loadNodeAsync("#/nodes/" + index, childNode));
}
}
this.onMeshLoadedObservable.notifyObservers(babylonMesh);
return Promise.all(promises).then(function () { });
};
GLTFLoader.prototype._loadMeshAsync = function (context, node, mesh, babylonMesh) {
// TODO: instancing
var _this = this;
var promises = new Array();
var primitives = mesh.primitives;
if (!primitives || primitives.length === 0) {
throw new Error(context + ": Primitives are missing");
}
GLTF2.ArrayItem.Assign(primitives);
if (primitives.length === 1) {
var primitive = primitives[0];
promises.push(this._loadPrimitiveAsync(context + "/primitives/" + primitive._index, node, mesh, primitive, babylonMesh));
}
else {
node._primitiveBabylonMeshes = [];
for (var _i = 0, primitives_1 = primitives; _i < primitives_1.length; _i++) {
var primitive = primitives_1[_i];
var primitiveBabylonMesh = new BABYLON.Mesh((mesh.name || babylonMesh.name) + "_" + primitive._index, this._babylonScene, babylonMesh);
node._primitiveBabylonMeshes.push(babylonMesh);
promises.push(this._loadPrimitiveAsync(context + "/primitives/" + primitive._index, node, mesh, primitive, primitiveBabylonMesh));
this.onMeshLoadedObservable.notifyObservers(babylonMesh);
}
}
if (node.skin != undefined) {
var skin = GLTFLoader._GetProperty(context + "/skin", this._gltf.skins, node.skin);
promises.push(this._loadSkinAsync("#/skins/" + skin._index, node, mesh, skin));
}
return Promise.all(promises).then(function () {
_this._forEachNodeMesh(node, function (babylonMesh) {
babylonMesh._refreshBoundingInfo(true);
});
});
};
GLTFLoader.prototype._loadPrimitiveAsync = function (context, node, mesh, primitive, babylonMesh) {
var _this = this;
var promises = new Array();
this._createMorphTargets(context, node, mesh, primitive, babylonMesh);
promises.push(this._loadVertexDataAsync(context, primitive, babylonMesh).then(function (babylonVertexData) {
new BABYLON.Geometry(babylonMesh.name, _this._babylonScene, babylonVertexData, false, babylonMesh);
return _this._loadMorphTargetsAsync(context, primitive, babylonMesh, babylonVertexData);
}));
if (primitive.material == undefined) {
babylonMesh.material = this._getDefaultMaterial();
}
else {
var material = GLTFLoader._GetProperty(context + "/material}", this._gltf.materials, primitive.material);
promises.push(this._loadMaterialAsync("#/materials/" + material._index, material, babylonMesh, function (babylonMaterial) {
babylonMesh.material = babylonMaterial;
}));
}
return Promise.all(promises).then(function () { });
};
GLTFLoader.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) {
var _this = this;
var promise = GLTF2.GLTFLoaderExtension._LoadVertexDataAsync(this, context, primitive, babylonMesh);
if (promise) {
return promise;
}
var attributes = primitive.attributes;
if (!attributes) {
throw new Error(context + ": Attributes are missing");
}
if (primitive.mode != undefined && primitive.mode !== 4 /* TRIANGLES */) {
// TODO: handle other primitive modes
throw new Error(context + ": Mode (" + primitive.mode + ") is not currently supported");
}
var promises = new Array();
var babylonVertexData = new BABYLON.VertexData();
if (primitive.indices == undefined) {
var positionAccessorIndex = attributes["POSITION"];
if (positionAccessorIndex != undefined) {
var accessor = GLTFLoader._GetProperty(context + "/attributes/POSITION", this._gltf.accessors, positionAccessorIndex);
babylonVertexData.indices = new Uint32Array(accessor.count);
for (var i = 0; i < babylonVertexData.indices.length; i++) {
babylonVertexData.indices[i] = i;
}
}
}
else {
var indicesAccessor = GLTFLoader._GetProperty(context + "/indices", this._gltf.accessors, primitive.indices);
promises.push(this._loadAccessorAsync("#/accessors/" + indicesAccessor._index, indicesAccessor).then(function (data) {
babylonVertexData.indices = data;
}));
}
var loadAttribute = function (attribute, kind) {
if (attributes[attribute] == undefined) {
return;
}
babylonMesh._delayInfo = babylonMesh._delayInfo || [];
if (babylonMesh._delayInfo.indexOf(kind) === -1) {
babylonMesh._delayInfo.push(kind);
}
if (attribute === "COLOR_0") {
// Assume vertex color has alpha on the mesh. The alphaMode of the material controls whether the material should use alpha or not.
babylonMesh.hasVertexAlpha = true;
}
var accessor = GLTFLoader._GetProperty(context + "/attributes/" + attribute, _this._gltf.accessors, attributes[attribute]);
promises.push(_this._loadAccessorAsync("#/accessors/" + accessor._index, accessor).then(function (data) {
var attributeData = GLTFLoader._ConvertToFloat32Array(context, accessor, data);
if (attribute === "COLOR_0" && accessor.type === "VEC3") {
attributeData = GLTFLoader._ConvertVec3ToVec4(context, attributeData);
}
babylonVertexData.set(attributeData, kind);
}));
};
loadAttribute("POSITION", BABYLON.VertexBuffer.PositionKind);
loadAttribute("NORMAL", BABYLON.VertexBuffer.NormalKind);
loadAttribute("TANGENT", BABYLON.VertexBuffer.TangentKind);
loadAttribute("TEXCOORD_0", BABYLON.VertexBuffer.UVKind);
loadAttribute("TEXCOORD_1", BABYLON.VertexBuffer.UV2Kind);
loadAttribute("JOINTS_0", BABYLON.VertexBuffer.MatricesIndicesKind);
loadAttribute("WEIGHTS_0", BABYLON.VertexBuffer.MatricesWeightsKind);
loadAttribute("COLOR_0", BABYLON.VertexBuffer.ColorKind);
return Promise.all(promises).then(function () {
return babylonVertexData;
});
};
GLTFLoader.prototype._createMorphTargets = function (context, node, mesh, primitive, babylonMesh) {
if (!primitive.targets) {
return;
}
if (node._numMorphTargets == undefined) {
node._numMorphTargets = primitive.targets.length;
}
else if (primitive.targets.length !== node._numMorphTargets) {
throw new Error(context + ": Primitives do not have the same number of targets");
}
babylonMesh.morphTargetManager = new BABYLON.MorphTargetManager();
for (var index = 0; index < primitive.targets.length; index++) {
var weight = node.weights ? node.weights[index] : mesh.weights ? mesh.weights[index] : 0;
babylonMesh.morphTargetManager.addTarget(new BABYLON.MorphTarget("morphTarget" + index, weight));
// TODO: tell the target whether it has positions, normals, tangents
}
};
GLTFLoader.prototype._loadMorphTargetsAsync = function (context, primitive, babylonMesh, babylonVertexData) {
if (!primitive.targets) {
return Promise.resolve();
}
var promises = new Array();
var morphTargetManager = babylonMesh.morphTargetManager;
for (var index = 0; index < morphTargetManager.numTargets; index++) {
var babylonMorphTarget = morphTargetManager.getTarget(index);
promises.push(this._loadMorphTargetVertexDataAsync(context + "/targets/" + index, babylonVertexData, primitive.targets[index], babylonMorphTarget));
}
return Promise.all(promises).then(function () { });
};
GLTFLoader.prototype._loadMorphTargetVertexDataAsync = function (context, babylonVertexData, attributes, babylonMorphTarget) {
var _this = this;
var promises = new Array();
var loadAttribute = function (attribute, setData) {
if (attributes[attribute] == undefined) {
return;
}
var accessor = GLTFLoader._GetProperty(context + "/" + attribute, _this._gltf.accessors, attributes[attribute]);
promises.push(_this._loadAccessorAsync("#/accessors/" + accessor._index, accessor).then(function (data) {
setData(data);
}));
};
loadAttribute("POSITION", function (data) {
if (babylonVertexData.positions) {
for (var i = 0; i < data.length; i++) {
data[i] += babylonVertexData.positions[i];
}
babylonMorphTarget.setPositions(data);
}
});
loadAttribute("NORMAL", function (data) {
if (babylonVertexData.normals) {
for (var i = 0; i < data.length; i++) {
data[i] += babylonVertexData.normals[i];
}
babylonMorphTarget.setNormals(data);
}
});
loadAttribute("TANGENT", function (data) {
if (babylonVertexData.tangents) {
// Tangent data for morph targets is stored as xyz delta.
// The vertexData.tangent is stored as xyzw.
// So we need to skip every fourth vertexData.tangent.
for (var i = 0, j = 0; i < data.length; i++) {
data[i] += babylonVertexData.tangents[j++];
if ((i + 1) % 3 == 0) {
j++;
}
}
babylonMorphTarget.setTangents(data);
}
});
return Promise.all(promises).then(function () { });
};
GLTFLoader._ConvertToFloat32Array = function (context, accessor, data) {
if (accessor.componentType == 5126 /* FLOAT */) {
return data;
}
var factor = 1;
if (accessor.normalized) {
switch (accessor.componentType) {
case 5121 /* UNSIGNED_BYTE */: {
factor = 1 / 255;
break;
}
case 5123 /* UNSIGNED_SHORT */: {
factor = 1 / 65535;
break;
}
default: {
throw new Error(context + ": Invalid component type (" + accessor.componentType + ")");
}
}
}
var result = new Float32Array(accessor.count * GLTFLoader._GetNumComponents(context, accessor.type));
for (var i = 0; i < result.length; i++) {
result[i] = data[i] * factor;
}
return result;
};
GLTFLoader._ConvertVec3ToVec4 = function (context, data) {
var result = new Float32Array(data.length / 3 * 4);
var offset = 0;
for (var i = 0; i < result.length; i++) {
if ((i + 1) % 4 === 0) {
result[i] = 1;
}
else {
result[i] = data[offset++];
}
}
return result;
};
GLTFLoader._LoadTransform = function (node, babylonNode) {
var position = BABYLON.Vector3.Zero();
var rotation = BABYLON.Quaternion.Identity();
var scaling = BABYLON.Vector3.One();
if (node.matrix) {
var matrix = BABYLON.Matrix.FromArray(node.matrix);
matrix.decompose(scaling, rotation, position);
}
else {
if (node.translation)
position = BABYLON.Vector3.FromArray(node.translation);
if (node.rotation)
rotation = BABYLON.Quaternion.FromArray(node.rotation);
if (node.scale)
scaling = BABYLON.Vector3.FromArray(node.scale);
}
babylonNode.position = position;
babylonNode.rotationQuaternion = rotation;
babylonNode.scaling = scaling;
};
GLTFLoader.prototype._loadSkinAsync = function (context, node, mesh, skin) {
var _this = this;
var assignSkeleton = function () {
_this._forEachNodeMesh(node, function (babylonMesh) {
babylonMesh.skeleton = skin._babylonSkeleton;
});
node._babylonMesh.parent = _this._rootBabylonMesh;
node._babylonMesh.position = BABYLON.Vector3.Zero();
node._babylonMesh.rotationQuaternion = BABYLON.Quaternion.Identity();
node._babylonMesh.scaling = BABYLON.Vector3.One();
};
if (skin._loaded) {
return skin._loaded.then(function () {
assignSkeleton();
});
}
// TODO: split into two parts so that bones are created before inverseBindMatricesData is loaded (for compiling materials).
return (skin._loaded = this._loadSkinInverseBindMatricesDataAsync(context, skin).then(function (inverseBindMatricesData) {
var skeletonId = "skeleton" + skin._index;
var babylonSkeleton = new BABYLON.Skeleton(skin.name || skeletonId, skeletonId, _this._babylonScene);
skin._babylonSkeleton = babylonSkeleton;
_this._loadBones(context, skin, inverseBindMatricesData);
assignSkeleton();
}));
};
GLTFLoader.prototype._loadSkinInverseBindMatricesDataAsync = function (context, skin) {
if (skin.inverseBindMatrices == undefined) {
return Promise.resolve(null);
}
var accessor = GLTFLoader._GetProperty(context + "/inverseBindMatrices", this._gltf.accessors, skin.inverseBindMatrices);
return this._loadAccessorAsync("#/accessors/" + accessor._index, accessor).then(function (data) {
return data;
});
};
GLTFLoader.prototype._createBone = function (node, skin, parent, localMatrix, baseMatrix, index) {
var babylonBone = new BABYLON.Bone(node.name || "joint" + node._index, skin._babylonSkeleton, parent, localMatrix, null, baseMatrix, index);
node._babylonAnimationTargets = node._babylonAnimationTargets || [];
node._babylonAnimationTargets.push(babylonBone);
return babylonBone;
};
GLTFLoader.prototype._loadBones = function (context, skin, inverseBindMatricesData) {
var babylonBones = {};
for (var _i = 0, _a = skin.joints; _i < _a.length; _i++) {
var index = _a[_i];
var node = GLTFLoader._GetProperty(context + "/joints/" + index, this._gltf.nodes, index);
this._loadBone(node, skin, inverseBindMatricesData, babylonBones);
}
};
GLTFLoader.prototype._loadBone = function (node, skin, inverseBindMatricesData, babylonBones) {
var babylonBone = babylonBones[node._index];
if (babylonBone) {
return babylonBone;
}
var boneIndex = skin.joints.indexOf(node._index);
var baseMatrix = BABYLON.Matrix.Identity();
if (inverseBindMatricesData && boneIndex !== -1) {
baseMatrix = BABYLON.Matrix.FromArray(inverseBindMatricesData, boneIndex * 16);
baseMatrix.invertToRef(baseMatrix);
}
var babylonParentBone = null;
if (node._parent._babylonMesh !== this._rootBabylonMesh) {
babylonParentBone = this._loadBone(node._parent, skin, inverseBindMatricesData, babylonBones);
baseMatrix.multiplyToRef(babylonParentBone.getInvertedAbsoluteTransform(), baseMatrix);
}
babylonBone = this._createBone(node, skin, babylonParentBone, this._getNodeMatrix(node), baseMatrix, boneIndex);
babylonBones[node._index] = babylonBone;
return babylonBone;
};
GLTFLoader.prototype._getNodeMatrix = function (node) {
return node.matrix ?
BABYLON.Matrix.FromArray(node.matrix) :
BABYLON.Matrix.Compose(node.scale ? BABYLON.Vector3.FromArray(node.scale) : BABYLON.Vector3.One(), node.rotation ? BABYLON.Quaternion.FromArray(node.rotation) : BABYLON.Quaternion.Identity(), node.translation ? BABYLON.Vector3.FromArray(node.translation) : BABYLON.Vector3.Zero());
};
GLTFLoader.prototype._loadAnimationsAsync = function () {
var animations = this._gltf.animations;
if (!animations) {
return Promise.resolve();
}
var promises = new Array();
for (var index = 0; index < animations.length; index++) {
var animation = animations[index];
promises.push(this._loadAnimationAsync("#/animations/" + index, animation));
}
return Promise.all(promises).then(function () { });
};
GLTFLoader.prototype._loadAnimationAsync = function (context, animation) {
var babylonAnimationGroup = new BABYLON.AnimationGroup(animation.name || "animation" + animation._index, this._babylonScene);
animation._babylonAnimationGroup = babylonAnimationGroup;
var promises = new Array();
GLTF2.ArrayItem.Assign(animation.channels);
GLTF2.ArrayItem.Assign(animation.samplers);
for (var _i = 0, _a = animation.channels; _i < _a.length; _i++) {
var channel = _a[_i];
promises.push(this._loadAnimationChannelAsync(context + "/channels/" + channel._index, context, animation, channel, babylonAnimationGroup));
}
this.onAnimationGroupLoadedObservable.notifyObservers(babylonAnimationGroup);
return Promise.all(promises).then(function () {
babylonAnimationGroup.normalize();
});
};
GLTFLoader.prototype._loadAnimationChannelAsync = function (context, animationContext, animation, channel, babylonAnimationGroup) {
var _this = this;
var targetNode = GLTFLoader._GetProperty(context + "/target/node", this._gltf.nodes, channel.target.node);
if (!targetNode._babylonMesh || targetNode.skin != undefined) {
return Promise.resolve();
}
var sampler = GLTFLoader._GetProperty(context + "/sampler", animation.samplers, channel.sampler);
return this._loadAnimationSamplerAsync(animationContext + "/samplers/" + channel.sampler, sampler).then(function (data) {
var targetPath;
var animationType;
switch (channel.target.path) {
case "translation" /* TRANSLATION */: {
targetPath = "position";
animationType = BABYLON.Animation.ANIMATIONTYPE_VECTOR3;
break;
}
case "rotation" /* ROTATION */: {
targetPath = "rotationQuaternion";
animationType = BABYLON.Animation.ANIMATIONTYPE_QUATERNION;
break;
}
case "scale" /* SCALE */: {
targetPath = "scaling";
animationType = BABYLON.Animation.ANIMATIONTYPE_VECTOR3;
break;
}
case "weights" /* WEIGHTS */: {
targetPath = "influence";
animationType = BABYLON.Animation.ANIMATIONTYPE_FLOAT;
break;
}
default: {
throw new Error(context + ": Invalid target path (" + channel.target.path + ")");
}
}
var outputBufferOffset = 0;
var getNextOutputValue;
switch (targetPath) {
case "position": {
getNextOutputValue = function () {
var value = BABYLON.Vector3.FromArray(data.output, outputBufferOffset);
outputBufferOffset += 3;
return value;
};
break;
}
case "rotationQuaternion": {
getNextOutputValue = function () {
var value = BABYLON.Quaternion.FromArray(data.output, outputBufferOffset);
outputBufferOffset += 4;
return value;
};
break;
}
case "scaling": {
getNextOutputValue = function () {
var value = BABYLON.Vector3.FromArray(data.output, outputBufferOffset);
outputBufferOffset += 3;
return value;
};
break;
}
case "influence": {
getNextOutputValue = function () {
var value = new Array(targetNode._numMorphTargets);
for (var i = 0; i < targetNode._numMorphTargets; i++) {
value[i] = data.output[outputBufferOffset++];
}
return value;
};
break;
}
}
var getNextKey;
switch (data.interpolation) {
case "STEP" /* STEP */: {
getNextKey = function (frameIndex) { return ({
frame: data.input[frameIndex],
value: getNextOutputValue(),
interpolation: BABYLON.AnimationKeyInterpolation.STEP
}); };
break;
}
case "LINEAR" /* LINEAR */: {
getNextKey = function (frameIndex) { return ({
frame: data.input[frameIndex],
value: getNextOutputValue()
}); };
break;
}
case "CUBICSPLINE" /* CUBICSPLINE */: {
getNextKey = function (frameIndex) { return ({
frame: data.input[frameIndex],
inTangent: getNextOutputValue(),
value: getNextOutputValue(),
outTangent: getNextOutputValue()
}); };
break;
}
}
var keys;
if (data.input.length === 1) {
var key = getNextKey(0);
keys = [
{ frame: key.frame, value: key.value },
{ frame: key.frame + 1, value: key.value }
];
}
else {
keys = new Array(data.input.length);
for (var frameIndex = 0; frameIndex < data.input.length; frameIndex++) {
keys[frameIndex] = getNextKey(frameIndex);
}
}
if (targetPath === "influence") {
var _loop_1 = function (targetIndex) {
var animationName = babylonAnimationGroup.name + "_channel" + babylonAnimationGroup.targetedAnimations.length;
var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
babylonAnimation.setKeys(keys.map(function (key) { return ({
frame: key.frame,
inTangent: key.inTangent ? key.inTangent[targetIndex] : undefined,
value: key.value[targetIndex],
outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
}); }));
_this._forEachNodeMesh(targetNode, function (babylonMesh) {
var morphTarget = babylonMesh.morphTargetManager.getTarget(targetIndex);
babylonAnimationGroup.addTargetedAnimation(babylonAnimation, morphTarget);
});
};
for (var targetIndex = 0; targetIndex < targetNode._numMorphTargets; targetIndex++) {
_loop_1(targetIndex);
}
}
else {
var animationName = babylonAnimationGroup.name + "_channel" + babylonAnimationGroup.targetedAnimations.length;
var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
babylonAnimation.setKeys(keys);
if (targetNode._babylonAnimationTargets) {
for (var _i = 0, _a = targetNode._babylonAnimationTargets; _i < _a.length; _i++) {
var target = _a[_i];
babylonAnimationGroup.addTargetedAnimation(babylonAnimation, target);
}
}
}
});
};
GLTFLoader.prototype._loadAnimationSamplerAsync = function (context, sampler) {
if (sampler._data) {
return sampler._data;
}
var interpolation = sampler.interpolation || "LINEAR" /* LINEAR */;
switch (interpolation) {
case "STEP" /* STEP */:
case "LINEAR" /* LINEAR */:
case "CUBICSPLINE" /* CUBICSPLINE */: {
break;
}
default: {
throw new Error(context + ": Invalid interpolation (" + sampler.interpolation + ")");
}
}
var inputData;
var outputData;
var inputAccessor = GLTFLoader._GetProperty(context + "/input", this._gltf.accessors, sampler.input);
var outputAccessor = GLTFLoader._GetProperty(context + "/output", this._gltf.accessors, sampler.output);
sampler._data = Promise.all([
this._loadAccessorAsync("#/accessors/" + inputAccessor._index, inputAccessor).then(function (data) {
inputData = data;
}),
this._loadAccessorAsync("#/accessors/" + outputAccessor._index, outputAccessor).then(function (data) {
outputData = data;
})
]).then(function () {
return {
input: inputData,
interpolation: interpolation,
output: outputData,
};
});
return sampler._data;
};
GLTFLoader.prototype._loadBufferAsync = function (context, buffer) {
if (buffer._data) {
return buffer._data;
}
if (!buffer.uri) {
throw new Error(context + ": Uri is missing");
}
buffer._data = this._loadUriAsync(context, buffer.uri);
return buffer._data;
};
GLTFLoader.prototype._loadBufferViewAsync = function (context, bufferView) {
if (bufferView._data) {
return bufferView._data;
}
var buffer = GLTFLoader._GetProperty(context + "/buffer", this._gltf.buffers, bufferView.buffer);
bufferView._data = this._loadBufferAsync("#/buffers/" + buffer._index, buffer).then(function (bufferData) {
try {
return new Uint8Array(bufferData.buffer, bufferData.byteOffset + (bufferView.byteOffset || 0), bufferView.byteLength);
}
catch (e) {
throw new Error(context + ": " + e.message);
}
});
return bufferView._data;
};
GLTFLoader.prototype._loadAccessorAsync = function (context, accessor) {
var _this = this;
if (accessor.sparse) {
throw new Error(context + ": Sparse accessors are not currently supported");
}
if (accessor._data) {
return accessor._data;
}
var bufferView = GLTFLoader._GetProperty(context + "/bufferView", this._gltf.bufferViews, accessor.bufferView);
accessor._data = this._loadBufferViewAsync("#/bufferViews/" + bufferView._index, bufferView).then(function (bufferViewData) {
var numComponents = GLTFLoader._GetNumComponents(context, accessor.type);
var byteOffset = accessor.byteOffset || 0;
var byteStride = bufferView.byteStride;
if (byteStride === 0) {
BABYLON.Tools.Warn(context + ": Byte stride of 0 is not valid");
}
try {
switch (accessor.componentType) {
case 5120 /* BYTE */: {
return _this._buildArrayBuffer(Float32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
}
case 5121 /* UNSIGNED_BYTE */: {
return _this._buildArrayBuffer(Uint8Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
}
case 5122 /* SHORT */: {
return _this._buildArrayBuffer(Int16Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
}
case 5123 /* UNSIGNED_SHORT */: {
return _this._buildArrayBuffer(Uint16Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
}
case 5125 /* UNSIGNED_INT */: {
return _this._buildArrayBuffer(Uint32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
}
case 5126 /* FLOAT */: {
return _this._buildArrayBuffer(Float32Array, bufferViewData, byteOffset, accessor.count, numComponents, byteStride);
}
default: {
throw new Error(context + ": Invalid component type (" + accessor.componentType + ")");
}
}
}
catch (e) {
throw new Error(context + ": " + e.messsage);
}
});
return accessor._data;
};
GLTFLoader.prototype._buildArrayBuffer = function (typedArray, data, byteOffset, count, numComponents, byteStride) {
byteOffset += data.byteOffset;
var targetLength = count * numComponents;
if (!byteStride || byteStride === numComponents * typedArray.BYTES_PER_ELEMENT) {
return new typedArray(data.buffer, byteOffset, targetLength);
}
var elementStride = byteStride / typedArray.BYTES_PER_ELEMENT;
var sourceBuffer = new typedArray(data.buffer, byteOffset, elementStride * count);
var targetBuffer = new typedArray(targetLength);
var sourceIndex = 0;
var targetIndex = 0;
while (targetIndex < targetLength) {
for (var componentIndex = 0; componentIndex < numComponents; componentIndex++) {
targetBuffer[targetIndex] = sourceBuffer[sourceIndex + componentIndex];
targetIndex++;
}
sourceIndex += elementStride;
}
return targetBuffer;
};
GLTFLoader.prototype._getDefaultMaterial = function () {
var id = "__gltf_default";
var babylonMaterial = this._babylonScene.getMaterialByName(id);
if (!babylonMaterial) {
babylonMaterial = new BABYLON.PBRMaterial(id, this._babylonScene);
babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE;
babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? BABYLON.Material.CounterClockWiseSideOrientation : BABYLON.Material.ClockWiseSideOrientation;
babylonMaterial.metallic = 1;
babylonMaterial.roughness = 1;
this.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
}
return babylonMaterial;
};
GLTFLoader.prototype._loadMaterialMetallicRoughnessPropertiesAsync = function (context, material) {
var promises = new Array();
var babylonMaterial = material._babylonMaterial;
// Ensure metallic workflow
babylonMaterial.metallic = 1;
babylonMaterial.roughness = 1;
var properties = material.pbrMetallicRoughness;
if (properties) {
if (properties.baseColorFactor) {
babylonMaterial.albedoColor = BABYLON.Color3.FromArray(properties.baseColorFactor);
babylonMaterial.alpha = properties.baseColorFactor[3];
}
else {
babylonMaterial.albedoColor = BABYLON.Color3.White();
}
babylonMaterial.metallic = properties.metallicFactor == undefined ? 1 : properties.metallicFactor;
babylonMaterial.roughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor;
if (properties.baseColorTexture) {
promises.push(this._loadTextureAsync(context + "/baseColorTexture", properties.baseColorTexture, function (texture) {
babylonMaterial.albedoTexture = texture;
}));
}
if (properties.metallicRoughnessTexture) {
promises.push(this._loadTextureAsync(context + "/metallicRoughnessTexture", properties.metallicRoughnessTexture, function (texture) {
babylonMaterial.metallicTexture = texture;
}));
babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
babylonMaterial.useRoughnessFromMetallicTextureGreen = true;
babylonMaterial.useRoughnessFromMetallicTextureAlpha = false;
}
}
this._loadMaterialAlphaProperties(context, material);
return Promise.all(promises).then(function () { });
};
GLTFLoader.prototype._loadMaterialAsync = function (context, material, babylonMesh, assign) {
var promise = GLTF2.GLTFLoaderExtension._LoadMaterialAsync(this, context, material, babylonMesh, assign);
if (promise) {
return promise;
}
material._babylonMeshes = material._babylonMeshes || [];
material._babylonMeshes.push(babylonMesh);
if (!material._loaded) {
var promises = new Array();
var babylonMaterial = this._createMaterial(material);
material._babylonMaterial = babylonMaterial;
promises.push(this._loadMaterialBasePropertiesAsync(context, material));
promises.push(this._loadMaterialMetallicRoughnessPropertiesAsync(context, material));
this.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
material._loaded = Promise.all(promises).then(function () { });
}
assign(material._babylonMaterial);
return material._loaded;
};
GLTFLoader.prototype._createMaterial = function (material) {
var babylonMaterial = new BABYLON.PBRMaterial(material.name || "material" + material._index, this._babylonScene);
babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? BABYLON.Material.CounterClockWiseSideOrientation : BABYLON.Material.ClockWiseSideOrientation;
return babylonMaterial;
};
GLTFLoader.prototype._loadMaterialBasePropertiesAsync = function (context, material) {
var promises = new Array();
var babylonMaterial = material._babylonMaterial;
babylonMaterial.emissiveColor = material.emissiveFactor ? BABYLON.Color3.FromArray(material.emissiveFactor) : new BABYLON.Color3(0, 0, 0);
if (material.doubleSided) {
babylonMaterial.backFaceCulling = false;
babylonMaterial.twoSidedLighting = true;
}
if (material.normalTexture) {
promises.push(this._loadTextureAsync(context + "/normalTexture", material.normalTexture, function (texture) {
babylonMaterial.bumpTexture = texture;
}));
babylonMaterial.invertNormalMapX = !this._babylonScene.useRightHandedSystem;
babylonMaterial.invertNormalMapY = this._babylonScene.useRightHandedSystem;
if (material.normalTexture.scale != undefined) {
babylonMaterial.bumpTexture.level = material.normalTexture.scale;
}
}
if (material.occlusionTexture) {
promises.push(this._loadTextureAsync(context + "/occlusionTexture", material.occlusionTexture, function (texture) {
babylonMaterial.ambientTexture = texture;
}));
babylonMaterial.useAmbientInGrayScale = true;
if (material.occlusionTexture.strength != undefined) {
babylonMaterial.ambientTextureStrength = material.occlusionTexture.strength;
}
}
if (material.emissiveTexture) {
promises.push(this._loadTextureAsync(context + "/emissiveTexture", material.emissiveTexture, function (texture) {
babylonMaterial.emissiveTexture = texture;
}));
}
return Promise.all(promises).then(function () { });
};
GLTFLoader.prototype._loadMaterialAlphaProperties = function (context, material) {
var babylonMaterial = material._babylonMaterial;
var alphaMode = material.alphaMode || "OPAQUE" /* OPAQUE */;
switch (alphaMode) {
case "OPAQUE" /* OPAQUE */: {
babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE;
break;
}
case "MASK" /* MASK */: {
babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_ALPHATEST;
babylonMaterial.alphaCutOff = (material.alphaCutoff == undefined ? 0.5 : material.alphaCutoff);
if (babylonMaterial.alpha) {
if (babylonMaterial.alpha === 0) {
babylonMaterial.alphaCutOff = 1;
}
else {
babylonMaterial.alphaCutOff /= babylonMaterial.alpha;
}
babylonMaterial.alpha = 1;
}
if (babylonMaterial.albedoTexture) {
babylonMaterial.albedoTexture.hasAlpha = true;
}
break;
}
case "BLEND" /* BLEND */: {
babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_ALPHABLEND;
if (babylonMaterial.albedoTexture) {
babylonMaterial.albedoTexture.hasAlpha = true;
babylonMaterial.useAlphaFromAlbedoTexture = true;
}
break;
}
default: {
throw new Error(context + ": Invalid alpha mode (" + material.alphaMode + ")");
}
}
};
GLTFLoader.prototype._loadTextureAsync = function (context, textureInfo, assign) {
var _this = this;
var texture = GLTFLoader._GetProperty(context + "/index", this._gltf.textures, textureInfo.index);
context = "#/textures/" + textureInfo.index;
var promises = new Array();
var sampler = (texture.sampler == undefined ? this._defaultSampler : GLTFLoader._GetProperty(context + "/sampler", this._gltf.samplers, texture.sampler));
var samplerData = this._loadSampler("#/samplers/" + sampler._index, sampler);
var deferred = new BABYLON.Deferred();
var babylonTexture = new BABYLON.Texture(null, this._babylonScene, samplerData.noMipMaps, false, samplerData.samplingMode, function () {
if (!_this._disposed) {
deferred.resolve();
}
}, function (message, exception) {
if (!_this._disposed) {
deferred.reject(new Error(context + ": " + ((exception && exception.message) ? exception.message : message || "Failed to load texture")));
}
});
promises.push(deferred.promise);
babylonTexture.name = texture.name || "texture" + texture._index;
babylonTexture.wrapU = samplerData.wrapU;
babylonTexture.wrapV = samplerData.wrapV;
babylonTexture.coordinatesIndex = textureInfo.texCoord || 0;
var image = GLTFLoader._GetProperty(context + "/source", this._gltf.images, texture.source);
promises.push(this._loadImageAsync("#/images/" + image._index, image).then(function (objectURL) {
babylonTexture.updateURL(objectURL);
}));
assign(babylonTexture);
this.onTextureLoadedObservable.notifyObservers(babylonTexture);
return Promise.all(promises).then(function () { });
};
GLTFLoader.prototype._loadSampler = function (context, sampler) {
if (!sampler._data) {
sampler._data = {
noMipMaps: (sampler.minFilter === 9728 /* NEAREST */ || sampler.minFilter === 9729 /* LINEAR */),
samplingMode: GLTFLoader._GetTextureSamplingMode(context, sampler.magFilter, sampler.minFilter),
wrapU: GLTFLoader._GetTextureWrapMode(context, sampler.wrapS),
wrapV: GLTFLoader._GetTextureWrapMode(context, sampler.wrapT)
};
}
;
return sampler._data;
};
GLTFLoader.prototype._loadImageAsync = function (context, image) {
if (image._objectURL) {
return image._objectURL;
}
var promise;
if (image.uri) {
promise = this._loadUriAsync(context, image.uri);
}
else {
var bufferView = GLTFLoader._GetProperty(context + "/bufferView", this._gltf.bufferViews, image.bufferView);
promise = this._loadBufferViewAsync("#/bufferViews/" + bufferView._index, bufferView);
}
image._objectURL = promise.then(function (data) {
return URL.createObjectURL(new Blob([data], { type: image.mimeType }));
});
return image._objectURL;
};
GLTFLoader.prototype._loadUriAsync = function (context, uri) {
var _this = this;
var promise = GLTF2.GLTFLoaderExtension._LoadUriAsync(this, context, uri);
if (promise) {
return promise;
}
if (!GLTFLoader._ValidateUri(uri)) {
throw new Error(context + ": Uri '" + uri + "' is invalid");
}
if (BABYLON.Tools.IsBase64(uri)) {
return Promise.resolve(new Uint8Array(BABYLON.Tools.DecodeBase64(uri)));
}
return new Promise(function (resolve, reject) {
var request = BABYLON.Tools.LoadFile(_this._rootUrl + uri, function (data) {
if (!_this._disposed) {
resolve(new Uint8Array(data));
}
}, function (event) {
if (!_this._disposed) {
try {
if (request && _this._state === BABYLON.GLTFLoaderState.Loading) {
request._lengthComputable = event.lengthComputable;
request._loaded = event.loaded;
request._total = event.total;
_this._onProgress();
}
}
catch (e) {
reject(e);
}
}
}, _this._babylonScene.database, true, function (request, exception) {
if (!_this._disposed) {
reject(new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request));
}
});
_this._requests.push(request);
});
};
GLTFLoader.prototype._onProgress = function () {
if (!this._progressCallback) {
return;
}
var lengthComputable = true;
var loaded = 0;
var total = 0;
for (var _i = 0, _a = this._requests; _i < _a.length; _i++) {
var request = _a[_i];
if (request._lengthComputable === undefined || request._loaded === undefined || request._total === undefined) {
return;
}
lengthComputable = lengthComputable && request._lengthComputable;
loaded += request._loaded;
total += request._total;
}
this._progressCallback(new BABYLON.SceneLoaderProgressEvent(lengthComputable, loaded, lengthComputable ? total : 0));
};
GLTFLoader._GetProperty = function (context, array, index) {
if (!array || index == undefined || !array[index]) {
throw new Error(context + ": Failed to find index (" + index + ")");
}
return array[index];
};
GLTFLoader._GetTextureWrapMode = function (context, mode) {
// Set defaults if undefined
mode = mode == undefined ? 10497 /* REPEAT */ : mode;
switch (mode) {
case 33071 /* CLAMP_TO_EDGE */: return BABYLON.Texture.CLAMP_ADDRESSMODE;
case 33648 /* MIRRORED_REPEAT */: return BABYLON.Texture.MIRROR_ADDRESSMODE;
case 10497 /* REPEAT */: return BABYLON.Texture.WRAP_ADDRESSMODE;
default:
BABYLON.Tools.Warn(context + ": Invalid texture wrap mode (" + mode + ")");
return BABYLON.Texture.WRAP_ADDRESSMODE;
}
};
GLTFLoader._GetTextureSamplingMode = function (context, magFilter, minFilter) {
// Set defaults if undefined
magFilter = magFilter == undefined ? 9729 /* LINEAR */ : magFilter;
minFilter = minFilter == undefined ? 9987 /* LINEAR_MIPMAP_LINEAR */ : minFilter;
if (magFilter === 9729 /* LINEAR */) {
switch (minFilter) {
case 9728 /* NEAREST */: return BABYLON.Texture.LINEAR_NEAREST;
case 9729 /* LINEAR */: return BABYLON.Texture.LINEAR_LINEAR;
case 9984 /* NEAREST_MIPMAP_NEAREST */: return BABYLON.Texture.LINEAR_NEAREST_MIPNEAREST;
case 9985 /* LINEAR_MIPMAP_NEAREST */: return BABYLON.Texture.LINEAR_LINEAR_MIPNEAREST;
case 9986 /* NEAREST_MIPMAP_LINEAR */: return BABYLON.Texture.LINEAR_NEAREST_MIPLINEAR;
case 9987 /* LINEAR_MIPMAP_LINEAR */: return BABYLON.Texture.LINEAR_LINEAR_MIPLINEAR;
default:
BABYLON.Tools.Warn(context + ": Invalid texture minification filter (" + minFilter + ")");
return BABYLON.Texture.LINEAR_LINEAR_MIPLINEAR;
}
}
else {
if (magFilter !== 9728 /* NEAREST */) {
BABYLON.Tools.Warn(context + ": Invalid texture magnification filter (" + magFilter + ")");
}
switch (minFilter) {
case 9728 /* NEAREST */: return BABYLON.Texture.NEAREST_NEAREST;
case 9729 /* LINEAR */: return BABYLON.Texture.NEAREST_LINEAR;
case 9984 /* NEAREST_MIPMAP_NEAREST */: return BABYLON.Texture.NEAREST_NEAREST_MIPNEAREST;
case 9985 /* LINEAR_MIPMAP_NEAREST */: return BABYLON.Texture.NEAREST_LINEAR_MIPNEAREST;
case 9986 /* NEAREST_MIPMAP_LINEAR */: return BABYLON.Texture.NEAREST_NEAREST_MIPLINEAR;
case 9987 /* LINEAR_MIPMAP_LINEAR */: return BABYLON.Texture.NEAREST_LINEAR_MIPLINEAR;
default:
BABYLON.Tools.Warn(context + ": Invalid texture minification filter (" + minFilter + ")");
return BABYLON.Texture.NEAREST_NEAREST_MIPNEAREST;
}
}
};
GLTFLoader._GetNumComponents = function (context, type) {
switch (type) {
case "SCALAR": return 1;
case "VEC2": return 2;
case "VEC3": return 3;
case "VEC4": return 4;
case "MAT2": return 4;
case "MAT3": return 9;
case "MAT4": return 16;
}
throw new Error(context + ": Invalid type (" + type + ")");
};
GLTFLoader._ValidateUri = function (uri) {
return (BABYLON.Tools.IsBase64(uri) || uri.indexOf("..") === -1);
};
GLTFLoader.prototype._compileMaterialsAsync = function () {
var promises = new Array();
if (this._gltf.materials) {
for (var _i = 0, _a = this._gltf.materials; _i < _a.length; _i++) {
var material = _a[_i];
var babylonMaterial = material._babylonMaterial;
var babylonMeshes = material._babylonMeshes;
if (babylonMaterial && babylonMeshes) {
for (var _b = 0, babylonMeshes_1 = babylonMeshes; _b < babylonMeshes_1.length; _b++) {
var babylonMesh = babylonMeshes_1[_b];
// Ensure nonUniformScaling is set if necessary.
babylonMesh.computeWorldMatrix(true);
promises.push(babylonMaterial.forceCompilationAsync(babylonMesh));
if (this.useClipPlane) {
promises.push(babylonMaterial.forceCompilationAsync(babylonMesh, { clipPlane: true }));
}
}
}
}
}
return Promise.all(promises).then(function () { });
};
GLTFLoader.prototype._compileShadowGeneratorsAsync = function () {
var promises = new Array();
var lights = this._babylonScene.lights;
for (var _i = 0, lights_1 = lights; _i < lights_1.length; _i++) {
var light = lights_1[_i];
var generator = light.getShadowGenerator();
if (generator) {
promises.push(generator.forceCompilationAsync());
}
}
return Promise.all(promises).then(function () { });
};
GLTFLoader.prototype._clear = function () {
for (var _i = 0, _a = this._requests; _i < _a.length; _i++) {
var request = _a[_i];
request.abort();
}
this._requests.length = 0;
if (this._gltf && this._gltf.images) {
for (var _b = 0, _c = this._gltf.images; _b < _c.length; _b++) {
var image = _c[_b];
if (image._objectURL) {
image._objectURL.then(function (value) {
URL.revokeObjectURL(value);
});
image._objectURL = undefined;
}
}
}
delete this._gltf;
delete this._babylonScene;
this._completePromises.length = 0;
for (var name_3 in this._extensions) {
this._extensions[name_3].dispose();
}
this._extensions = {};
delete this._rootBabylonMesh;
delete this._progressCallback;
this.onMeshLoadedObservable.clear();
this.onTextureLoadedObservable.clear();
this.onMaterialLoadedObservable.clear();
};
GLTFLoader.prototype._applyExtensions = function (actionAsync) {
for (var _i = 0, _a = GLTFLoader._Names; _i < _a.length; _i++) {
var name_4 = _a[_i];
var extension = this._extensions[name_4];
if (extension.enabled) {
var promise = actionAsync(extension);
if (promise) {
return promise;
}
}
}
return null;
};
GLTFLoader._Names = new Array();
GLTFLoader._Factories = {};
return GLTFLoader;
}());
GLTF2.GLTFLoader = GLTFLoader;
BABYLON.GLTFFileLoader.CreateGLTFLoaderV2 = function () { return new GLTFLoader(); };
})(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.glTFLoader.js.map
///
var BABYLON;
(function (BABYLON) {
var GLTF2;
(function (GLTF2) {
var GLTFLoaderExtension = /** @class */ (function () {
function GLTFLoaderExtension(loader) {
this.enabled = true;
this._loader = loader;
}
GLTFLoaderExtension.prototype.dispose = function () {
delete this._loader;
};
// #region Overridable Methods
/** Override this method to modify the default behavior for loading scenes. */
GLTFLoaderExtension.prototype._loadSceneAsync = function (context, node) { return null; };
/** Override this method to modify the default behavior for loading nodes. */
GLTFLoaderExtension.prototype._loadNodeAsync = function (context, node) { return null; };
/** Override this method to modify the default behavior for loading mesh primitive vertex data. */
GLTFLoaderExtension.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) { return null; };
/** Override this method to modify the default behavior for loading materials. */
GLTFLoaderExtension.prototype._loadMaterialAsync = function (context, material, babylonMesh, assign) { return null; };
/** Override this method to modify the default behavior for loading uris. */
GLTFLoaderExtension.prototype._loadUriAsync = function (context, uri) { return null; };
// #endregion
/** Helper method called by a loader extension to load an glTF extension. */
GLTFLoaderExtension.prototype._loadExtensionAsync = function (context, property, actionAsync) {
if (!property.extensions) {
return null;
}
var extensions = property.extensions;
var extension = extensions[this.name];
if (!extension) {
return null;
}
// Clear out the extension before executing the action to avoid recursing into the same property.
delete extensions[this.name];
try {
return actionAsync(context + "/extensions/" + this.name, extension);
}
finally {
// Restore the extension after executing the action.
extensions[this.name] = extension;
}
};
/** Helper method called by the loader to allow extensions to override loading scenes. */
GLTFLoaderExtension._LoadSceneAsync = function (loader, context, scene) {
return loader._applyExtensions(function (extension) { return extension._loadSceneAsync(context, scene); });
};
/** Helper method called by the loader to allow extensions to override loading nodes. */
GLTFLoaderExtension._LoadNodeAsync = function (loader, context, node) {
return loader._applyExtensions(function (extension) { return extension._loadNodeAsync(context, node); });
};
/** Helper method called by the loader to allow extensions to override loading mesh primitive vertex data. */
GLTFLoaderExtension._LoadVertexDataAsync = function (loader, context, primitive, babylonMesh) {
return loader._applyExtensions(function (extension) { return extension._loadVertexDataAsync(context, primitive, babylonMesh); });
};
/** Helper method called by the loader to allow extensions to override loading materials. */
GLTFLoaderExtension._LoadMaterialAsync = function (loader, context, material, babylonMesh, assign) {
return loader._applyExtensions(function (extension) { return extension._loadMaterialAsync(context, material, babylonMesh, assign); });
};
/** Helper method called by the loader to allow extensions to override loading uris. */
GLTFLoaderExtension._LoadUriAsync = function (loader, context, uri) {
return loader._applyExtensions(function (extension) { return extension._loadUriAsync(context, uri); });
};
return GLTFLoaderExtension;
}());
GLTF2.GLTFLoaderExtension = GLTFLoaderExtension;
})(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=babylon.glTFLoaderExtension.js.map
///
var BABYLON;
(function (BABYLON) {
var GLTF2;
(function (GLTF2) {
var Extensions;
(function (Extensions) {
// https://github.com/sbtron/glTF/tree/MSFT_lod/extensions/Vendor/MSFT_lod
var NAME = "MSFT_lod";
var MSFT_lod = /** @class */ (function (_super) {
__extends(MSFT_lod, _super);
function MSFT_lod() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.name = NAME;
/**
* Maximum number of LODs to load, starting from the lowest LOD.
*/
_this.maxLODsToLoad = Number.MAX_VALUE;
_this._loadingNodeLOD = null;
_this._loadNodeSignals = {};
_this._loadingMaterialLOD = null;
_this._loadMaterialSignals = {};
return _this;
}
MSFT_lod.prototype._loadNodeAsync = function (context, node) {
var _this = this;
return this._loadExtensionAsync(context, node, function (context, extension) {
var firstPromise;
var nodeLODs = _this._getLODs(context, node, _this._loader._gltf.nodes, extension.ids);
var _loop_1 = function (indexLOD) {
var nodeLOD = nodeLODs[indexLOD];
if (indexLOD !== 0) {
_this._loadingNodeLOD = nodeLOD;
if (!_this._loadNodeSignals[nodeLOD._index]) {
_this._loadNodeSignals[nodeLOD._index] = new BABYLON.Deferred();
}
}
var promise = _this._loader._loadNodeAsync("#/nodes/" + nodeLOD._index, nodeLOD).then(function () {
if (indexLOD !== 0) {
var previousNodeLOD = nodeLODs[indexLOD - 1];
if (previousNodeLOD._babylonMesh) {
previousNodeLOD._babylonMesh.dispose();
delete previousNodeLOD._babylonMesh;
}
}
if (indexLOD !== nodeLODs.length - 1) {
var nodeIndex = nodeLODs[indexLOD + 1]._index;
if (_this._loadNodeSignals[nodeIndex]) {
_this._loadNodeSignals[nodeIndex].resolve();
delete _this._loadNodeSignals[nodeIndex];
}
}
});
if (indexLOD === 0) {
firstPromise = promise;
}
else {
_this._loader._completePromises.push(promise);
_this._loadingNodeLOD = null;
}
};
for (var indexLOD = 0; indexLOD < nodeLODs.length; indexLOD++) {
_loop_1(indexLOD);
}
return firstPromise;
});
};
MSFT_lod.prototype._loadMaterialAsync = function (context, material, babylonMesh, assign) {
var _this = this;
// Don't load material LODs if already loading a node LOD.
if (this._loadingNodeLOD) {
return null;
}
return this._loadExtensionAsync(context, material, function (context, extension) {
var firstPromise;
var materialLODs = _this._getLODs(context, material, _this._loader._gltf.materials, extension.ids);
var _loop_2 = function (indexLOD) {
var materialLOD = materialLODs[indexLOD];
if (indexLOD !== 0) {
_this._loadingMaterialLOD = materialLOD;
if (!_this._loadMaterialSignals[materialLOD._index]) {
_this._loadMaterialSignals[materialLOD._index] = new BABYLON.Deferred();
}
}
var promise = _this._loader._loadMaterialAsync("#/materials/" + materialLOD._index, materialLOD, babylonMesh, indexLOD === 0 ? assign : function () { }).then(function () {
if (indexLOD !== 0) {
assign(materialLOD._babylonMaterial);
var previousMaterialLOD = materialLODs[indexLOD - 1];
if (previousMaterialLOD._babylonMaterial) {
previousMaterialLOD._babylonMaterial.dispose();
delete previousMaterialLOD._babylonMaterial;
}
}
if (indexLOD !== materialLODs.length - 1) {
var materialIndex = materialLODs[indexLOD + 1]._index;
if (_this._loadMaterialSignals[materialIndex]) {
_this._loadMaterialSignals[materialIndex].resolve();
delete _this._loadMaterialSignals[materialIndex];
}
}
});
if (indexLOD === 0) {
firstPromise = promise;
}
else {
_this._loader._completePromises.push(promise);
_this._loadingMaterialLOD = null;
}
};
for (var indexLOD = 0; indexLOD < materialLODs.length; indexLOD++) {
_loop_2(indexLOD);
}
return firstPromise;
});
};
MSFT_lod.prototype._loadUriAsync = function (context, uri) {
var _this = this;
// Defer the loading of uris if loading a material or node LOD.
if (this._loadingMaterialLOD) {
var index = this._loadingMaterialLOD._index;
return this._loadMaterialSignals[index].promise.then(function () {
return _this._loader._loadUriAsync(context, uri);
});
}
else if (this._loadingNodeLOD) {
var index = this._loadingNodeLOD._index;
return this._loadNodeSignals[index].promise.then(function () {
return _this._loader._loadUriAsync(context, uri);
});
}
return null;
};
/**
* Gets an array of LOD properties from lowest to highest.
*/
MSFT_lod.prototype._getLODs = function (context, property, array, ids) {
if (this.maxLODsToLoad <= 0) {
throw new Error("maxLODsToLoad must be greater than zero");
}
var properties = new Array();
for (var i = ids.length - 1; i >= 0; i--) {
properties.push(GLTF2.GLTFLoader._GetProperty(context + "/ids/" + ids[i], array, ids[i]));
if (properties.length === this.maxLODsToLoad) {
return properties;
}
}
properties.push(property);
return properties;
};
return MSFT_lod;
}(GLTF2.GLTFLoaderExtension));
Extensions.MSFT_lod = MSFT_lod;
GLTF2.GLTFLoader._Register(NAME, function (loader) { return new MSFT_lod(loader); });
})(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
})(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=MSFT_lod.js.map
///
var BABYLON;
(function (BABYLON) {
var GLTF2;
(function (GLTF2) {
var Extensions;
(function (Extensions) {
// https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression
var NAME = "KHR_draco_mesh_compression";
var KHR_draco_mesh_compression = /** @class */ (function (_super) {
__extends(KHR_draco_mesh_compression, _super);
function KHR_draco_mesh_compression(loader) {
var _this = _super.call(this, loader) || this;
_this.name = NAME;
_this._dracoCompression = null;
// Disable extension if decoder is not available.
if (!BABYLON.DracoCompression.DecoderUrl) {
_this.enabled = false;
}
return _this;
}
KHR_draco_mesh_compression.prototype.dispose = function () {
if (this._dracoCompression) {
this._dracoCompression.dispose();
}
_super.prototype.dispose.call(this);
};
KHR_draco_mesh_compression.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) {
var _this = this;
return this._loadExtensionAsync(context, primitive, function (extensionContext, extension) {
if (primitive.mode != undefined) {
if (primitive.mode !== 5 /* TRIANGLE_STRIP */ &&
primitive.mode !== 4 /* TRIANGLES */) {
throw new Error(context + ": Unsupported mode " + primitive.mode);
}
// TODO: handle triangle strips
if (primitive.mode === 5 /* TRIANGLE_STRIP */) {
throw new Error(context + ": Mode " + primitive.mode + " is not currently supported");
}
}
var attributes = {};
var loadAttribute = function (name, kind) {
var uniqueId = extension.attributes[name];
if (uniqueId == undefined) {
return;
}
babylonMesh._delayInfo = babylonMesh._delayInfo || [];
if (babylonMesh._delayInfo.indexOf(kind) === -1) {
babylonMesh._delayInfo.push(kind);
}
attributes[kind] = uniqueId;
};
loadAttribute("POSITION", BABYLON.VertexBuffer.PositionKind);
loadAttribute("NORMAL", BABYLON.VertexBuffer.NormalKind);
loadAttribute("TANGENT", BABYLON.VertexBuffer.TangentKind);
loadAttribute("TEXCOORD_0", BABYLON.VertexBuffer.UVKind);
loadAttribute("TEXCOORD_1", BABYLON.VertexBuffer.UV2Kind);
loadAttribute("JOINTS_0", BABYLON.VertexBuffer.MatricesIndicesKind);
loadAttribute("WEIGHTS_0", BABYLON.VertexBuffer.MatricesWeightsKind);
loadAttribute("COLOR_0", BABYLON.VertexBuffer.ColorKind);
var bufferView = GLTF2.GLTFLoader._GetProperty(extensionContext, _this._loader._gltf.bufferViews, extension.bufferView);
return _this._loader._loadBufferViewAsync("#/bufferViews/" + bufferView._index, bufferView).then(function (data) {
try {
if (!_this._dracoCompression) {
_this._dracoCompression = new BABYLON.DracoCompression();
}
return _this._dracoCompression.decodeMeshAsync(data, attributes);
}
catch (e) {
throw new Error(context + ": " + e.message);
}
});
});
};
return KHR_draco_mesh_compression;
}(GLTF2.GLTFLoaderExtension));
Extensions.KHR_draco_mesh_compression = KHR_draco_mesh_compression;
GLTF2.GLTFLoader._Register(NAME, function (loader) { return new KHR_draco_mesh_compression(loader); });
})(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
})(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=KHR_draco_mesh_compression.js.map
///
var BABYLON;
(function (BABYLON) {
var GLTF2;
(function (GLTF2) {
var Extensions;
(function (Extensions) {
// https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness
var NAME = "KHR_materials_pbrSpecularGlossiness";
var KHR_materials_pbrSpecularGlossiness = /** @class */ (function (_super) {
__extends(KHR_materials_pbrSpecularGlossiness, _super);
function KHR_materials_pbrSpecularGlossiness() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.name = NAME;
return _this;
}
KHR_materials_pbrSpecularGlossiness.prototype._loadMaterialAsync = function (context, material, babylonMesh, assign) {
var _this = this;
return this._loadExtensionAsync(context, material, function (context, extension) {
material._babylonMeshes = material._babylonMeshes || [];
material._babylonMeshes.push(babylonMesh);
if (!material._loaded) {
var promises = new Array();
var babylonMaterial = _this._loader._createMaterial(material);
material._babylonMaterial = babylonMaterial;
promises.push(_this._loader._loadMaterialBasePropertiesAsync(context, material));
promises.push(_this._loadSpecularGlossinessPropertiesAsync(context, material, extension));
_this._loader.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
material._loaded = Promise.all(promises).then(function () { });
}
assign(material._babylonMaterial);
return material._loaded;
});
};
KHR_materials_pbrSpecularGlossiness.prototype._loadSpecularGlossinessPropertiesAsync = function (context, material, properties) {
var promises = new Array();
var babylonMaterial = material._babylonMaterial;
if (properties.diffuseFactor) {
babylonMaterial.albedoColor = BABYLON.Color3.FromArray(properties.diffuseFactor);
babylonMaterial.alpha = properties.diffuseFactor[3];
}
else {
babylonMaterial.albedoColor = BABYLON.Color3.White();
}
babylonMaterial.reflectivityColor = properties.specularFactor ? BABYLON.Color3.FromArray(properties.specularFactor) : BABYLON.Color3.White();
babylonMaterial.microSurface = properties.glossinessFactor == undefined ? 1 : properties.glossinessFactor;
if (properties.diffuseTexture) {
promises.push(this._loader._loadTextureAsync(context + "/diffuseTexture", properties.diffuseTexture, function (texture) {
babylonMaterial.albedoTexture = texture;
}));
}
if (properties.specularGlossinessTexture) {
promises.push(this._loader._loadTextureAsync(context + "/specularGlossinessTexture", properties.specularGlossinessTexture, function (texture) {
babylonMaterial.reflectivityTexture = texture;
}));
babylonMaterial.reflectivityTexture.hasAlpha = true;
babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
}
this._loader._loadMaterialAlphaProperties(context, material);
return Promise.all(promises).then(function () { });
};
return KHR_materials_pbrSpecularGlossiness;
}(GLTF2.GLTFLoaderExtension));
Extensions.KHR_materials_pbrSpecularGlossiness = KHR_materials_pbrSpecularGlossiness;
GLTF2.GLTFLoader._Register(NAME, function (loader) { return new KHR_materials_pbrSpecularGlossiness(loader); });
})(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
})(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=KHR_materials_pbrSpecularGlossiness.js.map
///
var BABYLON;
(function (BABYLON) {
var GLTF2;
(function (GLTF2) {
var Extensions;
(function (Extensions) {
// https://github.com/MiiBond/glTF/tree/khr_lights_v1/extensions/Khronos/KHR_lights
var NAME = "KHR_lights";
var LightType;
(function (LightType) {
LightType["AMBIENT"] = "ambient";
LightType["DIRECTIONAL"] = "directional";
LightType["POINT"] = "point";
LightType["SPOT"] = "spot";
})(LightType || (LightType = {}));
var KHR_lights = /** @class */ (function (_super) {
__extends(KHR_lights, _super);
function KHR_lights() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.name = NAME;
return _this;
}
KHR_lights.prototype._loadSceneAsync = function (context, scene) {
var _this = this;
return this._loadExtensionAsync(context, scene, function (context, extension) {
var promise = _this._loader._loadSceneAsync(context, scene);
var light = GLTF2.GLTFLoader._GetProperty(context, _this._lights, extension.light);
if (light.type !== LightType.AMBIENT) {
throw new Error(context + ": Only ambient lights are allowed on a scene");
}
_this._loader._babylonScene.ambientColor = light.color ? BABYLON.Color3.FromArray(light.color) : BABYLON.Color3.Black();
return promise;
});
};
KHR_lights.prototype._loadNodeAsync = function (context, node) {
var _this = this;
return this._loadExtensionAsync(context, node, function (context, extension) {
var promise = _this._loader._loadNodeAsync(context, node);
var babylonLight;
var light = GLTF2.GLTFLoader._GetProperty(context, _this._lights, extension.light);
var name = node._babylonMesh.name;
switch (light.type) {
case LightType.AMBIENT: {
throw new Error(context + ": Ambient lights are not allowed on a node");
}
case LightType.DIRECTIONAL: {
babylonLight = new BABYLON.DirectionalLight(name, BABYLON.Vector3.Forward(), _this._loader._babylonScene);
break;
}
case LightType.POINT: {
babylonLight = new BABYLON.PointLight(name, BABYLON.Vector3.Zero(), _this._loader._babylonScene);
break;
}
case LightType.SPOT: {
var spotLight = light;
// TODO: support inner and outer cone angles
//const innerConeAngle = spotLight.innerConeAngle || 0;
var outerConeAngle = spotLight.outerConeAngle || Math.PI / 4;
babylonLight = new BABYLON.SpotLight(name, BABYLON.Vector3.Zero(), BABYLON.Vector3.Forward(), outerConeAngle, 2, _this._loader._babylonScene);
break;
}
default: {
throw new Error(context + ": Invalid light type (" + light.type + ")");
}
}
babylonLight.diffuse = light.color ? BABYLON.Color3.FromArray(light.color) : BABYLON.Color3.White();
babylonLight.intensity = light.intensity == undefined ? 1 : light.intensity;
babylonLight.parent = node._babylonMesh;
return promise;
});
};
Object.defineProperty(KHR_lights.prototype, "_lights", {
get: function () {
var extensions = this._loader._gltf.extensions;
if (!extensions || !extensions[this.name]) {
throw new Error("#/extensions: '" + this.name + "' not found");
}
var extension = extensions[this.name];
return extension.lights;
},
enumerable: true,
configurable: true
});
return KHR_lights;
}(GLTF2.GLTFLoaderExtension));
Extensions.KHR_lights = KHR_lights;
GLTF2.GLTFLoader._Register(NAME, function (loader) { return new KHR_lights(loader); });
})(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
})(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
})(BABYLON || (BABYLON = {}));
//# sourceMappingURL=KHR_lights.js.map
var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : this);
globalObject["BABYLON"] = BABYLON
return BABYLON;
});