Esempio n. 1
0
void nebu_Camera_GetRotationMatrix(nebu_Matrix4D *matrix,
                                   const nebu_Camera *pCamera) {
    vec3 x, y, z;

    vec3_Sub(&z, &pCamera->vEye, &pCamera->vLookAt);
    vec3_Normalize(&z, &z);
    vec3_Cross(&x, &pCamera->vUp, &z);
    vec3_Normalize(&x, &x);
    vec3_Cross(&y, &z, &x);
    vec3_Normalize(&y, &y);

#define M(row,col)  matrix->m[col*4+row]
    M(0,0) = x.v[0];
    M(0,1) = x.v[1];
    M(0,2) = x.v[2];
    M(0,3) = 0.0;
    M(1,0) = y.v[0];
    M(1,1) = y.v[1];
    M(1,2) = y.v[2];
    M(1,3) = 0.0;
    M(2,0) = z.v[0];
    M(2,1) = z.v[1];
    M(2,2) = z.v[2];
    M(2,3) = 0.0;
    M(3,0) = 0.0;
    M(3,1) = 0.0;
    M(3,2) = 0.0;
    M(3,3) = 1.0;
#undef M
    return;
}
Esempio n. 2
0
static void doLookAt(const float *cam, const float *target, const float *up) {
    matrix m;
    vec3 x, y, z;

    vec3_Sub(&z, (vec3*) cam, (vec3*) target);
    vec3_Normalize(&z, &z);
    vec3_Cross(&x, (vec3*) up, &z);
    vec3_Normalize(&x, &x);
    vec3_Cross(&y, &z, &x);
    vec3_Normalize(&y, &y);

#define M(row,col)  m.m[col*4+row]
    M(0,0) = x.v[0];
    M(0,1) = x.v[1];
    M(0,2) = x.v[2];
    M(0,3) = 0.0;
    M(1,0) = y.v[0];
    M(1,1) = y.v[1];
    M(1,2) = y.v[2];
    M(1,3) = 0.0;
    M(2,0) = z.v[0];
    M(2,1) = z.v[1];
    M(2,2) = z.v[2];
    M(2,3) = 0.0;
    M(3,0) = 0.0;
    M(3,1) = 0.0;
    M(3,2) = 0.0;
    M(3,3) = 1.0;
#undef M
    glMultMatrixf( m.m );

    /* Translate Eye to Origin */
    glTranslatef( -cam[0], -cam[1], -cam[2]);
}
Esempio n. 3
0
static void drawSpires(float radius) {
  int i;
  vec3 right, left;
  vec3 zUnit = { { 0, 0, 1} };
  
  vec3 vectors[NUM_SPIRES] = {
    { {  1.00f,  0.20f,  0.00f  } },
    { {  0.80f,  0.25f,  0.00f  } },
    { {  0.90f,  0.50f,  0.00f  } },
    { {  0.70f,  0.50f,  0.00f  } },
    { {  0.52f,  0.45f,  0.00f  } },
    { {  0.65f,  0.75f,  0.00f  } },
    { {  0.42f,  0.68f,  0.00f  } },
    { {  0.40f,  1.02f,  0.00f  } },
    { {  0.20f,  0.90f,  0.00f  } },
    { {  0.08f,  0.65f,  0.00f  } },
    { {  0.00f,  1.00f,  0.00f  } }, /* vertical spire */
    { { -0.08f,  0.65f,  0.00f  } },
    { { -0.20f,  0.90f,  0.00f  } },
    { { -0.40f,  1.02f,  0.00f  } },
    { { -0.42f,  0.68f,  0.00f  } },
    { { -0.65f,  0.75f,  0.00f  } },
    { { -0.52f,  0.45f,  0.00f  } },
    { { -0.70f,  0.50f,  0.00f  } },
    { { -0.90f,  0.50f,  0.00f  } },
    { { -0.80f,  0.30f,  0.00f  } },
    { { -1.00f,  0.20f,  0.00f  } }
  };

  glColor3f(1, 1, 1);
  glVertex3f(0, 0, 0);
 
  glBlendFunc(GL_ONE, GL_ONE);

  glBegin(GL_TRIANGLES);
  
  for (i=0; i < NUM_SPIRES; i++) {
		vec3_Cross(&right, vectors + i, &zUnit);
		vec3_Normalize(&right, &right);
		vec3_Scale(&right, &right, SPIRE_WIDTH);

		vec3_Cross(&left, &zUnit, vectors + i);
		vec3_Normalize(&left, &left);
		vec3_Scale(&left, &left, SPIRE_WIDTH);

    glColor4f(1,1,1,0.0);
    glVertex3fv(right.v);
    glVertex3f(radius * vectors[i].v[0], radius * vectors[i].v[1], 0.0);
    glVertex3fv(left.v);
  } 
  
  glEnd();
}
Esempio n. 4
0
void nebu_Camera_Zoom(nebu_Camera *pCamera, float d) {
    vec3 v;
    vec3_Sub(&v, &pCamera->vLookAt, &pCamera->vEye);
    vec3_Normalize(&v, &v);
    vec3_Scale(&v, &v, d);
    vec3_Add(&pCamera->vEye, &pCamera->vEye, &v);
}
Esempio n. 5
0
void nebu_Camera_Roll(nebu_Camera *pCamera, float d) {
    vec3 v;
    matrix m;
    vec3_Sub(&v, &pCamera->vLookAt, &pCamera->vEye);
    vec3_Normalize(&v, &v);
    matrixRotationAxis(&m, d * 2 * (float)M_PI / 360.0f, &v);
    vec3_Transform(&pCamera->vUp, &pCamera->vUp, &m);
}
Esempio n. 6
0
void nebu_Camera_Slide(nebu_Camera *pCamera, float dx, float dy, float dz)
{
    vec3 vLook, vUp, vRight, vMovement;
    vec3_Sub(&vLook, &pCamera->vLookAt, &pCamera->vEye);
    vec3_Cross(&vRight, &vLook, &pCamera->vUp);
    vec3_Cross(&vUp, &vRight, &vLook);

    vec3_Normalize(&vUp, &vUp);
    vec3_Normalize(&vRight, &vRight);
    vec3_Normalize(&vLook, &vLook);
    vec3_Scale(&vUp, &vUp, dy);
    vec3_Scale(&vRight, &vRight, dx);
    vec3_Scale(&vLook, &vLook, dz);
    vec3_Add(&vMovement, &vUp, &vRight);
    vec3_Add(&vMovement, &vMovement, &vLook);
    vec3_Add(&pCamera->vEye, &pCamera->vEye, &vMovement);
    vec3_Add(&pCamera->vLookAt, &pCamera->vLookAt, &vMovement);
}
Esempio n. 7
0
int playerVisible(int eyePlayer, int targetPlayer) {
	vec3 v1, v2, tmp;
		
	float s;
	float d;
	int i;
	int lod_level;
	float x, y;

	vec3_Sub(&v1, (vec3*) gPlayerVisuals[eyePlayer].camera.target, (vec3*) gPlayerVisuals[eyePlayer].camera.cam);
	vec3_Normalize(&v1, &v1);
	
	getPositionFromData(&x, &y, game->player[targetPlayer].data);
	tmp.v[0] = x;
	tmp.v[1] = y;
	tmp.v[2] = 0;
		
	lod_level = (gSettingsCache.lod > MAX_LOD_LEVEL) ? 
		MAX_LOD_LEVEL : gSettingsCache.lod;

	/* calculate lod */
	vec3_Sub(&v2, (vec3*) &gPlayerVisuals[eyePlayer].camera.cam, &tmp);
	d = vec3_Length(&v2);
	for(i = 0; i < LC_LOD && d >= lod_dist[lod_level][i]; i++);
	if(i >= LC_LOD)
		return -1;

	vec3_Sub(&v2, &tmp, (vec3*) gPlayerVisuals[eyePlayer].camera.cam);
	vec3_Normalize(&v2, &v2);
	s = vec3_Dot(&v1, &v2);
	/* maybe that's not exactly correct, but I didn't notice anything */
	d = cosf((gSettingsCache.fov / 2) * 2 * PI / 360.0);
	/*
		printf("v1: %.2f %.2f %.2f\nv2: %.2f %.2f %.2f\ns: %.2f d: %.2f\n\n",
		v1[0], v1[1], v1[2], v2[0], v2[1], v2[2],
		s, d);
	*/
	if(s < d-(((gltron_Mesh*)resource_Get(gpTokenLightcycles[i], eRT_GLtronTriMesh))->BBox.fRadius*2))
		return -1;
	else
		return i;
}
Esempio n. 8
0
int playerVisible(Player *eye, Player *target) {
  vec3 v1, v2, tmp;
	
  float s;
  float d;
  int i;
  int lod_level;
	float x, y;

  vec3_Sub(&v1, (vec3*) eye->camera->target, (vec3*) eye->camera->cam);
	vec3_Normalize(&v1, &v1);
	
	getPositionFromData(&x, &y, target->data);
	tmp.v[0] = x;
  tmp.v[1] = y;
  tmp.v[2] = 0;
	
  lod_level = (gSettingsCache.lod > MAX_LOD_LEVEL) ? 
    MAX_LOD_LEVEL : gSettingsCache.lod;

  /* calculate lod */
  vec3_Sub(&v2, (vec3*) eye->camera->cam, &tmp);
  d = vec3_Length(&v2);
  for(i = 0; i < LC_LOD && d >= lod_dist[lod_level][i]; i++);
  if(i >= LC_LOD)
    return -1;

  vec3_Sub(&v2, &tmp, (vec3*) eye->camera->cam);
  vec3_Normalize(&v2, &v2);
  s = vec3_Dot(&v1, &v2);
  /* maybe that's not exactly correct, but I didn't notice anything */
  d = cosf((gSettingsCache.fov / 2) * 2 * PI / 360.0);
  /*
    printf("v1: %.2f %.2f %.2f\nv2: %.2f %.2f %.2f\ns: %.2f d: %.2f\n\n",
    v1[0], v1[1], v1[2], v2[0], v2[1], v2[2],
    s, d);
  */
  if(s < d-(lightcycle[i]->BBox.fRadius*2))
    return -1;
  else
    return i;
}
Esempio n. 9
0
Matrix4* mat4_LookAtView( const Vector3* eyePos, const Vector3* lookPos, const Vector3* up, Matrix4* out )
{
	assert( out != NULL );

	Vector3 u, f, s;

	memcpy( out, &IDENTITY_MATRIX, sizeof( Matrix4 ) );

	vec3_Subtract( lookPos, eyePos, &f );
	vec3_Normalize( &f );

	memcpy( &u, up, sizeof( Vector3 ) );
	vec3_Normalize( &u );

	vec3_CrossProd( &f, &u, &s );
	vec3_Normalize( &s );

	vec3_CrossProd( &s, &f, &u );

	out->m[0] = s.v[0];
	out->m[4] = s.v[1];
	out->m[8] = s.v[2];

	out->m[1] = u.v[0];
	out->m[5] = u.v[1];
	out->m[9] = u.v[2];

	out->m[2] = -f.v[0];
	out->m[6] = -f.v[1];
	out->m[10] = -f.v[2];

	out->m[12] = -vec3_DotProd( &s, eyePos );
	out->m[13] = -vec3_DotProd( &u, eyePos );
	out->m[14] = vec3_DotProd( &f, eyePos );

	return out;
}
Esempio n. 10
0
vec3* nebu_Mesh_ComputeFaceNormals(const nebu_Mesh_VB *pVB, const nebu_Mesh_IB *pIB)
{
	int i;

	vec3 *pNormals = (vec3*) malloc( pIB->nPrimitives * sizeof(vec3) );

	for(i = 0; i < pIB->nPrimitives; i++)
	{
		vec3_TriNormalDirection(pNormals + i,
			(vec3*) (pVB->pVertices + 3 * pIB->pIndices[ 3 * i + 0 ]),
			(vec3*) (pVB->pVertices + 3 * pIB->pIndices[ 3 * i + 1 ]),
			(vec3*) (pVB->pVertices + 3 * pIB->pIndices[ 3 * i + 2 ]) );
		vec3_Normalize(pNormals + i, pNormals + i);
	}
	return pNormals;
}
Esempio n. 11
0
void nebu_Camera_Rotate(nebu_Camera *pCamera, int flags,
                        float dx, float dy)
{
    // adjust up vector, so that it is orthogonal to
    // view direction
    vec3 vDiff, vView, vRight, vUp;
    vec3 vdx, vdy;
    vec3 *pvCenter, *pvMoving;

    switch(flags & NEBU_CAMERA_ROTATE_MASK)
    {
    case NEBU_CAMERA_ROTATE_AROUND_EYE:
        pvCenter = &pCamera->vEye;
        pvMoving = &pCamera->vLookAt;
        break;
    case NEBU_CAMERA_ROTATE_AROUND_LOOKAT:
        pvCenter = &pCamera->vLookAt;
        pvMoving = &pCamera->vEye;
        break;
    default:
        assert(0);
        return;
    }

    vec3_Sub(&vDiff, pvCenter, pvMoving);
    vec3_Normalize(&vView, &vDiff);
    vec3_Cross(&vRight, &pCamera->vUp, &vView);
    vec3_Normalize(&vRight, &vRight);
    vec3_Cross(&vUp, &vView, &vRight);
    vec3_Normalize(&vUp, &vUp);

    // horizontal movement (dx):
    if(dx == 0) {
        vec3_Zero(&vdx);
    } else {
        // rotate moving around up vector through center point
        vec3 v = vDiff;
        float fAngle = dx * 2 * (float)M_PI / 360.0f;
        matrix matRotation;
        matrixRotationAxis(&matRotation, fAngle, &vUp);
        vec3_Transform(&v, &vDiff, &matRotation);
        vec3_Sub(&vdx, &v, &vDiff);
    }

    // vertical movement (dy):
    if(dy == 0) {
        vec3_Zero(&vdy);
    } else {
        // rotate eye point around up vector through lookAt point
        vec3 v = vDiff;
        float fAngle = dy * 2 * (float)M_PI / 360.0f;
        matrix matRotation;
        matrixRotationAxis(&matRotation, fAngle, &vRight);
        vec3_Transform(&v, &vDiff, &matRotation);
        vec3_Sub(&vdy, &v, &vDiff);

        matrixTranspose(&matRotation, &matRotation);
        if(!(flags & NEBU_CAMERA_FIXED_UP))
            vec3_Transform(&pCamera->vUp, &pCamera->vUp, &matRotation);
    }

    {
        vec3 v;
        vec3_Add(&v, &vdx, &vdy);
        vec3_Add(&v, &v, pvMoving);
        vec3_Sub(&v, &v, pvCenter);
        vec3_Normalize(&v, &v);
        // printf("up dot view: %.4f\n", - vec3_Dot(&v, &pCamera->vUp));
        vec3_Scale(&v, &v, vec3_Length(&vDiff));
        vec3_Add(pvMoving, &v, pvCenter);

    }
}
Esempio n. 12
0
void drawCam(int player) {
	int i;
	float up[3] = { 0, 0, 1 };
	Visual *d = & gPlayerVisuals[player].display;
	
	float reflectivity = getReflectivity();
	// compute shadow color based on glocal constant & reflectivity
	for(i = 0; i < 4; i++) 
		gCurrentShadowColor[i] = gShadowColor[i] * (1 - reflectivity);

	glColor3f(0.0, 1.0, 0.0);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	doPerspective(gSettingsCache.fov, (float) d->vp_w / (float) d->vp_h,
		gSettingsCache.znear, box2_Diameter(& game2->level->boundingBox) * 6.5f);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	{
		vec3 vLookAt;
		vec3 vTarget;
		matrix matRotate;

		vec3_Sub(&vLookAt, (vec3*)gPlayerVisuals[player].camera.target, (vec3*)gPlayerVisuals[player].camera.cam);
		vec3_Normalize(&vLookAt, &vLookAt);
		matrixRotationAxis(&matRotate, 90.0f * (float) gPlayerVisuals[player].camera.bIsGlancing, (vec3*)up);
		vec3_Transform(&vLookAt, &vLookAt, &matRotate);
		vec3_Add(&vTarget, (vec3*)gPlayerVisuals[player].camera.cam, &vLookAt);
		doLookAt(gPlayerVisuals[player].camera.cam, (float*)&vTarget, up);
	}

	glDisable(GL_LIGHTING); // initial config at frame start
	glDisable(GL_BLEND); // initial config at frame start

	// disable writes to alpha
	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);

	/* skybox */
	glDepthMask(GL_FALSE);
	glDisable(GL_DEPTH_TEST);

	drawSkybox( box2_Diameter( & game2->level->boundingBox ) * 2.5f );

	glDepthMask(GL_TRUE);
	glEnable(GL_DEPTH_TEST);
	/* skybox done */

	/* floor */ 
	if(reflectivity == 0) {
		// draw floor to fb and stencil (set to 1),
		// using alpha-blending
		// TODO: draw floor alpha to fb
		video_Shader_Setup(& gWorld->floor_shader);
		glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
		glStencilFunc(GL_ALWAYS, 1, 255);
		glEnable(GL_STENCIL_TEST);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		nebu_Mesh_DrawGeometry( gWorld->floor );
		glDisable(GL_BLEND);
		glDisable(GL_STENCIL_TEST);
		video_Shader_Cleanup(& gWorld->floor_shader);
	} else {
		/* reflections */
		/* first draw reflector to stencil */
		/* and reflector alpha to fb */

		video_Shader_Setup(& gWorld->floor_shader);

		// store only reflector alpha in framebuffer
		glDepthMask(GL_FALSE);
		glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
		glStencilFunc(GL_ALWAYS, 1, 255);
		glEnable(GL_STENCIL_TEST);
		glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
		// glEnable(GL_ALPHA_TEST);
		// glAlphaFunc(GL_GREATER, 0.1f);

		nebu_Mesh_DrawGeometry( gWorld->floor );
		
		// glDisable(GL_ALPHA_TEST);
		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
		glDepthMask(GL_TRUE);
		glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
		glStencilFunc(GL_EQUAL, 1, 255);

		video_Shader_Cleanup(& gWorld->floor_shader);
		
		/* then draw world & skybox reflected, where stencil is set */
		/* protect the alpha buffer */
		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);

		isRenderingReflection = 1; // hack: reverse lighting
		glPushMatrix();
		glScalef(1,1,-1);
		glCullFace(GL_FRONT); // reverse culling
		// clip skybox & world to floor plane
		glEnable(GL_CLIP_PLANE0);
		{
			double plane[] = { 0, 0, 1, 0 };
			glClipPlane(GL_CLIP_PLANE0, plane);
		}

		drawSkybox( box2_Diameter( & game2->level->boundingBox ) * 2.5f );
		drawWorld(player);

		glDisable(GL_CLIP_PLANE0);
		glCullFace(GL_BACK);
		glPopMatrix();
		isRenderingReflection = 0; // hack: normal lighting

		/* then blend the skybox into the scene, where stencil is set */
		/* modulate with the destination alpha */
		glDisable(GL_DEPTH_TEST);
		glEnable(GL_BLEND);
		glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);
		drawSkybox( box2_Diameter( & game2->level->boundingBox ) * 2.5f );
		glDisable(GL_BLEND);
		glEnable(GL_DEPTH_TEST);
		
		/* then blend reflector into the scene */
		glDisable(GL_DEPTH_TEST);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		glColor4f(1, 1, 1, 1 - reflectivity);

		glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
		glStencilFunc(GL_ALWAYS, 1, 255);

		video_Shader_Setup(& gWorld->floor_shader);
		nebu_Mesh_DrawGeometry( gWorld->floor );
		video_Shader_Cleanup(& gWorld->floor_shader);

		glDisable(GL_STENCIL_TEST);
		glDisable(GL_BLEND);
		glEnable(GL_DEPTH_TEST);
	}
	/* floor done */

	/* planar shadows */
	glDepthMask(GL_FALSE);
	glDisable(GL_DEPTH_TEST);

	if(reflectivity != 1) // there are no shadows on perfect mirrors
		drawPlanarShadows(player);

	glDepthMask(GL_TRUE);
	glEnable(GL_DEPTH_TEST);
	/* planar shadows done */

	drawWorld(player);

	/* transparent stuff */
	/* draw the glow around the other players: */
	if (gSettingsCache.show_glow == 1) {
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		for (i = 0; i < game->players; i++)
		{
			if (i != player && PLAYER_IS_ACTIVE(game->player + i))
			{
				drawGlow(&gPlayerVisuals[player].camera, game->player + i, gPlayerVisuals + i,
					d, TRAIL_HEIGHT * 4);
			}
		}
		glDisable(GL_BLEND);
	}
}
void ai_getConfig(int player, int target,
										AI_Configuration *config) {

	Data *data;
	
	getPositionFromIndex(config->player.vStart.v + 0,
											 config->player.vStart.v + 1,
											 player);
	getPositionFromIndex(config->opponent.vStart.v + 0,
											 config->opponent.vStart.v + 1,
											 target);
	
	data = game->player[player].data;
	config->player.vDirection.v[0] = dirsX[ data->dir ] * data->speed;
	config->player.vDirection.v[1] = dirsY[ data->dir ] * data->speed;

	data = game->player[target].data;
	config->opponent.vDirection.v[0] = dirsX[ data->dir ] * data->speed;
	config->opponent.vDirection.v[1] = dirsY[ data->dir ] * data->speed;
	
	// compute sector
	{
		vec2 diff;
		vec3 v1, v2, v3;
		vec3 up = { { 0, 0, 1 } };
		float cosphi;
		float phi;
		int i;

		vec2_Sub(&diff, &config->player.vStart, &config->opponent.vStart);
		v1.v[0] = diff.v[0];
		v1.v[1] = diff.v[1];
		v1.v[2] = 0;

		v2.v[0] = config->opponent.vDirection.v[0];
		v2.v[1] = config->opponent.vDirection.v[1];
		v2.v[2] = 0;

		vec3_Normalize(&v1, &v1);
		vec3_Normalize(&v2, &v2);

		vec3_Cross(&v3, &v1, &v2);
		vec3_Normalize(&v3, &v3);
	
		cosphi = vec3_Dot(&v1, &v2);
		nebu_Clamp(&cosphi, -1, 1);
		phi = (float) acos(cosphi);
		if(vec3_Dot(&v3, &up) > 0)
			phi = 2 * (float) M_PI - phi;
	
		for(i = 0; i < 8; i++) {
			phi -= (float) M_PI / 4;
			if(phi < 0) {
				config->location = i;
				break;
			}
		}
	}
	// compute intersection
	{
		segment2 seg1;
		segment2 seg2;
		seg1.vStart = config->opponent.vStart;
		seg1.vDirection = config->opponent.vDirection;
		seg2.vStart = config->player.vStart;
		vec2_Orthogonal( &seg2.vDirection, &config->opponent.vDirection );
		vec2_Normalize( &seg2.vDirection, &seg2.vDirection );
		vec2_Scale( &seg2.vDirection, 
							 &seg2.vDirection,
							 vec2_Length( &config->player.vDirection )
							 );
							 
		segment2_Intersect( &config->intersection, 
												&config->t_opponent, &config->t_player,
												&seg1, &seg2 );
		if(config->t_player < 0)
			config->t_player *= -1;
	}
	
}
Esempio n. 14
0
void nebu_Camera_RotateAroundTarget(nebu_Camera *pCamera,
																		float dx, float dy) {
	// adjust up vector, so that it is orthogonal to
	// view direction
	vec3 vDiff, vView, vRight, vUp;
	vec3 vdx, vdy;
	
	vec3_Sub(&vDiff, &pCamera->vLookAt, &pCamera->vEye);
	vec3_Normalize(&vView, &vDiff);
	vec3_Cross(&vRight, &pCamera->vUp, &vView);
	vec3_Normalize(&vRight, &vRight);
	vec3_Cross(&vUp, &vView, &vRight);
	vec3_Normalize(&vUp, &vUp);
	
	// horizontal movement (dx):
	if(dx == 0) {
		vec3_Zero(&vdx);
	} else {
		// rotate eye point around up vector through lookAt point
		vec3 v = vDiff;
		float fAngle = dx * 2 * M_PI / 360.0;
		matrix matRotation;
		matrixRotationAxis(&matRotation, fAngle, &vUp);
		vec3_Transform(&v, &vDiff, &matRotation);
		vec3_Sub(&vdx, &v, &vDiff);
	}

	// vertical movement (dy):
	if(dy == 0) {
		vec3_Zero(&vdy);
	} else {
		// rotate eye point around up vector through lookAt point
		vec3 v = vDiff;
		float fAngle = dy * 2 * M_PI / 360.0;
		matrix matRotation;
		matrixRotationAxis(&matRotation, fAngle, &vRight);
		vec3_Transform(&v, &vDiff, &matRotation);
		vec3_Sub(&vdy, &v, &vDiff);

		matrixTranspose(&matRotation, &matRotation);
		vec3_Transform(&pCamera->vUp, &pCamera->vUp, &matRotation);
	}

	// add relative movements to camera position
	
	/*
	vec3_Add(&pCamera->vEye, &pCamera->vEye, &vdx);
	vec3_Add(&pCamera->vEye, &pCamera->vEye, &vdy);
	*/
	{
		vec3 v;
		vec3_Add(&v, &vdx, &vdy);
		vec3_Add(&v, &v, &pCamera->vEye);
		vec3_Sub(&v, &v, &pCamera->vLookAt);
		vec3_Normalize(&v, &v);
		// printf("up dot view: %.4f\n", - vec3_Dot(&v, &pCamera->vUp));
		vec3_Scale(&v, &v, vec3_Length(&vDiff));
		vec3_Add(&pCamera->vEye, &v, &pCamera->vLookAt);

	}
}