quaternion_t quaternion_t::operator* ( const quaternion_t& quat) const { return quaternion_t( q[3]*quat.q[0] + q[0]*quat.q[3] + q[1]*quat.q[2] - q[2]*quat.q[1], q[3]*quat.q[1] + q[1]*quat.q[3] + q[2]*quat.q[0] - q[0]*quat.q[2], q[3]*quat.q[2] + q[2]*quat.q[3] + q[0]*quat.q[1] - q[1]*quat.q[0], q[3]*quat.q[3] - q[0]*quat.q[0] - q[1]*quat.q[1] - q[2]*quat.q[2] ); }
// gets called every frame to draw the scene void CRenderer::Update(const float dt, const uint32_t ticks) { CObj* obj, *localctrl; int localctrlid; OBJITER iter; matrix_t m; vec3_t dir, up, side; CFrustum frustum; CWorld* world; localctrl = m_world->GetLocalController(); localctrlid = m_world->GetLocalObj()->GetID(); world = m_world->GetInterpWorld(); const vec3_t campos = localctrl->GetOrigin(); const quaternion_t camrot = localctrl->GetRot(); m.SetCamTransform(campos, camrot); m.GetVec3Cam(&dir, &up, &side); dir = -dir; frustum.Setup(campos, dir, up, side, RENDERER_FOV, (float)m_width/(float)m_height, PLANE_NEAR, PLANE_FAR); // light floating above the players head const vec3_t lightpos0(campos + vec3_t(0,25.0f,0)); const quaternion_t lightrot0(quaternion_t(vec3_t::xAxis, -90.0f*lynxmath::DEGTORAD)); const float lightpos0_4f[4] = {lightpos0.x, lightpos0.y, lightpos0.z, 1}; glLightfv(GL_LIGHT0, GL_POSITION, lightpos0_4f); if(m_shaderactive) { if(m_useShadows) { glUseProgram(0); // draw shadowmap with fixed function pipeline PrepareShadowMap(lightpos0, lightrot0, world, localctrlid); // the player is the light } glUseProgram(m_program); // activate shader } glMatrixMode(GL_MODELVIEW); glLoadMatrixf(m.pm); glClear(GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT); glActiveTexture(GL_TEXTURE0); // normal texture channel if(m_shaderactive) { glUniform1i(m_tex, 0); // good old textures: GL_TEXTURE0 glUniform1i(m_normalMap, 1); // normal maps are GL_TEXTURE1 glUniform1i(m_lightmap, 2); // lightmap if(m_useShadows) { glUniform1i(m_shadowMapUniform, 7); glActiveTexture(GL_TEXTURE7); // shadow mapping texture GL_TEXTURE7 glBindTexture(GL_TEXTURE_2D, m_depthTextureId); glActiveTexture(GL_TEXTURE0); } #ifdef DRAW_NORMALS glUseProgram(0); // use fixed pipeline for this debug mode #endif } // Main drawing DrawScene(frustum, world, localctrlid, false); if(m_shaderactive) glUseProgram(0); // don't use shader for particles // Particle Draw glDisable(GL_LIGHTING); glDepthMask(false); for(iter=world->ObjBegin();iter!=world->ObjEnd();++iter) { obj = (*iter).second; if(obj->GetMesh()) { // Animate mesh is done in the particle loop // and not in DrawScene, because DrawScene // can be called multiple times per frame obj->GetMesh()->Animate(obj->GetMeshState(), dt); } if(obj->GetID() == localctrlid || !obj->GetParticleSystem()) continue; // Update/animate the particles, depending on dt and the current position. obj->GetParticleSystem()->Update(dt, ticks, obj->GetOrigin()); // Draw the particles. FIXME: this should use a frustum test obj->GetParticleSystem()->Render(side, up, dir); } glDepthMask(true); glColor4f(1,1,1,1); glEnable(GL_LIGHTING); #ifdef DRAW_NORMALS // Draw vertex normals of level geometry (not face normals) if(world && world->GetBSP()) { glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); world->GetBSP()->RenderNormals(); glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); } #endif // Draw weapon if(m_shaderactive) // use shader for weapon glUseProgram(m_program); CModelMD5* viewmodel; md5_state_t* viewmodelstate; m_world->m_hud.GetModel(&viewmodel, &viewmodelstate); glDisable(GL_LIGHTING); if(viewmodel) { glClear(GL_DEPTH_BUFFER_BIT); glPushMatrix(); glLoadIdentity(); viewmodel->Render(viewmodelstate); viewmodel->Animate(viewmodelstate, dt); glPopMatrix(); } glEnable(GL_LIGHTING); // Draw HUD if(m_shaderactive) glUseProgram(0); // no shader for HUD glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, m_width, m_height, 0, 0, 1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glColor4f(1,1,1,1); glBindTexture(GL_TEXTURE_2D, m_crosshair); // Draw center crosshair glBegin(GL_QUADS); glTexCoord2d(0,1); glVertex3f((m_width-m_crosshair_width)*0.5f, (m_height-m_crosshair_height)*0.5f,0.0f); glTexCoord2d(0,0); glVertex3f((m_width-m_crosshair_width)*0.5f, (m_height+m_crosshair_height)*0.5f,0.0f); glTexCoord2d(1,0); glVertex3f((m_width+m_crosshair_width)*0.5f, (m_height+m_crosshair_height)*0.5f,0.0f); glTexCoord2d(1,1); glVertex3f((m_width+m_crosshair_width)*0.5f, (m_height-m_crosshair_height)*0.5f,0.0f); glEnd(); // draw HUD text: score, health... char hudtextbuf[64]; sprintf(hudtextbuf, "Frags: %i", m_world->m_hud.score); m_font.DrawGL(10.0f, m_height - 30.0f, 0.0f, hudtextbuf); sprintf(hudtextbuf, "%i", m_world->m_hud.health); m_font.DrawGL(10.0f, m_height - 35.0f - (float)m_font.GetHeight(), 0.0f, hudtextbuf); #ifdef DRAW_SHADOWMAP // draw a small window with the scene from the light POV if(m_shaderactive) { //glBindTexture(GL_TEXTURE_2D, m_depthTextureId); glBindTexture(GL_TEXTURE_2D, g_fboShadowCamColor); const float shadowmap_debug_width = 200.0f; const float shadowmap_debug_height = shadowmap_debug_width*(float)m_height/(float)m_width; glBegin(GL_QUADS); glTexCoord2d(0,1); // upper left glVertex3f(0.0f, 0.0f, 0.0f); glTexCoord2d(0,0); //lower left glVertex3f(0.0f, shadowmap_debug_height, 0.0f); glTexCoord2d(1,0); //lower right glVertex3f(shadowmap_debug_width, shadowmap_debug_height, 0.0f); glTexCoord2d(1,1); // upper right glVertex3f(shadowmap_debug_width, 0.0f, 0.0f); glEnd(); } #endif glBindTexture(GL_TEXTURE_2D, 0); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); }
quaternion_t quaternion_t::operator/ ( double val) const { val = 1.0/val; return quaternion_t( q[0]*val, q[1]*val, q[2]*val, q[3]*val); }
quaternion_t quaternion_t::conj() const { return quaternion_t(-q[0], -q[1], -q[2], q[3]); }
quaternion_t quaternion_t::operator/ ( const quaternion_t& quat) const { return quaternion_t((*this)*(quat.conj())); }
quaternion_t quaternion_t::operator * ( double val) const { return quaternion_t( q[0]*val, q[1]*val, q[2]*val, q[3]*val); }
quaternion_t quaternion_t::operator-() //Negation { return quaternion_t(-q[0], -q[1], -q[2], -q[3]); }
quaternion_t quaternion_t::operator- ( const quaternion_t& quat) const { return quaternion_t( q[0]-quat.q[0], q[1]-quat.q[1], q[2]-quat.q[2], q[3]-quat.q[3]); }
quaternion_t quaternion_t::operator+ ( const quaternion_t& quat) const { return quaternion_t( q[0]+quat.q[0], q[1]+quat.q[1], q[2]+quat.q[2], q[3]+quat.q[3]); }