OpenGL - How can I move my 3D model in the screen plane ?

March 25, 2013 - 3:10am #1

Certain applications need to be able to move the augmentation 3D model in a plane parallel to the screen; for instance this is a tyical requirement for applications where the user can drag the object around by tapping on the screen.

This article provides a quick guide on how to achieve that using the ImageTargets sample as a reference.

The first thing you need to do is to add a global variable to keep track of the 3D model overall displacement in the native code in ImageTargets.cpp:

QCAR::Vec3F targetCumulatedDisplacement(0.0f, 0.0f, 0.0f);

then you need to write some code to compute the conversion of the displacement vector from screen-aligned coordinates to object coordinates (i.e. to represent the vector in the target local reference frame):

void
computeTargetTranslationFromScreenVector(float screenDeltaX, float screenDeltaY, 
		QCAR::Matrix44F & modelViewMatrix, QCAR::Vec3F & result)
{
	QCAR::Vec3F screenAlignedDisplacement;
	screenAlignedDisplacement.data[0] = screenDeltaX;
	screenAlignedDisplacement.data[1] = screenDeltaY;
	screenAlignedDisplacement.data[2] = 0.0f;

	// Compute matrix to pass from Eye Coordinates to Object Coordinates
	QCAR::Matrix44F inverseModelViewMatrix = SampleMath::Matrix44FInverse(modelViewMatrix);

	// Convert the screen-aligned displacement vector to Object Coordinates
	// (i.e. in the target local reference frame)
	QCAR::Vec3F localTargetDisplacement = SampleMath::Vec3FTransformNormal(screenAlignedDisplacement, inverseModelViewMatrix);

	// COmpute a speed factor based on the distance of the target object from the camera
	float distanceObjectToCamera = fabs(modelViewMatrix.data[14]);
	float speed = 0.001f * distanceObjectToCamera;// TODO adjust value to your needs

	// set the result taking the speed factor into account
	result.data[0] = speed * localTargetDisplacement.data[0];
	result.data[1] = speed * localTargetDisplacement.data[1];
	result.data[2] = speed * localTargetDisplacement.data[2];
}

Finally, you need to apply the function above to an actual vector that represents your desired 2D scren-aligned motion and to apply the resulting 3D displacement to the translation part of your 3D model; this can be done by adjusting the code in the renderFrame() function in ImageTargets.cpp as follows:

QCAR::Matrix44F modelViewProjection;

        SampleUtils::translatePoseMatrix(0.f, 0.f, kObjectScale,
                                         &modelViewMatrix.data[0]);
        SampleUtils::scalePoseMatrix(kObjectScale, kObjectScale, kObjectScale,
                                     &modelViewMatrix.data[0]);


        float screenDeltaX = 2.0f;// moving to the right 2 pixels every frame
        float screenDeltaY = 0.0f;//

        QCAR::Vec3F targetLocalDisplacement;
        computeTargetTranslationFromScreenVector(screenDeltaX, screenDeltaY, modelViewMatrix, targetLocalDisplacement);


        targetCumulatedDisplacement.data[0] += targetLocalDisplacement.data[0];
        targetCumulatedDisplacement.data[1] += targetLocalDisplacement.data[1];
        targetCumulatedDisplacement.data[2] += targetLocalDisplacement.data[2];


        SampleUtils::translatePoseMatrix(targetCumulatedDisplacement.data[0],
        		targetCumulatedDisplacement.data[1],
        		targetCumulatedDisplacement.data[2],
                                         &modelViewMatrix.data[0]);

        SampleUtils::multiplyMatrix(&projectionMatrix.data[0],
                                    &modelViewMatrix.data[0] ,
                                    &modelViewProjection.data[0]);

 

Topic locked