[SOLVED] Rotate camera around constraint object...

Post Reply
LastBlow
Posts: 18
Joined: Mon Jul 11, 2016 10:36 am
Location: SAN DIEGO

[SOLVED] Rotate camera around constraint object...

Post 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!
Attachments
IMG_4524.PNG
IMG_4524.PNG (881.27 KiB) Viewed 5026 times
IMG_4523.PNG
IMG_4523.PNG (910.9 KiB) Viewed 5026 times
Last edited by LastBlow on Thu Jun 21, 2018 8:46 am, edited 9 times in total.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Rotate around constraint object...

Post 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.
LastBlow
Posts: 18
Joined: Mon Jul 11, 2016 10:36 am
Location: SAN DIEGO

Re: Rotate camera around constraint object...

Post 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()));
`
Last edited by LastBlow on Thu Jun 21, 2018 8:46 am, edited 3 times in total.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Rotate around constraint object...

Post 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.
LastBlow
Posts: 18
Joined: Mon Jul 11, 2016 10:36 am
Location: SAN DIEGO

Re: Rotate camera around constraint object...

Post 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;
}
Post Reply