I am trying to implement a virtual trackball system, which when the user clicks and drags the mouse - the model is rotated.
I can't seem to find the problem in my code, which is based on quaternions. When the program is run, the model just jumps and does not rotate.
Please help, I have been through numerous maths tutorials, just can't see what is missing. I am sure it will be something obvious.
Thank you for any help.
#include "DarkGDK.h"
void user_Input(void);
void set_MouseVec(int vector_id);
void multiply_Quaternions(int vector_a, int vector_b, int vector_result);
void set_CameraQuaternion(int camera_id, int vector_result);
int initial_position = 0;
// the main entry point for the application is this function
void DarkGDK ( void ) {
// in this application we are going to create some 3D objects
// and position them on screen
// when starting a Dark GDK program it is useful to set global
// application properties, we begin by turning the sync rate on,
// this means we control when the screen is updated, we also set
// the maximum rate to 60 which means the maximum frame rate will
// be set at 60 frames per second
dbSyncOn( );
dbSyncRate ( 60 );
// set our random seed to a value from the timer, this will help
// to ensure each time we run our program the random values appear
// more random
dbRandomize( dbTimer ( ) );
// make some 3D objects
for ( int i = 1; i < 10; i++ )
{
// make a sphere
dbMakeObjectSphere( i, 1 );
// position the object in a random location
dbPositionObject( i, dbRnd ( 20 ), dbRnd ( 20 ), dbRnd ( 20 ) );
// adjust scaling
dbScaleObject ( i, 100 + dbRnd ( 400 ), 100 + dbRnd ( 400 ), 100 + dbRnd ( 400 ) );
// give the object a color
dbColorObject ( i, dbRgb ( dbRnd ( 255 ), dbRnd ( 255 ), dbRnd ( 255 ) ) );
// increase specular power
dbSetObjectSpecularPower ( i, 255 );
// turn off ambient lighting for this object
dbSetObjectAmbient ( i, 0 );
}
// move our camera back so we can view the objects
dbPositionCamera ( 10, 10, -20 );
//variables
float c=0;
dbMakeVector3(2); //initial mouse position
dbMakeVector3(3); //end mouse position
// now we come to our main loop, we call LoopGDK so some internal
// work can be carried out by the GDK
while ( LoopGDK ( ) )
{
// display some text on screen
dbText ( 0, 5, "QuaNano ChemXplore" );
// move the camera forwards
if ( dbUpKey ( ) )
dbMoveCamera ( 1 );
// move the camera backwards
if ( dbDownKey ( ) )
dbMoveCamera ( -1 );
user_Input();
float currx = ( float(dbMouseX()) / ( float(dbScreenWidth()) / 2) ) - 1;
dbText ( 10, 25, dbStr(currx) );
float curry = 1 - ( ( 2 * float(dbMouseY()) ) / float(dbScreenHeight()) );
dbText ( 10, 50, dbStr(curry) );
dbText ( 10, 75, dbStr(initial_position) );
dbText ( 10, 100, dbStr(dbScreenHeight()) );
// here we make a call to update the contents of the screen
dbSync ( );
}
// before quitting delete our objects
for ( int i = 1; i < 50; i++ )
dbDeleteObject ( i );
// and now everything is ready to return back to Windows
return;
}
void user_Input(void)
{
if ( initial_position == 1) {
set_MouseVec(3);//End Mouse Position Vector 3
dbMakeVector3(4);
dbCrossProductVector3(4, 2, 3);//Axis Vector 4
float theta = dbACOS(dbDotProductVector3(2, 3));
float sin_angle_2 = dbSIN( .5 * theta );
float c = dbCOS( .5 * theta );
float q_x = 0.0f;
float q_y = 0.0f;
float q_z = 0.0f;
float current_x = dbXVector3(4);
float current_y = dbYVector3(4);
float current_z = dbZVector3(4);
if (theta != 0){
q_x = current_x * sin_angle_2;
q_y = current_y * sin_angle_2;
q_z = current_z * sin_angle_2;
}
//Build Rotation Quaternion from Axis and Angle
dbMakeVector4(8);
dbSetVector4(8, q_x, q_y, q_z, c );
//Build Conjugate Rotation Quaternion from Axis and Angle
dbMakeVector4(9);
dbSetVector4(9, -(q_x), -(q_y), -(q_z), c );
//Build current Camera Quaternion
dbMakeVector4(6);
set_CameraQuaternion( 1, 6 );
//Calculate Rotation Quaternion (R) * Camera Quaternion (Cp)
dbMakeVector4(7);
multiply_Quaternions( 8, 6, 7 );
//Calculate R * Cp * R-1
dbMakeVector4(10);
multiply_Quaternions( 7, 9, 10 );
//Delete unnecessary vectors
dbDeleteVector4(6);
dbDeleteVector4(7);
dbDeleteVector4(8);
dbDeleteVector4(9);
dbPositionCamera( dbXVector4(10), dbYVector4(10), dbZVector4(10) );
//dbPointCamera( 0.0f, 0.0f, 0.0f );
initial_position = 0;
}
if ( dbMouseClick() == 1) {
set_MouseVec(2); //Initial Mouse Position Vector 2
initial_position = 1;
}
}
void set_MouseVec(int vector_id) {
float currentx;
float currenty;
float currentz;
currentx = ( ( 2 * float(dbMouseX()) ) / float(dbScreenWidth()) ) - 1;
currenty = 1 - ( ( 2 * float(dbMouseY()) ) / float(dbScreenHeight()) );
float currentzsq = 1 - ( currentx * currentx ) + ( currenty * currenty );
if (currentzsq > 0) {
currentz = dbSQRT( currentzsq );
} else {
currentz = 0;
}
dbMakeVector3(1);
dbSetVector3(1, currentx, currenty, currentz);
dbNormalizeVector3(vector_id, 1);
dbDeleteVector3(1);
}
void multiply_Quaternions(int vector_a, int vector_b, int vector_result){
float w1 = dbWVector4(vector_a);
float x1 = dbXVector4(vector_a);
float y1 = dbYVector4(vector_a);
float z1 = dbZVector4(vector_a);
float w2 = dbWVector4(vector_b);
float x2 = dbXVector4(vector_b);
float y2 = dbYVector4(vector_b);
float z2 = dbZVector4(vector_b);
float w = (w1 * w2) - (x1 * x2) - (y1 * y2) - (z1 * z2);
float x = (w1 * x2) + (x1 * w2) + (y1 * z2) - (z1 * y2);
float y = (w1 * y2) + (y1 * w2) + (z1 * x2) - (x1 * z2);
float z = (w1 * z2) + (z1 * w2) + (x1 * y2) - (y1 * x2);
dbSetVector4(vector_result, x, y, z, w);
}
void set_CameraQuaternion(int camera_id, int vector_result){
dbMakeVector3(5);
dbSetVector3ToCameraPosition ( 5, camera_id );
dbSetVector4(vector_result, dbXVector3(5), dbYVector3(5), dbZVector3(5), 0.0f );
dbDeleteVector3(5);
}
Adam Sykes