void GeomTree::RayTriIntersect(int numRays, const vector3f &origin, const vector3f *dirs, int triIdx, isect_t *isects) const { const vector3f a(m_vertices[m_indices[triIdx+0]]); const vector3f b(m_vertices[m_indices[triIdx+1]]); const vector3f c(m_vertices[m_indices[triIdx+2]]); vector3f v0_cross, v1_cross, v2_cross; const vector3f n = (c-a).Cross(b-a); const float nominator = n.Dot(a-origin); v0_cross = (c-origin).Cross(b-origin); v1_cross = (b-origin).Cross(a-origin); v2_cross = (a-origin).Cross(c-origin); for (int i=0; i<numRays; i++) { const float v0d = v0_cross.Dot(dirs[i]); const float v1d = v1_cross.Dot(dirs[i]); const float v2d = v2_cross.Dot(dirs[i]); if (((v0d > 0) && (v1d > 0) && (v2d > 0)) || ((v0d < 0) && (v1d < 0) && (v2d < 0))) { const float dist = nominator / dirs[i].Dot(n); if ((dist > 0) && (dist < isects[i].dist)) { isects[i].dist = dist; isects[i].triIdx = triIdx/3; } } } }
void Camera::Draw(Renderer *renderer, const Body *excludeBody) { if (!m_camFrame) return; if (!renderer) return; m_renderer = renderer; glPushAttrib(GL_ALL_ATTRIB_BITS & (~GL_POINT_BIT)); m_renderer->SetPerspectiveProjection(m_fovAng, m_width/m_height, m_zNear, m_zFar); m_renderer->SetTransform(matrix4x4f::Identity()); m_renderer->ClearScreen(); matrix4x4d trans2bg; Frame::GetFrameRenderTransform(Pi::game->GetSpace()->GetRootFrame(), m_camFrame, trans2bg); trans2bg.ClearToRotOnly(); // Pick up to four suitable system light sources (stars) m_lightSources.clear(); m_lightSources.reserve(4); position_system_lights(m_camFrame, Pi::game->GetSpace()->GetRootFrame(), m_lightSources); if (m_lightSources.empty()) { // no lights means we're somewhere weird (eg hyperspace). fake one const Color col(1.f); m_lightSources.push_back(LightSource(0, Graphics::Light(Graphics::Light::LIGHT_DIRECTIONAL, vector3f(0.f), col, col))); } //fade space background based on atmosphere thickness and light angle float bgIntensity = 1.f; if (m_camFrame->GetParent() && m_camFrame->GetParent()->IsRotFrame()) { //check if camera is near a planet Body *camParentBody = m_camFrame->GetParent()->GetBody(); if (camParentBody && camParentBody->IsType(Object::PLANET)) { Planet *planet = static_cast<Planet*>(camParentBody); const vector3f relpos(planet->GetInterpPositionRelTo(m_camFrame)); double altitude(relpos.Length()); double pressure, density; planet->GetAtmosphericState(altitude, &pressure, &density); if (pressure >= 0.001) { //go through all lights to calculate something resembling light intensity float angle = 0.f; for(std::vector<LightSource>::const_iterator it = m_lightSources.begin(); it != m_lightSources.end(); ++it) { const vector3f lightDir(it->GetLight().GetPosition().Normalized()); angle += std::max(0.f, lightDir.Dot(-relpos.Normalized())) * it->GetLight().GetDiffuse().GetLuminance(); } //calculate background intensity with some hand-tweaked fuzz applied bgIntensity = Clamp(1.f - std::min(1.f, powf(density, 0.25f)) * (0.3f + powf(angle, 0.25f)), 0.f, 1.f); } } } Pi::game->GetSpace()->GetBackground().SetIntensity(bgIntensity); Pi::game->GetSpace()->GetBackground().Draw(renderer, trans2bg); { std::vector<Graphics::Light> rendererLights; for (size_t i = 0; i < m_lightSources.size(); i++) rendererLights.push_back(m_lightSources[i].GetLight()); renderer->SetLights(rendererLights.size(), &rendererLights[0]); } for (std::list<BodyAttrs>::iterator i = m_sortedBodies.begin(); i != m_sortedBodies.end(); ++i) { BodyAttrs *attrs = &(*i); // explicitly exclude a single body if specified (eg player) if (attrs->body == excludeBody) continue; double rad = attrs->body->GetClipRadius(); if (!m_frustum.TestPointInfinite((*i).viewCoords, rad)) continue; // draw spikes for far objects double screenrad = 500 * rad / attrs->camDist; // approximate pixel size if (attrs->body->IsType(Object::PLANET) && screenrad < 2) { // absolute bullshit double spikerad = (7 + 1.5*log10(screenrad)) * rad / screenrad; DrawSpike(spikerad, attrs->viewCoords, attrs->viewTransform); } else if (screenrad >= 2 || attrs->body->IsType(Object::STAR) || (attrs->body->IsType(Object::PROJECTILE) && screenrad > 0.25)) attrs->body->Render(renderer, this, attrs->viewCoords, attrs->viewTransform); } Sfx::RenderAll(renderer, Pi::game->GetSpace()->GetRootFrame(), m_camFrame); m_frame->RemoveChild(m_camFrame); delete m_camFrame; m_camFrame = 0; glPopAttrib(); }