void CDeflector::L_Direct (CDB::COLLIDER* DB, base_lighting* LightsSelected, HASH& H) { R_ASSERT (DB); R_ASSERT (LightsSelected); lm_layer& lm = layer; // Setup variables Fvector2 dim,half; dim.set (float(lm.width),float(lm.height)); half.set (.5f/dim.x,.5f/dim.y); // Jitter data Fvector2 JS; JS.set (.4999f/dim.x, .4999f/dim.y); u32 Jcount; Fvector2* Jitter; Jitter_Select(Jitter, Jcount); // Lighting itself DB->ray_options (0); for (u32 V=0; V<lm.height; V++) { for (u32 U=0; U<lm.width; U++) { u32 Fcount = 0; base_color_c C; try { for (u32 J=0; J<Jcount; J++) { // LUMEL space Fvector2 P; P.x = float(U)/dim.x + half.x + Jitter[J].x * JS.x; P.y = float(V)/dim.y + half.y + Jitter[J].y * JS.y; xr_vector<UVtri*>& space = H.query(P.x,P.y); // World space Fvector wP,wN,B; for (UVtri** it=&*space.begin(); it!=&*space.end(); it++) { if ((*it)->isInside(P,B)) { // We found triangle and have barycentric coords Face *F = (*it)->owner; Vertex *V1 = F->v[0]; Vertex *V2 = F->v[1]; Vertex *V3 = F->v[2]; wP.from_bary(V1->P,V2->P,V3->P,B); //. не нужно использовать if (F->Shader().flags.bLIGHT_Sharp) { wN.set(F->N); } // else { wN.from_bary(V1->N,V2->N,V3->N,B); exact_normalize (wN); wN.add (F->N); exact_normalize (wN); } try { LightPoint (DB, RCAST_Model, C, wP, wN, *LightsSelected, (b_norgb?LP_dont_rgb:0)|(b_nosun?LP_dont_sun:0)|LP_UseFaceDisable, F); //. Fcount += 1; } catch (...) { clMsg("* ERROR (CDB). Recovered. "); } break; } } } } catch (...) { clMsg("* ERROR (Light). Recovered. "); } if (Fcount) { C.scale (Fcount); C.mul (.5f); lm.surface [V*lm.width+U]._set(C); lm.marker [V*lm.width+U] = 255; } else { lm.surface [V*lm.width+U]._set(C); // 0-0-0-0-0 lm.marker [V*lm.width+U] = 0; } } } // *** Render Edges float texel_size = (1.f/float(_max(lm.width,lm.height)))/8.f; for (u32 t=0; t<UVpolys.size(); t++) { UVtri& T = UVpolys[t]; Face* F = T.owner; R_ASSERT (F); try { L_Direct_Edge (DB,LightsSelected, T.uv[0], T.uv[1], F->v[0]->P, F->v[1]->P, F->N, texel_size,F); L_Direct_Edge (DB,LightsSelected, T.uv[1], T.uv[2], F->v[1]->P, F->v[2]->P, F->N, texel_size,F); L_Direct_Edge (DB,LightsSelected, T.uv[2], T.uv[0], F->v[2]->P, F->v[0]->P, F->N, texel_size,F); } catch (...) { clMsg("* ERROR (Edge). Recovered. "); } } }
//----------------------------------------------------------------------- void xrMU_Model::calc_lighting (xr_vector<base_color>& dest, const Fmatrix& xform, CDB::MODEL* MDL, base_lighting& lights, u32 flags) { // trans-map typedef xr_multimap<float,v_vertices> mapVert; typedef mapVert::iterator mapVertIt; mapVert g_trans; u32 I; // trans-epsilons const float eps = EPS_L; const float eps2 = 2.f*eps; // calc pure rotation matrix Fmatrix Rxform,tmp,R; R.set (xform ); R.translate_over (0,0,0 ); tmp.transpose (R ); Rxform.invert (tmp ); // Perform lighting CDB::COLLIDER DB; DB.ray_options (0); // Disable faces if needed /* BOOL bDisableFaces = flags&LP_UseFaceDisable; if (bDisableFaces) for (I=0; I<m_faces.size(); I++) m_faces[I]->flags.bDisableShadowCast = true; */ // Perform lighting for (I = 0; I<m_vertices.size(); I++) { _vertex* V = m_vertices[I]; // Get ambient factor float v_amb = 0.f; float v_trans = 0.f; for (u32 f=0; f<V->m_adjacents.size(); f++) { _face* F = V->m_adjacents[f]; v_amb += F->Shader().vert_ambient; v_trans += F->Shader().vert_translucency; } v_amb /= float(V->m_adjacents.size()); v_trans /= float(V->m_adjacents.size()); float v_inv = 1.f-v_amb; base_color_c vC; Fvector vP,vN; xform.transform_tiny (vP,V->P); Rxform.transform_dir (vN,V->N); exact_normalize (vN); // multi-sample const int n_samples = (g_params().m_quality==ebqDraft)?1:6; for (u32 sample=0; sample<(u32)n_samples; sample++) { float a = 0.2f * float(sample) / float(n_samples); Fvector P,N; N.random_dir (vN,deg2rad(30.f)); P.mad (vP,N,a); LightPoint (&DB, MDL, vC, P, N, lights, flags, 0); } vC.scale (n_samples); vC._tmp_ = v_trans; if (flags&LP_dont_hemi) ; else vC.hemi += v_amb; V->C._set (vC); // Search const float key = V->P.x; mapVertIt it = g_trans.lower_bound (key); mapVertIt it2 = it; // Decrement to the start and inc to end while (it!=g_trans.begin() && ((it->first+eps2)>key)) it--; while (it2!=g_trans.end() && ((it2->first-eps2)<key)) it2++; if (it2!=g_trans.end()) it2++; // Search BOOL found = FALSE; for (; it!=it2; it++) { v_vertices& VL = it->second; _vertex* Front = VL.front(); R_ASSERT (Front); if (Front->P.similar(V->P,eps)) { found = TRUE; VL.push_back (V); } } // Register if (!found) { mapVertIt ins = g_trans.insert(mk_pair(key,v_vertices())); ins->second.reserve (32); ins->second.push_back (V); } } // Enable faces if needed /* if (bDisableFaces) for (I=0; I<m_faces.size(); I++) m_faces[I]->flags.bDisableShadowCast = true; */ // Process all groups for (mapVertIt it=g_trans.begin(); it!=g_trans.end(); it++) { // Unique v_vertices& VL = it->second; std::sort (VL.begin(),VL.end()); VL.erase (std::unique(VL.begin(),VL.end()),VL.end()); // Calc summary color base_color_c C; for (int v=0; v<int(VL.size()); v++) { base_color_c vC; VL[v]->C._get (vC); C.max (vC); } // Calculate final vertex color for (u32 v=0; v<int(VL.size()); v++) { base_color_c vC; VL[v]->C._get (vC); // trans-level float level = vC._tmp_; // base_color_c R; R.lerp (vC,C,level); R.max (vC); R.mul (.5f); VL[v]->C._set (R); } } // Transfer colors to destination dest.resize (m_vertices.size()); for (I = 0; I<m_vertices.size(); I++) { Fvector ptPos = m_vertices[I]->P; base_color ptColor = m_vertices[I]->C; dest[I] = ptColor; } }