void write( IWriter &w, const CDB::MODEL &m, const xrLC_GlobalData &lc_global_data ) { w.w_u32( (u32)m.get_verts_count() ); w.w( m.get_verts(), m.get_verts_count() * sizeof(Fvector) ); u32 tris_count = (u32) m.get_tris_count() ; w.w_u32( tris_count ); for( u32 i = 0; i < tris_count; ++i) ::write( w, m.get_tris()[i], lc_global_data ); // w.w( m.get_tris(), m.get_tris_count() * sizeof(CDB::TRI) ); }
void write( IWriter &w, const CDB::MODEL &m ) { w.w_u32( (u32)m.get_verts_count() ); w.w( m.get_verts(), m.get_verts_count() * sizeof(Fvector) ); u32 tris_count = (u32) m.get_tris_count() ; w.w_u32( tris_count ); for( u32 i = 0; i < tris_count; ++i) ::write( w, m.get_tris()[i] ); // w.w( m.get_tris(), m.get_tris_count() * sizeof(CDB::TRI) ); }
void CLightShadows::render () { // Gain access to collision-DB CDB::MODEL* DB = g_pGameLevel->ObjectSpace.GetStaticModel(); CDB::TRI* TRIS = DB->get_tris(); Fvector* VERTS = DB->get_verts(); int slot_line = S_rt_size/S_size; // Projection and xform float _43 = Device.mProject._43; Device.mProject._43 -= 0.002f; RCache.set_xform_world (Fidentity); RCache.set_xform_project (Device.mProject); Fvector View = Device.vCameraPosition; // Render shadows RCache.set_Shader (sh_World); RCache.set_Geometry (geom_World); int batch = 0; u32 Offset = 0; FVF::LIT* pv = (FVF::LIT*) RCache.Vertex.Lock (batch_size*3,geom_World->vb_stride,Offset); for (u32 s_it=0; s_it<shadows.size(); s_it++) { Device.Statistic->RenderDUMP_Srender.Begin (); shadow& S = shadows[s_it]; float Le = S.L->color.intensity()*S.E; int s_x = S.slot%slot_line; int s_y = S.slot/slot_line; Fvector2 t_scale, t_offset; t_scale.set (float(S_size)/float(S_rt_size),float(S_size)/float(S_rt_size)); t_scale.mul (.5f); t_offset.set(float(s_x)/float(slot_line),float(s_y)/float(slot_line)); t_offset.x += .5f/S_rt_size; t_offset.y += .5f/S_rt_size; // Search the cache cache_item* CI = 0; BOOL bValid = FALSE; cache_item CI_what; CI_what.O = S.O; CI_what.L = S.L; CI_what.tris=0; xr_vector<cache_item>::iterator CI_ptr = std::lower_bound(cache.begin(),cache.end(),CI_what,cache_search); if (CI_ptr==cache.end()) { // empty ? CI_ptr = cache.insert (CI_ptr,CI_what); CI = &*CI_ptr; bValid = FALSE; } else { if (CI_ptr->O != CI_what.O || CI_ptr->L != CI_what.L) { // we found something different CI_ptr = cache.insert (CI_ptr,CI_what); CI = &*CI_ptr; bValid = FALSE; } else { // Everything, OK. Check if info is still relevant... CI = &*CI_ptr; bValid = TRUE; if (!CI->Op.similar(CI->O->renderable.xform.c)) bValid = FALSE; else if (!CI->Lp.similar(CI->L->position)) bValid = FALSE; } } CI->time = Device.dwTimeGlobal; // acess time if (!bValid) { // Frustum CFrustum F; F.CreateFromMatrix (S.M,FRUSTUM_P_ALL); // Query xrc.frustum_options (0); xrc.frustum_query (DB,F); if (0==xrc.r_count()) continue; // Clip polys by frustum tess.clear (); for (CDB::RESULT* p = xrc.r_begin(); p!=xrc.r_end(); p++) { VERIFY((p->id>=0)&&(p->id<DB->get_tris_count())); // CDB::TRI& t = TRIS[p->id]; if (t.suppress_shadows) continue; sPoly A,B; A.push_back (VERTS[t.verts[0]]); A.push_back (VERTS[t.verts[1]]); A.push_back (VERTS[t.verts[2]]); // Calc plane, throw away degenerate tris and invisible to light polygons Fplane P; float mag = 0; Fvector t1,t2,n; t1.sub (A[0],A[1]); t2.sub (A[0],A[2]); n.crossproduct (t1,t2); mag = n.square_magnitude(); if (mag<EPS_S) continue; n.mul (1.f/_sqrt(mag)); P.build_unit_normal (A[0],n); float DOT_Fade = P.classify(S.L->position); if (DOT_Fade<0) continue; // Clip polygon sPoly* clip = F.ClipPoly (A,B); if (0==clip) continue; // Triangulate poly for (u32 v=2; v<clip->size(); v++) { tess.push_back (tess_tri()); tess_tri& T = tess.back(); T.v[0] = (*clip)[0]; T.v[1] = (*clip)[v-1]; T.v[2] = (*clip)[v]; T.N = P.n; } } // Remember params which builded cache item CI->O = S.O; CI->Op = CI->O->renderable.xform.c; CI->L = S.L; CI->Lp = CI->L->position; CI->tcnt = tess.size(); //Msg ("---free--- %x",u32(CI->tris)); xr_free (CI->tris); VERIFY(0==CI->tris); if (tess.size()) { CI->tris = xr_alloc<tess_tri>(CI->tcnt); //Msg ("---alloc--- %x",u32(CI->tris)); CopyMemory (CI->tris,&*tess.begin(),CI->tcnt * sizeof(tess_tri)); } } // Fill VB for (u32 tid=0; tid<CI->tcnt; tid++) { tess_tri& TT = CI->tris[tid]; Fvector* v = TT.v; Fvector T; Fplane ttp; ttp.build_unit_normal(v[0],TT.N); if (ttp.classify(View)<0) continue; int c0 = PLC_calc(v[0],TT.N,S.L,Le,S.C); int c1 = PLC_calc(v[1],TT.N,S.L,Le,S.C); int c2 = PLC_calc(v[2],TT.N,S.L,Le,S.C); if (c0>S_clip && c1>S_clip && c2>S_clip) continue; clamp (c0,S_ambient,255); clamp (c1,S_ambient,255); clamp (c2,S_ambient,255); S.M.transform(T,v[0]); pv->set(v[0],CLS(c0),(T.x+1)*t_scale.x+t_offset.x,(1-T.y)*t_scale.y+t_offset.y); pv++; S.M.transform(T,v[1]); pv->set(v[1],CLS(c1),(T.x+1)*t_scale.x+t_offset.x,(1-T.y)*t_scale.y+t_offset.y); pv++; S.M.transform(T,v[2]); pv->set(v[2],CLS(c2),(T.x+1)*t_scale.x+t_offset.x,(1-T.y)*t_scale.y+t_offset.y); pv++; batch++; if (batch==batch_size) { // Flush RCache.Vertex.Unlock (batch*3,geom_World->vb_stride); RCache.Render (D3DPT_TRIANGLELIST,Offset,batch); pv = (FVF::LIT*) RCache.Vertex.Lock(batch_size*3,geom_World->vb_stride,Offset); batch = 0; } } Device.Statistic->RenderDUMP_Srender.End (); } // Flush if nessesary RCache.Vertex.Unlock (batch*3,geom_World->vb_stride); if (batch) { RCache.Render (D3DPT_TRIANGLELIST,Offset,batch); } // Clear all shadows and free old entries in the cache shadows.clear (); for (int cit=0; cit<int(cache.size()); cit++) { cache_item& ci = cache[cit]; u32 time = Device.dwTimeGlobal - ci.time; if (time > cache_old) { //Msg ("---free--- %x",u32(ci.tris)); xr_free (ci.tris); VERIFY(0==ci.tris); cache.erase (cache.begin()+cit); cit --; } } // Projection Device.mProject._43 = _43; RCache.set_xform_project (Device.mProject); }