Page 1 of 1

[SOLVED] Rotate camera around constraint object...

Posted: Tue Jun 12, 2018 10:41 pm
by LastBlow
Wanted to ask here while I am trying to figure it out by myself... ;-)))

I am rotating the camera around an object with a constraint applied on it, like when you would turn on yourself while holding an object which would then constantly present the same face to you. Only, despite the constraint, the object rotates as the camera rotates, see 2 pics here attached.

What is the best way to keep the object facing the camera - rotate object in the opposite direction, update basis of the constraint, both?

Thank you in advance for giving it a though!

Re: Rotate around constraint object...

Posted: Thu Jun 14, 2018 3:41 pm
by drleviathan
As the object rotates you want to slave the camera to it such that the camera always looks at a particular face of the object?

Or do you want to slave the object to the camera such that whenever the camera moves the object rotates to present the same face?

If the first: don't use a constraint. Instead just compute the camera's transform as an offset from the object's transform.

If the second: you could use a constraint on the object, but it would be constrained to the world (as opposed to being constrained to another object, or the camera directly) and you would want to update the constraint's target transform whenever the camera moves. Another way to do it would be to make a custom Action that quickly spins the object toward its target transform.

Re: Rotate camera around constraint object...

Posted: Sat Jun 16, 2018 9:49 am
by LastBlow
Thank you for the reply! ;-)))

Yes, there is a constraint applied to the object, so it can be carried around like it was held in a hand while walking and turning around.

Did add the line here below to account for the camera rotation. The object now faces the camera but jerks when grabbed because its initial rotation is overwritten at first by the camera rotation. Now looking into how to take into account the initial object rotation...

Code: Select all

		pickConstraint->getFrameOffsetA().setBasis(glm2bulletR(m_camera->getRotationMatrix()));
`

Re: Rotate around constraint object...

Posted: Mon Jun 18, 2018 3:37 pm
by drleviathan
This is how I reason through such problems:

Define some notation:

Tbw = transform from body to World = body->getWorldTransForm();
Tcw = transform from camera to world = camera->getWorldTransform();
Tbc = transform from body to camera, which will be constant

At the moment the body is grabbed you want to compute the relative transform between it and the camera Tbc and save for later: this will be a constant.

The simplest way to think about it for both GLM and Bullet is: transforms always operate from the left on column vectors to the right. Therefore transform equation is:

Code: Select all

// Tbc = Twc * Tbw = Tcw^-1 * Tbw
btTransform Tbc = camera->getWorldTransform().inverse() * body->getWorldTransform()
Thereafter you want to compute the new Tbw for subsequent values of Twc:

Code: Select all

//Tbw = Tcw * Tbc
btTransform newTbw = camera->getWorldTransform() * Tbc;
Rotations are hard, but maybe that outline is helpful.

Re: Rotate camera around constraint object...

Posted: Thu Jun 21, 2018 8:33 am
by LastBlow
Right, rotations are always harder than translations... ;-)))

Here below the final version - did save the initial transform, then used it to constantly update the basis of the constraint.
Only, make sure there are no other constraints on y, so the object can be rotated around y to face the camera:

Code: Select all

 revolutionSurface->getRigidBody()->setAngularFactor(btVector3(0, 1, 0));     // up straight 
Thank you for your answer, it did help me! Hope it helps someone else one day.

Will mark the post solved.

Code: Select all

void InceptionPhysics::addHitConstraint(const btVector3& endPosition, bool limitAngularMotion) {

	if (m_dynamicsWorld) {

		RayCast rayCast;

		if (!hitObject(glm2bullet(m_camera->getPosition()), endPosition, rayCast))
			return;

		logFileStderr(VERBOSE, "MESSAGE: Picking up object!...\n");

		m_pickedRigidBody = rayCast.rigidBody;
		m_pickedRigidBody->setActivationState(DISABLE_DEACTIVATION);

		m_initialTransform = glm::inverse(m_camera->getRotationMatrix()) * bullet2glm(m_pickedRigidBody->getWorldTransform());

		btTransform transform;
		transform.setIdentity();
		btVector3 localPoint = m_pickedRigidBody->getCenterOfMassTransform().inverse() * rayCast.point;
		transform.setOrigin(localPoint);

		m_previousPickingDistance = (rayCast.point - glm2bullet(m_camera->getPosition())).length();

		m_pickConstraint = new btGeneric6DofConstraint(*m_pickedRigidBody, transform, false);

		float CFM = 0.5f;		// strength constraint all axis 0-5
		float ERP = 0.5f;		// error reduction constraint all axis 0-5

		for (int i = 0; i < 6; i++) {
			m_pickConstraint->setParam(BT_CONSTRAINT_STOP_CFM, CFM, i);
			m_pickConstraint->setParam(BT_CONSTRAINT_STOP_ERP, ERP, i);
		}

		m_dynamicsWorld->addConstraint(m_pickConstraint, true);
	}
}


void InceptionPhysics::moveObject(const btVector3 &position) {
	// logStderr(VERBOSE, "MESSAGE: Moving object...\n");

	if (m_pickedRigidBody) {

		if (!m_pickConstraint)
			return;

		btVector3 target = position - glm2bullet(m_camera->getPosition());
		target.normalize();

		target *= m_previousPickingDistance;
		btVector3 newPivot = glm2bullet(m_camera->getPosition()) + target;

		m_pickConstraint->getFrameOffsetA().setOrigin(newPivot);
		m_pickConstraint->getFrameOffsetA().setBasis(glm2bulletR(m_camera->getRotationMatrix() * m_initialTransform));
	}
}


btMatrix3x3 glm2bulletR(const glm::mat4& matrix) {
	btMatrix3x3 basis;

	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
			basis[j][i] = matrix[i][j];

	return basis;
}