@openhps/core
Version:
Open Hybrid Positioning System - Core component
207 lines (192 loc) • 5.93 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _Matrix = require("../../math/Matrix3.js");
var _Plane = require("../../math/Plane.js");
var _Vector = require("../../math/Vector4.js");
const _plane = /*@__PURE__*/new _Plane.Plane();
/**
* Represents the state that is used to perform clipping via clipping planes.
* There is a default clipping context for each render context. When the
* scene holds instances of `ClippingGroup`, there will be a context for each
* group.
*
* @private
*/
class ClippingContext {
/**
* Constructs a new clipping context.
*
* @param {?ClippingContext} [parentContext=null] - A reference to the parent clipping context.
*/
constructor(parentContext = null) {
/**
* The clipping context's version.
*
* @type {number}
* @readonly
*/
this.version = 0;
/**
* Whether the intersection of the clipping planes is used to clip objects, rather than their union.
*
* @type {?boolean}
* @default null
*/
this.clipIntersection = null;
/**
* The clipping context's cache key.
*
* @type {string}
*/
this.cacheKey = '';
/**
* Whether the shadow pass is active or not.
*
* @type {boolean}
* @default false
*/
this.shadowPass = false;
/**
* The view normal matrix.
*
* @type {Matrix3}
*/
this.viewNormalMatrix = new _Matrix.Matrix3();
/**
* Internal cache for maintaining clipping contexts.
*
* @type {WeakMap<ClippingGroup,ClippingContext>}
*/
this.clippingGroupContexts = new WeakMap();
/**
* The intersection planes.
*
* @type {Array<Vector4>}
*/
this.intersectionPlanes = [];
/**
* The intersection planes.
*
* @type {Array<Vector4>}
*/
this.unionPlanes = [];
/**
* The version of the clipping context's parent context.
*
* @type {?number}
* @readonly
*/
this.parentVersion = null;
if (parentContext !== null) {
this.viewNormalMatrix = parentContext.viewNormalMatrix;
this.clippingGroupContexts = parentContext.clippingGroupContexts;
this.shadowPass = parentContext.shadowPass;
this.viewMatrix = parentContext.viewMatrix;
}
}
/**
* Projects the given source clipping planes and writes the result into the
* destination array.
*
* @param {Array<Plane>} source - The source clipping planes.
* @param {Array<Vector4>} destination - The destination.
* @param {number} offset - The offset.
*/
projectPlanes(source, destination, offset) {
const l = source.length;
for (let i = 0; i < l; i++) {
_plane.copy(source[i]).applyMatrix4(this.viewMatrix, this.viewNormalMatrix);
const v = destination[offset + i];
const normal = _plane.normal;
v.x = -normal.x;
v.y = -normal.y;
v.z = -normal.z;
v.w = _plane.constant;
}
}
/**
* Updates the root clipping context of a scene.
*
* @param {Scene} scene - The scene.
* @param {Camera} camera - The camera that is used to render the scene.
*/
updateGlobal(scene, camera) {
this.shadowPass = scene.overrideMaterial !== null && scene.overrideMaterial.isShadowPassMaterial;
this.viewMatrix = camera.matrixWorldInverse;
this.viewNormalMatrix.getNormalMatrix(this.viewMatrix);
}
/**
* Updates the clipping context.
*
* @param {ClippingContext} parentContext - The parent context.
* @param {ClippingGroup} clippingGroup - The clipping group this context belongs to.
*/
update(parentContext, clippingGroup) {
let update = false;
if (parentContext.version !== this.parentVersion) {
this.intersectionPlanes = Array.from(parentContext.intersectionPlanes);
this.unionPlanes = Array.from(parentContext.unionPlanes);
this.parentVersion = parentContext.version;
}
if (this.clipIntersection !== clippingGroup.clipIntersection) {
this.clipIntersection = clippingGroup.clipIntersection;
if (this.clipIntersection) {
this.unionPlanes.length = parentContext.unionPlanes.length;
} else {
this.intersectionPlanes.length = parentContext.intersectionPlanes.length;
}
}
const srcClippingPlanes = clippingGroup.clippingPlanes;
const l = srcClippingPlanes.length;
let dstClippingPlanes;
let offset;
if (this.clipIntersection) {
dstClippingPlanes = this.intersectionPlanes;
offset = parentContext.intersectionPlanes.length;
} else {
dstClippingPlanes = this.unionPlanes;
offset = parentContext.unionPlanes.length;
}
if (dstClippingPlanes.length !== offset + l) {
dstClippingPlanes.length = offset + l;
for (let i = 0; i < l; i++) {
dstClippingPlanes[offset + i] = new _Vector.Vector4();
}
update = true;
}
this.projectPlanes(srcClippingPlanes, dstClippingPlanes, offset);
if (update) {
this.version++;
this.cacheKey = `${this.intersectionPlanes.length}:${this.unionPlanes.length}`;
}
}
/**
* Returns a clipping context for the given clipping group.
*
* @param {ClippingGroup} clippingGroup - The clipping group.
* @return {ClippingContext} The clipping context.
*/
getGroupContext(clippingGroup) {
if (this.shadowPass && !clippingGroup.clipShadows) return this;
let context = this.clippingGroupContexts.get(clippingGroup);
if (context === undefined) {
context = new ClippingContext(this);
this.clippingGroupContexts.set(clippingGroup, context);
}
context.update(this, clippingGroup);
return context;
}
/**
* The count of union clipping planes.
*
* @type {number}
* @readonly
*/
get unionClippingCount() {
return this.unionPlanes.length;
}
}
var _default = exports.default = ClippingContext;