载入中...
搜索中...
未找到
DynamicBoneSolver.cpp
浏览该文件的文档.
56 if (!skeleton_ || rootBone<0 || endBone<0 || rootBone>=skeleton_->getBoneCount() || endBone>=skeleton_->getBoneCount()) return result;
57 for (int bone=endBone; bone>=0; bone=skeleton_->getParent(bone)) { result.push_back(bone); if (bone==rootBone) break; }
71int DynamicBoneSolver::addChain(int rootBone,int endBone,float stiffness,float damping,float inertia,float gravityScale,float radius,int iterations) {
79int DynamicBoneSolver::addChainByName(const std::string &root,const std::string &end,float stiffness,float damping,float inertia,float gravityScale,float radius,int iterations) {
85void DynamicBoneSolver::setChainEnabled(int index,bool enabled) { if (index>=0 && index<static_cast<int>(chains_.size())) chains_[static_cast<size_t>(index)].enabled=enabled; }
86bool DynamicBoneSolver::isChainEnabled(int index) const { return index>=0 && index<static_cast<int>(chains_.size()) && chains_[static_cast<size_t>(index)].enabled; }
87void DynamicBoneSolver::setChainFreezeAxis(int index,int axis) { if (index>=0 && index<static_cast<int>(chains_.size())) chains_[static_cast<size_t>(index)].freezeAxis=axis>=1 && axis<=3?axis:0; }
88void DynamicBoneSolver::setChainSelfCollision(int index,bool enabled) { if(index>=0&&index<static_cast<int>(chains_.size()))chains_[static_cast<size_t>(index)].selfCollision=enabled; }
89void DynamicBoneSolver::setChainParticleParameters(int index,int particle,float stiffness,float damping,float inertia,float gravityScale,float radius) {
94 if (chain.particleParameters.size()!=count) chain.particleParameters.assign(count,{chain.stiffness,chain.damping,chain.inertia,chain.gravityScale,chain.radius});
97void DynamicBoneSolver::setChainEndLength(int index,float value) { if (index>=0 && index<static_cast<int>(chains_.size())) { auto &chain=chains_[static_cast<size_t>(index)]; chain.endLength=std::max(value,0.f); chain.endMode=chain.endLength>0.f?1:0; chain.particleParameters.clear(); chain.initialized=false; } }
98void DynamicBoneSolver::setChainEndOffset(int index,float x,float y,float z) { if (index>=0 && index<static_cast<int>(chains_.size())) { auto &chain=chains_[static_cast<size_t>(index)]; chain.endOffset={x,y,z}; chain.endMode=length(x,y,z)>kEpsilon?2:0; chain.particleParameters.clear(); chain.initialized=false; } }
99void DynamicBoneSolver::clearChainEnd(int index) { if (index>=0 && index<static_cast<int>(chains_.size())) { auto &chain=chains_[static_cast<size_t>(index)]; chain.endMode=0; chain.particleParameters.clear(); chain.initialized=false; } }
100void DynamicBoneSolver::setGlobalGravity(float x,float y,float z) { globalGravityX_=x; globalGravityY_=y; globalGravityZ_=z; }
101void DynamicBoneSolver::setExternalForce(float x,float y,float z) { externalForceX_=x; externalForceY_=y; externalForceZ_=z; }
104void DynamicBoneSolver::setTeleportThreshold(float value) { teleportThreshold_=std::max(value,0.f); }
105void DynamicBoneSolver::setObjectMoveResponse(float value) { objectMoveResponse_=clamp01(value); }
106void DynamicBoneSolver::setDistanceReference(float x,float y,float z) { distanceReference_={x,y,z}; }
108bool DynamicBoneSolver::isChainSleeping(int index) const { return index>=0 && index<static_cast<int>(chains_.size()) && chains_[static_cast<size_t>(index)].sleeping; }
109void DynamicBoneSolver::addColliderSphere(float x,float y,float z,float radius) { if (radius>0.f) colliders_.push_back({-1,{},{},{x,y,z},{x,y,z},radius,false,true,false}); }
110void DynamicBoneSolver::addBoneColliderSphere(int bone,float x,float y,float z,float radius) { if (skeleton_ && bone>=0 && bone<skeleton_->getBoneCount() && radius>0.f) colliders_.push_back({bone,{x,y,z},{x,y,z},{},{},radius,false,true,false}); }
111void DynamicBoneSolver::addColliderCapsule(float sx,float sy,float sz,float ex,float ey,float ez,float radius) { if (radius>0.f) colliders_.push_back({-1,{},{},{sx,sy,sz},{ex,ey,ez},radius,true,true,false}); }
112void DynamicBoneSolver::addBoneColliderCapsule(int bone,float sx,float sy,float sz,float ex,float ey,float ez,float radius) { if (skeleton_ && bone>=0 && bone<skeleton_->getBoneCount() && radius>0.f) colliders_.push_back({bone,{sx,sy,sz},{ex,ey,ez},{},{},radius,true,true,false}); }
115void DynamicBoneSolver::removeCollider(int index) { if (index>=0 && index<static_cast<int>(colliders_.size())) colliders_.erase(colliders_.begin()+index); }
116void DynamicBoneSolver::setColliderEnabled(int index,bool enabled) { if (index>=0 && index<static_cast<int>(colliders_.size())) colliders_[static_cast<size_t>(index)].enabled=enabled; }
117void DynamicBoneSolver::setColliderInside(int index,bool inside) { if (index>=0 && index<static_cast<int>(colliders_.size())) colliders_[static_cast<size_t>(index)].inside=inside; }
118void DynamicBoneSolver::setColliderRadius(int index,float radius) { if (index>=0 && index<static_cast<int>(colliders_.size()) && radius>0.f) colliders_[static_cast<size_t>(index)].radius=radius; }
123 for (size_t i=0;i<chain.bones.size();++i) { const auto &w=pose.world(chain.bones[i]); chain.target[i]={w.px,w.py,w.pz}; }
127 if (d>kEpsilon) chain.target.push_back({b.x+dx*chain.endLength/d,b.y+dy*chain.endLength/d,b.z+dz*chain.endLength/d});
130 rotate({w.qx,w.qy,w.qz,w.qw},chain.endOffset.x*w.sx,chain.endOffset.y*w.sy,chain.endOffset.z*w.sz,end.x,end.y,end.z);
133 if (chain.particleParameters.size()!=chain.target.size()) chain.particleParameters.assign(chain.target.size(),{chain.stiffness,chain.damping,chain.inertia,chain.gravityScale,chain.radius});
139 for (size_t i=1;i<chain.target.size();++i) chain.restLength[i-1]=length(chain.target[i].x-chain.target[i-1].x,chain.target[i].y-chain.target[i-1].y,chain.target[i].z-chain.target[i-1].z);
149 const float t=std::clamp(((p.x-c.center.x)*sx+(p.y-c.center.y)*sy+(p.z-c.center.z)*sz)/segmentLengthSquared,0.f,1.f);
166 if (forceField_) { float x=0.f,y=0.f,z=0.f; forceField_->sampleForce(chain.current[i].x,chain.current[i].y,chain.current[i].z,simulationTime_,x,y,z); forceX+=x; forceY+=y; forceZ+=z; }
168 chain.current[i].x+=(chain.current[i].x-chain.previous[i].x)*retention+(globalGravityX_+forceX)*parameters.gravityScale*dt2;
169 chain.current[i].y+=(chain.current[i].y-chain.previous[i].y)*retention+(globalGravityY_+forceY)*parameters.gravityScale*dt2;
170 chain.current[i].z+=(chain.current[i].z-chain.previous[i].z)*retention+(globalGravityZ_+forceZ)*parameters.gravityScale*dt2;
178 if(chain.selfCollision)for(size_t i=1;i<chain.current.size();++i)for(size_t j=i+2;j<chain.current.size();++j){++lastUpdateStats_.selfCollisionTests;Vec3& a=chain.current[i];Vec3& b=chain.current[j];const float dx=b.x-a.x,dy=b.y-a.y,dz=b.z-a.z,d=length(dx,dy,dz);const float minimum=chain.particleParameters[i].radius+chain.particleParameters[j].radius;if(d<minimum&&minimum>0.f){const float nx=d>kEpsilon?dx/d:1.f,ny=d>kEpsilon?dy/d:0.f,nz=d>kEpsilon?dz/d:0.f,correction=(minimum-d)*0.5f;a.x-=nx*correction;a.y-=ny*correction;a.z-=nz*correction;b.x+=nx*correction;b.y+=ny*correction;b.z+=nz*correction;}}
183 for (const auto &collider:colliders_) { ++lastUpdateStats_.colliderTests; resolveCollider(collider,chain.particleParameters[i].radius,b); }
201 float d1=*coordinates[first]-parentCoordinates[first],d2=*coordinates[second]-parentCoordinates[second];
203 const float freeLength=std::sqrt(std::max(chain.restLength[i-1]*chain.restLength[i-1]-frozenDelta*frozenDelta,0.f));
205 if (freeDistance<=kEpsilon) { d1=targetCoordinates[first]-parentCoordinates[first]; d2=targetCoordinates[second]-parentCoordinates[second]; freeDistance=length(d1,d2,0.f); }
206 if (freeDistance>kEpsilon) { *coordinates[first]=parentCoordinates[first]+d1*freeLength/freeDistance; *coordinates[second]=parentCoordinates[second]+d2*freeLength/freeDistance; }
212 rotate({w.qx,w.qy,w.qz,w.qw},c.offset.x*w.sx,c.offset.y*w.sy,c.offset.z*w.sz,c.center.x,c.center.y,c.center.z);
214 rotate({w.qx,w.qy,w.qz,w.qw},c.endOffset.x*w.sx,c.endOffset.y*w.sy,c.endOffset.z*w.sz,c.end.x,c.end.y,c.end.z);
224 if (i+1<chain.bones.size()) { const auto &cw=pose.world(chain.bones[i+1]); animatedX=cw.px-w.px; animatedY=cw.py-w.py; animatedZ=cw.pz-w.pz; }
225 else { animatedX=chain.target[i+1].x-chain.target[i].x; animatedY=chain.target[i+1].y-chain.target[i].y; animatedZ=chain.target[i+1].z-chain.target[i].z; }
226 const Quat delta=fromTo(animatedX,animatedY,animatedZ,chain.current[i+1].x-chain.current[i].x,chain.current[i+1].y-chain.current[i].y,chain.current[i+1].z-chain.current[i].z);
230 if (parent>=0) { const auto &pw=pose.world(parent); desiredLocal=multiply(inverse({pw.qx,pw.qy,pw.qz,pw.qw}),desiredWorld); }
231 const auto &local=pose.local(bone); const Quat result=blend({local.qx,local.qy,local.qz,local.qw},desiredLocal,weight_);
237 if (!skeleton_ || !pose || !std::isfinite(dt) || dt<=0.f || weight_<=0.f || skeleton_->getBoneCount()!=pose->getBoneCount()) return;
245 const float rootDistance=length(chain.target[0].x-distanceReference_.x,chain.target[0].y-distanceReference_.y,chain.target[0].z-distanceReference_.z);
246 if (distanceLimit_>0.f && rootDistance>distanceLimit_) { chain.sleeping=true; chain.initialized=false; ++lastUpdateStats_.sleepingChains; continue; }
248 ++lastUpdateStats_.activeChains;lastUpdateStats_.particles+=static_cast<int>(chain.target.size());lastUpdateStats_.substeps+=steps;
250 const float moveX=chain.target[0].x-chain.current[0].x,moveY=chain.target[0].y-chain.current[0].y,moveZ=chain.target[0].z-chain.current[0].z;
251 if (teleportThreshold_>0.f && length(moveX,moveY,moveZ)>teleportThreshold_) chain.initialized=false;
253 chain.current[i].x+=moveX*objectMoveResponse_; chain.current[i].y+=moveY*objectMoveResponse_; chain.current[i].z+=moveZ*objectMoveResponse_;
266 for(size_t chainIndex=0;chainIndex<chains_.size();++chainIndex){const auto& chain=chains_[chainIndex];for(size_t particle=0;particle<chain.current.size();++particle){const auto& point=chain.current[particle];const float radius=particle<chain.particleParameters.size()?chain.particleParameters[particle].radius:chain.radius;result.particles.push_back({static_cast<int>(chainIndex),static_cast<int>(particle),point.x,point.y,point.z,radius,chain.sleeping});}}
267 for(const auto& collider:colliders_)result.colliders.push_back({collider.center.x,collider.center.y,collider.center.z,collider.end.x,collider.end.y,collider.end.z,collider.radius,collider.capsule,collider.inside,collider.enabled});
Evaluated local (and optional world) pose for an AnimSkeleton. Script type: AnimPose.
Definition AnimPose.h:17
3D bone hierarchy + bind-pose local TRS for skeletal animation. Independent of ik::Skeleton3D (FABRIK...
Definition AnimSkeleton.h:16
void setChainParticleParameters(int chainIndex, int particleIndex, float stiffness, float damping, float inertia, float gravityScale, float radius)
Override simulation parameters for one chain particle, where zero is the root.
Definition DynamicBoneSolver.cpp:89
int addChain(int rootBone, int endBone, float stiffness, float damping, float inertia, float gravityScale=1.f, float radius=0.f, int iterations=4)
Add an ancestor-to-descendant spring chain.
Definition DynamicBoneSolver.cpp:71
DynamicBoneSolver(AnimSkeleton *skeleton)
Construct for a borrowed skeleton, which may be null.
Definition DynamicBoneSolver.cpp:46
bool isChainEnabled(int chainIndex) const
Return enabled state, or false for an invalid index.
Definition DynamicBoneSolver.cpp:86
void setChainSelfCollision(int chainIndex, bool enabled)
Enable or disable non-adjacent particle self-collision for a chain.
Definition DynamicBoneSolver.cpp:88
void setChainEnabled(int chainIndex, bool enabled)
Set a valid chain's enabled state; invalid indices are ignored.
Definition DynamicBoneSolver.cpp:85
void setSkeleton(AnimSkeleton *skeleton)
Rebind the borrowed skeleton; changing it clears index-dependent state.
Definition DynamicBoneSolver.cpp:49
int addChainByName(const std::string &rootBone, const std::string &endBone, float stiffness, float damping, float inertia, float gravityScale=1.f, float radius=0.f, int iterations=4)
Name-based addChain variant; returns -1 for invalid input.
Definition DynamicBoneSolver.cpp:79
void setChainFreezeAxis(int chainIndex, int axis)
Restrict a chain to its animated model-space plane.
Definition DynamicBoneSolver.cpp:87
Definition Animation.cpp:58
Owning renderer-neutral snapshot safe after the solver changes.
Definition DynamicBoneSolver.h:27
std::vector< DynamicBoneDebugParticle > particles
Definition DynamicBoneSolver.h:27
std::vector< DynamicBoneDebugCollider > colliders
Definition DynamicBoneSolver.h:27