void CollisionShape::NodeChanged() { Node *n = node; while (n) { auto rigidBody = n->GetComponent<RigidBody>(); if (rigidBody) { rigidBody->UpdateCollisionShapes(); break; } n = n->GetParent(); } }
// 4.6 Write an algorithm to find the 'next' node (i.e., in-order successor) of a given node in a binary search tree. Node* Tree::FindSuccessor(Node* node) { if(node->GetRight() != NULL) { // node has right child/subtree node = node->GetRight(); while(node->GetLeft() != NULL) { // go to the left-most node (min node) in the right subtree node = node->GetLeft(); } return node; } Node* parent = node->GetParent(); // go up the tree until we encounter a node that is the left child of its parent while(parent != NULL && node == parent->GetRight()) { node = parent; parent = parent->GetParent(); } return parent; }
// ---------------------------------------------------------------------------- void IKSolver::HandleComponentAdded(Scene *,Node *node,Component *component) { /* * When a solver gets added into the scene, any parent solver's tree will * be invalidated. We need to find all parent solvers (by iterating up the * tree) and mark them as such. */ if (component->GetType() == IKSolver::GetTypeStatic()) { for (Node* iterNode = node; iterNode != nullptr; iterNode = iterNode->GetParent()) { IKSolver* parentSolver = iterNode->GetComponent<IKSolver>(); if (parentSolver != nullptr) parentSolver->MarkTreeNeedsRebuild(); } return; // No need to continue processing effectors or constraints } if (solver_->tree == nullptr) return; /* * Update tree if component is an effector and is part of our subtree. */ if (component->GetType() == IKEffector::GetTypeStatic()) { // Not interested in components that won't be part of our if (ComponentIsInOurSubtree(component) == false) return; BuildTreeToEffector(static_cast<IKEffector*>(component)); effectorList_.push_back(static_cast<IKEffector*>(component)); return; } if (component->GetType() == IKConstraint::GetTypeStatic()) { if (ComponentIsInOurSubtree(component) == false) return; constraintList_.push_back(static_cast<IKConstraint*>(component)); } }
Skein::Node* Skein::GetThreadTop(Node* node) { while (true) { Node* parent = node->GetParent(); if (parent == NULL) { ASSERT(FALSE); return node; } if (parent->GetNumChildren() != 1) return node; if (parent->GetParent() == NULL) return node; node = parent; } }
bool Skein::GetLineFromHistory(CStringW& line, int history) { // Find the node to return the line from Node* node = m_inst.current; while (--history > 0) { node = node->GetParent(); if (node == NULL) return false; } // Don't return the root node if (node == m_inst.root) return false; line = EscapeLine(node->GetLine(),RemoveEscapes); return true; }
bool RBT::Delete(Node* toDelete) { if (!toDelete) return false; COLOR deletedColor = toDelete->GetColor(); Node* toFix; if (toDelete->GetLeft() == NIL) { toFix = toDelete->GetRight(); Transplant(toDelete, toDelete->GetRight()); } else if (toDelete->GetRight() == NIL) { toFix = toDelete->GetLeft(); Transplant(toDelete, toDelete->GetLeft()); } else { Node* successor = GetSuccessorOf(toDelete); deletedColor = successor->GetColor(); toFix = successor->GetRight(); if (successor->GetParent() == NIL) toFix->SetParent(successor); else { Transplant(successor, successor->GetRight()); successor->SetRight(toDelete->GetRight()); successor->GetRight()->SetParent(successor); } Transplant(toDelete, successor); successor->SetLeft(toDelete->GetLeft()); successor->GetLeft()->SetParent(successor); successor->SetColor(toDelete->GetColor()); } if (deletedColor == BLACK) FixDeletion(toFix); return true; }
Node* GetNextNode(Node *node) { assert(node != NULL); Node* next = node->GetFirstChild(); if(next) return next; next = node->GetSlibing(); if(next) return next; next = node->GetParent(); while (next) { next = next->GetSlibing(); if(next) return next; next = next->GetParent(); } return NULL; }
// the main update method void CCDIKSolver::Update(const float timeDeltaInSeconds) { // if we are using cloned nodes if (mStartNode_Clone != mStartNode) { // make sure that the cloned nodes are all still attached to the root of the chain // they can and will become distant if we dont do this Matrix mat = mStartNode_Clone->GetLocalTM(); mat.SetTranslation(mStartNode->GetLocalTM().GetTranslation()); mStartNode_Clone->SetLocalTM(mat); mStartNode_Clone->RecursiveUpdateWorldTM(NULL); } // some values we need int curIteration = 0; float dist = FLT_MAX; Node* curNode = mEndNode_Clone->GetParent(); // the CCD iteration loop while (curIteration < mMaxIterations && dist > mDistThreshold) { // required bone positions Vector3 rootPos = curNode->GetWorldPos(); Vector3 curEnd = mEndNode_Clone->GetWorldPos(); Vector3 desiredEnd = mGoal; // if we are far enough from the goal dist = (desiredEnd - curEnd).SquareLength(); if (dist > mDistThreshold) { // vector to the current effector pos Vector3 curVector = (curEnd - rootPos).Normalize(); // desired effector position vector Vector3 targetVector = (mGoal - rootPos).Normalize(); // calculate the cosine angle const float cosAngle = targetVector.Dot( curVector ); // if the dot product is 1, we don't need to rotate, since it is 0 degrees if (cosAngle < 0.99999f) { // calculate the rotation axis Vector3 crossResult = curVector.Cross( targetVector ); crossResult.Normalize(); // get the rotation angle in radians const float turnAngle = Math::ACos( cosAngle ); // rotate our matrix Matrix rotMat; rotMat.SetRotationMatrixAxisAngle(crossResult, turnAngle); Matrix tempMat = curNode->GetWorldTM() * rotMat; tempMat.SetTranslation( curNode->GetWorldPos() ); // Get our rotational limit attribute NodeLimitAttribute* attribute = (NodeLimitAttribute*)curNode->GetAttributeByType( NodeLimitAttribute::TYPE_ID ); // no need to do all these calculations if there is no valid NodeLimitAttribute or if the user // doesnt want us to do joint limits, or if there is no parent to constrain against if (attribute && mDoJointLimits && (curNode->GetParent() != NULL)) { // NOTE: 3DS Max seems to need us to invert the angles // TODO: verify this with Maya Vector3 min = -attribute->GetRotationMax(); Vector3 max = -attribute->GetRotationMin(); // Instead of: // Vector3 max = attribute->GetRotationMax(); // Vector3 min = attribute->GetRotationMin(); // convert the matrix into local coordinates of the node tempMat *= curNode->GetParent()->GetWorldTM().Inversed(); // calculate the euler representation of this matrix Vector3 tempEuler = tempMat.CalcEulerAngles(); // apply the constraints (simple cliping) if (tempEuler.x > max.x) tempEuler.x = max.x; if (tempEuler.x < min.x) tempEuler.x = min.x; if (tempEuler.y > max.y) tempEuler.y = max.y; if (tempEuler.y < min.y) tempEuler.y = min.y; if (tempEuler.z > max.z) tempEuler.z = max.z; if (tempEuler.z < min.z) tempEuler.z = min.z; // rebuild the matrix from the modified euler angles tempMat.SetRotationMatrixEuler(tempEuler); // convert back into world co-ordinates tempMat *= curNode->GetParent()->GetWorldTM(); } // add correct scale and translation to the rotation matrix Vector3 scale = curNode->GetWorldScale(); tempMat.Scale(scale.x, scale.y, scale.z); tempMat.SetTranslation( curNode->GetWorldPos() ); // recursively update the world TM (forward kinematics) curNode->RecursiveUpdateWorldTM( &tempMat ); } // go one node up in the hierarchy (towards the front of the chain) curNode = curNode->GetParent(); // if we reach the start of the chain, go to the end again and increment the iteration counter if (curNode == mStartNode_Clone->GetParent()) { curNode = mEndNode_Clone->GetParent(); curIteration++; } } } // check if we found a solution if (curIteration >= mMaxIterations) mHasSolution = false; else mHasSolution = true; // if we are not using cloned nodes // then we dont need to copy the positions from the cloned chain into the real chain if (mStartNode_Clone == mStartNode) return; // copy the positions of all the cloned nodes into the real nodes Node *n1 = mEndNode_Clone; Node *n2 = mEndNode; while (true) { n2->SetWorldTM( n1->GetWorldTM() ); n2->SetLocalTM( n1->GetLocalTM() ); n1 = n1->GetParent(); n2 = n2->GetParent(); if (n1 == mStartNode_Clone->GetParent() || n2 == mStartNode->GetParent()) { if (n1 == mStartNode_Clone->GetParent() && n2 == mStartNode->GetParent()) break; else { LOG("Something is VERY wrong in the CCD controller"); LOG("n1='%s' - n2='%s'", n1->GetName().AsChar(), n2->GetName().AsChar()); break; } } } // make sure that all the children that AREN'T in the cloned chain are updated properly mStartNode->RecursiveUpdateWorldTM(NULL); }
TEST_F(NodeTest, NodeInitiallyHasNoParent) { Node testObject; EXPECT_EQ((INode*)0, testObject.GetParent()); }
void SceneView3D::HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData) { // Visualize the currently selected nodes if (selectedNode_.NotNull()) { DrawNodeDebug(selectedNode_, debugRenderer_); } if (!MouseInView()) return; Input* input = GetSubsystem<Input>(); mouseLeftDown_ = false; if (input->GetMouseButtonPress(MOUSEB_LEFT)) { SetFocus(); if (!mouseMoved_ && !sceneEditor_->GetGizmo()->Selected()) { Ray camRay = GetCameraRay(); PODVector<RayQueryResult> result; RayOctreeQuery query(result, camRay, RAY_TRIANGLE, camera_->GetFarClip(), DRAWABLE_GEOMETRY, 0x7fffffff); octree_->RaycastSingle(query); if (query.result_.Size()) { const RayQueryResult& r = result[0]; if (r.drawable_) { VariantMap neventData; Node* node = r.drawable_->GetNode(); // if temporary, this is a prefab // TODO: if we use temporary for other stuff // fix this to look for prefab if (node->IsTemporary()) node = node->GetParent(); neventData[EditorActiveNodeChange::P_NODE] = node; SendEvent(E_EDITORACTIVENODECHANGE, neventData); } } } mouseMoved_ = false; } else if (!input->GetMouseButtonDown(MOUSEB_LEFT)) { Ray camRay = GetCameraRay(); PODVector<RayQueryResult> result; mouseMoved_ = false; /* Array<int> pickModeDrawableFlags = { DRAWABLE_GEOMETRY, DRAWABLE_LIGHT, DRAWABLE_ZONE }; */ RayOctreeQuery query(result, camRay, RAY_TRIANGLE, camera_->GetFarClip(), DRAWABLE_GEOMETRY, 0x7fffffff); octree_->RaycastSingle(query); if (query.result_.Size()) { const RayQueryResult& r = result[0]; if (r.drawable_) { debugRenderer_->AddNode(r.drawable_->GetNode(), 1.0, false); r.drawable_->DrawDebugGeometry(debugRenderer_, false); } } } else { mouseLeftDown_ = true; if (Abs(input->GetMouseMoveX() > 3 || input->GetMouseMoveY() > 3)) { mouseMoved_ = true; } } }