From 72bc83b7e2e355d98cb40ac83e13587d45de0180 Mon Sep 17 00:00:00 2001 From: monjanse Date: Fri, 31 Jul 2026 13:46:06 +0000 Subject: [PATCH] Automated Extension submission for issue #2210 --- extensions/community/ParticleFur3D.json | 8723 +++++++++++++++++++++++ 1 file changed, 8723 insertions(+) create mode 100644 extensions/community/ParticleFur3D.json diff --git a/extensions/community/ParticleFur3D.json b/extensions/community/ParticleFur3D.json new file mode 100644 index 000000000..65a4591c2 --- /dev/null +++ b/extensions/community/ParticleFur3D.json @@ -0,0 +1,8723 @@ +{ + "author": "monjanse", + "category": "Visual effect", + "dimension": "3D", + "extensionNamespace": "", + "fullName": "Particle Fur 3D", + "gdevelopVersion": ">=5.5.222", + "helpPath": "", + "iconUrl": "data:image/png;base64,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", + "name": "ParticleFur3D", + "previewIconUrl": "data:image/png;base64,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", + "shortDescription": "GPU-skinned 3D fur with world-gravity-aligned tail resting hang, stable tail jump/fall inertia, an embedded GDevelop behavior icon, regional masks, texture colors, undercoat and long-coat motion.", + "version": "1.8.9", + "description": [ + "Version 1.8.9 corrects tail fur that rested diagonally when the tail pointed downward. Tail resting, jump and fall motion now use live world gravity rather than a diagonal surface-tangent projection.", + "The Particle Fur 3D logo is embedded directly into the extension and behavior icon fields, so it appears in GDevelop's behavior list." + ], + "origin": { + "identifier": "ParticleFur3D", + "name": "user-extension" + }, + "tags": [ + "3d", + "fur", + "hair", + "model", + "vertex group", + "gltf", + "glb", + "animation" + ], + "authorIds": [], + "dependencies": [], + "globalVariables": [], + "sceneVariables": [], + "eventsFunctions": [], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT" + }, + "eventsBasedBehaviors": [ + { + "description": "Generates GPU-skinned outer coat and undercoat with world-gravity-aligned tail resting hang, stable tail jump/fall inertia, model-verified regional masks, texture colors, rear-head coverage and surface protection.", + "fullName": "Particle Fur 3D", + "helpPath": "", + "iconUrl": "data:image/png;base64,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", + "name": "ParticleFur3D", + "objectType": "", + "previewIconUrl": "data:image/png;base64,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", + "eventsFunctions": [ + { + "fullName": "", + "functionType": "Action", + "name": "onCreated", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "(function installParticleFur3DManager() {", + " \"use strict\";", + " if (gdjs.__ParticleFur3D_v189) return;", + "", + " const M = {};", + " M.version = \"1.8.9\";", + "", + " const clamp = (v, a, b) => Math.max(a, Math.min(b, v));", + " const numberOr = (v, fallback) => Number.isFinite(Number(v)) ? Number(v) : fallback;", + "", + " function makeRandom(seed) {", + " let state = (seed >>> 0) || 0x6d2b79f5;", + " return function random() {", + " state += 0x6d2b79f5;", + " let t = state;", + " t = Math.imul(t ^ (t >>> 15), t | 1);", + " t ^= t + Math.imul(t ^ (t >>> 7), t | 61);", + " return ((t ^ (t >>> 14)) >>> 0) / 4294967296;", + " };", + " }", + "", + " function component(attribute, index, componentIndex) {", + " if (!attribute) return 0;", + " if (componentIndex === 0) return attribute.getX(index);", + " if (componentIndex === 1) return attribute.getY(index);", + " if (componentIndex === 2) return attribute.getZ(index);", + " if (componentIndex === 3) return attribute.getW(index);", + " return 0;", + " }", + "", + " function getState(behavior) {", + " if (!behavior._particleFur3DState) {", + " behavior._particleFur3DState = {", + " groups: [],", + " built: false,", + " status: \"Waiting for the 3D model.\",", + " strandCount: 0,", + " rootCount: 0,", + " retryFrames: 0,", + " lastConfig: \"\",", + " accumulator: 0,", + " time: 0,", + " previousX: 0,", + " previousY: 0,", + " previousZ: 0,", + " filteredVerticalVelocity: 0,", + " tailVerticalResponse: 0,", + " tailResponseSign: 0,", + " hasPreviousPosition: false,", + " warnedKeys: new Set()", + " };", + " }", + " return behavior._particleFur3DState;", + " }", + "", + " function setStatus(object, behavior, message, strandCount) {", + " const state = getState(behavior);", + " state.status = String(message || \"\");", + " if (typeof strandCount === \"number\") state.strandCount = strandCount;", + "", + " try {", + " const variables = object.getVariables && object.getVariables();", + " if (variables && variables.get) {", + " const statusVar = variables.get(\"ParticleFurStatus\");", + " if (statusVar && statusVar.setString) statusVar.setString(state.status);", + " const countVar = variables.get(\"ParticleFurStrandCount\");", + " if (countVar && countVar.setNumber) countVar.setNumber(state.strandCount || 0);", + " const rootCountVar = variables.get(\"ParticleFurRootCount\");", + " if (rootCountVar && rootCountVar.setNumber) rootCountVar.setNumber(state.rootCount || 0);", + " }", + " } catch (error) {", + " // Object variables are only a convenience; never fail fur creation because of them.", + " }", + "", + " if (behavior._getDebugLog && behavior._getDebugLog()) {", + " console.info(\"[Particle Fur 3D] \" + state.status);", + " }", + " }", + "", + " function warnOnce(object, behavior, key, message) {", + " const state = getState(behavior);", + " if (state.warnedKeys.has(key)) return;", + " state.warnedKeys.add(key);", + " console.warn(\"[Particle Fur 3D] \" + message);", + " }", + "", + " function parseColor(text) {", + " const match = String(text || \"120;90;65\").match(/(-?\\d+(?:\\.\\d+)?)\\s*[;, ]\\s*(-?\\d+(?:\\.\\d+)?)\\s*[;, ]\\s*(-?\\d+(?:\\.\\d+)?)/);", + " if (!match) return { r: 120 / 255, g: 90 / 255, b: 65 / 255 };", + " return {", + " r: clamp(Number(match[1]) / 255, 0, 1),", + " g: clamp(Number(match[2]) / 255, 0, 1),", + " b: clamp(Number(match[3]) / 255, 0, 1)", + " };", + " }", + "", + " function srgbToLinear(value) {", + " const v = clamp(numberOr(value, 0), 0, 1);", + " return v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);", + " }", + "", + " function materialAt(mesh, materialIndex) {", + " const materials = Array.isArray(mesh && mesh.material) ? mesh.material : [mesh && mesh.material];", + " if (!materials.length) return null;", + " const safeIndex = Math.max(0, Math.min(materials.length - 1, Math.floor(numberOr(materialIndex, 0))));", + " return materials[safeIndex] || materials.find(Boolean) || null;", + " }", + "", + " function materialIndexForTriangle(geometry, triangleStart) {", + " const groups = geometry && Array.isArray(geometry.groups) ? geometry.groups : [];", + " for (const group of groups) {", + " const start = numberOr(group.start, 0);", + " const end = start + numberOr(group.count, 0);", + " if (triangleStart >= start && triangleStart < end) return Math.floor(numberOr(group.materialIndex, 0));", + " }", + " return 0;", + " }", + "", + " const textureSamplerCache = new Map();", + "", + " function textureImage(texture) {", + " if (!texture) return null;", + " if (texture.image) return texture.image;", + " if (texture.source && texture.source.data) return texture.source.data;", + " return null;", + " }", + "", + " function prepareTextureSampler(texture) {", + " if (!texture) return null;", + " const cacheKey = texture.uuid || (\"texture-\" + String(texture.id || \"unknown\"));", + " if (textureSamplerCache.has(cacheKey)) return textureSamplerCache.get(cacheKey);", + "", + " let sampler = null;", + " try {", + " const image = textureImage(texture);", + " const width = Math.floor(numberOr(image && (image.naturalWidth || image.videoWidth || image.width), 0));", + " const height = Math.floor(numberOr(image && (image.naturalHeight || image.videoHeight || image.height), 0));", + " if (!image || width <= 0 || height <= 0 || typeof document === \"undefined\") {", + " textureSamplerCache.set(cacheKey, null);", + " return null;", + " }", + " const canvas = document.createElement(\"canvas\");", + " canvas.width = width;", + " canvas.height = height;", + " const context = canvas.getContext(\"2d\", { willReadFrequently: true });", + " if (!context) {", + " textureSamplerCache.set(cacheKey, null);", + " return null;", + " }", + " context.clearRect(0, 0, width, height);", + " context.drawImage(image, 0, 0, width, height);", + " const pixels = context.getImageData(0, 0, width, height).data;", + " sampler = { width, height, pixels };", + " } catch (error) {", + " sampler = null;", + " }", + " textureSamplerCache.set(cacheKey, sampler);", + " return sampler;", + " }", + "", + " function wrapCoordinate(value, wrapping) {", + " if (!Number.isFinite(value)) return 0;", + " // Three.js constants: RepeatWrapping=1000, ClampToEdgeWrapping=1001, MirroredRepeatWrapping=1002.", + " if (wrapping === 1000) return value - Math.floor(value);", + " if (wrapping === 1002) {", + " const whole = Math.floor(value);", + " const fraction = value - whole;", + " return Math.abs(whole) % 2 === 1 ? 1 - fraction : fraction;", + " }", + " return clamp(value, 0, 1);", + " }", + "", + " function transformedUv(texture, u, v) {", + " if (texture && texture.matrixAutoUpdate && typeof texture.updateMatrix === \"function\") texture.updateMatrix();", + " const elements = texture && texture.matrix && texture.matrix.elements;", + " let transformedU = u;", + " let transformedV = v;", + " if (elements && elements.length >= 9) {", + " transformedU = elements[0] * u + elements[3] * v + elements[6];", + " transformedV = elements[1] * u + elements[4] * v + elements[7];", + " } else if (texture) {", + " const repeatX = texture.repeat ? numberOr(texture.repeat.x, 1) : 1;", + " const repeatY = texture.repeat ? numberOr(texture.repeat.y, 1) : 1;", + " const offsetX = texture.offset ? numberOr(texture.offset.x, 0) : 0;", + " const offsetY = texture.offset ? numberOr(texture.offset.y, 0) : 0;", + " transformedU = transformedU * repeatX + offsetX;", + " transformedV = transformedV * repeatY + offsetY;", + " }", + " transformedU = wrapCoordinate(transformedU, texture && texture.wrapS);", + " transformedV = wrapCoordinate(transformedV, texture && texture.wrapT);", + " // Do not flip here. Canvas pixel selection below handles texture.flipY exactly once.", + " return { u: transformedU, v: transformedV };", + " }", + "", + " function sampleTextureColor(texture, u, v) {", + " const sampler = prepareTextureSampler(texture);", + " if (!sampler) return null;", + " const uv = transformedUv(texture, u, v);", + " const x = Math.max(0, Math.min(sampler.width - 1, Math.round(uv.u * (sampler.width - 1))));", + " // Canvas rows start at the top. GLB/glTF textures normally use flipY=false,", + " // so v=0 must sample the top row. Non-glTF textures with flipY=true use 1-v.", + " const pixelV = texture && texture.flipY ? (1 - uv.v) : uv.v;", + " const y = Math.max(0, Math.min(sampler.height - 1, Math.round(pixelV * (sampler.height - 1))));", + " const offset = (y * sampler.width + x) * 4;", + " let r = sampler.pixels[offset] / 255;", + " let g = sampler.pixels[offset + 1] / 255;", + " let b = sampler.pixels[offset + 2] / 255;", + " const colorSpace = String(texture && texture.colorSpace || \"\").toLowerCase();", + " if (colorSpace.includes(\"srgb\")) {", + " r = srgbToLinear(r);", + " g = srgbToLinear(g);", + " b = srgbToLinear(b);", + " }", + " return { r, g, b, a: sampler.pixels[offset + 3] / 255 };", + " }", + "", + " function surfaceColor(mesh, materialIndex, ia, ib, ic, ba, bb, bc, options) {", + " const manual = parseColor(options.color);", + " const material = materialAt(mesh, materialIndex);", + " const materialColor = material && material.color ? {", + " r: clamp(numberOr(material.color.r, 1), 0, 1),", + " g: clamp(numberOr(material.color.g, 1), 0, 1),", + " b: clamp(numberOr(material.color.b, 1), 0, 1)", + " } : { r: 1, g: 1, b: 1 };", + "", + " let sampled = materialColor;", + " if (options.useModelTextureColor && material && material.map) {", + " const channel = Math.floor(numberOr(material.map.channel, 0));", + " const uvName = channel <= 0 ? \"uv\" : \"uv\" + channel;", + " const uv = mesh.geometry && mesh.geometry.getAttribute && mesh.geometry.getAttribute(uvName);", + " if (uv && uv.count > Math.max(ia, ib, ic)) {", + " const u = uv.getX(ia) * ba + uv.getX(ib) * bb + uv.getX(ic) * bc;", + " const v = uv.getY(ia) * ba + uv.getY(ib) * bb + uv.getY(ic) * bc;", + " const textureColor = sampleTextureColor(material.map, u, v);", + " if (textureColor) {", + " sampled = {", + " r: clamp(textureColor.r * materialColor.r, 0, 1),", + " g: clamp(textureColor.g * materialColor.g, 0, 1),", + " b: clamp(textureColor.b * materialColor.b, 0, 1)", + " };", + " }", + " }", + " }", + "", + " const strength = clamp(numberOr(options.modelTextureColorStrength, 1), 0, 1);", + " return {", + " r: manual.r * (1 - strength) + sampled.r * strength,", + " g: manual.g * (1 - strength) + sampled.g * strength,", + " b: manual.b * (1 - strength) + sampled.b * strength", + " };", + " }", + "", + " function allWeights(count, value) {", + " const weights = new Float32Array(count);", + " weights.fill(value);", + " return weights;", + " }", + "", + " function findAttributeCaseInsensitive(geometry, wanted) {", + " if (!geometry || !geometry.getAttribute) return null;", + " const direct = geometry.getAttribute(wanted);", + " if (direct) return direct;", + " const names = Object.keys(geometry.attributes || {});", + " const lower = String(wanted).toLowerCase();", + " const actual = names.find(name => String(name).toLowerCase() === lower);", + " return actual ? geometry.getAttribute(actual) : null;", + " }", + "", + " function groupAttributeCandidates(groupName) {", + " const raw = String(groupName || \"\").trim();", + " if (!raw) return [];", + "", + " const compact = raw.replace(", + " /[^A-Za-z0-9_]/g,", + " \"_\"", + " );", + " const base = raw", + " .replace(/^_VG_/i, \"\")", + " .replace(/^VG_/i, \"\")", + " .replace(/^_+/, \"\");", + " const compactBase = base.replace(", + " /[^A-Za-z0-9_]/g,", + " \"_\"", + " );", + "", + " // Only variants of the requested group are allowed.", + " // Never fall back from \"head\" or \"tail\" to a generic \"fur\" mask.", + " return Array.from(", + " new Set(", + " [", + " raw,", + " compact,", + " base,", + " compactBase,", + " \"_\" + base,", + " \"_\" + compactBase,", + " \"_VG_\" + base,", + " \"_VG_\" + compactBase,", + " \"VG_\" + base,", + " \"VG_\" + compactBase", + " ].filter(Boolean)", + " )", + " );", + " }", + "", + " function weightsFromCustomAttribute(", + " geometry,", + " groupName,", + " vertexCount", + " ) {", + " const candidates =", + " groupAttributeCandidates(groupName);", + " if (!candidates.length) return null;", + "", + " for (const name of candidates) {", + " const attribute =", + " findAttributeCaseInsensitive(", + " geometry,", + " name", + " );", + " if (", + " !attribute ||", + " attribute.count < vertexCount", + " ) {", + " continue;", + " }", + "", + " const result =", + " new Float32Array(vertexCount);", + " for (", + " let vertex = 0;", + " vertex < vertexCount;", + " vertex++", + " ) {", + " result[vertex] = clamp(", + " numberOr(", + " attribute.getX(vertex),", + " 0", + " ),", + " 0,", + " 1", + " );", + " }", + " return {", + " weights: result,", + " source: \"attribute \" + name,", + " resolvedName: name", + " };", + " }", + " return null;", + " }", + "", + " function weightsFromUserData(geometry, groupName, vertexCount) {", + " const containers = [", + " geometry.userData && geometry.userData.vertexGroups,", + " geometry.userData && geometry.userData.gdevelopFurVertexGroups,", + " geometry.userData && geometry.userData.furVertexGroups", + " ];", + " for (const container of containers) {", + " if (!container || !Object.prototype.hasOwnProperty.call(container, groupName)) continue;", + " let source = container[groupName];", + " if (source && source.weights) source = source.weights;", + " const result = new Float32Array(vertexCount);", + " if (Array.isArray(source) || ArrayBuffer.isView(source)) {", + " for (let i = 0; i < vertexCount; i++) result[i] = clamp(numberOr(source[i], 0), 0, 1);", + " return {", + " weights: result,", + " source: \"geometry userData\",", + " resolvedName: groupName", + " };", + " }", + " if (source && typeof source === \"object\") {", + " for (const key of Object.keys(source)) {", + " const index = Number(key);", + " if (Number.isInteger(index) && index >= 0 && index < vertexCount) {", + " result[index] = clamp(numberOr(source[key], 0), 0, 1);", + " }", + " }", + " return {", + " weights: result,", + " source: \"geometry userData\",", + " resolvedName: groupName", + " };", + " }", + " }", + " return null;", + " }", + "", + " function weightsFromBone(mesh, groupName, vertexCount) {", + " if (!mesh.isSkinnedMesh || !mesh.skeleton) return null;", + " const wanted = String(groupName || \"\").toLowerCase();", + " let boneIndex = mesh.skeleton.bones.findIndex(bone => bone && String(bone.name).toLowerCase() === wanted);", + " if (boneIndex < 0) return null;", + "", + " const skinIndex = mesh.geometry.getAttribute(\"skinIndex\");", + " const skinWeight = mesh.geometry.getAttribute(\"skinWeight\");", + " if (!skinIndex || !skinWeight) return null;", + "", + " const result = new Float32Array(vertexCount);", + " const itemSize = Math.min(4, skinIndex.itemSize || 4, skinWeight.itemSize || 4);", + " for (let vertex = 0; vertex < vertexCount; vertex++) {", + " let value = 0;", + " for (let channel = 0; channel < itemSize; channel++) {", + " if (Math.round(component(skinIndex, vertex, channel)) === boneIndex) {", + " value += component(skinWeight, vertex, channel);", + " }", + " }", + " result[vertex] = clamp(value, 0, 1);", + " }", + " return {", + " weights: result,", + " source:", + " \"bone \" +", + " mesh.skeleton.bones[boneIndex].name,", + " resolvedName:", + " mesh.skeleton.bones[boneIndex].name", + " };", + " }", + "", + " function parseVertexGroupNames(value) {", + " return Array.from(", + " new Set(", + " String(value || \"\")", + " .split(/[,;|]+/)", + " .map(name => name.trim())", + " .filter(Boolean)", + " )", + " );", + " }", + "", + " function resolveSingleGroupWeights(mesh, groupName, vertexCount) {", + " return (", + " weightsFromCustomAttribute(mesh.geometry, groupName, vertexCount) ||", + " weightsFromUserData(mesh.geometry, groupName, vertexCount) ||", + " weightsFromBone(mesh, groupName, vertexCount)", + " );", + " }", + "", + " function resolveWeights(mesh, options) {", + " const position =", + " mesh.geometry &&", + " mesh.geometry.getAttribute &&", + " mesh.geometry.getAttribute(\"position\");", + " if (!position) return null;", + "", + " const vertexCount = position.count;", + " const groupNames = parseVertexGroupNames(options.vertexGroupName);", + " if (!groupNames.length) {", + " return {", + " weights: allWeights(vertexCount, 1),", + " source: \"whole mesh\",", + " foundGroups: [],", + " missingGroups: []", + " };", + " }", + "", + " const combined = new Float32Array(vertexCount);", + " const foundGroups = [];", + " const missingGroups = [];", + " const sources = [];", + "", + " for (const groupName of groupNames) {", + " const resolved = resolveSingleGroupWeights(mesh, groupName, vertexCount);", + " if (!resolved) {", + " missingGroups.push(groupName);", + " continue;", + " }", + " foundGroups.push(groupName);", + " sources.push(resolved.source);", + " for (let vertex = 0; vertex < vertexCount; vertex++) {", + " combined[vertex] = Math.max(combined[vertex], resolved.weights[vertex] || 0);", + " }", + " }", + "", + " if (!foundGroups.length) {", + " if (!options.useWholeMeshIfGroupMissing) return null;", + " return {", + " weights: allWeights(vertexCount, 1),", + " source: \"whole mesh fallback\",", + " foundGroups: [],", + " missingGroups", + " };", + " }", + "", + " if (options.invertVertexGroup) {", + " for (let vertex = 0; vertex < combined.length; vertex++) {", + " combined[vertex] = 1 - combined[vertex];", + " }", + " }", + "", + " return {", + " weights: combined,", + " source:", + " \"vertex groups: \" +", + " foundGroups.join(\", \") +", + " (options.invertVertexGroup ? \" (inverted)\" : \"\"),", + " foundGroups,", + " missingGroups", + " };", + " }", + "", + " function resolveOptionalCombinedWeights(", + " mesh,", + " groupNamesText,", + " vertexCount", + " ) {", + " const groupNames =", + " parseVertexGroupNames(groupNamesText);", + " if (!groupNames.length) return null;", + "", + " const combined =", + " new Float32Array(vertexCount);", + " const foundGroups = [];", + " const missingGroups = [];", + " const sources = [];", + "", + " for (const groupName of groupNames) {", + " const resolved =", + " resolveSingleGroupWeights(", + " mesh,", + " groupName,", + " vertexCount", + " );", + " if (!resolved) {", + " missingGroups.push(groupName);", + " continue;", + " }", + "", + " foundGroups.push(groupName);", + " sources.push(", + " resolved.source ||", + " resolved.resolvedName ||", + " groupName", + " );", + "", + " for (", + " let vertex = 0;", + " vertex < vertexCount;", + " vertex++", + " ) {", + " combined[vertex] = Math.max(", + " combined[vertex],", + " resolved.weights[vertex] || 0", + " );", + " }", + " }", + "", + " if (!foundGroups.length) return null;", + "", + " combined._particleFurFoundGroups =", + " foundGroups;", + " combined._particleFurMissingGroups =", + " missingGroups;", + " combined._particleFurSources =", + " sources;", + " return combined;", + " }", + "", + " const regionalNeighborCache = new WeakMap();", + "", + " function copyMaskDiagnostics(", + " source,", + " target,", + " suffix", + " ) {", + " if (!source || !target) return target;", + " target._particleFurFoundGroups =", + " Array.isArray(source._particleFurFoundGroups)", + " ? source._particleFurFoundGroups.slice()", + " : [];", + " target._particleFurMissingGroups =", + " Array.isArray(source._particleFurMissingGroups)", + " ? source._particleFurMissingGroups.slice()", + " : [];", + " target._particleFurSources =", + " Array.isArray(source._particleFurSources)", + " ? source._particleFurSources.map(", + " value => String(value) + (suffix || \"\")", + " )", + " : [];", + " return target;", + " }", + "", + " function buildVertexNeighbors(", + " geometry,", + " vertexCount", + " ) {", + " const cached = regionalNeighborCache.get(geometry);", + " if (cached && cached.vertexCount === vertexCount) {", + " return cached.neighbors;", + " }", + "", + " const neighbors = Array.from(", + " { length: vertexCount },", + " () => []", + " );", + " const index = geometry.index;", + " const valueCount = index ? index.count : vertexCount;", + " const triangleCount = Math.floor(valueCount / 3);", + "", + " const connect = (a, b) => {", + " if (", + " a < 0 || b < 0 ||", + " a >= vertexCount || b >= vertexCount ||", + " a === b", + " ) {", + " return;", + " }", + " neighbors[a].push(b);", + " neighbors[b].push(a);", + " };", + "", + " for (let triangle = 0; triangle < triangleCount; triangle++) {", + " const offset = triangle * 3;", + " const a = index ? index.getX(offset) : offset;", + " const b = index ? index.getX(offset + 1) : offset + 1;", + " const c = index ? index.getX(offset + 2) : offset + 2;", + " connect(a, b);", + " connect(b, c);", + " connect(c, a);", + " }", + "", + " for (let vertex = 0; vertex < vertexCount; vertex++) {", + " if (neighbors[vertex].length > 1) {", + " neighbors[vertex] = Array.from(new Set(neighbors[vertex]));", + " }", + " }", + "", + " regionalNeighborCache.set(geometry, {", + " vertexCount,", + " neighbors", + " });", + " return neighbors;", + " }", + "", + " function expandVertexMask(", + " geometry,", + " sourceWeights,", + " rings,", + " falloff", + " ) {", + " if (!sourceWeights || !geometry || rings <= 0) {", + " return sourceWeights;", + " }", + "", + " const neighbors = buildVertexNeighbors(", + " geometry,", + " sourceWeights.length", + " );", + " let current = Float32Array.from(sourceWeights);", + "", + " for (let ring = 0; ring < rings; ring++) {", + " const next = Float32Array.from(current);", + " const ringFalloff = Math.pow(falloff, ring + 1);", + "", + " for (let vertex = 0; vertex < current.length; vertex++) {", + " const propagated =", + " (current[vertex] || 0) *", + " ringFalloff;", + " if (propagated <= 0) continue;", + "", + " for (const neighbor of neighbors[vertex]) {", + " if (propagated > next[neighbor]) {", + " next[neighbor] = propagated;", + " }", + " }", + " }", + " current = next;", + " }", + "", + " return copyMaskDiagnostics(", + " sourceWeights,", + " current,", + " \" (expanded)\"", + " );", + " }", + "", + " const regionalSpatialIndexCache =", + " new WeakMap();", + "", + " function buildSpatialVertexIndex(", + " geometry,", + " radius", + " ) {", + " const position =", + " geometry &&", + " geometry.getAttribute &&", + " geometry.getAttribute(\"position\");", + " if (", + " !position ||", + " position.count <= 0 ||", + " !Number.isFinite(radius) ||", + " radius <= 1e-9", + " ) {", + " return null;", + " }", + "", + " let geometryCache =", + " regionalSpatialIndexCache.get(geometry);", + " if (!geometryCache) {", + " geometryCache = new Map();", + " regionalSpatialIndexCache.set(", + " geometry,", + " geometryCache", + " );", + " }", + "", + " const cacheKey =", + " radius.toPrecision(8);", + " if (geometryCache.has(cacheKey)) {", + " return geometryCache.get(cacheKey);", + " }", + "", + " const inverseRadius = 1 / radius;", + " const cells = new Map();", + " const xs = new Float32Array(position.count);", + " const ys = new Float32Array(position.count);", + " const zs = new Float32Array(position.count);", + "", + " const keyFor = (x, y, z) =>", + " x + \"|\" + y + \"|\" + z;", + "", + " for (", + " let vertex = 0;", + " vertex < position.count;", + " vertex++", + " ) {", + " const x = position.getX(vertex);", + " const y = position.getY(vertex);", + " const z = position.getZ(vertex);", + " xs[vertex] = x;", + " ys[vertex] = y;", + " zs[vertex] = z;", + "", + " const cellX = Math.floor(", + " x * inverseRadius", + " );", + " const cellY = Math.floor(", + " y * inverseRadius", + " );", + " const cellZ = Math.floor(", + " z * inverseRadius", + " );", + " const key = keyFor(", + " cellX,", + " cellY,", + " cellZ", + " );", + " let list = cells.get(key);", + " if (!list) {", + " list = [];", + " cells.set(key, list);", + " }", + " list.push(vertex);", + " }", + "", + " const result = {", + " radius,", + " radiusSquared: radius * radius,", + " inverseRadius,", + " cells,", + " xs,", + " ys,", + " zs,", + " keyFor", + " };", + " geometryCache.set(cacheKey, result);", + " return result;", + " }", + "", + " function bridgeMaskAcrossNearbySeams(", + " geometry,", + " sourceWeights,", + " radius,", + " falloff,", + " threshold", + " ) {", + " if (", + " !sourceWeights ||", + " !geometry ||", + " !Number.isFinite(radius) ||", + " radius <= 1e-9", + " ) {", + " return sourceWeights;", + " }", + "", + " const spatial =", + " buildSpatialVertexIndex(", + " geometry,", + " radius", + " );", + " if (!spatial) return sourceWeights;", + "", + " const result =", + " Float32Array.from(sourceWeights);", + " const minimumWeight = Math.max(", + " 0,", + " Number(threshold) || 0", + " );", + "", + " for (", + " let sourceVertex = 0;", + " sourceVertex < sourceWeights.length;", + " sourceVertex++", + " ) {", + " const sourceWeight =", + " sourceWeights[sourceVertex] || 0;", + " if (sourceWeight <= minimumWeight) {", + " continue;", + " }", + "", + " const sourceX =", + " spatial.xs[sourceVertex];", + " const sourceY =", + " spatial.ys[sourceVertex];", + " const sourceZ =", + " spatial.zs[sourceVertex];", + " const cellX = Math.floor(", + " sourceX * spatial.inverseRadius", + " );", + " const cellY = Math.floor(", + " sourceY * spatial.inverseRadius", + " );", + " const cellZ = Math.floor(", + " sourceZ * spatial.inverseRadius", + " );", + "", + " for (", + " let offsetX = -1;", + " offsetX <= 1;", + " offsetX++", + " ) {", + " for (", + " let offsetY = -1;", + " offsetY <= 1;", + " offsetY++", + " ) {", + " for (", + " let offsetZ = -1;", + " offsetZ <= 1;", + " offsetZ++", + " ) {", + " const list = spatial.cells.get(", + " spatial.keyFor(", + " cellX + offsetX,", + " cellY + offsetY,", + " cellZ + offsetZ", + " )", + " );", + " if (!list) continue;", + "", + " for (const targetVertex of list) {", + " if (targetVertex === sourceVertex) {", + " continue;", + " }", + "", + " const deltaX =", + " spatial.xs[targetVertex] -", + " sourceX;", + " const deltaY =", + " spatial.ys[targetVertex] -", + " sourceY;", + " const deltaZ =", + " spatial.zs[targetVertex] -", + " sourceZ;", + " const distanceSquared =", + " deltaX * deltaX +", + " deltaY * deltaY +", + " deltaZ * deltaZ;", + "", + " if (", + " distanceSquared >", + " spatial.radiusSquared", + " ) {", + " continue;", + " }", + "", + " const distanceRatio =", + " Math.sqrt(distanceSquared) /", + " spatial.radius;", + " const distanceFalloff =", + " 1 -", + " 0.45 *", + " clamp(", + " distanceRatio,", + " 0,", + " 1", + " );", + " const propagated =", + " sourceWeight *", + " falloff *", + " distanceFalloff;", + "", + " if (", + " propagated >", + " result[targetVertex]", + " ) {", + " result[targetVertex] =", + " propagated;", + " }", + " }", + " }", + " }", + " }", + " }", + "", + " return copyMaskDiagnostics(", + " sourceWeights,", + " result,", + " \" (spatial seam bridge)\"", + " );", + " }", + "", + " function mergeMasksMaximum(", + " first,", + " second,", + " vertexCount,", + " sourceLabel", + " ) {", + " if (!first && !second) return null;", + " const result =", + " new Float32Array(vertexCount);", + "", + " for (", + " let vertex = 0;", + " vertex < vertexCount;", + " vertex++", + " ) {", + " result[vertex] = Math.max(", + " first ? first[vertex] || 0 : 0,", + " second ? second[vertex] || 0 : 0", + " );", + " }", + "", + " const sources = [];", + " if (", + " first &&", + " Array.isArray(", + " first._particleFurSources", + " )", + " ) {", + " sources.push(", + " ...first._particleFurSources", + " );", + " }", + " if (", + " second &&", + " Array.isArray(", + " second._particleFurSources", + " )", + " ) {", + " sources.push(", + " ...second._particleFurSources", + " );", + " }", + " if (sourceLabel) {", + " sources.push(sourceLabel);", + " }", + "", + " result._particleFurFoundGroups = [];", + " result._particleFurMissingGroups = [];", + " result._particleFurSources =", + " Array.from(new Set(sources));", + " return result;", + " }", + "", + " function weightedMaskCentroid(", + " mesh,", + " position,", + " weights,", + " target", + " ) {", + " target.set(0, 0, 0);", + " if (!position || !weights) return 0;", + "", + " const point = mesh.position.clone();", + " let totalWeight = 0;", + " for (", + " let vertex = 0;", + " vertex < position.count;", + " vertex++", + " ) {", + " const weight = clamp(", + " Number(weights[vertex]) || 0,", + " 0,", + " 1", + " );", + " if (weight <= 0) continue;", + " readBindPosition(mesh, vertex, point);", + " target.x += point.x * weight;", + " target.y += point.y * weight;", + " target.z += point.z * weight;", + " totalWeight += weight;", + " }", + "", + " if (totalWeight > 1e-9) {", + " target.x /= totalWeight;", + " target.y /= totalWeight;", + " target.z /= totalWeight;", + " }", + " return totalWeight;", + " }", + "", + " function createAutomaticBackHeadMask(", + " mesh,", + " position,", + " headWeights,", + " bodyWeights,", + " options", + " ) {", + " if (", + " !options.autoBackHeadCoverage ||", + " !headWeights ||", + " !position", + " ) {", + " return null;", + " }", + "", + " const headCenter = mesh.position.clone();", + " const bodyCenter = mesh.position.clone();", + " const headTotal = weightedMaskCentroid(", + " mesh,", + " position,", + " headWeights,", + " headCenter", + " );", + " const bodyTotal = weightedMaskCentroid(", + " mesh,", + " position,", + " bodyWeights,", + " bodyCenter", + " );", + "", + " if (headTotal <= 1e-9) return null;", + "", + " let directionX =", + " bodyCenter.x - headCenter.x;", + " let directionY =", + " bodyCenter.y - headCenter.y;", + " let directionZ =", + " bodyCenter.z - headCenter.z;", + " let directionLength = Math.hypot(", + " directionX,", + " directionY,", + " directionZ", + " );", + "", + " if (", + " bodyTotal <= 1e-9 ||", + " directionLength <= 1e-8", + " ) {", + " directionX = 1;", + " directionY = 0;", + " directionZ = 0;", + " directionLength = 1;", + " }", + "", + " directionX /= directionLength;", + " directionY /= directionLength;", + " directionZ /= directionLength;", + "", + " const point = mesh.position.clone();", + " let minimumProjection = Infinity;", + " let maximumProjection = -Infinity;", + "", + " for (", + " let vertex = 0;", + " vertex < position.count;", + " vertex++", + " ) {", + " if (", + " (headWeights[vertex] || 0) <=", + " options.groupThreshold * 0.2", + " ) {", + " continue;", + " }", + " readBindPosition(mesh, vertex, point);", + " const projection =", + " point.x * directionX +", + " point.y * directionY +", + " point.z * directionZ;", + " minimumProjection = Math.min(", + " minimumProjection,", + " projection", + " );", + " maximumProjection = Math.max(", + " maximumProjection,", + " projection", + " );", + " }", + "", + " const projectionRange = Math.max(", + " 1e-8,", + " maximumProjection -", + " minimumProjection", + " );", + " const result =", + " new Float32Array(position.count);", + "", + " for (", + " let vertex = 0;", + " vertex < position.count;", + " vertex++", + " ) {", + " const headWeight =", + " headWeights[vertex] || 0;", + " if (headWeight <= 0) continue;", + "", + " readBindPosition(mesh, vertex, point);", + " const projection =", + " point.x * directionX +", + " point.y * directionY +", + " point.z * directionZ;", + " const normalizedProjection = clamp(", + " (", + " projection -", + " minimumProjection", + " ) /", + " projectionRange,", + " 0,", + " 1", + " );", + "", + " const rearWeight = clamp(", + " (", + " normalizedProjection -", + " options.backHeadStart", + " ) /", + " Math.max(", + " 0.0001,", + " 1 -", + " options.backHeadStart", + " ),", + " 0,", + " 1", + " );", + "", + " result[vertex] =", + " headWeight * rearWeight;", + " }", + "", + " result._particleFurFoundGroups = [];", + " result._particleFurMissingGroups = [];", + " result._particleFurSources = [", + " \"automatic back-head mask from HEAD toward BODY\"", + " ];", + " return result;", + " }", + "", + " function deriveLocalUpFromBodyAndPaws(", + " mesh,", + " position,", + " bodyWeights,", + " pawWeights,", + " target", + " ) {", + " const bodyCenter = mesh.position.clone();", + " const pawCenter = mesh.position.clone();", + " const bodyTotal = weightedMaskCentroid(", + " mesh,", + " position,", + " bodyWeights,", + " bodyCenter", + " );", + " const pawTotal = weightedMaskCentroid(", + " mesh,", + " position,", + " pawWeights,", + " pawCenter", + " );", + "", + " if (", + " bodyTotal > 1e-9 &&", + " pawTotal > 1e-9", + " ) {", + " target.x =", + " bodyCenter.x - pawCenter.x;", + " target.y =", + " bodyCenter.y - pawCenter.y;", + " target.z =", + " bodyCenter.z - pawCenter.z;", + " const length = Math.hypot(", + " target.x,", + " target.y,", + " target.z", + " );", + " if (length > 1e-8) {", + " target.x /= length;", + " target.y /= length;", + " target.z /= length;", + " return target;", + " }", + " }", + "", + " localDirection(", + " mesh,", + " 0,", + " 0,", + " 1,", + " target", + " );", + " return target;", + " }", + "", + " function createAutomaticTopBackMask(", + " mesh,", + " geometry,", + " position,", + " baseCoverage,", + " bodyReferenceWeights,", + " pawReferenceWeights,", + " options", + " ) {", + " if (", + " !options.autoTopBackCoverage ||", + " !mesh ||", + " !geometry ||", + " !position", + " ) {", + " return null;", + " }", + "", + " const localUp = mesh.position.clone();", + " deriveLocalUpFromBodyAndPaws(", + " mesh,", + " position,", + " bodyReferenceWeights,", + " pawReferenceWeights,", + " localUp", + " );", + " const upLength = Math.hypot(", + " localUp.x,", + " localUp.y,", + " localUp.z", + " );", + " if (upLength <= 1e-8) {", + " localUp.x = 0;", + " localUp.y = 0;", + " localUp.z = 1;", + " }", + "", + " const normal =", + " geometry.getAttribute(\"normal\");", + " const point = mesh.position.clone();", + " let minimumHeight = Infinity;", + " let maximumHeight = -Infinity;", + "", + " for (", + " let vertex = 0;", + " vertex < position.count;", + " vertex++", + " ) {", + " readBindPosition(", + " mesh,", + " vertex,", + " point", + " );", + " const height =", + " point.x * localUp.x +", + " point.y * localUp.y +", + " point.z * localUp.z;", + " minimumHeight = Math.min(", + " minimumHeight,", + " height", + " );", + " maximumHeight = Math.max(", + " maximumHeight,", + " height", + " );", + " }", + "", + " const heightRange = Math.max(", + " 1e-8,", + " maximumHeight - minimumHeight", + " );", + "", + " let nearbyCoverage = baseCoverage", + " ? expandVertexMask(", + " geometry,", + " baseCoverage,", + " options.topBackCoverageExpansionRings,", + " options.topBackCoverageExpansionFalloff", + " )", + " : null;", + "", + " if (", + " nearbyCoverage &&", + " options.bridgeRegionalMaskSeams", + " ) {", + " const referenceDimension =", + " meshReferenceDimension(", + " mesh,", + " position", + " );", + " nearbyCoverage =", + " bridgeMaskAcrossNearbySeams(", + " geometry,", + " nearbyCoverage,", + " referenceDimension *", + " options.regionalSeamBridgeRadius,", + " options.regionalSeamBridgeFalloff,", + " options.groupThreshold * 0.2", + " );", + " }", + "", + " const result =", + " new Float32Array(position.count);", + "", + " for (", + " let vertex = 0;", + " vertex < position.count;", + " vertex++", + " ) {", + " readBindPosition(", + " mesh,", + " vertex,", + " point", + " );", + " const height =", + " point.x * localUp.x +", + " point.y * localUp.y +", + " point.z * localUp.z;", + " const normalizedHeight = clamp(", + " (", + " height -", + " minimumHeight", + " ) /", + " heightRange,", + " 0,", + " 1", + " );", + "", + " if (", + " normalizedHeight <", + " options.topBackHeightStart", + " ) {", + " continue;", + " }", + "", + " const heightWeight = clamp(", + " (", + " normalizedHeight -", + " options.topBackHeightStart", + " ) /", + " Math.max(", + " 0.0001,", + " 1 -", + " options.topBackHeightStart", + " ),", + " 0,", + " 1", + " );", + "", + " let upwardNormal = 0;", + " if (normal) {", + " upwardNormal =", + " normal.getX(vertex) *", + " localUp.x +", + " normal.getY(vertex) *", + " localUp.y +", + " normal.getZ(vertex) *", + " localUp.z;", + " }", + "", + " // High vertices keep a baseline weight even on the vertical rear of", + " // the head. Upward-facing back surfaces receive the full weight.", + " const orientationWeight = Math.max(", + " options.topBackHighVertexBias,", + " clamp(", + " (", + " upwardNormal + 0.15", + " ) /", + " 1.15,", + " 0,", + " 1", + " )", + " );", + "", + " const neighborhoodWeight =", + " nearbyCoverage", + " ? nearbyCoverage[vertex] || 0", + " : 1;", + "", + " result[vertex] =", + " heightWeight *", + " orientationWeight *", + " neighborhoodWeight;", + " }", + "", + " result._particleFurFoundGroups = [];", + " result._particleFurMissingGroups = [];", + " result._particleFurSources = [", + " \"automatic top/back coverage\"", + " ];", + " return result;", + " }", + "", + " function availableAttributeNames(geometry) {", + " return Object.keys(", + " geometry &&", + " geometry.attributes", + " ? geometry.attributes", + " : {}", + " ).sort();", + " }", + "", + " function describeMask(", + " requestedText,", + " weights", + " ) {", + " const requested =", + " parseVertexGroupNames(requestedText);", + " if (!requested.length) return \"not set\";", + "", + " if (!weights) {", + " return (", + " \"MISSING [\" +", + " requested.join(\", \") +", + " \"]\"", + " );", + " }", + "", + " const sources =", + " weights._particleFurSources || [];", + " return sources.length", + " ? sources.join(\" + \")", + " : \"resolved\";", + " }", + "", + " function createZeroCoverage(", + " vertexCount,", + " source", + " ) {", + " return {", + " weights: new Float32Array(vertexCount),", + " source: source || \"empty coverage\",", + " foundGroups: [],", + " missingGroups: []", + " };", + " }", + "", + " function extendCoverageWithMasks(", + " resolvedCoverage,", + " maskArrays,", + " vertexCount", + " ) {", + " let result = resolvedCoverage;", + " let foundMask = false;", + "", + " for (const weights of maskArrays) {", + " if (!weights) continue;", + " foundMask = true;", + "", + " if (!result) {", + " result = createZeroCoverage(", + " vertexCount,", + " \"regional and length masks\"", + " );", + " }", + "", + " for (", + " let vertex = 0;", + " vertex < vertexCount;", + " vertex++", + " ) {", + " result.weights[vertex] = Math.max(", + " result.weights[vertex] || 0,", + " weights[vertex] || 0", + " );", + " }", + " }", + "", + " if (", + " foundMask &&", + " result &&", + " !String(result.source).includes(", + " \"regional and length masks\"", + " )", + " ) {", + " result.source =", + " String(result.source || \"coverage\") +", + " \" + regional and length masks\";", + " }", + "", + " return {", + " resolved: result,", + " foundMask", + " };", + " }", + "", + " function parseKeywordList(value) {", + " return Array.from(", + " new Set(", + " String(value || \"\")", + " .toLowerCase()", + " .split(/[,;|]+/)", + " .map(keyword => keyword.trim())", + " .filter(Boolean)", + " )", + " );", + " }", + "", + " function nameMatchesKeywords(name, keywords) {", + " const lowerName = String(name || \"\").toLowerCase();", + " if (!lowerName) return false;", + " for (const keyword of keywords) {", + " if (keyword && lowerName.includes(keyword)) return true;", + " }", + " return false;", + " }", + "", + " function triangleBoneRegion(", + " mesh,", + " ia,", + " ib,", + " ic,", + " options", + " ) {", + " if (", + " !options.autoRegionBoneDetection ||", + " !mesh.isSkinnedMesh ||", + " !mesh.skeleton ||", + " !mesh.geometry", + " ) {", + " return \"body\";", + " }", + "", + " const skinIndex =", + " mesh.geometry.getAttribute(\"skinIndex\");", + " const skinWeight =", + " mesh.geometry.getAttribute(\"skinWeight\");", + " if (!skinIndex || !skinWeight) return \"body\";", + "", + " const tailKeywords = parseKeywordList(", + " options.tailBoneKeywords", + " );", + " const legKeywords = parseKeywordList(", + " options.legBoneKeywords", + " );", + " const pawKeywords = parseKeywordList(", + " options.pawBoneKeywords", + " );", + " const earKeywords = parseKeywordList(", + " options.earBoneKeywords", + " );", + " const headKeywords = parseKeywordList(", + " options.headBoneKeywords", + " );", + "", + " const scores = {", + " tail: 0,", + " leg: 0,", + " paw: 0,", + " ear: 0,", + " head: 0", + " };", + " const vertexIndices = [ia, ib, ic];", + "", + " for (const vertexIndex of vertexIndices) {", + " for (", + " let componentIndex = 0;", + " componentIndex < 4;", + " componentIndex++", + " ) {", + " const rawBoneIndex = component(", + " skinIndex,", + " vertexIndex,", + " componentIndex", + " );", + " const rawWeight = component(", + " skinWeight,", + " vertexIndex,", + " componentIndex", + " );", + " if (", + " !Number.isFinite(rawBoneIndex) ||", + " !Number.isFinite(rawWeight) ||", + " rawWeight <= 0", + " ) {", + " continue;", + " }", + "", + " const boneIndex = Math.round(rawBoneIndex);", + " const bone =", + " mesh.skeleton.bones[boneIndex];", + " if (!bone) continue;", + "", + " const contribution =", + " clamp(rawWeight, 0, 1) / 3;", + " const boneName = bone.name || \"\";", + "", + " // More specific regions are checked first.", + " if (", + " nameMatchesKeywords(", + " boneName,", + " tailKeywords", + " )", + " ) {", + " scores.tail += contribution;", + " } else if (", + " nameMatchesKeywords(", + " boneName,", + " pawKeywords", + " )", + " ) {", + " scores.paw += contribution;", + " } else if (", + " nameMatchesKeywords(", + " boneName,", + " earKeywords", + " )", + " ) {", + " scores.ear += contribution;", + " } else if (", + " nameMatchesKeywords(", + " boneName,", + " headKeywords", + " )", + " ) {", + " scores.head += contribution;", + " } else if (", + " nameMatchesKeywords(", + " boneName,", + " legKeywords", + " )", + " ) {", + " scores.leg += contribution;", + " }", + " }", + " }", + "", + " let bestRegion = \"body\";", + " let bestScore = 0.04;", + " for (const region of [", + " \"tail\",", + " \"paw\",", + " \"ear\",", + " \"leg\",", + " \"head\"", + " ]) {", + " if (scores[region] > bestScore) {", + " bestScore = scores[region];", + " bestRegion = region;", + " }", + " }", + " return bestRegion;", + " }", + "", + " function chooseExplicitRegion(", + " tailWeight,", + " legWeight,", + " pawWeight,", + " earWeight,", + " headWeight,", + " fallbackRegion", + " ) {", + " let region = fallbackRegion || \"body\";", + " let bestWeight = 0.05;", + "", + " const weightedRegions = [", + " [\"head\", headWeight],", + " [\"leg\", legWeight],", + " [\"ear\", earWeight],", + " [\"paw\", pawWeight],", + " [\"tail\", tailWeight]", + " ];", + "", + " for (const entry of weightedRegions) {", + " const candidateRegion = entry[0];", + " const candidateWeight =", + " Number(entry[1]) || 0;", + " if (candidateWeight > bestWeight) {", + " bestWeight = candidateWeight;", + " region = candidateRegion;", + " }", + " }", + " return region;", + " }", + "", + " function densityMultiplierForRegion(", + " region,", + " options", + " ) {", + " if (region === \"tail\") {", + " return options.tailDensityMultiplier;", + " }", + " if (region === \"leg\") {", + " return options.legDensityMultiplier;", + " }", + " if (region === \"paw\") {", + " return options.pawDensityMultiplier;", + " }", + " if (region === \"ear\") {", + " return options.earDensityMultiplier;", + " }", + " if (region === \"head\") {", + " return options.headDensityMultiplier;", + " }", + " return 1;", + " }", + "", + " function lengthMultiplierForRegion(", + " region,", + " options", + " ) {", + " if (region === \"tail\") {", + " return options.tailLengthMultiplier;", + " }", + " if (region === \"leg\") {", + " return options.legLengthMultiplier;", + " }", + " if (region === \"paw\") {", + " return options.pawLengthMultiplier;", + " }", + " if (region === \"ear\") {", + " return options.earLengthMultiplier;", + " }", + " if (region === \"head\") {", + " return 1;", + " }", + " return 1;", + " }", + "", + " function minimumShareForRegion(", + " region,", + " options", + " ) {", + " if (region === \"tail\") {", + " return options.minimumTailRootShare;", + " }", + " if (region === \"leg\") {", + " return options.minimumLegRootShare;", + " }", + " if (region === \"paw\") {", + " return options.minimumPawRootShare;", + " }", + " if (region === \"ear\") {", + " return options.minimumEarRootShare;", + " }", + " if (region === \"head\") {", + " return options.minimumHeadRootShare;", + " }", + " return 0;", + " }", + "", + " function makeCandidatePool(candidates) {", + " const entries = [];", + " let totalWeight = 0;", + " for (const candidate of candidates) {", + " const selectionWeight = Math.max(", + " 0,", + " Number(candidate.selectionWeight) || 0", + " );", + " if (selectionWeight <= 0) continue;", + " totalWeight += selectionWeight;", + " entries.push({", + " candidate,", + " cumulativeWeight: totalWeight", + " });", + " }", + " return {", + " entries,", + " totalWeight", + " };", + " }", + "", + " function collectMeshes(root, meshName) {", + " const result = [];", + " const wanted = String(meshName || \"\").trim().toLowerCase();", + " if (!root || !root.traverse) return result;", + " root.traverse(node => {", + " if (!node || !(node.isMesh || node.isSkinnedMesh) || !node.geometry) return;", + " if (node.userData && node.userData.__ParticleFur3DStrands) return;", + " const position = node.geometry.getAttribute && node.geometry.getAttribute(\"position\");", + " if (!position || position.count < 3) return;", + " if (wanted && String(node.name || \"\").toLowerCase() !== wanted) return;", + " result.push(node);", + " });", + " return result;", + " }", + "", + " function chooseCandidate(candidates, totalWeight, random) {", + " const target = random() * totalWeight;", + " let low = 0;", + " let high = candidates.length - 1;", + " while (low < high) {", + " const middle = (low + high) >> 1;", + " if (", + " candidates[middle].cumulativeWeight <", + " target", + " ) {", + " low = middle + 1;", + " } else {", + " high = middle;", + " }", + " }", + " const selected = candidates[low];", + " return selected && selected.candidate", + " ? selected.candidate", + " : selected;", + " }", + "", + " function meshConstructorFrom(source) {", + " if (!source.isSkinnedMesh) return source.constructor;", + " const parentPrototype = Object.getPrototypeOf(source.constructor.prototype);", + " return parentPrototype && parentPrototype.constructor ? parentPrototype.constructor : source.constructor;", + " }", + "", + " function syncFurShaderUniforms(shaderState) {", + " const uniforms = shaderState.uniforms;", + " if (!uniforms) return;", + "", + " uniforms.uFurTime.value = shaderState.time;", + " uniforms.uFurWindDirection.value.set(", + " shaderState.windX,", + " shaderState.windY,", + " shaderState.windZ", + " );", + " uniforms.uFurMovementDirection.value.set(", + " shaderState.movementX,", + " shaderState.movementY,", + " shaderState.movementZ", + " );", + " uniforms.uFurGravityDirection.value.set(", + " shaderState.gravityX,", + " shaderState.gravityY,", + " shaderState.gravityZ", + " );", + " uniforms.uFurWindStrength.value = shaderState.windStrength;", + " uniforms.uFurWindFrequency.value = shaderState.windFrequency;", + " uniforms.uFurMovementInfluence.value =", + " shaderState.movementInfluence;", + " uniforms.uFurMovementAmount.value = shaderState.movementAmount;", + " uniforms.uFurGravityStrength.value = shaderState.gravityStrength;", + " uniforms.uFurLayerLength.value = shaderState.layerLength;", + " uniforms.uFurRootStiffness.value = shaderState.rootStiffness;", + " uniforms.uFurMotionScale.value =", + " shaderState.motionScale;", + " uniforms.uFurHangStrength.value =", + " shaderState.hangStrength;", + " uniforms.uFurHangStart.value =", + " shaderState.hangStart;", + " uniforms.uFurWaveAmplitude.value =", + " shaderState.waveAmplitude;", + " uniforms.uFurWaveAlongHair.value =", + " shaderState.waveAlongHair;", + " uniforms.uFurWaveSpeed.value =", + " shaderState.waveSpeed;", + " uniforms.uFurRestWaveAmount.value =", + " shaderState.restWaveAmount;", + " uniforms.uFurMovementWaveBoost.value =", + " shaderState.movementWaveBoost;", + " uniforms.uFurPreventSurfacePenetration.value =", + " shaderState.preventSurfacePenetration;", + " uniforms.uFurSurfaceSafetyLift.value =", + " shaderState.surfaceSafetyLift;", + " uniforms.uFurTailVerticalResponse.value =", + " shaderState.tailVerticalResponse;", + " uniforms.uFurTailVerticalInfluence.value =", + " shaderState.tailVerticalInfluence;", + " uniforms.uFurTailVerticalTipPower.value =", + " shaderState.tailVerticalTipPower;", + " uniforms.uFurTailFallOverrideResponse.value =", + " shaderState.tailFallOverrideResponse;", + " uniforms.uFurTailRestGravityAlignment.value =", + " shaderState.tailRestGravityAlignment;", + " uniforms.uFurTailRestHangMultiplier.value =", + " shaderState.tailRestHangMultiplier;", + " }", + "", + " function createMaterial(source, layerOptions) {", + " const sourceMaterials = Array.isArray(source.material)", + " ? source.material", + " : [source.material];", + " const base = sourceMaterials.find(Boolean);", + " if (!base) throw new Error(\"Source mesh has no material.\");", + "", + " let material = null;", + " try {", + " material = new base.constructor({", + " color: 0xffffff,", + " vertexColors: true,", + " side: 2,", + " transparent: false,", + " opacity: 1,", + " depthWrite: true,", + " roughness: 0.92,", + " metalness: 0", + " });", + " } catch (error) {", + " material = base.clone();", + " }", + "", + " if (material.color && material.color.setRGB) {", + " material.color.setRGB(1, 1, 1);", + " }", + " if (\"vertexColors\" in material) material.vertexColors = true;", + " if (\"side\" in material) material.side = 2;", + " if (\"map\" in material) material.map = null;", + " if (\"alphaMap\" in material) material.alphaMap = null;", + " if (\"normalMap\" in material) material.normalMap = null;", + " if (\"roughness\" in material) material.roughness = 0.92;", + " if (\"metalness\" in material) material.metalness = 0;", + " if (\"transparent\" in material) material.transparent = false;", + " if (\"opacity\" in material) material.opacity = 1;", + " if (\"depthWrite\" in material) material.depthWrite = true;", + "", + " const shaderState = {", + " uniforms: null,", + " time: 0,", + " windX: 0,", + " windY: 0,", + " windZ: 0,", + " movementX: 0,", + " movementY: 0,", + " movementZ: 0,", + " gravityX: 0,", + " gravityY: 0,", + " gravityZ: -1,", + " windStrength: 0,", + " windFrequency: 1,", + " movementInfluence: 0,", + " movementAmount: 0,", + " gravityStrength: 0,", + " layerLength: Math.max(0.00001, layerOptions.length),", + " rootStiffness:", + " clamp(", + " layerOptions.rootStiffness,", + " 0,", + " 1", + " ),", + " motionScale:", + " layerOptions.kind === \"undercoat\"", + " ? 0.25", + " : 1,", + " hangStrength: 0,", + " hangStart: 0.12,", + " waveAmplitude: 0,", + " waveAlongHair: 1.6,", + " waveSpeed: 1.1,", + " restWaveAmount: 0.05,", + " movementWaveBoost: 1.2,", + " preventSurfacePenetration: 1,", + " surfaceSafetyLift: 0.06,", + " tailVerticalResponse: 0,", + " tailVerticalInfluence: 0,", + " tailVerticalTipPower: 1.5,", + " tailFallOverrideResponse: 0.3,", + " tailRestGravityAlignment: 1,", + " tailRestHangMultiplier: 1", + " };", + "", + " material.userData = Object.assign(", + " {},", + " material.userData || {},", + " {", + " __ParticleFur3DOwned: true,", + " __ParticleFurShaderState: shaderState", + " }", + " );", + "", + " material.onBeforeCompile = function (shader) {", + " const vectorTemplate = source.position.clone();", + " vectorTemplate.set(0, 0, 0);", + "", + " shader.uniforms.uFurTime = { value: shaderState.time };", + " shader.uniforms.uFurWindDirection = {", + " value: vectorTemplate.clone()", + " };", + " shader.uniforms.uFurMovementDirection = {", + " value: vectorTemplate.clone()", + " };", + " shader.uniforms.uFurGravityDirection = {", + " value: vectorTemplate.clone().set(0, 0, -1)", + " };", + " shader.uniforms.uFurWindStrength = {", + " value: shaderState.windStrength", + " };", + " shader.uniforms.uFurWindFrequency = {", + " value: shaderState.windFrequency", + " };", + " shader.uniforms.uFurMovementInfluence = {", + " value: shaderState.movementInfluence", + " };", + " shader.uniforms.uFurMovementAmount = {", + " value: shaderState.movementAmount", + " };", + " shader.uniforms.uFurGravityStrength = {", + " value: shaderState.gravityStrength", + " };", + " shader.uniforms.uFurLayerLength = {", + " value: shaderState.layerLength", + " };", + " shader.uniforms.uFurRootStiffness = {", + " value: shaderState.rootStiffness", + " };", + " shader.uniforms.uFurMotionScale = {", + " value: shaderState.motionScale", + " };", + " shader.uniforms.uFurHangStrength = {", + " value: shaderState.hangStrength", + " };", + " shader.uniforms.uFurHangStart = {", + " value: shaderState.hangStart", + " };", + " shader.uniforms.uFurWaveAmplitude = {", + " value: shaderState.waveAmplitude", + " };", + " shader.uniforms.uFurWaveAlongHair = {", + " value: shaderState.waveAlongHair", + " };", + " shader.uniforms.uFurWaveSpeed = {", + " value: shaderState.waveSpeed", + " };", + " shader.uniforms.uFurRestWaveAmount = {", + " value: shaderState.restWaveAmount", + " };", + " shader.uniforms.uFurMovementWaveBoost = {", + " value: shaderState.movementWaveBoost", + " };", + " shader.uniforms.uFurPreventSurfacePenetration = {", + " value:", + " shaderState.preventSurfacePenetration", + " };", + " shader.uniforms.uFurSurfaceSafetyLift = {", + " value:", + " shaderState.surfaceSafetyLift", + " };", + " shader.uniforms.uFurTailVerticalResponse = {", + " value:", + " shaderState.tailVerticalResponse", + " };", + " shader.uniforms.uFurTailVerticalInfluence = {", + " value:", + " shaderState.tailVerticalInfluence", + " };", + " shader.uniforms.uFurTailVerticalTipPower = {", + " value:", + " shaderState.tailVerticalTipPower", + " };", + " shader.uniforms.uFurTailFallOverrideResponse = {", + " value:", + " shaderState.tailFallOverrideResponse", + " };", + " shader.uniforms.uFurTailRestGravityAlignment = {", + " value:", + " shaderState.tailRestGravityAlignment", + " };", + " shader.uniforms.uFurTailRestHangMultiplier = {", + " value:", + " shaderState.tailRestHangMultiplier", + " };", + "", + " const declarations = [", + " \"attribute vec4 furMotion;\",", + " \"attribute vec3 furTailDownDirection;\",", + " \"attribute vec3 furSurfaceNormal;\",", + " \"uniform float uFurTime;\",", + " \"uniform vec3 uFurWindDirection;\",", + " \"uniform vec3 uFurMovementDirection;\",", + " \"uniform vec3 uFurGravityDirection;\",", + " \"uniform float uFurWindStrength;\",", + " \"uniform float uFurWindFrequency;\",", + " \"uniform float uFurMovementInfluence;\",", + " \"uniform float uFurMovementAmount;\",", + " \"uniform float uFurGravityStrength;\",", + " \"uniform float uFurLayerLength;\",", + " \"uniform float uFurRootStiffness;\",", + " \"uniform float uFurMotionScale;\",", + " \"uniform float uFurHangStrength;\",", + " \"uniform float uFurHangStart;\",", + " \"uniform float uFurWaveAmplitude;\",", + " \"uniform float uFurWaveAlongHair;\",", + " \"uniform float uFurWaveSpeed;\",", + " \"uniform float uFurRestWaveAmount;\",", + " \"uniform float uFurMovementWaveBoost;\",", + " \"uniform float uFurPreventSurfacePenetration;\",", + " \"uniform float uFurSurfaceSafetyLift;\",", + " \"uniform float uFurTailVerticalResponse;\",", + " \"uniform float uFurTailVerticalInfluence;\",", + " \"uniform float uFurTailVerticalTipPower;\",", + " \"uniform float uFurTailFallOverrideResponse;\",", + " \"uniform float uFurTailRestGravityAlignment;\",", + " \"uniform float uFurTailRestHangMultiplier;\"", + " ].join(\"\\n\");", + "", + " shader.vertexShader =", + " declarations + \"\\n\" + shader.vertexShader;", + "", + " const beginVertexReplacement = [", + " \"vec3 transformed = vec3( position );\"", + " ].join(\"\\n\");", + "", + " const postSkinningFurDisplacement = [", + " \"float furT = clamp(furMotion.x, 0.0, 1.0);\",", + " \"float furPhase = furMotion.y;\",", + " \"float furHangScale = max(furMotion.z, 0.0);\",", + " \"float furWaveScale = max(furMotion.w, 0.0);\",", + " \"float furExponent = 1.0 + uFurRootStiffness * 7.0;\",", + " \"float furInfluence = pow(furT, furExponent);\",", + " \"float furFlutter = 0.70 + 0.30 * sin(\",", + " \" uFurTime * uFurWindFrequency * 6.28318530718 +\",", + " \" furPhase\",", + " \");\",", + " \"\",", + " \"// Transform the corrected source-surface normal with the same\",", + " \"// skinning matrix as the animated model.\",", + " \"vec3 safeSurfaceNormal = normalize(furSurfaceNormal);\",", + " \"#ifdef USE_SKINNING\",", + " \" safeSurfaceNormal = normalize(\",", + " \" mat3(skinMatrix) * safeSurfaceNormal\",", + " \" );\",", + " \"#endif\",", + " \"if (length(safeSurfaceNormal) < 0.001) {\",", + " \" safeSurfaceNormal = normalize(objectNormal);\",", + " \"}\",", + " \"\",", + " \"// Fixed per-root tail direction. It is generated once in bind pose\",", + " \"// and skinned with the tail, so it cannot choose a different side\",", + " \"// on later frames.\",", + " \"vec3 stableTailDown = furTailDownDirection;\",", + " \"#ifdef USE_SKINNING\",", + " \" stableTailDown =\",", + " \" mat3(skinMatrix) * stableTailDown;\",", + " \"#endif\",", + " \"float stableTailFactor =\",", + " \" length(stableTailDown);\",", + " \"if (stableTailFactor > 0.0001) {\",", + " \" stableTailDown /=\",", + " \" stableTailFactor;\",", + " \"}\",", + " \"\",", + " \"vec3 safeGravity = normalize(\",", + " \" length(uFurGravityDirection) > 0.0001\",", + " \" ? uFurGravityDirection\",", + " \" : vec3(0.0, 0.0, -1.0)\",", + " \");\",", + " \"\",", + " \"vec3 protectedWind = uFurWindDirection;\",", + " \"vec3 protectedMovement = uFurMovementDirection;\",", + " \"vec3 protectedGravity = safeGravity;\",", + " \"if (uFurPreventSurfacePenetration > 0.5) {\",", + " \" float windInward = dot(protectedWind, safeSurfaceNormal);\",", + " \" float movementInward = dot(protectedMovement, safeSurfaceNormal);\",", + " \" float gravityInward = dot(protectedGravity, safeSurfaceNormal);\",", + " \" protectedWind -=\",", + " \" safeSurfaceNormal * min(windInward, 0.0);\",", + " \" protectedMovement -=\",", + " \" safeSurfaceNormal * min(movementInward, 0.0);\",", + " \" protectedGravity -=\",", + " \" safeSurfaceNormal * min(gravityInward, 0.0);\",", + " \"}\",", + " \"\",", + " \"// Tail resting direction is calculated from current world gravity.\",", + " \"vec3 surfaceSafeTailGravity = protectedGravity;\",", + " \"if (length(surfaceSafeTailGravity) < 0.0001) {\",", + " \" surfaceSafeTailGravity = safeGravity;\",", + " \"}\",", + " \"surfaceSafeTailGravity = normalize(\",", + " \" surfaceSafeTailGravity\",", + " \");\",", + " \"vec3 tailRestGravity = normalize(mix(\",", + " \" surfaceSafeTailGravity,\",", + " \" safeGravity,\",", + " \" clamp(\",", + " \" uFurTailRestGravityAlignment,\",", + " \" 0.0,\",", + " \" 1.0\",", + " \" )\",", + " \"));\",", + " \"\",", + " \"vec3 furBend =\",", + " \" protectedWind * uFurWindStrength * furFlutter +\",", + " \" protectedMovement *\",", + " \" uFurMovementInfluence *\",", + " \" uFurMovementAmount +\",", + " \" protectedGravity * uFurGravityStrength;\",", + " \"transformed += furBend *\",", + " \" furInfluence *\",", + " \" uFurLayerLength *\",", + " \" uFurMotionScale;\",", + " \"\",", + " \"// Signed response on one fixed skinned axis.\",", + " \"// Positive = falling, negative = rising/jumping.\",", + " \"float signedTailResponse = clamp(\",", + " \" uFurTailVerticalResponse,\",", + " \" -1.0,\",", + " \" 1.0\",", + " \");\",", + " \"float tailFallBlend = clamp(\",", + " \" max(signedTailResponse, 0.0) /\",", + " \" max(\",", + " \" 0.01,\",", + " \" uFurTailFallOverrideResponse\",", + " \" ),\",", + " \" 0.0,\",", + " \" 1.0\",", + " \");\",", + " \"float tailJumpAmount =\",", + " \" max(-signedTailResponse, 0.0);\",", + " \"float tailTipEnvelope = pow(\",", + " \" furT,\",", + " \" max(\",", + " \" 0.1,\",", + " \" uFurTailVerticalTipPower\",", + " \" )\",", + " \");\",", + " \"\",", + " \"// Hanging follows the outside tangent of the surface instead of\",", + " \"// moving through the model. furT=0 keeps the exact root fixed.\",", + " \"float hangT = smoothstep(\",", + " \" clamp(uFurHangStart, 0.0, 0.95),\",", + " \" 1.0,\",", + " \" furT\",", + " \");\",", + " \"float hangInfluence =\",", + " \" hangT * hangT * (3.0 - 2.0 * hangT);\",", + " \"float tailLikeSag =\",", + " \" hangInfluence * (0.55 + 0.45 * furT);\",", + " \"float staticHangAmount =\",", + " \" uFurHangStrength *\",", + " \" furHangScale *\",", + " \" tailLikeSag;\",", + " \"if (stableTailFactor > 0.0001) {\",", + " \" // Tail rest, jump and fall all use live world gravity.\",", + " \" staticHangAmount *=\",", + " \" uFurTailRestHangMultiplier;\",", + " \" float fallLiftAmount =\",", + " \" uFurTailVerticalInfluence *\",", + " \" tailLikeSag *\",", + " \" tailTipEnvelope;\",", + " \" float dynamicTailAmount = mix(\",", + " \" staticHangAmount,\",", + " \" -fallLiftAmount,\",", + " \" tailFallBlend\",", + " \" );\",", + " \" dynamicTailAmount +=\",", + " \" tailJumpAmount *\",", + " \" uFurTailVerticalInfluence *\",", + " \" tailLikeSag *\",", + " \" tailTipEnvelope;\",", + " \" transformed +=\",", + " \" tailRestGravity *\",", + " \" dynamicTailAmount *\",", + " \" stableTailFactor *\",", + " \" uFurLayerLength *\",", + " \" uFurMotionScale;\",", + " \"} else {\",", + " \" transformed += protectedGravity *\",", + " \" staticHangAmount *\",", + " \" uFurLayerLength *\",", + " \" uFurMotionScale;\",", + " \"}\",", + " \"\",", + " \"// A small outward lift prevents long tangential strands from\",", + " \"// numerically touching or entering the source surface.\",", + " \"if (uFurPreventSurfacePenetration > 0.5) {\",", + " \" transformed += safeSurfaceNormal *\",", + " \" uFurSurfaceSafetyLift *\",", + " \" furHangScale *\",", + " \" hangInfluence *\",", + " \" uFurLayerLength *\",", + " \" uFurMotionScale;\",", + " \"}\",", + " \"\",", + " \"vec3 waveAxis = cross(\",", + " \" safeSurfaceNormal,\",", + " \" safeGravity\",", + " \");\",", + " \"if (length(waveAxis) < 0.001) {\",", + " \" waveAxis = cross(\",", + " \" safeSurfaceNormal,\",", + " \" vec3(1.0, 0.0, 0.0)\",", + " \" );\",", + " \"}\",", + " \"waveAxis = normalize(waveAxis);\",", + " \"float waveEnvelope =\",", + " \" sin(3.14159265359 * furT) *\",", + " \" pow(furT, 0.35);\",", + " \"float wavePhase =\",", + " \" uFurTime * uFurWaveSpeed * 6.28318530718 +\",", + " \" furPhase +\",", + " \" furT * uFurWaveAlongHair * 6.28318530718;\",", + " \"float waveSignal =\",", + " \" sin(wavePhase) +\",", + " \" 0.35 * sin(\",", + " \" wavePhase * 1.73 + furPhase * 0.37\",", + " \" );\",", + " \"float waveAmount =\",", + " \" uFurRestWaveAmount +\",", + " \" uFurMovementWaveBoost *\",", + " \" uFurMovementAmount;\",", + " \"transformed += waveAxis *\",", + " \" waveSignal *\",", + " \" waveEnvelope *\",", + " \" uFurWaveAmplitude *\",", + " \" furWaveScale *\",", + " \" waveAmount *\",", + " \" uFurLayerLength *\",", + " \" uFurMotionScale;\"", + " ].join(\"\\n\");", + "", + " shader.vertexShader = shader.vertexShader.replace(", + " \"#include \",", + " beginVertexReplacement", + " );", + "", + " const skinningChunk =", + " \"#include \";", + " if (shader.vertexShader.includes(skinningChunk)) {", + " shader.vertexShader = shader.vertexShader.replace(", + " skinningChunk,", + " skinningChunk + \"\\n\" +", + " postSkinningFurDisplacement", + " );", + " } else {", + " // Compatibility fallback for a custom material without the standard", + " // skinning chunk. Static meshes still receive the displacement.", + " shader.vertexShader = shader.vertexShader.replace(", + " beginVertexReplacement,", + " beginVertexReplacement + \"\\n\" +", + " postSkinningFurDisplacement", + " );", + " }", + "", + " shaderState.uniforms = shader.uniforms;", + " syncFurShaderUniforms(shaderState);", + " };", + "", + " material.customProgramCacheKey = function () {", + " return [", + " \"ParticleFur3D_v189\",", + " layerOptions.kind,", + " layerOptions.segments,", + " layerOptions.planes", + " ].join(\"_\");", + " };", + "", + " material.needsUpdate = true;", + " return material;", + " }", + "", + "", + " function localDirection(source, worldX, worldY, worldZ, target) {", + " target.x = 0;", + " target.y = 0;", + " target.z = 0;", + " if (!source.getWorldPosition || !source.worldToLocal || !source.position || !source.position.clone) return target;", + " if (source.updateMatrixWorld) source.updateMatrixWorld(true);", + " const worldOrigin = source.getWorldPosition(source.position.clone());", + " const worldTarget = worldOrigin.clone();", + " worldTarget.x += worldX;", + " worldTarget.y += worldY;", + " worldTarget.z += worldZ;", + " const localOrigin = source.worldToLocal(worldOrigin.clone());", + " const localTarget = source.worldToLocal(worldTarget.clone());", + " target.x = localTarget.x - localOrigin.x;", + " target.y = localTarget.y - localOrigin.y;", + " target.z = localTarget.z - localOrigin.z;", + " const length = Math.hypot(target.x, target.y, target.z);", + " if (length > 1e-9) {", + " target.x /= length;", + " target.y /= length;", + " target.z /= length;", + " }", + " return target;", + " }", + "", + " function writeVertex(array, vertexIndex, x, y, z) {", + " const offset = vertexIndex * 3;", + " array[offset] = x;", + " array[offset + 1] = y;", + " array[offset + 2] = z;", + " }", + "", + " function normalize3(x, y, z) {", + " const length = Math.hypot(x, y, z);", + " if (length <= 1e-12) return { x: 0, y: 0, z: 1 };", + " return { x: x / length, y: y / length, z: z / length };", + " }", + "", + "", + " function readBindPosition(mesh, index, target) {", + " target.fromBufferAttribute(mesh.geometry.getAttribute(\"position\"), index);", + " return target;", + " }", + "", + " function meshReferenceDimension(", + " mesh,", + " position", + " ) {", + " const geometry = mesh && mesh.geometry;", + " if (!geometry || !position) return 1;", + "", + " if (", + " typeof geometry.computeBoundingBox ===", + " \"function\" &&", + " !geometry.boundingBox", + " ) {", + " geometry.computeBoundingBox();", + " }", + "", + " if (", + " geometry.boundingBox &&", + " geometry.boundingBox.min &&", + " geometry.boundingBox.max", + " ) {", + " const width = Math.abs(", + " geometry.boundingBox.max.x -", + " geometry.boundingBox.min.x", + " );", + " const height = Math.abs(", + " geometry.boundingBox.max.y -", + " geometry.boundingBox.min.y", + " );", + " const depth = Math.abs(", + " geometry.boundingBox.max.z -", + " geometry.boundingBox.min.z", + " );", + " const largest = Math.max(", + " width,", + " height,", + " depth", + " );", + " if (", + " Number.isFinite(largest) &&", + " largest > 1e-8", + " ) {", + " return largest;", + " }", + " }", + "", + " const point = mesh.position.clone();", + " let minimumX = Infinity;", + " let minimumY = Infinity;", + " let minimumZ = Infinity;", + " let maximumX = -Infinity;", + " let maximumY = -Infinity;", + " let maximumZ = -Infinity;", + "", + " const step = Math.max(", + " 1,", + " Math.floor(position.count / 2048)", + " );", + " for (", + " let vertex = 0;", + " vertex < position.count;", + " vertex += step", + " ) {", + " point.fromBufferAttribute(", + " position,", + " vertex", + " );", + " minimumX = Math.min(minimumX, point.x);", + " minimumY = Math.min(minimumY, point.y);", + " minimumZ = Math.min(minimumZ, point.z);", + " maximumX = Math.max(maximumX, point.x);", + " maximumY = Math.max(maximumY, point.y);", + " maximumZ = Math.max(maximumZ, point.z);", + " }", + "", + " const largest = Math.max(", + " maximumX - minimumX,", + " maximumY - minimumY,", + " maximumZ - minimumZ", + " );", + " return (", + " Number.isFinite(largest) &&", + " largest > 1e-8", + " )", + " ? largest", + " : 1;", + " }", + "", + " function effectiveHairUnitScale(", + " mesh,", + " options", + " ) {", + " if (!options.scaleHairToModelSize) {", + " return {", + " referenceDimension: 1,", + " scale: 1", + " };", + " }", + "", + " const position =", + " mesh &&", + " mesh.geometry &&", + " mesh.geometry.getAttribute &&", + " mesh.geometry.getAttribute(\"position\");", + " const referenceDimension =", + " meshReferenceDimension(", + " mesh,", + " position", + " );", + "", + " // Legacy Particle Fur values were tuned for models whose largest local", + " // dimension was close to 1. Never shrink smaller normalized models.", + " const normalizedDimension = Math.max(", + " 1,", + " referenceDimension", + " );", + " const scale = clamp(", + " normalizedDimension *", + " options.modelRelativeSizeMultiplier,", + " 0.001,", + " options.maximumAutomaticHairScale", + " );", + "", + " return {", + " referenceDimension,", + " scale", + " };", + " }", + "", + " function geometryCenter(mesh, position) {", + " const center = mesh.position.clone();", + " center.set(0, 0, 0);", + "", + " const geometry = mesh.geometry;", + " if (", + " geometry &&", + " typeof geometry.computeBoundingBox === \"function\" &&", + " !geometry.boundingBox", + " ) {", + " geometry.computeBoundingBox();", + " }", + "", + " if (", + " geometry &&", + " geometry.boundingBox &&", + " geometry.boundingBox.min &&", + " geometry.boundingBox.max", + " ) {", + " center", + " .copy(geometry.boundingBox.min)", + " .add(geometry.boundingBox.max)", + " .multiplyScalar(0.5);", + " return center;", + " }", + "", + " if (!position || !position.count) return center;", + "", + " const point = mesh.position.clone();", + " let minimumX = Infinity;", + " let minimumY = Infinity;", + " let minimumZ = Infinity;", + " let maximumX = -Infinity;", + " let maximumY = -Infinity;", + " let maximumZ = -Infinity;", + "", + " const step = Math.max(", + " 1,", + " Math.floor(position.count / 2048)", + " );", + " for (", + " let vertex = 0;", + " vertex < position.count;", + " vertex += step", + " ) {", + " point.fromBufferAttribute(position, vertex);", + " minimumX = Math.min(minimumX, point.x);", + " minimumY = Math.min(minimumY, point.y);", + " minimumZ = Math.min(minimumZ, point.z);", + " maximumX = Math.max(maximumX, point.x);", + " maximumY = Math.max(maximumY, point.y);", + " maximumZ = Math.max(maximumZ, point.z);", + " }", + "", + " if (", + " Number.isFinite(", + " minimumX + minimumY + minimumZ +", + " maximumX + maximumY + maximumZ", + " )", + " ) {", + " center.set(", + " (minimumX + maximumX) * 0.5,", + " (minimumY + maximumY) * 0.5,", + " (minimumZ + maximumZ) * 0.5", + " );", + " }", + " return center;", + " }", + "", + " function outwardScoreFromVertexNormals(", + " mesh,", + " position,", + " normalAttribute,", + " center", + " ) {", + " if (", + " !position ||", + " !normalAttribute ||", + " position.count !== normalAttribute.count", + " ) {", + " return {", + " score: 0,", + " samples: 0,", + " source: \"none\"", + " };", + " }", + "", + " const point = mesh.position.clone();", + " const normal = mesh.position.clone();", + " let score = 0;", + " let samples = 0;", + " const step = Math.max(", + " 1,", + " Math.floor(position.count / 768)", + " );", + "", + " for (", + " let vertex = 0;", + " vertex < position.count;", + " vertex += step", + " ) {", + " point.fromBufferAttribute(position, vertex);", + " normal.fromBufferAttribute(", + " normalAttribute,", + " vertex", + " );", + "", + " const offsetX = point.x - center.x;", + " const offsetY = point.y - center.y;", + " const offsetZ = point.z - center.z;", + " const offsetLength = Math.hypot(", + " offsetX,", + " offsetY,", + " offsetZ", + " );", + " const normalLength = Math.hypot(", + " normal.x,", + " normal.y,", + " normal.z", + " );", + "", + " if (", + " offsetLength <= 1e-7 ||", + " normalLength <= 1e-7", + " ) {", + " continue;", + " }", + "", + " const dot =", + " (", + " normal.x * offsetX +", + " normal.y * offsetY +", + " normal.z * offsetZ", + " ) /", + " (normalLength * offsetLength);", + "", + " if (!Number.isFinite(dot)) continue;", + " score += clamp(dot, -1, 1);", + " samples++;", + " }", + "", + " return {", + " score: samples ? score / samples : 0,", + " samples,", + " source: \"vertex normals\"", + " };", + " }", + "", + " function outwardScoreFromTriangleWinding(", + " mesh,", + " position,", + " center", + " ) {", + " if (!position || position.count < 3) {", + " return {", + " score: 0,", + " samples: 0,", + " source: \"none\"", + " };", + " }", + "", + " const geometry = mesh.geometry;", + " const index = geometry.index;", + " const valueCount = index", + " ? index.count", + " : position.count;", + " const triangleCount = Math.floor(", + " valueCount / 3", + " );", + " const triangleStep = Math.max(", + " 1,", + " Math.floor(triangleCount / 512)", + " );", + "", + " const a = mesh.position.clone();", + " const b = mesh.position.clone();", + " const c = mesh.position.clone();", + "", + " let score = 0;", + " let samples = 0;", + "", + " for (", + " let triangle = 0;", + " triangle < triangleCount;", + " triangle += triangleStep", + " ) {", + " const start = triangle * 3;", + " const ia = index", + " ? index.getX(start)", + " : start;", + " const ib = index", + " ? index.getX(start + 1)", + " : start + 1;", + " const ic = index", + " ? index.getX(start + 2)", + " : start + 2;", + "", + " a.fromBufferAttribute(position, ia);", + " b.fromBufferAttribute(position, ib);", + " c.fromBufferAttribute(position, ic);", + "", + " const abX = b.x - a.x;", + " const abY = b.y - a.y;", + " const abZ = b.z - a.z;", + " const acX = c.x - a.x;", + " const acY = c.y - a.y;", + " const acZ = c.z - a.z;", + "", + " const normalX = abY * acZ - abZ * acY;", + " const normalY = abZ * acX - abX * acZ;", + " const normalZ = abX * acY - abY * acX;", + " const normalLength = Math.hypot(", + " normalX,", + " normalY,", + " normalZ", + " );", + " if (normalLength <= 1e-12) continue;", + "", + " const centroidX =", + " (a.x + b.x + c.x) / 3 - center.x;", + " const centroidY =", + " (a.y + b.y + c.y) / 3 - center.y;", + " const centroidZ =", + " (a.z + b.z + c.z) / 3 - center.z;", + " const centroidLength = Math.hypot(", + " centroidX,", + " centroidY,", + " centroidZ", + " );", + " if (centroidLength <= 1e-7) continue;", + "", + " const dot =", + " (", + " normalX * centroidX +", + " normalY * centroidY +", + " normalZ * centroidZ", + " ) /", + " (normalLength * centroidLength);", + "", + " if (!Number.isFinite(dot)) continue;", + " score += clamp(dot, -1, 1);", + " samples++;", + " }", + "", + " return {", + " score: samples ? score / samples : 0,", + " samples,", + " source: \"triangle winding\"", + " };", + " }", + "", + " function determineMeshNormalDirection(", + " mesh,", + " options", + " ) {", + " const geometry = mesh.geometry;", + " const position =", + " geometry &&", + " geometry.getAttribute &&", + " geometry.getAttribute(\"position\");", + " const normalAttribute =", + " geometry &&", + " geometry.getAttribute &&", + " geometry.getAttribute(\"normal\");", + "", + " let automaticSign = 1;", + " let result = {", + " score: 0,", + " samples: 0,", + " source: \"disabled\"", + " };", + " const center = geometryCenter(", + " mesh,", + " position", + " );", + "", + " if (", + " options.autoCorrectInwardNormals &&", + " position", + " ) {", + " result = outwardScoreFromVertexNormals(", + " mesh,", + " position,", + " normalAttribute,", + " center", + " );", + "", + " // Open or very flat meshes can make center-based vertex-normal", + " // scoring ambiguous. In that case use triangle winding as fallback.", + " if (", + " result.samples < 8 ||", + " Math.abs(result.score) < 0.055", + " ) {", + " const windingResult =", + " outwardScoreFromTriangleWinding(", + " mesh,", + " position,", + " center", + " );", + " if (", + " windingResult.samples >= result.samples ||", + " Math.abs(windingResult.score) >", + " Math.abs(result.score)", + " ) {", + " result = windingResult;", + " }", + " }", + "", + " if (", + " result.samples >= 4 &&", + " result.score < -0.055", + " ) {", + " automaticSign = -1;", + " }", + " }", + "", + " const manualSign =", + " options.invertSurfaceNormals", + " ? -1", + " : 1;", + " const sign = automaticSign * manualSign;", + "", + " return {", + " sign,", + " wasAutomaticallyFlipped:", + " automaticSign < 0,", + " wasManuallyInverted:", + " manualSign < 0,", + " score: result.score,", + " samples: result.samples,", + " source: result.source,", + " centerX: center.x,", + " centerY: center.y,", + " centerZ: center.z", + " };", + " }", + "", + " function createCandidateList(", + " meshes,", + " options", + " ) {", + " const rawCandidates = [];", + " const topBackRawCandidates = [];", + " const backHeadRawCandidates = [];", + " const regionRawCandidates = {", + " body: [],", + " tail: [],", + " leg: [],", + " paw: [],", + " ear: [],", + " head: []", + " };", + " const missingGroups = [];", + " const normalDiagnostics = [];", + " const maskDiagnostics = [];", + " let flippedNormalMeshCount = 0;", + "", + " for (const mesh of meshes) {", + " const geometry = mesh.geometry;", + " const position =", + " geometry &&", + " geometry.getAttribute &&", + " geometry.getAttribute(\"position\");", + " if (!position || position.count < 3) continue;", + "", + " const normalDirection =", + " determineMeshNormalDirection(", + " mesh,", + " options", + " );", + " const hairScale =", + " effectiveHairUnitScale(", + " mesh,", + " options", + " );", + " if (normalDirection.sign < 0) {", + " flippedNormalMeshCount++;", + " }", + " normalDiagnostics.push({", + " meshName:", + " mesh.name || \"(unnamed mesh)\",", + " sign: normalDirection.sign,", + " score: normalDirection.score,", + " samples: normalDirection.samples,", + " source: normalDirection.source,", + " automatic:", + " normalDirection.wasAutomaticallyFlipped,", + " manual:", + " normalDirection.wasManuallyInverted", + " });", + "", + " let resolved = resolveWeights(", + " mesh,", + " options", + " );", + "", + " let tailRegionWeights =", + " resolveOptionalCombinedWeights(", + " mesh,", + " options.tailRegionGroupName,", + " position.count", + " );", + " let legRegionWeights =", + " resolveOptionalCombinedWeights(", + " mesh,", + " options.legRegionGroupName,", + " position.count", + " );", + " let pawRegionWeights =", + " resolveOptionalCombinedWeights(", + " mesh,", + " options.pawRegionGroupName,", + " position.count", + " );", + " let earRegionWeights =", + " resolveOptionalCombinedWeights(", + " mesh,", + " options.earRegionGroupName,", + " position.count", + " );", + " let headRegionWeights =", + " resolveOptionalCombinedWeights(", + " mesh,", + " options.headRegionGroupName,", + " position.count", + " );", + " let topBackWeights =", + " resolveOptionalCombinedWeights(", + " mesh,", + " options.topBackGroupName,", + " position.count", + " );", + " let longCoatWeights =", + " resolveOptionalCombinedWeights(", + " mesh,", + " options.longCoatGroupName,", + " position.count", + " );", + " let headHairLengthWeights =", + " resolveOptionalCombinedWeights(", + " mesh,", + " options.headHairLengthGroupName,", + " position.count", + " );", + " const noseBridgeHairLengthWeights =", + " resolveOptionalCombinedWeights(", + " mesh,", + " options.noseBridgeHairLengthGroupName,", + " position.count", + " );", + " const innerEarsHairLengthWeights =", + " resolveOptionalCombinedWeights(", + " mesh,", + " options.innerEarsHairLengthGroupName,", + " position.count", + " );", + "", + " let bodyReferenceWeights =", + " resolveOptionalCombinedWeights(", + " mesh,", + " \"_VG_BODY,VG_BODY,BODY,body,torso\",", + " position.count", + " );", + " let profileFeetWeights =", + " resolveOptionalCombinedWeights(", + " mesh,", + " \"_VG_FEET,VG_FEET,FEET,feet,foot\",", + " position.count", + " );", + " let profilePawWeights =", + " resolveOptionalCombinedWeights(", + " mesh,", + " \"_VG_PAWS,VG_PAWS,PAWS,paws,paw,toes,toe\",", + " position.count", + " );", + " let profileHeadWeights =", + " resolveOptionalCombinedWeights(", + " mesh,", + " \"_VG_HEAD,VG_HEAD,HEAD,head\",", + " position.count", + " );", + " let profileEarWeights =", + " resolveOptionalCombinedWeights(", + " mesh,", + " \"_VG_EARS,VG_EARS,EARS,ears,ear\",", + " position.count", + " );", + " let profileTailWeights =", + " resolveOptionalCombinedWeights(", + " mesh,", + " \"_VG_TAIL,VG_TAIL,TAIL,tail\",", + " position.count", + " );", + " let profileLongCoatWeights =", + " resolveOptionalCombinedWeights(", + " mesh,", + " \"_VG_LONGFUR,VG_LONGFUR,LONGFUR,longfur,long_fur\",", + " position.count", + " );", + "", + " if (options.autoMapCommonFurGroups) {", + " // The uploaded model contains separate FEET and PAWS attributes.", + " // FEET belongs to the leg region; PAWS belongs to toes/paws only.", + " // Keeping them separate prevents the paw root budget from being", + " // diluted across the complete lower legs.", + " if (profileFeetWeights) {", + " legRegionWeights =", + " profileFeetWeights;", + " }", + " if (profilePawWeights) {", + " pawRegionWeights =", + " profilePawWeights;", + " }", + " if (profileHeadWeights) {", + " headRegionWeights =", + " profileHeadWeights;", + " headHairLengthWeights =", + " profileHeadWeights;", + " }", + " if (profileEarWeights) {", + " earRegionWeights =", + " profileEarWeights;", + " }", + " if (profileTailWeights) {", + " tailRegionWeights =", + " profileTailWeights;", + " }", + " if (profileLongCoatWeights) {", + " longCoatWeights =", + " profileLongCoatWeights;", + " }", + " }", + "", + " if (", + " options.expandRegionalMasks &&", + " options.regionalMaskExpansionRings > 0", + " ) {", + " pawRegionWeights = expandVertexMask(", + " geometry,", + " pawRegionWeights,", + " options.regionalMaskExpansionRings,", + " options.regionalMaskExpansionFalloff", + " );", + " headRegionWeights = expandVertexMask(", + " geometry,", + " headRegionWeights,", + " options.regionalMaskExpansionRings,", + " options.regionalMaskExpansionFalloff", + " );", + " headHairLengthWeights = expandVertexMask(", + " geometry,", + " headHairLengthWeights,", + " options.regionalMaskExpansionRings,", + " options.regionalMaskExpansionFalloff", + " );", + " topBackWeights = expandVertexMask(", + " geometry,", + " topBackWeights,", + " options.topBackCoverageExpansionRings,", + " options.topBackCoverageExpansionFalloff", + " );", + " }", + "", + " if (", + " options.bridgeRegionalMaskSeams", + " ) {", + " const referenceDimension =", + " meshReferenceDimension(", + " mesh,", + " position", + " );", + " const bridgeRadius =", + " referenceDimension *", + " options.regionalSeamBridgeRadius;", + "", + " pawRegionWeights =", + " bridgeMaskAcrossNearbySeams(", + " geometry,", + " pawRegionWeights,", + " bridgeRadius,", + " options.regionalSeamBridgeFalloff,", + " options.groupThreshold * 0.2", + " );", + " headRegionWeights =", + " bridgeMaskAcrossNearbySeams(", + " geometry,", + " headRegionWeights,", + " bridgeRadius,", + " options.regionalSeamBridgeFalloff,", + " options.groupThreshold * 0.2", + " );", + " headHairLengthWeights =", + " bridgeMaskAcrossNearbySeams(", + " geometry,", + " headHairLengthWeights,", + " bridgeRadius,", + " options.regionalSeamBridgeFalloff,", + " options.groupThreshold * 0.2", + " );", + " topBackWeights =", + " bridgeMaskAcrossNearbySeams(", + " geometry,", + " topBackWeights,", + " bridgeRadius,", + " options.regionalSeamBridgeFalloff,", + " options.groupThreshold * 0.2", + " );", + " }", + "", + " const automaticTopBackWeights =", + " createAutomaticTopBackMask(", + " mesh,", + " geometry,", + " position,", + " resolved", + " ? resolved.weights", + " : null,", + " bodyReferenceWeights,", + " pawRegionWeights,", + " options", + " );", + " topBackWeights = mergeMasksMaximum(", + " topBackWeights,", + " automaticTopBackWeights,", + " position.count,", + " \"combined top/back coverage\"", + " );", + "", + " let backHeadWeights =", + " createAutomaticBackHeadMask(", + " mesh,", + " position,", + " headRegionWeights,", + " bodyReferenceWeights,", + " options", + " );", + "", + " if (", + " backHeadWeights &&", + " options.expandRegionalMasks", + " ) {", + " backHeadWeights = expandVertexMask(", + " geometry,", + " backHeadWeights,", + " options.backHeadExpansionRings,", + " options.backHeadExpansionFalloff", + " );", + " }", + "", + " if (", + " backHeadWeights &&", + " options.bridgeRegionalMaskSeams", + " ) {", + " const referenceDimension =", + " meshReferenceDimension(", + " mesh,", + " position", + " );", + " backHeadWeights =", + " bridgeMaskAcrossNearbySeams(", + " geometry,", + " backHeadWeights,", + " referenceDimension *", + " options.regionalSeamBridgeRadius,", + " options.regionalSeamBridgeFalloff,", + " options.groupThreshold * 0.1", + " );", + " }", + "", + " topBackWeights = mergeMasksMaximum(", + " topBackWeights,", + " backHeadWeights,", + " position.count,", + " \"back-head plus top/back coverage\"", + " );", + "", + " if (options.regionalMasksExtendCoverage) {", + " const extensionResult =", + " extendCoverageWithMasks(", + " resolved,", + " [", + " tailRegionWeights,", + " legRegionWeights,", + " pawRegionWeights,", + " earRegionWeights,", + " headRegionWeights,", + " topBackWeights,", + " longCoatWeights,", + " headHairLengthWeights,", + " noseBridgeHairLengthWeights,", + " innerEarsHairLengthWeights", + " ],", + " position.count", + " );", + " resolved = extensionResult.resolved;", + "", + " // Keep a zero-weight candidate source so recognized bone regions can", + " // add fur even when the main coverage group is absent on this mesh.", + " if (", + " !resolved &&", + " options.autoRegionBoneDetection &&", + " mesh.isSkinnedMesh", + " ) {", + " resolved = createZeroCoverage(", + " position.count,", + " \"automatic regional bone coverage\"", + " );", + " }", + " }", + "", + " maskDiagnostics.push({", + " meshName:", + " mesh.name || \"(unnamed mesh)\",", + " referenceDimension:", + " hairScale.referenceDimension,", + " hairUnitScale:", + " hairScale.scale,", + " effectiveOuterLength:", + " options.outerLength *", + " hairScale.scale,", + " effectiveUndercoatLength:", + " options.undercoatLength *", + " hairScale.scale,", + " attributes:", + " availableAttributeNames(geometry),", + " coverage:", + " resolved", + " ? String(resolved.source || \"resolved\")", + " : (", + " options.vertexGroupName", + " ? (", + " \"MISSING [\" +", + " options.vertexGroupName +", + " \"]\"", + " )", + " : \"whole mesh\"", + " ),", + " tail:", + " describeMask(", + " options.tailRegionGroupName,", + " tailRegionWeights", + " ),", + " leg:", + " describeMask(", + " options.legRegionGroupName,", + " legRegionWeights", + " ),", + " paw:", + " describeMask(", + " options.pawRegionGroupName,", + " pawRegionWeights", + " ),", + " ear:", + " describeMask(", + " options.earRegionGroupName,", + " earRegionWeights", + " ),", + " head:", + " describeMask(", + " options.headRegionGroupName,", + " headRegionWeights", + " ),", + " topBack:", + " describeMask(", + " options.topBackGroupName,", + " topBackWeights", + " ),", + " backHead:", + " describeMask(", + " \"automatic HEAD-to-BODY\",", + " backHeadWeights", + " ),", + " longCoat:", + " describeMask(", + " options.longCoatGroupName,", + " longCoatWeights", + " ),", + " headLength:", + " describeMask(", + " options.headHairLengthGroupName,", + " headHairLengthWeights", + " ),", + " noseLength:", + " describeMask(", + " options.noseBridgeHairLengthGroupName,", + " noseBridgeHairLengthWeights", + " ),", + " innerEarLength:", + " describeMask(", + " options.innerEarsHairLengthGroupName,", + " innerEarsHairLengthWeights", + " )", + " });", + "", + " if (!resolved) {", + " missingGroups.push(", + " (mesh.name || \"(unnamed mesh)\") +", + " \": \" +", + " String(options.vertexGroupName || \"\")", + " );", + " continue;", + " }", + "", + " const index = geometry.index;", + " const triangleValueCount =", + " index ? index.count : position.count;", + " const va = mesh.position.clone();", + " const vb = mesh.position.clone();", + " const vc = mesh.position.clone();", + "", + " for (", + " let triangleStart = 0;", + " triangleStart + 2 < triangleValueCount;", + " triangleStart += 3", + " ) {", + " const ia = index", + " ? index.getX(triangleStart)", + " : triangleStart;", + " const ib = index", + " ? index.getX(triangleStart + 1)", + " : triangleStart + 1;", + " const ic = index", + " ? index.getX(triangleStart + 2)", + " : triangleStart + 2;", + "", + " let wa = resolved.weights[ia] || 0;", + " let wb = resolved.weights[ib] || 0;", + " let wc = resolved.weights[ic] || 0;", + "", + " const automaticRegion =", + " triangleBoneRegion(", + " mesh,", + " ia,", + " ib,", + " ic,", + " options", + " );", + "", + " if (", + " options.regionalMasksExtendCoverage &&", + " automaticRegion !== \"body\"", + " ) {", + " wa = Math.max(wa, 1);", + " wb = Math.max(wb, 1);", + " wc = Math.max(wc, 1);", + " }", + "", + " const averageWeight =", + " (wa + wb + wc) / 3;", + " const maximumWeight = Math.max(", + " wa,", + " wb,", + " wc", + " );", + " if (", + " maximumWeight <", + " options.groupThreshold", + " ) {", + " continue;", + " }", + "", + " readBindPosition(mesh, ia, va);", + " readBindPosition(mesh, ib, vb);", + " readBindPosition(mesh, ic, vc);", + "", + " const abx = vb.x - va.x;", + " const aby = vb.y - va.y;", + " const abz = vb.z - va.z;", + " const acx = vc.x - va.x;", + " const acy = vc.y - va.y;", + " const acz = vc.z - va.z;", + " const crossX =", + " aby * acz - abz * acy;", + " const crossY =", + " abz * acx - abx * acz;", + " const crossZ =", + " abx * acy - aby * acx;", + " const area =", + " 0.5 *", + " Math.hypot(", + " crossX,", + " crossY,", + " crossZ", + " );", + " if (", + " !Number.isFinite(area) ||", + " area <= 1e-12", + " ) {", + " continue;", + " }", + "", + " const tailWeight = tailRegionWeights", + " ? (", + " (tailRegionWeights[ia] || 0) +", + " (tailRegionWeights[ib] || 0) +", + " (tailRegionWeights[ic] || 0)", + " ) / 3", + " : 0;", + " const legWeight = legRegionWeights", + " ? (", + " (legRegionWeights[ia] || 0) +", + " (legRegionWeights[ib] || 0) +", + " (legRegionWeights[ic] || 0)", + " ) / 3", + " : 0;", + " const pawWeight = pawRegionWeights", + " ? (", + " (pawRegionWeights[ia] || 0) +", + " (pawRegionWeights[ib] || 0) +", + " (pawRegionWeights[ic] || 0)", + " ) / 3", + " : 0;", + " const earWeight = earRegionWeights", + " ? (", + " (earRegionWeights[ia] || 0) +", + " (earRegionWeights[ib] || 0) +", + " (earRegionWeights[ic] || 0)", + " ) / 3", + " : 0;", + " const headWeight = headRegionWeights", + " ? (", + " (headRegionWeights[ia] || 0) +", + " (headRegionWeights[ib] || 0) +", + " (headRegionWeights[ic] || 0)", + " ) / 3", + " : 0;", + " const topBackWeight =", + " topBackWeights", + " ? (", + " (topBackWeights[ia] || 0) +", + " (topBackWeights[ib] || 0) +", + " (topBackWeights[ic] || 0)", + " ) / 3", + " : 0;", + " const backHeadWeight =", + " backHeadWeights", + " ? (", + " (backHeadWeights[ia] || 0) +", + " (backHeadWeights[ib] || 0) +", + " (backHeadWeights[ic] || 0)", + " ) / 3", + " : 0;", + "", + " const region =", + " chooseExplicitRegion(", + " tailWeight,", + " legWeight,", + " pawWeight,", + " earWeight,", + " headWeight,", + " automaticRegion", + " );", + "", + " const longWa = longCoatWeights", + " ? longCoatWeights[ia] || 0", + " : 0;", + " const longWb = longCoatWeights", + " ? longCoatWeights[ib] || 0", + " : 0;", + " const longWc = longCoatWeights", + " ? longCoatWeights[ic] || 0", + " : 0;", + " const longAverage =", + " (longWa + longWb + longWc) / 3;", + "", + " const headLengthWa = headHairLengthWeights", + " ? headHairLengthWeights[ia] || 0", + " : 0;", + " const headLengthWb = headHairLengthWeights", + " ? headHairLengthWeights[ib] || 0", + " : 0;", + " const headLengthWc = headHairLengthWeights", + " ? headHairLengthWeights[ic] || 0", + " : 0;", + "", + " const noseBridgeLengthWa =", + " noseBridgeHairLengthWeights", + " ? noseBridgeHairLengthWeights[ia] || 0", + " : 0;", + " const noseBridgeLengthWb =", + " noseBridgeHairLengthWeights", + " ? noseBridgeHairLengthWeights[ib] || 0", + " : 0;", + " const noseBridgeLengthWc =", + " noseBridgeHairLengthWeights", + " ? noseBridgeHairLengthWeights[ic] || 0", + " : 0;", + "", + " const innerEarsLengthWa =", + " innerEarsHairLengthWeights", + " ? innerEarsHairLengthWeights[ia] || 0", + " : 0;", + " const innerEarsLengthWb =", + " innerEarsHairLengthWeights", + " ? innerEarsHairLengthWeights[ib] || 0", + " : 0;", + " const innerEarsLengthWc =", + " innerEarsHairLengthWeights", + " ? innerEarsHairLengthWeights[ic] || 0", + " : 0;", + "", + " const maskWeight = Math.max(", + " averageWeight,", + " maximumWeight * 0.15,", + " 0.0001", + " );", + " const regionDensity =", + " densityMultiplierForRegion(", + " region,", + " options", + " );", + " const longCoatDensity =", + " 1 +", + " (", + " options.longCoatDensityMultiplier -", + " 1", + " ) *", + " clamp(longAverage, 0, 1);", + " const topBackDensity =", + " 1 +", + " (", + " options.topBackDensityMultiplier -", + " 1", + " ) *", + " clamp(", + " topBackWeight,", + " 0,", + " 1", + " );", + " const backHeadDensity =", + " 1 +", + " (", + " options.backHeadDensityMultiplier -", + " 1", + " ) *", + " clamp(", + " backHeadWeight,", + " 0,", + " 1", + " );", + "", + " const candidate = {", + " mesh,", + " ia,", + " ib,", + " ic,", + " wa,", + " wb,", + " wc,", + " longWa,", + " longWb,", + " longWc,", + " headLengthWa,", + " headLengthWb,", + " headLengthWc,", + " noseBridgeLengthWa,", + " noseBridgeLengthWb,", + " noseBridgeLengthWc,", + " innerEarsLengthWa,", + " innerEarsLengthWb,", + " innerEarsLengthWc,", + " tailRegionWeight: tailWeight,", + " legRegionWeight: legWeight,", + " pawRegionWeight: pawWeight,", + " earRegionWeight: earWeight,", + " headRegionWeight: headWeight,", + " topBackWeight,", + " backHeadWeight,", + " automaticRegion,", + " region,", + " normalSign:", + " normalDirection.sign,", + " normalDetectionScore:", + " normalDirection.score,", + " meshCenterX:", + " normalDirection.centerX,", + " meshCenterY:", + " normalDirection.centerY,", + " meshCenterZ:", + " normalDirection.centerZ,", + " materialIndex:", + " materialIndexForTriangle(", + " geometry,", + " triangleStart", + " ),", + " maskSource: resolved.source,", + " selectionWeight:", + " area *", + " maskWeight *", + " regionDensity *", + " longCoatDensity *", + " topBackDensity *", + " backHeadDensity", + " };", + "", + " rawCandidates.push(candidate);", + " regionRawCandidates[region].push(", + " candidate", + " );", + " if (", + " topBackWeight >=", + " options.topBackPoolThreshold", + " ) {", + " topBackRawCandidates.push(", + " candidate", + " );", + " }", + " if (", + " backHeadWeight >=", + " options.backHeadPoolThreshold", + " ) {", + " backHeadRawCandidates.push(", + " candidate", + " );", + " }", + " }", + " }", + "", + " const globalPool =", + " makeCandidatePool(rawCandidates);", + " const topBackPool =", + " makeCandidatePool(", + " topBackRawCandidates", + " );", + " const backHeadPool =", + " makeCandidatePool(", + " backHeadRawCandidates", + " );", + " const regionPools = {};", + " for (const region of [", + " \"body\",", + " \"tail\",", + " \"leg\",", + " \"paw\",", + " \"ear\",", + " \"head\"", + " ]) {", + " regionPools[region] =", + " makeCandidatePool(", + " regionRawCandidates[region]", + " );", + " }", + "", + " return {", + " candidates: globalPool.entries,", + " totalWeight: globalPool.totalWeight,", + " regionPools,", + " topBackPool,", + " backHeadPool,", + " missingGroups,", + " normalDiagnostics,", + " maskDiagnostics,", + " flippedNormalMeshCount", + " };", + " }", + "", + "", + " function aggregateRootSkin(mesh, ia, ib, ic, ba, bb, bc) {", + " if (", + " !mesh.isSkinnedMesh ||", + " !mesh.geometry ||", + " !mesh.skeleton", + " ) {", + " return null;", + " }", + " const skinIndex =", + " mesh.geometry.getAttribute(\"skinIndex\");", + " const skinWeight =", + " mesh.geometry.getAttribute(\"skinWeight\");", + " if (!skinIndex || !skinWeight) return null;", + "", + " const boneCount = Math.max(", + " 1,", + " mesh.skeleton.bones.length", + " );", + " const totals = new Map();", + " const addVertex = (vertexIndex, barycentricWeight) => {", + " if (barycentricWeight <= 0) return;", + " for (let componentIndex = 0; componentIndex < 4; componentIndex++) {", + " const rawBoneIndex = component(", + " skinIndex,", + " vertexIndex,", + " componentIndex", + " );", + " const rawWeight = component(", + " skinWeight,", + " vertexIndex,", + " componentIndex", + " );", + " if (", + " !Number.isFinite(rawBoneIndex) ||", + " !Number.isFinite(rawWeight)", + " ) {", + " continue;", + " }", + "", + " const boneIndex =", + " Math.round(rawBoneIndex);", + " if (", + " boneIndex < 0 ||", + " boneIndex >= boneCount", + " ) {", + " continue;", + " }", + "", + " const contribution =", + " clamp(rawWeight, 0, 1) *", + " barycentricWeight;", + " if (", + " !Number.isFinite(contribution) ||", + " contribution <= 0", + " ) {", + " continue;", + " }", + " totals.set(", + " boneIndex,", + " (totals.get(boneIndex) || 0) +", + " contribution", + " );", + " }", + " };", + "", + " addVertex(ia, ba);", + " addVertex(ib, bb);", + " addVertex(ic, bc);", + "", + " let entries = Array.from(totals.entries()).sort((a, b) => b[1] - a[1]).slice(0, 4);", + " if (!entries.length) entries = [[0, 1]];", + " let sum = entries.reduce((value, entry) => value + entry[1], 0);", + " if (!Number.isFinite(sum) || sum <= 1e-12) {", + " entries = [[0, 1]];", + " sum = 1;", + " }", + "", + " const indices = [0, 0, 0, 0];", + " const weights = [0, 0, 0, 0];", + " for (let index = 0; index < entries.length; index++) {", + " indices[index] = entries[index][0];", + " weights[index] = entries[index][1] / sum;", + " }", + " return { indices, weights };", + " }", + "", + " function createRoot(mesh, candidate, ba, bb, bc, groupWeight, longCoatWeight, headHairLengthWeight, noseBridgeHairLengthWeight, innerEarsHairLengthWeight, options) {", + " const position = mesh.geometry.getAttribute(\"position\");", + " const normalAttribute = mesh.geometry.getAttribute(\"normal\");", + " const a = mesh.position.clone().fromBufferAttribute(position, candidate.ia);", + " const b = mesh.position.clone().fromBufferAttribute(position, candidate.ib);", + " const c = mesh.position.clone().fromBufferAttribute(position, candidate.ic);", + "", + " const rootX = a.x * ba + b.x * bb + c.x * bc;", + " const rootY = a.y * ba + b.y * bb + c.y * bc;", + " const rootZ = a.z * ba + b.z * bb + c.z * bc;", + "", + " let normal;", + " if (normalAttribute) {", + " const na = mesh.position.clone().fromBufferAttribute(normalAttribute, candidate.ia);", + " const nb = mesh.position.clone().fromBufferAttribute(normalAttribute, candidate.ib);", + " const nc = mesh.position.clone().fromBufferAttribute(normalAttribute, candidate.ic);", + " normal = normalize3(", + " na.x * ba + nb.x * bb + nc.x * bc,", + " na.y * ba + nb.y * bb + nc.y * bc,", + " na.z * ba + nb.z * bb + nc.z * bc", + " );", + " } else {", + " const abx = b.x - a.x;", + " const aby = b.y - a.y;", + " const abz = b.z - a.z;", + " const acx = c.x - a.x;", + " const acy = c.y - a.y;", + " const acz = c.z - a.z;", + " normal = normalize3(", + " aby * acz - abz * acy,", + " abz * acx - abx * acz,", + " abx * acy - aby * acx", + " );", + " }", + "", + " const normalSign =", + " candidate.normalSign === -1", + " ? -1", + " : 1;", + " normal = normalize3(", + " normal.x * normalSign,", + " normal.y * normalSign,", + " normal.z * normalSign", + " );", + "", + " const abX = b.x - a.x;", + " const abY = b.y - a.y;", + " const abZ = b.z - a.z;", + " const acX = c.x - a.x;", + " const acY = c.y - a.y;", + " const acZ = c.z - a.z;", + "", + " let faceNormal = normalize3(", + " (", + " abY * acZ -", + " abZ * acY", + " ) * normalSign,", + " (", + " abZ * acX -", + " abX * acZ", + " ) * normalSign,", + " (", + " abX * acY -", + " abY * acX", + " ) * normalSign", + " );", + "", + " if (options.perRootOutwardCorrection) {", + " let agreement =", + " normal.x * faceNormal.x +", + " normal.y * faceNormal.y +", + " normal.z * faceNormal.z;", + "", + " if (", + " options.trustImportedNormals &&", + " normalAttribute", + " ) {", + " // A valid glTF normal and the triangle winding describe the local", + " // surface more reliably than a vector from the center of a concave", + " // animal mesh. The old center test inverted correct normals on paws", + " // and on the rear-facing surface of the head.", + " if (agreement < 0) {", + " faceNormal = normalize3(", + " -faceNormal.x,", + " -faceNormal.y,", + " -faceNormal.z", + " );", + " agreement = -agreement;", + " }", + "", + " const minimumAgreement =", + " options.minimumFaceNormalAgreement;", + " if (", + " agreement < minimumAgreement &&", + " minimumAgreement < 0.999", + " ) {", + " const blend = clamp(", + " (", + " minimumAgreement -", + " agreement", + " ) /", + " Math.max(", + " 0.0001,", + " 1 - agreement", + " ),", + " 0,", + " 1", + " );", + " normal = normalize3(", + " normal.x * (1 - blend) +", + " faceNormal.x * blend,", + " normal.y * (1 - blend) +", + " faceNormal.y * blend,", + " normal.z * (1 - blend) +", + " faceNormal.z * blend", + " );", + " }", + " } else {", + " // Legacy fallback for models that do not contain usable normals.", + " const outward = normalize3(", + " rootX -", + " numberOr(candidate.meshCenterX, 0),", + " rootY -", + " numberOr(candidate.meshCenterY, 0),", + " rootZ -", + " numberOr(candidate.meshCenterZ, 0)", + " );", + "", + " if (", + " Number.isFinite(", + " outward.x + outward.y + outward.z", + " ) &&", + " (", + " faceNormal.x * outward.x +", + " faceNormal.y * outward.y +", + " faceNormal.z * outward.z", + " ) < 0", + " ) {", + " faceNormal = normalize3(", + " -faceNormal.x,", + " -faceNormal.y,", + " -faceNormal.z", + " );", + " }", + "", + " agreement =", + " normal.x * faceNormal.x +", + " normal.y * faceNormal.y +", + " normal.z * faceNormal.z;", + "", + " if (agreement < 0) {", + " normal = normalize3(", + " -normal.x,", + " -normal.y,", + " -normal.z", + " );", + " }", + " }", + " }", + "", + " const edgeX = abX;", + " const edgeY = abY;", + " const edgeZ = abZ;", + " const edgeDotNormal = edgeX * normal.x + edgeY * normal.y + edgeZ * normal.z;", + " let tangent = normalize3(", + " edgeX - normal.x * edgeDotNormal,", + " edgeY - normal.y * edgeDotNormal,", + " edgeZ - normal.z * edgeDotNormal", + " );", + " if (!Number.isFinite(tangent.x + tangent.y + tangent.z)) {", + " tangent = normalize3(normal.y, -normal.x, 0);", + " }", + " const tangent2 = normalize3(", + " normal.y * tangent.z - normal.z * tangent.y,", + " normal.z * tangent.x - normal.x * tangent.z,", + " normal.x * tangent.y - normal.y * tangent.x", + " );", + "", + " const region =", + " candidate.region || \"body\";", + " const baseLengthMultiplier =", + " lengthMultiplierForRegion(", + " region,", + " options", + " );", + " const clampedLongCoatWeight =", + " clamp(longCoatWeight, 0, 1);", + " const longLengthMultiplier =", + " 1 +", + " (", + " options.longCoatLengthMultiplier -", + " 1", + " ) *", + " clampedLongCoatWeight;", + " const clampedHeadHairLengthWeight =", + " clamp(headHairLengthWeight, 0, 1);", + " const clampedNoseBridgeHairLengthWeight =", + " clamp(noseBridgeHairLengthWeight, 0, 1);", + " const clampedInnerEarsHairLengthWeight =", + " clamp(innerEarsHairLengthWeight, 0, 1);", + "", + " // Specific masks take priority over the broad head mask.", + " const specificHeadOverride = clamp(", + " Math.max(", + " clampedNoseBridgeHairLengthWeight,", + " clampedInnerEarsHairLengthWeight", + " ),", + " 0,", + " 1", + " );", + " const effectiveHeadHairLengthWeight =", + " clampedHeadHairLengthWeight *", + " (1 - specificHeadOverride);", + "", + " const headHairLengthFactor =", + " 1 +", + " (", + " options.headHairLengthMultiplier -", + " 1", + " ) *", + " effectiveHeadHairLengthWeight;", + " const noseBridgeHairLengthFactor =", + " 1 +", + " (", + " options.noseBridgeHairLengthMultiplier -", + " 1", + " ) *", + " clampedNoseBridgeHairLengthWeight;", + " const innerEarsHairLengthFactor =", + " 1 +", + " (", + " options.innerEarsHairLengthMultiplier -", + " 1", + " ) *", + " clampedInnerEarsHairLengthWeight;", + "", + " const lengthMultiplier =", + " baseLengthMultiplier *", + " longLengthMultiplier *", + " headHairLengthFactor *", + " noseBridgeHairLengthFactor *", + " innerEarsHairLengthFactor;", + "", + " const baseHangMultiplier =", + " region === \"tail\"", + " ? options.tailGravityHangingMultiplier", + " : region === \"ear\"", + " ? 1.35", + " : region === \"leg\"", + " ? 1.12", + " : region === \"paw\"", + " ? 0.90", + " : options.bodyGravityHangingMultiplier;", + " const baseWaveMultiplier =", + " region === \"tail\"", + " ? 1.35", + " : region === \"ear\"", + " ? 1.40", + " : region === \"leg\"", + " ? 1.18", + " : region === \"paw\"", + " ? 0.82", + " : 0.72;", + "", + " // The ordinary body coat remains surface-normal by default.", + " // A long-coat mask may still enable hanging on selected body areas.", + " const hangMultiplier = Math.max(", + " baseHangMultiplier,", + " options.longCoatHangMultiplier *", + " clampedLongCoatWeight", + " );", + " const waveMultiplier =", + " baseWaveMultiplier *", + " (", + " 1 +", + " (", + " options.longCoatWaveMultiplier -", + " 1", + " ) *", + " clampedLongCoatWeight", + " );", + "", + " return {", + " x: rootX,", + " y: rootY,", + " z: rootZ,", + " normal,", + " surfaceNormal:", + " normalize3(", + " normal.x,", + " normal.y,", + " normal.z", + " ),", + " tangent,", + " tangent2,", + " groupWeight,", + " region,", + " lengthMultiplier,", + " hangMultiplier,", + " waveMultiplier,", + " longCoatWeight:", + " clampedLongCoatWeight,", + " headHairLengthWeight:", + " clampedHeadHairLengthWeight,", + " noseBridgeHairLengthWeight:", + " clampedNoseBridgeHairLengthWeight,", + " innerEarsHairLengthWeight:", + " clampedInnerEarsHairLengthWeight,", + " skin: aggregateRootSkin(", + " mesh,", + " candidate.ia,", + " candidate.ib,", + " candidate.ic,", + " ba,", + " bb,", + " bc", + " ),", + " surfaceColor: surfaceColor(", + " mesh,", + " candidate.materialIndex,", + " candidate.ia,", + " candidate.ib,", + " candidate.ic,", + " ba,", + " bb,", + " bc,", + " options", + " )", + " };", + " }", + "", + " function createBufferAttribute(", + " referenceAttribute,", + " array,", + " itemSize,", + " normalized", + " ) {", + " const AttributeConstructor =", + " referenceAttribute && referenceAttribute.constructor", + " ? referenceAttribute.constructor", + " : null;", + " if (!AttributeConstructor) {", + " throw new Error(\"Could not resolve BufferAttribute constructor.\");", + " }", + " return new AttributeConstructor(", + " array,", + " itemSize,", + " !!normalized", + " );", + " }", + "", + " function safeRootSkin(mesh, skin) {", + " if (!mesh.isSkinnedMesh || !mesh.skeleton) return null;", + "", + " const boneCount = Math.max(1, mesh.skeleton.bones.length);", + " const indices = [0, 0, 0, 0];", + " const weights = [1, 0, 0, 0];", + "", + " if (!skin || !skin.indices || !skin.weights) {", + " return { indices, weights };", + " }", + "", + " let sum = 0;", + " for (let componentIndex = 0; componentIndex < 4; componentIndex++) {", + " const rawIndex = Number(skin.indices[componentIndex]);", + " const rawWeight = Number(skin.weights[componentIndex]);", + " const boneIndex =", + " Number.isFinite(rawIndex)", + " ? Math.round(rawIndex)", + " : 0;", + " const weight =", + " Number.isFinite(rawWeight)", + " ? clamp(rawWeight, 0, 1)", + " : 0;", + "", + " indices[componentIndex] =", + " boneIndex >= 0 && boneIndex < boneCount", + " ? boneIndex", + " : 0;", + " weights[componentIndex] = weight;", + " sum += weight;", + " }", + "", + " if (sum <= 1e-8) {", + " indices[0] = 0;", + " weights[0] = 1;", + " weights[1] = 0;", + " weights[2] = 0;", + " weights[3] = 0;", + " return { indices, weights };", + " }", + "", + " for (let componentIndex = 0; componentIndex < 4; componentIndex++) {", + " weights[componentIndex] /= sum;", + " }", + " return { indices, weights };", + " }", + "", + " function writePosition(array, vertexIndex, x, y, z) {", + " const offset = vertexIndex * 3;", + " array[offset] = Number.isFinite(x) ? x : 0;", + " array[offset + 1] = Number.isFinite(y) ? y : 0;", + " array[offset + 2] = Number.isFinite(z) ? z : 0;", + " }", + "", + " function writeColorBytes(array, vertexIndex, r, g, b) {", + " const offset = vertexIndex * 3;", + " array[offset] = Math.round(clamp(r, 0, 1) * 255);", + " array[offset + 1] = Math.round(clamp(g, 0, 1) * 255);", + " array[offset + 2] = Math.round(clamp(b, 0, 1) * 255);", + " }", + "", + " function writeSkin(", + " skinIndices,", + " skinWeights,", + " vertexIndex,", + " skin", + " ) {", + " if (!skinIndices || !skinWeights || !skin) return;", + " const offset = vertexIndex * 4;", + " for (let componentIndex = 0; componentIndex < 4; componentIndex++) {", + " skinIndices[offset + componentIndex] =", + " skin.indices[componentIndex];", + " skinWeights[offset + componentIndex] =", + " skin.weights[componentIndex];", + " }", + " }", + "", + " function createLayerGroup(", + " source,", + " roots,", + " layerOptions,", + " options,", + " random", + " ) {", + " const sourcePosition =", + " source.geometry.getAttribute(\"position\");", + " const scaleInfo =", + " effectiveHairUnitScale(", + " source,", + " options", + " );", + " const hairUnitScale =", + " scaleInfo.scale;", + "", + " // Work on a copy because the same base layer settings are reused for", + " // several source meshes that may have different native scales.", + " layerOptions = Object.assign(", + " {},", + " layerOptions,", + " {", + " length:", + " layerOptions.length *", + " hairUnitScale,", + " thickness:", + " layerOptions.thickness *", + " hairUnitScale,", + " spread:", + " layerOptions.spread *", + " hairUnitScale,", + " modelReferenceDimension:", + " scaleInfo.referenceDimension,", + " hairUnitScale", + " }", + " );", + " const effectiveSurfaceOffset =", + " options.surfaceOffset *", + " hairUnitScale;", + "", + " const localWorldDown =", + " source.position.clone();", + " localDirection(", + " source,", + " 0,", + " 0,", + " -1,", + " localWorldDown", + " );", + "", + " function stableTailDownDirection(", + " surfaceNormal,", + " factor", + " ) {", + " if (factor <= 0) {", + " return {", + " x: 0,", + " y: 0,", + " z: 0", + " };", + " }", + "", + " // This is now a stable tail-region marker and fallback direction.", + " // The actual resting direction is recalculated from live world gravity", + " // in the shader, avoiding a diagonal tangent bias on downward tails.", + " return {", + " x: localWorldDown.x * factor,", + " y: localWorldDown.y * factor,", + " z: localWorldDown.z * factor", + " };", + " }", + "", + " const GeometryConstructor = source.geometry.constructor;", + " const geometry = new GeometryConstructor();", + "", + " const segments = Math.max(", + " 1,", + " Math.floor(layerOptions.segments)", + " );", + " const planes = Math.max(", + " 1,", + " Math.floor(layerOptions.planes || 1)", + " );", + " const rings = segments + 1;", + " const verticesPerPlane = rings * 2;", + " const verticesPerFiber = planes * verticesPerPlane;", + " const indicesPerPlane = segments * 6;", + " const indicesPerFiber = planes * indicesPerPlane;", + " const fiberCount =", + " roots.length * layerOptions.strandsPerRoot;", + " const vertexCount = fiberCount * verticesPerFiber;", + " const indexCount = fiberCount * indicesPerFiber;", + "", + " const positions = new Float32Array(vertexCount * 3);", + " const normals = new Float32Array(vertexCount * 3);", + " const colors = new Uint8Array(vertexCount * 3);", + " const furMotion = new Float32Array(vertexCount * 4);", + " const furTailDownDirections =", + " new Float32Array(vertexCount * 3);", + " const furSurfaceNormals =", + " new Float32Array(vertexCount * 3);", + "", + " let skinIndices = null;", + " let skinWeights = null;", + " if (source.isSkinnedMesh) {", + " if (", + " !source.geometry.getAttribute(\"skinIndex\") ||", + " !source.geometry.getAttribute(\"skinWeight\") ||", + " !source.skeleton", + " ) {", + " throw new Error(", + " \"Skinned source mesh is missing skinIndex, skinWeight or skeleton.\"", + " );", + " }", + " skinIndices = new Uint16Array(vertexCount * 4);", + " skinWeights = new Float32Array(vertexCount * 4);", + " }", + "", + " const IndexArray =", + " vertexCount <= 65535", + " ? Uint16Array", + " : Uint32Array;", + " const indices = new IndexArray(indexCount);", + "", + " let fiberIndex = 0;", + " let indexCursor = 0;", + " const safeSpread = Math.min(", + " Math.max(0, layerOptions.spread),", + " Math.max(0.000001, layerOptions.length * 0.18)", + " );", + "", + " for (let rootIndex = 0; rootIndex < roots.length; rootIndex++) {", + " const root = roots[rootIndex];", + " const bundleRotation = random() * Math.PI * 2;", + " const skin = safeRootSkin(source, root.skin);", + "", + " for (", + " let strand = 0;", + " strand < layerOptions.strandsPerRoot;", + " strand++", + " ) {", + " const strandFraction =", + " layerOptions.strandsPerRoot <= 1", + " ? 0", + " : strand / layerOptions.strandsPerRoot;", + " const angularJitter =", + " layerOptions.strandsPerRoot <= 1", + " ? 0", + " : (", + " random() * 2 - 1", + " ) *", + " (", + " Math.PI /", + " layerOptions.strandsPerRoot", + " ) *", + " 0.10;", + " const angle =", + " bundleRotation +", + " strandFraction * Math.PI * 2 +", + " angularJitter;", + " const radius =", + " layerOptions.strandsPerRoot <= 1", + " ? 0", + " : safeSpread * (0.62 + random() * 0.38);", + "", + " const jitterScale =", + " layerOptions.kind === \"undercoat\"", + " ? 0.035", + " : 0.065;", + " const tiltX =", + " (random() * 2 - 1) * jitterScale;", + " const tiltY =", + " (random() * 2 - 1) * jitterScale;", + "", + " const lengthFactor = Math.max(", + " 0.10,", + " 1 +", + " (random() * 2 - 1) *", + " layerOptions.lengthRandomness", + " );", + " const thicknessFactor =", + " 0.84 + random() * 0.32;", + " const phase = random() * Math.PI * 2;", + "", + " const variation =", + " (random() * 2 - 1) *", + " options.colorVariation;", + " const darkening = clamp(", + " layerOptions.colorDarkening,", + " 0,", + " 0.95", + " );", + " const baseColor =", + " root.surfaceColor ||", + " parseColor(options.color);", + " const colorR = clamp(", + " baseColor.r *", + " (1 - darkening) *", + " (1 + variation),", + " 0,", + " 1", + " );", + " const colorG = clamp(", + " baseColor.g *", + " (1 - darkening) *", + " (1 + variation),", + " 0,", + " 1", + " );", + " const colorB = clamp(", + " baseColor.b *", + " (1 - darkening) *", + " (1 + variation),", + " 0,", + " 1", + " );", + "", + " const rootX =", + " root.x +", + " root.normal.x * effectiveSurfaceOffset +", + " root.tangent.x * Math.cos(angle) * radius +", + " root.tangent2.x * Math.sin(angle) * radius;", + " const rootY =", + " root.y +", + " root.normal.y * effectiveSurfaceOffset +", + " root.tangent.y * Math.cos(angle) * radius +", + " root.tangent2.y * Math.sin(angle) * radius;", + " const rootZ =", + " root.z +", + " root.normal.z * effectiveSurfaceOffset +", + " root.tangent.z * Math.cos(angle) * radius +", + " root.tangent2.z * Math.sin(angle) * radius;", + "", + " let direction = normalize3(", + " root.normal.x +", + " root.tangent.x * tiltX +", + " root.tangent2.x * tiltY,", + " root.normal.y +", + " root.tangent.y * tiltX +", + " root.tangent2.y * tiltY,", + " root.normal.z +", + " root.tangent.z * tiltX +", + " root.tangent2.z * tiltY", + " );", + " const outward =", + " direction.x * root.normal.x +", + " direction.y * root.normal.y +", + " direction.z * root.normal.z;", + " if (outward < 0.65) {", + " direction = normalize3(", + " direction.x +", + " root.normal.x * (0.65 - outward),", + " direction.y +", + " root.normal.y * (0.65 - outward),", + " direction.z +", + " root.normal.z * (0.65 - outward)", + " );", + " }", + "", + " const weightLength =", + " options.weightAffectsLength", + " ? Math.max(0.08, root.groupWeight)", + " : 1;", + " const regionalLengthMultiplier =", + " layerOptions.kind === \"outer\"", + " ? Math.max(", + " 0.10,", + " root.lengthMultiplier || 1", + " )", + " : 1;", + " const length =", + " layerOptions.length *", + " lengthFactor *", + " weightLength *", + " regionalLengthMultiplier;", + " const lengthRatio =", + " length /", + " Math.max(", + " layerOptions.length,", + " 0.00001", + " );", + " const hangScale =", + " layerOptions.kind === \"outer\"", + " ? Math.max(", + " 0,", + " (root.hangMultiplier || 1) *", + " lengthRatio", + " )", + " : 0.08;", + " const waveScale =", + " layerOptions.kind === \"outer\"", + " ? Math.max(", + " 0,", + " (root.waveMultiplier || 1) *", + " lengthRatio", + " )", + " : 0.06;", + " const halfWidth =", + " layerOptions.thickness *", + " thicknessFactor *", + " 0.5;", + " const correctedSurfaceNormal =", + " root.surfaceNormal ||", + " root.normal;", + " const tailLayerFactor =", + " root.region === \"tail\"", + " ? (", + " layerOptions.kind === \"outer\"", + " ? 1", + " : 0.35", + " )", + " : 0;", + " const tailDownDirection =", + " stableTailDownDirection(", + " correctedSurfaceNormal,", + " tailLayerFactor", + " );", + "", + " for (let plane = 0; plane < planes; plane++) {", + " const planeAngle =", + " (plane / planes) * Math.PI;", + " const cosine = Math.cos(planeAngle);", + " const sine = Math.sin(planeAngle);", + " const sideX =", + " root.tangent.x * cosine +", + " root.tangent2.x * sine;", + " const sideY =", + " root.tangent.y * cosine +", + " root.tangent2.y * sine;", + " const sideZ =", + " root.tangent.z * cosine +", + " root.tangent2.z * sine;", + "", + " const face = normalize3(", + " sideY * direction.z -", + " sideZ * direction.y,", + " sideZ * direction.x -", + " sideX * direction.z,", + " sideX * direction.y -", + " sideY * direction.x", + " );", + "", + " const planeVertexStart =", + " fiberIndex * verticesPerFiber +", + " plane * verticesPerPlane;", + "", + " for (let ring = 0; ring < rings; ring++) {", + " const t = ring / segments;", + " const pointX =", + " rootX + direction.x * length * t;", + " const pointY =", + " rootY + direction.y * length * t;", + " const pointZ =", + " rootZ + direction.z * length * t;", + "", + " const taper = Math.max(", + " 0.10,", + " 1 - t * 0.90", + " );", + " let coverage = 1;", + " if (", + " layerOptions.kind === \"outer\" &&", + " layerOptions.coverageWidthMultiplier > 1", + " ) {", + " const coverageLength = Math.max(", + " 0.02,", + " layerOptions.coverageLength", + " );", + " const base = clamp(", + " 1 - t / coverageLength,", + " 0,", + " 1", + " );", + " coverage =", + " 1 +", + " (", + " layerOptions.coverageWidthMultiplier -", + " 1", + " ) *", + " base *", + " base;", + " }", + " const width =", + " halfWidth * taper * coverage;", + "", + " const leftVertex =", + " planeVertexStart + ring * 2;", + " const rightVertex = leftVertex + 1;", + "", + " writePosition(", + " positions,", + " leftVertex,", + " pointX - sideX * width,", + " pointY - sideY * width,", + " pointZ - sideZ * width", + " );", + " writePosition(", + " positions,", + " rightVertex,", + " pointX + sideX * width,", + " pointY + sideY * width,", + " pointZ + sideZ * width", + " );", + "", + " writePosition(", + " normals,", + " leftVertex,", + " face.x,", + " face.y,", + " face.z", + " );", + " writePosition(", + " normals,", + " rightVertex,", + " face.x,", + " face.y,", + " face.z", + " );", + "", + " writeColorBytes(", + " colors,", + " leftVertex,", + " colorR,", + " colorG,", + " colorB", + " );", + " writeColorBytes(", + " colors,", + " rightVertex,", + " colorR,", + " colorG,", + " colorB", + " );", + "", + " writePosition(", + " furSurfaceNormals,", + " leftVertex,", + " correctedSurfaceNormal.x,", + " correctedSurfaceNormal.y,", + " correctedSurfaceNormal.z", + " );", + " writePosition(", + " furSurfaceNormals,", + " rightVertex,", + " correctedSurfaceNormal.x,", + " correctedSurfaceNormal.y,", + " correctedSurfaceNormal.z", + " );", + " writePosition(", + " furTailDownDirections,", + " leftVertex,", + " tailDownDirection.x,", + " tailDownDirection.y,", + " tailDownDirection.z", + " );", + " writePosition(", + " furTailDownDirections,", + " rightVertex,", + " tailDownDirection.x,", + " tailDownDirection.y,", + " tailDownDirection.z", + " );", + "", + " const motionOffsetLeft =", + " leftVertex * 4;", + " const motionOffsetRight =", + " rightVertex * 4;", + " furMotion[motionOffsetLeft] = t;", + " furMotion[motionOffsetLeft + 1] =", + " phase;", + " furMotion[motionOffsetLeft + 2] =", + " hangScale;", + " furMotion[motionOffsetLeft + 3] =", + " waveScale;", + " furMotion[motionOffsetRight] = t;", + " furMotion[motionOffsetRight + 1] =", + " phase;", + " furMotion[motionOffsetRight + 2] =", + " hangScale;", + " furMotion[motionOffsetRight + 3] =", + " waveScale;", + "", + " writeSkin(", + " skinIndices,", + " skinWeights,", + " leftVertex,", + " skin", + " );", + " writeSkin(", + " skinIndices,", + " skinWeights,", + " rightVertex,", + " skin", + " );", + " }", + "", + " for (", + " let segment = 0;", + " segment < segments;", + " segment++", + " ) {", + " const a =", + " planeVertexStart + segment * 2;", + " const b = a + 1;", + " const c = a + 2;", + " const d = a + 3;", + "", + " indices[indexCursor++] = a;", + " indices[indexCursor++] = b;", + " indices[indexCursor++] = c;", + " indices[indexCursor++] = b;", + " indices[indexCursor++] = d;", + " indices[indexCursor++] = c;", + " }", + " }", + "", + " fiberIndex++;", + " }", + " }", + "", + " geometry.setAttribute(", + " \"position\",", + " createBufferAttribute(", + " sourcePosition,", + " positions,", + " 3,", + " false", + " )", + " );", + " geometry.setAttribute(", + " \"normal\",", + " createBufferAttribute(", + " sourcePosition,", + " normals,", + " 3,", + " false", + " )", + " );", + " geometry.setAttribute(", + " \"color\",", + " createBufferAttribute(", + " sourcePosition,", + " colors,", + " 3,", + " true", + " )", + " );", + " geometry.setAttribute(", + " \"furMotion\",", + " createBufferAttribute(", + " sourcePosition,", + " furMotion,", + " 4,", + " false", + " )", + " );", + " geometry.setAttribute(", + " \"furTailDownDirection\",", + " createBufferAttribute(", + " sourcePosition,", + " furTailDownDirections,", + " 3,", + " false", + " )", + " );", + " geometry.setAttribute(", + " \"furSurfaceNormal\",", + " createBufferAttribute(", + " sourcePosition,", + " furSurfaceNormals,", + " 3,", + " false", + " )", + " );", + "", + " if (source.isSkinnedMesh) {", + " geometry.setAttribute(", + " \"skinIndex\",", + " createBufferAttribute(", + " sourcePosition,", + " skinIndices,", + " 4,", + " false", + " )", + " );", + " geometry.setAttribute(", + " \"skinWeight\",", + " createBufferAttribute(", + " sourcePosition,", + " skinWeights,", + " 4,", + " false", + " )", + " );", + " }", + "", + " geometry.setIndex(", + " createBufferAttribute(", + " sourcePosition,", + " indices,", + " 1,", + " false", + " )", + " );", + "", + " if (geometry.computeBoundingSphere) {", + " geometry.computeBoundingSphere();", + " }", + "", + " const material = createMaterial(", + " source,", + " layerOptions", + " );", + " material.skinning = !!source.isSkinnedMesh;", + " material.needsUpdate = true;", + "", + " let furMesh;", + " if (source.isSkinnedMesh) {", + " furMesh = new source.constructor(", + " geometry,", + " material", + " );", + " if (\"bindMode\" in source) {", + " furMesh.bindMode = source.bindMode;", + " }", + " source.add(furMesh);", + " if (typeof furMesh.bind === \"function\") {", + " furMesh.bind(", + " source.skeleton,", + " source.bindMatrix", + " );", + " } else {", + " furMesh.skeleton = source.skeleton;", + " if (", + " furMesh.bindMatrix &&", + " source.bindMatrix", + " ) {", + " furMesh.bindMatrix.copy(", + " source.bindMatrix", + " );", + " }", + " if (", + " furMesh.bindMatrixInverse &&", + " source.bindMatrixInverse", + " ) {", + " furMesh.bindMatrixInverse.copy(", + " source.bindMatrixInverse", + " );", + " }", + " }", + " if (", + " typeof furMesh.normalizeSkinWeights ===", + " \"function\"", + " ) {", + " furMesh.normalizeSkinWeights();", + " }", + " } else {", + " const MeshConstructor =", + " meshConstructorFrom(source);", + " furMesh = new MeshConstructor(", + " geometry,", + " material", + " );", + " source.add(furMesh);", + " }", + "", + " furMesh.position.set(0, 0, 0);", + " furMesh.rotation.set(0, 0, 0);", + " furMesh.quaternion.set(0, 0, 0, 1);", + " furMesh.scale.set(1, 1, 1);", + " furMesh.name =", + " \"__ParticleFur3D_LowMemory_\" +", + " layerOptions.kind +", + " \"_\" +", + " (source.name || \"Mesh\");", + " furMesh.frustumCulled = false;", + " furMesh.castShadow = !!options.castShadow;", + " furMesh.receiveShadow = false;", + " furMesh.renderOrder =", + " numberOr(source.renderOrder, 0) +", + " (", + " layerOptions.kind === \"undercoat\"", + " ? 1", + " : 2", + " );", + " furMesh.userData = Object.assign(", + " {},", + " furMesh.userData || {},", + " {", + " __ParticleFur3DStrands: true,", + " __ParticleFur3DOwned: true,", + " __ParticleFur3DLayer:", + " layerOptions.kind,", + " __ParticleFur3DGpuSkinned:", + " !!source.isSkinnedMesh,", + " __ParticleFur3DIndexed: true,", + " __ParticleFur3DReferenceDimension:", + " scaleInfo.referenceDimension,", + " __ParticleFur3DHairUnitScale:", + " hairUnitScale,", + " __ParticleFur3DEffectiveLength:", + " layerOptions.length", + " }", + " );", + "", + " return {", + " source,", + " geometry,", + " material,", + " furMesh,", + " layerOptions,", + " vertexCount,", + " indexCount", + " };", + " }", + "", + " function updateGroup(", + " group,", + " options,", + " motion,", + " tailVerticalResponse,", + " time", + " ) {", + " const source = group.source;", + " if (!source || !group.furMesh) return;", + "", + " const windLocal = source.position.clone();", + " const movementLocal = source.position.clone();", + " const gravityLocal = source.position.clone();", + "", + " localDirection(", + " source,", + " options.windX,", + " -options.windY,", + " options.windZ,", + " windLocal", + " );", + " localDirection(", + " source,", + " motion.x,", + " motion.y,", + " motion.z,", + " movementLocal", + " );", + " localDirection(", + " source,", + " 0,", + " 0,", + " -1,", + " gravityLocal", + " );", + "", + " const shaderState =", + " group.material &&", + " group.material.userData", + " ? group.material.userData", + " .__ParticleFurShaderState", + " : null;", + " if (!shaderState) return;", + "", + " shaderState.time = time;", + " shaderState.windX = windLocal.x;", + " shaderState.windY = windLocal.y;", + " shaderState.windZ = windLocal.z;", + " shaderState.movementX = movementLocal.x;", + " shaderState.movementY = movementLocal.y;", + " shaderState.movementZ = movementLocal.z;", + " shaderState.gravityX = gravityLocal.x;", + " shaderState.gravityY = gravityLocal.y;", + " shaderState.gravityZ = gravityLocal.z;", + " shaderState.windStrength =", + " options.windStrength;", + " shaderState.windFrequency =", + " options.windFrequency;", + " shaderState.movementInfluence =", + " options.movementInfluence;", + " shaderState.movementAmount =", + " motion.amount;", + " shaderState.gravityStrength =", + " options.gravityStrength;", + " shaderState.layerLength =", + " group.layerOptions.length;", + " shaderState.rootStiffness =", + " group.layerOptions.rootStiffness;", + " shaderState.motionScale =", + " group.layerOptions.kind === \"undercoat\"", + " ? 0.25", + " : 1;", + " shaderState.hangStrength =", + " group.layerOptions.kind === \"outer\"", + " ? options.hangStrength", + " : options.hangStrength * 0.06;", + " shaderState.hangStart =", + " options.hangStart;", + " shaderState.waveAmplitude =", + " group.layerOptions.kind === \"outer\"", + " ? options.waveAmplitude", + " : options.waveAmplitude * 0.08;", + " shaderState.waveAlongHair =", + " options.waveAlongHair;", + " shaderState.waveSpeed =", + " options.waveSpeed;", + " shaderState.restWaveAmount =", + " options.restWaveAmount;", + " shaderState.movementWaveBoost =", + " options.movementWaveBoost;", + " shaderState.preventSurfacePenetration =", + " options.preventSurfacePenetration", + " ? 1", + " : 0;", + " shaderState.surfaceSafetyLift =", + " options.surfaceSafetyLift;", + " shaderState.tailVerticalResponse =", + " tailVerticalResponse;", + " shaderState.tailVerticalInfluence =", + " options.tailVerticalInertiaInfluence;", + " shaderState.tailVerticalTipPower =", + " options.tailVerticalInertiaTipPower;", + " shaderState.tailFallOverrideResponse =", + " options.tailFallOverrideResponse;", + " shaderState.tailRestGravityAlignment =", + " options.tailRestGravityAlignment;", + " shaderState.tailRestHangMultiplier =", + " options.tailRestHangMultiplier;", + "", + " syncFurShaderUniforms(shaderState);", + " }", + "", + "", + " function optionsFromBehavior(behavior) {", + " return {", + " meshName: String(behavior._getMeshName() || \"\").trim(),", + " vertexGroupName: String(behavior._getVertexGroupName() || \"\").trim(),", + " groupThreshold: clamp(numberOr(behavior._getGroupThreshold(), 0.05), 0, 1),", + " invertVertexGroup: !!behavior._getInvertVertexGroup(),", + " weightAffectsLength: !!behavior._getWeightAffectsLength(),", + " useWholeMeshIfGroupMissing:", + " !!behavior._getUseWholeMeshIfGroupMissing(),", + " autoCorrectInwardNormals:", + " !!behavior._getAutoCorrectInwardNormals(),", + " invertSurfaceNormals:", + " !!behavior._getInvertSurfaceNormals(),", + " perRootOutwardCorrection:", + " !!behavior._getPerRootOutwardCorrection(),", + " trustImportedNormals:", + " !!behavior._getTrustImportedNormals(),", + " minimumFaceNormalAgreement:", + " clamp(", + " numberOr(", + " behavior._getMinimumFaceNormalAgreement(),", + " 0.25", + " ),", + " 0,", + " 1", + " ),", + " preventSurfacePenetration:", + " !!behavior._getPreventSurfacePenetration(),", + " surfaceSafetyLift:", + " clamp(", + " numberOr(", + " behavior._getSurfaceSafetyLift(),", + " 0.06", + " ),", + " 0,", + " 1", + " ),", + " regionalMasksExtendCoverage:", + " !!behavior._getRegionalMasksExtendCoverage(),", + " strictVertexGroupMatching:", + " !!behavior._getStrictVertexGroupMatching(),", + " expandRegionalMasks:", + " !!behavior._getExpandRegionalMasks(),", + " regionalMaskExpansionRings:", + " Math.max(", + " 0,", + " Math.min(", + " 6,", + " Math.round(", + " numberOr(", + " behavior._getRegionalMaskExpansionRings(),", + " 2", + " )", + " )", + " )", + " ),", + " regionalMaskExpansionFalloff:", + " clamp(", + " numberOr(", + " behavior._getRegionalMaskExpansionFalloff(),", + " 0.72", + " ),", + " 0.05,", + " 1", + " ),", + " bridgeRegionalMaskSeams:", + " !!behavior._getBridgeRegionalMaskSeams(),", + " regionalSeamBridgeRadius:", + " clamp(", + " numberOr(", + " behavior._getRegionalSeamBridgeRadius(),", + " 0.018", + " ),", + " 0,", + " 0.12", + " ),", + " regionalSeamBridgeFalloff:", + " clamp(", + " numberOr(", + " behavior._getRegionalSeamBridgeFalloff(),", + " 0.82", + " ),", + " 0.05,", + " 1", + " ),", + " scaleHairToModelSize:", + " !!behavior._getScaleHairToModelSize(),", + " modelRelativeSizeMultiplier:", + " clamp(", + " numberOr(", + " behavior._getModelRelativeSizeMultiplier(),", + " 1", + " ),", + " 0.01,", + " 20", + " ),", + " maximumAutomaticHairScale:", + " clamp(", + " numberOr(", + " behavior._getMaximumAutomaticHairScale(),", + " 250", + " ),", + " 1,", + " 10000", + " ),", + "", + " autoRegionBoneDetection:", + " !!behavior._getAutoRegionBoneDetection(),", + " autoMapCommonFurGroups:", + " !!behavior._getAutoMapCommonFurGroups(),", + " tailRegionGroupName:", + " String(", + " behavior._getTailRegionGroupName() || \"\"", + " ).trim(),", + " legRegionGroupName:", + " String(", + " behavior._getLegRegionGroupName() || \"\"", + " ).trim(),", + " pawRegionGroupName:", + " String(", + " behavior._getPawRegionGroupName() || \"\"", + " ).trim(),", + " earRegionGroupName:", + " String(", + " behavior._getEarRegionGroupName() || \"\"", + " ).trim(),", + " headRegionGroupName:", + " String(", + " behavior._getHeadRegionGroupName() || \"\"", + " ).trim(),", + " topBackGroupName:", + " String(", + " behavior._getTopBackGroupName() || \"\"", + " ).trim(),", + " autoTopBackCoverage:", + " !!behavior._getAutoTopBackCoverage(),", + " topBackHeightStart:", + " clamp(", + " numberOr(", + " behavior._getTopBackHeightStart(),", + " 0.54", + " ),", + " 0,", + " 0.95", + " ),", + " topBackHighVertexBias:", + " clamp(", + " numberOr(", + " behavior._getTopBackHighVertexBias(),", + " 0.5", + " ),", + " 0,", + " 1", + " ),", + " topBackCoverageExpansionRings:", + " Math.max(", + " 0,", + " Math.min(", + " 8,", + " Math.round(", + " numberOr(", + " behavior._getTopBackCoverageExpansionRings(),", + " 4", + " )", + " )", + " )", + " ),", + " topBackCoverageExpansionFalloff:", + " clamp(", + " numberOr(", + " behavior._getTopBackCoverageExpansionFalloff(),", + " 0.82", + " ),", + " 0.05,", + " 1", + " ),", + " topBackDensityMultiplier:", + " clamp(", + " numberOr(", + " behavior._getTopBackDensityMultiplier(),", + " 3", + " ),", + " 0.1,", + " 12", + " ),", + " minimumTopBackRootShare:", + " clamp(", + " numberOr(", + " behavior._getMinimumTopBackRootShare(),", + " 0.16", + " ),", + " 0,", + " 0.5", + " ),", + " topBackPoolThreshold:", + " clamp(", + " numberOr(", + " behavior._getTopBackPoolThreshold(),", + " 0.08", + " ),", + " 0,", + " 1", + " ),", + " autoBackHeadCoverage:", + " !!behavior._getAutoBackHeadCoverage(),", + " backHeadStart:", + " clamp(", + " numberOr(", + " behavior._getBackHeadStart(),", + " 0.60", + " ),", + " 0,", + " 0.95", + " ),", + " backHeadExpansionRings:", + " Math.max(", + " 0,", + " Math.min(", + " 8,", + " Math.round(", + " numberOr(", + " behavior._getBackHeadExpansionRings(),", + " 2", + " )", + " )", + " )", + " ),", + " backHeadExpansionFalloff:", + " clamp(", + " numberOr(", + " behavior._getBackHeadExpansionFalloff(),", + " 0.82", + " ),", + " 0.05,", + " 1", + " ),", + " backHeadDensityMultiplier:", + " clamp(", + " numberOr(", + " behavior._getBackHeadDensityMultiplier(),", + " 4", + " ),", + " 0.1,", + " 12", + " ),", + " minimumBackHeadRootShare:", + " clamp(", + " numberOr(", + " behavior._getMinimumBackHeadRootShare(),", + " 0.09", + " ),", + " 0,", + " 0.35", + " ),", + " backHeadPoolThreshold:", + " clamp(", + " numberOr(", + " behavior._getBackHeadPoolThreshold(),", + " 0.05", + " ),", + " 0,", + " 1", + " ),", + " longCoatGroupName:", + " String(", + " behavior._getLongCoatGroupName() || \"\"", + " ).trim(),", + "", + " headHairLengthGroupName:", + " String(", + " behavior._getHeadHairLengthGroupName() || \"\"", + " ).trim(),", + " noseBridgeHairLengthGroupName:", + " String(", + " behavior._getNoseBridgeHairLengthGroupName() || \"\"", + " ).trim(),", + " innerEarsHairLengthGroupName:", + " String(", + " behavior._getInnerEarsHairLengthGroupName() || \"\"", + " ).trim(),", + "", + " headHairLengthMultiplier:", + " clamp(", + " numberOr(", + " behavior._getHeadHairLengthMultiplier(),", + " 1.15", + " ),", + " 0.05,", + " 6", + " ),", + " noseBridgeHairLengthMultiplier:", + " clamp(", + " numberOr(", + " behavior._getNoseBridgeHairLengthMultiplier(),", + " 0.45", + " ),", + " 0.05,", + " 6", + " ),", + " innerEarsHairLengthMultiplier:", + " clamp(", + " numberOr(", + " behavior._getInnerEarsHairLengthMultiplier(),", + " 0.65", + " ),", + " 0.05,", + " 6", + " ),", + "", + " tailDensityMultiplier:", + " clamp(", + " numberOr(", + " behavior._getTailDensityMultiplier(),", + " 4", + " ),", + " 0.1,", + " 12", + " ),", + " legDensityMultiplier:", + " clamp(", + " numberOr(", + " behavior._getLegDensityMultiplier(),", + " 2.5", + " ),", + " 0.1,", + " 12", + " ),", + " pawDensityMultiplier:", + " clamp(", + " numberOr(", + " behavior._getPawDensityMultiplier(),", + " 3", + " ),", + " 0.1,", + " 12", + " ),", + " earDensityMultiplier:", + " clamp(", + " numberOr(", + " behavior._getEarDensityMultiplier(),", + " 2.5", + " ),", + " 0.1,", + " 12", + " ),", + " headDensityMultiplier:", + " clamp(", + " numberOr(", + " behavior._getHeadDensityMultiplier(),", + " 2", + " ),", + " 0.1,", + " 12", + " ),", + "", + " minimumTailRootShare:", + " clamp(", + " numberOr(", + " behavior._getMinimumTailRootShare(),", + " 0.08", + " ),", + " 0,", + " 0.5", + " ),", + " minimumLegRootShare:", + " clamp(", + " numberOr(", + " behavior._getMinimumLegRootShare(),", + " 0.24", + " ),", + " 0,", + " 0.7", + " ),", + " minimumPawRootShare:", + " clamp(", + " numberOr(", + " behavior._getMinimumPawRootShare(),", + " 0.08", + " ),", + " 0,", + " 0.4", + " ),", + " minimumEarRootShare:", + " clamp(", + " numberOr(", + " behavior._getMinimumEarRootShare(),", + " 0.05", + " ),", + " 0,", + " 0.3", + " ),", + " minimumHeadRootShare:", + " clamp(", + " numberOr(", + " behavior._getMinimumHeadRootShare(),", + " 0.12", + " ),", + " 0,", + " 0.5", + " ),", + "", + " tailLengthMultiplier:", + " clamp(", + " numberOr(", + " behavior._getTailLengthMultiplier(),", + " 1.8", + " ),", + " 0.1,", + " 5", + " ),", + " tailGravityHangingMultiplier:", + " clamp(", + " numberOr(", + " behavior._getTailGravityHangingMultiplier(),", + " 1.8", + " ),", + " 0,", + " 6", + " ),", + " bodyGravityHangingMultiplier:", + " clamp(", + " numberOr(", + " behavior._getBodyGravityHangingMultiplier(),", + " 0", + " ),", + " 0,", + " 4", + " ),", + " legLengthMultiplier:", + " clamp(", + " numberOr(", + " behavior._getLegLengthMultiplier(),", + " 1.5", + " ),", + " 0.1,", + " 5", + " ),", + " pawLengthMultiplier:", + " clamp(", + " numberOr(", + " behavior._getPawLengthMultiplier(),", + " 1.25", + " ),", + " 0.1,", + " 5", + " ),", + " earLengthMultiplier:", + " clamp(", + " numberOr(", + " behavior._getEarLengthMultiplier(),", + " 1.8", + " ),", + " 0.1,", + " 5", + " ),", + "", + " longCoatDensityMultiplier:", + " clamp(", + " numberOr(", + " behavior._getLongCoatDensityMultiplier(),", + " 2", + " ),", + " 0.1,", + " 8", + " ),", + " longCoatLengthMultiplier:", + " clamp(", + " numberOr(", + " behavior._getLongCoatLengthMultiplier(),", + " 1.8", + " ),", + " 0.1,", + " 6", + " ),", + " longCoatHangMultiplier:", + " clamp(", + " numberOr(", + " behavior._getLongCoatHangMultiplier(),", + " 1.35", + " ),", + " 0,", + " 5", + " ),", + " longCoatWaveMultiplier:", + " clamp(", + " numberOr(", + " behavior._getLongCoatWaveMultiplier(),", + " 1.4", + " ),", + " 0,", + " 5", + " ),", + "", + " tailBoneKeywords:", + " String(", + " behavior._getTailBoneKeywords() ||", + " \"tail,cauda,coda\"", + " ),", + " legBoneKeywords:", + " String(", + " behavior._getLegBoneKeywords() ||", + " \"leg,thigh,calf,shin,femur,tibia,hock,upperarm,forearm,humerus,radius,ulna\"", + " ),", + " pawBoneKeywords:", + " String(", + " behavior._getPawBoneKeywords() ||", + " \"paw,foot,toe,digit,claw,carpal,metacarp,metatars,ankle\"", + " ),", + " earBoneKeywords:", + " String(", + " behavior._getEarBoneKeywords() ||", + " \"ear\"", + " ),", + " headBoneKeywords:", + " String(", + " behavior._getHeadBoneKeywords() ||", + " \"head,skull,cranium,muzzle,snout,jaw\"", + " ),", + "", + " rootCount: Math.floor(clamp(numberOr(behavior._getStrandCount(), 2500), 1, 30000)),", + " outerStrandsPerRoot: Math.floor(clamp(numberOr(behavior._getOuterStrandsPerRoot(), 2), 1, 8)),", + " outerLength: Math.max(0.00001, numberOr(behavior._getFurLength(), 0.025)),", + " outerThickness: Math.max(0.000001, numberOr(behavior._getFurThickness(), 0.0035)),", + " outerSegments: Math.floor(clamp(numberOr(behavior._getOuterBendSegments(), 4), 1, 8)),", + " outerRootStiffness: clamp(numberOr(behavior._getOuterRootStiffness(), 0.72), 0, 1),", + " outerSpread: Math.max(0, numberOr(behavior._getOuterRootSpread(), 0.004)),", + " outerCoverageWidthMultiplier: clamp(", + " numberOr(behavior._getOuterCoverageWidthMultiplier(), 2.2),", + " 1,", + " 5", + " ),", + " outerCoverageLength: clamp(", + " numberOr(behavior._getOuterCoverageLength(), 0.45),", + " 0.02,", + " 1", + " ),", + " outerCoveragePlanes: Math.floor(", + " clamp(numberOr(behavior._getOuterCoveragePlanes(), 3), 1, 4)", + " ),", + " outerLengthRandomness: clamp(numberOr(behavior._getLengthRandomness(), 0.25), 0, 1),", + " undercoatEnabled: !!behavior._getUndercoatEnabled(),", + " undercoatStrandsPerRoot: Math.floor(clamp(numberOr(behavior._getUndercoatStrandsPerRoot(), 3), 0, 12)),", + " undercoatLength: Math.max(0.00001, numberOr(behavior._getUndercoatLength(), 0.009)),", + " undercoatThickness: Math.max(0.000001, numberOr(behavior._getUndercoatThickness(), 0.0042)),", + " undercoatSegments: Math.floor(clamp(numberOr(behavior._getUndercoatBendSegments(), 2), 1, 5)),", + " undercoatRootStiffness: clamp(numberOr(behavior._getUndercoatRootStiffness(), 0.9), 0, 1),", + " undercoatSpread: Math.max(0, numberOr(behavior._getUndercoatRootSpread(), 0.002)),", + " undercoatLengthRandomness: clamp(numberOr(behavior._getUndercoatLengthRandomness(), 0.18), 0, 1),", + " undercoatDarkening: clamp(numberOr(behavior._getUndercoatDarkening(), 0.06), 0, 0.95),", + " maximumVisualStrands: Math.floor(", + " clamp(", + " numberOr(", + " behavior._getMaximumVisualStrands(),", + " 100000", + " ),", + " 100,", + " 250000", + " )", + " ),", + " maximumFurMemoryMB: clamp(", + " numberOr(", + " behavior._getMaximumFurMemoryMB(),", + " 96", + " ),", + " 16,", + " 512", + " ),", + " surfaceOffset: Math.max(", + " 0,", + " numberOr(", + " behavior._getSurfaceOffset(),", + " 0.0002", + " )", + " ),", + " color: String(behavior._getFurColor() || \"120;90;65\"),", + " useModelTextureColor: !!behavior._getUseModelTextureColor(),", + " modelTextureColorStrength: clamp(numberOr(behavior._getModelTextureColorStrength(), 1), 0, 1),", + " colorVariation: clamp(numberOr(behavior._getColorVariation(), 0.05), 0, 1),", + " windX: numberOr(behavior._getWindDirectionX(), 1),", + " windY: numberOr(behavior._getWindDirectionY(), 0),", + " windZ: numberOr(behavior._getWindDirectionZ(), 0),", + " windStrength: Math.max(0, numberOr(behavior._getWindStrength(), 0.18)),", + " windFrequency: Math.max(0, numberOr(behavior._getWindFrequency(), 1.4)),", + " movementInfluence: Math.max(0, numberOr(behavior._getMovementInfluence(), 0.18)),", + " verticalMovementInfluence: clamp(numberOr(behavior._getVerticalMovementInfluence(), 0), 0, 1),", + " tailVerticalInertiaEnabled:", + " !!behavior._getTailVerticalInertiaEnabled(),", + " tailVerticalInertiaInfluence:", + " clamp(", + " numberOr(", + " behavior._getTailVerticalInertiaInfluence(),", + " 1.35", + " ),", + " 0,", + " 5", + " ),", + " tailVerticalFullSpeed:", + " Math.max(", + " 1,", + " numberOr(", + " behavior._getTailVerticalFullSpeed(),", + " 180", + " )", + " ),", + " tailVerticalVelocitySmoothing:", + " clamp(", + " numberOr(", + " behavior._getTailVerticalVelocitySmoothing(),", + " 0.08", + " ),", + " 0.005,", + " 1", + " ),", + " tailVerticalResponseSmoothing:", + " clamp(", + " numberOr(", + " behavior._getTailVerticalResponseSmoothing(),", + " 0.16", + " ),", + " 0.005,", + " 1", + " ),", + " tailVerticalDeadZone:", + " Math.max(", + " 0,", + " numberOr(", + " behavior._getTailVerticalDeadZone(),", + " 8", + " )", + " ),", + " tailVerticalSignHysteresis:", + " Math.max(", + " 0,", + " numberOr(", + " behavior._getTailVerticalSignHysteresis(),", + " 6", + " )", + " ),", + " tailVerticalInertiaTipPower:", + " clamp(", + " numberOr(", + " behavior._getTailVerticalInertiaTipPower(),", + " 1.5", + " ),", + " 0.1,", + " 5", + " ),", + " tailFallOverrideResponse:", + " clamp(", + " numberOr(", + " behavior._getTailFallOverrideResponse(),", + " 0.3", + " ),", + " 0.02,", + " 1", + " ),", + " tailRestGravityAlignment:", + " clamp(", + " numberOr(", + " behavior._getTailRestGravityAlignment(),", + " 1", + " ),", + " 0,", + " 1", + " ),", + " tailRestHangMultiplier:", + " clamp(", + " numberOr(", + " behavior._getTailRestHangMultiplier(),", + " 1", + " ),", + " 0,", + " 4", + " ),", + " movementVelocityScale: Math.max(0.001, numberOr(behavior._getMovementVelocityScale(), 180)),", + " gravityStrength:", + " Math.max(", + " 0,", + " numberOr(", + " behavior._getGravityStrength(),", + " 0.08", + " )", + " ),", + " hangStrength:", + " clamp(", + " numberOr(", + " behavior._getHangStrength(),", + " 1.15", + " ),", + " 0,", + " 4", + " ),", + " hangStart:", + " clamp(", + " numberOr(", + " behavior._getHangStart(),", + " 0.12", + " ),", + " 0,", + " 0.95", + " ),", + " waveAmplitude:", + " clamp(", + " numberOr(", + " behavior._getWaveAmplitude(),", + " 0.16", + " ),", + " 0,", + " 2", + " ),", + " waveAlongHair:", + " clamp(", + " numberOr(", + " behavior._getWaveAlongHair(),", + " 1.6", + " ),", + " 0,", + " 8", + " ),", + " waveSpeed:", + " clamp(", + " numberOr(", + " behavior._getWaveSpeed(),", + " 1.1", + " ),", + " 0,", + " 8", + " ),", + " restWaveAmount:", + " clamp(", + " numberOr(", + " behavior._getRestWaveAmount(),", + " 0.04", + " ),", + " 0,", + " 2", + " ),", + " movementWaveBoost:", + " clamp(", + " numberOr(", + " behavior._getMovementWaveBoost(),", + " 1.3", + " ),", + " 0,", + " 6", + " ),", + " updateRate: clamp(numberOr(behavior._getUpdateRate(), 20), 1, 60),", + " maximumDistance: Math.max(0, numberOr(behavior._getMaximumDistance(), 0)),", + " castShadow: !!behavior._getCastShadow(),", + " seed: Math.floor(numberOr(behavior._getSeed(), 12345))", + " };", + " }", + "", + " function fixedNumber(value, digits) {", + " const number = Number(value);", + " return Number.isFinite(number)", + " ? number.toFixed(digits)", + " : String(value);", + " }", + "", + " function compactMaskDiagnostics(", + " diagnostics", + " ) {", + " if (!diagnostics || !diagnostics.length) {", + " return \"No mask diagnostics.\";", + " }", + "", + " return diagnostics", + " .slice(0, 3)", + " .map(entry => {", + " const parts = [", + " \"nativeSize=\" +", + " fixedNumber(", + " entry.referenceDimension,", + " 3", + " ),", + " \"hairScale=x\" +", + " fixedNumber(", + " entry.hairUnitScale,", + " 3", + " ),", + " \"effectiveOuter=\" +", + " fixedNumber(", + " entry.effectiveOuterLength,", + " 4", + " ),", + " \"effectiveUndercoat=\" +", + " fixedNumber(", + " entry.effectiveUndercoatLength,", + " 4", + " ),", + " \"coverage=\" + entry.coverage,", + " \"tail=\" + entry.tail,", + " \"paw=\" + entry.paw,", + " \"ear=\" + entry.ear,", + " \"head=\" + entry.head,", + " \"topBack=\" + entry.topBack,", + " \"backHead=\" + entry.backHead,", + " \"headLength=\" +", + " entry.headLength,", + " \"noseLength=\" +", + " entry.noseLength,", + " \"innerEarLength=\" +", + " entry.innerEarLength", + " ];", + " return (", + " entry.meshName +", + " \" {\" +", + " parts.join(\"; \") +", + " \"}\"", + " );", + " })", + " .join(\" | \");", + " }", + "", + " M.configString = function (behavior) {", + " return JSON.stringify(optionsFromBehavior(behavior));", + " };", + "", + " function removeOrphanedFurMeshes(object) {", + " if (", + " !object ||", + " typeof object.get3DRendererObject !== \"function\"", + " ) {", + " return;", + " }", + " const rootObject =", + " object.get3DRendererObject();", + " if (!rootObject || !rootObject.traverse) return;", + "", + " const orphaned = [];", + " rootObject.traverse(node => {", + " if (", + " node &&", + " node.userData &&", + " (", + " node.userData.__ParticleFur3DOwned ||", + " node.userData.__ParticleFur3DStrands", + " )", + " ) {", + " orphaned.push(node);", + " }", + " });", + "", + " for (const node of orphaned) {", + " if (node.parent) node.parent.remove(node);", + " if (", + " node.geometry &&", + " node.geometry.dispose", + " ) {", + " node.geometry.dispose();", + " }", + " const materials = Array.isArray(node.material)", + " ? node.material", + " : [node.material];", + " for (const material of materials) {", + " if (", + " material &&", + " material.userData &&", + " material.userData.__ParticleFur3DOwned &&", + " material.dispose", + " ) {", + " material.dispose();", + " }", + " }", + " }", + " }", + "", + " M.remove = function (object, behavior, statusMessage) {", + " const state = getState(behavior);", + " for (const group of state.groups || []) {", + " if (group.furMesh && group.furMesh.parent) group.furMesh.parent.remove(group.furMesh);", + " if (group.geometry && group.geometry.dispose) group.geometry.dispose();", + " if (group.material && group.material.dispose) group.material.dispose();", + " }", + " state.groups = [];", + " state.built = false;", + " state.strandCount = 0;", + " state.rootCount = 0;", + " state.accumulator = 0;", + " state.filteredVerticalVelocity = 0;", + " state.tailVerticalResponse = 0;", + " state.tailResponseSign = 0;", + " state.hasPreviousPosition = false;", + " removeOrphanedFurMeshes(object);", + " if (statusMessage) {", + " setStatus(", + " object,", + " behavior,", + " statusMessage,", + " 0", + " );", + " }", + " };", + "", + " function sourceIsSkinnedCandidate(candidates) {", + " for (const candidate of candidates || []) {", + " const rawCandidate =", + " candidate && candidate.candidate", + " ? candidate.candidate", + " : candidate;", + " if (", + " rawCandidate &&", + " rawCandidate.mesh &&", + " rawCandidate.mesh.isSkinnedMesh", + " ) {", + " return true;", + " }", + " }", + " return false;", + " }", + "", + " M.build = function (object, behavior) {", + " const state = getState(behavior);", + " M.remove(object, behavior, \"Building GPU-skinned multi-segment fur...\");", + "", + " if (!object || typeof object.get3DRendererObject !== \"function\") {", + " setStatus(object, behavior, \"The object has no compatible 3D renderer.\", 0);", + " return { ok: false, retry: false };", + " }", + " const rootObject = object.get3DRendererObject();", + " if (!rootObject || !rootObject.traverse) {", + " setStatus(object, behavior, \"The 3D model has not finished loading yet.\", 0);", + " return { ok: false, retry: true };", + " }", + "", + " const options = optionsFromBehavior(behavior);", + " const meshes = collectMeshes(rootObject, options.meshName);", + " if (!meshes.length) {", + " setStatus(object, behavior, options.meshName ? \"No mesh named \\\"\" + options.meshName + \"\\\" was found.\" : \"No fully loaded compatible mesh was found yet.\", 0);", + " return { ok: false, retry: true };", + " }", + "", + " const candidateData = createCandidateList(meshes, options);", + " if (!candidateData.candidates.length || candidateData.totalWeight <= 0) {", + " let message = \"No triangles passed the vertex-group filter.\";", + " if (options.vertexGroupName && candidateData.missingGroups.length) {", + " message += \" \" + candidateData.missingGroups.join(\"; \");", + " }", + " setStatus(object, behavior, message, 0);", + " return { ok: false, retry: false };", + " }", + "", + " const requestedPerRoot =", + " options.outerStrandsPerRoot +", + " (", + " options.undercoatEnabled", + " ? options.undercoatStrandsPerRoot", + " : 0", + " );", + " const maximumRootsFromStrands = Math.max(", + " 1,", + " Math.floor(", + " options.maximumVisualStrands /", + " Math.max(1, requestedPerRoot)", + " )", + " );", + "", + " const outerVerticesPerRoot =", + " options.outerStrandsPerRoot *", + " options.outerCoveragePlanes *", + " (options.outerSegments + 1) *", + " 2;", + " const outerIndicesPerRoot =", + " options.outerStrandsPerRoot *", + " options.outerCoveragePlanes *", + " options.outerSegments *", + " 6;", + " const undercoatVerticesPerRoot =", + " options.undercoatEnabled", + " ? (", + " options.undercoatStrandsPerRoot *", + " (options.undercoatSegments + 1) *", + " 2", + " )", + " : 0;", + " const undercoatIndicesPerRoot =", + " options.undercoatEnabled", + " ? (", + " options.undercoatStrandsPerRoot *", + " options.undercoatSegments *", + " 6", + " )", + " : 0;", + "", + " // Approximate bytes per indexed vertex:", + " // position 12 + normal 12 + RGB 3 + skinIndex 8 +", + " // skinWeight 16 + furMotion 16 + tail down 12 + surface normal 12 = 91 bytes.", + " const vertexBytes =", + " (outerVerticesPerRoot +", + " undercoatVerticesPerRoot) *", + " (sourceIsSkinnedCandidate(", + " candidateData.candidates", + " )", + " ? 91", + " : 67);", + " const indexBytes =", + " (outerIndicesPerRoot +", + " undercoatIndicesPerRoot) *", + " 4;", + " const bytesPerRoot = Math.max(", + " 1,", + " vertexBytes + indexBytes", + " );", + " const maximumRootsFromMemory = Math.max(", + " 1,", + " Math.floor(", + " options.maximumFurMemoryMB *", + " 1024 *", + " 1024 /", + " bytesPerRoot", + " )", + " );", + "", + " const targetRootCount = Math.min(", + " options.rootCount,", + " maximumRootsFromStrands,", + " maximumRootsFromMemory", + " );", + " const random = makeRandom(options.seed || 12345);", + " const rootsByMesh = new Map();", + " let generatedRoots = 0;", + " const regionCounts = {", + " body: 0,", + " tail: 0,", + " leg: 0,", + " paw: 0,", + " ear: 0,", + " head: 0", + " };", + " const maximumAttemptsPerRoot = 80;", + "", + " const addOneRootFromPool = pool => {", + " if (", + " !pool ||", + " !pool.entries ||", + " !pool.entries.length ||", + " pool.totalWeight <= 0", + " ) {", + " return false;", + " }", + "", + " for (", + " let localAttempt = 0;", + " localAttempt < maximumAttemptsPerRoot;", + " localAttempt++", + " ) {", + " const candidate = chooseCandidate(", + " pool.entries,", + " pool.totalWeight,", + " random", + " );", + " if (!candidate) return false;", + "", + " const rootRandom = Math.sqrt(random());", + " const secondRandom = random();", + " const ba = 1 - rootRandom;", + " const bb =", + " rootRandom * (1 - secondRandom);", + " const bc =", + " rootRandom * secondRandom;", + "", + " const groupWeight = clamp(", + " candidate.wa * ba +", + " candidate.wb * bb +", + " candidate.wc * bc,", + " 0,", + " 1", + " );", + " if (", + " groupWeight <", + " options.groupThreshold", + " ) {", + " continue;", + " }", + "", + " const longCoatWeight = clamp(", + " candidate.longWa * ba +", + " candidate.longWb * bb +", + " candidate.longWc * bc,", + " 0,", + " 1", + " );", + " const headHairLengthWeight = clamp(", + " candidate.headLengthWa * ba +", + " candidate.headLengthWb * bb +", + " candidate.headLengthWc * bc,", + " 0,", + " 1", + " );", + " const noseBridgeHairLengthWeight = clamp(", + " candidate.noseBridgeLengthWa * ba +", + " candidate.noseBridgeLengthWb * bb +", + " candidate.noseBridgeLengthWc * bc,", + " 0,", + " 1", + " );", + " const innerEarsHairLengthWeight = clamp(", + " candidate.innerEarsLengthWa * ba +", + " candidate.innerEarsLengthWb * bb +", + " candidate.innerEarsLengthWc * bc,", + " 0,", + " 1", + " );", + "", + " let roots =", + " rootsByMesh.get(candidate.mesh);", + " if (!roots) {", + " roots = [];", + " rootsByMesh.set(", + " candidate.mesh,", + " roots", + " );", + " }", + "", + " const root = createRoot(", + " candidate.mesh,", + " candidate,", + " ba,", + " bb,", + " bc,", + " groupWeight,", + " longCoatWeight,", + " headHairLengthWeight,", + " noseBridgeHairLengthWeight,", + " innerEarsHairLengthWeight,", + " options", + " );", + " roots.push(root);", + " generatedRoots++;", + " regionCounts[root.region] =", + " (regionCounts[root.region] || 0) + 1;", + " return true;", + " }", + " return false;", + " };", + "", + " let backHeadReservedRoots = 0;", + " if (", + " candidateData.backHeadPool &&", + " candidateData.backHeadPool.entries &&", + " candidateData.backHeadPool.entries.length", + " ) {", + " const requestedBackHeadRoots =", + " Math.min(", + " targetRootCount - generatedRoots,", + " Math.floor(", + " targetRootCount *", + " options.minimumBackHeadRootShare", + " )", + " );", + "", + " for (", + " let count = 0;", + " count < requestedBackHeadRoots;", + " count++", + " ) {", + " if (", + " !addOneRootFromPool(", + " candidateData.backHeadPool", + " )", + " ) {", + " break;", + " }", + " backHeadReservedRoots++;", + " }", + " }", + "", + " let topBackReservedRoots = 0;", + " if (", + " candidateData.topBackPool &&", + " candidateData.topBackPool.entries &&", + " candidateData.topBackPool.entries.length", + " ) {", + " const requestedTopBackRoots =", + " Math.min(", + " targetRootCount - generatedRoots,", + " Math.floor(", + " targetRootCount *", + " options.minimumTopBackRootShare", + " )", + " );", + "", + " for (", + " let count = 0;", + " count < requestedTopBackRoots;", + " count++", + " ) {", + " if (", + " !addOneRootFromPool(", + " candidateData.topBackPool", + " )", + " ) {", + " break;", + " }", + " topBackReservedRoots++;", + " }", + " }", + "", + " // Reserve a minimum share for thin regions before the global fill.", + " for (const region of [", + " \"tail\",", + " \"leg\",", + " \"paw\",", + " \"ear\",", + " \"head\"", + " ]) {", + " const pool =", + " candidateData.regionPools[region];", + " if (", + " !pool ||", + " !pool.entries.length", + " ) {", + " continue;", + " }", + "", + " const requested = Math.min(", + " targetRootCount - generatedRoots,", + " Math.floor(", + " targetRootCount *", + " minimumShareForRegion(", + " region,", + " options", + " )", + " )", + " );", + " for (", + " let count = 0;", + " count < requested;", + " count++", + " ) {", + " if (!addOneRootFromPool(pool)) break;", + " }", + " }", + "", + " const globalPool = {", + " entries: candidateData.candidates,", + " totalWeight: candidateData.totalWeight", + " };", + " let failedGlobalAttempts = 0;", + " const maximumGlobalFailures =", + " Math.max(targetRootCount * 5, 250);", + "", + " while (", + " generatedRoots < targetRootCount &&", + " failedGlobalAttempts <", + " maximumGlobalFailures", + " ) {", + " if (", + " addOneRootFromPool(globalPool)", + " ) {", + " failedGlobalAttempts = 0;", + " } else {", + " failedGlobalAttempts++;", + " }", + " }", + "", + " if (!generatedRoots) {", + " setStatus(object, behavior, \"No generated roots passed the vertex-group threshold.\", 0);", + " return { ok: false, retry: false };", + " }", + "", + " const outerLayer = {", + " kind: \"outer\",", + " strandsPerRoot: options.outerStrandsPerRoot,", + " length: options.outerLength,", + " thickness: options.outerThickness,", + " segments: options.outerSegments,", + " rootStiffness: options.outerRootStiffness,", + " spread: options.outerSpread,", + " coverageWidthMultiplier: options.outerCoverageWidthMultiplier,", + " coverageLength: options.outerCoverageLength,", + " planes: options.outerCoveragePlanes,", + " lengthRandomness: options.outerLengthRandomness,", + " colorDarkening: 0", + " };", + " const undercoatLayer = {", + " kind: \"undercoat\",", + " strandsPerRoot: options.undercoatStrandsPerRoot,", + " length: options.undercoatLength,", + " thickness: options.undercoatThickness,", + " segments: options.undercoatSegments,", + " rootStiffness: options.undercoatRootStiffness,", + " spread: options.undercoatSpread,", + " coverageWidthMultiplier: 1,", + " coverageLength: 0.1,", + " planes: 1,", + " lengthRandomness: options.undercoatLengthRandomness,", + " colorDarkening: options.undercoatDarkening", + " };", + "", + " const groups = [];", + " let visualStrands = 0;", + " try {", + " for (const entry of rootsByMesh) {", + " const source = entry[0];", + " const roots = entry[1];", + " if (outerLayer.strandsPerRoot > 0) {", + " groups.push(createLayerGroup(source, roots, outerLayer, options, random));", + " visualStrands += roots.length * outerLayer.strandsPerRoot;", + " }", + " if (options.undercoatEnabled && undercoatLayer.strandsPerRoot > 0) {", + " groups.push(createLayerGroup(source, roots, undercoatLayer, options, random));", + " visualStrands += roots.length * undercoatLayer.strandsPerRoot;", + " }", + " }", + " } catch (error) {", + " for (const group of groups) {", + " if (group.furMesh && group.furMesh.parent) group.furMesh.parent.remove(group.furMesh);", + " if (group.geometry && group.geometry.dispose) group.geometry.dispose();", + " if (group.material && group.material.dispose) group.material.dispose();", + " }", + " console.error(\"[Particle Fur 3D] GPU build failed:\", error);", + " setStatus(object, behavior, \"Could not create GPU-skinned fur: \" + (error && error.message ? error.message : String(error)), 0);", + " return { ok: false, retry: false };", + " }", + "", + " state.groups = groups;", + " state.built = true;", + " state.rootCount = generatedRoots;", + " state.strandCount = visualStrands;", + " state.accumulator = 0;", + " state.time = 0;", + " state.previousX = numberOr(object.getX && object.getX(), 0);", + " state.previousY = numberOr(object.getY && object.getY(), 0);", + " state.previousZ = numberOr(object.getZ && object.getZ(), 0);", + " state.filteredVerticalVelocity = 0;", + " state.tailVerticalResponse = 0;", + " state.tailResponseSign = 0;", + " state.hasPreviousPosition = true;", + " let generatedVertices = 0;", + " let generatedIndices = 0;", + " for (const group of groups) {", + " generatedVertices += group.vertexCount || 0;", + " generatedIndices += group.indexCount || 0;", + " }", + " const estimatedMemoryMB =", + " (", + " generatedVertices *", + " (", + " sourceIsSkinnedCandidate(", + " candidateData.candidates", + " )", + " ? 91", + " : 67", + " ) +", + " generatedIndices * 4", + " ) /", + " (1024 * 1024);", + "", + " let statusMessage =", + " \"Long coat created: \" +", + " generatedRoots +", + " \" roots, \" +", + " visualStrands +", + " \" visual strands, approximately \" +", + " estimatedMemoryMB.toFixed(1) +", + " \" MB. Regions: tail \" +", + " regionCounts.tail +", + " \", legs \" +", + " regionCounts.leg +", + " \", paws \" +", + " regionCounts.paw +", + " \", ears \" +", + " regionCounts.ear +", + " \", head \" +", + " regionCounts.head +", + " \". Back-head reserved roots: \" +", + " backHeadReservedRoots +", + " \". Top/back reserved roots: \" +", + " topBackReservedRoots +", + " \".\";", + " if (generatedRoots < options.rootCount) {", + " statusMessage +=", + " \" The root count was automatically reduced by the memory or strand limit.\";", + " }", + " if (", + " candidateData.flippedNormalMeshCount > 0", + " ) {", + " statusMessage +=", + " \" Corrected inward-facing surface normals on \" +", + " candidateData.flippedNormalMeshCount +", + " \" mesh\" +", + " (", + " candidateData.flippedNormalMeshCount === 1", + " ? \".\"", + " : \"es.\"", + " );", + " }", + "", + " statusMessage +=", + " \" Settings: outer length=\" +", + " fixedNumber(options.outerLength, 5) +", + " (", + " options.scaleHairToModelSize", + " ? \" (model-relative)\"", + " : \" (local units)\"", + " ) +", + " \", size multiplier x\" +", + " fixedNumber(", + " options.modelRelativeSizeMultiplier,", + " 2", + " ) +", + " \", mask expansion=\" +", + " (", + " options.expandRegionalMasks", + " ? (", + " options.regionalMaskExpansionRings +", + " \" ring(s), falloff \" +", + " fixedNumber(", + " options.regionalMaskExpansionFalloff,", + " 2", + " )", + " )", + " : \"off\"", + " ) +", + " \", head x\" +", + " fixedNumber(", + " options.headHairLengthMultiplier,", + " 2", + " ) +", + " \", nose x\" +", + " fixedNumber(", + " options.noseBridgeHairLengthMultiplier,", + " 2", + " ) +", + " \", inner ear x\" +", + " fixedNumber(", + " options.innerEarsHairLengthMultiplier,", + " 2", + " ) +", + " \", stable tail vertical inertia=\" +", + " (", + " options.tailVerticalInertiaEnabled", + " ? (", + " \"on x\" +", + " fixedNumber(", + " options.tailVerticalInertiaInfluence,", + " 2", + " ) +", + " \", fall override at \" +", + " fixedNumber(", + " options.tailFallOverrideResponse,", + " 2", + " ) +", + " \", rest gravity alignment \" +", + " fixedNumber(", + " options.tailRestGravityAlignment,", + " 2", + " )", + " )", + " : \"off\"", + " ) +", + " \". Masks: \" +", + " compactMaskDiagnostics(", + " candidateData.maskDiagnostics", + " );", + "", + " setStatus(", + " object,", + " behavior,", + " statusMessage,", + " visualStrands", + " );", + " M.update(object, behavior, true);", + " return { ok: true, retry: false };", + " };", + "", + " M.update = function (object, behavior, force) {", + " const state = getState(behavior);", + " if (!state.built || !state.groups.length) return;", + " const options = optionsFromBehavior(behavior);", + " const runtimeScene = object.getRuntimeScene ? object.getRuntimeScene() : null;", + " const elapsed = runtimeScene && runtimeScene.getTimeManager ? Math.max(0, runtimeScene.getTimeManager().getElapsedTime() / 1000) : 1 / 60;", + " state.accumulator += elapsed;", + " const interval = 1 / options.updateRate;", + " if (!force && state.accumulator < interval) return;", + " const dt = force ? Math.max(interval, 1 / 60) : Math.max(state.accumulator, 1e-6);", + " state.accumulator = 0;", + " state.time += dt;", + "", + " const currentX = numberOr(object.getX && object.getX(), 0);", + " const currentY = numberOr(object.getY && object.getY(), 0);", + " const currentZ = numberOr(object.getZ && object.getZ(), 0);", + " if (!state.hasPreviousPosition) {", + " state.previousX = currentX;", + " state.previousY = currentY;", + " state.previousZ = currentZ;", + " state.hasPreviousPosition = true;", + " }", + " const velocityX =", + " (currentX - state.previousX) / dt;", + " const velocityY =", + " -(currentY - state.previousY) / dt;", + " const rawVelocityZ = clamp(", + " (currentZ - state.previousZ) / dt,", + " -options.tailVerticalFullSpeed * 4,", + " options.tailVerticalFullSpeed * 4", + " );", + " state.previousX = currentX;", + " state.previousY = currentY;", + " state.previousZ = currentZ;", + "", + " const velocityFilterAlpha =", + " 1 -", + " Math.exp(", + " -dt /", + " Math.max(", + " 0.005,", + " options.tailVerticalVelocitySmoothing", + " )", + " );", + " state.filteredVerticalVelocity +=", + " (", + " rawVelocityZ -", + " state.filteredVerticalVelocity", + " ) *", + " velocityFilterAlpha;", + "", + " // Positive response means falling; negative response means jumping.", + " const verticalSignal =", + " -state.filteredVerticalVelocity;", + " const enterThreshold =", + " options.tailVerticalDeadZone +", + " options.tailVerticalSignHysteresis;", + " const exitThreshold =", + " options.tailVerticalDeadZone;", + " let responseSign =", + " Number(state.tailResponseSign) || 0;", + "", + " if (responseSign === 0) {", + " if (verticalSignal > enterThreshold) {", + " responseSign = 1;", + " } else if (", + " verticalSignal < -enterThreshold", + " ) {", + " responseSign = -1;", + " }", + " } else if (responseSign > 0) {", + " if (verticalSignal < -enterThreshold) {", + " responseSign = -1;", + " } else if (", + " verticalSignal < exitThreshold", + " ) {", + " responseSign = 0;", + " }", + " } else {", + " if (verticalSignal > enterThreshold) {", + " responseSign = 1;", + " } else if (", + " verticalSignal > -exitThreshold", + " ) {", + " responseSign = 0;", + " }", + " }", + " state.tailResponseSign = responseSign;", + "", + " let targetTailResponse = 0;", + " if (", + " options.tailVerticalInertiaEnabled &&", + " responseSign !== 0", + " ) {", + " const signedMagnitude =", + " responseSign > 0", + " ? Math.max(", + " 0,", + " verticalSignal -", + " options.tailVerticalDeadZone", + " )", + " : Math.max(", + " 0,", + " -verticalSignal -", + " options.tailVerticalDeadZone", + " );", + " targetTailResponse =", + " responseSign *", + " clamp(", + " signedMagnitude /", + " Math.max(", + " 1,", + " options.tailVerticalFullSpeed -", + " options.tailVerticalDeadZone", + " ),", + " 0,", + " 1", + " );", + " }", + "", + " const responseAlpha =", + " 1 -", + " Math.exp(", + " -dt /", + " Math.max(", + " 0.005,", + " options.tailVerticalResponseSmoothing", + " )", + " );", + " state.tailVerticalResponse +=", + " (", + " targetTailResponse -", + " state.tailVerticalResponse", + " ) *", + " responseAlpha;", + "", + " if (", + " Math.abs(state.tailVerticalResponse) <", + " 0.0005 &&", + " responseSign === 0", + " ) {", + " state.tailVerticalResponse = 0;", + " }", + "", + " try {", + " const variables =", + " object.getVariables &&", + " object.getVariables();", + " if (variables && variables.get) {", + " const velocityVariable =", + " variables.get(", + " \"ParticleFurVerticalVelocity\"", + " );", + " if (", + " velocityVariable &&", + " velocityVariable.setNumber", + " ) {", + " velocityVariable.setNumber(", + " state.filteredVerticalVelocity", + " );", + " }", + " const responseVariable =", + " variables.get(", + " \"ParticleFurTailVerticalResponse\"", + " );", + " if (", + " responseVariable &&", + " responseVariable.setNumber", + " ) {", + " responseVariable.setNumber(", + " state.tailVerticalResponse", + " );", + " }", + " }", + " } catch (error) {", + " // Debug variables are optional.", + " }", + "", + " const movementX = -velocityX;", + " const movementY = -velocityY;", + " const movementZ =", + " -rawVelocityZ *", + " options.verticalMovementInfluence;", + " const speed = Math.hypot(", + " movementX,", + " movementY,", + " movementZ", + " );", + " const amount = clamp(", + " speed /", + " options.movementVelocityScale,", + " 0,", + " 1", + " );", + " const motion =", + " speed > 1e-9", + " ? {", + " x: movementX / speed,", + " y: movementY / speed,", + " z: movementZ / speed,", + " amount", + " }", + " : {", + " x: 0,", + " y: 0,", + " z: 0,", + " amount: 0", + " };", + "", + " let visible = true;", + " if (options.maximumDistance > 0 && runtimeScene) {", + " try {", + " const rendererObject = object.get3DRendererObject();", + " const worldPosition = rendererObject.getWorldPosition(rendererObject.position.clone());", + " const layerName = object.getLayer ? object.getLayer() : \"\";", + " const camera = runtimeScene.getLayer(layerName).getRenderer().getThreeCamera();", + " visible = !!camera && camera.position.distanceTo(worldPosition) <= options.maximumDistance;", + " } catch (error) {", + " visible = true;", + " }", + " }", + "", + " for (const group of state.groups) {", + " if (group.furMesh) {", + " group.furMesh.visible = visible;", + " }", + " if (visible) {", + " updateGroup(", + " group,", + " options,", + " motion,", + " state.tailVerticalResponse,", + " state.time", + " );", + " }", + " }", + " };", + "", + " M.hasFur = function (behavior) {", + " const state = getState(behavior);", + " return !!(state.built && state.groups && state.groups.length);", + " };", + " M.status = function (behavior) { return String(getState(behavior).status || \"\"); };", + " M.strandCount = function (behavior) { return Number(getState(behavior).strandCount || 0); };", + " M.rootCount = function (behavior) { return Number(getState(behavior).rootCount || 0); };", + "", + " gdjs.__ParticleFur3D_v189 = M;", + "})();const object = objects[0];", + "if (!object) return;", + "const behaviorName = eventsFunctionContext.getBehaviorName(\"Behavior\");", + "const behavior = object.getBehavior(behaviorName);", + "if (!behavior) return;", + "const state = behavior._particleFur3DState || (behavior._particleFur3DState = {", + " groups: [],", + " built: false,", + " status: \"Waiting for the 3D model.\",", + " strandCount: 0,", + " rootCount: 0,", + " retryFrames: 0,", + " lastConfig: \"\",", + " accumulator: 0,", + " time: 0,", + " previousX: 0,", + " previousY: 0,", + " previousZ: 0,", + " filteredVerticalVelocity: 0,", + " tailVerticalResponse: 0,", + " tailResponseSign: 0,", + " hasPreviousPosition: false,", + " warnedKeys: new Set()", + "});", + "state.previousX = Number(object.getX ? object.getX() : 0) || 0;", + "state.previousY = Number(object.getY ? object.getY() : 0) || 0;", + "state.previousZ = Number(object.getZ ? object.getZ() : 0) || 0;", + "state.filteredVerticalVelocity = 0;", + "state.tailVerticalResponse = 0;", + "state.tailResponseSign = 0;", + "state.hasPreviousPosition = true;" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ParticleFur3D::ParticleFur3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "doStepPostEvents", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "if (!object || !gdjs.__ParticleFur3D_v189) return;", + "const behaviorName = eventsFunctionContext.getBehaviorName(\"Behavior\");", + "const behavior = object.getBehavior(behaviorName);", + "if (!behavior) return;", + "const manager = gdjs.__ParticleFur3D_v189;", + "const state = behavior._particleFur3DState || (behavior._particleFur3DState = {", + " groups: [], built: false, status: \"Waiting for the 3D model.\", strandCount: 0,", + " retryFrames: 0, lastConfig: \"\", accumulator: 0, time: 0,", + " previousX: 0, previousY: 0, previousZ: 0, hasPreviousPosition: false,", + " warnedKeys: new Set()", + "});", + "", + "if (!behavior._getEnabled()) {", + " if (state.built) manager.remove(object, behavior, \"Particle fur is disabled.\");", + " return;", + "}", + "", + "const config = manager.configString(behavior);", + "if (state.lastConfig !== config) {", + " if (state.built) manager.remove(object, behavior, \"Fur settings changed. Rebuilding...\");", + " state.lastConfig = config;", + " state.retryFrames = 0;", + " state.built = false;", + "}", + "", + "if (!state.built) {", + " if (state.retryFrames > 0) {", + " state.retryFrames--;", + " return;", + " }", + " const result = manager.build(object, behavior);", + " if (!result.ok) state.retryFrames = result.retry ? 10 : 60;", + " return;", + "}", + "", + "manager.update(object, behavior, false);" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": true + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ParticleFur3D::ParticleFur3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "onDeActivate", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "if (!object || !gdjs.__ParticleFur3D_v189) return;", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "if (behavior) gdjs.__ParticleFur3D_v189.remove(object, behavior, \"The behavior is deactivated.\");" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ParticleFur3D::ParticleFur3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "onActivate", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "if (!object) return;", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "if (!behavior) return;", + "const state = behavior._particleFur3DState;", + "if (state) {", + " state.built = false;", + " state.retryFrames = 0;", + " state.lastConfig = \"\";", + "}" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ParticleFur3D::ParticleFur3D", + "type": "behavior" + } + ], + "objectGroups": [] + }, + { + "fullName": "Regenerate particle fur", + "functionType": "Action", + "name": "RegenerateFur", + "sentence": "Regenerate particle fur on _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "if (!object || !gdjs.__ParticleFur3D_v189) return;", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "if (!behavior) return;", + "gdjs.__ParticleFur3D_v189.remove(object, behavior, \"Regenerating particle fur...\");", + "const state = behavior._particleFur3DState;", + "state.retryFrames = 0;", + "state.lastConfig = \"\";" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ParticleFur3D::ParticleFur3D", + "type": "behavior" + } + ], + "objectGroups": [], + "description": "Removes the current fur and rebuilds it using the behavior settings.", + "group": "Particle fur" + }, + { + "fullName": "Remove particle fur", + "functionType": "Action", + "name": "RemoveFur", + "sentence": "Remove particle fur from _PARAM0_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "if (!object || !gdjs.__ParticleFur3D_v189) return;", + "const behavior = object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\"));", + "if (behavior) gdjs.__ParticleFur3D_v189.remove(object, behavior, \"Particle fur was removed.\");" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ParticleFur3D::ParticleFur3D", + "type": "behavior" + } + ], + "objectGroups": [], + "description": "Removes all generated particle-fur meshes from the object.", + "group": "Particle fur" + }, + { + "fullName": "Has particle fur", + "functionType": "Condition", + "name": "HasFur", + "sentence": "_PARAM0_ has generated particle fur", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object ? object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\")) : null;", + "eventsFunctionContext.returnValue = !!(behavior && gdjs.__ParticleFur3D_v189 && gdjs.__ParticleFur3D_v189.hasFur(behavior));" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ParticleFur3D::ParticleFur3D", + "type": "behavior" + } + ], + "objectGroups": [], + "description": "Checks whether particle fur has been generated successfully.", + "group": "Particle fur" + }, + { + "fullName": "Generated visual strand count", + "functionType": "Expression", + "name": "GeneratedStrandCount", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object ? object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\")) : null;", + "eventsFunctionContext.returnValue = behavior && gdjs.__ParticleFur3D_v189 ? gdjs.__ParticleFur3D_v189.strandCount(behavior) : 0;" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ParticleFur3D::ParticleFur3D", + "type": "behavior" + } + ], + "objectGroups": [], + "description": "Returns the actual number of generated outer-coat and undercoat strands.", + "group": "Particle fur", + "expressionType": { + "type": "expression" + } + }, + { + "fullName": "Generated root count", + "functionType": "Expression", + "name": "GeneratedRootCount", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object ? object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\")) : null;", + "eventsFunctionContext.returnValue = behavior && gdjs.__ParticleFur3D_v189 ? gdjs.__ParticleFur3D_v189.rootCount(behavior) : 0;" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ParticleFur3D::ParticleFur3D", + "type": "behavior" + } + ], + "objectGroups": [], + "description": "Returns the number of generated surface-distribution roots.", + "group": "Particle fur", + "expressionType": { + "type": "expression" + } + }, + { + "fullName": "Particle fur status", + "functionType": "StringExpression", + "name": "LastStatus", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const object = objects[0];", + "const behavior = object ? object.getBehavior(eventsFunctionContext.getBehaviorName(\"Behavior\")) : null;", + "eventsFunctionContext.returnValue = behavior && gdjs.__ParticleFur3D_v189 ? gdjs.__ParticleFur3D_v189.status(behavior) : \"Particle Fur 3D er ikke initialisert.\";" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Object", + "name": "Object", + "type": "object" + }, + { + "description": "Behavior", + "name": "Behavior", + "supplementaryInformation": "ParticleFur3D::ParticleFur3D", + "type": "behavior" + } + ], + "objectGroups": [], + "description": "Returns the latest build, runtime, or error status message.", + "group": "Particle fur", + "expressionType": { + "type": "string" + } + } + ], + "eventsFunctionsFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "functionName": "onCreated" + }, + { + "functionName": "doStepPostEvents" + }, + { + "functionName": "onDeActivate" + }, + { + "functionName": "onActivate" + }, + { + "folderName": "Particle Fur", + "children": [ + { + "functionName": "RegenerateFur" + }, + { + "functionName": "RemoveFur" + }, + { + "functionName": "HasFur" + }, + { + "functionName": "GeneratedStrandCount" + }, + { + "functionName": "GeneratedRootCount" + }, + { + "functionName": "LastStatus" + } + ] + } + ] + }, + "propertyDescriptors": [ + { + "value": "", + "type": "Behavior", + "label": "3D capability", + "description": "Connects the extension to the model object's built-in 3D behavior. Leave this set to Object3D.", + "extraInformation": [ + "Scene3D::Base3DBehavior" + ], + "choices": [], + "name": "Object3D" + }, + { + "value": "true", + "type": "Boolean", + "label": "Enable particle fur", + "description": "Automatically creates and updates the fur at runtime.", + "name": "Enabled" + }, + { + "value": "", + "type": "String", + "label": "Child mesh name", + "description": "Leave empty to use every compatible mesh in the model. Enter an exact child-mesh name to restrict fur generation.", + "name": "MeshName" + }, + { + "value": "", + "type": "String", + "label": "Fur coverage vertex group(s)", + "description": "Restricts where fur may be generated. Separate multiple group names with commas, semicolons, or |. Supports exported attributes and bone names.", + "name": "VertexGroupName" + }, + { + "value": "0.05", + "type": "Number", + "label": "Vertex weight threshold", + "description": "Each generated root must have an interpolated coverage-group weight equal to or greater than this value.", + "name": "GroupThreshold" + }, + { + "value": "false", + "type": "Boolean", + "label": "Invert fur coverage mask", + "description": "Generates fur outside the selected coverage group instead of inside it.", + "name": "InvertVertexGroup" + }, + { + "value": "true", + "type": "Boolean", + "label": "Coverage weight affects length", + "description": "Lower coverage-group weights produce shorter outer-coat hairs.", + "name": "WeightAffectsLength" + }, + { + "value": "false", + "type": "Boolean", + "label": "Use whole mesh if coverage group is missing", + "description": "Not recommended. When enabled, a missing coverage group falls back to the whole mesh instead of generating no fur.", + "name": "UseWholeMeshIfGroupMissing" + }, + { + "value": "true", + "type": "Boolean", + "label": "Automatically correct inward surface normals", + "description": "Detects meshes whose exported normals point toward the mesh center and reverses the fur direction for those meshes. This fixes fur that grows through a custom model and appears only underneath it.", + "name": "AutoCorrectInwardNormals" + }, + { + "value": "false", + "type": "Boolean", + "label": "Manually invert surface normals", + "description": "Manually reverses the generated hair direction after automatic normal detection. Use this when an open or unusual mesh is classified incorrectly.", + "name": "InvertSurfaceNormals" + }, + { + "value": "true", + "type": "Boolean", + "label": "Correct every hair root outward", + "description": "Checks the exact source triangle of every generated root. Locally inverted or mixed vertex normals are aligned with the outward-facing triangle direction instead of relying only on one normal direction for the entire mesh.", + "name": "PerRootOutwardCorrection" + }, + { + "value": "true", + "type": "Boolean", + "label": "Trust imported vertex normals on concave models", + "description": "Uses valid glTF vertex normals and triangle winding instead of flipping every root away from the whole mesh center. This is important for paws, toes, the rear of the head, armpits, and other concave animal-model surfaces.", + "name": "TrustImportedNormals" + }, + { + "value": "0.25", + "type": "Number", + "label": "Minimum root/face normal agreement", + "description": "Minimum dot-product agreement between the interpolated vertex normal and the corrected triangle face normal. Higher values force unreliable custom normals closer to the local surface direction.", + "name": "MinimumFaceNormalAgreement" + }, + { + "value": "true", + "type": "Boolean", + "label": "Prevent fur from moving through the surface", + "description": "Projects gravity, wind, and movement so their inward-facing components are removed. Fur may move along or away from the surface, but dynamic motion cannot push it into the model.", + "name": "PreventSurfacePenetration" + }, + { + "value": "0.06", + "type": "Number", + "label": "Surface safety outward lift", + "description": "Adds a small outward offset to hanging strands after skinning. This helps long tangential coat remain visibly outside the model. The value is relative to the strand length.", + "name": "SurfaceSafetyLift" + }, + { + "value": "true", + "type": "Boolean", + "label": "Regional and length masks extend fur coverage", + "description": "Allows explicit tail, leg, paw, ear, head, long-coat, and regional hair-length masks to add fur where the main Fur coverage vertex group has zero weight or is missing. Automatically detected bone regions may also add coverage.", + "name": "RegionalMasksExtendCoverage" + }, + { + "value": "true", + "type": "Boolean", + "label": "Strict vertex-group attribute matching", + "description": "Only accepts attribute-name variants derived from the requested vertex-group name. A missing head, tail, paw, ear, or length mask will never silently fall back to a generic fur attribute.", + "name": "StrictVertexGroupMatching" + }, + { + "value": "true", + "type": "Boolean", + "label": "Expand head and paw masks into neighboring vertices", + "description": "Expands explicit head, head-length, and paw masks across connected vertices to cover the back of the head, neck transition, feet, toes, and hooves.", + "name": "ExpandRegionalMasks" + }, + { + "value": "2", + "type": "Number", + "label": "Regional mask expansion rings", + "description": "Number of connected edge rings used for mask expansion.", + "name": "RegionalMaskExpansionRings" + }, + { + "value": "0.72", + "type": "Number", + "label": "Regional mask expansion falloff", + "description": "Weight retained through each mask-expansion ring.", + "name": "RegionalMaskExpansionFalloff" + }, + { + "value": "true", + "type": "Boolean", + "label": "Bridge regional masks across nearby disconnected seams", + "description": "Copies head, head-length, paw, and top/back mask weights to nearby vertices even when the GLB contains duplicated seam vertices or separate but touching mesh islands.", + "name": "BridgeRegionalMaskSeams" + }, + { + "value": "0.018", + "type": "Number", + "label": "Regional seam bridge radius", + "description": "Maximum bridge distance as a fraction of the mesh's largest native dimension. Start with 0.018. Increase only when a visible seam remains at the back of the head or around a paw.", + "name": "RegionalSeamBridgeRadius" + }, + { + "value": "0.82", + "type": "Number", + "label": "Regional seam bridge falloff", + "description": "Weight retained when a regional mask crosses a nearby disconnected seam.", + "name": "RegionalSeamBridgeFalloff" + }, + { + "value": "true", + "type": "Boolean", + "label": "Scale hair dimensions to the model's native size", + "description": "Interprets length, thickness, root spread, and surface offset relative to each source mesh's largest local bounding-box dimension. This keeps fur visible on models exported in meters, centimeters, or large custom local units.", + "name": "ScaleHairToModelSize" + }, + { + "value": "1", + "type": "Number", + "label": "Model-relative hair size multiplier", + "description": "Multiplies the automatically measured model-relative hair scale. Use values below 1 for shorter/thinner fur and values above 1 for larger fur without changing every individual dimension setting.", + "name": "ModelRelativeSizeMultiplier" + }, + { + "value": "250", + "type": "Number", + "label": "Maximum automatic hair scale", + "description": "Safety cap for automatic model-relative scaling. Lower this if a mesh contains stray vertices or an unusually large bounding box.", + "name": "MaximumAutomaticHairScale" + }, + { + "value": "5000", + "type": "Number", + "label": "Generated root count", + "description": "Number of distribution roots sampled on the model. Each root may create several outer-coat and undercoat strands.", + "name": "StrandCount" + }, + { + "value": "2", + "type": "Number", + "label": "Outer strands per root", + "description": "Number of long outer-coat strands generated around each distribution root.", + "name": "OuterStrandsPerRoot" + }, + { + "value": "0.025", + "type": "Number", + "label": "Outer-coat length", + "description": "Base outer-coat length in the model's local 3D units.", + "name": "FurLength" + }, + { + "value": "0.0035", + "type": "Number", + "label": "Outer-coat thickness", + "description": "Base width at the root of each outer-coat ribbon.", + "name": "FurThickness" + }, + { + "value": "5", + "type": "Number", + "label": "Outer-coat bend segments", + "description": "Number of segments along each outer-coat strand. More segments produce smoother hanging and wave deformation.", + "name": "OuterBendSegments" + }, + { + "value": "0.48", + "type": "Number", + "label": "Outer-coat root stiffness", + "description": "Higher values keep more of the strand near the root rigid and move most bending toward the tip.", + "name": "OuterRootStiffness" + }, + { + "value": "0.0018", + "type": "Number", + "label": "Outer-coat root spread", + "description": "Spreads strands from the same root over the surface. The runtime limits this relative to strand length to prevent visible separation from the model.", + "name": "OuterRootSpread" + }, + { + "value": "2.2", + "type": "Number", + "label": "Outer-coat base coverage width", + "description": "Widens the lower part of outer-coat ribbons so neighboring strands overlap and hide the skin.", + "name": "OuterCoverageWidthMultiplier" + }, + { + "value": "0.45", + "type": "Number", + "label": "Outer-coat coverage length", + "description": "Fraction of the strand over which the additional base width fades back to normal.", + "name": "OuterCoverageLength" + }, + { + "value": "2", + "type": "Number", + "label": "Outer-coat coverage planes", + "description": "Number of crossed indexed ribbon planes per outer-coat strand. Two planes provide good coverage with moderate memory use.", + "name": "OuterCoveragePlanes" + }, + { + "value": "0.0005", + "type": "Number", + "label": "Surface offset", + "description": "Moves every hair root slightly outward from the model surface.", + "name": "SurfaceOffset" + }, + { + "value": "true", + "type": "Boolean", + "label": "Auto-detect tail, legs, paws, and ears", + "description": "Uses bone names and skin weights to identify thin body regions automatically.", + "name": "AutoRegionBoneDetection" + }, + { + "value": "true", + "type": "Boolean", + "label": "Automatically map common exported fur groups", + "description": "Recognizes BODY, HEAD, FEET, PAWS, EARS, TAIL, and LONGFUR attributes. FEET is mapped to legs while PAWS is mapped only to paws and toes, preventing toe roots from being diluted over the entire lower leg.", + "name": "AutoMapCommonFurGroups" + }, + { + "value": "", + "type": "String", + "label": "Tail region vertex group(s)", + "description": "Optional explicit vertex-group mask for the tail region. It takes priority over automatic classification where its weight is significant.", + "name": "TailRegionGroupName" + }, + { + "value": "", + "type": "String", + "label": "Leg region vertex group(s)", + "description": "Optional explicit vertex-group mask for the legs.", + "name": "LegRegionGroupName" + }, + { + "value": "", + "type": "String", + "label": "Paw region vertex group(s)", + "description": "Optional explicit mask for paws, feet, toes, and claws. This mask controls paw classification, density, reserved roots, and—when regional coverage extension is enabled—whether fur may be created.", + "name": "PawRegionGroupName" + }, + { + "value": "", + "type": "String", + "label": "Ear region vertex group(s)", + "description": "Optional explicit vertex-group mask for the ears.", + "name": "EarRegionGroupName" + }, + { + "value": "", + "type": "String", + "label": "Head region vertex group(s)", + "description": "Optional explicit mask for the head and muzzle. This is a density and coverage region; use the separate head, nose-bridge, and inner-ear length masks to control strand length.", + "name": "HeadRegionGroupName" + }, + { + "value": "", + "type": "String", + "label": "Top/back coverage vertex group(s)", + "description": "Optional explicit coverage mask for the upper back, shoulders, neck top, and back of the head. Multiple names may be separated with commas.", + "name": "TopBackGroupName" + }, + { + "value": "true", + "type": "Boolean", + "label": "Automatically fill top/back coverage gaps", + "description": "Creates a dorsal coverage mask from world-up height and surface orientation, but only near existing fur coverage. This fills bare strips on the upper body and back of the head.", + "name": "AutoTopBackCoverage" + }, + { + "value": "0.54", + "type": "Number", + "label": "Top/back height start", + "description": "Normalized world-up height where automatic dorsal coverage begins. Lower values cover farther down the sides.", + "name": "TopBackHeightStart" + }, + { + "value": "0.5", + "type": "Number", + "label": "Back-head vertical-surface coverage", + "description": "Minimum automatic weight for high vertices whose normals face sideways, such as the vertical rear of the head and neck.", + "name": "TopBackHighVertexBias" + }, + { + "value": "4", + "type": "Number", + "label": "Top/back coverage expansion rings", + "description": "Connected edge rings used to search from existing fur coverage toward the upper back and back of the head.", + "name": "TopBackCoverageExpansionRings" + }, + { + "value": "0.82", + "type": "Number", + "label": "Top/back coverage expansion falloff", + "description": "Weight retained through each top/back coverage expansion ring.", + "name": "TopBackCoverageExpansionFalloff" + }, + { + "value": "3", + "type": "Number", + "label": "Top/back density multiplier", + "description": "Increases root selection density on the upper back and rear-head coverage mask without changing hair length.", + "name": "TopBackDensityMultiplier" + }, + { + "value": "0.16", + "type": "Number", + "label": "Minimum top/back root share", + "description": "Reserves this fraction of the total root budget for upper-back and back-head candidates before the normal global fill.", + "name": "MinimumTopBackRootShare" + }, + { + "value": "0.08", + "type": "Number", + "label": "Top/back root-pool threshold", + "description": "Minimum average top/back mask weight required for a triangle to join the reserved dorsal root pool.", + "name": "TopBackPoolThreshold" + }, + { + "value": "true", + "type": "Boolean", + "label": "Automatically detect the back of the head", + "description": "Builds a rear-head mask from the HEAD group in the direction of the BODY group. No separate back-head vertex group is required.", + "name": "AutoBackHeadCoverage" + }, + { + "value": "0.60", + "type": "Number", + "label": "Back-head region start", + "description": "Normalized position within the HEAD group where the rear-head mask begins. Lower values include more of the head.", + "name": "BackHeadStart" + }, + { + "value": "2", + "type": "Number", + "label": "Back-head expansion rings", + "description": "Connected edge rings added around the detected rear-head mask.", + "name": "BackHeadExpansionRings" + }, + { + "value": "0.82", + "type": "Number", + "label": "Back-head expansion falloff", + "description": "Weight retained through each rear-head expansion ring.", + "name": "BackHeadExpansionFalloff" + }, + { + "value": "4", + "type": "Number", + "label": "Back-head density multiplier", + "description": "Increases root density on the detected rear-facing head surface.", + "name": "BackHeadDensityMultiplier" + }, + { + "value": "0.09", + "type": "Number", + "label": "Minimum back-head root share", + "description": "Reserves this fraction of the root budget specifically for the back of the head before the other regional and global fills.", + "name": "MinimumBackHeadRootShare" + }, + { + "value": "0.05", + "type": "Number", + "label": "Back-head root-pool threshold", + "description": "Minimum rear-head mask weight required for reserved root selection.", + "name": "BackHeadPoolThreshold" + }, + { + "value": "", + "type": "String", + "label": "Long-coat vertex group(s)", + "description": "Optional mask for especially long, dense, hanging, and wavy coat, such as ears, chest, leg furnishings, belly, and tail.", + "name": "LongCoatGroupName" + }, + { + "value": "", + "type": "String", + "label": "Head hair length vertex group(s)", + "description": "Optional vertex-group mask for head hair length. Multiple names may be separated by commas, semicolons, or |. The interpolated vertex weight blends smoothly between the normal length and the head multiplier.", + "name": "HeadHairLengthGroupName" + }, + { + "value": "1.15", + "type": "Number", + "label": "Head hair length multiplier", + "description": "Outer-coat length at full weight in the head length mask. Values below 1 shorten the coat; values above 1 lengthen it.", + "name": "HeadHairLengthMultiplier" + }, + { + "value": "", + "type": "String", + "label": "Nose bridge hair length vertex group(s)", + "description": "Optional vertex-group mask for the bridge of the nose. This specific mask overrides the broad head mask in overlapping areas.", + "name": "NoseBridgeHairLengthGroupName" + }, + { + "value": "0.45", + "type": "Number", + "label": "Nose bridge hair length multiplier", + "description": "Outer-coat length at full weight on the nose bridge. A value around 0.35–0.60 keeps the muzzle and nose bridge short.", + "name": "NoseBridgeHairLengthMultiplier" + }, + { + "value": "", + "type": "String", + "label": "Inner-ear hair length vertex group(s)", + "description": "Optional vertex-group mask for the inner surfaces of the ears. This specific mask overrides the broad head mask where they overlap.", + "name": "InnerEarsHairLengthGroupName" + }, + { + "value": "0.65", + "type": "Number", + "label": "Inner-ear hair length multiplier", + "description": "Outer-coat length at full weight inside the ears. Use a value below 1 for shorter inner-ear hair or above 1 for furnishings.", + "name": "InnerEarsHairLengthMultiplier" + }, + { + "value": "4", + "type": "Number", + "label": "Tail density multiplier", + "description": "Increases root sampling on the tail without increasing torso density by the same amount.", + "name": "TailDensityMultiplier" + }, + { + "value": "2.5", + "type": "Number", + "label": "Leg density multiplier", + "description": "Increases root sampling on the legs.", + "name": "LegDensityMultiplier" + }, + { + "value": "3", + "type": "Number", + "label": "Paw density multiplier", + "description": "Increases root sampling on paws and toes.", + "name": "PawDensityMultiplier" + }, + { + "value": "2.5", + "type": "Number", + "label": "Ear density multiplier", + "description": "Increases root sampling on the ears.", + "name": "EarDensityMultiplier" + }, + { + "value": "2", + "type": "Number", + "label": "Head density multiplier", + "description": "Increases root sampling on triangles classified as the head region.", + "name": "HeadDensityMultiplier" + }, + { + "value": "0.08", + "type": "Number", + "label": "Minimum tail root share", + "description": "Reserves this fraction of all generated roots for the tail when a tail region is available.", + "name": "MinimumTailRootShare" + }, + { + "value": "0.24", + "type": "Number", + "label": "Minimum leg root share", + "description": "Reserves this fraction of all generated roots for the legs when a leg region is available.", + "name": "MinimumLegRootShare" + }, + { + "value": "0.08", + "type": "Number", + "label": "Minimum paw root share", + "description": "Reserves this fraction of all generated roots for paws when a paw region is available.", + "name": "MinimumPawRootShare" + }, + { + "value": "0.05", + "type": "Number", + "label": "Minimum ear root share", + "description": "Reserves this fraction of all generated roots for ears when an ear region is available.", + "name": "MinimumEarRootShare" + }, + { + "value": "0.12", + "type": "Number", + "label": "Minimum head root share", + "description": "Reserves this fraction of all generated roots for the head when a head region is available.", + "name": "MinimumHeadRootShare" + }, + { + "value": "1.8", + "type": "Number", + "label": "Tail fur length multiplier", + "description": "Multiplies outer-coat length on the detected tail region.", + "name": "TailLengthMultiplier" + }, + { + "value": "1.8", + "type": "Number", + "label": "Tail gravity hanging multiplier", + "description": "Additional gravity-sag multiplier applied only to roots classified as tail fur. The displacement is evaluated after skeletal skinning, so animated tail bones cannot rotate world-down sideways.", + "name": "TailGravityHangingMultiplier" + }, + { + "value": "0", + "type": "Number", + "label": "Body gravity hanging multiplier", + "description": "Gravity-hanging multiplier for ordinary body-region outer coat. The default is 0 so normal body fur continues to cover the model surface. Long-coat masks may still enable hanging locally.", + "name": "BodyGravityHangingMultiplier" + }, + { + "value": "1.5", + "type": "Number", + "label": "Leg fur length multiplier", + "description": "Multiplies outer-coat length on the detected leg region.", + "name": "LegLengthMultiplier" + }, + { + "value": "1.25", + "type": "Number", + "label": "Paw fur length multiplier", + "description": "Multiplies outer-coat length on paws and toes.", + "name": "PawLengthMultiplier" + }, + { + "value": "1.8", + "type": "Number", + "label": "Ear fur length multiplier", + "description": "Multiplies outer-coat length on the detected ear region.", + "name": "EarLengthMultiplier" + }, + { + "value": "2", + "type": "Number", + "label": "Long-coat density multiplier", + "description": "Density multiplier at full weight in the long-coat mask.", + "name": "LongCoatDensityMultiplier" + }, + { + "value": "1.8", + "type": "Number", + "label": "Long-coat length multiplier", + "description": "Outer-coat length multiplier at full weight in the long-coat mask.", + "name": "LongCoatLengthMultiplier" + }, + { + "value": "1.35", + "type": "Number", + "label": "Long-coat hanging multiplier", + "description": "Increases downward hanging at full weight in the long-coat mask.", + "name": "LongCoatHangMultiplier" + }, + { + "value": "1.4", + "type": "Number", + "label": "Long-coat wave multiplier", + "description": "Increases traveling-wave motion at full weight in the long-coat mask.", + "name": "LongCoatWaveMultiplier" + }, + { + "value": "120;90;65", + "type": "String", + "label": "Fallback fur color (R;G;B)", + "description": "Used when the model texture cannot be sampled or when model-texture color strength is below 1.", + "name": "FurColor" + }, + { + "value": "true", + "type": "Boolean", + "label": "Use model texture color", + "description": "Samples the model's base-color texture at each generated hair root.", + "name": "UseModelTextureColor" + }, + { + "value": "1", + "type": "Number", + "label": "Model texture color strength", + "description": "1 uses the sampled model texture color. 0 uses only the fallback fur color.", + "name": "ModelTextureColorStrength" + }, + { + "value": "0.25", + "type": "Number", + "label": "Outer-coat length randomness", + "description": "Random length variation applied to outer-coat strands.", + "name": "LengthRandomness" + }, + { + "value": "true", + "type": "Boolean", + "label": "Enable undercoat", + "description": "Creates a separate short and dense undercoat layer.", + "name": "UndercoatEnabled" + }, + { + "value": "3", + "type": "Number", + "label": "Undercoat strands per root", + "description": "Number of short undercoat strands generated at each distribution root.", + "name": "UndercoatStrandsPerRoot" + }, + { + "value": "0.009", + "type": "Number", + "label": "Undercoat length", + "description": "Base length of the short undercoat.", + "name": "UndercoatLength" + }, + { + "value": "0.0042", + "type": "Number", + "label": "Undercoat thickness", + "description": "Base width of undercoat ribbons. Slightly wider strands hide the model surface more effectively.", + "name": "UndercoatThickness" + }, + { + "value": "2", + "type": "Number", + "label": "Undercoat bend segments", + "description": "Number of segments in each undercoat strand.", + "name": "UndercoatBendSegments" + }, + { + "value": "0.90", + "type": "Number", + "label": "Undercoat root stiffness", + "description": "Higher values keep the short undercoat stable close to the skin.", + "name": "UndercoatRootStiffness" + }, + { + "value": "0.002", + "type": "Number", + "label": "Undercoat root spread", + "description": "Spreads undercoat strands around each root to fill gaps.", + "name": "UndercoatRootSpread" + }, + { + "value": "0.18", + "type": "Number", + "label": "Undercoat length randomness", + "description": "Random undercoat length variation. A value of 0.18 produces approximately 18% variation.", + "name": "UndercoatLengthRandomness" + }, + { + "value": "0.06", + "type": "Number", + "label": "Undercoat darkening", + "description": "Darkens the undercoat relative to the sampled model texture color.", + "name": "UndercoatDarkening" + }, + { + "value": "0.05", + "type": "Number", + "label": "Color variation", + "description": "Adds a small random brightness variation between visual strands.", + "name": "ColorVariation" + }, + { + "value": "1", + "type": "Number", + "label": "Wind direction X", + "description": "World-space X component of the wind direction.", + "name": "WindDirectionX" + }, + { + "value": "0", + "type": "Number", + "label": "Wind direction Y", + "description": "World-space Y component of the wind direction.", + "name": "WindDirectionY" + }, + { + "value": "0", + "type": "Number", + "label": "Wind direction Z", + "description": "World-space Z component of the wind direction.", + "name": "WindDirectionZ" + }, + { + "value": "0.02", + "type": "Number", + "label": "Wind strength", + "description": "Controls how strongly wind bends the fur.", + "name": "WindStrength" + }, + { + "value": "1.4", + "type": "Number", + "label": "Wind frequency", + "description": "Controls the speed of wind flutter.", + "name": "WindFrequency" + }, + { + "value": "0.06", + "type": "Number", + "label": "Movement influence", + "description": "Bends the strand shape opposite the object's movement direction. Hair roots remain fixed to the model's skin weights.", + "name": "MovementInfluence" + }, + { + "value": "0", + "type": "Number", + "label": "Vertical movement influence", + "description": "Controls how much jumping and falling contribute to movement bending. Use 0 to keep landing motion conservative.", + "name": "VerticalMovementInfluence" + }, + { + "value": "true", + "type": "Boolean", + "label": "Enable stable tail jump and fall inertia", + "description": "Makes only tail fur react to vertical object movement. Upward jumps bend tail coat downward and falling bends it upward. Every root uses one fixed skinned direction, preventing rapid left/right direction changes.", + "name": "TailVerticalInertiaEnabled" + }, + { + "value": "1.35", + "type": "Number", + "label": "Tail vertical inertia influence", + "description": "Strength of the tail-only jump and fall displacement.", + "name": "TailVerticalInertiaInfluence" + }, + { + "value": "180", + "type": "Number", + "label": "Full tail response vertical speed", + "description": "Vertical object speed that produces the maximum tail response. Lower values make small jumps affect the tail more strongly.", + "name": "TailVerticalFullSpeed" + }, + { + "value": "0.08", + "type": "Number", + "label": "Tail vertical velocity smoothing", + "description": "Low-pass filtering time in seconds for the measured vertical speed. Increase this only when the object's Z position is noisy.", + "name": "TailVerticalVelocitySmoothing" + }, + { + "value": "0.16", + "type": "Number", + "label": "Tail vertical response smoothing", + "description": "Time in seconds used to blend the tail from its current response toward the new jump, fall, or resting state.", + "name": "TailVerticalResponseSmoothing" + }, + { + "value": "8", + "type": "Number", + "label": "Tail vertical movement dead zone", + "description": "Ignores very small vertical speeds so idle position jitter cannot move the tail coat.", + "name": "TailVerticalDeadZone" + }, + { + "value": "6", + "type": "Number", + "label": "Tail jump/fall direction hysteresis", + "description": "Additional speed required before switching directly between jump and fall directions. This prevents rapid sign changes around zero.", + "name": "TailVerticalSignHysteresis" + }, + { + "value": "1.5", + "type": "Number", + "label": "Tail vertical inertia tip emphasis", + "description": "Controls how the effect grows from the fixed root toward the tip. Higher values keep more of the strand base stable.", + "name": "TailVerticalInertiaTipPower" + }, + { + "value": "0.3", + "type": "Number", + "label": "Fall response that fully reverses tail hanging", + "description": "Normalized fall response at which the static downward tail hanging is completely replaced by upward fall lift. Lower values make the tail reverse earlier during a fall.", + "name": "TailFallOverrideResponse" + }, + { + "value": "1", + "type": "Number", + "label": "Tail resting gravity alignment", + "description": "Blends tail resting hang from a surface-safe direction toward true world gravity. Use 1 for hair that hangs vertically downward when the tail points down.", + "name": "TailRestGravityAlignment" + }, + { + "value": "1", + "type": "Number", + "label": "Tail resting hang multiplier", + "description": "Strength multiplier for the normal resting tail hang. Fall lift still replaces the downward hang.", + "name": "TailRestHangMultiplier" + }, + { + "value": "180", + "type": "Number", + "label": "Full movement speed", + "description": "Object speed that produces the maximum movement-bending amount.", + "name": "MovementVelocityScale" + }, + { + "value": "0", + "type": "Number", + "label": "Gravity bend", + "description": "Additional global gravity bending applied to every fur region. Keep this at 0 for normal short body coat; use regional hanging and long-coat masks for controlled downward fur.", + "name": "GravityStrength" + }, + { + "value": "1.15", + "type": "Number", + "label": "Long-fur hanging strength", + "description": "Global scale for regional and long-coat hanging. Ordinary body fur is unaffected while Body gravity hanging multiplier is 0.", + "name": "HangStrength" + }, + { + "value": "0.12", + "type": "Number", + "label": "Hanging start along strand", + "description": "Fraction near the root that remains rigid before downward hanging begins.", + "name": "HangStart" + }, + { + "value": "0.16", + "type": "Number", + "label": "Long-coat wave amplitude", + "description": "Amplitude of the traveling side-to-side wave along outer-coat strands.", + "name": "WaveAmplitude" + }, + { + "value": "1.6", + "type": "Number", + "label": "Waves along strand", + "description": "Number of wave cycles from root to tip.", + "name": "WaveAlongHair" + }, + { + "value": "1.1", + "type": "Number", + "label": "Long-coat wave speed", + "description": "Speed at which the wave travels along the strand.", + "name": "WaveSpeed" + }, + { + "value": "0.04", + "type": "Number", + "label": "Resting wave amount", + "description": "Small wave amount applied while the object is stationary.", + "name": "RestWaveAmount" + }, + { + "value": "1.3", + "type": "Number", + "label": "Movement wave boost", + "description": "Controls how strongly movement speed increases long-coat waves.", + "name": "MovementWaveBoost" + }, + { + "value": "30", + "type": "Number", + "label": "Motion updates per second", + "description": "Updates only shader uniforms such as motion, wind, and time. Static fur geometry is not rewritten every frame.", + "name": "UpdateRate" + }, + { + "value": "100000", + "type": "Number", + "label": "Maximum visual strands", + "description": "Upper limit for the combined number of outer-coat and undercoat strands.", + "name": "MaximumVisualStrands" + }, + { + "value": "96", + "type": "Number", + "label": "Maximum fur memory (MB)", + "description": "Approximate geometry-memory budget. The extension automatically reduces the root count when the estimated budget is exceeded.", + "name": "MaximumFurMemoryMB" + }, + { + "value": "0", + "type": "Number", + "label": "Maximum camera distance", + "description": "Hides the fur beyond this camera distance. Set to 0 to disable distance culling.", + "name": "MaximumDistance" + }, + { + "value": "false", + "type": "Boolean", + "label": "Cast shadows", + "description": "Lets fur cast shadows. This can be expensive with a high strand count.", + "name": "CastShadow" + }, + { + "value": "12345", + "type": "Number", + "label": "Random seed", + "description": "Using the same value produces the same root and strand distribution.", + "name": "Seed" + }, + { + "value": "false", + "type": "Boolean", + "label": "Debug logging", + "description": "Writes build and runtime status messages to the preview console.", + "name": "DebugLog" + }, + { + "value": "tail,cauda,coda", + "type": "String", + "label": "Tail bone keywords", + "description": "Comma-separated substrings used to recognize tail bones automatically.", + "name": "TailBoneKeywords" + }, + { + "value": "leg,thigh,calf,shin,femur,tibia,hock,upperarm,forearm,humerus,radius,ulna", + "type": "String", + "label": "Leg bone keywords", + "description": "Comma-separated substrings used to recognize front- and hind-leg bones automatically.", + "name": "LegBoneKeywords" + }, + { + "value": "paw,paws,foot,feet,toe,toes,digit,claw,hoof,hooves,pastern,fetlock,carpal,metacarp,metatars,ankle,hock", + "type": "String", + "label": "Paw bone keywords", + "description": "Comma-separated substrings used to recognize paw, foot, toe, and digit bones automatically.", + "name": "PawBoneKeywords" + }, + { + "value": "ear", + "type": "String", + "label": "Ear bone keywords", + "description": "Comma-separated substrings used to recognize ear bones automatically.", + "name": "EarBoneKeywords" + }, + { + "value": "head,skull,cranium,muzzle,snout,jaw,neck,cervical,nape,occiput,occipital", + "type": "String", + "label": "Head bone keywords", + "description": "Comma-separated substrings used to identify head and muzzle bones for automatic regional coverage and density.", + "name": "HeadBoneKeywords" + } + ], + "propertiesFolderStructure": { + "folderName": "__ROOT", + "children": [ + { + "folderName": "1. General", + "children": [ + { + "propertyName": "Object3D" + }, + { + "propertyName": "Enabled" + } + ] + }, + { + "folderName": "2. Surface Selection", + "children": [ + { + "propertyName": "MeshName" + }, + { + "propertyName": "VertexGroupName" + }, + { + "propertyName": "GroupThreshold" + }, + { + "propertyName": "InvertVertexGroup" + }, + { + "propertyName": "WeightAffectsLength" + }, + { + "propertyName": "UseWholeMeshIfGroupMissing" + }, + { + "propertyName": "AutoCorrectInwardNormals" + }, + { + "propertyName": "InvertSurfaceNormals" + }, + { + "propertyName": "PerRootOutwardCorrection" + }, + { + "propertyName": "TrustImportedNormals" + }, + { + "propertyName": "MinimumFaceNormalAgreement" + }, + { + "propertyName": "PreventSurfacePenetration" + }, + { + "propertyName": "SurfaceSafetyLift" + }, + { + "propertyName": "RegionalMasksExtendCoverage" + }, + { + "propertyName": "StrictVertexGroupMatching" + }, + { + "propertyName": "ExpandRegionalMasks" + }, + { + "propertyName": "RegionalMaskExpansionRings" + }, + { + "propertyName": "RegionalMaskExpansionFalloff" + }, + { + "propertyName": "BridgeRegionalMaskSeams" + }, + { + "propertyName": "RegionalSeamBridgeRadius" + }, + { + "propertyName": "RegionalSeamBridgeFalloff" + } + ] + }, + { + "folderName": "3. Root Distribution", + "children": [ + { + "propertyName": "StrandCount" + }, + { + "propertyName": "MaximumVisualStrands" + }, + { + "propertyName": "MaximumFurMemoryMB" + }, + { + "propertyName": "SurfaceOffset" + } + ] + }, + { + "folderName": "3. Model-relative Hair Size", + "children": [ + { + "propertyName": "ScaleHairToModelSize" + }, + { + "propertyName": "ModelRelativeSizeMultiplier" + }, + { + "propertyName": "MaximumAutomaticHairScale" + } + ] + }, + { + "folderName": "5. Regional Distribution", + "children": [ + { + "propertyName": "AutoRegionBoneDetection" + }, + { + "propertyName": "AutoMapCommonFurGroups" + }, + { + "propertyName": "TailRegionGroupName" + }, + { + "propertyName": "LegRegionGroupName" + }, + { + "propertyName": "PawRegionGroupName" + }, + { + "propertyName": "EarRegionGroupName" + }, + { + "propertyName": "HeadRegionGroupName" + }, + { + "propertyName": "TopBackGroupName" + }, + { + "propertyName": "AutoTopBackCoverage" + }, + { + "propertyName": "TopBackHeightStart" + }, + { + "propertyName": "TopBackHighVertexBias" + }, + { + "propertyName": "TopBackCoverageExpansionRings" + }, + { + "propertyName": "TopBackCoverageExpansionFalloff" + }, + { + "propertyName": "TopBackDensityMultiplier" + }, + { + "propertyName": "MinimumTopBackRootShare" + }, + { + "propertyName": "TopBackPoolThreshold" + }, + { + "propertyName": "AutoBackHeadCoverage" + }, + { + "propertyName": "BackHeadStart" + }, + { + "propertyName": "BackHeadExpansionRings" + }, + { + "propertyName": "BackHeadExpansionFalloff" + }, + { + "propertyName": "BackHeadDensityMultiplier" + }, + { + "propertyName": "MinimumBackHeadRootShare" + }, + { + "propertyName": "BackHeadPoolThreshold" + }, + { + "propertyName": "LongCoatGroupName" + }, + { + "propertyName": "TailDensityMultiplier" + }, + { + "propertyName": "LegDensityMultiplier" + }, + { + "propertyName": "PawDensityMultiplier" + }, + { + "propertyName": "EarDensityMultiplier" + }, + { + "propertyName": "HeadDensityMultiplier" + }, + { + "propertyName": "MinimumTailRootShare" + }, + { + "propertyName": "MinimumLegRootShare" + }, + { + "propertyName": "MinimumPawRootShare" + }, + { + "propertyName": "MinimumEarRootShare" + }, + { + "propertyName": "MinimumHeadRootShare" + }, + { + "propertyName": "TailLengthMultiplier" + }, + { + "propertyName": "TailGravityHangingMultiplier" + }, + { + "propertyName": "BodyGravityHangingMultiplier" + }, + { + "propertyName": "LegLengthMultiplier" + }, + { + "propertyName": "PawLengthMultiplier" + }, + { + "propertyName": "EarLengthMultiplier" + }, + { + "propertyName": "LongCoatDensityMultiplier" + }, + { + "propertyName": "LongCoatLengthMultiplier" + }, + { + "propertyName": "LongCoatHangMultiplier" + }, + { + "propertyName": "LongCoatWaveMultiplier" + } + ] + }, + { + "folderName": "6. Regional Hair Length Masks", + "children": [ + { + "propertyName": "HeadHairLengthGroupName" + }, + { + "propertyName": "HeadHairLengthMultiplier" + }, + { + "propertyName": "NoseBridgeHairLengthGroupName" + }, + { + "propertyName": "NoseBridgeHairLengthMultiplier" + }, + { + "propertyName": "InnerEarsHairLengthGroupName" + }, + { + "propertyName": "InnerEarsHairLengthMultiplier" + } + ] + }, + { + "folderName": "7. Outer Coat", + "children": [ + { + "propertyName": "OuterStrandsPerRoot" + }, + { + "propertyName": "FurLength" + }, + { + "propertyName": "FurThickness" + }, + { + "propertyName": "OuterBendSegments" + }, + { + "propertyName": "OuterRootStiffness" + }, + { + "propertyName": "OuterRootSpread" + }, + { + "propertyName": "OuterCoverageWidthMultiplier" + }, + { + "propertyName": "OuterCoverageLength" + }, + { + "propertyName": "OuterCoveragePlanes" + }, + { + "propertyName": "LengthRandomness" + } + ] + }, + { + "folderName": "8. Undercoat", + "children": [ + { + "propertyName": "UndercoatEnabled" + }, + { + "propertyName": "UndercoatStrandsPerRoot" + }, + { + "propertyName": "UndercoatLength" + }, + { + "propertyName": "UndercoatThickness" + }, + { + "propertyName": "UndercoatBendSegments" + }, + { + "propertyName": "UndercoatRootStiffness" + }, + { + "propertyName": "UndercoatRootSpread" + }, + { + "propertyName": "UndercoatLengthRandomness" + }, + { + "propertyName": "UndercoatDarkening" + } + ] + }, + { + "folderName": "9. Color", + "children": [ + { + "propertyName": "FurColor" + }, + { + "propertyName": "UseModelTextureColor" + }, + { + "propertyName": "ModelTextureColorStrength" + }, + { + "propertyName": "ColorVariation" + } + ] + }, + { + "folderName": "10. Motion and Long-Coat Waves", + "children": [ + { + "propertyName": "WindDirectionX" + }, + { + "propertyName": "WindDirectionY" + }, + { + "propertyName": "WindDirectionZ" + }, + { + "propertyName": "WindStrength" + }, + { + "propertyName": "WindFrequency" + }, + { + "propertyName": "MovementInfluence" + }, + { + "propertyName": "VerticalMovementInfluence" + }, + { + "propertyName": "TailVerticalInertiaEnabled" + }, + { + "propertyName": "TailVerticalInertiaInfluence" + }, + { + "propertyName": "TailVerticalFullSpeed" + }, + { + "propertyName": "TailVerticalVelocitySmoothing" + }, + { + "propertyName": "TailVerticalResponseSmoothing" + }, + { + "propertyName": "TailVerticalDeadZone" + }, + { + "propertyName": "TailVerticalSignHysteresis" + }, + { + "propertyName": "TailVerticalInertiaTipPower" + }, + { + "propertyName": "TailFallOverrideResponse" + }, + { + "propertyName": "TailRestGravityAlignment" + }, + { + "propertyName": "TailRestHangMultiplier" + }, + { + "propertyName": "MovementVelocityScale" + }, + { + "propertyName": "GravityStrength" + }, + { + "propertyName": "HangStrength" + }, + { + "propertyName": "HangStart" + }, + { + "propertyName": "WaveAmplitude" + }, + { + "propertyName": "WaveAlongHair" + }, + { + "propertyName": "WaveSpeed" + }, + { + "propertyName": "RestWaveAmount" + }, + { + "propertyName": "MovementWaveBoost" + } + ] + }, + { + "folderName": "11. Performance", + "children": [ + { + "propertyName": "UpdateRate" + }, + { + "propertyName": "MaximumDistance" + }, + { + "propertyName": "CastShadow" + } + ] + }, + { + "folderName": "12. Advanced and Debug", + "children": [ + { + "propertyName": "Seed" + }, + { + "propertyName": "DebugLog" + }, + { + "propertyName": "TailBoneKeywords" + }, + { + "propertyName": "LegBoneKeywords" + }, + { + "propertyName": "PawBoneKeywords" + }, + { + "propertyName": "EarBoneKeywords" + }, + { + "propertyName": "HeadBoneKeywords" + } + ] + } + ] + } + } + ], + "eventsBasedObjects": [] +}