troika-three-utils
Advanced tools
Comparing version 0.37.0 to 0.38.0
@@ -0,0 +0,0 @@ import { encodeFloatToFourInts, decodeFloatFromFourInts } from '../src/ShaderFloatArray.js' |
@@ -6,2 +6,13 @@ # Change Log | ||
# [0.38.0](https://github.com/protectwise/troika/compare/v0.37.0...v0.38.0) (2021-01-24) | ||
### Features | ||
* move InstancedUniformsMesh to its own three-instanced-uniforms-mesh package ([f623b1f](https://github.com/protectwise/troika/commit/f623b1f2307b0db094912246ee4cf4bef54ffd85)) | ||
# [0.37.0](https://github.com/protectwise/troika/compare/v0.36.1...v0.37.0) (2021-01-18) | ||
@@ -8,0 +19,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { ShaderChunk, MathUtils, UniformsUtils, MeshDepthMaterial, RGBADepthPacking, MeshDistanceMaterial, ShaderLib, MeshBasicMaterial, InstancedMesh, InstancedBufferAttribute, Vector3, Mesh, CylinderBufferGeometry, Vector2, MeshStandardMaterial, DoubleSide } from 'three'; | ||
import { ShaderChunk, MathUtils, UniformsUtils, MeshDepthMaterial, RGBADepthPacking, MeshDistanceMaterial, ShaderLib, Vector3, Mesh, CylinderBufferGeometry, Vector2, MeshStandardMaterial, DoubleSide } from 'three'; | ||
@@ -469,188 +469,2 @@ /** | ||
const precededByUniformRE = /\buniform\s+(int|float|vec[234])\s+$/; | ||
const attrRefReplacer = (name, index, str) => (precededByUniformRE.test(str.substr(0, index)) ? name : `troika_${name}`); | ||
const varyingRefReplacer = (name, index, str) => (precededByUniformRE.test(str.substr(0, index)) ? name : `troika_vary_${name}`); | ||
function createInstancedUniformsDerivedMaterial (baseMaterial, uniformNames) { | ||
const derived = createDerivedMaterial(baseMaterial, { | ||
defines: { | ||
TROIKA_INSTANCED_UNIFORMS: uniformNames.sort().join('|') | ||
}, | ||
customRewriter ({ vertexShader, fragmentShader }) { | ||
let vertexDeclarations = []; | ||
let vertexAssignments = []; | ||
let fragmentDeclarations = []; | ||
// Find what uniforms are declared in which shader and their types | ||
let vertexUniforms = getShaderUniformTypes(vertexShader); | ||
let fragmentUniforms = getShaderUniformTypes(fragmentShader); | ||
// Add attributes and varyings for, and rewrite references to, instanceUniforms | ||
uniformNames.forEach((name) => { | ||
let vertType = vertexUniforms[name]; | ||
let fragType = fragmentUniforms[name]; | ||
if (vertType || fragType) { | ||
let finder = new RegExp(`\\b${name}\\b`, 'g'); | ||
vertexDeclarations.push(`attribute ${vertType || fragType} troika_attr_${name};`); | ||
if (vertType) { | ||
vertexShader = vertexShader.replace(finder, attrRefReplacer); | ||
} | ||
if (fragType) { | ||
fragmentShader = fragmentShader.replace(finder, varyingRefReplacer); | ||
let varyingDecl = `varying ${fragType} troika_vary_${name};`; | ||
vertexDeclarations.push(varyingDecl); | ||
fragmentDeclarations.push(varyingDecl); | ||
vertexAssignments.push(`troika_vary_${name} = troika_attr_${name};`); | ||
} | ||
} | ||
}); | ||
// Inject vertex shader declarations and assignments | ||
vertexShader = `${vertexDeclarations.join('\n')}\n${vertexShader.replace(voidMainRegExp, `\n$&\n${vertexAssignments.join('\n')}`)}`; | ||
// Inject fragment shader declarations | ||
if (fragmentDeclarations.length) { | ||
fragmentShader = `${fragmentDeclarations.join('\n')}\n${fragmentShader}`; | ||
} | ||
return { vertexShader, fragmentShader } | ||
} | ||
}); | ||
derived.isInstancedUniformsMaterial = true; | ||
return derived | ||
} | ||
const defaultMaterial = new MeshBasicMaterial(); | ||
class InstancedUniformsMesh extends InstancedMesh { | ||
constructor (geometry, material, count) { | ||
super(geometry, material, count); | ||
this._instancedUniformNames = []; //treated as immutable | ||
} | ||
/* | ||
* Getter/setter for automatically wrapping the user-supplied geometry with one that will | ||
* carry our extra InstancedBufferAttribute(s) | ||
*/ | ||
get geometry () { | ||
return this._derivedGeometry | ||
} | ||
set geometry (geometry) { | ||
// Extend the geometry so we can add our instancing attributes but inherit everything else | ||
if (geometry) { | ||
geometry = Object.create(geometry); | ||
geometry.attributes = Object.create(geometry.attributes); | ||
} | ||
this._derivedGeometry = geometry; | ||
} | ||
/* | ||
* Getter/setter for automatically wrapping the user-supplied material with our upgrades. We do the | ||
* wrapping lazily on _read_ rather than write to avoid unnecessary wrapping on transient values. | ||
*/ | ||
get material () { | ||
let derivedMaterial = this._derivedMaterial; | ||
const baseMaterial = this._baseMaterial || this._defaultMaterial || (this._defaultMaterial = defaultMaterial.clone()); | ||
const uniformNames = this._instancedUniformNames; | ||
if (!derivedMaterial || derivedMaterial.baseMaterial !== baseMaterial || derivedMaterial._instancedUniformNames !== uniformNames) { | ||
derivedMaterial = this._derivedMaterial = createInstancedUniformsDerivedMaterial(baseMaterial, uniformNames); | ||
derivedMaterial._instancedUniformNames = uniformNames; | ||
// dispose the derived material when its base material is disposed: | ||
baseMaterial.addEventListener('dispose', function onDispose () { | ||
baseMaterial.removeEventListener('dispose', onDispose); | ||
derivedMaterial.dispose(); | ||
}); | ||
} | ||
return derivedMaterial | ||
} | ||
set material (baseMaterial) { | ||
if (Array.isArray(baseMaterial)) { | ||
throw new Error('InstancedUniformsMesh does not support multiple materials') | ||
} | ||
// Unwrap already-derived materials | ||
while (baseMaterial && baseMaterial.isInstancedUniformsMaterial) { | ||
baseMaterial = baseMaterial.baseMaterial; | ||
} | ||
this._baseMaterial = baseMaterial; | ||
} | ||
get customDepthMaterial () { | ||
return this.material.getDepthMaterial() | ||
} | ||
get customDistanceMaterial () { | ||
return this.material.getDistanceMaterial() | ||
} | ||
/** | ||
* Set the value of a shader uniform for a single instance. | ||
* @param {string} name - the name of the shader uniform | ||
* @param {number} index - the index of the instance to set the value for | ||
* @param {number|Vector2|Vector3|Vector4|Color|Array} value - the uniform value for this instance | ||
*/ | ||
setUniformAt (name, index, value) { | ||
const attrs = this.geometry.attributes; | ||
const attrName = `troika_attr_${name}`; | ||
let attr = attrs[attrName]; | ||
if (!attr) { | ||
const defaultValue = getDefaultUniformValue(this._baseMaterial, name); | ||
const itemSize = getItemSizeForValue(defaultValue); | ||
attr = attrs[attrName] = new InstancedBufferAttribute(new Float32Array(itemSize * this.count), itemSize); | ||
// Fill with default value: | ||
if (defaultValue !== null) { | ||
for (let i = 0; i < this.count; i++) { | ||
setAttributeValue(attr, i, defaultValue); | ||
} | ||
} | ||
this._instancedUniformNames = [...this._instancedUniformNames, name]; | ||
} | ||
setAttributeValue(attr, index, value); | ||
attr.needsUpdate = true; | ||
} | ||
} | ||
function setAttributeValue (attr, index, value) { | ||
let size = attr.itemSize; | ||
if (size === 1) { | ||
attr.setX(index, value); | ||
} else if (size === 2) { | ||
attr.setXY(index, value.x, value.y); | ||
} else if (size === 3) { | ||
if (value.isColor) { | ||
attr.setXYZ(index, value.r, value.g, value.b); | ||
} else { | ||
attr.setXYZ(index, value.x, value.y, value.z); | ||
} | ||
} else if (size === 4) { | ||
attr.setXYZW(index, value.x, value.y, value.z, value.w); | ||
} | ||
} | ||
function getDefaultUniformValue (material, name) { | ||
// Try uniforms on the material itself, then try the builtin material shaders | ||
let uniforms = material.uniforms; | ||
if (uniforms && uniforms[name]) { | ||
return uniforms[name].value | ||
} | ||
uniforms = getShadersForMaterial(material).uniforms; | ||
if (uniforms && uniforms[name]) { | ||
return uniforms[name].value | ||
} | ||
return null | ||
} | ||
function getItemSizeForValue (value) { | ||
return value == null ? 0 | ||
: typeof value === 'number' ? 1 | ||
: value.isVector2 ? 2 | ||
: value.isVector3 || value.isColor ? 3 | ||
: value.isVector4 ? 4 | ||
: Array.isArray(value) ? value.length | ||
: 0 | ||
} | ||
/* | ||
@@ -865,2 +679,2 @@ Input geometry is a cylinder with r=1, height in y dimension from 0 to 1, | ||
export { BezierMesh, InstancedUniformsMesh, createDerivedMaterial, expandShaderIncludes, getShaderUniformTypes, getShadersForMaterial, voidMainRegExp }; | ||
export { BezierMesh, createDerivedMaterial, expandShaderIncludes, getShaderUniformTypes, getShadersForMaterial, voidMainRegExp }; |
@@ -458,201 +458,2 @@ (function (global, factory) { | ||
var precededByUniformRE = /\buniform\s+(int|float|vec[234])\s+$/; | ||
var attrRefReplacer = function (name, index, str) { return (precededByUniformRE.test(str.substr(0, index)) ? name : ("troika_" + name)); }; | ||
var varyingRefReplacer = function (name, index, str) { return (precededByUniformRE.test(str.substr(0, index)) ? name : ("troika_vary_" + name)); }; | ||
function createInstancedUniformsDerivedMaterial (baseMaterial, uniformNames) { | ||
var derived = createDerivedMaterial(baseMaterial, { | ||
defines: { | ||
TROIKA_INSTANCED_UNIFORMS: uniformNames.sort().join('|') | ||
}, | ||
customRewriter: function customRewriter (ref) { | ||
var vertexShader = ref.vertexShader; | ||
var fragmentShader = ref.fragmentShader; | ||
var vertexDeclarations = []; | ||
var vertexAssignments = []; | ||
var fragmentDeclarations = []; | ||
// Find what uniforms are declared in which shader and their types | ||
var vertexUniforms = getShaderUniformTypes(vertexShader); | ||
var fragmentUniforms = getShaderUniformTypes(fragmentShader); | ||
// Add attributes and varyings for, and rewrite references to, instanceUniforms | ||
uniformNames.forEach(function (name) { | ||
var vertType = vertexUniforms[name]; | ||
var fragType = fragmentUniforms[name]; | ||
if (vertType || fragType) { | ||
var finder = new RegExp(("\\b" + name + "\\b"), 'g'); | ||
vertexDeclarations.push(("attribute " + (vertType || fragType) + " troika_attr_" + name + ";")); | ||
if (vertType) { | ||
vertexShader = vertexShader.replace(finder, attrRefReplacer); | ||
} | ||
if (fragType) { | ||
fragmentShader = fragmentShader.replace(finder, varyingRefReplacer); | ||
var varyingDecl = "varying " + fragType + " troika_vary_" + name + ";"; | ||
vertexDeclarations.push(varyingDecl); | ||
fragmentDeclarations.push(varyingDecl); | ||
vertexAssignments.push(("troika_vary_" + name + " = troika_attr_" + name + ";")); | ||
} | ||
} | ||
}); | ||
// Inject vertex shader declarations and assignments | ||
vertexShader = (vertexDeclarations.join('\n')) + "\n" + (vertexShader.replace(voidMainRegExp, ("\n$&\n" + (vertexAssignments.join('\n'))))); | ||
// Inject fragment shader declarations | ||
if (fragmentDeclarations.length) { | ||
fragmentShader = (fragmentDeclarations.join('\n')) + "\n" + fragmentShader; | ||
} | ||
return { vertexShader: vertexShader, fragmentShader: fragmentShader } | ||
} | ||
}); | ||
derived.isInstancedUniformsMaterial = true; | ||
return derived | ||
} | ||
var defaultMaterial = new three.MeshBasicMaterial(); | ||
var InstancedUniformsMesh = /*@__PURE__*/(function (InstancedMesh) { | ||
function InstancedUniformsMesh (geometry, material, count) { | ||
InstancedMesh.call(this, geometry, material, count); | ||
this._instancedUniformNames = []; //treated as immutable | ||
} | ||
if ( InstancedMesh ) InstancedUniformsMesh.__proto__ = InstancedMesh; | ||
InstancedUniformsMesh.prototype = Object.create( InstancedMesh && InstancedMesh.prototype ); | ||
InstancedUniformsMesh.prototype.constructor = InstancedUniformsMesh; | ||
var prototypeAccessors = { geometry: { configurable: true },material: { configurable: true },customDepthMaterial: { configurable: true },customDistanceMaterial: { configurable: true } }; | ||
/* | ||
* Getter/setter for automatically wrapping the user-supplied geometry with one that will | ||
* carry our extra InstancedBufferAttribute(s) | ||
*/ | ||
prototypeAccessors.geometry.get = function () { | ||
return this._derivedGeometry | ||
}; | ||
prototypeAccessors.geometry.set = function (geometry) { | ||
// Extend the geometry so we can add our instancing attributes but inherit everything else | ||
if (geometry) { | ||
geometry = Object.create(geometry); | ||
geometry.attributes = Object.create(geometry.attributes); | ||
} | ||
this._derivedGeometry = geometry; | ||
}; | ||
/* | ||
* Getter/setter for automatically wrapping the user-supplied material with our upgrades. We do the | ||
* wrapping lazily on _read_ rather than write to avoid unnecessary wrapping on transient values. | ||
*/ | ||
prototypeAccessors.material.get = function () { | ||
var derivedMaterial = this._derivedMaterial; | ||
var baseMaterial = this._baseMaterial || this._defaultMaterial || (this._defaultMaterial = defaultMaterial.clone()); | ||
var uniformNames = this._instancedUniformNames; | ||
if (!derivedMaterial || derivedMaterial.baseMaterial !== baseMaterial || derivedMaterial._instancedUniformNames !== uniformNames) { | ||
derivedMaterial = this._derivedMaterial = createInstancedUniformsDerivedMaterial(baseMaterial, uniformNames); | ||
derivedMaterial._instancedUniformNames = uniformNames; | ||
// dispose the derived material when its base material is disposed: | ||
baseMaterial.addEventListener('dispose', function onDispose () { | ||
baseMaterial.removeEventListener('dispose', onDispose); | ||
derivedMaterial.dispose(); | ||
}); | ||
} | ||
return derivedMaterial | ||
}; | ||
prototypeAccessors.material.set = function (baseMaterial) { | ||
if (Array.isArray(baseMaterial)) { | ||
throw new Error('InstancedUniformsMesh does not support multiple materials') | ||
} | ||
// Unwrap already-derived materials | ||
while (baseMaterial && baseMaterial.isInstancedUniformsMaterial) { | ||
baseMaterial = baseMaterial.baseMaterial; | ||
} | ||
this._baseMaterial = baseMaterial; | ||
}; | ||
prototypeAccessors.customDepthMaterial.get = function () { | ||
return this.material.getDepthMaterial() | ||
}; | ||
prototypeAccessors.customDistanceMaterial.get = function () { | ||
return this.material.getDistanceMaterial() | ||
}; | ||
/** | ||
* Set the value of a shader uniform for a single instance. | ||
* @param {string} name - the name of the shader uniform | ||
* @param {number} index - the index of the instance to set the value for | ||
* @param {number|Vector2|Vector3|Vector4|Color|Array} value - the uniform value for this instance | ||
*/ | ||
InstancedUniformsMesh.prototype.setUniformAt = function setUniformAt (name, index, value) { | ||
var attrs = this.geometry.attributes; | ||
var attrName = "troika_attr_" + name; | ||
var attr = attrs[attrName]; | ||
if (!attr) { | ||
var defaultValue = getDefaultUniformValue(this._baseMaterial, name); | ||
var itemSize = getItemSizeForValue(defaultValue); | ||
attr = attrs[attrName] = new three.InstancedBufferAttribute(new Float32Array(itemSize * this.count), itemSize); | ||
// Fill with default value: | ||
if (defaultValue !== null) { | ||
for (var i = 0; i < this.count; i++) { | ||
setAttributeValue(attr, i, defaultValue); | ||
} | ||
} | ||
this._instancedUniformNames = ( this._instancedUniformNames ).concat( [name]); | ||
} | ||
setAttributeValue(attr, index, value); | ||
attr.needsUpdate = true; | ||
}; | ||
Object.defineProperties( InstancedUniformsMesh.prototype, prototypeAccessors ); | ||
return InstancedUniformsMesh; | ||
}(three.InstancedMesh)); | ||
function setAttributeValue (attr, index, value) { | ||
var size = attr.itemSize; | ||
if (size === 1) { | ||
attr.setX(index, value); | ||
} else if (size === 2) { | ||
attr.setXY(index, value.x, value.y); | ||
} else if (size === 3) { | ||
if (value.isColor) { | ||
attr.setXYZ(index, value.r, value.g, value.b); | ||
} else { | ||
attr.setXYZ(index, value.x, value.y, value.z); | ||
} | ||
} else if (size === 4) { | ||
attr.setXYZW(index, value.x, value.y, value.z, value.w); | ||
} | ||
} | ||
function getDefaultUniformValue (material, name) { | ||
// Try uniforms on the material itself, then try the builtin material shaders | ||
var uniforms = material.uniforms; | ||
if (uniforms && uniforms[name]) { | ||
return uniforms[name].value | ||
} | ||
uniforms = getShadersForMaterial(material).uniforms; | ||
if (uniforms && uniforms[name]) { | ||
return uniforms[name].value | ||
} | ||
return null | ||
} | ||
function getItemSizeForValue (value) { | ||
return value == null ? 0 | ||
: typeof value === 'number' ? 1 | ||
: value.isVector2 ? 2 | ||
: value.isVector3 || value.isColor ? 3 | ||
: value.isVector4 ? 4 | ||
: Array.isArray(value) ? value.length | ||
: 0 | ||
} | ||
/* | ||
@@ -826,3 +627,2 @@ Input geometry is a cylinder with r=1, height in y dimension from 0 to 1, | ||
exports.BezierMesh = BezierMesh; | ||
exports.InstancedUniformsMesh = InstancedUniformsMesh; | ||
exports.createDerivedMaterial = createDerivedMaterial; | ||
@@ -829,0 +629,0 @@ exports.expandShaderIncludes = expandShaderIncludes; |
@@ -1,22 +0,16 @@ | ||
'use strict';(function(h,f){"object"===typeof exports&&"undefined"!==typeof module?f(exports,require("three")):"function"===typeof define&&define.amd?define(["exports","three"],f):(h=h||self,f(h.troika_three_utils={},h.THREE))})(this,function(h,f){function r(b){return b.replace(/^[ \t]*#include +<([\w\d./]+)>/gm,function(b,d){return(d=f.ShaderChunk[d])?r(d):b})}function q(b,c){var d=G(c),a=x.get(b);a||x.set(b,a=Object.create(null));if(a[d])return new a[d];var e="_onBeforeCompile"+d,t=function(a){b.onBeforeCompile.call(this, | ||
a);var m=d+"|||"+a.vertexShader+"|||"+a.fragmentShader,g=y[m];g||(g=H(a,c,d),g=y[m]=g);a.vertexShader=g.vertexShader;a.fragmentShader=g.fragmentShader;l(a.uniforms,this.uniforms);c.timeUniform&&(a.uniforms[c.timeUniform]={get value(){return Date.now()-I}});if(this[e])this[e](a)},k=function(){return n(c.chained?b:b.clone())},n=function(a){var e=Object.create(a,g);Object.defineProperty(e,"baseMaterial",{value:b});Object.defineProperty(e,"id",{value:J++});e.uuid=f.MathUtils.generateUUID();e.uniforms= | ||
l({},a.uniforms,c.uniforms);e.defines=l({},a.defines,c.defines);e.defines["TROIKA_DERIVED_MATERIAL_"+d]="";e.extensions=l({},a.extensions,c.extensions);e._listeners=void 0;return e},g={constructor:{value:k},isDerivedMaterial:{value:!0},customProgramCacheKey:{value:function(){return d}},onBeforeCompile:{get:function(){return t},set:function(a){this[e]=a}},copy:{writable:!0,configurable:!0,value:function(a){b.copy.call(this,a);b.isShaderMaterial||b.isDerivedMaterial||(l(this.extensions,a.extensions), | ||
l(this.defines,a.defines),l(this.uniforms,f.UniformsUtils.clone(a.uniforms)));return this}},clone:{writable:!0,configurable:!0,value:function(){var a=new b.constructor;return n(a).copy(this)}},getDepthMaterial:{writable:!0,configurable:!0,value:function(){var a=this._depthMaterial;a||(a=this._depthMaterial=q(b.isDerivedMaterial?b.getDepthMaterial():new f.MeshDepthMaterial({depthPacking:f.RGBADepthPacking}),c),a.defines.IS_DEPTH_MATERIAL="",a.uniforms=this.uniforms);return a}},getDistanceMaterial:{writable:!0, | ||
configurable:!0,value:function(){var a=this._distanceMaterial;a||(a=this._distanceMaterial=q(b.isDerivedMaterial?b.getDistanceMaterial():new f.MeshDistanceMaterial,c),a.defines.IS_DISTANCE_MATERIAL="",a.uniforms=this.uniforms);return a}},dispose:{writable:!0,configurable:!0,value:function(){var a=this._depthMaterial,c=this._distanceMaterial;a&&a.dispose();c&&c.dispose();b.dispose.call(this)}}};a[d]=k;return new k}function H(b,c,d){var a=b.vertexShader,e=b.fragmentShader;b=c.vertexDefs;var f=c.vertexMainIntro, | ||
k=c.vertexMainOutro,n=c.vertexTransform,g=c.fragmentDefs,m=c.fragmentMainIntro,h=c.fragmentMainOutro,p=c.fragmentColorTransform,u=c.customRewriter;c=c.timeUniform;b=b||"";f=f||"";k=k||"";g=g||"";m=m||"";h=h||"";if(n||u)a=r(a);if(p||u)e=e.replace(/^[ \t]*#include <((?:tonemapping|encodings|fog|premultiplied_alpha|dithering)_fragment)>/gm,"\n//!BEGIN_POST_CHUNK $1\n$&\n//!END_POST_CHUNK\n"),e=r(e);u&&(e=u({vertexShader:a,fragmentShader:e}),a=e.vertexShader,e=e.fragmentShader);if(p){var l=[];e=e.replace(/^\/\/!BEGIN_POST_CHUNK[^]+?^\/\/!END_POST_CHUNK/gm, | ||
function(a){l.push(a);return""});h=p+"\n"+l.join("\n")+"\n"+h}c&&(p="\nuniform float "+c+";\n",b=p+b,g=p+g);n&&(b=b+"\nvec3 troika_position_"+d+";\nvec3 troika_normal_"+d+";\nvec2 troika_uv_"+d+";\nvoid troikaVertexTransform"+d+"(inout vec3 position, inout vec3 normal, inout vec2 uv) {\n "+n+"\n}\n",f="\ntroika_position_"+d+" = vec3(position);\ntroika_normal_"+d+" = vec3(normal);\ntroika_uv_"+d+" = vec2(uv);\ntroikaVertexTransform"+d+"(troika_position_"+d+", troika_normal_"+d+", troika_uv_"+d+");\n"+ | ||
f+"\n",a=a.replace(/\b(position|normal|uv)\b/g,function(a,b,c,e){return/\battribute\s+vec[23]\s+$/.test(e.substr(0,c))?b:"troika_"+b+"_"+d}));a=z(a,d,b,f,k);e=z(e,d,g,m,h);return{vertexShader:a,fragmentShader:e}}function z(b,c,d,a,e){if(a||e||d)b=b.replace(v,"\n"+d+"\nvoid troikaOrigMain"+c+"() {"),b+="\nvoid main() {\n "+a+"\n troikaOrigMain"+c+"();\n "+e+"\n}";return b}function K(b,c){return"uniforms"===b?void 0:"function"===typeof c?c.toString():c}function G(b){b=JSON.stringify(b,K);var c=A.get(b); | ||
null==c&&A.set(b,c=++L);return c}function B(b){var c=M[b.type];return c?f.ShaderLib[c]:b}function w(b){for(var c=/\buniform\s+(int|float|vec[234])\s+([A-Za-z_][\w]*)/g,d=Object.create(null),a;null!==(a=c.exec(b));)d[a[2]]=a[1];return d}function N(b,c){b=q(b,{defines:{TROIKA_INSTANCED_UNIFORMS:c.sort().join("|")},customRewriter:function(b){var a=b.vertexShader,d=b.fragmentShader,f=[],k=[],h=[],g=w(a),m=w(d);c.forEach(function(b){var c=g[b],e=m[b];if(c||e){var t=new RegExp("\\b"+b+"\\b","g");f.push("attribute "+ | ||
(c||e)+" troika_attr_"+b+";");c&&(a=a.replace(t,O));e&&(d=d.replace(t,P),c="varying "+e+" troika_vary_"+b+";",f.push(c),h.push(c),k.push("troika_vary_"+b+" = troika_attr_"+b+";"))}});a=f.join("\n")+"\n"+a.replace(v,"\n$&\n"+k.join("\n"));h.length&&(d=h.join("\n")+"\n"+d);return{vertexShader:a,fragmentShader:d}}});b.isInstancedUniformsMaterial=!0;return b}function C(b,c,d){var a=b.itemSize;1===a?b.setX(c,d):2===a?b.setXY(c,d.x,d.y):3===a?d.isColor?b.setXYZ(c,d.r,d.g,d.b):b.setXYZ(c,d.x,d.y,d.z):4=== | ||
a&&b.setXYZW(c,d.x,d.y,d.z,d.w)}var v=/\bvoid\s+main\s*\(\s*\)\s*{/g,l=Object.assign||function(){for(var b=arguments,c=arguments[0],d=1,a=arguments.length;d<a;d++){var e=b[d];if(e)for(var f in e)e.hasOwnProperty(f)&&(c[f]=e[f])}return c},I=Date.now(),x=new WeakMap,y=new Map,J=1E10,L=0,A=new Map,M={MeshDepthMaterial:"depth",MeshDistanceMaterial:"distanceRGBA",MeshNormalMaterial:"normal",MeshBasicMaterial:"basic",MeshLambertMaterial:"lambert",MeshPhongMaterial:"phong",MeshToonMaterial:"toon",MeshStandardMaterial:"physical", | ||
MeshPhysicalMaterial:"physical",MeshMatcapMaterial:"matcap",LineBasicMaterial:"basic",LineDashedMaterial:"dashed",PointsMaterial:"points",ShadowMaterial:"shadow",SpriteMaterial:"sprite"},D=/\buniform\s+(int|float|vec[234])\s+$/,O=function(b,c,d){return D.test(d.substr(0,c))?b:"troika_"+b},P=function(b,c,d){return D.test(d.substr(0,c))?b:"troika_vary_"+b},Q=new f.MeshBasicMaterial,R=function(b){function c(a,c,d){b.call(this,a,c,d);this._instancedUniformNames=[]}b&&(c.__proto__=b);c.prototype=Object.create(b&& | ||
b.prototype);c.prototype.constructor=c;var d={geometry:{configurable:!0},material:{configurable:!0},customDepthMaterial:{configurable:!0},customDistanceMaterial:{configurable:!0}};d.geometry.get=function(){return this._derivedGeometry};d.geometry.set=function(a){a&&(a=Object.create(a),a.attributes=Object.create(a.attributes));this._derivedGeometry=a};d.material.get=function(){var a=this._derivedMaterial,b=this._baseMaterial||this._defaultMaterial||(this._defaultMaterial=Q.clone()),c=this._instancedUniformNames; | ||
a&&a.baseMaterial===b&&a._instancedUniformNames===c||(a=this._derivedMaterial=N(b,c),a._instancedUniformNames=c,b.addEventListener("dispose",function n(){b.removeEventListener("dispose",n);a.dispose()}));return a};d.material.set=function(a){if(Array.isArray(a))throw Error("InstancedUniformsMesh does not support multiple materials");for(;a&&a.isInstancedUniformsMaterial;)a=a.baseMaterial;this._baseMaterial=a};d.customDepthMaterial.get=function(){return this.material.getDepthMaterial()};d.customDistanceMaterial.get= | ||
function(){return this.material.getDistanceMaterial()};c.prototype.setUniformAt=function(a,b,c){var d=this.geometry.attributes,e="troika_attr_"+a,g=d[e];if(!g){var h=this._baseMaterial;h=(g=h.uniforms)&&g[a]?g[a].value:(g=B(h).uniforms)&&g[a]?g[a].value:null;g=h;g=null==g?0:"number"===typeof g?1:g.isVector2?2:g.isVector3||g.isColor?3:g.isVector4?4:Array.isArray(g)?g.length:0;g=d[e]=new f.InstancedBufferAttribute(new Float32Array(g*this.count),g);if(null!==h)for(d=0;d<this.count;d++)C(g,d,h);this._instancedUniformNames= | ||
this._instancedUniformNames.concat([a])}C(g,b,c);g.needsUpdate=!0};Object.defineProperties(c.prototype,d);return c}(f.InstancedMesh),E=null,F=new f.MeshStandardMaterial({color:16777215,side:f.DoubleSide}),S=function(b){function c(){b.call(this,c.getGeometry(),F);this.pointA=new f.Vector3;this.controlA=new f.Vector3;this.controlB=new f.Vector3;this.pointB=new f.Vector3;this.radius=.01;this.dashArray=new f.Vector2;this.dashOffset=0;this.frustumCulled=!1}b&&(c.__proto__=b);c.prototype=Object.create(b&& | ||
b.prototype);c.prototype.constructor=c;var d={material:{configurable:!0},customDepthMaterial:{configurable:!0},customDistanceMaterial:{configurable:!0}};c.getGeometry=function(){return E||(E=(new f.CylinderBufferGeometry(1,1,1,6,64)).translate(0,.5,0))};d.material.get=function(){var a=this._derivedMaterial,b=this._baseMaterial||this._defaultMaterial||(this._defaultMaterial=F.clone());a&&a.baseMaterial===b||(a=this._derivedMaterial=q(b,{chained:!0,uniforms:{pointA:{value:new f.Vector3},controlA:{value:new f.Vector3}, | ||
controlB:{value:new f.Vector3},pointB:{value:new f.Vector3},radius:{value:.01},dashing:{value:new f.Vector3}},vertexDefs:"\nuniform vec3 pointA;\nuniform vec3 controlA;\nuniform vec3 controlB;\nuniform vec3 pointB;\nuniform float radius;\nvarying float bezierT;\n\nvec3 cubicBezier(vec3 p1, vec3 c1, vec3 c2, vec3 p2, float t) {\n float t2 = 1.0 - t;\n float b0 = t2 * t2 * t2;\n float b1 = 3.0 * t * t2 * t2;\n float b2 = 3.0 * t * t * t2;\n float b3 = t * t * t;\n return b0 * p1 + b1 * c1 + b2 * c2 + b3 * p2;\n}\n\nvec3 cubicBezierDerivative(vec3 p1, vec3 c1, vec3 c2, vec3 p2, float t) {\n float t2 = 1.0 - t;\n return -3.0 * p1 * t2 * t2 +\n c1 * (3.0 * t2 * t2 - 6.0 * t2 * t) +\n c2 * (6.0 * t2 * t - 3.0 * t * t) +\n 3.0 * p2 * t * t;\n}\n", | ||
'use strict';(function(f,c){"object"===typeof exports&&"undefined"!==typeof module?c(exports,require("three")):"function"===typeof define&&define.amd?define(["exports","three"],c):(f=f||self,c(f.troika_three_utils={},f.THREE))})(this,function(f,c){function r(b){return b.replace(/^[ \t]*#include +<([\w\d./]+)>/gm,function(a,b){return(b=c.ShaderChunk[b])?r(b):a})}function l(b,a){var e=z(a),d=q.get(b);d||q.set(b,d=Object.create(null));if(d[e])return new d[e];var g="_onBeforeCompile"+e,C=function(h){b.onBeforeCompile.call(this, | ||
h);var d=e+"|||"+h.vertexShader+"|||"+h.fragmentShader,c=t[d];c||(c=A(h,a,e),c=t[d]=c);h.vertexShader=c.vertexShader;h.fragmentShader=c.fragmentShader;k(h.uniforms,this.uniforms);a.timeUniform&&(h.uniforms[a.timeUniform]={get value(){return Date.now()-B}});if(this[g])this[g](h)},f=function(){return p(a.chained?b:b.clone())},p=function(d){var h=Object.create(d,m);Object.defineProperty(h,"baseMaterial",{value:b});Object.defineProperty(h,"id",{value:E++});h.uuid=c.MathUtils.generateUUID();h.uniforms= | ||
k({},d.uniforms,a.uniforms);h.defines=k({},d.defines,a.defines);h.defines["TROIKA_DERIVED_MATERIAL_"+e]="";h.extensions=k({},d.extensions,a.extensions);h._listeners=void 0;return h},m={constructor:{value:f},isDerivedMaterial:{value:!0},customProgramCacheKey:{value:function(){return e}},onBeforeCompile:{get:function(){return C},set:function(b){this[g]=b}},copy:{writable:!0,configurable:!0,value:function(a){b.copy.call(this,a);b.isShaderMaterial||b.isDerivedMaterial||(k(this.extensions,a.extensions), | ||
k(this.defines,a.defines),k(this.uniforms,c.UniformsUtils.clone(a.uniforms)));return this}},clone:{writable:!0,configurable:!0,value:function(){var a=new b.constructor;return p(a).copy(this)}},getDepthMaterial:{writable:!0,configurable:!0,value:function(){var d=this._depthMaterial;d||(d=this._depthMaterial=l(b.isDerivedMaterial?b.getDepthMaterial():new c.MeshDepthMaterial({depthPacking:c.RGBADepthPacking}),a),d.defines.IS_DEPTH_MATERIAL="",d.uniforms=this.uniforms);return d}},getDistanceMaterial:{writable:!0, | ||
configurable:!0,value:function(){var d=this._distanceMaterial;d||(d=this._distanceMaterial=l(b.isDerivedMaterial?b.getDistanceMaterial():new c.MeshDistanceMaterial,a),d.defines.IS_DISTANCE_MATERIAL="",d.uniforms=this.uniforms);return d}},dispose:{writable:!0,configurable:!0,value:function(){var a=this._depthMaterial,d=this._distanceMaterial;a&&a.dispose();d&&d.dispose();b.dispose.call(this)}}};d[e]=f;return new f}function A(b,a,e){var d=b.vertexShader,g=b.fragmentShader;b=a.vertexDefs;var c=a.vertexMainIntro, | ||
f=a.vertexMainOutro,p=a.vertexTransform,m=a.fragmentDefs,h=a.fragmentMainIntro,k=a.fragmentMainOutro,n=a.fragmentColorTransform,l=a.customRewriter;a=a.timeUniform;b=b||"";c=c||"";f=f||"";m=m||"";h=h||"";k=k||"";if(p||l)d=r(d);if(n||l)g=g.replace(/^[ \t]*#include <((?:tonemapping|encodings|fog|premultiplied_alpha|dithering)_fragment)>/gm,"\n//!BEGIN_POST_CHUNK $1\n$&\n//!END_POST_CHUNK\n"),g=r(g);l&&(g=l({vertexShader:d,fragmentShader:g}),d=g.vertexShader,g=g.fragmentShader);if(n){var q=[];g=g.replace(/^\/\/!BEGIN_POST_CHUNK[^]+?^\/\/!END_POST_CHUNK/gm, | ||
function(a){q.push(a);return""});k=n+"\n"+q.join("\n")+"\n"+k}a&&(n="\nuniform float "+a+";\n",b=n+b,m=n+m);p&&(b=b+"\nvec3 troika_position_"+e+";\nvec3 troika_normal_"+e+";\nvec2 troika_uv_"+e+";\nvoid troikaVertexTransform"+e+"(inout vec3 position, inout vec3 normal, inout vec2 uv) {\n "+p+"\n}\n",c="\ntroika_position_"+e+" = vec3(position);\ntroika_normal_"+e+" = vec3(normal);\ntroika_uv_"+e+" = vec2(uv);\ntroikaVertexTransform"+e+"(troika_position_"+e+", troika_normal_"+e+", troika_uv_"+e+");\n"+ | ||
c+"\n",d=d.replace(/\b(position|normal|uv)\b/g,function(a,d,b,c){return/\battribute\s+vec[23]\s+$/.test(c.substr(0,b))?d:"troika_"+d+"_"+e}));d=u(d,e,b,c,f);g=u(g,e,m,h,k);return{vertexShader:d,fragmentShader:g}}function u(b,a,c,d,g){if(d||g||c)b=b.replace(v,"\n"+c+"\nvoid troikaOrigMain"+a+"() {"),b+="\nvoid main() {\n "+d+"\n troikaOrigMain"+a+"();\n "+g+"\n}";return b}function F(b,a){return"uniforms"===b?void 0:"function"===typeof a?a.toString():a}function z(b){b=JSON.stringify(b,F);var a=w.get(b); | ||
null==a&&w.set(b,a=++G);return a}var v=/\bvoid\s+main\s*\(\s*\)\s*{/g,k=Object.assign||function(){for(var b=arguments,a=arguments[0],c=1,d=arguments.length;c<d;c++){var g=b[c];if(g)for(var f in g)g.hasOwnProperty(f)&&(a[f]=g[f])}return a},B=Date.now(),q=new WeakMap,t=new Map,E=1E10,G=0,w=new Map,H={MeshDepthMaterial:"depth",MeshDistanceMaterial:"distanceRGBA",MeshNormalMaterial:"normal",MeshBasicMaterial:"basic",MeshLambertMaterial:"lambert",MeshPhongMaterial:"phong",MeshToonMaterial:"toon",MeshStandardMaterial:"physical", | ||
MeshPhysicalMaterial:"physical",MeshMatcapMaterial:"matcap",LineBasicMaterial:"basic",LineDashedMaterial:"dashed",PointsMaterial:"points",ShadowMaterial:"shadow",SpriteMaterial:"sprite"},x=null,y=new c.MeshStandardMaterial({color:16777215,side:c.DoubleSide}),I=function(b){function a(){b.call(this,a.getGeometry(),y);this.pointA=new c.Vector3;this.controlA=new c.Vector3;this.controlB=new c.Vector3;this.pointB=new c.Vector3;this.radius=.01;this.dashArray=new c.Vector2;this.dashOffset=0;this.frustumCulled= | ||
!1}b&&(a.__proto__=b);a.prototype=Object.create(b&&b.prototype);a.prototype.constructor=a;var e={material:{configurable:!0},customDepthMaterial:{configurable:!0},customDistanceMaterial:{configurable:!0}};a.getGeometry=function(){return x||(x=(new c.CylinderBufferGeometry(1,1,1,6,64)).translate(0,.5,0))};e.material.get=function(){var a=this._derivedMaterial,b=this._baseMaterial||this._defaultMaterial||(this._defaultMaterial=y.clone());a&&a.baseMaterial===b||(a=this._derivedMaterial=l(b,{chained:!0, | ||
uniforms:{pointA:{value:new c.Vector3},controlA:{value:new c.Vector3},controlB:{value:new c.Vector3},pointB:{value:new c.Vector3},radius:{value:.01},dashing:{value:new c.Vector3}},vertexDefs:"\nuniform vec3 pointA;\nuniform vec3 controlA;\nuniform vec3 controlB;\nuniform vec3 pointB;\nuniform float radius;\nvarying float bezierT;\n\nvec3 cubicBezier(vec3 p1, vec3 c1, vec3 c2, vec3 p2, float t) {\n float t2 = 1.0 - t;\n float b0 = t2 * t2 * t2;\n float b1 = 3.0 * t * t2 * t2;\n float b2 = 3.0 * t * t * t2;\n float b3 = t * t * t;\n return b0 * p1 + b1 * c1 + b2 * c2 + b3 * p2;\n}\n\nvec3 cubicBezierDerivative(vec3 p1, vec3 c1, vec3 c2, vec3 p2, float t) {\n float t2 = 1.0 - t;\n return -3.0 * p1 * t2 * t2 +\n c1 * (3.0 * t2 * t2 - 6.0 * t2 * t) +\n c2 * (6.0 * t2 * t - 3.0 * t * t) +\n 3.0 * p2 * t * t;\n}\n", | ||
vertexTransform:'\nfloat t = position.y;\nbezierT = t;\nvec3 bezierCenterPos = cubicBezier(pointA, controlA, controlB, pointB, t);\nvec3 bezierDir = normalize(cubicBezierDerivative(pointA, controlA, controlB, pointB, t));\n\n// Make "sideways" always perpendicular to the camera ray; this ensures that any twists\n// in the cylinder occur where you won\'t see them: \nvec3 viewDirection = normalMatrix * vec3(0.0, 0.0, 1.0);\nif (bezierDir == viewDirection) {\n bezierDir = normalize(cubicBezierDerivative(pointA, controlA, controlB, pointB, t == 1.0 ? t - 0.0001 : t + 0.0001));\n}\nvec3 sideways = normalize(cross(bezierDir, viewDirection));\nvec3 upish = normalize(cross(sideways, bezierDir));\n\n// Build a matrix for transforming this disc in the cylinder:\nmat4 discTx;\ndiscTx[0].xyz = sideways * radius;\ndiscTx[1].xyz = bezierDir * radius;\ndiscTx[2].xyz = upish * radius;\ndiscTx[3].xyz = bezierCenterPos;\ndiscTx[3][3] = 1.0;\n\n// Apply transform, ignoring original y\nposition = (discTx * vec4(position.x, 0.0, position.z, 1.0)).xyz;\nnormal = normalize(mat3(discTx) * normal);\n', | ||
fragmentDefs:"\nuniform vec3 dashing;\nvarying float bezierT;\n",fragmentMainIntro:"\nif (dashing.x + dashing.y > 0.0) {\n float dashFrac = mod(bezierT - dashing.z, dashing.x + dashing.y);\n if (dashFrac > dashing.x) {\n discard;\n }\n}\n"}),b.addEventListener("dispose",function k(){b.removeEventListener("dispose",k);a.dispose()}));return a};d.material.set=function(a){this._baseMaterial=a};d.customDepthMaterial.get=function(){return this.material.getDepthMaterial()};d.customDistanceMaterial.get= | ||
function(){return this.material.getDistanceMaterial()};c.prototype.onBeforeRender=function(a){a=this.material.uniforms;var b=this.controlA,c=this.controlB,d=this.pointB,f=this.radius,g=this.dashArray,h=this.dashOffset;a.pointA.value.copy(this.pointA);a.controlA.value.copy(b);a.controlB.value.copy(c);a.pointB.value.copy(d);a.radius.value=f;a.dashing.value.set(g.x,g.y,h||0)};c.prototype.raycast=function(a,b){};Object.defineProperties(c.prototype,d);return c}(f.Mesh);h.BezierMesh=S;h.InstancedUniformsMesh= | ||
R;h.createDerivedMaterial=q;h.expandShaderIncludes=r;h.getShaderUniformTypes=w;h.getShadersForMaterial=B;h.voidMainRegExp=v;Object.defineProperty(h,"__esModule",{value:!0})}) | ||
fragmentDefs:"\nuniform vec3 dashing;\nvarying float bezierT;\n",fragmentMainIntro:"\nif (dashing.x + dashing.y > 0.0) {\n float dashFrac = mod(bezierT - dashing.z, dashing.x + dashing.y);\n if (dashFrac > dashing.x) {\n discard;\n }\n}\n"}),b.addEventListener("dispose",function D(){b.removeEventListener("dispose",D);a.dispose()}));return a};e.material.set=function(a){this._baseMaterial=a};e.customDepthMaterial.get=function(){return this.material.getDepthMaterial()};e.customDistanceMaterial.get= | ||
function(){return this.material.getDistanceMaterial()};a.prototype.onBeforeRender=function(a){a=this.material.uniforms;var b=this.controlA,d=this.controlB,c=this.pointB,e=this.radius,f=this.dashArray,h=this.dashOffset;a.pointA.value.copy(this.pointA);a.controlA.value.copy(b);a.controlB.value.copy(d);a.pointB.value.copy(c);a.radius.value=e;a.dashing.value.set(f.x,f.y,h||0)};a.prototype.raycast=function(a,b){};Object.defineProperties(a.prototype,e);return a}(c.Mesh);f.BezierMesh=I;f.createDerivedMaterial= | ||
l;f.expandShaderIncludes=r;f.getShaderUniformTypes=function(b){for(var a=/\buniform\s+(int|float|vec[234])\s+([A-Za-z_][\w]*)/g,c=Object.create(null),d;null!==(d=a.exec(b));)c[d[2]]=d[1];return c};f.getShadersForMaterial=function(b){var a=H[b.type];return a?c.ShaderLib[a]:b};f.voidMainRegExp=v;Object.defineProperty(f,"__esModule",{value:!0})}) |
{ | ||
"name": "troika-three-utils", | ||
"version": "0.37.0", | ||
"version": "0.38.0", | ||
"description": "Various utilities related to Three.js", | ||
@@ -19,3 +19,3 @@ "author": "Jason Johnston <jason.johnston@protectwise.com>", | ||
}, | ||
"gitHead": "f2c9c725b22a88ca3275c39150d75f6894ea3503" | ||
"gitHead": "d48144bf99a2eaf2089c0cd2a8065506161dfdf4" | ||
} |
@@ -65,41 +65,7 @@ # Troika Three.js Utilities | ||
### InstancedUniformsMesh | ||
[Source code](./src/InstancedUniformsMesh.js) | ||
This extends Three.js's [`InstancedMesh`](https://threejs.org/docs/#api/en/objects/InstancedMesh) to allow any of its material's shader uniforms to be set individually per instance. It behaves just like `InstancedMesh` but exposes a new `setUniformAt(uniformName, instanceIndex, value)` method. | ||
When you call `setUniformAt`, the geometry and the material shaders will be automatically upgraded behind the scenes to turn that uniform into an instanced buffer attribute, filling in the other indices with the uniform's default value. You can do this for any uniform of type `float`, `vec2`, `vec3`, or `vec4`. It works both for built-in Three.js materials and also for any custom ShaderMaterial. | ||
For example, here is how you could set random `emissive` and `metalness` values for each instance using a `MeshStandardMaterial`: | ||
```js | ||
import { InstancedUniformsMesh } from 'troika-three-utils' | ||
const count = 100 | ||
const mesh = new InstancedUniformsMesh( | ||
someGeometry, | ||
new MeshStandardMaterial(), | ||
count | ||
) | ||
const color = new Color() | ||
for (let i = 0; i < count; i++) { | ||
mesh.setUniformAt('metalness', i, Math.random()) | ||
mesh.setUniformAt('emissive', i, color.set(Math.random() * 0xffffff)) | ||
} | ||
``` | ||
The type of the `value` argument should match the type of the uniform defined in the material's shader: | ||
| For uniform type: | Pass a value of this type: | | ||
| ----------------- | ----------------------------------------- | | ||
| float | Number | | ||
| vec2 | `Vector2` or Array w/ length=2 | | ||
| vec3 | `Vector3` or `Color` or Array w/ length=3 | | ||
| vec4 | `Vector4` or Array w/ length=4 | | ||
### BezierMesh | ||
_[Source code with JSDoc](./src/BezierMesh.js)_ | _[Online example](https://troika-examples.netlify.com/#bezier3d)_ | ||
_[Source code with JSDoc](./src/BezierMesh.js)_ | ||
_[Online example](https://troika-examples.netlify.com/#bezier3d)_ | ||
_[Online example using InstancedUniformsMesh](https://ibyou.csb.app/)_ | ||
@@ -120,1 +86,5 @@ This creates a cylindrical mesh and bends it along a 3D cubic bezier path between two points, in a custom derived vertex shader. This is useful for visually connecting objects in 3D space with a line that has thickness to it. | ||
### InstancedUniformsMesh | ||
> NOTE: InstancedUniformsMesh has been moved to [its own `three-instanced-uniforms-mesh` package](https://github.com/protectwise/troika/tree/master/packages/three-instanced-uniforms-mesh). |
@@ -0,0 +0,0 @@ import { CylinderBufferGeometry, DoubleSide, Mesh, MeshStandardMaterial, Vector2, Vector3 } from 'three' |
@@ -0,0 +0,0 @@ import { createDerivedMaterial } from './DerivedMaterial.js' |
@@ -0,0 +0,0 @@ import { voidMainRegExp } from './voidMainRegExp.js' |
@@ -0,0 +0,0 @@ import { ShaderChunk } from 'three' |
@@ -0,0 +0,0 @@ import { ShaderLib } from 'three' |
@@ -0,0 +0,0 @@ /** |
@@ -8,3 +8,2 @@ // Troika Three.js Utilities exports | ||
export { voidMainRegExp } from './voidMainRegExp.js' | ||
export { InstancedUniformsMesh } from './InstancedUniformsMesh.js' | ||
export { BezierMesh } from './BezierMesh.js' |
@@ -0,0 +0,0 @@ import { |
@@ -0,0 +0,0 @@ /** |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
112392
17
2148
89