Example #1
0
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;
}
Example #3
0
// ----------------------------------------------------------------------------
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));
    }
}
Example #4
0
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;
  }
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #8
0
// 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);
}
Example #9
0
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;
        }
    }

}