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; }
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]); }
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(); }
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); }
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); }
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); }
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; }
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; }
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; }
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; }
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); } }
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; } }
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); } }