void CreateLog (BOOL nl) { no_log = nl; strconcat (logFName,Core.ApplicationName,"_",Core.UserName,".log"); if (FS.path_exist("$logs$")) FS.update_path (logFName,"$logs$",logFName); if (!no_log) { IWriter *f = FS.w_open (logFName); if (f==NULL) { MessageBox (NULL,"Can't create log file.","Error",MB_ICONERROR); abort(); } FS.w_close (f); } LogFile.reserve (128); // Calculating build time_t Time; time (&Time); int build=0, mnum=0, dnum, ynum, mcnt; char mon[4]; char buf[128]; strcpy(buf,__DATE__); sscanf(buf,"%s %d %d",mon,&dnum, &ynum); for (int i=0; i<12; i++) { if (stricmp(month[i],mon)==0) mnum=i; } for (mcnt=6; mcnt<mnum; mcnt++) build+=day_in_month[mcnt]; build+=dnum; Msg("'%s' build %d, %s\n","xrCore",build+(ynum-1999)*365, __DATE__); }
void transfer(const char *name, xr_vector<T> &dest, IReader& F, u32 chunk) { IReader* O = F.open_chunk(chunk); u32 count = O?(O->length()/sizeof(T)):0; clMsg ("* %16s: %d",name,count); if (count) { dest.reserve(count); dest.insert (dest.begin(), (T*)O->pointer(), (T*)O->pointer() + count); } if (O) O->close (); }
void CDeflector::RemapUV (xr_vector<UVtri>& dest, u32 base_u, u32 base_v, u32 size_u, u32 size_v, u32 lm_u, u32 lm_v, BOOL bRotate) { dest.clear (); dest.reserve(UVpolys.size()); // UV rect (actual) Fvector2 a_min,a_max,a_size; GetRect (a_min,a_max); a_size.sub (a_max,a_min); // UV rect (dedicated) Fvector2 d_min,d_max,d_size; d_min.x = (float(base_u)+.5f)/float(lm_u); d_min.y = (float(base_v)+.5f)/float(lm_v); d_max.x = (float(base_u+size_u)-.5f)/float(lm_u); d_max.y = (float(base_v+size_v)-.5f)/float(lm_v); if (d_min.x>=d_max.x) { d_min.x=d_max.x=(d_min.x+d_max.x)/2; d_min.x-=EPS_S; d_max.x+=EPS_S; } if (d_min.y>=d_max.y) { d_min.y=d_max.y=(d_min.y+d_max.y)/2; d_min.y-=EPS_S; d_max.y+=EPS_S; } d_size.sub (d_max,d_min); // Remapping Fvector2 tc; UVtri tnew; if (bRotate) { for (UVIt it = UVpolys.begin(); it!=UVpolys.end(); it++) { UVtri& T = *it; tnew.owner = T.owner; for (int i=0; i<3; i++) { tc.x = ((T.uv[i].y-a_min.y)/a_size.y)*d_size.x + d_min.x; tc.y = ((T.uv[i].x-a_min.x)/a_size.x)*d_size.y + d_min.y; tnew.uv[i].set(tc); } dest.push_back (tnew); } } else { for (UVIt it = UVpolys.begin(); it!=UVpolys.end(); it++) { UVtri& T = *it; tnew.owner = T.owner; for (int i=0; i<3; i++) { tc.x = ((T.uv[i].x-a_min.x)/a_size.x)*d_size.x + d_min.x; tc.y = ((T.uv[i].y-a_min.y)/a_size.y)*d_size.y + d_min.y; tnew.uv[i].set(tc); } dest.push_back (tnew); } } }
BOOL QuadFit(u32 Base, u32 Size) { // ***** build horizontal line vecDW BaseLine; BaseLine.reserve(Size); // middle vertex& BaseNode = g_nodes[Base]; BaseLine.push_back(Base); // right expansion for (; BaseLine.size()<Size; ) { vertex& B = g_nodes[BaseLine.back()]; u32 RP = B.nRight(); if (RP==InvalidNode) break; if (used[RP]) break; if (!NodeSimilar(BaseNode,g_nodes[RP])) break; BaseLine.push_back(RP); } if (BaseLine.size()<Size) return FALSE; // down expansion BestQuad.clear (); BestQuad_Count = 0; BestQuad.reserve (Size); BestQuad.push_back (BaseLine); for (; BestQuad.size() < Size;) { // create _new list BestQuad.push_back (vecDW()); vecDW& src = BestQuad[BestQuad.size()-2]; vecDW& dest = BestQuad[BestQuad.size()-1]; dest.reserve (Size); // iterate on it vecDW_it I = src.begin (); vecDW_it E = src.end (); for (; I!=E; I++) { u32 id = g_nodes[*I].nBack(); if (id==InvalidNode) return FALSE; if (used[id]) return FALSE; if (!NodeSimilar(g_nodes[id],BaseNode)) return FALSE; dest.push_back (id); } } return TRUE; }
void CBuild::BuildPVS() { Fvector size; Fvector pos; Fvector ground_dir; Status("Preparing..."); g_TREE_ROOT->bbox.getsize(size); g_pvs_X = iROUND(ceilf(size.x/g_params.m_sample_step))+1; g_pvs_Y = iROUND(ceilf(size.y/g_params.m_sample_step))+1; g_pvs_Z = iROUND(ceilf(size.z/g_params.m_sample_step))+1; clMsg("Ceiling dimensions: [%3d,%3d,%3d]",g_pvs_X, g_pvs_Y, g_pvs_Z); // ground pick setup XRC.RayMode (RAY_ONLYFIRST|RAY_CULL); ground_dir.set (0,-1,0); // reserve memory CFS_File pvs_map ("pvs.temp"); u32 dwSlot = 0; u32 dwSlotsTotal= g_pvs_X*g_pvs_Y*g_pvs_Z; u32 pvs_reserve = dwSlotsTotal/1024 + 512; clMsg("PVS: %d M", (pvs_reserve*sizeof(vecW))/(1024*1024)); g_pvs.reserve (pvs_reserve); // begin! Status("Processing..."); u32 dwStartTime = timeGetTime(); for (int z=0; z<g_pvs_Z; z++) { for (int x=0; x<g_pvs_X; x++) { for (int y=0; y<g_pvs_Y; y++) { pos.set(x,y,z); pos.mul(g_params.m_sample_step); pos.add(g_TREE_ROOT->bbox.min); dwSlot++; // ground pick XRC.RayPick(precalc_identity,1.f,&RCAST_Model,pos,ground_dir,g_params.m_sample_break); if (XRC.GetRayContactCount()==0) { // don't calculate PVS for this point int tmp = -1; pvs_map.write(&tmp,4); continue; } // Sample PVS data g_TREE_ROOT->VisUnroll(pos,g_selected); if (!g_selected.empty()) { g_result.resize(g_selected.size()); ZeroMemory(g_result.begin(),g_result.size()*sizeof(BOOL)); ORM_Process(g_selected.size(),pos,g_selected.begin(),g_result.begin()); // Exclude invisible for (int i=0; i<g_selected.size(); i++) { if (!g_result[i]) { if (g_tree[g_selected[i]]->isPatch) continue; g_selected.erase(g_selected.begin()+i); g_result.erase(g_result.begin()+i); i--; } } } // Compress and record PVS sample pvs_map.w_u32(CompressSelected()); g_selected.clear(); // Statistic if (dwSlot%64 == 63) { Progress(float(dwSlot)/float(dwSlotsTotal)); u32 dwCurrentTime = timeGetTime(); Status("Sample #%d\nSpeed %3.1f samples per second\nPVS entrys: %d", dwSlot,1000.f*float(dwSlot)/float(dwCurrentTime-dwStartTime), g_pvs.size() ); } } } } ORM_Destroy(); clMsg("* PVS entrys: %d", g_pvs.size()); clMsg("* Aver. Speed: %3.1f", 1000.f*float(dwSlot)/float(timeGetTime()-dwStartTime)); }
BOOL ESceneAIMapTool::CreateNode(Fvector& vAt, SAINode& N, bool bIC) { // *** Query and cache polygons for ray-casting Fvector PointUp; PointUp.set(vAt); PointUp.y += RCAST_Depth; SnapXZ (PointUp,m_Params.fPatchSize); Fvector PointDown; PointDown.set(vAt); PointDown.y -= RCAST_Depth; SnapXZ (PointDown,m_Params.fPatchSize); Fbox BB; BB.set (PointUp,PointUp); BB.grow(m_Params.fPatchSize/2); // box 1 Fbox B2; B2.set (PointDown,PointDown); B2.grow(m_Params.fPatchSize/2); // box 2 BB.merge (B2); if (m_CFModel) { /* for(u32 i=0; i<m_CFModel->get_tris_count(); ++i) { CDB::TRI* tri = (m_CFModel->get_tris()+i); if(tri->material!=0) Msg("non-default material"); } */ Scene->BoxQuery(PQ,BB,CDB::OPT_FULL_TEST,m_CFModel); }else Scene->BoxQuery(PQ,BB,CDB::OPT_FULL_TEST,GetSnapList()); DWORD dwCount = PQ.r_count(); if (dwCount==0){ // Log("chasm1"); return FALSE; // chasm? } // *** Transfer triangles and compute sector // R_ASSERT(dwCount<RCAST_MaxTris); static xr_vector<tri> tris; tris.reserve(RCAST_MaxTris); tris.clear(); for (DWORD i=0; i<dwCount; i++) { SPickQuery::SResult* R = PQ.r_begin()+i; if (R->e_obj&&R->e_mesh) { CSurface* surf = R->e_mesh->GetSurfaceByFaceID(R->tag); //. SGameMtl* mtl = GMLib.GetMaterialByID(surf->_GameMtl()); //. if (mtl->Flags.is(SGameMtl::flPassable))continue; Shader_xrLC* c_sh = Device.ShaderXRLC.Get(surf->_ShaderXRLCName()); if (!c_sh->flags.bCollision) continue; } /* if(m_CFModel) { u16 mtl_id = R->material; if(std::find(m_ignored_materials.begin(), m_ignored_materials.end(), mtl_id) != m_ignored_materials.end() ) { //. Msg("--ignore"); continue; } } */ tris.push_back (tri()); tri& D = tris.back(); Fvector* V = R->verts; D.v[0] = &V[0]; D.v[1] = &V[1]; D.v[2] = &V[2]; D.N.mknormal(*D.v[0],*D.v[1],*D.v[2]); if (D.N.y<=0) tris.pop_back (); } if (tris.size()==0){ // Log("chasm2"); return FALSE; // chasm? } static xr_vector<Fvector> points; points.reserve(RCAST_Total); points.clear(); static xr_vector<Fvector> normals; normals.reserve(RCAST_Total);normals.clear(); Fvector P,D; D.set(0,-1,0); float coeff = 0.5f*m_Params.fPatchSize/float(RCAST_Count); for (int x=-RCAST_Count; x<=RCAST_Count; x++) { P.x = vAt.x + coeff*float(x); for (int z=-RCAST_Count; z<=RCAST_Count; z++) { P.z = vAt.z + coeff*float(z); P.y = vAt.y + 10.f; float tri_min_range = flt_max; int tri_selected = -1; float range,u,v; for (i=0; i<DWORD(tris.size()); i++){ if (ETOOLS::TestRayTriA(P,D,tris[i].v,u,v,range,false)){ if (range<tri_min_range){ tri_min_range = range; tri_selected = i; } } } if (tri_selected>=0) { P.y -= tri_min_range; points.push_back(P); normals.push_back(tris[tri_selected].N); } } } if (points.size()<3) { // Msg ("Failed to create node at [%f,%f,%f].",vAt.x,vAt.y,vAt.z); return FALSE; } //. float rc_lim = bIC?0.015f:0.7f; if (float(points.size())/float(RCAST_Total) < rc_lim) { // Msg ("Partial chasm at [%f,%f,%f].",vAt.x,vAt.y,vAt.z); return FALSE; } // *** Calc normal Fvector vNorm; vNorm.set(0,0,0); for (DWORD n=0; n<normals.size(); n++) vNorm.add(normals[n]); vNorm.div(float(normals.size())); vNorm.normalize(); /* { // second algorithm (Magic) Fvector N,O; N.set(vNorm); O.set(points[0]); Mgc::OrthogonalPlaneFit( points.size(),(Mgc::Vector3*)points.begin(), *((Mgc::Vector3*)&O), *((Mgc::Vector3*)&N) ); if (N.y<0) N.invert(); N.normalize(); vNorm.lerp(vNorm,N,.3f); vNorm.normalize(); } */ // *** Align plane Fvector vOffs; vOffs.set(0,-1000,0); Fplane PL; PL.build(vOffs,vNorm); for (DWORD p=0; p<points.size(); p++) { float dist = PL.classify(points[p]); if (dist>0) { vOffs = points[p]; PL.build(vOffs,vNorm); } } // *** Create node and register it N.Plane.build (vOffs,vNorm); // build plane D.set (0,1,0); N.Plane.intersectRayPoint(PointDown,D,N.Pos); // "project" position // *** Validate results vNorm.set(0,1,0); if (vNorm.dotproduct(N.Plane.n)<_cos(deg2rad(60.f))) return FALSE; float y_old = vAt.y; float y_new = N.Pos.y; if (y_old>y_new) { // down if (y_old-y_new > m_Params.fCanDOWN ) return FALSE; } else { // up if (y_new-y_old > m_Params.fCanUP ) return FALSE; } // *** Validate plane { Fvector PLP; D.set(0,-1,0); int num_successed_rays = 0; for (int x=-RCAST_Count; x<=RCAST_Count; x++) { P.x = N.Pos.x + coeff*float(x); for (int z=-RCAST_Count; z<=RCAST_Count; z++) { P.z = N.Pos.z + coeff*float(z); P.y = N.Pos.y; N.Plane.intersectRayPoint(P,D,PLP); // "project" position P.y = PLP.y+RCAST_VALID*0.01f; float tri_min_range = flt_max; int tri_selected = -1; float range,u,v; for (i=0; i<tris.size(); i++){ if (ETOOLS::TestRayTriA(P,D,tris[i].v,u,v,range,false)){ if (range<tri_min_range){ tri_min_range = range; tri_selected = i; } } } if (tri_selected>=0){ if (tri_min_range<RCAST_VALID) num_successed_rays++; } } } float perc = float(num_successed_rays)/float(RCAST_Total); //. if (!bIC&&(perc < 0.5f)){ float perc_lim = bIC?0.015f:0.5f; if (perc < perc_lim){ // Msg ("Floating node."); return FALSE; } } // *** Mask check // ??? return TRUE; }
wm_slot (ref_shader sh) {shader=sh;static_items.reserve(256);skeleton_items.reserve(256);}
void ProcessOne (u32 Base, u32 limit=8) { BestQuad.clear (); BestQuad_Count = 0; // ***** build horizontal line vecDW BaseLine; BaseLine.reserve(limit*2); u32 BL_Left=0,BL_Right=0; // middle vertex& BaseNode = g_nodes[Base]; BaseLine.push_back(Base); // left expansion for (;;) { vertex& B = g_nodes[BaseLine.front()]; u32 LP = B.nLeft(); if (BL_Left>limit) break; if (LP==InvalidNode) break; if (used[LP]) break; if (!NodeSimilar(BaseNode,g_nodes[LP])) break; BL_Left ++; BaseLine.insert(BaseLine.begin(),LP); } // right expansion for (;;) { vertex& B = g_nodes[BaseLine.back()]; u32 RP = B.nRight(); if (BL_Right>limit) break; if (RP==InvalidNode) break; if (used[RP]) break; if (!NodeSimilar(BaseNode,g_nodes[RP])) break; BL_Right++; BaseLine.push_back(RP); } // main cycle // Msg("- ---"); u32 BasePos = BaseLine[BL_Left]; for (u32 left=0; left<=BL_Left; left++) { u32 limit_right = left+limit-1; if (limit_right>=BaseLine.size()) limit_right=BaseLine.size()-1; u32 limit_left = left; if (limit_left<BL_Left) limit_left = BL_Left; if (limit_left>limit_right) limit_left = limit_right; for (int right=int(limit_right); right>=int(limit_left); right--) { // now we have range [left,right] // expand it up and down xr_vector<vecDW> stack_up; xr_vector<vecDW> stack_down; // Msg("[%2d,%2d], %d", left,right,BaseLine.size()); stack_up.reserve (limit); stack_up.push_back (vecDW()); stack_up.back().assign (BaseLine.begin()+left,BaseLine.begin()+right+1); stack_down.reserve (limit); stack_down.push_back (vecDW()); stack_down.back().assign(BaseLine.begin()+left,BaseLine.begin()+right+1); // expand up for (;stack_up.size()<=limit;) { // create _new list stack_up.push_back (vecDW()); vecDW& src = stack_up[stack_up.size()-2]; vecDW& dest = stack_up[stack_up.size()-1]; dest.reserve (limit); BOOL bFailed = FALSE; // iterate on it vecDW_it I = src.begin (); vecDW_it E = src.end (); for (; I!=E; I++) { u32 id = g_nodes[*I].nForward(); if (id==InvalidNode) { bFailed=TRUE; break; } if (used[id]) { bFailed=TRUE; break; } if (!NodeSimilar(g_nodes[id],BaseNode)){ bFailed=TRUE; break; } dest.push_back (id); } if (bFailed) { stack_up.pop_back(); break; } } // expand down for (; (stack_up.size()+stack_down.size()-1) <= limit;) { // create _new list stack_down.push_back(vecDW()); vecDW& src = stack_down[stack_down.size()-2]; vecDW& dest = stack_down[stack_down.size()-1]; dest.reserve (limit); BOOL bFailed = FALSE; // iterate on it vecDW_it I = src.begin (); vecDW_it E = src.end (); for (; I!=E; I++) { u32 id = g_nodes[*I].nBack(); if (id==InvalidNode) { bFailed=TRUE; break; } if (used[id]) { bFailed=TRUE; break; } if (!NodeSimilar(g_nodes[id],BaseNode)){ bFailed=TRUE; break; } dest.push_back (id); } if (bFailed) { stack_down.pop_back(); break; } } // calculate size u32 size_z = stack_up.size()+stack_down.size()-1; u32 size_x = stack_up.back().size(); u32 size_mix = size_z*size_x; if (size_mix>BestQuad_Count) { BestQuad_Count = size_mix; BestQuad.clear (); BestQuad.reserve (size_z); // transfer quad for (u32 it=stack_up.size()-1; it>0; it--) BestQuad.push_back(stack_up[it]); BestQuad.insert(BestQuad.begin(),stack_down.begin(),stack_down.end()); } } } }