Buckets:
ktongue/docker_container / simsite /frontend /node_modules /three-stdlib /animation /CCDIKSolver.cjs
| ; | |
| Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); | |
| const THREE = require("three"); | |
| const _q = /* @__PURE__ */ new THREE.Quaternion(); | |
| const _targetPos = /* @__PURE__ */ new THREE.Vector3(); | |
| const _targetVec = /* @__PURE__ */ new THREE.Vector3(); | |
| const _effectorPos = /* @__PURE__ */ new THREE.Vector3(); | |
| const _effectorVec = /* @__PURE__ */ new THREE.Vector3(); | |
| const _linkPos = /* @__PURE__ */ new THREE.Vector3(); | |
| const _invLinkQ = /* @__PURE__ */ new THREE.Quaternion(); | |
| const _linkScale = /* @__PURE__ */ new THREE.Vector3(); | |
| const _axis = /* @__PURE__ */ new THREE.Vector3(); | |
| const _vector = /* @__PURE__ */ new THREE.Vector3(); | |
| const _matrix = /* @__PURE__ */ new THREE.Matrix4(); | |
| class CCDIKSolver { | |
| /** | |
| * @param {THREE.SkinnedMesh} mesh | |
| * @param {Array<Object>} iks | |
| */ | |
| constructor(mesh, iks = []) { | |
| this.mesh = mesh; | |
| this.iks = iks; | |
| this._valid(); | |
| } | |
| /** | |
| * Update all IK bones. | |
| * | |
| * @return {CCDIKSolver} | |
| */ | |
| update() { | |
| const iks = this.iks; | |
| for (let i = 0, il = iks.length; i < il; i++) { | |
| this.updateOne(iks[i]); | |
| } | |
| return this; | |
| } | |
| /** | |
| * Update one IK bone | |
| * | |
| * @param {Object} ik parameter | |
| * @return {CCDIKSolver} | |
| */ | |
| updateOne(ik) { | |
| const bones = this.mesh.skeleton.bones; | |
| const math = Math; | |
| const effector = bones[ik.effector]; | |
| const target = bones[ik.target]; | |
| _targetPos.setFromMatrixPosition(target.matrixWorld); | |
| const links = ik.links; | |
| const iteration = ik.iteration !== void 0 ? ik.iteration : 1; | |
| for (let i = 0; i < iteration; i++) { | |
| let rotated = false; | |
| for (let j = 0, jl = links.length; j < jl; j++) { | |
| const link = bones[links[j].index]; | |
| if (links[j].enabled === false) | |
| break; | |
| const limitation = links[j].limitation; | |
| const rotationMin = links[j].rotationMin; | |
| const rotationMax = links[j].rotationMax; | |
| link.matrixWorld.decompose(_linkPos, _invLinkQ, _linkScale); | |
| _invLinkQ.invert(); | |
| _effectorPos.setFromMatrixPosition(effector.matrixWorld); | |
| _effectorVec.subVectors(_effectorPos, _linkPos); | |
| _effectorVec.applyQuaternion(_invLinkQ); | |
| _effectorVec.normalize(); | |
| _targetVec.subVectors(_targetPos, _linkPos); | |
| _targetVec.applyQuaternion(_invLinkQ); | |
| _targetVec.normalize(); | |
| let angle = _targetVec.dot(_effectorVec); | |
| if (angle > 1) { | |
| angle = 1; | |
| } else if (angle < -1) { | |
| angle = -1; | |
| } | |
| angle = math.acos(angle); | |
| if (angle < 1e-5) | |
| continue; | |
| if (ik.minAngle !== void 0 && angle < ik.minAngle) { | |
| angle = ik.minAngle; | |
| } | |
| if (ik.maxAngle !== void 0 && angle > ik.maxAngle) { | |
| angle = ik.maxAngle; | |
| } | |
| _axis.crossVectors(_effectorVec, _targetVec); | |
| _axis.normalize(); | |
| _q.setFromAxisAngle(_axis, angle); | |
| link.quaternion.multiply(_q); | |
| if (limitation !== void 0) { | |
| let c = link.quaternion.w; | |
| if (c > 1) | |
| c = 1; | |
| const c2 = math.sqrt(1 - c * c); | |
| link.quaternion.set(limitation.x * c2, limitation.y * c2, limitation.z * c2, c); | |
| } | |
| if (rotationMin !== void 0) { | |
| link.rotation.setFromVector3(_vector.setFromEuler(link.rotation).max(rotationMin)); | |
| } | |
| if (rotationMax !== void 0) { | |
| link.rotation.setFromVector3(_vector.setFromEuler(link.rotation).min(rotationMax)); | |
| } | |
| link.updateMatrixWorld(true); | |
| rotated = true; | |
| } | |
| if (!rotated) | |
| break; | |
| } | |
| return this; | |
| } | |
| /** | |
| * Creates Helper | |
| * | |
| * @return {CCDIKHelper} | |
| */ | |
| createHelper() { | |
| return new CCDIKHelper(this.mesh, this.iks); | |
| } | |
| // private methods | |
| _valid() { | |
| const iks = this.iks; | |
| const bones = this.mesh.skeleton.bones; | |
| for (let i = 0, il = iks.length; i < il; i++) { | |
| const ik = iks[i]; | |
| const effector = bones[ik.effector]; | |
| const links = ik.links; | |
| let link0, link1; | |
| link0 = effector; | |
| for (let j = 0, jl = links.length; j < jl; j++) { | |
| link1 = bones[links[j].index]; | |
| if (link0.parent !== link1) { | |
| console.warn("THREE.CCDIKSolver: bone " + link0.name + " is not the child of bone " + link1.name); | |
| } | |
| link0 = link1; | |
| } | |
| } | |
| } | |
| } | |
| function getPosition(bone, matrixWorldInv) { | |
| return _vector.setFromMatrixPosition(bone.matrixWorld).applyMatrix4(matrixWorldInv); | |
| } | |
| function setPositionOfBoneToAttributeArray(array, index, bone, matrixWorldInv) { | |
| const v = getPosition(bone, matrixWorldInv); | |
| array[index * 3 + 0] = v.x; | |
| array[index * 3 + 1] = v.y; | |
| array[index * 3 + 2] = v.z; | |
| } | |
| class CCDIKHelper extends THREE.Object3D { | |
| constructor(mesh, iks = [], sphereSize = 0.25) { | |
| super(); | |
| this.root = mesh; | |
| this.iks = iks; | |
| this.matrix.copy(mesh.matrixWorld); | |
| this.matrixAutoUpdate = false; | |
| this.sphereGeometry = new THREE.SphereGeometry(sphereSize, 16, 8); | |
| this.targetSphereMaterial = new THREE.MeshBasicMaterial({ | |
| color: new THREE.Color(16746632), | |
| depthTest: false, | |
| depthWrite: false, | |
| transparent: true | |
| }); | |
| this.effectorSphereMaterial = new THREE.MeshBasicMaterial({ | |
| color: new THREE.Color(8978312), | |
| depthTest: false, | |
| depthWrite: false, | |
| transparent: true | |
| }); | |
| this.linkSphereMaterial = new THREE.MeshBasicMaterial({ | |
| color: new THREE.Color(8947967), | |
| depthTest: false, | |
| depthWrite: false, | |
| transparent: true | |
| }); | |
| this.lineMaterial = new THREE.LineBasicMaterial({ | |
| color: new THREE.Color(16711680), | |
| depthTest: false, | |
| depthWrite: false, | |
| transparent: true | |
| }); | |
| this._init(); | |
| } | |
| /** | |
| * Updates IK bones visualization. | |
| */ | |
| updateMatrixWorld(force) { | |
| const mesh = this.root; | |
| if (this.visible) { | |
| let offset = 0; | |
| const iks = this.iks; | |
| const bones = mesh.skeleton.bones; | |
| _matrix.copy(mesh.matrixWorld).invert(); | |
| for (let i = 0, il = iks.length; i < il; i++) { | |
| const ik = iks[i]; | |
| const targetBone = bones[ik.target]; | |
| const effectorBone = bones[ik.effector]; | |
| const targetMesh = this.children[offset++]; | |
| const effectorMesh = this.children[offset++]; | |
| targetMesh.position.copy(getPosition(targetBone, _matrix)); | |
| effectorMesh.position.copy(getPosition(effectorBone, _matrix)); | |
| for (let j = 0, jl = ik.links.length; j < jl; j++) { | |
| const link = ik.links[j]; | |
| const linkBone = bones[link.index]; | |
| const linkMesh = this.children[offset++]; | |
| linkMesh.position.copy(getPosition(linkBone, _matrix)); | |
| } | |
| const line = this.children[offset++]; | |
| const array = line.geometry.attributes.position.array; | |
| setPositionOfBoneToAttributeArray(array, 0, targetBone, _matrix); | |
| setPositionOfBoneToAttributeArray(array, 1, effectorBone, _matrix); | |
| for (let j = 0, jl = ik.links.length; j < jl; j++) { | |
| const link = ik.links[j]; | |
| const linkBone = bones[link.index]; | |
| setPositionOfBoneToAttributeArray(array, j + 2, linkBone, _matrix); | |
| } | |
| line.geometry.attributes.position.needsUpdate = true; | |
| } | |
| } | |
| this.matrix.copy(mesh.matrixWorld); | |
| super.updateMatrixWorld(force); | |
| } | |
| /** | |
| * Frees the GPU-related resources allocated by this instance. Call this method whenever this instance is no longer used in your app. | |
| */ | |
| dispose() { | |
| this.sphereGeometry.dispose(); | |
| this.targetSphereMaterial.dispose(); | |
| this.effectorSphereMaterial.dispose(); | |
| this.linkSphereMaterial.dispose(); | |
| this.lineMaterial.dispose(); | |
| const children = this.children; | |
| for (let i = 0; i < children.length; i++) { | |
| const child = children[i]; | |
| if (child.isLine) | |
| child.geometry.dispose(); | |
| } | |
| } | |
| // private method | |
| _init() { | |
| const scope = this; | |
| const iks = this.iks; | |
| function createLineGeometry(ik) { | |
| const geometry = new THREE.BufferGeometry(); | |
| const vertices = new Float32Array((2 + ik.links.length) * 3); | |
| geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3)); | |
| return geometry; | |
| } | |
| function createTargetMesh() { | |
| return new THREE.Mesh(scope.sphereGeometry, scope.targetSphereMaterial); | |
| } | |
| function createEffectorMesh() { | |
| return new THREE.Mesh(scope.sphereGeometry, scope.effectorSphereMaterial); | |
| } | |
| function createLinkMesh() { | |
| return new THREE.Mesh(scope.sphereGeometry, scope.linkSphereMaterial); | |
| } | |
| function createLine(ik) { | |
| return new THREE.Line(createLineGeometry(ik), scope.lineMaterial); | |
| } | |
| for (let i = 0, il = iks.length; i < il; i++) { | |
| const ik = iks[i]; | |
| this.add(createTargetMesh()); | |
| this.add(createEffectorMesh()); | |
| for (let j = 0, jl = ik.links.length; j < jl; j++) { | |
| this.add(createLinkMesh()); | |
| } | |
| this.add(createLine(ik)); | |
| } | |
| } | |
| } | |
| exports.CCDIKHelper = CCDIKHelper; | |
| exports.CCDIKSolver = CCDIKSolver; | |
| //# sourceMappingURL=CCDIKSolver.cjs.map | |
Xet Storage Details
- Size:
- 9.14 kB
- Xet hash:
- 8b122b41e9a54ccef6e86584f6974ba3a5074f15f6836847e4b585fee7cd8f58
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.