void CCustomObject::AnimationDrawPath() { // motion path VERIFY (m_Motion); #ifdef _EDITOR if (EPrefs->object_flags.is(epoDrawAnimPath)){ float fps = m_Motion->FPS(); float min_t = (float)m_Motion->FrameStart()/fps; float max_t = (float)m_Motion->FrameEnd()/fps; Fvector T,r; u32 clr = 0xffffffff; path_points.clear (); for (float t=min_t; (t<max_t)||fsimilar(t,max_t,EPS_L); t+=1/30.f){ m_Motion->_Evaluate (t,T,r); path_points.push_back(T); } Device.SetShader (Device.m_WireShader); RCache.set_xform_world (Fidentity); if (!path_points.empty()) DU_impl.DrawPrimitiveL (D3DPT_LINESTRIP,path_points.size()-1,path_points.begin(),path_points.size(),clr,true,false); CEnvelope* E = m_Motion->Envelope(); for (KeyIt k_it=E->keys.begin(); k_it!=E->keys.end(); k_it++){ m_Motion->_Evaluate ((*k_it)->time,T,r); if (Device.m_Camera.GetPosition().distance_to_sqr(T)<50.f*50.f){ DU_impl.DrawCross (T,0.1f,0.1f,0.1f, 0.1f,0.1f,0.1f, clr,false); DU_impl.OutText (T,AnsiString().sprintf("K: %3.3f",(*k_it)->time).c_str(),0xffffffff,0x00000000); } } } #endif }
BOOL SphereValid (FvectorVec& geom, Fsphere& test) { if (!f_valid(test.P.x) || !f_valid(test.R)) { Msg ("*** Attention ***: invalid sphere: %f,%f,%f - %f",test.P.x,test.P.y,test.P.z,test.R); } Fsphere S = test; S.R += EPS_L; for (FvectorIt I = geom.begin(); I!=geom.end(); I++) if (!S.contains(*I)) return FALSE; return TRUE; }
int AppendVertex(FvectorVec& _points, MPoint& _pt) { Fvector pt; // convert from internal units to the current ui units MDistance dst_x (_pt.x); MDistance dst_y (_pt.y); MDistance dst_z (_pt.z); pt.set ((float)dst_x.asMeters(),(float)dst_y.asMeters(),-(float)dst_z.asMeters()); for (FvectorIt it=_points.begin(); it!=_points.end(); it++) if (it->similar(pt)) return it-_points.begin(); _points.push_back(pt); return _points.size()-1; }
void ComputeSphere(Fsphere &B, FvectorVec& V) { if (V.size()<3) { B.P.set(0,0,0); B.R=0.f; return; } // 1: calc first variation Fsphere S1; Fsphere_compute (S1,V.begin(),V.size()); BOOL B1 = SphereValid(V,S1); // 2: calc ordinary algorithm (2nd) Fsphere S2; Fbox bbox; bbox.invalidate (); for (FvectorIt I=V.begin(); I!=V.end(); I++) bbox.modify(*I); bbox.grow (EPS_L); bbox.getsphere (S2.P,S2.R); S2.R = -1; for (I=V.begin(); I!=V.end(); I++) { float d = S2.P.distance_to_sqr(*I); if (d>S2.R) S2.R=d; } S2.R = _sqrt (_abs(S2.R)); BOOL B2 = SphereValid(V,S2); // 3: calc magic-fm Mgc::Sphere _S3 = Mgc::MinSphere(V.size(), (const Mgc::Vector3*) V.begin()); Fsphere S3; S3.P.set (_S3.Center().x,_S3.Center().y,_S3.Center().z); S3.R = _S3.Radius(); BOOL B3 = SphereValid(V,S3); // select best one if (B1 && (S1.R<S2.R)){ // miniball or FM if (B3 && (S3.R<S1.R)){ // FM wins B.set (S3); }else{ // MiniBall wins B.set (S1); } }else{ // base or FM if (B3 && (S3.R<S2.R)){ // FM wins B.set (S3); }else{ // Base wins :) R_ASSERT(B2); B.set (S2); } } }
void ComputeCylinder(Fcylinder& C, Fobb& B, FvectorVec& V) { if (V.size()<3) { C.invalidate(); return; } // pow(area,(3/2))/volume // 2*Pi*R*H+2*Pi*R*R // Fvector axis; float max_hI = flt_min; float min_hI = flt_max; float max_rI = flt_min; float max_hJ = flt_min; float min_hJ = flt_max; float max_rJ = flt_min; float max_hK = flt_min; float min_hK = flt_max; float max_rK = flt_min; Fvector axisJ = B.m_rotate.j; Fvector axisI = B.m_rotate.i; Fvector axisK = B.m_rotate.k; Fvector& c = B.m_translate; for (FvectorIt I=V.begin(); I!=V.end(); I++){ Fvector tmp; Fvector pt = *I; Fvector pt_c; pt_c.sub(pt,c); float pI = axisI.dotproduct(pt); min_hI = _min(min_hI,pI); max_hI = _max(max_hI,pI); tmp.mad (c,axisI,axisI.dotproduct(pt_c)); max_rI = _max(max_rI,tmp.distance_to(pt)); float pJ = axisJ.dotproduct(pt); min_hJ = _min(min_hJ,pJ); max_hJ = _max(max_hJ,pJ); tmp.mad (c,axisJ,axisJ.dotproduct(pt_c)); max_rJ = _max(max_rJ,tmp.distance_to(pt)); float pK = axisK.dotproduct(pt); min_hK = _min(min_hK,pK); max_hK = _max(max_hK,pK); tmp.mad (c,axisK,axisK.dotproduct(pt_c)); max_rK = _max(max_rK,tmp.distance_to(pt)); } float hI = (max_hI-min_hI); float hJ = (max_hJ-min_hJ); float hK = (max_hK-min_hK); float vI = hI*M_PI*_sqr(max_rI); float vJ = hJ*M_PI*_sqr(max_rJ); float vK = hK*M_PI*_sqr(max_rK); // vI = pow(2*M_PI*max_rI*hI+2*M_PI*_sqr(max_rI),3/2)/vI; // vJ = pow(2*M_PI*max_rJ*hJ+2*M_PI*_sqr(max_rJ),3/2)/vJ; // vK = pow(2*M_PI*max_rK*hK+2*M_PI*_sqr(max_rK),3/2)/vK; // pow(area,(3/2))/volume // 2*Pi*R*H+2*Pi*R*R if (vI<vJ){ if (vI<vK){ //vI; C.m_direction.set (axisI); C.m_height = hI; C.m_radius = max_rI; }else{ // vK C.m_direction.set (axisK); C.m_height = hK; C.m_radius = max_rK; } }else { //vJ < vI if (vJ<vK){ // vJ C.m_direction.set (axisJ); C.m_height = hJ; C.m_radius = max_rJ; } else { //vK C.m_direction.set (axisK); C.m_height = hK; C.m_radius = max_rK; } } C.m_center.set (B.m_translate); /* if (V.size()<3) { B.invalidate(); return; } Mgc::Cylinder CYL = Mgc::ContCylinder(V.size(), (const Mgc::Vector3*) V.begin()); B.m_center.set (CYL.Center()); B.m_direction.set (CYL.Direction()); B.m_height = CYL.Height(); B.m_radius = CYL.Radius(); */ }
void CEditableMesh::Optimize(BOOL NoOpt) { if (!NoOpt){ #ifdef _EDITOR UnloadRenderBuffers (); UnloadCForm (); #endif UnloadFNormals (true); UnloadVNormals (true); UnloadSVertices (true); UnloadAdjacency (true); // clear static data for (int x=0; x<MX+1; x++) for (int y=0; y<MY+1; y++) for (int z=0; z<MZ+1; z++) VM[x][y][z].clear(); VMscale.set(m_Box.max.x-m_Box.min.x+EPS_S, m_Box.max.y-m_Box.min.y+EPS_S, m_Box.max.z-m_Box.min.z+EPS_S); VMmin.set(m_Box.min.x, m_Box.min.y, m_Box.min.z); VMeps.set(VMscale.x/MX/2,VMscale.y/MY/2,VMscale.z/MZ/2); VMeps.x = (VMeps.x<EPS_L)?VMeps.x:EPS_L; VMeps.y = (VMeps.y<EPS_L)?VMeps.y:EPS_L; VMeps.z = (VMeps.z<EPS_L)?VMeps.z:EPS_L; m_NewPoints.clear(); m_NewPoints.reserve(m_VertCount); boolVec faces_mark; faces_mark.resize(m_FaceCount,false); int i_del_face = 0; for (u32 k=0; k<m_FaceCount; k++){ if (!OptimizeFace(m_Faces[k])){ faces_mark[k] = true; i_del_face ++; } } m_VertCount = m_NewPoints.size(); xr_free (m_Verts); m_Verts = xr_alloc<Fvector>(m_VertCount); Memory.mem_copy (m_Verts,&*m_NewPoints.begin(),m_NewPoints.size()*sizeof(Fvector)); if (i_del_face){ st_Face* old_faces = m_Faces; u32* old_sg = m_SGs; m_Faces = xr_alloc<st_Face> (m_FaceCount-i_del_face); m_SGs = xr_alloc<u32> (m_FaceCount-i_del_face); u32 new_dk = 0; for (u32 dk=0; dk<m_FaceCount; dk++){ if (faces_mark[dk]){ for (SurfFacesPairIt plp_it=m_SurfFaces.begin(); plp_it!=m_SurfFaces.end(); plp_it++){ IntVec& pol_lst = plp_it->second; for (int k=0; k<int(pol_lst.size()); k++){ int& f = pol_lst[k]; if (f>(int)dk){ f--; }else if (f==(int)dk){ pol_lst.erase(pol_lst.begin()+k); k--; } } } continue; } m_Faces[new_dk] = old_faces[dk]; m_SGs[new_dk] = old_sg[dk]; new_dk++; } m_FaceCount = m_FaceCount-i_del_face; xr_free (old_faces); xr_free (old_sg); } } }
bool CEditableMesh::OptimizeFace(st_Face& face){ Fvector points[3]; int mface[3]; int k; for (k=0; k<3; k++){ points[k].set(m_Verts[face.pv[k].pindex]); mface[k] = -1; } // get similar vert idx list for (k=0; k<3; k++){ U32Vec* vl; int ix,iy,iz; ix = iFloor(float(points[k].x-VMmin.x)/VMscale.x*MX); iy = iFloor(float(points[k].y-VMmin.y)/VMscale.y*MY); iz = iFloor(float(points[k].z-VMmin.z)/VMscale.z*MZ); vl = &(VM[ix][iy][iz]); for(U32It it=vl->begin();it!=vl->end(); it++){ FvectorIt v = m_NewPoints.begin()+(*it); if( v->similar(points[k],EPS) ) mface[k] = *it; } } for(k=0; k<3; k++ ){ if( mface[k] == -1 ){ mface[k] = m_NewPoints.size(); m_NewPoints.push_back( points[k] ); int ix,iy,iz; ix = iFloor(float(points[k].x-VMmin.x)/VMscale.x*MX); iy = iFloor(float(points[k].y-VMmin.y)/VMscale.y*MY); iz = iFloor(float(points[k].z-VMmin.z)/VMscale.z*MZ); VM[ix][iy][iz].push_back(mface[k]); int ixE,iyE,izE; ixE = iFloor(float(points[k].x+VMeps.x-VMmin.x)/VMscale.x*MX); iyE = iFloor(float(points[k].y+VMeps.y-VMmin.y)/VMscale.y*MY); izE = iFloor(float(points[k].z+VMeps.z-VMmin.z)/VMscale.z*MZ); if (ixE!=ix) VM[ixE][iy][iz].push_back(mface[k]); if (iyE!=iy) VM[ix][iyE][iz].push_back(mface[k]); if (izE!=iz) VM[ix][iy][izE].push_back(mface[k]); if ((ixE!=ix)&&(iyE!=iy)) VM[ixE][iyE][iz].push_back(mface[k]); if ((ixE!=ix)&&(izE!=iz)) VM[ixE][iy][izE].push_back(mface[k]); if ((iyE!=iy)&&(izE!=iz)) VM[ix][iyE][izE].push_back(mface[k]); if ((ixE!=ix)&&(iyE!=iy)&&(izE!=iz)) VM[ixE][iyE][izE].push_back(mface[k]); } } if ((mface[0]==mface[1])||(mface[1]==mface[2])||(mface[0]==mface[2])){ Msg("!Optimize: Invalid face found. Removed."); return false; }else{ face.pv[0].pindex = mface[0]; face.pv[1].pindex = mface[1]; face.pv[2].pindex = mface[2]; return true; } }