예제 #1
0
dBodyID KinematicNodeFixed::attachToODE(PhysicsEnvironment *environment, dSpaceID visualSpaceID, dSpaceID collisionSpaceID, arma::mat44 coordinateFrame)
{
	KinematicNodeDummy::attachToODE(environment, visualSpaceID, collisionSpaceID, coordinateFrame);

	dBodyID body = getODEBody();
	dBodySetKinematic(body);

	return body;
}
예제 #2
0
dBodyID KinematicNodeDummy::attachToODE(PhysicsEnvironment *environment, dSpaceID visualSpaceID, dSpaceID collisionSpaceID, arma::mat44 parentsCoordinateFrame)
{
	// move coordinate frame to current node:
	arma::mat44 coordinateFrame = parentsCoordinateFrame * forwardMatrix;
	dWorldID worldID = environment->getWorldID();

	if (nullptr == m_parent)
	{
		// the body must coincide with the center of mass of the equivalent mass of all dummy children and this nodes masses
		arma::mat44 frame = arma::eye(4, 4);
		dMass equivMass = this->getODEMass(frame);
		for (KinematicNode *child : m_children)
		{
			arma::mat44 childFrame = frame * child->getForwardMatrix();
			dMass childMass = child->getODEMassToAttachToParent(childFrame);
			if (childMass.mass > 0.) {
				dMassAdd(&equivMass, &childMass);
			}
		}

		m_odeNodeBodyOffset = arma::eye(4, 4);
		m_odeNodeBodyOffset(0, 3) = equivMass.c[0];
		m_odeNodeBodyOffset(1, 3) = equivMass.c[1];
		m_odeNodeBodyOffset(2, 3) = equivMass.c[2];

		dMassTranslate(&equivMass, -m_odeNodeBodyOffset(0, 3), -m_odeNodeBodyOffset(1, 3), -m_odeNodeBodyOffset(2, 3));

		// create a body
		m_odeBody = dBodyCreate(worldID);

		arma::mat44 globalSystemBodyOffset = coordinateFrame * m_odeNodeBodyOffset;

		dMatrix3 bodyRotation;
		dVector3 bodyPosition;

		odeUtils::getRotationMatrixAsDMat(globalSystemBodyOffset, bodyRotation);
		odeUtils::getPositionAsDVec(globalSystemBodyOffset, bodyPosition);


		dBodySetPosition(m_odeBody, bodyPosition[0], bodyPosition[1], bodyPosition[2]);
		dBodySetRotation(m_odeBody, bodyRotation);
		if (equivMass.mass > 0.)
		{
			dBodySetMass(m_odeBody, &equivMass);
		} else {
			dBodyGetMass(m_odeBody, &equivMass);
			equivMass.mass = std::numeric_limits<double>::min();
			dBodySetMass(m_odeBody, &equivMass);
		}

	} else {
		// setup the nodeBodyOffset based on the parent's odeBody

		dBodyID body = this->getODEBody();
		const dReal *bodyPosition = dBodyGetPosition(body);
		const dReal *bodyRotation = dBodyGetRotation(body);
		arma::mat44 bodyFrame = odeUtils::getMatFromDMatAndDVec(bodyRotation, bodyPosition);
		arma::mat44 helperRotation = arma::eye(4, 4);

		helperRotation.submat(0, 0, 2, 2) = coordinateFrame.submat(0, 0, 2, 2);

		m_odeNodeBodyOffset = coordinateFrame.i() * bodyFrame;
	}

	// create a "box" to visualize the node
	dGeomID geom = dCreateSphere(visualSpaceID, 0.005);
	dMatrix3 bodyRotation;
	dVector3 bodyPosition;

	// the visuals are defined as "local" coordinates but here we need to incorporate the body offset
	arma::mat44 visualsFrame = m_odeNodeBodyOffset.i();
	odeUtils::getRotationMatrixAsDMat(visualsFrame, bodyRotation); // inverse of rotation part
	odeUtils::getPositionAsDVec(visualsFrame, bodyPosition);

	dGeomSetBody(geom, getODEBody());
	dGeomSetOffsetRotation(geom, bodyRotation);
	dGeomSetOffsetPosition(geom, bodyPosition[0], bodyPosition[1], bodyPosition[2]);

	// finally add all the visuals
	this->attatchODEVisuals(visualsFrame, getODEBody(), collisionSpaceID);


	// recurse into everything attached to this node
	for (KinematicNode *child : m_children)
	{
		dBodyID childBody = child->attachToODE(environment, visualSpaceID, collisionSpaceID, coordinateFrame);
		UNUSED(childBody);
	}

	return m_odeBody;
}