Initial project import
This commit is contained in:
637
node_modules/three-stdlib/utils/BufferGeometryUtils.cjs
generated
vendored
Normal file
637
node_modules/three-stdlib/utils/BufferGeometryUtils.cjs
generated
vendored
Normal file
@@ -0,0 +1,637 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
||||
const THREE = require("three");
|
||||
const helpers = require("../types/helpers.cjs");
|
||||
const mergeBufferGeometries = (geometries, useGroups) => {
|
||||
const isIndexed = geometries[0].index !== null;
|
||||
const attributesUsed = new Set(Object.keys(geometries[0].attributes));
|
||||
const morphAttributesUsed = new Set(Object.keys(geometries[0].morphAttributes));
|
||||
const attributes = {};
|
||||
const morphAttributes = {};
|
||||
const morphTargetsRelative = geometries[0].morphTargetsRelative;
|
||||
const mergedGeometry = new THREE.BufferGeometry();
|
||||
let offset = 0;
|
||||
geometries.forEach((geom, i) => {
|
||||
let attributesCount = 0;
|
||||
if (isIndexed !== (geom.index !== null)) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index " + i + ". All geometries must have compatible attributes; make sure index attribute exists among all geometries, or in none of them."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
for (let name in geom.attributes) {
|
||||
if (!attributesUsed.has(name)) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index " + i + '. All geometries must have compatible attributes; make sure "' + name + '" attribute exists among all geometries, or in none of them.'
|
||||
);
|
||||
return null;
|
||||
}
|
||||
if (attributes[name] === void 0) {
|
||||
attributes[name] = [];
|
||||
}
|
||||
attributes[name].push(geom.attributes[name]);
|
||||
attributesCount++;
|
||||
}
|
||||
if (attributesCount !== attributesUsed.size) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index " + i + ". Make sure all geometries have the same number of attributes."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
if (morphTargetsRelative !== geom.morphTargetsRelative) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index " + i + ". .morphTargetsRelative must be consistent throughout all geometries."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
for (let name in geom.morphAttributes) {
|
||||
if (!morphAttributesUsed.has(name)) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index " + i + ". .morphAttributes must be consistent throughout all geometries."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
if (morphAttributes[name] === void 0)
|
||||
morphAttributes[name] = [];
|
||||
morphAttributes[name].push(geom.morphAttributes[name]);
|
||||
}
|
||||
mergedGeometry.userData.mergedUserData = mergedGeometry.userData.mergedUserData || [];
|
||||
mergedGeometry.userData.mergedUserData.push(geom.userData);
|
||||
if (useGroups) {
|
||||
let count;
|
||||
if (geom.index) {
|
||||
count = geom.index.count;
|
||||
} else if (geom.attributes.position !== void 0) {
|
||||
count = geom.attributes.position.count;
|
||||
} else {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index " + i + ". The geometry must have either an index or a position attribute"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
mergedGeometry.addGroup(offset, count, i);
|
||||
offset += count;
|
||||
}
|
||||
});
|
||||
if (isIndexed) {
|
||||
let indexOffset = 0;
|
||||
const mergedIndex = [];
|
||||
geometries.forEach((geom) => {
|
||||
const index = geom.index;
|
||||
for (let j = 0; j < index.count; ++j) {
|
||||
mergedIndex.push(index.getX(j) + indexOffset);
|
||||
}
|
||||
indexOffset += geom.attributes.position.count;
|
||||
});
|
||||
mergedGeometry.setIndex(mergedIndex);
|
||||
}
|
||||
for (let name in attributes) {
|
||||
const mergedAttribute = mergeBufferAttributes(attributes[name]);
|
||||
if (!mergedAttribute) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed while trying to merge the " + name + " attribute."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
mergedGeometry.setAttribute(name, mergedAttribute);
|
||||
}
|
||||
for (let name in morphAttributes) {
|
||||
const numMorphTargets = morphAttributes[name][0].length;
|
||||
if (numMorphTargets === 0)
|
||||
break;
|
||||
mergedGeometry.morphAttributes = mergedGeometry.morphAttributes || {};
|
||||
mergedGeometry.morphAttributes[name] = [];
|
||||
for (let i = 0; i < numMorphTargets; ++i) {
|
||||
const morphAttributesToMerge = [];
|
||||
for (let j = 0; j < morphAttributes[name].length; ++j) {
|
||||
morphAttributesToMerge.push(morphAttributes[name][j][i]);
|
||||
}
|
||||
const mergedMorphAttribute = mergeBufferAttributes(morphAttributesToMerge);
|
||||
if (!mergedMorphAttribute) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed while trying to merge the " + name + " morphAttribute."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
mergedGeometry.morphAttributes[name].push(mergedMorphAttribute);
|
||||
}
|
||||
}
|
||||
return mergedGeometry;
|
||||
};
|
||||
const mergeBufferAttributes = (attributes) => {
|
||||
let TypedArray = void 0;
|
||||
let itemSize = void 0;
|
||||
let normalized = void 0;
|
||||
let arrayLength = 0;
|
||||
attributes.forEach((attr) => {
|
||||
if (TypedArray === void 0) {
|
||||
TypedArray = attr.array.constructor;
|
||||
}
|
||||
if (TypedArray !== attr.array.constructor) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. BufferAttribute.array must be of consistent array types across matching attributes."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
if (itemSize === void 0)
|
||||
itemSize = attr.itemSize;
|
||||
if (itemSize !== attr.itemSize) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. BufferAttribute.itemSize must be consistent across matching attributes."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
if (normalized === void 0)
|
||||
normalized = attr.normalized;
|
||||
if (normalized !== attr.normalized) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. BufferAttribute.normalized must be consistent across matching attributes."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
arrayLength += attr.array.length;
|
||||
});
|
||||
if (TypedArray && itemSize) {
|
||||
const array = new TypedArray(arrayLength);
|
||||
let offset = 0;
|
||||
attributes.forEach((attr) => {
|
||||
array.set(attr.array, offset);
|
||||
offset += attr.array.length;
|
||||
});
|
||||
return new THREE.BufferAttribute(array, itemSize, normalized);
|
||||
}
|
||||
};
|
||||
const interleaveAttributes = (attributes) => {
|
||||
let TypedArray = void 0;
|
||||
let arrayLength = 0;
|
||||
let stride = 0;
|
||||
for (let i = 0, l = attributes.length; i < l; ++i) {
|
||||
const attribute = attributes[i];
|
||||
if (TypedArray === void 0)
|
||||
TypedArray = attribute.array.constructor;
|
||||
if (TypedArray !== attribute.array.constructor) {
|
||||
console.error("AttributeBuffers of different types cannot be interleaved");
|
||||
return null;
|
||||
}
|
||||
arrayLength += attribute.array.length;
|
||||
stride += attribute.itemSize;
|
||||
}
|
||||
const interleavedBuffer = new THREE.InterleavedBuffer(new TypedArray(arrayLength), stride);
|
||||
let offset = 0;
|
||||
const res = [];
|
||||
const getters = ["getX", "getY", "getZ", "getW"];
|
||||
const setters = ["setX", "setY", "setZ", "setW"];
|
||||
for (let j = 0, l = attributes.length; j < l; j++) {
|
||||
const attribute = attributes[j];
|
||||
const itemSize = attribute.itemSize;
|
||||
const count = attribute.count;
|
||||
const iba = new THREE.InterleavedBufferAttribute(interleavedBuffer, itemSize, offset, attribute.normalized);
|
||||
res.push(iba);
|
||||
offset += itemSize;
|
||||
for (let c = 0; c < count; c++) {
|
||||
for (let k = 0; k < itemSize; k++) {
|
||||
const set = helpers.getWithKey(iba, setters[k]);
|
||||
const get = helpers.getWithKey(attribute, getters[k]);
|
||||
set(c, get(c));
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
};
|
||||
function estimateBytesUsed(geometry) {
|
||||
let mem = 0;
|
||||
for (let name in geometry.attributes) {
|
||||
const attr = geometry.getAttribute(name);
|
||||
mem += attr.count * attr.itemSize * attr.array.BYTES_PER_ELEMENT;
|
||||
}
|
||||
const indices = geometry.getIndex();
|
||||
mem += indices ? indices.count * indices.itemSize * indices.array.BYTES_PER_ELEMENT : 0;
|
||||
return mem;
|
||||
}
|
||||
function mergeVertices(geometry, tolerance = 1e-4) {
|
||||
tolerance = Math.max(tolerance, Number.EPSILON);
|
||||
const hashToIndex = {};
|
||||
const indices = geometry.getIndex();
|
||||
const positions = geometry.getAttribute("position");
|
||||
const vertexCount = indices ? indices.count : positions.count;
|
||||
let nextIndex = 0;
|
||||
const attributeNames = Object.keys(geometry.attributes);
|
||||
const attrArrays = {};
|
||||
const morphAttrsArrays = {};
|
||||
const newIndices = [];
|
||||
const getters = ["getX", "getY", "getZ", "getW"];
|
||||
for (let i = 0, l = attributeNames.length; i < l; i++) {
|
||||
const name = attributeNames[i];
|
||||
attrArrays[name] = [];
|
||||
const morphAttr = geometry.morphAttributes[name];
|
||||
if (morphAttr) {
|
||||
morphAttrsArrays[name] = new Array(morphAttr.length).fill(0).map(() => []);
|
||||
}
|
||||
}
|
||||
const decimalShift = Math.log10(1 / tolerance);
|
||||
const shiftMultiplier = Math.pow(10, decimalShift);
|
||||
for (let i = 0; i < vertexCount; i++) {
|
||||
const index = indices ? indices.getX(i) : i;
|
||||
let hash = "";
|
||||
for (let j = 0, l = attributeNames.length; j < l; j++) {
|
||||
const name = attributeNames[j];
|
||||
const attribute = geometry.getAttribute(name);
|
||||
const itemSize = attribute.itemSize;
|
||||
for (let k = 0; k < itemSize; k++) {
|
||||
hash += `${~~(attribute[getters[k]](index) * shiftMultiplier)},`;
|
||||
}
|
||||
}
|
||||
if (hash in hashToIndex) {
|
||||
newIndices.push(hashToIndex[hash]);
|
||||
} else {
|
||||
for (let j = 0, l = attributeNames.length; j < l; j++) {
|
||||
const name = attributeNames[j];
|
||||
const attribute = geometry.getAttribute(name);
|
||||
const morphAttr = geometry.morphAttributes[name];
|
||||
const itemSize = attribute.itemSize;
|
||||
const newarray = attrArrays[name];
|
||||
const newMorphArrays = morphAttrsArrays[name];
|
||||
for (let k = 0; k < itemSize; k++) {
|
||||
const getterFunc = getters[k];
|
||||
newarray.push(attribute[getterFunc](index));
|
||||
if (morphAttr) {
|
||||
for (let m = 0, ml = morphAttr.length; m < ml; m++) {
|
||||
newMorphArrays[m].push(morphAttr[m][getterFunc](index));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
hashToIndex[hash] = nextIndex;
|
||||
newIndices.push(nextIndex);
|
||||
nextIndex++;
|
||||
}
|
||||
}
|
||||
const result = geometry.clone();
|
||||
for (let i = 0, l = attributeNames.length; i < l; i++) {
|
||||
const name = attributeNames[i];
|
||||
const oldAttribute = geometry.getAttribute(name);
|
||||
const buffer = new oldAttribute.array.constructor(attrArrays[name]);
|
||||
const attribute = new THREE.BufferAttribute(buffer, oldAttribute.itemSize, oldAttribute.normalized);
|
||||
result.setAttribute(name, attribute);
|
||||
if (name in morphAttrsArrays) {
|
||||
for (let j = 0; j < morphAttrsArrays[name].length; j++) {
|
||||
const oldMorphAttribute = geometry.morphAttributes[name][j];
|
||||
const buffer2 = new oldMorphAttribute.array.constructor(morphAttrsArrays[name][j]);
|
||||
const morphAttribute = new THREE.BufferAttribute(buffer2, oldMorphAttribute.itemSize, oldMorphAttribute.normalized);
|
||||
result.morphAttributes[name][j] = morphAttribute;
|
||||
}
|
||||
}
|
||||
}
|
||||
result.setIndex(newIndices);
|
||||
return result;
|
||||
}
|
||||
function toTrianglesDrawMode(geometry, drawMode) {
|
||||
if (drawMode === THREE.TrianglesDrawMode) {
|
||||
console.warn("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles.");
|
||||
return geometry;
|
||||
}
|
||||
if (drawMode === THREE.TriangleFanDrawMode || drawMode === THREE.TriangleStripDrawMode) {
|
||||
let index = geometry.getIndex();
|
||||
if (index === null) {
|
||||
const indices = [];
|
||||
const position = geometry.getAttribute("position");
|
||||
if (position !== void 0) {
|
||||
for (let i = 0; i < position.count; i++) {
|
||||
indices.push(i);
|
||||
}
|
||||
geometry.setIndex(indices);
|
||||
index = geometry.getIndex();
|
||||
} else {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible."
|
||||
);
|
||||
return geometry;
|
||||
}
|
||||
}
|
||||
const numberOfTriangles = index.count - 2;
|
||||
const newIndices = [];
|
||||
if (index) {
|
||||
if (drawMode === THREE.TriangleFanDrawMode) {
|
||||
for (let i = 1; i <= numberOfTriangles; i++) {
|
||||
newIndices.push(index.getX(0));
|
||||
newIndices.push(index.getX(i));
|
||||
newIndices.push(index.getX(i + 1));
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < numberOfTriangles; i++) {
|
||||
if (i % 2 === 0) {
|
||||
newIndices.push(index.getX(i));
|
||||
newIndices.push(index.getX(i + 1));
|
||||
newIndices.push(index.getX(i + 2));
|
||||
} else {
|
||||
newIndices.push(index.getX(i + 2));
|
||||
newIndices.push(index.getX(i + 1));
|
||||
newIndices.push(index.getX(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newIndices.length / 3 !== numberOfTriangles) {
|
||||
console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles.");
|
||||
}
|
||||
const newGeometry = geometry.clone();
|
||||
newGeometry.setIndex(newIndices);
|
||||
newGeometry.clearGroups();
|
||||
return newGeometry;
|
||||
} else {
|
||||
console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:", drawMode);
|
||||
return geometry;
|
||||
}
|
||||
}
|
||||
function computeMorphedAttributes(object) {
|
||||
if (object.geometry.isBufferGeometry !== true) {
|
||||
console.error("THREE.BufferGeometryUtils: Geometry is not of type BufferGeometry.");
|
||||
return null;
|
||||
}
|
||||
const _vA = new THREE.Vector3();
|
||||
const _vB = new THREE.Vector3();
|
||||
const _vC = new THREE.Vector3();
|
||||
const _tempA = new THREE.Vector3();
|
||||
const _tempB = new THREE.Vector3();
|
||||
const _tempC = new THREE.Vector3();
|
||||
const _morphA = new THREE.Vector3();
|
||||
const _morphB = new THREE.Vector3();
|
||||
const _morphC = new THREE.Vector3();
|
||||
function _calculateMorphedAttributeData(object2, material2, attribute, morphAttribute, morphTargetsRelative2, a2, b2, c2, modifiedAttributeArray) {
|
||||
_vA.fromBufferAttribute(attribute, a2);
|
||||
_vB.fromBufferAttribute(attribute, b2);
|
||||
_vC.fromBufferAttribute(attribute, c2);
|
||||
const morphInfluences = object2.morphTargetInfluences;
|
||||
if (
|
||||
// @ts-ignore
|
||||
material2.morphTargets && morphAttribute && morphInfluences
|
||||
) {
|
||||
_morphA.set(0, 0, 0);
|
||||
_morphB.set(0, 0, 0);
|
||||
_morphC.set(0, 0, 0);
|
||||
for (let i2 = 0, il2 = morphAttribute.length; i2 < il2; i2++) {
|
||||
const influence = morphInfluences[i2];
|
||||
const morph = morphAttribute[i2];
|
||||
if (influence === 0)
|
||||
continue;
|
||||
_tempA.fromBufferAttribute(morph, a2);
|
||||
_tempB.fromBufferAttribute(morph, b2);
|
||||
_tempC.fromBufferAttribute(morph, c2);
|
||||
if (morphTargetsRelative2) {
|
||||
_morphA.addScaledVector(_tempA, influence);
|
||||
_morphB.addScaledVector(_tempB, influence);
|
||||
_morphC.addScaledVector(_tempC, influence);
|
||||
} else {
|
||||
_morphA.addScaledVector(_tempA.sub(_vA), influence);
|
||||
_morphB.addScaledVector(_tempB.sub(_vB), influence);
|
||||
_morphC.addScaledVector(_tempC.sub(_vC), influence);
|
||||
}
|
||||
}
|
||||
_vA.add(_morphA);
|
||||
_vB.add(_morphB);
|
||||
_vC.add(_morphC);
|
||||
}
|
||||
if (object2.isSkinnedMesh) {
|
||||
object2.boneTransform(a2, _vA);
|
||||
object2.boneTransform(b2, _vB);
|
||||
object2.boneTransform(c2, _vC);
|
||||
}
|
||||
modifiedAttributeArray[a2 * 3 + 0] = _vA.x;
|
||||
modifiedAttributeArray[a2 * 3 + 1] = _vA.y;
|
||||
modifiedAttributeArray[a2 * 3 + 2] = _vA.z;
|
||||
modifiedAttributeArray[b2 * 3 + 0] = _vB.x;
|
||||
modifiedAttributeArray[b2 * 3 + 1] = _vB.y;
|
||||
modifiedAttributeArray[b2 * 3 + 2] = _vB.z;
|
||||
modifiedAttributeArray[c2 * 3 + 0] = _vC.x;
|
||||
modifiedAttributeArray[c2 * 3 + 1] = _vC.y;
|
||||
modifiedAttributeArray[c2 * 3 + 2] = _vC.z;
|
||||
}
|
||||
const geometry = object.geometry;
|
||||
const material = object.material;
|
||||
let a, b, c;
|
||||
const index = geometry.index;
|
||||
const positionAttribute = geometry.attributes.position;
|
||||
const morphPosition = geometry.morphAttributes.position;
|
||||
const morphTargetsRelative = geometry.morphTargetsRelative;
|
||||
const normalAttribute = geometry.attributes.normal;
|
||||
const morphNormal = geometry.morphAttributes.position;
|
||||
const groups = geometry.groups;
|
||||
const drawRange = geometry.drawRange;
|
||||
let i, j, il, jl;
|
||||
let group, groupMaterial;
|
||||
let start, end;
|
||||
const modifiedPosition = new Float32Array(positionAttribute.count * positionAttribute.itemSize);
|
||||
const modifiedNormal = new Float32Array(normalAttribute.count * normalAttribute.itemSize);
|
||||
if (index !== null) {
|
||||
if (Array.isArray(material)) {
|
||||
for (i = 0, il = groups.length; i < il; i++) {
|
||||
group = groups[i];
|
||||
groupMaterial = material[group.materialIndex];
|
||||
start = Math.max(group.start, drawRange.start);
|
||||
end = Math.min(group.start + group.count, drawRange.start + drawRange.count);
|
||||
for (j = start, jl = end; j < jl; j += 3) {
|
||||
a = index.getX(j);
|
||||
b = index.getX(j + 1);
|
||||
c = index.getX(j + 2);
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
groupMaterial,
|
||||
positionAttribute,
|
||||
morphPosition,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedPosition
|
||||
);
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
groupMaterial,
|
||||
normalAttribute,
|
||||
morphNormal,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedNormal
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
start = Math.max(0, drawRange.start);
|
||||
end = Math.min(index.count, drawRange.start + drawRange.count);
|
||||
for (i = start, il = end; i < il; i += 3) {
|
||||
a = index.getX(i);
|
||||
b = index.getX(i + 1);
|
||||
c = index.getX(i + 2);
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
material,
|
||||
positionAttribute,
|
||||
morphPosition,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedPosition
|
||||
);
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
material,
|
||||
normalAttribute,
|
||||
morphNormal,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedNormal
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if (positionAttribute !== void 0) {
|
||||
if (Array.isArray(material)) {
|
||||
for (i = 0, il = groups.length; i < il; i++) {
|
||||
group = groups[i];
|
||||
groupMaterial = material[group.materialIndex];
|
||||
start = Math.max(group.start, drawRange.start);
|
||||
end = Math.min(group.start + group.count, drawRange.start + drawRange.count);
|
||||
for (j = start, jl = end; j < jl; j += 3) {
|
||||
a = j;
|
||||
b = j + 1;
|
||||
c = j + 2;
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
groupMaterial,
|
||||
positionAttribute,
|
||||
morphPosition,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedPosition
|
||||
);
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
groupMaterial,
|
||||
normalAttribute,
|
||||
morphNormal,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedNormal
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
start = Math.max(0, drawRange.start);
|
||||
end = Math.min(positionAttribute.count, drawRange.start + drawRange.count);
|
||||
for (i = start, il = end; i < il; i += 3) {
|
||||
a = i;
|
||||
b = i + 1;
|
||||
c = i + 2;
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
material,
|
||||
positionAttribute,
|
||||
morphPosition,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedPosition
|
||||
);
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
material,
|
||||
normalAttribute,
|
||||
morphNormal,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedNormal
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
const morphedPositionAttribute = new THREE.Float32BufferAttribute(modifiedPosition, 3);
|
||||
const morphedNormalAttribute = new THREE.Float32BufferAttribute(modifiedNormal, 3);
|
||||
return {
|
||||
positionAttribute,
|
||||
normalAttribute,
|
||||
morphedPositionAttribute,
|
||||
morphedNormalAttribute
|
||||
};
|
||||
}
|
||||
function toCreasedNormals(geometry, creaseAngle = Math.PI / 3) {
|
||||
const creaseDot = Math.cos(creaseAngle);
|
||||
const hashMultiplier = (1 + 1e-10) * 100;
|
||||
const verts = [new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3()];
|
||||
const tempVec1 = new THREE.Vector3();
|
||||
const tempVec2 = new THREE.Vector3();
|
||||
const tempNorm = new THREE.Vector3();
|
||||
const tempNorm2 = new THREE.Vector3();
|
||||
function hashVertex(v) {
|
||||
const x = ~~(v.x * hashMultiplier);
|
||||
const y = ~~(v.y * hashMultiplier);
|
||||
const z = ~~(v.z * hashMultiplier);
|
||||
return `${x},${y},${z}`;
|
||||
}
|
||||
const resultGeometry = geometry.index ? geometry.toNonIndexed() : geometry;
|
||||
const posAttr = resultGeometry.attributes.position;
|
||||
const vertexMap = {};
|
||||
for (let i = 0, l = posAttr.count / 3; i < l; i++) {
|
||||
const i3 = 3 * i;
|
||||
const a = verts[0].fromBufferAttribute(posAttr, i3 + 0);
|
||||
const b = verts[1].fromBufferAttribute(posAttr, i3 + 1);
|
||||
const c = verts[2].fromBufferAttribute(posAttr, i3 + 2);
|
||||
tempVec1.subVectors(c, b);
|
||||
tempVec2.subVectors(a, b);
|
||||
const normal = new THREE.Vector3().crossVectors(tempVec1, tempVec2).normalize();
|
||||
for (let n = 0; n < 3; n++) {
|
||||
const vert = verts[n];
|
||||
const hash = hashVertex(vert);
|
||||
if (!(hash in vertexMap)) {
|
||||
vertexMap[hash] = [];
|
||||
}
|
||||
vertexMap[hash].push(normal);
|
||||
}
|
||||
}
|
||||
const normalArray = new Float32Array(posAttr.count * 3);
|
||||
const normAttr = new THREE.BufferAttribute(normalArray, 3, false);
|
||||
for (let i = 0, l = posAttr.count / 3; i < l; i++) {
|
||||
const i3 = 3 * i;
|
||||
const a = verts[0].fromBufferAttribute(posAttr, i3 + 0);
|
||||
const b = verts[1].fromBufferAttribute(posAttr, i3 + 1);
|
||||
const c = verts[2].fromBufferAttribute(posAttr, i3 + 2);
|
||||
tempVec1.subVectors(c, b);
|
||||
tempVec2.subVectors(a, b);
|
||||
tempNorm.crossVectors(tempVec1, tempVec2).normalize();
|
||||
for (let n = 0; n < 3; n++) {
|
||||
const vert = verts[n];
|
||||
const hash = hashVertex(vert);
|
||||
const otherNormals = vertexMap[hash];
|
||||
tempNorm2.set(0, 0, 0);
|
||||
for (let k = 0, lk = otherNormals.length; k < lk; k++) {
|
||||
const otherNorm = otherNormals[k];
|
||||
if (tempNorm.dot(otherNorm) > creaseDot) {
|
||||
tempNorm2.add(otherNorm);
|
||||
}
|
||||
}
|
||||
tempNorm2.normalize();
|
||||
normAttr.setXYZ(i3 + n, tempNorm2.x, tempNorm2.y, tempNorm2.z);
|
||||
}
|
||||
}
|
||||
resultGeometry.setAttribute("normal", normAttr);
|
||||
return resultGeometry;
|
||||
}
|
||||
exports.computeMorphedAttributes = computeMorphedAttributes;
|
||||
exports.estimateBytesUsed = estimateBytesUsed;
|
||||
exports.interleaveAttributes = interleaveAttributes;
|
||||
exports.mergeBufferAttributes = mergeBufferAttributes;
|
||||
exports.mergeBufferGeometries = mergeBufferGeometries;
|
||||
exports.mergeVertices = mergeVertices;
|
||||
exports.toCreasedNormals = toCreasedNormals;
|
||||
exports.toTrianglesDrawMode = toTrianglesDrawMode;
|
||||
//# sourceMappingURL=BufferGeometryUtils.cjs.map
|
||||
1
node_modules/three-stdlib/utils/BufferGeometryUtils.cjs.map
generated
vendored
Normal file
1
node_modules/three-stdlib/utils/BufferGeometryUtils.cjs.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
63
node_modules/three-stdlib/utils/BufferGeometryUtils.d.ts
generated
vendored
Normal file
63
node_modules/three-stdlib/utils/BufferGeometryUtils.d.ts
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
import { BufferAttribute, BufferGeometry, Float32BufferAttribute, InterleavedBufferAttribute, Mesh, Line, Points } from 'three';
|
||||
/**
|
||||
* @param {Array<BufferGeometry>} geometries
|
||||
* @param {Boolean} useGroups
|
||||
* @return {BufferGeometry}
|
||||
*/
|
||||
export declare const mergeBufferGeometries: (geometries: BufferGeometry[], useGroups?: boolean) => BufferGeometry | null;
|
||||
/**
|
||||
* @param {Array<BufferAttribute>} attributes
|
||||
* @return {BufferAttribute}
|
||||
*/
|
||||
export declare const mergeBufferAttributes: (attributes: BufferAttribute[]) => BufferAttribute | null | undefined;
|
||||
/**
|
||||
* @param {Array<BufferAttribute>} attributes
|
||||
* @return {Array<InterleavedBufferAttribute>}
|
||||
*/
|
||||
export declare const interleaveAttributes: (attributes: BufferAttribute[]) => InterleavedBufferAttribute[] | null;
|
||||
/**
|
||||
* @param {Array<BufferGeometry>} geometry
|
||||
* @return {number}
|
||||
*/
|
||||
export declare function estimateBytesUsed(geometry: BufferGeometry): number;
|
||||
/**
|
||||
* @param {BufferGeometry} geometry
|
||||
* @param {number} tolerance
|
||||
* @return {BufferGeometry>}
|
||||
*/
|
||||
export declare function mergeVertices(geometry: BufferGeometry, tolerance?: number): BufferGeometry;
|
||||
/**
|
||||
* @param {BufferGeometry} geometry
|
||||
* @param {number} drawMode
|
||||
* @return {BufferGeometry}
|
||||
*/
|
||||
export declare function toTrianglesDrawMode(geometry: BufferGeometry, drawMode: number): BufferGeometry;
|
||||
/**
|
||||
* Calculates the morphed attributes of a morphed/skinned BufferGeometry.
|
||||
* Helpful for Raytracing or Decals.
|
||||
* @param {Mesh | Line | Points} object An instance of Mesh, Line or Points.
|
||||
* @return {Object} An Object with original position/normal attributes and morphed ones.
|
||||
*/
|
||||
export type ComputedMorphedAttribute = {
|
||||
positionAttribute: BufferAttribute | InterleavedBufferAttribute;
|
||||
normalAttribute: BufferAttribute | InterleavedBufferAttribute;
|
||||
morphedPositionAttribute: Float32BufferAttribute;
|
||||
morphedNormalAttribute: Float32BufferAttribute;
|
||||
};
|
||||
export declare function computeMorphedAttributes(object: Mesh | Line | Points): ComputedMorphedAttribute | null;
|
||||
/**
|
||||
* Modifies the supplied geometry if it is non-indexed, otherwise creates a new,
|
||||
* non-indexed geometry. Returns the geometry with smooth normals everywhere except
|
||||
* faces that meet at an angle greater than the crease angle.
|
||||
*
|
||||
* Backwards compatible with code such as @react-three/drei's `<RoundedBox>`
|
||||
* which uses this method to operate on the original geometry.
|
||||
*
|
||||
* As of this writing, BufferGeometry.toNonIndexed() warns if the geometry is
|
||||
* non-indexed and returns `this`, i.e. the same geometry on which it was called:
|
||||
* `BufferGeometry is already non-indexed.`
|
||||
*
|
||||
* @param geometry
|
||||
* @param creaseAngle
|
||||
*/
|
||||
export declare function toCreasedNormals(geometry: BufferGeometry, creaseAngle?: number): BufferGeometry;
|
||||
637
node_modules/three-stdlib/utils/BufferGeometryUtils.js
generated
vendored
Normal file
637
node_modules/three-stdlib/utils/BufferGeometryUtils.js
generated
vendored
Normal file
@@ -0,0 +1,637 @@
|
||||
import { BufferGeometry, BufferAttribute, InterleavedBuffer, InterleavedBufferAttribute, TrianglesDrawMode, TriangleFanDrawMode, TriangleStripDrawMode, Vector3, Float32BufferAttribute } from "three";
|
||||
import { getWithKey } from "../types/helpers.js";
|
||||
const mergeBufferGeometries = (geometries, useGroups) => {
|
||||
const isIndexed = geometries[0].index !== null;
|
||||
const attributesUsed = new Set(Object.keys(geometries[0].attributes));
|
||||
const morphAttributesUsed = new Set(Object.keys(geometries[0].morphAttributes));
|
||||
const attributes = {};
|
||||
const morphAttributes = {};
|
||||
const morphTargetsRelative = geometries[0].morphTargetsRelative;
|
||||
const mergedGeometry = new BufferGeometry();
|
||||
let offset = 0;
|
||||
geometries.forEach((geom, i) => {
|
||||
let attributesCount = 0;
|
||||
if (isIndexed !== (geom.index !== null)) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index " + i + ". All geometries must have compatible attributes; make sure index attribute exists among all geometries, or in none of them."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
for (let name in geom.attributes) {
|
||||
if (!attributesUsed.has(name)) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index " + i + '. All geometries must have compatible attributes; make sure "' + name + '" attribute exists among all geometries, or in none of them.'
|
||||
);
|
||||
return null;
|
||||
}
|
||||
if (attributes[name] === void 0) {
|
||||
attributes[name] = [];
|
||||
}
|
||||
attributes[name].push(geom.attributes[name]);
|
||||
attributesCount++;
|
||||
}
|
||||
if (attributesCount !== attributesUsed.size) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index " + i + ". Make sure all geometries have the same number of attributes."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
if (morphTargetsRelative !== geom.morphTargetsRelative) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index " + i + ". .morphTargetsRelative must be consistent throughout all geometries."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
for (let name in geom.morphAttributes) {
|
||||
if (!morphAttributesUsed.has(name)) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index " + i + ". .morphAttributes must be consistent throughout all geometries."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
if (morphAttributes[name] === void 0)
|
||||
morphAttributes[name] = [];
|
||||
morphAttributes[name].push(geom.morphAttributes[name]);
|
||||
}
|
||||
mergedGeometry.userData.mergedUserData = mergedGeometry.userData.mergedUserData || [];
|
||||
mergedGeometry.userData.mergedUserData.push(geom.userData);
|
||||
if (useGroups) {
|
||||
let count;
|
||||
if (geom.index) {
|
||||
count = geom.index.count;
|
||||
} else if (geom.attributes.position !== void 0) {
|
||||
count = geom.attributes.position.count;
|
||||
} else {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed with geometry at index " + i + ". The geometry must have either an index or a position attribute"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
mergedGeometry.addGroup(offset, count, i);
|
||||
offset += count;
|
||||
}
|
||||
});
|
||||
if (isIndexed) {
|
||||
let indexOffset = 0;
|
||||
const mergedIndex = [];
|
||||
geometries.forEach((geom) => {
|
||||
const index = geom.index;
|
||||
for (let j = 0; j < index.count; ++j) {
|
||||
mergedIndex.push(index.getX(j) + indexOffset);
|
||||
}
|
||||
indexOffset += geom.attributes.position.count;
|
||||
});
|
||||
mergedGeometry.setIndex(mergedIndex);
|
||||
}
|
||||
for (let name in attributes) {
|
||||
const mergedAttribute = mergeBufferAttributes(attributes[name]);
|
||||
if (!mergedAttribute) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed while trying to merge the " + name + " attribute."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
mergedGeometry.setAttribute(name, mergedAttribute);
|
||||
}
|
||||
for (let name in morphAttributes) {
|
||||
const numMorphTargets = morphAttributes[name][0].length;
|
||||
if (numMorphTargets === 0)
|
||||
break;
|
||||
mergedGeometry.morphAttributes = mergedGeometry.morphAttributes || {};
|
||||
mergedGeometry.morphAttributes[name] = [];
|
||||
for (let i = 0; i < numMorphTargets; ++i) {
|
||||
const morphAttributesToMerge = [];
|
||||
for (let j = 0; j < morphAttributes[name].length; ++j) {
|
||||
morphAttributesToMerge.push(morphAttributes[name][j][i]);
|
||||
}
|
||||
const mergedMorphAttribute = mergeBufferAttributes(morphAttributesToMerge);
|
||||
if (!mergedMorphAttribute) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferGeometries() failed while trying to merge the " + name + " morphAttribute."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
mergedGeometry.morphAttributes[name].push(mergedMorphAttribute);
|
||||
}
|
||||
}
|
||||
return mergedGeometry;
|
||||
};
|
||||
const mergeBufferAttributes = (attributes) => {
|
||||
let TypedArray = void 0;
|
||||
let itemSize = void 0;
|
||||
let normalized = void 0;
|
||||
let arrayLength = 0;
|
||||
attributes.forEach((attr) => {
|
||||
if (TypedArray === void 0) {
|
||||
TypedArray = attr.array.constructor;
|
||||
}
|
||||
if (TypedArray !== attr.array.constructor) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. BufferAttribute.array must be of consistent array types across matching attributes."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
if (itemSize === void 0)
|
||||
itemSize = attr.itemSize;
|
||||
if (itemSize !== attr.itemSize) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. BufferAttribute.itemSize must be consistent across matching attributes."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
if (normalized === void 0)
|
||||
normalized = attr.normalized;
|
||||
if (normalized !== attr.normalized) {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils: .mergeBufferAttributes() failed. BufferAttribute.normalized must be consistent across matching attributes."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
arrayLength += attr.array.length;
|
||||
});
|
||||
if (TypedArray && itemSize) {
|
||||
const array = new TypedArray(arrayLength);
|
||||
let offset = 0;
|
||||
attributes.forEach((attr) => {
|
||||
array.set(attr.array, offset);
|
||||
offset += attr.array.length;
|
||||
});
|
||||
return new BufferAttribute(array, itemSize, normalized);
|
||||
}
|
||||
};
|
||||
const interleaveAttributes = (attributes) => {
|
||||
let TypedArray = void 0;
|
||||
let arrayLength = 0;
|
||||
let stride = 0;
|
||||
for (let i = 0, l = attributes.length; i < l; ++i) {
|
||||
const attribute = attributes[i];
|
||||
if (TypedArray === void 0)
|
||||
TypedArray = attribute.array.constructor;
|
||||
if (TypedArray !== attribute.array.constructor) {
|
||||
console.error("AttributeBuffers of different types cannot be interleaved");
|
||||
return null;
|
||||
}
|
||||
arrayLength += attribute.array.length;
|
||||
stride += attribute.itemSize;
|
||||
}
|
||||
const interleavedBuffer = new InterleavedBuffer(new TypedArray(arrayLength), stride);
|
||||
let offset = 0;
|
||||
const res = [];
|
||||
const getters = ["getX", "getY", "getZ", "getW"];
|
||||
const setters = ["setX", "setY", "setZ", "setW"];
|
||||
for (let j = 0, l = attributes.length; j < l; j++) {
|
||||
const attribute = attributes[j];
|
||||
const itemSize = attribute.itemSize;
|
||||
const count = attribute.count;
|
||||
const iba = new InterleavedBufferAttribute(interleavedBuffer, itemSize, offset, attribute.normalized);
|
||||
res.push(iba);
|
||||
offset += itemSize;
|
||||
for (let c = 0; c < count; c++) {
|
||||
for (let k = 0; k < itemSize; k++) {
|
||||
const set = getWithKey(iba, setters[k]);
|
||||
const get = getWithKey(attribute, getters[k]);
|
||||
set(c, get(c));
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
};
|
||||
function estimateBytesUsed(geometry) {
|
||||
let mem = 0;
|
||||
for (let name in geometry.attributes) {
|
||||
const attr = geometry.getAttribute(name);
|
||||
mem += attr.count * attr.itemSize * attr.array.BYTES_PER_ELEMENT;
|
||||
}
|
||||
const indices = geometry.getIndex();
|
||||
mem += indices ? indices.count * indices.itemSize * indices.array.BYTES_PER_ELEMENT : 0;
|
||||
return mem;
|
||||
}
|
||||
function mergeVertices(geometry, tolerance = 1e-4) {
|
||||
tolerance = Math.max(tolerance, Number.EPSILON);
|
||||
const hashToIndex = {};
|
||||
const indices = geometry.getIndex();
|
||||
const positions = geometry.getAttribute("position");
|
||||
const vertexCount = indices ? indices.count : positions.count;
|
||||
let nextIndex = 0;
|
||||
const attributeNames = Object.keys(geometry.attributes);
|
||||
const attrArrays = {};
|
||||
const morphAttrsArrays = {};
|
||||
const newIndices = [];
|
||||
const getters = ["getX", "getY", "getZ", "getW"];
|
||||
for (let i = 0, l = attributeNames.length; i < l; i++) {
|
||||
const name = attributeNames[i];
|
||||
attrArrays[name] = [];
|
||||
const morphAttr = geometry.morphAttributes[name];
|
||||
if (morphAttr) {
|
||||
morphAttrsArrays[name] = new Array(morphAttr.length).fill(0).map(() => []);
|
||||
}
|
||||
}
|
||||
const decimalShift = Math.log10(1 / tolerance);
|
||||
const shiftMultiplier = Math.pow(10, decimalShift);
|
||||
for (let i = 0; i < vertexCount; i++) {
|
||||
const index = indices ? indices.getX(i) : i;
|
||||
let hash = "";
|
||||
for (let j = 0, l = attributeNames.length; j < l; j++) {
|
||||
const name = attributeNames[j];
|
||||
const attribute = geometry.getAttribute(name);
|
||||
const itemSize = attribute.itemSize;
|
||||
for (let k = 0; k < itemSize; k++) {
|
||||
hash += `${~~(attribute[getters[k]](index) * shiftMultiplier)},`;
|
||||
}
|
||||
}
|
||||
if (hash in hashToIndex) {
|
||||
newIndices.push(hashToIndex[hash]);
|
||||
} else {
|
||||
for (let j = 0, l = attributeNames.length; j < l; j++) {
|
||||
const name = attributeNames[j];
|
||||
const attribute = geometry.getAttribute(name);
|
||||
const morphAttr = geometry.morphAttributes[name];
|
||||
const itemSize = attribute.itemSize;
|
||||
const newarray = attrArrays[name];
|
||||
const newMorphArrays = morphAttrsArrays[name];
|
||||
for (let k = 0; k < itemSize; k++) {
|
||||
const getterFunc = getters[k];
|
||||
newarray.push(attribute[getterFunc](index));
|
||||
if (morphAttr) {
|
||||
for (let m = 0, ml = morphAttr.length; m < ml; m++) {
|
||||
newMorphArrays[m].push(morphAttr[m][getterFunc](index));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
hashToIndex[hash] = nextIndex;
|
||||
newIndices.push(nextIndex);
|
||||
nextIndex++;
|
||||
}
|
||||
}
|
||||
const result = geometry.clone();
|
||||
for (let i = 0, l = attributeNames.length; i < l; i++) {
|
||||
const name = attributeNames[i];
|
||||
const oldAttribute = geometry.getAttribute(name);
|
||||
const buffer = new oldAttribute.array.constructor(attrArrays[name]);
|
||||
const attribute = new BufferAttribute(buffer, oldAttribute.itemSize, oldAttribute.normalized);
|
||||
result.setAttribute(name, attribute);
|
||||
if (name in morphAttrsArrays) {
|
||||
for (let j = 0; j < morphAttrsArrays[name].length; j++) {
|
||||
const oldMorphAttribute = geometry.morphAttributes[name][j];
|
||||
const buffer2 = new oldMorphAttribute.array.constructor(morphAttrsArrays[name][j]);
|
||||
const morphAttribute = new BufferAttribute(buffer2, oldMorphAttribute.itemSize, oldMorphAttribute.normalized);
|
||||
result.morphAttributes[name][j] = morphAttribute;
|
||||
}
|
||||
}
|
||||
}
|
||||
result.setIndex(newIndices);
|
||||
return result;
|
||||
}
|
||||
function toTrianglesDrawMode(geometry, drawMode) {
|
||||
if (drawMode === TrianglesDrawMode) {
|
||||
console.warn("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles.");
|
||||
return geometry;
|
||||
}
|
||||
if (drawMode === TriangleFanDrawMode || drawMode === TriangleStripDrawMode) {
|
||||
let index = geometry.getIndex();
|
||||
if (index === null) {
|
||||
const indices = [];
|
||||
const position = geometry.getAttribute("position");
|
||||
if (position !== void 0) {
|
||||
for (let i = 0; i < position.count; i++) {
|
||||
indices.push(i);
|
||||
}
|
||||
geometry.setIndex(indices);
|
||||
index = geometry.getIndex();
|
||||
} else {
|
||||
console.error(
|
||||
"THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible."
|
||||
);
|
||||
return geometry;
|
||||
}
|
||||
}
|
||||
const numberOfTriangles = index.count - 2;
|
||||
const newIndices = [];
|
||||
if (index) {
|
||||
if (drawMode === TriangleFanDrawMode) {
|
||||
for (let i = 1; i <= numberOfTriangles; i++) {
|
||||
newIndices.push(index.getX(0));
|
||||
newIndices.push(index.getX(i));
|
||||
newIndices.push(index.getX(i + 1));
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < numberOfTriangles; i++) {
|
||||
if (i % 2 === 0) {
|
||||
newIndices.push(index.getX(i));
|
||||
newIndices.push(index.getX(i + 1));
|
||||
newIndices.push(index.getX(i + 2));
|
||||
} else {
|
||||
newIndices.push(index.getX(i + 2));
|
||||
newIndices.push(index.getX(i + 1));
|
||||
newIndices.push(index.getX(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newIndices.length / 3 !== numberOfTriangles) {
|
||||
console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles.");
|
||||
}
|
||||
const newGeometry = geometry.clone();
|
||||
newGeometry.setIndex(newIndices);
|
||||
newGeometry.clearGroups();
|
||||
return newGeometry;
|
||||
} else {
|
||||
console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:", drawMode);
|
||||
return geometry;
|
||||
}
|
||||
}
|
||||
function computeMorphedAttributes(object) {
|
||||
if (object.geometry.isBufferGeometry !== true) {
|
||||
console.error("THREE.BufferGeometryUtils: Geometry is not of type BufferGeometry.");
|
||||
return null;
|
||||
}
|
||||
const _vA = new Vector3();
|
||||
const _vB = new Vector3();
|
||||
const _vC = new Vector3();
|
||||
const _tempA = new Vector3();
|
||||
const _tempB = new Vector3();
|
||||
const _tempC = new Vector3();
|
||||
const _morphA = new Vector3();
|
||||
const _morphB = new Vector3();
|
||||
const _morphC = new Vector3();
|
||||
function _calculateMorphedAttributeData(object2, material2, attribute, morphAttribute, morphTargetsRelative2, a2, b2, c2, modifiedAttributeArray) {
|
||||
_vA.fromBufferAttribute(attribute, a2);
|
||||
_vB.fromBufferAttribute(attribute, b2);
|
||||
_vC.fromBufferAttribute(attribute, c2);
|
||||
const morphInfluences = object2.morphTargetInfluences;
|
||||
if (
|
||||
// @ts-ignore
|
||||
material2.morphTargets && morphAttribute && morphInfluences
|
||||
) {
|
||||
_morphA.set(0, 0, 0);
|
||||
_morphB.set(0, 0, 0);
|
||||
_morphC.set(0, 0, 0);
|
||||
for (let i2 = 0, il2 = morphAttribute.length; i2 < il2; i2++) {
|
||||
const influence = morphInfluences[i2];
|
||||
const morph = morphAttribute[i2];
|
||||
if (influence === 0)
|
||||
continue;
|
||||
_tempA.fromBufferAttribute(morph, a2);
|
||||
_tempB.fromBufferAttribute(morph, b2);
|
||||
_tempC.fromBufferAttribute(morph, c2);
|
||||
if (morphTargetsRelative2) {
|
||||
_morphA.addScaledVector(_tempA, influence);
|
||||
_morphB.addScaledVector(_tempB, influence);
|
||||
_morphC.addScaledVector(_tempC, influence);
|
||||
} else {
|
||||
_morphA.addScaledVector(_tempA.sub(_vA), influence);
|
||||
_morphB.addScaledVector(_tempB.sub(_vB), influence);
|
||||
_morphC.addScaledVector(_tempC.sub(_vC), influence);
|
||||
}
|
||||
}
|
||||
_vA.add(_morphA);
|
||||
_vB.add(_morphB);
|
||||
_vC.add(_morphC);
|
||||
}
|
||||
if (object2.isSkinnedMesh) {
|
||||
object2.boneTransform(a2, _vA);
|
||||
object2.boneTransform(b2, _vB);
|
||||
object2.boneTransform(c2, _vC);
|
||||
}
|
||||
modifiedAttributeArray[a2 * 3 + 0] = _vA.x;
|
||||
modifiedAttributeArray[a2 * 3 + 1] = _vA.y;
|
||||
modifiedAttributeArray[a2 * 3 + 2] = _vA.z;
|
||||
modifiedAttributeArray[b2 * 3 + 0] = _vB.x;
|
||||
modifiedAttributeArray[b2 * 3 + 1] = _vB.y;
|
||||
modifiedAttributeArray[b2 * 3 + 2] = _vB.z;
|
||||
modifiedAttributeArray[c2 * 3 + 0] = _vC.x;
|
||||
modifiedAttributeArray[c2 * 3 + 1] = _vC.y;
|
||||
modifiedAttributeArray[c2 * 3 + 2] = _vC.z;
|
||||
}
|
||||
const geometry = object.geometry;
|
||||
const material = object.material;
|
||||
let a, b, c;
|
||||
const index = geometry.index;
|
||||
const positionAttribute = geometry.attributes.position;
|
||||
const morphPosition = geometry.morphAttributes.position;
|
||||
const morphTargetsRelative = geometry.morphTargetsRelative;
|
||||
const normalAttribute = geometry.attributes.normal;
|
||||
const morphNormal = geometry.morphAttributes.position;
|
||||
const groups = geometry.groups;
|
||||
const drawRange = geometry.drawRange;
|
||||
let i, j, il, jl;
|
||||
let group, groupMaterial;
|
||||
let start, end;
|
||||
const modifiedPosition = new Float32Array(positionAttribute.count * positionAttribute.itemSize);
|
||||
const modifiedNormal = new Float32Array(normalAttribute.count * normalAttribute.itemSize);
|
||||
if (index !== null) {
|
||||
if (Array.isArray(material)) {
|
||||
for (i = 0, il = groups.length; i < il; i++) {
|
||||
group = groups[i];
|
||||
groupMaterial = material[group.materialIndex];
|
||||
start = Math.max(group.start, drawRange.start);
|
||||
end = Math.min(group.start + group.count, drawRange.start + drawRange.count);
|
||||
for (j = start, jl = end; j < jl; j += 3) {
|
||||
a = index.getX(j);
|
||||
b = index.getX(j + 1);
|
||||
c = index.getX(j + 2);
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
groupMaterial,
|
||||
positionAttribute,
|
||||
morphPosition,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedPosition
|
||||
);
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
groupMaterial,
|
||||
normalAttribute,
|
||||
morphNormal,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedNormal
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
start = Math.max(0, drawRange.start);
|
||||
end = Math.min(index.count, drawRange.start + drawRange.count);
|
||||
for (i = start, il = end; i < il; i += 3) {
|
||||
a = index.getX(i);
|
||||
b = index.getX(i + 1);
|
||||
c = index.getX(i + 2);
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
material,
|
||||
positionAttribute,
|
||||
morphPosition,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedPosition
|
||||
);
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
material,
|
||||
normalAttribute,
|
||||
morphNormal,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedNormal
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if (positionAttribute !== void 0) {
|
||||
if (Array.isArray(material)) {
|
||||
for (i = 0, il = groups.length; i < il; i++) {
|
||||
group = groups[i];
|
||||
groupMaterial = material[group.materialIndex];
|
||||
start = Math.max(group.start, drawRange.start);
|
||||
end = Math.min(group.start + group.count, drawRange.start + drawRange.count);
|
||||
for (j = start, jl = end; j < jl; j += 3) {
|
||||
a = j;
|
||||
b = j + 1;
|
||||
c = j + 2;
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
groupMaterial,
|
||||
positionAttribute,
|
||||
morphPosition,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedPosition
|
||||
);
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
groupMaterial,
|
||||
normalAttribute,
|
||||
morphNormal,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedNormal
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
start = Math.max(0, drawRange.start);
|
||||
end = Math.min(positionAttribute.count, drawRange.start + drawRange.count);
|
||||
for (i = start, il = end; i < il; i += 3) {
|
||||
a = i;
|
||||
b = i + 1;
|
||||
c = i + 2;
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
material,
|
||||
positionAttribute,
|
||||
morphPosition,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedPosition
|
||||
);
|
||||
_calculateMorphedAttributeData(
|
||||
object,
|
||||
material,
|
||||
normalAttribute,
|
||||
morphNormal,
|
||||
morphTargetsRelative,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
modifiedNormal
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
const morphedPositionAttribute = new Float32BufferAttribute(modifiedPosition, 3);
|
||||
const morphedNormalAttribute = new Float32BufferAttribute(modifiedNormal, 3);
|
||||
return {
|
||||
positionAttribute,
|
||||
normalAttribute,
|
||||
morphedPositionAttribute,
|
||||
morphedNormalAttribute
|
||||
};
|
||||
}
|
||||
function toCreasedNormals(geometry, creaseAngle = Math.PI / 3) {
|
||||
const creaseDot = Math.cos(creaseAngle);
|
||||
const hashMultiplier = (1 + 1e-10) * 100;
|
||||
const verts = [new Vector3(), new Vector3(), new Vector3()];
|
||||
const tempVec1 = new Vector3();
|
||||
const tempVec2 = new Vector3();
|
||||
const tempNorm = new Vector3();
|
||||
const tempNorm2 = new Vector3();
|
||||
function hashVertex(v) {
|
||||
const x = ~~(v.x * hashMultiplier);
|
||||
const y = ~~(v.y * hashMultiplier);
|
||||
const z = ~~(v.z * hashMultiplier);
|
||||
return `${x},${y},${z}`;
|
||||
}
|
||||
const resultGeometry = geometry.index ? geometry.toNonIndexed() : geometry;
|
||||
const posAttr = resultGeometry.attributes.position;
|
||||
const vertexMap = {};
|
||||
for (let i = 0, l = posAttr.count / 3; i < l; i++) {
|
||||
const i3 = 3 * i;
|
||||
const a = verts[0].fromBufferAttribute(posAttr, i3 + 0);
|
||||
const b = verts[1].fromBufferAttribute(posAttr, i3 + 1);
|
||||
const c = verts[2].fromBufferAttribute(posAttr, i3 + 2);
|
||||
tempVec1.subVectors(c, b);
|
||||
tempVec2.subVectors(a, b);
|
||||
const normal = new Vector3().crossVectors(tempVec1, tempVec2).normalize();
|
||||
for (let n = 0; n < 3; n++) {
|
||||
const vert = verts[n];
|
||||
const hash = hashVertex(vert);
|
||||
if (!(hash in vertexMap)) {
|
||||
vertexMap[hash] = [];
|
||||
}
|
||||
vertexMap[hash].push(normal);
|
||||
}
|
||||
}
|
||||
const normalArray = new Float32Array(posAttr.count * 3);
|
||||
const normAttr = new BufferAttribute(normalArray, 3, false);
|
||||
for (let i = 0, l = posAttr.count / 3; i < l; i++) {
|
||||
const i3 = 3 * i;
|
||||
const a = verts[0].fromBufferAttribute(posAttr, i3 + 0);
|
||||
const b = verts[1].fromBufferAttribute(posAttr, i3 + 1);
|
||||
const c = verts[2].fromBufferAttribute(posAttr, i3 + 2);
|
||||
tempVec1.subVectors(c, b);
|
||||
tempVec2.subVectors(a, b);
|
||||
tempNorm.crossVectors(tempVec1, tempVec2).normalize();
|
||||
for (let n = 0; n < 3; n++) {
|
||||
const vert = verts[n];
|
||||
const hash = hashVertex(vert);
|
||||
const otherNormals = vertexMap[hash];
|
||||
tempNorm2.set(0, 0, 0);
|
||||
for (let k = 0, lk = otherNormals.length; k < lk; k++) {
|
||||
const otherNorm = otherNormals[k];
|
||||
if (tempNorm.dot(otherNorm) > creaseDot) {
|
||||
tempNorm2.add(otherNorm);
|
||||
}
|
||||
}
|
||||
tempNorm2.normalize();
|
||||
normAttr.setXYZ(i3 + n, tempNorm2.x, tempNorm2.y, tempNorm2.z);
|
||||
}
|
||||
}
|
||||
resultGeometry.setAttribute("normal", normAttr);
|
||||
return resultGeometry;
|
||||
}
|
||||
export {
|
||||
computeMorphedAttributes,
|
||||
estimateBytesUsed,
|
||||
interleaveAttributes,
|
||||
mergeBufferAttributes,
|
||||
mergeBufferGeometries,
|
||||
mergeVertices,
|
||||
toCreasedNormals,
|
||||
toTrianglesDrawMode
|
||||
};
|
||||
//# sourceMappingURL=BufferGeometryUtils.js.map
|
||||
1
node_modules/three-stdlib/utils/BufferGeometryUtils.js.map
generated
vendored
Normal file
1
node_modules/three-stdlib/utils/BufferGeometryUtils.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
575
node_modules/three-stdlib/utils/GeometryCompressionUtils.cjs
generated
vendored
Normal file
575
node_modules/three-stdlib/utils/GeometryCompressionUtils.cjs
generated
vendored
Normal file
@@ -0,0 +1,575 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
||||
const THREE = require("three");
|
||||
const constants = require("../_polyfill/constants.cjs");
|
||||
var GeometryCompressionUtils = {
|
||||
/**
|
||||
* Make the input mesh.geometry's normal attribute encoded and compressed by 3 different methods.
|
||||
* Also will change the mesh.material to `PackedPhongMaterial` which let the vertex shader program decode the normal data.
|
||||
*
|
||||
* @param {THREE.Mesh} mesh
|
||||
* @param {String} encodeMethod "DEFAULT" || "OCT1Byte" || "OCT2Byte" || "ANGLES"
|
||||
*
|
||||
*/
|
||||
compressNormals: function(mesh, encodeMethod) {
|
||||
if (!mesh.geometry) {
|
||||
console.error("Mesh must contain geometry. ");
|
||||
}
|
||||
const normal = mesh.geometry.attributes.normal;
|
||||
if (!normal) {
|
||||
console.error("Geometry must contain normal attribute. ");
|
||||
}
|
||||
if (normal.isPacked)
|
||||
return;
|
||||
if (normal.itemSize != 3) {
|
||||
console.error("normal.itemSize is not 3, which cannot be encoded. ");
|
||||
}
|
||||
const array = normal.array;
|
||||
const count = normal.count;
|
||||
let result;
|
||||
if (encodeMethod == "DEFAULT") {
|
||||
result = new Uint8Array(count * 3);
|
||||
for (let idx = 0; idx < array.length; idx += 3) {
|
||||
const encoded = this.EncodingFuncs.defaultEncode(array[idx], array[idx + 1], array[idx + 2], 1);
|
||||
result[idx + 0] = encoded[0];
|
||||
result[idx + 1] = encoded[1];
|
||||
result[idx + 2] = encoded[2];
|
||||
}
|
||||
mesh.geometry.setAttribute("normal", new THREE.BufferAttribute(result, 3, true));
|
||||
mesh.geometry.attributes.normal.bytes = result.length * 1;
|
||||
} else if (encodeMethod == "OCT1Byte") {
|
||||
result = new Int8Array(count * 2);
|
||||
for (let idx = 0; idx < array.length; idx += 3) {
|
||||
const encoded = this.EncodingFuncs.octEncodeBest(array[idx], array[idx + 1], array[idx + 2], 1);
|
||||
result[idx / 3 * 2 + 0] = encoded[0];
|
||||
result[idx / 3 * 2 + 1] = encoded[1];
|
||||
}
|
||||
mesh.geometry.setAttribute("normal", new THREE.BufferAttribute(result, 2, true));
|
||||
mesh.geometry.attributes.normal.bytes = result.length * 1;
|
||||
} else if (encodeMethod == "OCT2Byte") {
|
||||
result = new Int16Array(count * 2);
|
||||
for (let idx = 0; idx < array.length; idx += 3) {
|
||||
const encoded = this.EncodingFuncs.octEncodeBest(array[idx], array[idx + 1], array[idx + 2], 2);
|
||||
result[idx / 3 * 2 + 0] = encoded[0];
|
||||
result[idx / 3 * 2 + 1] = encoded[1];
|
||||
}
|
||||
mesh.geometry.setAttribute("normal", new THREE.BufferAttribute(result, 2, true));
|
||||
mesh.geometry.attributes.normal.bytes = result.length * 2;
|
||||
} else if (encodeMethod == "ANGLES") {
|
||||
result = new Uint16Array(count * 2);
|
||||
for (let idx = 0; idx < array.length; idx += 3) {
|
||||
const encoded = this.EncodingFuncs.anglesEncode(array[idx], array[idx + 1], array[idx + 2]);
|
||||
result[idx / 3 * 2 + 0] = encoded[0];
|
||||
result[idx / 3 * 2 + 1] = encoded[1];
|
||||
}
|
||||
mesh.geometry.setAttribute("normal", new THREE.BufferAttribute(result, 2, true));
|
||||
mesh.geometry.attributes.normal.bytes = result.length * 2;
|
||||
} else {
|
||||
console.error("Unrecognized encoding method, should be `DEFAULT` or `ANGLES` or `OCT`. ");
|
||||
}
|
||||
mesh.geometry.attributes.normal.needsUpdate = true;
|
||||
mesh.geometry.attributes.normal.isPacked = true;
|
||||
mesh.geometry.attributes.normal.packingMethod = encodeMethod;
|
||||
if (!(mesh.material instanceof PackedPhongMaterial)) {
|
||||
mesh.material = new PackedPhongMaterial().copy(mesh.material);
|
||||
}
|
||||
if (encodeMethod == "ANGLES") {
|
||||
mesh.material.defines.USE_PACKED_NORMAL = 0;
|
||||
}
|
||||
if (encodeMethod == "OCT1Byte") {
|
||||
mesh.material.defines.USE_PACKED_NORMAL = 1;
|
||||
}
|
||||
if (encodeMethod == "OCT2Byte") {
|
||||
mesh.material.defines.USE_PACKED_NORMAL = 1;
|
||||
}
|
||||
if (encodeMethod == "DEFAULT") {
|
||||
mesh.material.defines.USE_PACKED_NORMAL = 2;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Make the input mesh.geometry's position attribute encoded and compressed.
|
||||
* Also will change the mesh.material to `PackedPhongMaterial` which let the vertex shader program decode the position data.
|
||||
*
|
||||
* @param {THREE.Mesh} mesh
|
||||
*
|
||||
*/
|
||||
compressPositions: function(mesh) {
|
||||
if (!mesh.geometry) {
|
||||
console.error("Mesh must contain geometry. ");
|
||||
}
|
||||
const position = mesh.geometry.attributes.position;
|
||||
if (!position) {
|
||||
console.error("Geometry must contain position attribute. ");
|
||||
}
|
||||
if (position.isPacked)
|
||||
return;
|
||||
if (position.itemSize != 3) {
|
||||
console.error("position.itemSize is not 3, which cannot be packed. ");
|
||||
}
|
||||
const array = position.array;
|
||||
const encodingBytes = 2;
|
||||
const result = this.EncodingFuncs.quantizedEncode(array, encodingBytes);
|
||||
const quantized = result.quantized;
|
||||
const decodeMat = result.decodeMat;
|
||||
if (mesh.geometry.boundingBox == null)
|
||||
mesh.geometry.computeBoundingBox();
|
||||
if (mesh.geometry.boundingSphere == null)
|
||||
mesh.geometry.computeBoundingSphere();
|
||||
mesh.geometry.setAttribute("position", new THREE.BufferAttribute(quantized, 3));
|
||||
mesh.geometry.attributes.position.isPacked = true;
|
||||
mesh.geometry.attributes.position.needsUpdate = true;
|
||||
mesh.geometry.attributes.position.bytes = quantized.length * encodingBytes;
|
||||
if (!(mesh.material instanceof PackedPhongMaterial)) {
|
||||
mesh.material = new PackedPhongMaterial().copy(mesh.material);
|
||||
}
|
||||
mesh.material.defines.USE_PACKED_POSITION = 0;
|
||||
mesh.material.uniforms.quantizeMatPos.value = decodeMat;
|
||||
mesh.material.uniforms.quantizeMatPos.needsUpdate = true;
|
||||
},
|
||||
/**
|
||||
* Make the input mesh.geometry's uv attribute encoded and compressed.
|
||||
* Also will change the mesh.material to `PackedPhongMaterial` which let the vertex shader program decode the uv data.
|
||||
*
|
||||
* @param {THREE.Mesh} mesh
|
||||
*
|
||||
*/
|
||||
compressUvs: function(mesh) {
|
||||
if (!mesh.geometry) {
|
||||
console.error("Mesh must contain geometry property. ");
|
||||
}
|
||||
const uvs = mesh.geometry.attributes.uv;
|
||||
if (!uvs) {
|
||||
console.error("Geometry must contain uv attribute. ");
|
||||
}
|
||||
if (uvs.isPacked)
|
||||
return;
|
||||
const range = { min: Infinity, max: -Infinity };
|
||||
const array = uvs.array;
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
range.min = Math.min(range.min, array[i]);
|
||||
range.max = Math.max(range.max, array[i]);
|
||||
}
|
||||
let result;
|
||||
if (range.min >= -1 && range.max <= 1) {
|
||||
result = new Uint16Array(array.length);
|
||||
for (let i = 0; i < array.length; i += 2) {
|
||||
const encoded = this.EncodingFuncs.defaultEncode(array[i], array[i + 1], 0, 2);
|
||||
result[i] = encoded[0];
|
||||
result[i + 1] = encoded[1];
|
||||
}
|
||||
mesh.geometry.setAttribute("uv", new THREE.BufferAttribute(result, 2, true));
|
||||
mesh.geometry.attributes.uv.isPacked = true;
|
||||
mesh.geometry.attributes.uv.needsUpdate = true;
|
||||
mesh.geometry.attributes.uv.bytes = result.length * 2;
|
||||
if (!(mesh.material instanceof PackedPhongMaterial)) {
|
||||
mesh.material = new PackedPhongMaterial().copy(mesh.material);
|
||||
}
|
||||
mesh.material.defines.USE_PACKED_UV = 0;
|
||||
} else {
|
||||
result = this.EncodingFuncs.quantizedEncodeUV(array, 2);
|
||||
mesh.geometry.setAttribute("uv", new THREE.BufferAttribute(result.quantized, 2));
|
||||
mesh.geometry.attributes.uv.isPacked = true;
|
||||
mesh.geometry.attributes.uv.needsUpdate = true;
|
||||
mesh.geometry.attributes.uv.bytes = result.quantized.length * 2;
|
||||
if (!(mesh.material instanceof PackedPhongMaterial)) {
|
||||
mesh.material = new PackedPhongMaterial().copy(mesh.material);
|
||||
}
|
||||
mesh.material.defines.USE_PACKED_UV = 1;
|
||||
mesh.material.uniforms.quantizeMatUV.value = result.decodeMat;
|
||||
mesh.material.uniforms.quantizeMatUV.needsUpdate = true;
|
||||
}
|
||||
},
|
||||
EncodingFuncs: {
|
||||
defaultEncode: function(x, y, z, bytes) {
|
||||
if (bytes == 1) {
|
||||
const tmpx = Math.round((x + 1) * 0.5 * 255);
|
||||
const tmpy = Math.round((y + 1) * 0.5 * 255);
|
||||
const tmpz = Math.round((z + 1) * 0.5 * 255);
|
||||
return new Uint8Array([tmpx, tmpy, tmpz]);
|
||||
} else if (bytes == 2) {
|
||||
const tmpx = Math.round((x + 1) * 0.5 * 65535);
|
||||
const tmpy = Math.round((y + 1) * 0.5 * 65535);
|
||||
const tmpz = Math.round((z + 1) * 0.5 * 65535);
|
||||
return new Uint16Array([tmpx, tmpy, tmpz]);
|
||||
} else {
|
||||
console.error("number of bytes must be 1 or 2");
|
||||
}
|
||||
},
|
||||
defaultDecode: function(array, bytes) {
|
||||
if (bytes == 1) {
|
||||
return [array[0] / 255 * 2 - 1, array[1] / 255 * 2 - 1, array[2] / 255 * 2 - 1];
|
||||
} else if (bytes == 2) {
|
||||
return [array[0] / 65535 * 2 - 1, array[1] / 65535 * 2 - 1, array[2] / 65535 * 2 - 1];
|
||||
} else {
|
||||
console.error("number of bytes must be 1 or 2");
|
||||
}
|
||||
},
|
||||
// for `Angles` encoding
|
||||
anglesEncode: function(x, y, z) {
|
||||
const normal0 = parseInt(0.5 * (1 + Math.atan2(y, x) / Math.PI) * 65535);
|
||||
const normal1 = parseInt(0.5 * (1 + z) * 65535);
|
||||
return new Uint16Array([normal0, normal1]);
|
||||
},
|
||||
// for `Octahedron` encoding
|
||||
octEncodeBest: function(x, y, z, bytes) {
|
||||
var oct, dec, best, currentCos, bestCos;
|
||||
best = oct = octEncodeVec3(x, y, z, "floor", "floor");
|
||||
dec = octDecodeVec2(oct);
|
||||
bestCos = dot(x, y, z, dec);
|
||||
oct = octEncodeVec3(x, y, z, "ceil", "floor");
|
||||
dec = octDecodeVec2(oct);
|
||||
currentCos = dot(x, y, z, dec);
|
||||
if (currentCos > bestCos) {
|
||||
best = oct;
|
||||
bestCos = currentCos;
|
||||
}
|
||||
oct = octEncodeVec3(x, y, z, "floor", "ceil");
|
||||
dec = octDecodeVec2(oct);
|
||||
currentCos = dot(x, y, z, dec);
|
||||
if (currentCos > bestCos) {
|
||||
best = oct;
|
||||
bestCos = currentCos;
|
||||
}
|
||||
oct = octEncodeVec3(x, y, z, "ceil", "ceil");
|
||||
dec = octDecodeVec2(oct);
|
||||
currentCos = dot(x, y, z, dec);
|
||||
if (currentCos > bestCos) {
|
||||
best = oct;
|
||||
}
|
||||
return best;
|
||||
function octEncodeVec3(x0, y0, z0, xfunc, yfunc) {
|
||||
var x2 = x0 / (Math.abs(x0) + Math.abs(y0) + Math.abs(z0));
|
||||
var y2 = y0 / (Math.abs(x0) + Math.abs(y0) + Math.abs(z0));
|
||||
if (z < 0) {
|
||||
var tempx = (1 - Math.abs(y2)) * (x2 >= 0 ? 1 : -1);
|
||||
var tempy = (1 - Math.abs(x2)) * (y2 >= 0 ? 1 : -1);
|
||||
x2 = tempx;
|
||||
y2 = tempy;
|
||||
var diff = 1 - Math.abs(x2) - Math.abs(y2);
|
||||
if (diff > 0) {
|
||||
diff += 1e-3;
|
||||
x2 += x2 > 0 ? diff / 2 : -diff / 2;
|
||||
y2 += y2 > 0 ? diff / 2 : -diff / 2;
|
||||
}
|
||||
}
|
||||
if (bytes == 1) {
|
||||
return new Int8Array([Math[xfunc](x2 * 127.5 + (x2 < 0 ? 1 : 0)), Math[yfunc](y2 * 127.5 + (y2 < 0 ? 1 : 0))]);
|
||||
}
|
||||
if (bytes == 2) {
|
||||
return new Int16Array([
|
||||
Math[xfunc](x2 * 32767.5 + (x2 < 0 ? 1 : 0)),
|
||||
Math[yfunc](y2 * 32767.5 + (y2 < 0 ? 1 : 0))
|
||||
]);
|
||||
}
|
||||
}
|
||||
function octDecodeVec2(oct2) {
|
||||
var x2 = oct2[0];
|
||||
var y2 = oct2[1];
|
||||
if (bytes == 1) {
|
||||
x2 /= x2 < 0 ? 127 : 128;
|
||||
y2 /= y2 < 0 ? 127 : 128;
|
||||
} else if (bytes == 2) {
|
||||
x2 /= x2 < 0 ? 32767 : 32768;
|
||||
y2 /= y2 < 0 ? 32767 : 32768;
|
||||
}
|
||||
var z2 = 1 - Math.abs(x2) - Math.abs(y2);
|
||||
if (z2 < 0) {
|
||||
var tmpx = x2;
|
||||
x2 = (1 - Math.abs(y2)) * (x2 >= 0 ? 1 : -1);
|
||||
y2 = (1 - Math.abs(tmpx)) * (y2 >= 0 ? 1 : -1);
|
||||
}
|
||||
var length = Math.sqrt(x2 * x2 + y2 * y2 + z2 * z2);
|
||||
return [x2 / length, y2 / length, z2 / length];
|
||||
}
|
||||
function dot(x2, y2, z2, vec3) {
|
||||
return x2 * vec3[0] + y2 * vec3[1] + z2 * vec3[2];
|
||||
}
|
||||
},
|
||||
quantizedEncode: function(array, bytes) {
|
||||
let quantized, segments;
|
||||
if (bytes == 1) {
|
||||
quantized = new Uint8Array(array.length);
|
||||
segments = 255;
|
||||
} else if (bytes == 2) {
|
||||
quantized = new Uint16Array(array.length);
|
||||
segments = 65535;
|
||||
} else {
|
||||
console.error("number of bytes error! ");
|
||||
}
|
||||
const decodeMat = new THREE.Matrix4();
|
||||
const min = new Float32Array(3);
|
||||
const max = new Float32Array(3);
|
||||
min[0] = min[1] = min[2] = Number.MAX_VALUE;
|
||||
max[0] = max[1] = max[2] = -Number.MAX_VALUE;
|
||||
for (let i = 0; i < array.length; i += 3) {
|
||||
min[0] = Math.min(min[0], array[i + 0]);
|
||||
min[1] = Math.min(min[1], array[i + 1]);
|
||||
min[2] = Math.min(min[2], array[i + 2]);
|
||||
max[0] = Math.max(max[0], array[i + 0]);
|
||||
max[1] = Math.max(max[1], array[i + 1]);
|
||||
max[2] = Math.max(max[2], array[i + 2]);
|
||||
}
|
||||
decodeMat.scale(
|
||||
new THREE.Vector3((max[0] - min[0]) / segments, (max[1] - min[1]) / segments, (max[2] - min[2]) / segments)
|
||||
);
|
||||
decodeMat.elements[12] = min[0];
|
||||
decodeMat.elements[13] = min[1];
|
||||
decodeMat.elements[14] = min[2];
|
||||
decodeMat.transpose();
|
||||
const multiplier = new Float32Array([
|
||||
max[0] !== min[0] ? segments / (max[0] - min[0]) : 0,
|
||||
max[1] !== min[1] ? segments / (max[1] - min[1]) : 0,
|
||||
max[2] !== min[2] ? segments / (max[2] - min[2]) : 0
|
||||
]);
|
||||
for (let i = 0; i < array.length; i += 3) {
|
||||
quantized[i + 0] = Math.floor((array[i + 0] - min[0]) * multiplier[0]);
|
||||
quantized[i + 1] = Math.floor((array[i + 1] - min[1]) * multiplier[1]);
|
||||
quantized[i + 2] = Math.floor((array[i + 2] - min[2]) * multiplier[2]);
|
||||
}
|
||||
return {
|
||||
quantized,
|
||||
decodeMat
|
||||
};
|
||||
},
|
||||
quantizedEncodeUV: function(array, bytes) {
|
||||
let quantized, segments;
|
||||
if (bytes == 1) {
|
||||
quantized = new Uint8Array(array.length);
|
||||
segments = 255;
|
||||
} else if (bytes == 2) {
|
||||
quantized = new Uint16Array(array.length);
|
||||
segments = 65535;
|
||||
} else {
|
||||
console.error("number of bytes error! ");
|
||||
}
|
||||
const decodeMat = new THREE.Matrix3();
|
||||
const min = new Float32Array(2);
|
||||
const max = new Float32Array(2);
|
||||
min[0] = min[1] = Number.MAX_VALUE;
|
||||
max[0] = max[1] = -Number.MAX_VALUE;
|
||||
for (let i = 0; i < array.length; i += 2) {
|
||||
min[0] = Math.min(min[0], array[i + 0]);
|
||||
min[1] = Math.min(min[1], array[i + 1]);
|
||||
max[0] = Math.max(max[0], array[i + 0]);
|
||||
max[1] = Math.max(max[1], array[i + 1]);
|
||||
}
|
||||
decodeMat.scale((max[0] - min[0]) / segments, (max[1] - min[1]) / segments);
|
||||
decodeMat.elements[6] = min[0];
|
||||
decodeMat.elements[7] = min[1];
|
||||
decodeMat.transpose();
|
||||
const multiplier = new Float32Array([
|
||||
max[0] !== min[0] ? segments / (max[0] - min[0]) : 0,
|
||||
max[1] !== min[1] ? segments / (max[1] - min[1]) : 0
|
||||
]);
|
||||
for (let i = 0; i < array.length; i += 2) {
|
||||
quantized[i + 0] = Math.floor((array[i + 0] - min[0]) * multiplier[0]);
|
||||
quantized[i + 1] = Math.floor((array[i + 1] - min[1]) * multiplier[1]);
|
||||
}
|
||||
return {
|
||||
quantized,
|
||||
decodeMat
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
class PackedPhongMaterial extends THREE.MeshPhongMaterial {
|
||||
constructor(parameters) {
|
||||
super();
|
||||
this.defines = {};
|
||||
this.type = "PackedPhongMaterial";
|
||||
this.uniforms = THREE.UniformsUtils.merge([
|
||||
THREE.ShaderLib.phong.uniforms,
|
||||
{
|
||||
quantizeMatPos: { value: null },
|
||||
quantizeMatUV: { value: null }
|
||||
}
|
||||
]);
|
||||
this.vertexShader = [
|
||||
"#define PHONG",
|
||||
"varying vec3 vViewPosition;",
|
||||
"#ifndef FLAT_SHADED",
|
||||
"varying vec3 vNormal;",
|
||||
"#endif",
|
||||
THREE.ShaderChunk.common,
|
||||
THREE.ShaderChunk.uv_pars_vertex,
|
||||
THREE.ShaderChunk.uv2_pars_vertex,
|
||||
THREE.ShaderChunk.displacementmap_pars_vertex,
|
||||
THREE.ShaderChunk.envmap_pars_vertex,
|
||||
THREE.ShaderChunk.color_pars_vertex,
|
||||
THREE.ShaderChunk.fog_pars_vertex,
|
||||
THREE.ShaderChunk.morphtarget_pars_vertex,
|
||||
THREE.ShaderChunk.skinning_pars_vertex,
|
||||
THREE.ShaderChunk.shadowmap_pars_vertex,
|
||||
THREE.ShaderChunk.logdepthbuf_pars_vertex,
|
||||
THREE.ShaderChunk.clipping_planes_pars_vertex,
|
||||
`#ifdef USE_PACKED_NORMAL
|
||||
#if USE_PACKED_NORMAL == 0
|
||||
vec3 decodeNormal(vec3 packedNormal)
|
||||
{
|
||||
float x = packedNormal.x * 2.0 - 1.0;
|
||||
float y = packedNormal.y * 2.0 - 1.0;
|
||||
vec2 scth = vec2(sin(x * PI), cos(x * PI));
|
||||
vec2 scphi = vec2(sqrt(1.0 - y * y), y);
|
||||
return normalize( vec3(scth.y * scphi.x, scth.x * scphi.x, scphi.y) );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if USE_PACKED_NORMAL == 1
|
||||
vec3 decodeNormal(vec3 packedNormal)
|
||||
{
|
||||
vec3 v = vec3(packedNormal.xy, 1.0 - abs(packedNormal.x) - abs(packedNormal.y));
|
||||
if (v.z < 0.0)
|
||||
{
|
||||
v.xy = (1.0 - abs(v.yx)) * vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);
|
||||
}
|
||||
return normalize(v);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if USE_PACKED_NORMAL == 2
|
||||
vec3 decodeNormal(vec3 packedNormal)
|
||||
{
|
||||
vec3 v = (packedNormal * 2.0) - 1.0;
|
||||
return normalize(v);
|
||||
}
|
||||
#endif
|
||||
#endif`,
|
||||
`#ifdef USE_PACKED_POSITION
|
||||
#if USE_PACKED_POSITION == 0
|
||||
uniform mat4 quantizeMatPos;
|
||||
#endif
|
||||
#endif`,
|
||||
`#ifdef USE_PACKED_UV
|
||||
#if USE_PACKED_UV == 1
|
||||
uniform mat3 quantizeMatUV;
|
||||
#endif
|
||||
#endif`,
|
||||
`#ifdef USE_PACKED_UV
|
||||
#if USE_PACKED_UV == 0
|
||||
vec2 decodeUV(vec2 packedUV)
|
||||
{
|
||||
vec2 uv = (packedUV * 2.0) - 1.0;
|
||||
return uv;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if USE_PACKED_UV == 1
|
||||
vec2 decodeUV(vec2 packedUV)
|
||||
{
|
||||
vec2 uv = ( vec3(packedUV, 1.0) * quantizeMatUV ).xy;
|
||||
return uv;
|
||||
}
|
||||
#endif
|
||||
#endif`,
|
||||
"void main() {",
|
||||
THREE.ShaderChunk.uv_vertex,
|
||||
`#ifdef USE_UV
|
||||
#ifdef USE_PACKED_UV
|
||||
vUv = decodeUV(vUv);
|
||||
#endif
|
||||
#endif`,
|
||||
THREE.ShaderChunk.uv2_vertex,
|
||||
THREE.ShaderChunk.color_vertex,
|
||||
THREE.ShaderChunk.beginnormal_vertex,
|
||||
`#ifdef USE_PACKED_NORMAL
|
||||
objectNormal = decodeNormal(objectNormal);
|
||||
#endif
|
||||
|
||||
#ifdef USE_TANGENT
|
||||
vec3 objectTangent = vec3( tangent.xyz );
|
||||
#endif
|
||||
`,
|
||||
THREE.ShaderChunk.morphnormal_vertex,
|
||||
THREE.ShaderChunk.skinbase_vertex,
|
||||
THREE.ShaderChunk.skinnormal_vertex,
|
||||
THREE.ShaderChunk.defaultnormal_vertex,
|
||||
"#ifndef FLAT_SHADED",
|
||||
" vNormal = normalize( transformedNormal );",
|
||||
"#endif",
|
||||
THREE.ShaderChunk.begin_vertex,
|
||||
`#ifdef USE_PACKED_POSITION
|
||||
#if USE_PACKED_POSITION == 0
|
||||
transformed = ( vec4(transformed, 1.0) * quantizeMatPos ).xyz;
|
||||
#endif
|
||||
#endif`,
|
||||
THREE.ShaderChunk.morphtarget_vertex,
|
||||
THREE.ShaderChunk.skinning_vertex,
|
||||
THREE.ShaderChunk.displacementmap_vertex,
|
||||
THREE.ShaderChunk.project_vertex,
|
||||
THREE.ShaderChunk.logdepthbuf_vertex,
|
||||
THREE.ShaderChunk.clipping_planes_vertex,
|
||||
"vViewPosition = - mvPosition.xyz;",
|
||||
THREE.ShaderChunk.worldpos_vertex,
|
||||
THREE.ShaderChunk.envmap_vertex,
|
||||
THREE.ShaderChunk.shadowmap_vertex,
|
||||
THREE.ShaderChunk.fog_vertex,
|
||||
"}"
|
||||
].join("\n");
|
||||
this.fragmentShader = [
|
||||
"#define PHONG",
|
||||
"uniform vec3 diffuse;",
|
||||
"uniform vec3 emissive;",
|
||||
"uniform vec3 specular;",
|
||||
"uniform float shininess;",
|
||||
"uniform float opacity;",
|
||||
THREE.ShaderChunk.common,
|
||||
THREE.ShaderChunk.packing,
|
||||
THREE.ShaderChunk.dithering_pars_fragment,
|
||||
THREE.ShaderChunk.color_pars_fragment,
|
||||
THREE.ShaderChunk.uv_pars_fragment,
|
||||
THREE.ShaderChunk.uv2_pars_fragment,
|
||||
THREE.ShaderChunk.map_pars_fragment,
|
||||
THREE.ShaderChunk.alphamap_pars_fragment,
|
||||
THREE.ShaderChunk.aomap_pars_fragment,
|
||||
THREE.ShaderChunk.lightmap_pars_fragment,
|
||||
THREE.ShaderChunk.emissivemap_pars_fragment,
|
||||
THREE.ShaderChunk.envmap_common_pars_fragment,
|
||||
THREE.ShaderChunk.envmap_pars_fragment,
|
||||
THREE.ShaderChunk.cube_uv_reflection_fragment,
|
||||
THREE.ShaderChunk.fog_pars_fragment,
|
||||
THREE.ShaderChunk.bsdfs,
|
||||
THREE.ShaderChunk.lights_pars_begin,
|
||||
THREE.ShaderChunk.lights_phong_pars_fragment,
|
||||
THREE.ShaderChunk.shadowmap_pars_fragment,
|
||||
THREE.ShaderChunk.bumpmap_pars_fragment,
|
||||
THREE.ShaderChunk.normalmap_pars_fragment,
|
||||
THREE.ShaderChunk.specularmap_pars_fragment,
|
||||
THREE.ShaderChunk.logdepthbuf_pars_fragment,
|
||||
THREE.ShaderChunk.clipping_planes_pars_fragment,
|
||||
"void main() {",
|
||||
THREE.ShaderChunk.clipping_planes_fragment,
|
||||
"vec4 diffuseColor = vec4( diffuse, opacity );",
|
||||
"ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );",
|
||||
"vec3 totalEmissiveRadiance = emissive;",
|
||||
THREE.ShaderChunk.logdepthbuf_fragment,
|
||||
THREE.ShaderChunk.map_fragment,
|
||||
THREE.ShaderChunk.color_fragment,
|
||||
THREE.ShaderChunk.alphamap_fragment,
|
||||
THREE.ShaderChunk.alphatest_fragment,
|
||||
THREE.ShaderChunk.specularmap_fragment,
|
||||
THREE.ShaderChunk.normal_fragment_begin,
|
||||
THREE.ShaderChunk.normal_fragment_maps,
|
||||
THREE.ShaderChunk.emissivemap_fragment,
|
||||
// accumulation
|
||||
THREE.ShaderChunk.lights_phong_fragment,
|
||||
THREE.ShaderChunk.lights_fragment_begin,
|
||||
THREE.ShaderChunk.lights_fragment_maps,
|
||||
THREE.ShaderChunk.lights_fragment_end,
|
||||
// modulation
|
||||
THREE.ShaderChunk.aomap_fragment,
|
||||
"vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;",
|
||||
THREE.ShaderChunk.envmap_fragment,
|
||||
"gl_FragColor = vec4( outgoingLight, diffuseColor.a );",
|
||||
THREE.ShaderChunk.tonemapping_fragment,
|
||||
constants.version >= 154 ? THREE.ShaderChunk.colorspace_fragment : THREE.ShaderChunk.encodings_fragment,
|
||||
THREE.ShaderChunk.fog_fragment,
|
||||
THREE.ShaderChunk.premultiplied_alpha_fragment,
|
||||
THREE.ShaderChunk.dithering_fragment,
|
||||
"}"
|
||||
].join("\n");
|
||||
this.setValues(parameters);
|
||||
}
|
||||
}
|
||||
exports.GeometryCompressionUtils = GeometryCompressionUtils;
|
||||
exports.PackedPhongMaterial = PackedPhongMaterial;
|
||||
//# sourceMappingURL=GeometryCompressionUtils.cjs.map
|
||||
1
node_modules/three-stdlib/utils/GeometryCompressionUtils.cjs.map
generated
vendored
Normal file
1
node_modules/three-stdlib/utils/GeometryCompressionUtils.cjs.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
7
node_modules/three-stdlib/utils/GeometryCompressionUtils.d.ts
generated
vendored
Normal file
7
node_modules/three-stdlib/utils/GeometryCompressionUtils.d.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import { Mesh } from 'three'
|
||||
|
||||
export namespace GeometryCompressionUtils {
|
||||
function compressNormals(mesh: Mesh, encodeMethod: string): void
|
||||
function compressPositions(mesh: Mesh): void
|
||||
function compressUvs(mesh: Mesh): void
|
||||
}
|
||||
575
node_modules/three-stdlib/utils/GeometryCompressionUtils.js
generated
vendored
Normal file
575
node_modules/three-stdlib/utils/GeometryCompressionUtils.js
generated
vendored
Normal file
@@ -0,0 +1,575 @@
|
||||
import { BufferAttribute, Matrix4, Vector3, Matrix3, MeshPhongMaterial, UniformsUtils, ShaderLib, ShaderChunk } from "three";
|
||||
import { version } from "../_polyfill/constants.js";
|
||||
var GeometryCompressionUtils = {
|
||||
/**
|
||||
* Make the input mesh.geometry's normal attribute encoded and compressed by 3 different methods.
|
||||
* Also will change the mesh.material to `PackedPhongMaterial` which let the vertex shader program decode the normal data.
|
||||
*
|
||||
* @param {THREE.Mesh} mesh
|
||||
* @param {String} encodeMethod "DEFAULT" || "OCT1Byte" || "OCT2Byte" || "ANGLES"
|
||||
*
|
||||
*/
|
||||
compressNormals: function(mesh, encodeMethod) {
|
||||
if (!mesh.geometry) {
|
||||
console.error("Mesh must contain geometry. ");
|
||||
}
|
||||
const normal = mesh.geometry.attributes.normal;
|
||||
if (!normal) {
|
||||
console.error("Geometry must contain normal attribute. ");
|
||||
}
|
||||
if (normal.isPacked)
|
||||
return;
|
||||
if (normal.itemSize != 3) {
|
||||
console.error("normal.itemSize is not 3, which cannot be encoded. ");
|
||||
}
|
||||
const array = normal.array;
|
||||
const count = normal.count;
|
||||
let result;
|
||||
if (encodeMethod == "DEFAULT") {
|
||||
result = new Uint8Array(count * 3);
|
||||
for (let idx = 0; idx < array.length; idx += 3) {
|
||||
const encoded = this.EncodingFuncs.defaultEncode(array[idx], array[idx + 1], array[idx + 2], 1);
|
||||
result[idx + 0] = encoded[0];
|
||||
result[idx + 1] = encoded[1];
|
||||
result[idx + 2] = encoded[2];
|
||||
}
|
||||
mesh.geometry.setAttribute("normal", new BufferAttribute(result, 3, true));
|
||||
mesh.geometry.attributes.normal.bytes = result.length * 1;
|
||||
} else if (encodeMethod == "OCT1Byte") {
|
||||
result = new Int8Array(count * 2);
|
||||
for (let idx = 0; idx < array.length; idx += 3) {
|
||||
const encoded = this.EncodingFuncs.octEncodeBest(array[idx], array[idx + 1], array[idx + 2], 1);
|
||||
result[idx / 3 * 2 + 0] = encoded[0];
|
||||
result[idx / 3 * 2 + 1] = encoded[1];
|
||||
}
|
||||
mesh.geometry.setAttribute("normal", new BufferAttribute(result, 2, true));
|
||||
mesh.geometry.attributes.normal.bytes = result.length * 1;
|
||||
} else if (encodeMethod == "OCT2Byte") {
|
||||
result = new Int16Array(count * 2);
|
||||
for (let idx = 0; idx < array.length; idx += 3) {
|
||||
const encoded = this.EncodingFuncs.octEncodeBest(array[idx], array[idx + 1], array[idx + 2], 2);
|
||||
result[idx / 3 * 2 + 0] = encoded[0];
|
||||
result[idx / 3 * 2 + 1] = encoded[1];
|
||||
}
|
||||
mesh.geometry.setAttribute("normal", new BufferAttribute(result, 2, true));
|
||||
mesh.geometry.attributes.normal.bytes = result.length * 2;
|
||||
} else if (encodeMethod == "ANGLES") {
|
||||
result = new Uint16Array(count * 2);
|
||||
for (let idx = 0; idx < array.length; idx += 3) {
|
||||
const encoded = this.EncodingFuncs.anglesEncode(array[idx], array[idx + 1], array[idx + 2]);
|
||||
result[idx / 3 * 2 + 0] = encoded[0];
|
||||
result[idx / 3 * 2 + 1] = encoded[1];
|
||||
}
|
||||
mesh.geometry.setAttribute("normal", new BufferAttribute(result, 2, true));
|
||||
mesh.geometry.attributes.normal.bytes = result.length * 2;
|
||||
} else {
|
||||
console.error("Unrecognized encoding method, should be `DEFAULT` or `ANGLES` or `OCT`. ");
|
||||
}
|
||||
mesh.geometry.attributes.normal.needsUpdate = true;
|
||||
mesh.geometry.attributes.normal.isPacked = true;
|
||||
mesh.geometry.attributes.normal.packingMethod = encodeMethod;
|
||||
if (!(mesh.material instanceof PackedPhongMaterial)) {
|
||||
mesh.material = new PackedPhongMaterial().copy(mesh.material);
|
||||
}
|
||||
if (encodeMethod == "ANGLES") {
|
||||
mesh.material.defines.USE_PACKED_NORMAL = 0;
|
||||
}
|
||||
if (encodeMethod == "OCT1Byte") {
|
||||
mesh.material.defines.USE_PACKED_NORMAL = 1;
|
||||
}
|
||||
if (encodeMethod == "OCT2Byte") {
|
||||
mesh.material.defines.USE_PACKED_NORMAL = 1;
|
||||
}
|
||||
if (encodeMethod == "DEFAULT") {
|
||||
mesh.material.defines.USE_PACKED_NORMAL = 2;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Make the input mesh.geometry's position attribute encoded and compressed.
|
||||
* Also will change the mesh.material to `PackedPhongMaterial` which let the vertex shader program decode the position data.
|
||||
*
|
||||
* @param {THREE.Mesh} mesh
|
||||
*
|
||||
*/
|
||||
compressPositions: function(mesh) {
|
||||
if (!mesh.geometry) {
|
||||
console.error("Mesh must contain geometry. ");
|
||||
}
|
||||
const position = mesh.geometry.attributes.position;
|
||||
if (!position) {
|
||||
console.error("Geometry must contain position attribute. ");
|
||||
}
|
||||
if (position.isPacked)
|
||||
return;
|
||||
if (position.itemSize != 3) {
|
||||
console.error("position.itemSize is not 3, which cannot be packed. ");
|
||||
}
|
||||
const array = position.array;
|
||||
const encodingBytes = 2;
|
||||
const result = this.EncodingFuncs.quantizedEncode(array, encodingBytes);
|
||||
const quantized = result.quantized;
|
||||
const decodeMat = result.decodeMat;
|
||||
if (mesh.geometry.boundingBox == null)
|
||||
mesh.geometry.computeBoundingBox();
|
||||
if (mesh.geometry.boundingSphere == null)
|
||||
mesh.geometry.computeBoundingSphere();
|
||||
mesh.geometry.setAttribute("position", new BufferAttribute(quantized, 3));
|
||||
mesh.geometry.attributes.position.isPacked = true;
|
||||
mesh.geometry.attributes.position.needsUpdate = true;
|
||||
mesh.geometry.attributes.position.bytes = quantized.length * encodingBytes;
|
||||
if (!(mesh.material instanceof PackedPhongMaterial)) {
|
||||
mesh.material = new PackedPhongMaterial().copy(mesh.material);
|
||||
}
|
||||
mesh.material.defines.USE_PACKED_POSITION = 0;
|
||||
mesh.material.uniforms.quantizeMatPos.value = decodeMat;
|
||||
mesh.material.uniforms.quantizeMatPos.needsUpdate = true;
|
||||
},
|
||||
/**
|
||||
* Make the input mesh.geometry's uv attribute encoded and compressed.
|
||||
* Also will change the mesh.material to `PackedPhongMaterial` which let the vertex shader program decode the uv data.
|
||||
*
|
||||
* @param {THREE.Mesh} mesh
|
||||
*
|
||||
*/
|
||||
compressUvs: function(mesh) {
|
||||
if (!mesh.geometry) {
|
||||
console.error("Mesh must contain geometry property. ");
|
||||
}
|
||||
const uvs = mesh.geometry.attributes.uv;
|
||||
if (!uvs) {
|
||||
console.error("Geometry must contain uv attribute. ");
|
||||
}
|
||||
if (uvs.isPacked)
|
||||
return;
|
||||
const range = { min: Infinity, max: -Infinity };
|
||||
const array = uvs.array;
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
range.min = Math.min(range.min, array[i]);
|
||||
range.max = Math.max(range.max, array[i]);
|
||||
}
|
||||
let result;
|
||||
if (range.min >= -1 && range.max <= 1) {
|
||||
result = new Uint16Array(array.length);
|
||||
for (let i = 0; i < array.length; i += 2) {
|
||||
const encoded = this.EncodingFuncs.defaultEncode(array[i], array[i + 1], 0, 2);
|
||||
result[i] = encoded[0];
|
||||
result[i + 1] = encoded[1];
|
||||
}
|
||||
mesh.geometry.setAttribute("uv", new BufferAttribute(result, 2, true));
|
||||
mesh.geometry.attributes.uv.isPacked = true;
|
||||
mesh.geometry.attributes.uv.needsUpdate = true;
|
||||
mesh.geometry.attributes.uv.bytes = result.length * 2;
|
||||
if (!(mesh.material instanceof PackedPhongMaterial)) {
|
||||
mesh.material = new PackedPhongMaterial().copy(mesh.material);
|
||||
}
|
||||
mesh.material.defines.USE_PACKED_UV = 0;
|
||||
} else {
|
||||
result = this.EncodingFuncs.quantizedEncodeUV(array, 2);
|
||||
mesh.geometry.setAttribute("uv", new BufferAttribute(result.quantized, 2));
|
||||
mesh.geometry.attributes.uv.isPacked = true;
|
||||
mesh.geometry.attributes.uv.needsUpdate = true;
|
||||
mesh.geometry.attributes.uv.bytes = result.quantized.length * 2;
|
||||
if (!(mesh.material instanceof PackedPhongMaterial)) {
|
||||
mesh.material = new PackedPhongMaterial().copy(mesh.material);
|
||||
}
|
||||
mesh.material.defines.USE_PACKED_UV = 1;
|
||||
mesh.material.uniforms.quantizeMatUV.value = result.decodeMat;
|
||||
mesh.material.uniforms.quantizeMatUV.needsUpdate = true;
|
||||
}
|
||||
},
|
||||
EncodingFuncs: {
|
||||
defaultEncode: function(x, y, z, bytes) {
|
||||
if (bytes == 1) {
|
||||
const tmpx = Math.round((x + 1) * 0.5 * 255);
|
||||
const tmpy = Math.round((y + 1) * 0.5 * 255);
|
||||
const tmpz = Math.round((z + 1) * 0.5 * 255);
|
||||
return new Uint8Array([tmpx, tmpy, tmpz]);
|
||||
} else if (bytes == 2) {
|
||||
const tmpx = Math.round((x + 1) * 0.5 * 65535);
|
||||
const tmpy = Math.round((y + 1) * 0.5 * 65535);
|
||||
const tmpz = Math.round((z + 1) * 0.5 * 65535);
|
||||
return new Uint16Array([tmpx, tmpy, tmpz]);
|
||||
} else {
|
||||
console.error("number of bytes must be 1 or 2");
|
||||
}
|
||||
},
|
||||
defaultDecode: function(array, bytes) {
|
||||
if (bytes == 1) {
|
||||
return [array[0] / 255 * 2 - 1, array[1] / 255 * 2 - 1, array[2] / 255 * 2 - 1];
|
||||
} else if (bytes == 2) {
|
||||
return [array[0] / 65535 * 2 - 1, array[1] / 65535 * 2 - 1, array[2] / 65535 * 2 - 1];
|
||||
} else {
|
||||
console.error("number of bytes must be 1 or 2");
|
||||
}
|
||||
},
|
||||
// for `Angles` encoding
|
||||
anglesEncode: function(x, y, z) {
|
||||
const normal0 = parseInt(0.5 * (1 + Math.atan2(y, x) / Math.PI) * 65535);
|
||||
const normal1 = parseInt(0.5 * (1 + z) * 65535);
|
||||
return new Uint16Array([normal0, normal1]);
|
||||
},
|
||||
// for `Octahedron` encoding
|
||||
octEncodeBest: function(x, y, z, bytes) {
|
||||
var oct, dec, best, currentCos, bestCos;
|
||||
best = oct = octEncodeVec3(x, y, z, "floor", "floor");
|
||||
dec = octDecodeVec2(oct);
|
||||
bestCos = dot(x, y, z, dec);
|
||||
oct = octEncodeVec3(x, y, z, "ceil", "floor");
|
||||
dec = octDecodeVec2(oct);
|
||||
currentCos = dot(x, y, z, dec);
|
||||
if (currentCos > bestCos) {
|
||||
best = oct;
|
||||
bestCos = currentCos;
|
||||
}
|
||||
oct = octEncodeVec3(x, y, z, "floor", "ceil");
|
||||
dec = octDecodeVec2(oct);
|
||||
currentCos = dot(x, y, z, dec);
|
||||
if (currentCos > bestCos) {
|
||||
best = oct;
|
||||
bestCos = currentCos;
|
||||
}
|
||||
oct = octEncodeVec3(x, y, z, "ceil", "ceil");
|
||||
dec = octDecodeVec2(oct);
|
||||
currentCos = dot(x, y, z, dec);
|
||||
if (currentCos > bestCos) {
|
||||
best = oct;
|
||||
}
|
||||
return best;
|
||||
function octEncodeVec3(x0, y0, z0, xfunc, yfunc) {
|
||||
var x2 = x0 / (Math.abs(x0) + Math.abs(y0) + Math.abs(z0));
|
||||
var y2 = y0 / (Math.abs(x0) + Math.abs(y0) + Math.abs(z0));
|
||||
if (z < 0) {
|
||||
var tempx = (1 - Math.abs(y2)) * (x2 >= 0 ? 1 : -1);
|
||||
var tempy = (1 - Math.abs(x2)) * (y2 >= 0 ? 1 : -1);
|
||||
x2 = tempx;
|
||||
y2 = tempy;
|
||||
var diff = 1 - Math.abs(x2) - Math.abs(y2);
|
||||
if (diff > 0) {
|
||||
diff += 1e-3;
|
||||
x2 += x2 > 0 ? diff / 2 : -diff / 2;
|
||||
y2 += y2 > 0 ? diff / 2 : -diff / 2;
|
||||
}
|
||||
}
|
||||
if (bytes == 1) {
|
||||
return new Int8Array([Math[xfunc](x2 * 127.5 + (x2 < 0 ? 1 : 0)), Math[yfunc](y2 * 127.5 + (y2 < 0 ? 1 : 0))]);
|
||||
}
|
||||
if (bytes == 2) {
|
||||
return new Int16Array([
|
||||
Math[xfunc](x2 * 32767.5 + (x2 < 0 ? 1 : 0)),
|
||||
Math[yfunc](y2 * 32767.5 + (y2 < 0 ? 1 : 0))
|
||||
]);
|
||||
}
|
||||
}
|
||||
function octDecodeVec2(oct2) {
|
||||
var x2 = oct2[0];
|
||||
var y2 = oct2[1];
|
||||
if (bytes == 1) {
|
||||
x2 /= x2 < 0 ? 127 : 128;
|
||||
y2 /= y2 < 0 ? 127 : 128;
|
||||
} else if (bytes == 2) {
|
||||
x2 /= x2 < 0 ? 32767 : 32768;
|
||||
y2 /= y2 < 0 ? 32767 : 32768;
|
||||
}
|
||||
var z2 = 1 - Math.abs(x2) - Math.abs(y2);
|
||||
if (z2 < 0) {
|
||||
var tmpx = x2;
|
||||
x2 = (1 - Math.abs(y2)) * (x2 >= 0 ? 1 : -1);
|
||||
y2 = (1 - Math.abs(tmpx)) * (y2 >= 0 ? 1 : -1);
|
||||
}
|
||||
var length = Math.sqrt(x2 * x2 + y2 * y2 + z2 * z2);
|
||||
return [x2 / length, y2 / length, z2 / length];
|
||||
}
|
||||
function dot(x2, y2, z2, vec3) {
|
||||
return x2 * vec3[0] + y2 * vec3[1] + z2 * vec3[2];
|
||||
}
|
||||
},
|
||||
quantizedEncode: function(array, bytes) {
|
||||
let quantized, segments;
|
||||
if (bytes == 1) {
|
||||
quantized = new Uint8Array(array.length);
|
||||
segments = 255;
|
||||
} else if (bytes == 2) {
|
||||
quantized = new Uint16Array(array.length);
|
||||
segments = 65535;
|
||||
} else {
|
||||
console.error("number of bytes error! ");
|
||||
}
|
||||
const decodeMat = new Matrix4();
|
||||
const min = new Float32Array(3);
|
||||
const max = new Float32Array(3);
|
||||
min[0] = min[1] = min[2] = Number.MAX_VALUE;
|
||||
max[0] = max[1] = max[2] = -Number.MAX_VALUE;
|
||||
for (let i = 0; i < array.length; i += 3) {
|
||||
min[0] = Math.min(min[0], array[i + 0]);
|
||||
min[1] = Math.min(min[1], array[i + 1]);
|
||||
min[2] = Math.min(min[2], array[i + 2]);
|
||||
max[0] = Math.max(max[0], array[i + 0]);
|
||||
max[1] = Math.max(max[1], array[i + 1]);
|
||||
max[2] = Math.max(max[2], array[i + 2]);
|
||||
}
|
||||
decodeMat.scale(
|
||||
new Vector3((max[0] - min[0]) / segments, (max[1] - min[1]) / segments, (max[2] - min[2]) / segments)
|
||||
);
|
||||
decodeMat.elements[12] = min[0];
|
||||
decodeMat.elements[13] = min[1];
|
||||
decodeMat.elements[14] = min[2];
|
||||
decodeMat.transpose();
|
||||
const multiplier = new Float32Array([
|
||||
max[0] !== min[0] ? segments / (max[0] - min[0]) : 0,
|
||||
max[1] !== min[1] ? segments / (max[1] - min[1]) : 0,
|
||||
max[2] !== min[2] ? segments / (max[2] - min[2]) : 0
|
||||
]);
|
||||
for (let i = 0; i < array.length; i += 3) {
|
||||
quantized[i + 0] = Math.floor((array[i + 0] - min[0]) * multiplier[0]);
|
||||
quantized[i + 1] = Math.floor((array[i + 1] - min[1]) * multiplier[1]);
|
||||
quantized[i + 2] = Math.floor((array[i + 2] - min[2]) * multiplier[2]);
|
||||
}
|
||||
return {
|
||||
quantized,
|
||||
decodeMat
|
||||
};
|
||||
},
|
||||
quantizedEncodeUV: function(array, bytes) {
|
||||
let quantized, segments;
|
||||
if (bytes == 1) {
|
||||
quantized = new Uint8Array(array.length);
|
||||
segments = 255;
|
||||
} else if (bytes == 2) {
|
||||
quantized = new Uint16Array(array.length);
|
||||
segments = 65535;
|
||||
} else {
|
||||
console.error("number of bytes error! ");
|
||||
}
|
||||
const decodeMat = new Matrix3();
|
||||
const min = new Float32Array(2);
|
||||
const max = new Float32Array(2);
|
||||
min[0] = min[1] = Number.MAX_VALUE;
|
||||
max[0] = max[1] = -Number.MAX_VALUE;
|
||||
for (let i = 0; i < array.length; i += 2) {
|
||||
min[0] = Math.min(min[0], array[i + 0]);
|
||||
min[1] = Math.min(min[1], array[i + 1]);
|
||||
max[0] = Math.max(max[0], array[i + 0]);
|
||||
max[1] = Math.max(max[1], array[i + 1]);
|
||||
}
|
||||
decodeMat.scale((max[0] - min[0]) / segments, (max[1] - min[1]) / segments);
|
||||
decodeMat.elements[6] = min[0];
|
||||
decodeMat.elements[7] = min[1];
|
||||
decodeMat.transpose();
|
||||
const multiplier = new Float32Array([
|
||||
max[0] !== min[0] ? segments / (max[0] - min[0]) : 0,
|
||||
max[1] !== min[1] ? segments / (max[1] - min[1]) : 0
|
||||
]);
|
||||
for (let i = 0; i < array.length; i += 2) {
|
||||
quantized[i + 0] = Math.floor((array[i + 0] - min[0]) * multiplier[0]);
|
||||
quantized[i + 1] = Math.floor((array[i + 1] - min[1]) * multiplier[1]);
|
||||
}
|
||||
return {
|
||||
quantized,
|
||||
decodeMat
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
class PackedPhongMaterial extends MeshPhongMaterial {
|
||||
constructor(parameters) {
|
||||
super();
|
||||
this.defines = {};
|
||||
this.type = "PackedPhongMaterial";
|
||||
this.uniforms = UniformsUtils.merge([
|
||||
ShaderLib.phong.uniforms,
|
||||
{
|
||||
quantizeMatPos: { value: null },
|
||||
quantizeMatUV: { value: null }
|
||||
}
|
||||
]);
|
||||
this.vertexShader = [
|
||||
"#define PHONG",
|
||||
"varying vec3 vViewPosition;",
|
||||
"#ifndef FLAT_SHADED",
|
||||
"varying vec3 vNormal;",
|
||||
"#endif",
|
||||
ShaderChunk.common,
|
||||
ShaderChunk.uv_pars_vertex,
|
||||
ShaderChunk.uv2_pars_vertex,
|
||||
ShaderChunk.displacementmap_pars_vertex,
|
||||
ShaderChunk.envmap_pars_vertex,
|
||||
ShaderChunk.color_pars_vertex,
|
||||
ShaderChunk.fog_pars_vertex,
|
||||
ShaderChunk.morphtarget_pars_vertex,
|
||||
ShaderChunk.skinning_pars_vertex,
|
||||
ShaderChunk.shadowmap_pars_vertex,
|
||||
ShaderChunk.logdepthbuf_pars_vertex,
|
||||
ShaderChunk.clipping_planes_pars_vertex,
|
||||
`#ifdef USE_PACKED_NORMAL
|
||||
#if USE_PACKED_NORMAL == 0
|
||||
vec3 decodeNormal(vec3 packedNormal)
|
||||
{
|
||||
float x = packedNormal.x * 2.0 - 1.0;
|
||||
float y = packedNormal.y * 2.0 - 1.0;
|
||||
vec2 scth = vec2(sin(x * PI), cos(x * PI));
|
||||
vec2 scphi = vec2(sqrt(1.0 - y * y), y);
|
||||
return normalize( vec3(scth.y * scphi.x, scth.x * scphi.x, scphi.y) );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if USE_PACKED_NORMAL == 1
|
||||
vec3 decodeNormal(vec3 packedNormal)
|
||||
{
|
||||
vec3 v = vec3(packedNormal.xy, 1.0 - abs(packedNormal.x) - abs(packedNormal.y));
|
||||
if (v.z < 0.0)
|
||||
{
|
||||
v.xy = (1.0 - abs(v.yx)) * vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);
|
||||
}
|
||||
return normalize(v);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if USE_PACKED_NORMAL == 2
|
||||
vec3 decodeNormal(vec3 packedNormal)
|
||||
{
|
||||
vec3 v = (packedNormal * 2.0) - 1.0;
|
||||
return normalize(v);
|
||||
}
|
||||
#endif
|
||||
#endif`,
|
||||
`#ifdef USE_PACKED_POSITION
|
||||
#if USE_PACKED_POSITION == 0
|
||||
uniform mat4 quantizeMatPos;
|
||||
#endif
|
||||
#endif`,
|
||||
`#ifdef USE_PACKED_UV
|
||||
#if USE_PACKED_UV == 1
|
||||
uniform mat3 quantizeMatUV;
|
||||
#endif
|
||||
#endif`,
|
||||
`#ifdef USE_PACKED_UV
|
||||
#if USE_PACKED_UV == 0
|
||||
vec2 decodeUV(vec2 packedUV)
|
||||
{
|
||||
vec2 uv = (packedUV * 2.0) - 1.0;
|
||||
return uv;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if USE_PACKED_UV == 1
|
||||
vec2 decodeUV(vec2 packedUV)
|
||||
{
|
||||
vec2 uv = ( vec3(packedUV, 1.0) * quantizeMatUV ).xy;
|
||||
return uv;
|
||||
}
|
||||
#endif
|
||||
#endif`,
|
||||
"void main() {",
|
||||
ShaderChunk.uv_vertex,
|
||||
`#ifdef USE_UV
|
||||
#ifdef USE_PACKED_UV
|
||||
vUv = decodeUV(vUv);
|
||||
#endif
|
||||
#endif`,
|
||||
ShaderChunk.uv2_vertex,
|
||||
ShaderChunk.color_vertex,
|
||||
ShaderChunk.beginnormal_vertex,
|
||||
`#ifdef USE_PACKED_NORMAL
|
||||
objectNormal = decodeNormal(objectNormal);
|
||||
#endif
|
||||
|
||||
#ifdef USE_TANGENT
|
||||
vec3 objectTangent = vec3( tangent.xyz );
|
||||
#endif
|
||||
`,
|
||||
ShaderChunk.morphnormal_vertex,
|
||||
ShaderChunk.skinbase_vertex,
|
||||
ShaderChunk.skinnormal_vertex,
|
||||
ShaderChunk.defaultnormal_vertex,
|
||||
"#ifndef FLAT_SHADED",
|
||||
" vNormal = normalize( transformedNormal );",
|
||||
"#endif",
|
||||
ShaderChunk.begin_vertex,
|
||||
`#ifdef USE_PACKED_POSITION
|
||||
#if USE_PACKED_POSITION == 0
|
||||
transformed = ( vec4(transformed, 1.0) * quantizeMatPos ).xyz;
|
||||
#endif
|
||||
#endif`,
|
||||
ShaderChunk.morphtarget_vertex,
|
||||
ShaderChunk.skinning_vertex,
|
||||
ShaderChunk.displacementmap_vertex,
|
||||
ShaderChunk.project_vertex,
|
||||
ShaderChunk.logdepthbuf_vertex,
|
||||
ShaderChunk.clipping_planes_vertex,
|
||||
"vViewPosition = - mvPosition.xyz;",
|
||||
ShaderChunk.worldpos_vertex,
|
||||
ShaderChunk.envmap_vertex,
|
||||
ShaderChunk.shadowmap_vertex,
|
||||
ShaderChunk.fog_vertex,
|
||||
"}"
|
||||
].join("\n");
|
||||
this.fragmentShader = [
|
||||
"#define PHONG",
|
||||
"uniform vec3 diffuse;",
|
||||
"uniform vec3 emissive;",
|
||||
"uniform vec3 specular;",
|
||||
"uniform float shininess;",
|
||||
"uniform float opacity;",
|
||||
ShaderChunk.common,
|
||||
ShaderChunk.packing,
|
||||
ShaderChunk.dithering_pars_fragment,
|
||||
ShaderChunk.color_pars_fragment,
|
||||
ShaderChunk.uv_pars_fragment,
|
||||
ShaderChunk.uv2_pars_fragment,
|
||||
ShaderChunk.map_pars_fragment,
|
||||
ShaderChunk.alphamap_pars_fragment,
|
||||
ShaderChunk.aomap_pars_fragment,
|
||||
ShaderChunk.lightmap_pars_fragment,
|
||||
ShaderChunk.emissivemap_pars_fragment,
|
||||
ShaderChunk.envmap_common_pars_fragment,
|
||||
ShaderChunk.envmap_pars_fragment,
|
||||
ShaderChunk.cube_uv_reflection_fragment,
|
||||
ShaderChunk.fog_pars_fragment,
|
||||
ShaderChunk.bsdfs,
|
||||
ShaderChunk.lights_pars_begin,
|
||||
ShaderChunk.lights_phong_pars_fragment,
|
||||
ShaderChunk.shadowmap_pars_fragment,
|
||||
ShaderChunk.bumpmap_pars_fragment,
|
||||
ShaderChunk.normalmap_pars_fragment,
|
||||
ShaderChunk.specularmap_pars_fragment,
|
||||
ShaderChunk.logdepthbuf_pars_fragment,
|
||||
ShaderChunk.clipping_planes_pars_fragment,
|
||||
"void main() {",
|
||||
ShaderChunk.clipping_planes_fragment,
|
||||
"vec4 diffuseColor = vec4( diffuse, opacity );",
|
||||
"ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );",
|
||||
"vec3 totalEmissiveRadiance = emissive;",
|
||||
ShaderChunk.logdepthbuf_fragment,
|
||||
ShaderChunk.map_fragment,
|
||||
ShaderChunk.color_fragment,
|
||||
ShaderChunk.alphamap_fragment,
|
||||
ShaderChunk.alphatest_fragment,
|
||||
ShaderChunk.specularmap_fragment,
|
||||
ShaderChunk.normal_fragment_begin,
|
||||
ShaderChunk.normal_fragment_maps,
|
||||
ShaderChunk.emissivemap_fragment,
|
||||
// accumulation
|
||||
ShaderChunk.lights_phong_fragment,
|
||||
ShaderChunk.lights_fragment_begin,
|
||||
ShaderChunk.lights_fragment_maps,
|
||||
ShaderChunk.lights_fragment_end,
|
||||
// modulation
|
||||
ShaderChunk.aomap_fragment,
|
||||
"vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;",
|
||||
ShaderChunk.envmap_fragment,
|
||||
"gl_FragColor = vec4( outgoingLight, diffuseColor.a );",
|
||||
ShaderChunk.tonemapping_fragment,
|
||||
version >= 154 ? ShaderChunk.colorspace_fragment : ShaderChunk.encodings_fragment,
|
||||
ShaderChunk.fog_fragment,
|
||||
ShaderChunk.premultiplied_alpha_fragment,
|
||||
ShaderChunk.dithering_fragment,
|
||||
"}"
|
||||
].join("\n");
|
||||
this.setValues(parameters);
|
||||
}
|
||||
}
|
||||
export {
|
||||
GeometryCompressionUtils,
|
||||
PackedPhongMaterial
|
||||
};
|
||||
//# sourceMappingURL=GeometryCompressionUtils.js.map
|
||||
1
node_modules/three-stdlib/utils/GeometryCompressionUtils.js.map
generated
vendored
Normal file
1
node_modules/three-stdlib/utils/GeometryCompressionUtils.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
110
node_modules/three-stdlib/utils/GeometryUtils.cjs
generated
vendored
Normal file
110
node_modules/three-stdlib/utils/GeometryUtils.cjs
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
||||
const THREE = require("three");
|
||||
const hilbert2D = (center = new THREE.Vector3(0, 0, 0), size = 10, iterations = 1, v0 = 0, v1 = 1, v2 = 2, v3 = 3) => {
|
||||
const half = size / 2;
|
||||
const vec_s = [
|
||||
new THREE.Vector3(center.x - half, center.y, center.z - half),
|
||||
new THREE.Vector3(center.x - half, center.y, center.z + half),
|
||||
new THREE.Vector3(center.x + half, center.y, center.z + half),
|
||||
new THREE.Vector3(center.x + half, center.y, center.z - half)
|
||||
];
|
||||
const vec = [vec_s[v0], vec_s[v1], vec_s[v2], vec_s[v3]];
|
||||
if (0 <= --iterations) {
|
||||
const tmp = [];
|
||||
Array.prototype.push.apply(tmp, hilbert2D(vec[0], half, iterations, v0, v3, v2, v1));
|
||||
Array.prototype.push.apply(tmp, hilbert2D(vec[1], half, iterations, v0, v1, v2, v3));
|
||||
Array.prototype.push.apply(tmp, hilbert2D(vec[2], half, iterations, v0, v1, v2, v3));
|
||||
Array.prototype.push.apply(tmp, hilbert2D(vec[3], half, iterations, v2, v1, v0, v3));
|
||||
return tmp;
|
||||
}
|
||||
return vec;
|
||||
};
|
||||
const hilbert3D = (center = new THREE.Vector3(0, 0, 0), size = 10, iterations = 1, v0 = 0, v1 = 1, v2 = 2, v3 = 3, v4 = 4, v5 = 5, v6 = 6, v7 = 7) => {
|
||||
const half = size / 2;
|
||||
const vec_s = [
|
||||
new THREE.Vector3(center.x - half, center.y + half, center.z - half),
|
||||
new THREE.Vector3(center.x - half, center.y + half, center.z + half),
|
||||
new THREE.Vector3(center.x - half, center.y - half, center.z + half),
|
||||
new THREE.Vector3(center.x - half, center.y - half, center.z - half),
|
||||
new THREE.Vector3(center.x + half, center.y - half, center.z - half),
|
||||
new THREE.Vector3(center.x + half, center.y - half, center.z + half),
|
||||
new THREE.Vector3(center.x + half, center.y + half, center.z + half),
|
||||
new THREE.Vector3(center.x + half, center.y + half, center.z - half)
|
||||
];
|
||||
const vec = [vec_s[v0], vec_s[v1], vec_s[v2], vec_s[v3], vec_s[v4], vec_s[v5], vec_s[v6], vec_s[v7]];
|
||||
if (--iterations >= 0) {
|
||||
const tmp = [];
|
||||
Array.prototype.push.apply(tmp, hilbert3D(vec[0], half, iterations, v0, v3, v4, v7, v6, v5, v2, v1));
|
||||
Array.prototype.push.apply(tmp, hilbert3D(vec[1], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3));
|
||||
Array.prototype.push.apply(tmp, hilbert3D(vec[2], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3));
|
||||
Array.prototype.push.apply(tmp, hilbert3D(vec[3], half, iterations, v2, v3, v0, v1, v6, v7, v4, v5));
|
||||
Array.prototype.push.apply(tmp, hilbert3D(vec[4], half, iterations, v2, v3, v0, v1, v6, v7, v4, v5));
|
||||
Array.prototype.push.apply(tmp, hilbert3D(vec[5], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7));
|
||||
Array.prototype.push.apply(tmp, hilbert3D(vec[6], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7));
|
||||
Array.prototype.push.apply(tmp, hilbert3D(vec[7], half, iterations, v6, v5, v2, v1, v0, v3, v4, v7));
|
||||
return tmp;
|
||||
}
|
||||
return vec;
|
||||
};
|
||||
const gosper = (size = 1) => {
|
||||
function fractalize(config) {
|
||||
let output = "";
|
||||
let input = config.axiom;
|
||||
for (let i = 0, il = config.steps; 0 <= il ? i < il : i > il; 0 <= il ? i++ : i--) {
|
||||
output = "";
|
||||
for (let j = 0, jl = input.length; j < jl; j++) {
|
||||
const char = input[j];
|
||||
if (char in config.rules) {
|
||||
output += config.rules[char];
|
||||
} else {
|
||||
output += char;
|
||||
}
|
||||
}
|
||||
input = output;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
function toPoints(config) {
|
||||
let currX = 0;
|
||||
let currY = 0;
|
||||
let angle = 0;
|
||||
const path = [0, 0, 0];
|
||||
const fractal = config.fractal;
|
||||
for (let i = 0, l = fractal.length; i < l; i++) {
|
||||
const char = fractal[i];
|
||||
if (char === "+") {
|
||||
angle += config.angle;
|
||||
} else if (char === "-") {
|
||||
angle -= config.angle;
|
||||
} else if (char === "F") {
|
||||
currX += config.size * Math.cos(angle);
|
||||
currY += -config.size * Math.sin(angle);
|
||||
path.push(currX, currY, 0);
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
const gosper2 = fractalize({
|
||||
axiom: "A",
|
||||
steps: 4,
|
||||
rules: {
|
||||
A: "A+BF++BF-FA--FAFA-BF+",
|
||||
B: "-FA+BFBF++BF+FA--FA-B"
|
||||
}
|
||||
});
|
||||
const points = toPoints({
|
||||
fractal: gosper2,
|
||||
size,
|
||||
angle: Math.PI / 3
|
||||
// 60 degrees
|
||||
});
|
||||
return points;
|
||||
};
|
||||
const GeometryUtils = {
|
||||
hilbert3D,
|
||||
gosper,
|
||||
hilbert2D
|
||||
};
|
||||
exports.GeometryUtils = GeometryUtils;
|
||||
//# sourceMappingURL=GeometryUtils.cjs.map
|
||||
1
node_modules/three-stdlib/utils/GeometryUtils.cjs.map
generated
vendored
Normal file
1
node_modules/three-stdlib/utils/GeometryUtils.cjs.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
6
node_modules/three-stdlib/utils/GeometryUtils.d.ts
generated
vendored
Normal file
6
node_modules/three-stdlib/utils/GeometryUtils.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import { Vector3 } from 'three';
|
||||
export declare const GeometryUtils: {
|
||||
hilbert3D: (center?: Vector3, size?: number, iterations?: number, v0?: number, v1?: number, v2?: number, v3?: number, v4?: number, v5?: number, v6?: number, v7?: number) => Vector3[];
|
||||
gosper: (size?: number) => number[];
|
||||
hilbert2D: (center?: Vector3, size?: number, iterations?: number, v0?: number, v1?: number, v2?: number, v3?: number) => Vector3[];
|
||||
};
|
||||
110
node_modules/three-stdlib/utils/GeometryUtils.js
generated
vendored
Normal file
110
node_modules/three-stdlib/utils/GeometryUtils.js
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
import { Vector3 } from "three";
|
||||
const hilbert2D = (center = new Vector3(0, 0, 0), size = 10, iterations = 1, v0 = 0, v1 = 1, v2 = 2, v3 = 3) => {
|
||||
const half = size / 2;
|
||||
const vec_s = [
|
||||
new Vector3(center.x - half, center.y, center.z - half),
|
||||
new Vector3(center.x - half, center.y, center.z + half),
|
||||
new Vector3(center.x + half, center.y, center.z + half),
|
||||
new Vector3(center.x + half, center.y, center.z - half)
|
||||
];
|
||||
const vec = [vec_s[v0], vec_s[v1], vec_s[v2], vec_s[v3]];
|
||||
if (0 <= --iterations) {
|
||||
const tmp = [];
|
||||
Array.prototype.push.apply(tmp, hilbert2D(vec[0], half, iterations, v0, v3, v2, v1));
|
||||
Array.prototype.push.apply(tmp, hilbert2D(vec[1], half, iterations, v0, v1, v2, v3));
|
||||
Array.prototype.push.apply(tmp, hilbert2D(vec[2], half, iterations, v0, v1, v2, v3));
|
||||
Array.prototype.push.apply(tmp, hilbert2D(vec[3], half, iterations, v2, v1, v0, v3));
|
||||
return tmp;
|
||||
}
|
||||
return vec;
|
||||
};
|
||||
const hilbert3D = (center = new Vector3(0, 0, 0), size = 10, iterations = 1, v0 = 0, v1 = 1, v2 = 2, v3 = 3, v4 = 4, v5 = 5, v6 = 6, v7 = 7) => {
|
||||
const half = size / 2;
|
||||
const vec_s = [
|
||||
new Vector3(center.x - half, center.y + half, center.z - half),
|
||||
new Vector3(center.x - half, center.y + half, center.z + half),
|
||||
new Vector3(center.x - half, center.y - half, center.z + half),
|
||||
new Vector3(center.x - half, center.y - half, center.z - half),
|
||||
new Vector3(center.x + half, center.y - half, center.z - half),
|
||||
new Vector3(center.x + half, center.y - half, center.z + half),
|
||||
new Vector3(center.x + half, center.y + half, center.z + half),
|
||||
new Vector3(center.x + half, center.y + half, center.z - half)
|
||||
];
|
||||
const vec = [vec_s[v0], vec_s[v1], vec_s[v2], vec_s[v3], vec_s[v4], vec_s[v5], vec_s[v6], vec_s[v7]];
|
||||
if (--iterations >= 0) {
|
||||
const tmp = [];
|
||||
Array.prototype.push.apply(tmp, hilbert3D(vec[0], half, iterations, v0, v3, v4, v7, v6, v5, v2, v1));
|
||||
Array.prototype.push.apply(tmp, hilbert3D(vec[1], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3));
|
||||
Array.prototype.push.apply(tmp, hilbert3D(vec[2], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3));
|
||||
Array.prototype.push.apply(tmp, hilbert3D(vec[3], half, iterations, v2, v3, v0, v1, v6, v7, v4, v5));
|
||||
Array.prototype.push.apply(tmp, hilbert3D(vec[4], half, iterations, v2, v3, v0, v1, v6, v7, v4, v5));
|
||||
Array.prototype.push.apply(tmp, hilbert3D(vec[5], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7));
|
||||
Array.prototype.push.apply(tmp, hilbert3D(vec[6], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7));
|
||||
Array.prototype.push.apply(tmp, hilbert3D(vec[7], half, iterations, v6, v5, v2, v1, v0, v3, v4, v7));
|
||||
return tmp;
|
||||
}
|
||||
return vec;
|
||||
};
|
||||
const gosper = (size = 1) => {
|
||||
function fractalize(config) {
|
||||
let output = "";
|
||||
let input = config.axiom;
|
||||
for (let i = 0, il = config.steps; 0 <= il ? i < il : i > il; 0 <= il ? i++ : i--) {
|
||||
output = "";
|
||||
for (let j = 0, jl = input.length; j < jl; j++) {
|
||||
const char = input[j];
|
||||
if (char in config.rules) {
|
||||
output += config.rules[char];
|
||||
} else {
|
||||
output += char;
|
||||
}
|
||||
}
|
||||
input = output;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
function toPoints(config) {
|
||||
let currX = 0;
|
||||
let currY = 0;
|
||||
let angle = 0;
|
||||
const path = [0, 0, 0];
|
||||
const fractal = config.fractal;
|
||||
for (let i = 0, l = fractal.length; i < l; i++) {
|
||||
const char = fractal[i];
|
||||
if (char === "+") {
|
||||
angle += config.angle;
|
||||
} else if (char === "-") {
|
||||
angle -= config.angle;
|
||||
} else if (char === "F") {
|
||||
currX += config.size * Math.cos(angle);
|
||||
currY += -config.size * Math.sin(angle);
|
||||
path.push(currX, currY, 0);
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
const gosper2 = fractalize({
|
||||
axiom: "A",
|
||||
steps: 4,
|
||||
rules: {
|
||||
A: "A+BF++BF-FA--FAFA-BF+",
|
||||
B: "-FA+BFBF++BF+FA--FA-B"
|
||||
}
|
||||
});
|
||||
const points = toPoints({
|
||||
fractal: gosper2,
|
||||
size,
|
||||
angle: Math.PI / 3
|
||||
// 60 degrees
|
||||
});
|
||||
return points;
|
||||
};
|
||||
const GeometryUtils = {
|
||||
hilbert3D,
|
||||
gosper,
|
||||
hilbert2D
|
||||
};
|
||||
export {
|
||||
GeometryUtils
|
||||
};
|
||||
//# sourceMappingURL=GeometryUtils.js.map
|
||||
1
node_modules/three-stdlib/utils/GeometryUtils.js.map
generated
vendored
Normal file
1
node_modules/three-stdlib/utils/GeometryUtils.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
5
node_modules/three-stdlib/utils/LDrawUtils.d.ts
generated
vendored
Normal file
5
node_modules/three-stdlib/utils/LDrawUtils.d.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import { Group, Object3D } from 'three'
|
||||
|
||||
export namespace LDrawUtils {
|
||||
function mergeObject(object: Object3D): Group
|
||||
}
|
||||
224
node_modules/three-stdlib/utils/RoughnessMipmapper.cjs
generated
vendored
Normal file
224
node_modules/three-stdlib/utils/RoughnessMipmapper.cjs
generated
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
||||
var __publicField = (obj, key, value) => {
|
||||
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
||||
return value;
|
||||
};
|
||||
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
||||
const THREE = require("three");
|
||||
var _mipmapMaterial = /* @__PURE__ */ _getMipmapMaterial();
|
||||
var _mesh = /* @__PURE__ */ new THREE.Mesh(/* @__PURE__ */ new THREE.PlaneGeometry(2, 2), _mipmapMaterial);
|
||||
var _flatCamera = /* @__PURE__ */ new THREE.OrthographicCamera(0, 1, 0, 1, 0, 1);
|
||||
var _tempTarget = null;
|
||||
class RoughnessMipmapper {
|
||||
constructor(renderer) {
|
||||
__publicField(this, "generateMipmaps", function(material) {
|
||||
if ("roughnessMap" in material === false)
|
||||
return;
|
||||
var { roughnessMap, normalMap } = material;
|
||||
if (roughnessMap === null || normalMap === null || !roughnessMap.generateMipmaps || material.userData.roughnessUpdated) {
|
||||
return;
|
||||
}
|
||||
material.userData.roughnessUpdated = true;
|
||||
var width = Math.max(roughnessMap.image.width, normalMap.image.width);
|
||||
var height = Math.max(roughnessMap.image.height, normalMap.image.height);
|
||||
if (!THREE.MathUtils.isPowerOfTwo(width) || !THREE.MathUtils.isPowerOfTwo(height))
|
||||
return;
|
||||
var oldTarget = this._renderer.getRenderTarget();
|
||||
var autoClear = this._renderer.autoClear;
|
||||
this._renderer.autoClear = false;
|
||||
if (_tempTarget === null || _tempTarget.width !== width || _tempTarget.height !== height) {
|
||||
if (_tempTarget !== null)
|
||||
_tempTarget.dispose();
|
||||
_tempTarget = new THREE.WebGLRenderTarget(width, height, {
|
||||
depthBuffer: false
|
||||
});
|
||||
_tempTarget.scissorTest = true;
|
||||
}
|
||||
if (width !== roughnessMap.image.width || height !== roughnessMap.image.height) {
|
||||
var params = {
|
||||
wrapS: roughnessMap.wrapS,
|
||||
wrapT: roughnessMap.wrapT,
|
||||
magFilter: roughnessMap.magFilter,
|
||||
minFilter: roughnessMap.minFilter,
|
||||
depthBuffer: false
|
||||
};
|
||||
var newRoughnessTarget = new THREE.WebGLRenderTarget(width, height, params);
|
||||
newRoughnessTarget.texture.generateMipmaps = true;
|
||||
this._renderer.setRenderTarget(newRoughnessTarget);
|
||||
material.roughnessMap = newRoughnessTarget.texture;
|
||||
if (material.metalnessMap == roughnessMap)
|
||||
material.metalnessMap = material.roughnessMap;
|
||||
if (material.aoMap == roughnessMap)
|
||||
material.aoMap = material.roughnessMap;
|
||||
}
|
||||
_mipmapMaterial.uniforms.roughnessMap.value = roughnessMap;
|
||||
_mipmapMaterial.uniforms.normalMap.value = normalMap;
|
||||
var position = new THREE.Vector2(0, 0);
|
||||
var texelSize = _mipmapMaterial.uniforms.texelSize.value;
|
||||
for (let mip = 0; width >= 1 && height >= 1; ++mip, width /= 2, height /= 2) {
|
||||
texelSize.set(1 / width, 1 / height);
|
||||
if (mip == 0)
|
||||
texelSize.set(0, 0);
|
||||
_tempTarget.viewport.set(position.x, position.y, width, height);
|
||||
_tempTarget.scissor.set(position.x, position.y, width, height);
|
||||
this._renderer.setRenderTarget(_tempTarget);
|
||||
this._renderer.render(_mesh, _flatCamera);
|
||||
this._renderer.copyFramebufferToTexture(position, material.roughnessMap, mip);
|
||||
_mipmapMaterial.uniforms.roughnessMap.value = material.roughnessMap;
|
||||
}
|
||||
if (roughnessMap !== material.roughnessMap)
|
||||
roughnessMap.dispose();
|
||||
this._renderer.setRenderTarget(oldTarget);
|
||||
this._renderer.autoClear = autoClear;
|
||||
});
|
||||
__publicField(this, "dispose", function() {
|
||||
_mipmapMaterial.dispose();
|
||||
_mesh.geometry.dispose();
|
||||
if (_tempTarget != null)
|
||||
_tempTarget.dispose();
|
||||
});
|
||||
this._renderer = renderer;
|
||||
this._renderer.compile(_mesh, _flatCamera);
|
||||
}
|
||||
}
|
||||
function _getMipmapMaterial() {
|
||||
var shaderMaterial = new THREE.RawShaderMaterial({
|
||||
uniforms: {
|
||||
roughnessMap: { value: null },
|
||||
normalMap: { value: null },
|
||||
texelSize: { value: new THREE.Vector2(1, 1) }
|
||||
},
|
||||
vertexShader: (
|
||||
/* glsl */
|
||||
`
|
||||
precision mediump float;
|
||||
precision mediump int;
|
||||
|
||||
attribute vec3 position;
|
||||
attribute vec2 uv;
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
|
||||
vUv = uv;
|
||||
|
||||
gl_Position = vec4( position, 1.0 );
|
||||
|
||||
}
|
||||
`
|
||||
),
|
||||
fragmentShader: (
|
||||
/* glsl */
|
||||
`
|
||||
precision mediump float;
|
||||
precision mediump int;
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
uniform sampler2D roughnessMap;
|
||||
uniform sampler2D normalMap;
|
||||
uniform vec2 texelSize;
|
||||
|
||||
#define ENVMAP_TYPE_CUBE_UV
|
||||
|
||||
vec4 envMapTexelToLinear( vec4 a ) { return a; }
|
||||
|
||||
#include <cube_uv_reflection_fragment>
|
||||
|
||||
float roughnessToVariance( float roughness ) {
|
||||
|
||||
float variance = 0.0;
|
||||
|
||||
if ( roughness >= r1 ) {
|
||||
|
||||
variance = ( r0 - roughness ) * ( v1 - v0 ) / ( r0 - r1 ) + v0;
|
||||
|
||||
} else if ( roughness >= r4 ) {
|
||||
|
||||
variance = ( r1 - roughness ) * ( v4 - v1 ) / ( r1 - r4 ) + v1;
|
||||
|
||||
} else if ( roughness >= r5 ) {
|
||||
|
||||
variance = ( r4 - roughness ) * ( v5 - v4 ) / ( r4 - r5 ) + v4;
|
||||
|
||||
} else {
|
||||
|
||||
float roughness2 = roughness * roughness;
|
||||
|
||||
variance = 1.79 * roughness2 * roughness2;
|
||||
|
||||
}
|
||||
|
||||
return variance;
|
||||
|
||||
}
|
||||
|
||||
float varianceToRoughness( float variance ) {
|
||||
|
||||
float roughness = 0.0;
|
||||
|
||||
if ( variance >= v1 ) {
|
||||
|
||||
roughness = ( v0 - variance ) * ( r1 - r0 ) / ( v0 - v1 ) + r0;
|
||||
|
||||
} else if ( variance >= v4 ) {
|
||||
|
||||
roughness = ( v1 - variance ) * ( r4 - r1 ) / ( v1 - v4 ) + r1;
|
||||
|
||||
} else if ( variance >= v5 ) {
|
||||
|
||||
roughness = ( v4 - variance ) * ( r5 - r4 ) / ( v4 - v5 ) + r4;
|
||||
|
||||
} else {
|
||||
|
||||
roughness = pow( 0.559 * variance, 0.25 ); // 0.559 = 1.0 / 1.79
|
||||
|
||||
}
|
||||
|
||||
return roughness;
|
||||
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
gl_FragColor = texture2D( roughnessMap, vUv, - 1.0 );
|
||||
|
||||
if ( texelSize.x == 0.0 ) return;
|
||||
|
||||
float roughness = gl_FragColor.g;
|
||||
|
||||
float variance = roughnessToVariance( roughness );
|
||||
|
||||
vec3 avgNormal;
|
||||
|
||||
for ( float x = - 1.0; x < 2.0; x += 2.0 ) {
|
||||
|
||||
for ( float y = - 1.0; y < 2.0; y += 2.0 ) {
|
||||
|
||||
vec2 uv = vUv + vec2( x, y ) * 0.25 * texelSize;
|
||||
|
||||
avgNormal += normalize( texture2D( normalMap, uv, - 1.0 ).xyz - 0.5 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
variance += 1.0 - 0.25 * length( avgNormal );
|
||||
|
||||
gl_FragColor.g = varianceToRoughness( variance );
|
||||
|
||||
}
|
||||
`
|
||||
),
|
||||
blending: THREE.NoBlending,
|
||||
depthTest: false,
|
||||
depthWrite: false
|
||||
});
|
||||
shaderMaterial.type = "RoughnessMipmapper";
|
||||
return shaderMaterial;
|
||||
}
|
||||
exports.RoughnessMipmapper = RoughnessMipmapper;
|
||||
//# sourceMappingURL=RoughnessMipmapper.cjs.map
|
||||
1
node_modules/three-stdlib/utils/RoughnessMipmapper.cjs.map
generated
vendored
Normal file
1
node_modules/three-stdlib/utils/RoughnessMipmapper.cjs.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
8
node_modules/three-stdlib/utils/RoughnessMipmapper.d.ts
generated
vendored
Normal file
8
node_modules/three-stdlib/utils/RoughnessMipmapper.d.ts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Material, WebGLRenderer } from 'three'
|
||||
|
||||
export class RoughnessMipmapper {
|
||||
constructor(renderer: WebGLRenderer)
|
||||
|
||||
generateMipmaps(material: Material): void
|
||||
dispose(): void
|
||||
}
|
||||
224
node_modules/three-stdlib/utils/RoughnessMipmapper.js
generated
vendored
Normal file
224
node_modules/three-stdlib/utils/RoughnessMipmapper.js
generated
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
var __defProp = Object.defineProperty;
|
||||
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
||||
var __publicField = (obj, key, value) => {
|
||||
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
||||
return value;
|
||||
};
|
||||
import { MathUtils, WebGLRenderTarget, Vector2, Mesh, PlaneGeometry, OrthographicCamera, RawShaderMaterial, NoBlending } from "three";
|
||||
var _mipmapMaterial = /* @__PURE__ */ _getMipmapMaterial();
|
||||
var _mesh = /* @__PURE__ */ new Mesh(/* @__PURE__ */ new PlaneGeometry(2, 2), _mipmapMaterial);
|
||||
var _flatCamera = /* @__PURE__ */ new OrthographicCamera(0, 1, 0, 1, 0, 1);
|
||||
var _tempTarget = null;
|
||||
class RoughnessMipmapper {
|
||||
constructor(renderer) {
|
||||
__publicField(this, "generateMipmaps", function(material) {
|
||||
if ("roughnessMap" in material === false)
|
||||
return;
|
||||
var { roughnessMap, normalMap } = material;
|
||||
if (roughnessMap === null || normalMap === null || !roughnessMap.generateMipmaps || material.userData.roughnessUpdated) {
|
||||
return;
|
||||
}
|
||||
material.userData.roughnessUpdated = true;
|
||||
var width = Math.max(roughnessMap.image.width, normalMap.image.width);
|
||||
var height = Math.max(roughnessMap.image.height, normalMap.image.height);
|
||||
if (!MathUtils.isPowerOfTwo(width) || !MathUtils.isPowerOfTwo(height))
|
||||
return;
|
||||
var oldTarget = this._renderer.getRenderTarget();
|
||||
var autoClear = this._renderer.autoClear;
|
||||
this._renderer.autoClear = false;
|
||||
if (_tempTarget === null || _tempTarget.width !== width || _tempTarget.height !== height) {
|
||||
if (_tempTarget !== null)
|
||||
_tempTarget.dispose();
|
||||
_tempTarget = new WebGLRenderTarget(width, height, {
|
||||
depthBuffer: false
|
||||
});
|
||||
_tempTarget.scissorTest = true;
|
||||
}
|
||||
if (width !== roughnessMap.image.width || height !== roughnessMap.image.height) {
|
||||
var params = {
|
||||
wrapS: roughnessMap.wrapS,
|
||||
wrapT: roughnessMap.wrapT,
|
||||
magFilter: roughnessMap.magFilter,
|
||||
minFilter: roughnessMap.minFilter,
|
||||
depthBuffer: false
|
||||
};
|
||||
var newRoughnessTarget = new WebGLRenderTarget(width, height, params);
|
||||
newRoughnessTarget.texture.generateMipmaps = true;
|
||||
this._renderer.setRenderTarget(newRoughnessTarget);
|
||||
material.roughnessMap = newRoughnessTarget.texture;
|
||||
if (material.metalnessMap == roughnessMap)
|
||||
material.metalnessMap = material.roughnessMap;
|
||||
if (material.aoMap == roughnessMap)
|
||||
material.aoMap = material.roughnessMap;
|
||||
}
|
||||
_mipmapMaterial.uniforms.roughnessMap.value = roughnessMap;
|
||||
_mipmapMaterial.uniforms.normalMap.value = normalMap;
|
||||
var position = new Vector2(0, 0);
|
||||
var texelSize = _mipmapMaterial.uniforms.texelSize.value;
|
||||
for (let mip = 0; width >= 1 && height >= 1; ++mip, width /= 2, height /= 2) {
|
||||
texelSize.set(1 / width, 1 / height);
|
||||
if (mip == 0)
|
||||
texelSize.set(0, 0);
|
||||
_tempTarget.viewport.set(position.x, position.y, width, height);
|
||||
_tempTarget.scissor.set(position.x, position.y, width, height);
|
||||
this._renderer.setRenderTarget(_tempTarget);
|
||||
this._renderer.render(_mesh, _flatCamera);
|
||||
this._renderer.copyFramebufferToTexture(position, material.roughnessMap, mip);
|
||||
_mipmapMaterial.uniforms.roughnessMap.value = material.roughnessMap;
|
||||
}
|
||||
if (roughnessMap !== material.roughnessMap)
|
||||
roughnessMap.dispose();
|
||||
this._renderer.setRenderTarget(oldTarget);
|
||||
this._renderer.autoClear = autoClear;
|
||||
});
|
||||
__publicField(this, "dispose", function() {
|
||||
_mipmapMaterial.dispose();
|
||||
_mesh.geometry.dispose();
|
||||
if (_tempTarget != null)
|
||||
_tempTarget.dispose();
|
||||
});
|
||||
this._renderer = renderer;
|
||||
this._renderer.compile(_mesh, _flatCamera);
|
||||
}
|
||||
}
|
||||
function _getMipmapMaterial() {
|
||||
var shaderMaterial = new RawShaderMaterial({
|
||||
uniforms: {
|
||||
roughnessMap: { value: null },
|
||||
normalMap: { value: null },
|
||||
texelSize: { value: new Vector2(1, 1) }
|
||||
},
|
||||
vertexShader: (
|
||||
/* glsl */
|
||||
`
|
||||
precision mediump float;
|
||||
precision mediump int;
|
||||
|
||||
attribute vec3 position;
|
||||
attribute vec2 uv;
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
|
||||
vUv = uv;
|
||||
|
||||
gl_Position = vec4( position, 1.0 );
|
||||
|
||||
}
|
||||
`
|
||||
),
|
||||
fragmentShader: (
|
||||
/* glsl */
|
||||
`
|
||||
precision mediump float;
|
||||
precision mediump int;
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
uniform sampler2D roughnessMap;
|
||||
uniform sampler2D normalMap;
|
||||
uniform vec2 texelSize;
|
||||
|
||||
#define ENVMAP_TYPE_CUBE_UV
|
||||
|
||||
vec4 envMapTexelToLinear( vec4 a ) { return a; }
|
||||
|
||||
#include <cube_uv_reflection_fragment>
|
||||
|
||||
float roughnessToVariance( float roughness ) {
|
||||
|
||||
float variance = 0.0;
|
||||
|
||||
if ( roughness >= r1 ) {
|
||||
|
||||
variance = ( r0 - roughness ) * ( v1 - v0 ) / ( r0 - r1 ) + v0;
|
||||
|
||||
} else if ( roughness >= r4 ) {
|
||||
|
||||
variance = ( r1 - roughness ) * ( v4 - v1 ) / ( r1 - r4 ) + v1;
|
||||
|
||||
} else if ( roughness >= r5 ) {
|
||||
|
||||
variance = ( r4 - roughness ) * ( v5 - v4 ) / ( r4 - r5 ) + v4;
|
||||
|
||||
} else {
|
||||
|
||||
float roughness2 = roughness * roughness;
|
||||
|
||||
variance = 1.79 * roughness2 * roughness2;
|
||||
|
||||
}
|
||||
|
||||
return variance;
|
||||
|
||||
}
|
||||
|
||||
float varianceToRoughness( float variance ) {
|
||||
|
||||
float roughness = 0.0;
|
||||
|
||||
if ( variance >= v1 ) {
|
||||
|
||||
roughness = ( v0 - variance ) * ( r1 - r0 ) / ( v0 - v1 ) + r0;
|
||||
|
||||
} else if ( variance >= v4 ) {
|
||||
|
||||
roughness = ( v1 - variance ) * ( r4 - r1 ) / ( v1 - v4 ) + r1;
|
||||
|
||||
} else if ( variance >= v5 ) {
|
||||
|
||||
roughness = ( v4 - variance ) * ( r5 - r4 ) / ( v4 - v5 ) + r4;
|
||||
|
||||
} else {
|
||||
|
||||
roughness = pow( 0.559 * variance, 0.25 ); // 0.559 = 1.0 / 1.79
|
||||
|
||||
}
|
||||
|
||||
return roughness;
|
||||
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
gl_FragColor = texture2D( roughnessMap, vUv, - 1.0 );
|
||||
|
||||
if ( texelSize.x == 0.0 ) return;
|
||||
|
||||
float roughness = gl_FragColor.g;
|
||||
|
||||
float variance = roughnessToVariance( roughness );
|
||||
|
||||
vec3 avgNormal;
|
||||
|
||||
for ( float x = - 1.0; x < 2.0; x += 2.0 ) {
|
||||
|
||||
for ( float y = - 1.0; y < 2.0; y += 2.0 ) {
|
||||
|
||||
vec2 uv = vUv + vec2( x, y ) * 0.25 * texelSize;
|
||||
|
||||
avgNormal += normalize( texture2D( normalMap, uv, - 1.0 ).xyz - 0.5 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
variance += 1.0 - 0.25 * length( avgNormal );
|
||||
|
||||
gl_FragColor.g = varianceToRoughness( variance );
|
||||
|
||||
}
|
||||
`
|
||||
),
|
||||
blending: NoBlending,
|
||||
depthTest: false,
|
||||
depthWrite: false
|
||||
});
|
||||
shaderMaterial.type = "RoughnessMipmapper";
|
||||
return shaderMaterial;
|
||||
}
|
||||
export {
|
||||
RoughnessMipmapper
|
||||
};
|
||||
//# sourceMappingURL=RoughnessMipmapper.js.map
|
||||
1
node_modules/three-stdlib/utils/RoughnessMipmapper.js.map
generated
vendored
Normal file
1
node_modules/three-stdlib/utils/RoughnessMipmapper.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
37
node_modules/three-stdlib/utils/SceneUtils.cjs
generated
vendored
Normal file
37
node_modules/three-stdlib/utils/SceneUtils.cjs
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
||||
const THREE = require("three");
|
||||
const SceneUtils = {
|
||||
createMeshesFromInstancedMesh: function(instancedMesh) {
|
||||
const group = new THREE.Group();
|
||||
const count = instancedMesh.count;
|
||||
const geometry = instancedMesh.geometry;
|
||||
const material = instancedMesh.material;
|
||||
for (let i = 0; i < count; i++) {
|
||||
const mesh = new THREE.Mesh(geometry, material);
|
||||
instancedMesh.getMatrixAt(i, mesh.matrix);
|
||||
mesh.matrix.decompose(mesh.position, mesh.quaternion, mesh.scale);
|
||||
group.add(mesh);
|
||||
}
|
||||
group.copy(instancedMesh);
|
||||
group.updateMatrixWorld();
|
||||
return group;
|
||||
},
|
||||
createMultiMaterialObject: function(geometry, materials) {
|
||||
const group = new THREE.Group();
|
||||
for (let i = 0, l = materials.length; i < l; i++) {
|
||||
group.add(new THREE.Mesh(geometry, materials[i]));
|
||||
}
|
||||
return group;
|
||||
},
|
||||
detach: function(child, parent, scene) {
|
||||
console.warn("THREE.SceneUtils: detach() has been deprecated. Use scene.attach( child ) instead.");
|
||||
scene.attach(child);
|
||||
},
|
||||
attach: function(child, scene, parent) {
|
||||
console.warn("THREE.SceneUtils: attach() has been deprecated. Use parent.attach( child ) instead.");
|
||||
parent.attach(child);
|
||||
}
|
||||
};
|
||||
exports.SceneUtils = SceneUtils;
|
||||
//# sourceMappingURL=SceneUtils.cjs.map
|
||||
1
node_modules/three-stdlib/utils/SceneUtils.cjs.map
generated
vendored
Normal file
1
node_modules/three-stdlib/utils/SceneUtils.cjs.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"SceneUtils.cjs","sources":["../../src/utils/SceneUtils.ts"],"sourcesContent":["import { Group, Mesh } from 'three'\nimport type { BufferGeometry, InstancedMesh, Material, Object3D, Scene } from 'three'\n\nconst SceneUtils = {\n createMeshesFromInstancedMesh: function (instancedMesh: InstancedMesh): Group {\n const group = new Group()\n\n const count = instancedMesh.count\n const geometry = instancedMesh.geometry\n const material = instancedMesh.material\n\n for (let i = 0; i < count; i++) {\n const mesh = new Mesh(geometry, material)\n\n instancedMesh.getMatrixAt(i, mesh.matrix)\n mesh.matrix.decompose(mesh.position, mesh.quaternion, mesh.scale)\n\n group.add(mesh)\n }\n\n group.copy((instancedMesh as unknown) as Group)\n group.updateMatrixWorld() // ensure correct world matrices of meshes\n\n return group\n },\n\n createMultiMaterialObject: function (geometry: BufferGeometry, materials: Material[]): Group {\n const group = new Group()\n\n for (let i = 0, l = materials.length; i < l; i++) {\n group.add(new Mesh(geometry, materials[i]))\n }\n\n return group\n },\n\n detach: function (child: Object3D, parent: Object3D, scene: Scene): void {\n console.warn('THREE.SceneUtils: detach() has been deprecated. Use scene.attach( child ) instead.')\n\n scene.attach(child)\n },\n\n attach: function (child: Object3D, scene: Scene, parent: Object3D): void {\n console.warn('THREE.SceneUtils: attach() has been deprecated. Use parent.attach( child ) instead.')\n\n parent.attach(child)\n },\n}\n\nexport { SceneUtils }\n"],"names":["Group","Mesh"],"mappings":";;;AAGA,MAAM,aAAa;AAAA,EACjB,+BAA+B,SAAU,eAAqC;AACtE,UAAA,QAAQ,IAAIA,MAAAA;AAElB,UAAM,QAAQ,cAAc;AAC5B,UAAM,WAAW,cAAc;AAC/B,UAAM,WAAW,cAAc;AAE/B,aAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,YAAM,OAAO,IAAIC,MAAAA,KAAK,UAAU,QAAQ;AAE1B,oBAAA,YAAY,GAAG,KAAK,MAAM;AACxC,WAAK,OAAO,UAAU,KAAK,UAAU,KAAK,YAAY,KAAK,KAAK;AAEhE,YAAM,IAAI,IAAI;AAAA,IAChB;AAEA,UAAM,KAAM,aAAkC;AAC9C,UAAM,kBAAkB;AAEjB,WAAA;AAAA,EACT;AAAA,EAEA,2BAA2B,SAAU,UAA0B,WAA8B;AACrF,UAAA,QAAQ,IAAID,MAAAA;AAElB,aAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,IAAI,GAAG,KAAK;AAChD,YAAM,IAAI,IAAIC,MAAA,KAAK,UAAU,UAAU,CAAC,CAAC,CAAC;AAAA,IAC5C;AAEO,WAAA;AAAA,EACT;AAAA,EAEA,QAAQ,SAAU,OAAiB,QAAkB,OAAoB;AACvE,YAAQ,KAAK,oFAAoF;AAEjG,UAAM,OAAO,KAAK;AAAA,EACpB;AAAA,EAEA,QAAQ,SAAU,OAAiB,OAAc,QAAwB;AACvE,YAAQ,KAAK,qFAAqF;AAElG,WAAO,OAAO,KAAK;AAAA,EACrB;AACF;;"}
|
||||
9
node_modules/three-stdlib/utils/SceneUtils.d.ts
generated
vendored
Normal file
9
node_modules/three-stdlib/utils/SceneUtils.d.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Group } from 'three';
|
||||
import type { BufferGeometry, InstancedMesh, Material, Object3D, Scene } from 'three';
|
||||
declare const SceneUtils: {
|
||||
createMeshesFromInstancedMesh: (instancedMesh: InstancedMesh) => Group;
|
||||
createMultiMaterialObject: (geometry: BufferGeometry, materials: Material[]) => Group;
|
||||
detach: (child: Object3D, parent: Object3D, scene: Scene) => void;
|
||||
attach: (child: Object3D, scene: Scene, parent: Object3D) => void;
|
||||
};
|
||||
export { SceneUtils };
|
||||
37
node_modules/three-stdlib/utils/SceneUtils.js
generated
vendored
Normal file
37
node_modules/three-stdlib/utils/SceneUtils.js
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
import { Group, Mesh } from "three";
|
||||
const SceneUtils = {
|
||||
createMeshesFromInstancedMesh: function(instancedMesh) {
|
||||
const group = new Group();
|
||||
const count = instancedMesh.count;
|
||||
const geometry = instancedMesh.geometry;
|
||||
const material = instancedMesh.material;
|
||||
for (let i = 0; i < count; i++) {
|
||||
const mesh = new Mesh(geometry, material);
|
||||
instancedMesh.getMatrixAt(i, mesh.matrix);
|
||||
mesh.matrix.decompose(mesh.position, mesh.quaternion, mesh.scale);
|
||||
group.add(mesh);
|
||||
}
|
||||
group.copy(instancedMesh);
|
||||
group.updateMatrixWorld();
|
||||
return group;
|
||||
},
|
||||
createMultiMaterialObject: function(geometry, materials) {
|
||||
const group = new Group();
|
||||
for (let i = 0, l = materials.length; i < l; i++) {
|
||||
group.add(new Mesh(geometry, materials[i]));
|
||||
}
|
||||
return group;
|
||||
},
|
||||
detach: function(child, parent, scene) {
|
||||
console.warn("THREE.SceneUtils: detach() has been deprecated. Use scene.attach( child ) instead.");
|
||||
scene.attach(child);
|
||||
},
|
||||
attach: function(child, scene, parent) {
|
||||
console.warn("THREE.SceneUtils: attach() has been deprecated. Use parent.attach( child ) instead.");
|
||||
parent.attach(child);
|
||||
}
|
||||
};
|
||||
export {
|
||||
SceneUtils
|
||||
};
|
||||
//# sourceMappingURL=SceneUtils.js.map
|
||||
1
node_modules/three-stdlib/utils/SceneUtils.js.map
generated
vendored
Normal file
1
node_modules/three-stdlib/utils/SceneUtils.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"SceneUtils.js","sources":["../../src/utils/SceneUtils.ts"],"sourcesContent":["import { Group, Mesh } from 'three'\nimport type { BufferGeometry, InstancedMesh, Material, Object3D, Scene } from 'three'\n\nconst SceneUtils = {\n createMeshesFromInstancedMesh: function (instancedMesh: InstancedMesh): Group {\n const group = new Group()\n\n const count = instancedMesh.count\n const geometry = instancedMesh.geometry\n const material = instancedMesh.material\n\n for (let i = 0; i < count; i++) {\n const mesh = new Mesh(geometry, material)\n\n instancedMesh.getMatrixAt(i, mesh.matrix)\n mesh.matrix.decompose(mesh.position, mesh.quaternion, mesh.scale)\n\n group.add(mesh)\n }\n\n group.copy((instancedMesh as unknown) as Group)\n group.updateMatrixWorld() // ensure correct world matrices of meshes\n\n return group\n },\n\n createMultiMaterialObject: function (geometry: BufferGeometry, materials: Material[]): Group {\n const group = new Group()\n\n for (let i = 0, l = materials.length; i < l; i++) {\n group.add(new Mesh(geometry, materials[i]))\n }\n\n return group\n },\n\n detach: function (child: Object3D, parent: Object3D, scene: Scene): void {\n console.warn('THREE.SceneUtils: detach() has been deprecated. Use scene.attach( child ) instead.')\n\n scene.attach(child)\n },\n\n attach: function (child: Object3D, scene: Scene, parent: Object3D): void {\n console.warn('THREE.SceneUtils: attach() has been deprecated. Use parent.attach( child ) instead.')\n\n parent.attach(child)\n },\n}\n\nexport { SceneUtils }\n"],"names":[],"mappings":";AAGA,MAAM,aAAa;AAAA,EACjB,+BAA+B,SAAU,eAAqC;AACtE,UAAA,QAAQ,IAAI;AAElB,UAAM,QAAQ,cAAc;AAC5B,UAAM,WAAW,cAAc;AAC/B,UAAM,WAAW,cAAc;AAE/B,aAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,YAAM,OAAO,IAAI,KAAK,UAAU,QAAQ;AAE1B,oBAAA,YAAY,GAAG,KAAK,MAAM;AACxC,WAAK,OAAO,UAAU,KAAK,UAAU,KAAK,YAAY,KAAK,KAAK;AAEhE,YAAM,IAAI,IAAI;AAAA,IAChB;AAEA,UAAM,KAAM,aAAkC;AAC9C,UAAM,kBAAkB;AAEjB,WAAA;AAAA,EACT;AAAA,EAEA,2BAA2B,SAAU,UAA0B,WAA8B;AACrF,UAAA,QAAQ,IAAI;AAElB,aAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,IAAI,GAAG,KAAK;AAChD,YAAM,IAAI,IAAI,KAAK,UAAU,UAAU,CAAC,CAAC,CAAC;AAAA,IAC5C;AAEO,WAAA;AAAA,EACT;AAAA,EAEA,QAAQ,SAAU,OAAiB,QAAkB,OAAoB;AACvE,YAAQ,KAAK,oFAAoF;AAEjG,UAAM,OAAO,KAAK;AAAA,EACpB;AAAA,EAEA,QAAQ,SAAU,OAAiB,OAAc,QAAwB;AACvE,YAAQ,KAAK,qFAAqF;AAElG,WAAO,OAAO,KAAK;AAAA,EACrB;AACF;"}
|
||||
112
node_modules/three-stdlib/utils/ShadowMapViewer.cjs
generated
vendored
Normal file
112
node_modules/three-stdlib/utils/ShadowMapViewer.cjs
generated
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
||||
const THREE = require("three");
|
||||
const UnpackDepthRGBAShader = require("../shaders/UnpackDepthRGBAShader.cjs");
|
||||
class ShadowMapViewer {
|
||||
constructor(light) {
|
||||
const scope = this;
|
||||
const doRenderLabel = light.name !== void 0 && light.name !== "";
|
||||
let userAutoClearSetting;
|
||||
const frame = {
|
||||
x: 10,
|
||||
y: 10,
|
||||
width: 256,
|
||||
height: 256
|
||||
};
|
||||
const camera = new THREE.OrthographicCamera(
|
||||
window.innerWidth / -2,
|
||||
window.innerWidth / 2,
|
||||
window.innerHeight / 2,
|
||||
window.innerHeight / -2,
|
||||
1,
|
||||
10
|
||||
);
|
||||
camera.position.set(0, 0, 2);
|
||||
const scene = new THREE.Scene();
|
||||
const shader = UnpackDepthRGBAShader.UnpackDepthRGBAShader;
|
||||
const uniforms = THREE.UniformsUtils.clone(shader.uniforms);
|
||||
const material = new THREE.ShaderMaterial({
|
||||
uniforms,
|
||||
vertexShader: shader.vertexShader,
|
||||
fragmentShader: shader.fragmentShader
|
||||
});
|
||||
const plane = new THREE.PlaneGeometry(frame.width, frame.height);
|
||||
const mesh = new THREE.Mesh(plane, material);
|
||||
scene.add(mesh);
|
||||
let labelCanvas, labelMesh;
|
||||
if (doRenderLabel) {
|
||||
labelCanvas = document.createElement("canvas");
|
||||
const context = labelCanvas.getContext("2d");
|
||||
context.font = "Bold 20px Arial";
|
||||
const labelWidth = context.measureText(light.name).width;
|
||||
labelCanvas.width = labelWidth;
|
||||
labelCanvas.height = 25;
|
||||
context.font = "Bold 20px Arial";
|
||||
context.fillStyle = "rgba( 255, 0, 0, 1 )";
|
||||
context.fillText(light.name, 0, 20);
|
||||
const labelTexture = new THREE.Texture(labelCanvas);
|
||||
labelTexture.magFilter = THREE.LinearFilter;
|
||||
labelTexture.minFilter = THREE.LinearFilter;
|
||||
labelTexture.needsUpdate = true;
|
||||
const labelMaterial = new THREE.MeshBasicMaterial({ map: labelTexture, side: THREE.DoubleSide });
|
||||
labelMaterial.transparent = true;
|
||||
const labelPlane = new THREE.PlaneGeometry(labelCanvas.width, labelCanvas.height);
|
||||
labelMesh = new THREE.Mesh(labelPlane, labelMaterial);
|
||||
scene.add(labelMesh);
|
||||
}
|
||||
function resetPosition() {
|
||||
scope.position.set(scope.position.x, scope.position.y);
|
||||
}
|
||||
this.enabled = true;
|
||||
this.size = {
|
||||
width: frame.width,
|
||||
height: frame.height,
|
||||
set: function(width, height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
mesh.scale.set(this.width / frame.width, this.height / frame.height, 1);
|
||||
resetPosition();
|
||||
}
|
||||
};
|
||||
this.position = {
|
||||
x: frame.x,
|
||||
y: frame.y,
|
||||
set: function(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
const width = scope.size.width;
|
||||
const height = scope.size.height;
|
||||
mesh.position.set(-window.innerWidth / 2 + width / 2 + this.x, window.innerHeight / 2 - height / 2 - this.y, 0);
|
||||
if (doRenderLabel)
|
||||
labelMesh.position.set(mesh.position.x, mesh.position.y - scope.size.height / 2 + labelCanvas.height / 2, 0);
|
||||
}
|
||||
};
|
||||
this.render = function(renderer) {
|
||||
if (this.enabled) {
|
||||
uniforms.tDiffuse.value = light.shadow.map.texture;
|
||||
userAutoClearSetting = renderer.autoClear;
|
||||
renderer.autoClear = false;
|
||||
renderer.clearDepth();
|
||||
renderer.render(scene, camera);
|
||||
renderer.autoClear = userAutoClearSetting;
|
||||
}
|
||||
};
|
||||
this.updateForWindowResize = function() {
|
||||
if (this.enabled) {
|
||||
camera.left = window.innerWidth / -2;
|
||||
camera.right = window.innerWidth / 2;
|
||||
camera.top = window.innerHeight / 2;
|
||||
camera.bottom = window.innerHeight / -2;
|
||||
camera.updateProjectionMatrix();
|
||||
this.update();
|
||||
}
|
||||
};
|
||||
this.update = function() {
|
||||
this.position.set(this.position.x, this.position.y);
|
||||
this.size.set(this.size.width, this.size.height);
|
||||
};
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
exports.ShadowMapViewer = ShadowMapViewer;
|
||||
//# sourceMappingURL=ShadowMapViewer.cjs.map
|
||||
1
node_modules/three-stdlib/utils/ShadowMapViewer.cjs.map
generated
vendored
Normal file
1
node_modules/three-stdlib/utils/ShadowMapViewer.cjs.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
24
node_modules/three-stdlib/utils/ShadowMapViewer.d.ts
generated
vendored
Normal file
24
node_modules/three-stdlib/utils/ShadowMapViewer.d.ts
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Light, WebGLRenderer } from 'three'
|
||||
|
||||
export interface Size {
|
||||
width: number
|
||||
height: number
|
||||
set: (width: number, height: number) => void
|
||||
}
|
||||
|
||||
export interface Position {
|
||||
x: number
|
||||
y: number
|
||||
set: (x: number, y: number) => void
|
||||
}
|
||||
|
||||
export class ShadowMapViewer {
|
||||
constructor(light: Light)
|
||||
|
||||
enabled: boolean
|
||||
size: Size
|
||||
position: Position
|
||||
render(renderer: WebGLRenderer): void
|
||||
updateForWindowResize(): void
|
||||
update(): void
|
||||
}
|
||||
112
node_modules/three-stdlib/utils/ShadowMapViewer.js
generated
vendored
Normal file
112
node_modules/three-stdlib/utils/ShadowMapViewer.js
generated
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
import { OrthographicCamera, Scene, UniformsUtils, ShaderMaterial, PlaneGeometry, Mesh, Texture, LinearFilter, MeshBasicMaterial, DoubleSide } from "three";
|
||||
import { UnpackDepthRGBAShader } from "../shaders/UnpackDepthRGBAShader.js";
|
||||
class ShadowMapViewer {
|
||||
constructor(light) {
|
||||
const scope = this;
|
||||
const doRenderLabel = light.name !== void 0 && light.name !== "";
|
||||
let userAutoClearSetting;
|
||||
const frame = {
|
||||
x: 10,
|
||||
y: 10,
|
||||
width: 256,
|
||||
height: 256
|
||||
};
|
||||
const camera = new OrthographicCamera(
|
||||
window.innerWidth / -2,
|
||||
window.innerWidth / 2,
|
||||
window.innerHeight / 2,
|
||||
window.innerHeight / -2,
|
||||
1,
|
||||
10
|
||||
);
|
||||
camera.position.set(0, 0, 2);
|
||||
const scene = new Scene();
|
||||
const shader = UnpackDepthRGBAShader;
|
||||
const uniforms = UniformsUtils.clone(shader.uniforms);
|
||||
const material = new ShaderMaterial({
|
||||
uniforms,
|
||||
vertexShader: shader.vertexShader,
|
||||
fragmentShader: shader.fragmentShader
|
||||
});
|
||||
const plane = new PlaneGeometry(frame.width, frame.height);
|
||||
const mesh = new Mesh(plane, material);
|
||||
scene.add(mesh);
|
||||
let labelCanvas, labelMesh;
|
||||
if (doRenderLabel) {
|
||||
labelCanvas = document.createElement("canvas");
|
||||
const context = labelCanvas.getContext("2d");
|
||||
context.font = "Bold 20px Arial";
|
||||
const labelWidth = context.measureText(light.name).width;
|
||||
labelCanvas.width = labelWidth;
|
||||
labelCanvas.height = 25;
|
||||
context.font = "Bold 20px Arial";
|
||||
context.fillStyle = "rgba( 255, 0, 0, 1 )";
|
||||
context.fillText(light.name, 0, 20);
|
||||
const labelTexture = new Texture(labelCanvas);
|
||||
labelTexture.magFilter = LinearFilter;
|
||||
labelTexture.minFilter = LinearFilter;
|
||||
labelTexture.needsUpdate = true;
|
||||
const labelMaterial = new MeshBasicMaterial({ map: labelTexture, side: DoubleSide });
|
||||
labelMaterial.transparent = true;
|
||||
const labelPlane = new PlaneGeometry(labelCanvas.width, labelCanvas.height);
|
||||
labelMesh = new Mesh(labelPlane, labelMaterial);
|
||||
scene.add(labelMesh);
|
||||
}
|
||||
function resetPosition() {
|
||||
scope.position.set(scope.position.x, scope.position.y);
|
||||
}
|
||||
this.enabled = true;
|
||||
this.size = {
|
||||
width: frame.width,
|
||||
height: frame.height,
|
||||
set: function(width, height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
mesh.scale.set(this.width / frame.width, this.height / frame.height, 1);
|
||||
resetPosition();
|
||||
}
|
||||
};
|
||||
this.position = {
|
||||
x: frame.x,
|
||||
y: frame.y,
|
||||
set: function(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
const width = scope.size.width;
|
||||
const height = scope.size.height;
|
||||
mesh.position.set(-window.innerWidth / 2 + width / 2 + this.x, window.innerHeight / 2 - height / 2 - this.y, 0);
|
||||
if (doRenderLabel)
|
||||
labelMesh.position.set(mesh.position.x, mesh.position.y - scope.size.height / 2 + labelCanvas.height / 2, 0);
|
||||
}
|
||||
};
|
||||
this.render = function(renderer) {
|
||||
if (this.enabled) {
|
||||
uniforms.tDiffuse.value = light.shadow.map.texture;
|
||||
userAutoClearSetting = renderer.autoClear;
|
||||
renderer.autoClear = false;
|
||||
renderer.clearDepth();
|
||||
renderer.render(scene, camera);
|
||||
renderer.autoClear = userAutoClearSetting;
|
||||
}
|
||||
};
|
||||
this.updateForWindowResize = function() {
|
||||
if (this.enabled) {
|
||||
camera.left = window.innerWidth / -2;
|
||||
camera.right = window.innerWidth / 2;
|
||||
camera.top = window.innerHeight / 2;
|
||||
camera.bottom = window.innerHeight / -2;
|
||||
camera.updateProjectionMatrix();
|
||||
this.update();
|
||||
}
|
||||
};
|
||||
this.update = function() {
|
||||
this.position.set(this.position.x, this.position.y);
|
||||
this.size.set(this.size.width, this.size.height);
|
||||
};
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
export {
|
||||
ShadowMapViewer
|
||||
};
|
||||
//# sourceMappingURL=ShadowMapViewer.js.map
|
||||
1
node_modules/three-stdlib/utils/ShadowMapViewer.js.map
generated
vendored
Normal file
1
node_modules/three-stdlib/utils/ShadowMapViewer.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
212
node_modules/three-stdlib/utils/SkeletonUtils.cjs
generated
vendored
Normal file
212
node_modules/three-stdlib/utils/SkeletonUtils.cjs
generated
vendored
Normal file
@@ -0,0 +1,212 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
||||
const THREE = require("three");
|
||||
function retarget(target, source, options = {}) {
|
||||
const pos = new THREE.Vector3(), quat = new THREE.Quaternion(), scale = new THREE.Vector3(), bindBoneMatrix = new THREE.Matrix4(), relativeMatrix = new THREE.Matrix4(), globalMatrix = new THREE.Matrix4();
|
||||
options.preserveMatrix = options.preserveMatrix !== void 0 ? options.preserveMatrix : true;
|
||||
options.preservePosition = options.preservePosition !== void 0 ? options.preservePosition : true;
|
||||
options.preserveHipPosition = options.preserveHipPosition !== void 0 ? options.preserveHipPosition : false;
|
||||
options.useTargetMatrix = options.useTargetMatrix !== void 0 ? options.useTargetMatrix : false;
|
||||
options.hip = options.hip !== void 0 ? options.hip : "hip";
|
||||
options.names = options.names || {};
|
||||
const sourceBones = source.isObject3D ? source.skeleton.bones : getBones(source), bones = target.isObject3D ? target.skeleton.bones : getBones(target);
|
||||
let bindBones, bone, name, boneTo, bonesPosition;
|
||||
if (target.isObject3D) {
|
||||
target.skeleton.pose();
|
||||
} else {
|
||||
options.useTargetMatrix = true;
|
||||
options.preserveMatrix = false;
|
||||
}
|
||||
if (options.preservePosition) {
|
||||
bonesPosition = [];
|
||||
for (let i = 0; i < bones.length; i++) {
|
||||
bonesPosition.push(bones[i].position.clone());
|
||||
}
|
||||
}
|
||||
if (options.preserveMatrix) {
|
||||
target.updateMatrixWorld();
|
||||
target.matrixWorld.identity();
|
||||
for (let i = 0; i < target.children.length; ++i) {
|
||||
target.children[i].updateMatrixWorld(true);
|
||||
}
|
||||
}
|
||||
if (options.offsets) {
|
||||
bindBones = [];
|
||||
for (let i = 0; i < bones.length; ++i) {
|
||||
bone = bones[i];
|
||||
name = options.names[bone.name] || bone.name;
|
||||
if (options.offsets[name]) {
|
||||
bone.matrix.multiply(options.offsets[name]);
|
||||
bone.matrix.decompose(bone.position, bone.quaternion, bone.scale);
|
||||
bone.updateMatrixWorld();
|
||||
}
|
||||
bindBones.push(bone.matrixWorld.clone());
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < bones.length; ++i) {
|
||||
bone = bones[i];
|
||||
name = options.names[bone.name] || bone.name;
|
||||
boneTo = getBoneByName(name, sourceBones);
|
||||
globalMatrix.copy(bone.matrixWorld);
|
||||
if (boneTo) {
|
||||
boneTo.updateMatrixWorld();
|
||||
if (options.useTargetMatrix) {
|
||||
relativeMatrix.copy(boneTo.matrixWorld);
|
||||
} else {
|
||||
relativeMatrix.copy(target.matrixWorld).invert();
|
||||
relativeMatrix.multiply(boneTo.matrixWorld);
|
||||
}
|
||||
scale.setFromMatrixScale(relativeMatrix);
|
||||
relativeMatrix.scale(scale.set(1 / scale.x, 1 / scale.y, 1 / scale.z));
|
||||
globalMatrix.makeRotationFromQuaternion(quat.setFromRotationMatrix(relativeMatrix));
|
||||
if (target.isObject3D) {
|
||||
const boneIndex = bones.indexOf(bone), wBindMatrix = bindBones ? bindBones[boneIndex] : bindBoneMatrix.copy(target.skeleton.boneInverses[boneIndex]).invert();
|
||||
globalMatrix.multiply(wBindMatrix);
|
||||
}
|
||||
globalMatrix.copyPosition(relativeMatrix);
|
||||
}
|
||||
if (bone.parent && bone.parent.isBone) {
|
||||
bone.matrix.copy(bone.parent.matrixWorld).invert();
|
||||
bone.matrix.multiply(globalMatrix);
|
||||
} else {
|
||||
bone.matrix.copy(globalMatrix);
|
||||
}
|
||||
if (options.preserveHipPosition && name === options.hip) {
|
||||
bone.matrix.setPosition(pos.set(0, bone.position.y, 0));
|
||||
}
|
||||
bone.matrix.decompose(bone.position, bone.quaternion, bone.scale);
|
||||
bone.updateMatrixWorld();
|
||||
}
|
||||
if (options.preservePosition) {
|
||||
for (let i = 0; i < bones.length; ++i) {
|
||||
bone = bones[i];
|
||||
name = options.names[bone.name] || bone.name;
|
||||
if (name !== options.hip) {
|
||||
bone.position.copy(bonesPosition[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (options.preserveMatrix) {
|
||||
target.updateMatrixWorld(true);
|
||||
}
|
||||
}
|
||||
function retargetClip(target, source, clip, options = {}) {
|
||||
options.useFirstFramePosition = options.useFirstFramePosition !== void 0 ? options.useFirstFramePosition : false;
|
||||
options.fps = options.fps !== void 0 ? options.fps : 30;
|
||||
options.names = options.names || [];
|
||||
if (!source.isObject3D) {
|
||||
source = getHelperFromSkeleton(source);
|
||||
}
|
||||
const numFrames = Math.round(clip.duration * (options.fps / 1e3) * 1e3), delta = 1 / options.fps, convertedTracks = [], mixer = new THREE.AnimationMixer(source), bones = getBones(target.skeleton), boneDatas = [];
|
||||
let positionOffset, bone, boneTo, boneData, name;
|
||||
mixer.clipAction(clip).play();
|
||||
mixer.update(0);
|
||||
source.updateMatrixWorld();
|
||||
for (let i = 0; i < numFrames; ++i) {
|
||||
const time = i * delta;
|
||||
retarget(target, source, options);
|
||||
for (let j = 0; j < bones.length; ++j) {
|
||||
name = options.names[bones[j].name] || bones[j].name;
|
||||
boneTo = getBoneByName(name, source.skeleton);
|
||||
if (boneTo) {
|
||||
bone = bones[j];
|
||||
boneData = boneDatas[j] = boneDatas[j] || { bone };
|
||||
if (options.hip === name) {
|
||||
if (!boneData.pos) {
|
||||
boneData.pos = {
|
||||
times: new Float32Array(numFrames),
|
||||
values: new Float32Array(numFrames * 3)
|
||||
};
|
||||
}
|
||||
if (options.useFirstFramePosition) {
|
||||
if (i === 0) {
|
||||
positionOffset = bone.position.clone();
|
||||
}
|
||||
bone.position.sub(positionOffset);
|
||||
}
|
||||
boneData.pos.times[i] = time;
|
||||
bone.position.toArray(boneData.pos.values, i * 3);
|
||||
}
|
||||
if (!boneData.quat) {
|
||||
boneData.quat = {
|
||||
times: new Float32Array(numFrames),
|
||||
values: new Float32Array(numFrames * 4)
|
||||
};
|
||||
}
|
||||
boneData.quat.times[i] = time;
|
||||
bone.quaternion.toArray(boneData.quat.values, i * 4);
|
||||
}
|
||||
}
|
||||
mixer.update(delta);
|
||||
source.updateMatrixWorld();
|
||||
}
|
||||
for (let i = 0; i < boneDatas.length; ++i) {
|
||||
boneData = boneDatas[i];
|
||||
if (boneData) {
|
||||
if (boneData.pos) {
|
||||
convertedTracks.push(
|
||||
new THREE.VectorKeyframeTrack(
|
||||
".bones[" + boneData.bone.name + "].position",
|
||||
boneData.pos.times,
|
||||
boneData.pos.values
|
||||
)
|
||||
);
|
||||
}
|
||||
convertedTracks.push(
|
||||
new THREE.QuaternionKeyframeTrack(
|
||||
".bones[" + boneData.bone.name + "].quaternion",
|
||||
boneData.quat.times,
|
||||
boneData.quat.values
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
mixer.uncacheAction(clip);
|
||||
return new THREE.AnimationClip(clip.name, -1, convertedTracks);
|
||||
}
|
||||
function clone(source) {
|
||||
const sourceLookup = /* @__PURE__ */ new Map();
|
||||
const cloneLookup = /* @__PURE__ */ new Map();
|
||||
const clone2 = source.clone();
|
||||
parallelTraverse(source, clone2, function(sourceNode, clonedNode) {
|
||||
sourceLookup.set(clonedNode, sourceNode);
|
||||
cloneLookup.set(sourceNode, clonedNode);
|
||||
});
|
||||
clone2.traverse(function(node) {
|
||||
if (!node.isSkinnedMesh)
|
||||
return;
|
||||
const clonedMesh = node;
|
||||
const sourceMesh = sourceLookup.get(node);
|
||||
const sourceBones = sourceMesh.skeleton.bones;
|
||||
clonedMesh.skeleton = sourceMesh.skeleton.clone();
|
||||
clonedMesh.bindMatrix.copy(sourceMesh.bindMatrix);
|
||||
clonedMesh.skeleton.bones = sourceBones.map(function(bone) {
|
||||
return cloneLookup.get(bone);
|
||||
});
|
||||
clonedMesh.bind(clonedMesh.skeleton, clonedMesh.bindMatrix);
|
||||
});
|
||||
return clone2;
|
||||
}
|
||||
function getBoneByName(name, skeleton) {
|
||||
for (let i = 0, bones = getBones(skeleton); i < bones.length; i++) {
|
||||
if (name === bones[i].name)
|
||||
return bones[i];
|
||||
}
|
||||
}
|
||||
function getBones(skeleton) {
|
||||
return Array.isArray(skeleton) ? skeleton : skeleton.bones;
|
||||
}
|
||||
function getHelperFromSkeleton(skeleton) {
|
||||
const source = new THREE.SkeletonHelper(skeleton.bones[0]);
|
||||
source.skeleton = skeleton;
|
||||
return source;
|
||||
}
|
||||
function parallelTraverse(a, b, callback) {
|
||||
callback(a, b);
|
||||
for (let i = 0; i < a.children.length; i++) {
|
||||
parallelTraverse(a.children[i], b.children[i], callback);
|
||||
}
|
||||
}
|
||||
const SkeletonUtils = { retarget, retargetClip, clone };
|
||||
exports.SkeletonUtils = SkeletonUtils;
|
||||
//# sourceMappingURL=SkeletonUtils.cjs.map
|
||||
1
node_modules/three-stdlib/utils/SkeletonUtils.cjs.map
generated
vendored
Normal file
1
node_modules/three-stdlib/utils/SkeletonUtils.cjs.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
14
node_modules/three-stdlib/utils/SkeletonUtils.d.ts
generated
vendored
Normal file
14
node_modules/three-stdlib/utils/SkeletonUtils.d.ts
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
import { AnimationClip, Object3D, Skeleton } from 'three'
|
||||
|
||||
export namespace SkeletonUtils {
|
||||
export function clone(source: Object3D): Object3D
|
||||
|
||||
export function retarget(target: Object3D | Skeleton, source: Object3D | Skeleton, options: {}): void
|
||||
|
||||
export function retargetClip(
|
||||
target: Skeleton | Object3D,
|
||||
source: Skeleton | Object3D,
|
||||
clip: AnimationClip,
|
||||
options: {},
|
||||
): AnimationClip
|
||||
}
|
||||
212
node_modules/three-stdlib/utils/SkeletonUtils.js
generated
vendored
Normal file
212
node_modules/three-stdlib/utils/SkeletonUtils.js
generated
vendored
Normal file
@@ -0,0 +1,212 @@
|
||||
import { Vector3, Quaternion, Matrix4, AnimationMixer, VectorKeyframeTrack, QuaternionKeyframeTrack, AnimationClip, SkeletonHelper } from "three";
|
||||
function retarget(target, source, options = {}) {
|
||||
const pos = new Vector3(), quat = new Quaternion(), scale = new Vector3(), bindBoneMatrix = new Matrix4(), relativeMatrix = new Matrix4(), globalMatrix = new Matrix4();
|
||||
options.preserveMatrix = options.preserveMatrix !== void 0 ? options.preserveMatrix : true;
|
||||
options.preservePosition = options.preservePosition !== void 0 ? options.preservePosition : true;
|
||||
options.preserveHipPosition = options.preserveHipPosition !== void 0 ? options.preserveHipPosition : false;
|
||||
options.useTargetMatrix = options.useTargetMatrix !== void 0 ? options.useTargetMatrix : false;
|
||||
options.hip = options.hip !== void 0 ? options.hip : "hip";
|
||||
options.names = options.names || {};
|
||||
const sourceBones = source.isObject3D ? source.skeleton.bones : getBones(source), bones = target.isObject3D ? target.skeleton.bones : getBones(target);
|
||||
let bindBones, bone, name, boneTo, bonesPosition;
|
||||
if (target.isObject3D) {
|
||||
target.skeleton.pose();
|
||||
} else {
|
||||
options.useTargetMatrix = true;
|
||||
options.preserveMatrix = false;
|
||||
}
|
||||
if (options.preservePosition) {
|
||||
bonesPosition = [];
|
||||
for (let i = 0; i < bones.length; i++) {
|
||||
bonesPosition.push(bones[i].position.clone());
|
||||
}
|
||||
}
|
||||
if (options.preserveMatrix) {
|
||||
target.updateMatrixWorld();
|
||||
target.matrixWorld.identity();
|
||||
for (let i = 0; i < target.children.length; ++i) {
|
||||
target.children[i].updateMatrixWorld(true);
|
||||
}
|
||||
}
|
||||
if (options.offsets) {
|
||||
bindBones = [];
|
||||
for (let i = 0; i < bones.length; ++i) {
|
||||
bone = bones[i];
|
||||
name = options.names[bone.name] || bone.name;
|
||||
if (options.offsets[name]) {
|
||||
bone.matrix.multiply(options.offsets[name]);
|
||||
bone.matrix.decompose(bone.position, bone.quaternion, bone.scale);
|
||||
bone.updateMatrixWorld();
|
||||
}
|
||||
bindBones.push(bone.matrixWorld.clone());
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < bones.length; ++i) {
|
||||
bone = bones[i];
|
||||
name = options.names[bone.name] || bone.name;
|
||||
boneTo = getBoneByName(name, sourceBones);
|
||||
globalMatrix.copy(bone.matrixWorld);
|
||||
if (boneTo) {
|
||||
boneTo.updateMatrixWorld();
|
||||
if (options.useTargetMatrix) {
|
||||
relativeMatrix.copy(boneTo.matrixWorld);
|
||||
} else {
|
||||
relativeMatrix.copy(target.matrixWorld).invert();
|
||||
relativeMatrix.multiply(boneTo.matrixWorld);
|
||||
}
|
||||
scale.setFromMatrixScale(relativeMatrix);
|
||||
relativeMatrix.scale(scale.set(1 / scale.x, 1 / scale.y, 1 / scale.z));
|
||||
globalMatrix.makeRotationFromQuaternion(quat.setFromRotationMatrix(relativeMatrix));
|
||||
if (target.isObject3D) {
|
||||
const boneIndex = bones.indexOf(bone), wBindMatrix = bindBones ? bindBones[boneIndex] : bindBoneMatrix.copy(target.skeleton.boneInverses[boneIndex]).invert();
|
||||
globalMatrix.multiply(wBindMatrix);
|
||||
}
|
||||
globalMatrix.copyPosition(relativeMatrix);
|
||||
}
|
||||
if (bone.parent && bone.parent.isBone) {
|
||||
bone.matrix.copy(bone.parent.matrixWorld).invert();
|
||||
bone.matrix.multiply(globalMatrix);
|
||||
} else {
|
||||
bone.matrix.copy(globalMatrix);
|
||||
}
|
||||
if (options.preserveHipPosition && name === options.hip) {
|
||||
bone.matrix.setPosition(pos.set(0, bone.position.y, 0));
|
||||
}
|
||||
bone.matrix.decompose(bone.position, bone.quaternion, bone.scale);
|
||||
bone.updateMatrixWorld();
|
||||
}
|
||||
if (options.preservePosition) {
|
||||
for (let i = 0; i < bones.length; ++i) {
|
||||
bone = bones[i];
|
||||
name = options.names[bone.name] || bone.name;
|
||||
if (name !== options.hip) {
|
||||
bone.position.copy(bonesPosition[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (options.preserveMatrix) {
|
||||
target.updateMatrixWorld(true);
|
||||
}
|
||||
}
|
||||
function retargetClip(target, source, clip, options = {}) {
|
||||
options.useFirstFramePosition = options.useFirstFramePosition !== void 0 ? options.useFirstFramePosition : false;
|
||||
options.fps = options.fps !== void 0 ? options.fps : 30;
|
||||
options.names = options.names || [];
|
||||
if (!source.isObject3D) {
|
||||
source = getHelperFromSkeleton(source);
|
||||
}
|
||||
const numFrames = Math.round(clip.duration * (options.fps / 1e3) * 1e3), delta = 1 / options.fps, convertedTracks = [], mixer = new AnimationMixer(source), bones = getBones(target.skeleton), boneDatas = [];
|
||||
let positionOffset, bone, boneTo, boneData, name;
|
||||
mixer.clipAction(clip).play();
|
||||
mixer.update(0);
|
||||
source.updateMatrixWorld();
|
||||
for (let i = 0; i < numFrames; ++i) {
|
||||
const time = i * delta;
|
||||
retarget(target, source, options);
|
||||
for (let j = 0; j < bones.length; ++j) {
|
||||
name = options.names[bones[j].name] || bones[j].name;
|
||||
boneTo = getBoneByName(name, source.skeleton);
|
||||
if (boneTo) {
|
||||
bone = bones[j];
|
||||
boneData = boneDatas[j] = boneDatas[j] || { bone };
|
||||
if (options.hip === name) {
|
||||
if (!boneData.pos) {
|
||||
boneData.pos = {
|
||||
times: new Float32Array(numFrames),
|
||||
values: new Float32Array(numFrames * 3)
|
||||
};
|
||||
}
|
||||
if (options.useFirstFramePosition) {
|
||||
if (i === 0) {
|
||||
positionOffset = bone.position.clone();
|
||||
}
|
||||
bone.position.sub(positionOffset);
|
||||
}
|
||||
boneData.pos.times[i] = time;
|
||||
bone.position.toArray(boneData.pos.values, i * 3);
|
||||
}
|
||||
if (!boneData.quat) {
|
||||
boneData.quat = {
|
||||
times: new Float32Array(numFrames),
|
||||
values: new Float32Array(numFrames * 4)
|
||||
};
|
||||
}
|
||||
boneData.quat.times[i] = time;
|
||||
bone.quaternion.toArray(boneData.quat.values, i * 4);
|
||||
}
|
||||
}
|
||||
mixer.update(delta);
|
||||
source.updateMatrixWorld();
|
||||
}
|
||||
for (let i = 0; i < boneDatas.length; ++i) {
|
||||
boneData = boneDatas[i];
|
||||
if (boneData) {
|
||||
if (boneData.pos) {
|
||||
convertedTracks.push(
|
||||
new VectorKeyframeTrack(
|
||||
".bones[" + boneData.bone.name + "].position",
|
||||
boneData.pos.times,
|
||||
boneData.pos.values
|
||||
)
|
||||
);
|
||||
}
|
||||
convertedTracks.push(
|
||||
new QuaternionKeyframeTrack(
|
||||
".bones[" + boneData.bone.name + "].quaternion",
|
||||
boneData.quat.times,
|
||||
boneData.quat.values
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
mixer.uncacheAction(clip);
|
||||
return new AnimationClip(clip.name, -1, convertedTracks);
|
||||
}
|
||||
function clone(source) {
|
||||
const sourceLookup = /* @__PURE__ */ new Map();
|
||||
const cloneLookup = /* @__PURE__ */ new Map();
|
||||
const clone2 = source.clone();
|
||||
parallelTraverse(source, clone2, function(sourceNode, clonedNode) {
|
||||
sourceLookup.set(clonedNode, sourceNode);
|
||||
cloneLookup.set(sourceNode, clonedNode);
|
||||
});
|
||||
clone2.traverse(function(node) {
|
||||
if (!node.isSkinnedMesh)
|
||||
return;
|
||||
const clonedMesh = node;
|
||||
const sourceMesh = sourceLookup.get(node);
|
||||
const sourceBones = sourceMesh.skeleton.bones;
|
||||
clonedMesh.skeleton = sourceMesh.skeleton.clone();
|
||||
clonedMesh.bindMatrix.copy(sourceMesh.bindMatrix);
|
||||
clonedMesh.skeleton.bones = sourceBones.map(function(bone) {
|
||||
return cloneLookup.get(bone);
|
||||
});
|
||||
clonedMesh.bind(clonedMesh.skeleton, clonedMesh.bindMatrix);
|
||||
});
|
||||
return clone2;
|
||||
}
|
||||
function getBoneByName(name, skeleton) {
|
||||
for (let i = 0, bones = getBones(skeleton); i < bones.length; i++) {
|
||||
if (name === bones[i].name)
|
||||
return bones[i];
|
||||
}
|
||||
}
|
||||
function getBones(skeleton) {
|
||||
return Array.isArray(skeleton) ? skeleton : skeleton.bones;
|
||||
}
|
||||
function getHelperFromSkeleton(skeleton) {
|
||||
const source = new SkeletonHelper(skeleton.bones[0]);
|
||||
source.skeleton = skeleton;
|
||||
return source;
|
||||
}
|
||||
function parallelTraverse(a, b, callback) {
|
||||
callback(a, b);
|
||||
for (let i = 0; i < a.children.length; i++) {
|
||||
parallelTraverse(a.children[i], b.children[i], callback);
|
||||
}
|
||||
}
|
||||
const SkeletonUtils = { retarget, retargetClip, clone };
|
||||
export {
|
||||
SkeletonUtils
|
||||
};
|
||||
//# sourceMappingURL=SkeletonUtils.js.map
|
||||
1
node_modules/three-stdlib/utils/SkeletonUtils.js.map
generated
vendored
Normal file
1
node_modules/three-stdlib/utils/SkeletonUtils.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
81
node_modules/three-stdlib/utils/UVsDebug.cjs
generated
vendored
Normal file
81
node_modules/three-stdlib/utils/UVsDebug.cjs
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
||||
const THREE = require("three");
|
||||
function UVsDebug(geometry, size = 1024) {
|
||||
const abc = "abc";
|
||||
const a = new THREE.Vector2();
|
||||
const b = new THREE.Vector2();
|
||||
const uvs = [new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2()];
|
||||
const face = [];
|
||||
const canvas = document.createElement("canvas");
|
||||
const width = size;
|
||||
const height = size;
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.lineWidth = 1;
|
||||
ctx.strokeStyle = "rgb( 63, 63, 63 )";
|
||||
ctx.textAlign = "center";
|
||||
ctx.fillStyle = "rgb( 255, 255, 255 )";
|
||||
ctx.fillRect(0, 0, width, height);
|
||||
const index = geometry.index;
|
||||
const uvAttribute = geometry.attributes.uv;
|
||||
if (index) {
|
||||
for (let i = 0, il = index.count; i < il; i += 3) {
|
||||
face[0] = index.getX(i);
|
||||
face[1] = index.getX(i + 1);
|
||||
face[2] = index.getX(i + 2);
|
||||
uvs[0].fromBufferAttribute(uvAttribute, face[0]);
|
||||
uvs[1].fromBufferAttribute(uvAttribute, face[1]);
|
||||
uvs[2].fromBufferAttribute(uvAttribute, face[2]);
|
||||
processFace(face, uvs, i / 3);
|
||||
}
|
||||
} else {
|
||||
for (let i = 0, il = uvAttribute.count; i < il; i += 3) {
|
||||
face[0] = i;
|
||||
face[1] = i + 1;
|
||||
face[2] = i + 2;
|
||||
uvs[0].fromBufferAttribute(uvAttribute, face[0]);
|
||||
uvs[1].fromBufferAttribute(uvAttribute, face[1]);
|
||||
uvs[2].fromBufferAttribute(uvAttribute, face[2]);
|
||||
processFace(face, uvs, i / 3);
|
||||
}
|
||||
}
|
||||
return canvas;
|
||||
function processFace(face2, uvs2, index2) {
|
||||
ctx.beginPath();
|
||||
a.set(0, 0);
|
||||
for (let j = 0, jl = uvs2.length; j < jl; j++) {
|
||||
const uv = uvs2[j];
|
||||
a.x += uv.x;
|
||||
a.y += uv.y;
|
||||
if (j === 0) {
|
||||
ctx.moveTo(uv.x * (width - 2) + 0.5, (1 - uv.y) * (height - 2) + 0.5);
|
||||
} else {
|
||||
ctx.lineTo(uv.x * (width - 2) + 0.5, (1 - uv.y) * (height - 2) + 0.5);
|
||||
}
|
||||
}
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
a.divideScalar(uvs2.length);
|
||||
ctx.font = "18px Arial";
|
||||
ctx.fillStyle = "rgb( 63, 63, 63 )";
|
||||
ctx.fillText(index2, a.x * width, (1 - a.y) * height);
|
||||
if (a.x > 0.95) {
|
||||
ctx.fillText(index2, a.x % 1 * width, (1 - a.y) * height);
|
||||
}
|
||||
ctx.font = "12px Arial";
|
||||
ctx.fillStyle = "rgb( 191, 191, 191 )";
|
||||
for (let j = 0, jl = uvs2.length; j < jl; j++) {
|
||||
const uv = uvs2[j];
|
||||
b.addVectors(a, uv).divideScalar(2);
|
||||
const vnum = face2[j];
|
||||
ctx.fillText(abc[j] + vnum, b.x * width, (1 - b.y) * height);
|
||||
if (b.x > 0.95) {
|
||||
ctx.fillText(abc[j] + vnum, b.x % 1 * width, (1 - b.y) * height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.UVsDebug = UVsDebug;
|
||||
//# sourceMappingURL=UVsDebug.cjs.map
|
||||
1
node_modules/three-stdlib/utils/UVsDebug.cjs.map
generated
vendored
Normal file
1
node_modules/three-stdlib/utils/UVsDebug.cjs.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
3
node_modules/three-stdlib/utils/UVsDebug.d.ts
generated
vendored
Normal file
3
node_modules/three-stdlib/utils/UVsDebug.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import { BufferGeometry } from 'three'
|
||||
|
||||
export function UVsDebug(geometry: BufferGeometry, size: number): HTMLCanvasElement
|
||||
81
node_modules/three-stdlib/utils/UVsDebug.js
generated
vendored
Normal file
81
node_modules/three-stdlib/utils/UVsDebug.js
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
import { Vector2 } from "three";
|
||||
function UVsDebug(geometry, size = 1024) {
|
||||
const abc = "abc";
|
||||
const a = new Vector2();
|
||||
const b = new Vector2();
|
||||
const uvs = [new Vector2(), new Vector2(), new Vector2()];
|
||||
const face = [];
|
||||
const canvas = document.createElement("canvas");
|
||||
const width = size;
|
||||
const height = size;
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.lineWidth = 1;
|
||||
ctx.strokeStyle = "rgb( 63, 63, 63 )";
|
||||
ctx.textAlign = "center";
|
||||
ctx.fillStyle = "rgb( 255, 255, 255 )";
|
||||
ctx.fillRect(0, 0, width, height);
|
||||
const index = geometry.index;
|
||||
const uvAttribute = geometry.attributes.uv;
|
||||
if (index) {
|
||||
for (let i = 0, il = index.count; i < il; i += 3) {
|
||||
face[0] = index.getX(i);
|
||||
face[1] = index.getX(i + 1);
|
||||
face[2] = index.getX(i + 2);
|
||||
uvs[0].fromBufferAttribute(uvAttribute, face[0]);
|
||||
uvs[1].fromBufferAttribute(uvAttribute, face[1]);
|
||||
uvs[2].fromBufferAttribute(uvAttribute, face[2]);
|
||||
processFace(face, uvs, i / 3);
|
||||
}
|
||||
} else {
|
||||
for (let i = 0, il = uvAttribute.count; i < il; i += 3) {
|
||||
face[0] = i;
|
||||
face[1] = i + 1;
|
||||
face[2] = i + 2;
|
||||
uvs[0].fromBufferAttribute(uvAttribute, face[0]);
|
||||
uvs[1].fromBufferAttribute(uvAttribute, face[1]);
|
||||
uvs[2].fromBufferAttribute(uvAttribute, face[2]);
|
||||
processFace(face, uvs, i / 3);
|
||||
}
|
||||
}
|
||||
return canvas;
|
||||
function processFace(face2, uvs2, index2) {
|
||||
ctx.beginPath();
|
||||
a.set(0, 0);
|
||||
for (let j = 0, jl = uvs2.length; j < jl; j++) {
|
||||
const uv = uvs2[j];
|
||||
a.x += uv.x;
|
||||
a.y += uv.y;
|
||||
if (j === 0) {
|
||||
ctx.moveTo(uv.x * (width - 2) + 0.5, (1 - uv.y) * (height - 2) + 0.5);
|
||||
} else {
|
||||
ctx.lineTo(uv.x * (width - 2) + 0.5, (1 - uv.y) * (height - 2) + 0.5);
|
||||
}
|
||||
}
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
a.divideScalar(uvs2.length);
|
||||
ctx.font = "18px Arial";
|
||||
ctx.fillStyle = "rgb( 63, 63, 63 )";
|
||||
ctx.fillText(index2, a.x * width, (1 - a.y) * height);
|
||||
if (a.x > 0.95) {
|
||||
ctx.fillText(index2, a.x % 1 * width, (1 - a.y) * height);
|
||||
}
|
||||
ctx.font = "12px Arial";
|
||||
ctx.fillStyle = "rgb( 191, 191, 191 )";
|
||||
for (let j = 0, jl = uvs2.length; j < jl; j++) {
|
||||
const uv = uvs2[j];
|
||||
b.addVectors(a, uv).divideScalar(2);
|
||||
const vnum = face2[j];
|
||||
ctx.fillText(abc[j] + vnum, b.x * width, (1 - b.y) * height);
|
||||
if (b.x > 0.95) {
|
||||
ctx.fillText(abc[j] + vnum, b.x % 1 * width, (1 - b.y) * height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
export {
|
||||
UVsDebug
|
||||
};
|
||||
//# sourceMappingURL=UVsDebug.js.map
|
||||
1
node_modules/three-stdlib/utils/UVsDebug.js.map
generated
vendored
Normal file
1
node_modules/three-stdlib/utils/UVsDebug.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
63
node_modules/three-stdlib/utils/WorkerPool.cjs
generated
vendored
Normal file
63
node_modules/three-stdlib/utils/WorkerPool.cjs
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
||||
class WorkerPool {
|
||||
constructor(pool = 4) {
|
||||
this.pool = pool;
|
||||
this.queue = [];
|
||||
this.workers = [];
|
||||
this.workersResolve = [];
|
||||
this.workerStatus = 0;
|
||||
}
|
||||
_initWorker(workerId) {
|
||||
if (!this.workers[workerId]) {
|
||||
const worker = this.workerCreator();
|
||||
worker.addEventListener("message", this._onMessage.bind(this, workerId));
|
||||
this.workers[workerId] = worker;
|
||||
}
|
||||
}
|
||||
_getIdleWorker() {
|
||||
for (let i = 0; i < this.pool; i++)
|
||||
if (!(this.workerStatus & 1 << i))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
_onMessage(workerId, msg) {
|
||||
const resolve = this.workersResolve[workerId];
|
||||
resolve && resolve(msg);
|
||||
if (this.queue.length) {
|
||||
const { resolve: resolve2, msg: msg2, transfer } = this.queue.shift();
|
||||
this.workersResolve[workerId] = resolve2;
|
||||
this.workers[workerId].postMessage(msg2, transfer);
|
||||
} else {
|
||||
this.workerStatus ^= 1 << workerId;
|
||||
}
|
||||
}
|
||||
setWorkerCreator(workerCreator) {
|
||||
this.workerCreator = workerCreator;
|
||||
}
|
||||
setWorkerLimit(pool) {
|
||||
this.pool = pool;
|
||||
}
|
||||
postMessage(msg, transfer) {
|
||||
return new Promise((resolve) => {
|
||||
const workerId = this._getIdleWorker();
|
||||
if (workerId !== -1) {
|
||||
this._initWorker(workerId);
|
||||
this.workerStatus |= 1 << workerId;
|
||||
this.workersResolve[workerId] = resolve;
|
||||
this.workers[workerId].postMessage(msg, transfer);
|
||||
} else {
|
||||
this.queue.push({ resolve, msg, transfer });
|
||||
}
|
||||
});
|
||||
}
|
||||
dispose() {
|
||||
this.workers.forEach((worker) => worker.terminate());
|
||||
this.workersResolve.length = 0;
|
||||
this.workers.length = 0;
|
||||
this.queue.length = 0;
|
||||
this.workerStatus = 0;
|
||||
}
|
||||
}
|
||||
exports.WorkerPool = WorkerPool;
|
||||
//# sourceMappingURL=WorkerPool.cjs.map
|
||||
1
node_modules/three-stdlib/utils/WorkerPool.cjs.map
generated
vendored
Normal file
1
node_modules/three-stdlib/utils/WorkerPool.cjs.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"WorkerPool.cjs","sources":["../../src/utils/WorkerPool.js"],"sourcesContent":["/**\n * @author Deepkolos / https://github.com/deepkolos\n */\n\nexport class WorkerPool {\n constructor(pool = 4) {\n this.pool = pool\n this.queue = []\n this.workers = []\n this.workersResolve = []\n this.workerStatus = 0\n }\n\n _initWorker(workerId) {\n if (!this.workers[workerId]) {\n const worker = this.workerCreator()\n worker.addEventListener('message', this._onMessage.bind(this, workerId))\n this.workers[workerId] = worker\n }\n }\n\n _getIdleWorker() {\n for (let i = 0; i < this.pool; i++) if (!(this.workerStatus & (1 << i))) return i\n\n return -1\n }\n\n _onMessage(workerId, msg) {\n const resolve = this.workersResolve[workerId]\n resolve && resolve(msg)\n\n if (this.queue.length) {\n const { resolve, msg, transfer } = this.queue.shift()\n this.workersResolve[workerId] = resolve\n this.workers[workerId].postMessage(msg, transfer)\n } else {\n this.workerStatus ^= 1 << workerId\n }\n }\n\n setWorkerCreator(workerCreator) {\n this.workerCreator = workerCreator\n }\n\n setWorkerLimit(pool) {\n this.pool = pool\n }\n\n postMessage(msg, transfer) {\n return new Promise((resolve) => {\n const workerId = this._getIdleWorker()\n\n if (workerId !== -1) {\n this._initWorker(workerId)\n this.workerStatus |= 1 << workerId\n this.workersResolve[workerId] = resolve\n this.workers[workerId].postMessage(msg, transfer)\n } else {\n this.queue.push({ resolve, msg, transfer })\n }\n })\n }\n\n dispose() {\n this.workers.forEach((worker) => worker.terminate())\n this.workersResolve.length = 0\n this.workers.length = 0\n this.queue.length = 0\n this.workerStatus = 0\n }\n}\n"],"names":["resolve","msg"],"mappings":";;AAIO,MAAM,WAAW;AAAA,EACtB,YAAY,OAAO,GAAG;AACpB,SAAK,OAAO;AACZ,SAAK,QAAQ,CAAE;AACf,SAAK,UAAU,CAAE;AACjB,SAAK,iBAAiB,CAAE;AACxB,SAAK,eAAe;AAAA,EACrB;AAAA,EAED,YAAY,UAAU;AACpB,QAAI,CAAC,KAAK,QAAQ,QAAQ,GAAG;AAC3B,YAAM,SAAS,KAAK,cAAe;AACnC,aAAO,iBAAiB,WAAW,KAAK,WAAW,KAAK,MAAM,QAAQ,CAAC;AACvE,WAAK,QAAQ,QAAQ,IAAI;AAAA,IAC1B;AAAA,EACF;AAAA,EAED,iBAAiB;AACf,aAAS,IAAI,GAAG,IAAI,KAAK,MAAM;AAAK,UAAI,EAAE,KAAK,eAAgB,KAAK;AAAK,eAAO;AAEhF,WAAO;AAAA,EACR;AAAA,EAED,WAAW,UAAU,KAAK;AACxB,UAAM,UAAU,KAAK,eAAe,QAAQ;AAC5C,eAAW,QAAQ,GAAG;AAEtB,QAAI,KAAK,MAAM,QAAQ;AACrB,YAAM,EAAE,SAAAA,UAAS,KAAAC,MAAK,SAAU,IAAG,KAAK,MAAM,MAAO;AACrD,WAAK,eAAe,QAAQ,IAAID;AAChC,WAAK,QAAQ,QAAQ,EAAE,YAAYC,MAAK,QAAQ;AAAA,IACtD,OAAW;AACL,WAAK,gBAAgB,KAAK;AAAA,IAC3B;AAAA,EACF;AAAA,EAED,iBAAiB,eAAe;AAC9B,SAAK,gBAAgB;AAAA,EACtB;AAAA,EAED,eAAe,MAAM;AACnB,SAAK,OAAO;AAAA,EACb;AAAA,EAED,YAAY,KAAK,UAAU;AACzB,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,YAAM,WAAW,KAAK,eAAgB;AAEtC,UAAI,aAAa,IAAI;AACnB,aAAK,YAAY,QAAQ;AACzB,aAAK,gBAAgB,KAAK;AAC1B,aAAK,eAAe,QAAQ,IAAI;AAChC,aAAK,QAAQ,QAAQ,EAAE,YAAY,KAAK,QAAQ;AAAA,MACxD,OAAa;AACL,aAAK,MAAM,KAAK,EAAE,SAAS,KAAK,UAAU;AAAA,MAC3C;AAAA,IACP,CAAK;AAAA,EACF;AAAA,EAED,UAAU;AACR,SAAK,QAAQ,QAAQ,CAAC,WAAW,OAAO,WAAW;AACnD,SAAK,eAAe,SAAS;AAC7B,SAAK,QAAQ,SAAS;AACtB,SAAK,MAAM,SAAS;AACpB,SAAK,eAAe;AAAA,EACrB;AACH;;"}
|
||||
63
node_modules/three-stdlib/utils/WorkerPool.js
generated
vendored
Normal file
63
node_modules/three-stdlib/utils/WorkerPool.js
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
class WorkerPool {
|
||||
constructor(pool = 4) {
|
||||
this.pool = pool;
|
||||
this.queue = [];
|
||||
this.workers = [];
|
||||
this.workersResolve = [];
|
||||
this.workerStatus = 0;
|
||||
}
|
||||
_initWorker(workerId) {
|
||||
if (!this.workers[workerId]) {
|
||||
const worker = this.workerCreator();
|
||||
worker.addEventListener("message", this._onMessage.bind(this, workerId));
|
||||
this.workers[workerId] = worker;
|
||||
}
|
||||
}
|
||||
_getIdleWorker() {
|
||||
for (let i = 0; i < this.pool; i++)
|
||||
if (!(this.workerStatus & 1 << i))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
_onMessage(workerId, msg) {
|
||||
const resolve = this.workersResolve[workerId];
|
||||
resolve && resolve(msg);
|
||||
if (this.queue.length) {
|
||||
const { resolve: resolve2, msg: msg2, transfer } = this.queue.shift();
|
||||
this.workersResolve[workerId] = resolve2;
|
||||
this.workers[workerId].postMessage(msg2, transfer);
|
||||
} else {
|
||||
this.workerStatus ^= 1 << workerId;
|
||||
}
|
||||
}
|
||||
setWorkerCreator(workerCreator) {
|
||||
this.workerCreator = workerCreator;
|
||||
}
|
||||
setWorkerLimit(pool) {
|
||||
this.pool = pool;
|
||||
}
|
||||
postMessage(msg, transfer) {
|
||||
return new Promise((resolve) => {
|
||||
const workerId = this._getIdleWorker();
|
||||
if (workerId !== -1) {
|
||||
this._initWorker(workerId);
|
||||
this.workerStatus |= 1 << workerId;
|
||||
this.workersResolve[workerId] = resolve;
|
||||
this.workers[workerId].postMessage(msg, transfer);
|
||||
} else {
|
||||
this.queue.push({ resolve, msg, transfer });
|
||||
}
|
||||
});
|
||||
}
|
||||
dispose() {
|
||||
this.workers.forEach((worker) => worker.terminate());
|
||||
this.workersResolve.length = 0;
|
||||
this.workers.length = 0;
|
||||
this.queue.length = 0;
|
||||
this.workerStatus = 0;
|
||||
}
|
||||
}
|
||||
export {
|
||||
WorkerPool
|
||||
};
|
||||
//# sourceMappingURL=WorkerPool.js.map
|
||||
1
node_modules/three-stdlib/utils/WorkerPool.js.map
generated
vendored
Normal file
1
node_modules/three-stdlib/utils/WorkerPool.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"WorkerPool.js","sources":["../../src/utils/WorkerPool.js"],"sourcesContent":["/**\n * @author Deepkolos / https://github.com/deepkolos\n */\n\nexport class WorkerPool {\n constructor(pool = 4) {\n this.pool = pool\n this.queue = []\n this.workers = []\n this.workersResolve = []\n this.workerStatus = 0\n }\n\n _initWorker(workerId) {\n if (!this.workers[workerId]) {\n const worker = this.workerCreator()\n worker.addEventListener('message', this._onMessage.bind(this, workerId))\n this.workers[workerId] = worker\n }\n }\n\n _getIdleWorker() {\n for (let i = 0; i < this.pool; i++) if (!(this.workerStatus & (1 << i))) return i\n\n return -1\n }\n\n _onMessage(workerId, msg) {\n const resolve = this.workersResolve[workerId]\n resolve && resolve(msg)\n\n if (this.queue.length) {\n const { resolve, msg, transfer } = this.queue.shift()\n this.workersResolve[workerId] = resolve\n this.workers[workerId].postMessage(msg, transfer)\n } else {\n this.workerStatus ^= 1 << workerId\n }\n }\n\n setWorkerCreator(workerCreator) {\n this.workerCreator = workerCreator\n }\n\n setWorkerLimit(pool) {\n this.pool = pool\n }\n\n postMessage(msg, transfer) {\n return new Promise((resolve) => {\n const workerId = this._getIdleWorker()\n\n if (workerId !== -1) {\n this._initWorker(workerId)\n this.workerStatus |= 1 << workerId\n this.workersResolve[workerId] = resolve\n this.workers[workerId].postMessage(msg, transfer)\n } else {\n this.queue.push({ resolve, msg, transfer })\n }\n })\n }\n\n dispose() {\n this.workers.forEach((worker) => worker.terminate())\n this.workersResolve.length = 0\n this.workers.length = 0\n this.queue.length = 0\n this.workerStatus = 0\n }\n}\n"],"names":["resolve","msg"],"mappings":"AAIO,MAAM,WAAW;AAAA,EACtB,YAAY,OAAO,GAAG;AACpB,SAAK,OAAO;AACZ,SAAK,QAAQ,CAAE;AACf,SAAK,UAAU,CAAE;AACjB,SAAK,iBAAiB,CAAE;AACxB,SAAK,eAAe;AAAA,EACrB;AAAA,EAED,YAAY,UAAU;AACpB,QAAI,CAAC,KAAK,QAAQ,QAAQ,GAAG;AAC3B,YAAM,SAAS,KAAK,cAAe;AACnC,aAAO,iBAAiB,WAAW,KAAK,WAAW,KAAK,MAAM,QAAQ,CAAC;AACvE,WAAK,QAAQ,QAAQ,IAAI;AAAA,IAC1B;AAAA,EACF;AAAA,EAED,iBAAiB;AACf,aAAS,IAAI,GAAG,IAAI,KAAK,MAAM;AAAK,UAAI,EAAE,KAAK,eAAgB,KAAK;AAAK,eAAO;AAEhF,WAAO;AAAA,EACR;AAAA,EAED,WAAW,UAAU,KAAK;AACxB,UAAM,UAAU,KAAK,eAAe,QAAQ;AAC5C,eAAW,QAAQ,GAAG;AAEtB,QAAI,KAAK,MAAM,QAAQ;AACrB,YAAM,EAAE,SAAAA,UAAS,KAAAC,MAAK,SAAU,IAAG,KAAK,MAAM,MAAO;AACrD,WAAK,eAAe,QAAQ,IAAID;AAChC,WAAK,QAAQ,QAAQ,EAAE,YAAYC,MAAK,QAAQ;AAAA,IACtD,OAAW;AACL,WAAK,gBAAgB,KAAK;AAAA,IAC3B;AAAA,EACF;AAAA,EAED,iBAAiB,eAAe;AAC9B,SAAK,gBAAgB;AAAA,EACtB;AAAA,EAED,eAAe,MAAM;AACnB,SAAK,OAAO;AAAA,EACb;AAAA,EAED,YAAY,KAAK,UAAU;AACzB,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,YAAM,WAAW,KAAK,eAAgB;AAEtC,UAAI,aAAa,IAAI;AACnB,aAAK,YAAY,QAAQ;AACzB,aAAK,gBAAgB,KAAK;AAC1B,aAAK,eAAe,QAAQ,IAAI;AAChC,aAAK,QAAQ,QAAQ,EAAE,YAAY,KAAK,QAAQ;AAAA,MACxD,OAAa;AACL,aAAK,MAAM,KAAK,EAAE,SAAS,KAAK,UAAU;AAAA,MAC3C;AAAA,IACP,CAAK;AAAA,EACF;AAAA,EAED,UAAU;AACR,SAAK,QAAQ,QAAQ,CAAC,WAAW,OAAO,WAAW;AACnD,SAAK,eAAe,SAAS;AAC7B,SAAK,QAAQ,SAAS;AACtB,SAAK,MAAM,SAAS;AACpB,SAAK,eAAe;AAAA,EACrB;AACH;"}
|
||||
Reference in New Issue
Block a user