// ---------------------------------------------------------------------------- ik_node_t* IKSolver::CreateIKNodeFromUrhoNode(const Node* node) { ik_node_t* ikNode = ik_node_create(node->GetID()); // Set initial position/rotation and pass in Node* as user data for later ikNode->original_position = Vec3Urho2IK(node->GetWorldPosition()); ikNode->original_rotation = QuatUrho2IK(node->GetWorldRotation()); ikNode->user_data = (void*)node; /* * If Urho's node has an effector, also create and attach one to the * library's node. At this point, the IKEffector component shouldn't be * holding a reference to any internal effector. Check this for debugging * purposes and log if it does. */ IKEffector* effector = node->GetComponent<IKEffector>(); if (effector != nullptr) { #ifdef DEBUG if (effector->ikEffectorNode_ != NULL) URHO3D_LOGWARNINGF("[ik] IKEffector (attached to node \"%s\") has a reference to a possibly invalid internal effector. Should be NULL.", effector->GetNode()->GetName().CString()); #endif ik_effector_t* ikEffector = ik_effector_create(); ik_node_attach_effector(ikNode, ikEffector); // ownership of effector effector->SetIKSolver(this); effector->SetIKEffectorNode(ikNode); } // Exact same deal with the constraint IKConstraint* constraint = node->GetComponent<IKConstraint>(); if (constraint != nullptr) { #ifdef DEBUG if (constraint->ikConstraintNode_ != NULL) URHO3D_LOGWARNINGF("[ik] IKConstraint (attached to node \"%s\") has a reference to a possibly invalid internal constraint. Should be NULL.", constraint->GetNode()->GetName().CString()); #endif constraint->SetIKConstraintNode(ikNode); } return ikNode; }
// ---------------------------------------------------------------------------- void IKSolver::BuildTreeToEffector(const Node* node) { // Check if the component that was added is an IK effector. If not, then it // does not concern us. IKEffector* effector = static_cast<IKEffector*>(node->GetComponent<IKEffector>()); if (effector == NULL || effector->GetType() != IKEffector::GetTypeStatic()) return; // May need to build tree up to the node where this effector was added. Do // this by following the chain of parent nodes until we hit a node that // exists in the solver's tree. Then iterate backwards again and add each // missing node to the solver's tree. PODVector<const Node*> missingNodes; const Node* iterNode = node; ik_node_t* ikNode = ik_node_find_child(solver_->tree, node->GetID()); while (ikNode == NULL) { missingNodes.Push(iterNode); iterNode = iterNode->GetParent(); ikNode = ik_node_find_child(solver_->tree, iterNode->GetID()); } while (missingNodes.Size() > 0) { iterNode = missingNodes.Back(); missingNodes.Pop(); ik_node_t* ikChildNode = CreateIKNode(iterNode); ik_node_add_child(ikNode, ikChildNode); ikNode = ikChildNode; } // The tip of the tree is the effector. The solver library has ownership of // the effector object, but our IKEffector object also needs to know about // it. ik_effector_t* ikEffector = ik_effector_create(); ik_node_attach_effector(ikNode, ikEffector); // ownership of effector effector->SetIKEffector(ikEffector); // "weak" reference to effector effector->SetIKSolver(this); effectorList_.Push(effector); MarkSolverTreeDirty(); }