void BuildMatrix (Fmatrix &mView, float invsz, const Fvector norm, const Fvector& from) { // build projection Fmatrix mScale; Fvector at,up,right,y; at.sub (from,norm); y.set (0,1,0); if (_abs(norm.y)>.99f) y.set(1,0,0); right.crossproduct (y,norm); up.crossproduct (norm,right); mView.build_camera (from,at,up); mScale.scale (invsz,invsz,invsz); mView.mulA_43 (mScale); }
void CWallmarksEngine::BuildMatrix (Fmatrix &mView, float invsz, const Fvector& from) { // build projection Fmatrix mScale; Fvector at,up,right,y; at.sub (from,sml_normal); y.set (0,1,0); if (_abs(sml_normal.y)>.99f) y.set(1,0,0); right.crossproduct (y,sml_normal); up.crossproduct (sml_normal,right); mView.build_camera (from,at,up); mScale.scale (invsz,invsz,invsz); mView.mulA_43 (mScale); }
void CLightShadows::calculate () { if (casters.empty()) return; BOOL bRTS = FALSE; Device.Statistic->RenderDUMP_Scalc.Begin (); HW.pDevice->SetRenderState (D3DRS_ZENABLE, D3DZB_FALSE); // iterate on objects int slot_id = 0; int slot_line = S_rt_size/S_size; int slot_max = slot_line*slot_line; const float eps = 2*EPS_L; for (u32 o_it=0; o_it<casters.size(); o_it++) { caster& C = *casters [o_it]; if (C.nodes.empty()) continue; // Select lights and calc importance CROS_impl* LT = (CROS_impl*)C.O->renderable_ROS(); xr_vector<CROS_impl::Light>& lights = LT->lights; // iterate on lights for (u32 l_it=0; (l_it<lights.size()) && (slot_id<slot_max); l_it++) { CROS_impl::Light& L = lights[l_it]; if (L.energy<S_level) continue; //Msg ("~ light: %d",l_it); // setup rt+state(s) for first use if (!bRTS) { bRTS = TRUE; RCache.set_RT (RT_temp->pRT); RCache.set_ZB (RImplementation.Target->pTempZB); HW.pDevice->Clear (0,0,D3DCLEAR_TARGET,D3DCOLOR_XRGB(255,255,255),1,0); } // calculate light center Fvector Lpos = L.source->position; float Lrange = L.source->range; //Log ("* l-pos:",Lpos); //Msg ("* l-range: %f",Lrange); if (L.source->flags.type==IRender_Light::DIRECT) { // Msg (" -direct- : %f",L.energy); Lpos.mul (L.source->direction,-100); Lpos.add (C.C); Lrange = 120; } else { VERIFY (_valid(Lpos)); VERIFY (_valid(C.C)); float _dist ; while (true) { _dist = C.C.distance_to (Lpos); //Msg ("* o-dist: %f", _dist); if (_dist>EPS_L) break; Lpos.y += .01f; //. hack to avoid light-in-the-center-of-object } float _R = C.O->renderable.visual->vis.sphere.R+0.1f; //Msg ("* o-r: %f",_R); if (_dist<_R) { Fvector Ldir; Ldir.sub (C.C,Lpos); Ldir.normalize (); Lpos.mad (Lpos,Ldir,_dist-_R); //Msg ("* moving lpos"); } } // calculate projection-matrix Fmatrix mProject,mProjectR; float p_dist = C.C.distance_to(Lpos); float p_R = C.O->renderable.visual->vis.sphere.R; float p_hat = p_R/p_dist; float p_asp = 1.f; float p_near = p_dist-p_R-eps; float p_nearR = C.C.distance_to(L.source->position) + p_R*0.85f + eps; p_nearR = p_near; float p_far = _min(Lrange,_max(p_dist+S_fade,p_dist+p_R)); if (p_near<eps) continue; if (p_far<(p_near+eps)) continue; if (p_hat>0.9f) continue; if (p_hat<0.01f) continue; //Msg ("* near(%f), near-x(%f)",p_near,p_nearR); mProject.build_projection_HAT (p_hat,p_asp,p_near, p_far); mProjectR.build_projection_HAT (p_hat,p_asp,p_nearR, p_far); RCache.set_xform_project (mProject); // calculate view-matrix Fmatrix mView; Fvector v_D,v_N,v_R; v_D.sub (C.C,Lpos); v_D.normalize (); if(1-_abs(v_D.y)<EPS) v_N.set(1,0,0); else v_N.set(0,1,0); v_R.crossproduct (v_N,v_D); v_N.crossproduct (v_D,v_R); mView.build_camera (Lpos,C.C,v_N); RCache.set_xform_view (mView); // combine and build frustum Fmatrix mCombine,mCombineR; mCombine.mul (mProject,mView); mCombineR.mul (mProjectR,mView); // Select slot and set viewport int s_x = slot_id%slot_line; int s_y = slot_id/slot_line; D3DVIEWPORT9 VP = {s_x*S_size,s_y*S_size,S_size,S_size,0,1 }; CHK_DX (HW.pDevice->SetViewport(&VP)); // Render object-parts for (u32 n_it=0; n_it<C.nodes.size(); n_it++) { NODE& N = C.nodes[n_it]; IRender_Visual *V = N.pVisual; RCache.set_Element (V->shader_ref->E[SE_R1_LMODELS]); RCache.set_xform_world (N.Matrix); V->Render (-1.0f); } // register shadow and increment slot shadows.push_back (shadow()); shadows.back().O = C.O; shadows.back().slot = slot_id; shadows.back().C = C.C; shadows.back().M = mCombineR; shadows.back().L = L.source; shadows.back().E = L.energy; #ifdef DEBUG shadows.back().dbg_HAT = p_hat; #endif slot_id ++; } } // clear casters for (u32 cs=0; cs<casters.size(); cs++) casters_pool.push_back(casters[cs]); casters.clear (); // Blur if (bRTS) { // Fill VB u32 Offset; FVF::TL4uv* pv = (FVF::TL4uv*) RCache.Vertex.Lock (4,geom_Blur.stride(),Offset); RImplementation.ApplyBlur4 (pv,S_rt_size,S_rt_size,S_blur_kernel); RCache.Vertex.Unlock (4,geom_Blur.stride()); // Actual rendering (pass0, temp2real) RCache.set_RT (RT->pRT ); RCache.set_ZB (RImplementation.Target->pTempZB ); RCache.set_Shader (sh_BlurTR ); RCache.set_Geometry (geom_Blur ); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } // Finita la comedia HW.pDevice->SetRenderState (D3DRS_ZENABLE, D3DZB_TRUE); Device.Statistic->RenderDUMP_Scalc.End (); RCache.set_xform_project (Device.mProject); RCache.set_xform_view (Device.mView); }
void CDeflector::OA_Export() { if (UVpolys.empty()) return; // Correct normal // (semi-proportional to pixel density) FPU::m64r (); Fvector tN; tN.set (0,0,0); float density = 0; float fcount = 0; for (UVIt it = UVpolys.begin(); it!=UVpolys.end(); it++) { Face *F = it->owner; Fvector SN; SN.set (F->N); SN.mul (1+EPS*F->CalcArea()); tN.add (SN); density += F->Shader().lm_density; fcount += 1.f; } if (tN.magnitude()>EPS_S && _valid(tN)) normal.set(tN).normalize(); else clMsg("* ERROR: Internal precision error in CDeflector::OA_Export"); density /= fcount; // Orbitrary Oriented Ortho - Projection Fmatrix mView; Fvector at,from,up,right,y; at.set (0,0,0); from.add (at,normal); y.set (0,1,0); if (_abs(normal.y)>.99f) y.set(1,0,0); right.crossproduct(y,normal); right.normalize_safe(); up.crossproduct(normal,right); up.normalize_safe(); mView.build_camera(from,at,up); Fbox bb; bb.invalidate(); for (UVIt it = UVpolys.begin(); it!=UVpolys.end(); it++) { UVtri *T = &*it; Face *F = T->owner; Fvector P; // projected for (int i=0; i<3; i++) { mView.transform_tiny (P,F->v[i]->P); T->uv[i].set (P.x,P.y); bb.modify (F->v[i]->P); } } bb.getsphere(Sphere.P,Sphere.R); // UV rect Fvector2 min,max,size; GetRect (min,max); size.sub (max,min); // Surface u32 dwWidth = iCeil(size.x*g_params.m_lm_pixels_per_meter*density+.5f); clamp(dwWidth, 1u,512u-2*BORDER); u32 dwHeight = iCeil(size.y*g_params.m_lm_pixels_per_meter*density+.5f); clamp(dwHeight,1u,512u-2*BORDER); layer.create (dwWidth,dwHeight); }
void CLightProjector::calculate () { #ifdef _GPA_ENABLED TAL_SCOPED_TASK_NAMED( "CLightProjector::calculate()" ); #endif // _GPA_ENABLED if (receivers.empty()) return; // perform validate / markup for (u32 r_it=0; r_it<receivers.size(); r_it++) { // validate BOOL bValid = TRUE; IRenderable* O = receivers[r_it]; CROS_impl* LT = (CROS_impl*)O->renderable_ROS(); int slot = LT->shadow_recv_slot; if (slot<0 || slot>=P_o_count) bValid = FALSE; // invalid slot else if (cache[slot].O!=O) bValid = FALSE; // not the same object else { // seems to be valid Fbox bb; bb.xform (O->renderable.visual->getVisData().box,O->renderable.xform); if (cache[slot].BB.contains(bb)) { // inside, but maybe timelimit exceeded? if (Device.dwTimeGlobal > cache[slot].dwTimeValid) bValid = FALSE; // timeout } else bValid = FALSE; // out of bounds } // if (bValid) { // Ok, use cached version cache[slot].dwFrame = Device.dwFrame; } else { taskid.push_back (r_it); } } if (taskid.empty()) return; // Begin Device.Statistic->RenderDUMP_Pcalc.Begin (); RCache.set_RT (RT->pRT); RCache.set_ZB (RImplementation.Target->pTempZB); CHK_DX(HW.pDevice->Clear (0,0, D3DCLEAR_ZBUFFER | (HW.Caps.bStencil?D3DCLEAR_STENCIL:0), 0,1,0 )); RCache.set_xform_world (Fidentity); // reallocate/reassociate structures + perform all the work for (u32 c_it=0; c_it<cache.size(); c_it++) { if (taskid.empty()) break; if (Device.dwFrame==cache[c_it].dwFrame) continue; // found not used slot int tid = taskid.back(); taskid.pop_back(); recv& R = cache [c_it]; IRenderable* O = receivers [tid]; const vis_data& vis = O->renderable.visual->getVisData(); CROS_impl* LT = (CROS_impl*)O->renderable_ROS(); VERIFY2 (_valid(O->renderable.xform),"Invalid object transformation"); VERIFY2 (_valid(vis.sphere.P),"Invalid object's visual sphere"); Fvector C; O->renderable.xform.transform_tiny (C,vis.sphere.P); R.O = O; R.C = C; R.C.y += vis.sphere.R*0.1f; //. YURA: 0.1 can be more R.BB.xform (vis.box,O->renderable.xform).scale(0.1f); R.dwTimeValid = Device.dwTimeGlobal + ::Random.randI(time_min,time_max); LT->shadow_recv_slot = c_it; // Msg ("[%f,%f,%f]-%f",C.C.x,C.C.y,C.C.z,C.O->renderable.visual->vis.sphere.R); // calculate projection-matrix Fmatrix mProject; float p_R = R.O->renderable.visual->getVisData().sphere.R * 1.1f; //VERIFY2 (p_R>EPS_L,"Object has no physical size"); VERIFY3 (p_R>EPS_L,"Object has no physical size", R.O->renderable.visual->getDebugName().c_str()); float p_hat = p_R/P_cam_dist; float p_asp = 1.f; float p_near = P_cam_dist-EPS_L; float p_far = P_cam_dist+p_R+P_cam_range; mProject.build_projection_HAT (p_hat,p_asp,p_near,p_far); RCache.set_xform_project (mProject); // calculate view-matrix Fmatrix mView; Fvector v_C, v_Cs, v_N; v_C.set (R.C); v_Cs = v_C; v_C.y += P_cam_dist; v_N.set (0,0,1); VERIFY (_valid(v_C) && _valid(v_Cs) && _valid(v_N)); // validate Fvector v; v.sub (v_Cs,v_C);; #ifdef DEBUG if ((v.x*v.x+v.y*v.y+v.z*v.z)<=flt_zero) { CObject* OO = dynamic_cast<CObject*>(R.O); Msg("Object[%s] Visual[%s] has invalid position. ",*OO->cName(),*OO->cNameVisual()); Fvector cc; OO->Center(cc); Log("center=",cc); Log("visual_center=",OO->Visual()->getVisData().sphere.P); Log("full_matrix=",OO->XFORM()); Log ("v_N",v_N); Log ("v_C",v_C); Log ("v_Cs",v_Cs); Log("all bones transform:--------"); CKinematics* K = dynamic_cast<CKinematics*>(OO->Visual()); for(u16 ii=0; ii<K->LL_BoneCount();++ii){ Fmatrix tr; tr = K->LL_GetTransform(ii); Log("bone ",K->LL_BoneName_dbg(ii)); Log("bone_matrix",tr); } Log("end-------"); } #endif // handle invalid object-bug if ((v.x*v.x+v.y*v.y+v.z*v.z)<=flt_zero) { // invalidate record, so that object will be unshadowed, but doesn't crash R.dwTimeValid = Device.dwTimeGlobal; LT->shadow_recv_frame = Device.dwFrame-1; LT->shadow_recv_slot = -1; continue ; } mView.build_camera (v_C,v_Cs,v_N); RCache.set_xform_view (mView); // Select slot, set viewport int s_x = c_it%P_o_line; int s_y = c_it/P_o_line; D3DVIEWPORT9 VP = {s_x*P_o_size,s_y*P_o_size,P_o_size,P_o_size,0,1 }; CHK_DX (HW.pDevice->SetViewport(&VP)); // Clear color to ambience Fvector& cap = LT->get_approximate(); CHK_DX (HW.pDevice->Clear(0,0, D3DCLEAR_TARGET, color_rgba_f(cap.x,cap.y,cap.z, (cap.x+cap.y+cap.z)/4.f), 1, 0 )); // calculate uv-gen matrix and clamper Fmatrix mCombine; mCombine.mul (mProject,mView); Fmatrix mTemp; float fSlotSize = float(P_o_size)/float(P_rt_size); float fSlotX = float(s_x*P_o_size)/float(P_rt_size); float fSlotY = float(s_y*P_o_size)/float(P_rt_size); float fTexelOffs = (.5f / P_rt_size); Fmatrix m_TexelAdjust = { 0.5f/*x-scale*/, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f/*y-scale*/, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f/*z-range*/, 0.0f, 0.5f/*x-bias*/, 0.5f + fTexelOffs/*y-bias*/, 0.0f/*z-bias*/, 1.0f }; R.UVgen.mul (m_TexelAdjust,mCombine); mTemp.scale (fSlotSize,fSlotSize,1); R.UVgen.mulA_44 (mTemp); mTemp.translate (fSlotX+fTexelOffs,fSlotY+fTexelOffs,0); R.UVgen.mulA_44 (mTemp); // Build bbox and render Fvector min,max; Fbox BB; min.set (R.C.x-p_R, R.C.y-(p_R+P_cam_range), R.C.z-p_R); max.set (R.C.x+p_R, R.C.y+0, R.C.z+p_R); BB.set (min,max); R.UVclamp_min.set (min).add (.05f); // shrink a little R.UVclamp_max.set (max).sub (.05f); // shrink a little ISpatial* spatial = dynamic_cast<ISpatial*> (O); if (spatial) { spatial->spatial_updatesector (); if (spatial->spatial.sector) RImplementation.r_dsgraph_render_R1_box (spatial->spatial.sector,BB,SE_R1_LMODELS); } //if (spatial) RImplementation.r_dsgraph_render_subspace (spatial->spatial.sector,mCombine,v_C,FALSE); } // Blur /* { // Fill vertex buffer u32 Offset; FVF::TL4uv* pv = (FVF::TL4uv*) RCache.Vertex.Lock (4,geom_Blur.stride(),Offset); RImplementation.ApplyBlur4 (pv,P_rt_size,P_rt_size,P_blur_kernel); RCache.Vertex.Unlock (4,geom_Blur.stride()); // Actual rendering (pass0, temp2real) RCache.set_RT (RT->pRT); RCache.set_ZB (NULL); RCache.set_Shader (sh_BlurTR ); RCache.set_Geometry (geom_Blur ); RCache.Render (D3DPT_TRIANGLELIST,Offset,0,4,0,2); } */ // Finita la comedia Device.Statistic->RenderDUMP_Pcalc.End (); RCache.set_xform_project (Device.mProject); RCache.set_xform_view (Device.mView); }