C3DModel CTriangulator<Real, OBB3<Real> >::Triangulate(const OBB3<Real> &pShape) { C3DModel model; std::vector<Vector3<Real> > vVertices; std::vector<TriFace> vFaces; Vector3<Real> vertices[8]; pShape.computeVertices(vertices); for(int i=0;i<8;i++) vVertices.push_back(vertices[i]); //front faces int verts[3]; verts[0]=0; verts[1]=1; verts[2]=5; TriFace face(verts); vFaces.push_back(face); verts[0]=0; verts[1]=5; verts[2]=4; face=TriFace(verts); vFaces.push_back(face); //back faces verts[0]=3; verts[1]=6; verts[2]=7; face=TriFace(verts); vFaces.push_back(face); verts[0]=3; verts[1]=2; verts[2]=6; face=TriFace(verts); vFaces.push_back(face); //bottom faces verts[0]=0; verts[1]=1; verts[2]=2; face=TriFace(verts); vFaces.push_back(face); verts[0]=0; verts[1]=2; verts[2]=3; face=TriFace(verts); vFaces.push_back(face); //top faces verts[0]=4; verts[1]=5; verts[2]=6; face=TriFace(verts); vFaces.push_back(face); verts[0]=4; verts[1]=6; verts[2]=7; face=TriFace(verts); vFaces.push_back(face); //left faces verts[0]=3; verts[1]=7; verts[2]=4; face=TriFace(verts); vFaces.push_back(face); verts[0]=3; verts[1]=4; verts[2]=0; face=TriFace(verts); vFaces.push_back(face); //right faces verts[0]=1; verts[1]=2; verts[2]=6; face=TriFace(verts); vFaces.push_back(face); verts[0]=1; verts[1]=6; verts[2]=5; face=TriFace(verts); vFaces.push_back(face); model.CreateFrom(vVertices,vFaces); return model; }
const Point& vertex_of_face(size_t v, size_t f) const { return vertex(face(f)(v)); }
void TET::drawFaces() { for(int x = 0; x < 4; x++) face(x).draw(); }
const MGFace* MGShell::face(size_t i)const{ const_pcellItr j=pcell_begin(); std::advance(j,i); return face(j); }
bool Foam::solidParticle::move(solidParticle::trackData& td) { td.switchProcessor = false; td.keepParticle = true; const polyMesh& mesh = cloud().pMesh(); const polyBoundaryMesh& pbMesh = mesh.boundaryMesh(); scalar deltaT = mesh.time().deltaT().value(); scalar tEnd = (1.0 - stepFraction())*deltaT; scalar dtMax = tEnd; while (td.keepParticle && !td.switchProcessor && tEnd > SMALL) { if (debug) { Info<< "Time = " << mesh.time().timeName() << " deltaT = " << deltaT << " tEnd = " << tEnd << " steptFraction() = " << stepFraction() << endl; } // set the lagrangian time-step scalar dt = min(dtMax, tEnd); // remember which cell the parcel is in // since this will change if a face is hit label celli = cell(); dt *= trackToFace(position() + dt*U_, td); tEnd -= dt; stepFraction() = 1.0 - tEnd/deltaT; cellPointWeight cpw(mesh, position(), celli, face()); scalar rhoc = td.rhoInterp().interpolate(cpw); vector Uc = td.UInterp().interpolate(cpw); scalar nuc = td.nuInterp().interpolate(cpw); scalar rhop = td.spc().rhop(); scalar magUr = mag(Uc - U_); scalar ReFunc = 1.0; scalar Re = magUr*d_/nuc; if (Re > 0.01) { ReFunc += 0.15*pow(Re, 0.687); } scalar Dc = (24.0*nuc/d_)*ReFunc*(3.0/4.0)*(rhoc/(d_*rhop)); U_ = (U_ + dt*(Dc*Uc + (1.0 - rhoc/rhop)*td.g()))/(1.0 + dt*Dc); if (onBoundary() && td.keepParticle) { if (isA<processorPolyPatch>(pbMesh[patch(face())])) { td.switchProcessor = true; } } } return td.keepParticle; }
void Surface_mesh:: split(Edge e, Vertex v) { Halfedge h0 = halfedge(e, 0); Halfedge o0 = halfedge(e, 1); Vertex v2 = to_vertex(o0); Halfedge e1 = new_edge(v, v2); Halfedge t1 = opposite_halfedge(e1); Face f0 = face(h0); Face f3 = face(o0); set_halfedge(v, h0); set_vertex(o0, v); if (!is_boundary(h0)) { Halfedge h1 = next_halfedge(h0); Halfedge h2 = next_halfedge(h1); Vertex v1 = to_vertex(h1); Halfedge e0 = new_edge(v, v1); Halfedge t0 = opposite_halfedge(e0); Face f1 = new_face(); set_halfedge(f0, h0); set_halfedge(f1, h2); set_face(h1, f0); set_face(t0, f0); set_face(h0, f0); set_face(h2, f1); set_face(t1, f1); set_face(e0, f1); set_next_halfedge(h0, h1); set_next_halfedge(h1, t0); set_next_halfedge(t0, h0); set_next_halfedge(e0, h2); set_next_halfedge(h2, t1); set_next_halfedge(t1, e0); } else { set_next_halfedge(prev_halfedge(h0), t1); set_next_halfedge(t1, h0); // halfedge handle of _vh already is h0 } if (!is_boundary(o0)) { Halfedge o1 = next_halfedge(o0); Halfedge o2 = next_halfedge(o1); Vertex v3 = to_vertex(o1); Halfedge e2 = new_edge(v, v3); Halfedge t2 = opposite_halfedge(e2); Face f2 = new_face(); set_halfedge(f2, o1); set_halfedge(f3, o0); set_face(o1, f2); set_face(t2, f2); set_face(e1, f2); set_face(o2, f3); set_face(o0, f3); set_face(e2, f3); set_next_halfedge(e1, o1); set_next_halfedge(o1, t2); set_next_halfedge(t2, e1); set_next_halfedge(o0, e2); set_next_halfedge(e2, o2); set_next_halfedge(o2, o0); } else { set_next_halfedge(e1, next_halfedge(o0)); set_next_halfedge(o0, e1); set_halfedge(v, e1); } if (halfedge(v2) == h0) set_halfedge(v2, t1); }
void Sighter::procSight(cv::Mat &frame, cv::Mat &lfeat, cv::Mat &rfeat) { cv::cvtColor(frame, drawMat, CV_BGRA2BGR); cv::flip(drawMat, drawMat, 1); cv::cvtColor(drawMat, grayMat, CV_BGR2GRAY); cv::Rect frect; cv::Mat& draw = drawMat; cv::Mat& gray = grayMat; //Detect face cv::vector<cv::Rect> faces; faceDetector.detectMultiScale(gray, faces, 1.1, 20, CV_HAAR_DO_CANNY_PRUNING|CV_HAAR_FIND_BIGGEST_OBJECT, cv::Size(gray.cols/4,gray.rows/4)); if(faces.empty()) { return; } frect = faces[0]; cv::Mat face = gray(frect); //Detect eye cv::vector<cv::Rect> leyes,reyes; cv::Size max_size = cv::Size(face.cols/2,face.rows/4); cv::Size min_size = cv::Size(face.cols/10, 10); cv::Mat lface = face(cv::Rect(0,face.rows/4,face.cols/2,face.rows/3)); eyeDetector.detectMultiScale(lface, leyes, 1.1, 20, CV_HAAR_DO_CANNY_PRUNING, min_size, max_size); cv::Mat rface = face(cv::Rect(face.cols/2,face.rows/4,face.cols/2,face.rows/3)); eyeDetector.detectMultiScale(rface, reyes, 1.1, 20, CV_HAAR_DO_CANNY_PRUNING, min_size, max_size); int szl = (int)leyes.size(); int szr = (int)reyes.size(); if(szl < 1 || szr < 1) { return; } //have min vertical difference int min_dy = INT_MAX; cv::Rect lerect, rerect; for(int i=0;i<szl;i++) { int cy = leyes[i].y + leyes[i].height/2; for(int j=0;j<szr;j++) { int cyr = reyes[j].y + reyes[j].height/2; int d = abs(cy-cyr); if( d < min_dy) { min_dy = d; lerect = leyes[i]; rerect = reyes[j]; } } } //transform to worldwide coordinate lerect.x += frect.x; lerect.y += frect.y + frect.height/4; rerect.x += frect.x + frect.width/2; rerect.y += frect.y + frect.height/4; //classifing eye's action cv::Mat legray = gray(lerect); cv::Mat regray = gray(rerect); cv::flip(regray, regray, 1); lfeat = legray; rfeat = regray; cv::Mat sample(50,50,CV_8UC1); cv::resize(legray, sample, sample.size()); int ldir = -1; if(eyeActM) ldir = eyeActM->predict(sample); cv::resize(regray, sample, sample.size()); int rdir = -1; if(eyeActM) rdir = eyeActM->predict(sample); SightState sstate = STARE_NONE; if( ldir == 0 && rdir == 0 ) { sstate = STARE_CENTER; } if( ldir == 2 && rdir == 1) { sstate = STARE_LEFT; } if( ldir == 1 && rdir == 2) { sstate = STARE_RIGHT; } { #define ACT_STAT_TOTAL 10 static SightState sstates[ACT_STAT_TOTAL] = {STARE_NONE}; static int ssi = 0; static int ssleft = 0; static int ssright = 0; static int sscenter = 0; static int ssnone = ACT_STAT_TOTAL; switch(sstates[ssi]) { case STARE_NONE: ssnone--; break; case STARE_LEFT: ssleft--; break; case STARE_RIGHT: ssright--; break; case STARE_CENTER: sscenter--; break; default: break; } switch(sstate) { case STARE_NONE: ssnone++; if(ssnone >= ACT_STAT_TOTAL*0.6) { sightState = STARE_NONE; } break; case STARE_LEFT: ssleft++; if(ssleft >= ACT_STAT_TOTAL*0.6) { sightState = STARE_LEFT; } break; case STARE_RIGHT: ssright++; if(ssright >= ACT_STAT_TOTAL*0.6) { sightState = STARE_RIGHT; } break; case STARE_CENTER: sscenter++; if(sscenter >= ACT_STAT_TOTAL*0.6) { sightState = STARE_CENTER; } break; default: break; } sstates[ssi] = sstate; ssi = (ssi+1)%ACT_STAT_TOTAL; } //tracking the pupil pulLeft.procPupil(legray); pulRight.procPupil(regray); pulLeft.pulCenter += lerect.tl(); pulRight.pulCenter += rerect.tl(); //Drawing int r = MAX(pulLeft.pulRect.height, pulRight.pulRect.height)/3; static int ani_r = 100; static int ani_speed = 5; if(ani_r > 0) { cv::circle(draw, pulLeft.pulCenter, ani_r, CV_RGB(255,0,0),1.5); cv::circle(draw, pulRight.pulCenter, ani_r, CV_RGB(255,0,0),1.5); ani_r -= ani_speed; ani_speed += 5; } else if( r > 0 ) { cv::circle(draw, pulLeft.pulCenter, r, CV_RGB(255,0,0), CV_FILLED); cv::circle(draw, pulLeft.pulCenter, r*3, CV_RGB(255,0,0), 1); cv::circle(draw, pulRight.pulCenter, r, CV_RGB(255,0,0), CV_FILLED); cv::circle(draw, pulRight.pulCenter, r*3, CV_RGB(255,0,0), 1); } cv::rectangle(draw, frect, CV_RGB(255,255,0)); cv::rectangle(draw, lerect, CV_RGB(0,255,0)); cv::rectangle(draw, rerect, CV_RGB(0,255,0)); }
forAll(patchTopologyFaces, patchTopologyFaceLabel) { label blockLabel = blockLabels[patchTopologyFaceLabel]; faceList blockFaces ( blocks[blockLabel].blockDef().blockShape().faces() ); forAll(blockFaces, blockFaceLabel) { if ( blockFaces[blockFaceLabel] == patchTopologyFaces[patchTopologyFaceLabel] ) { const labelListList& blockPatchFaces = blocks[blockLabel].boundaryPatches()[blockFaceLabel]; forAll(blockPatchFaces, blockFaceLabel) { // Lookup the face points // and collapse duplicate point labels quadFace[0] = mergeList_ [ blockPatchFaces[blockFaceLabel][0] + blockOffsets_[blockLabel] ]; label nUnique = 1; for ( label facePointLabel = 1; facePointLabel < 4; facePointLabel++ ) { quadFace[nUnique] = mergeList_ [ blockPatchFaces[blockFaceLabel][facePointLabel] + blockOffsets_[blockLabel] ]; if (quadFace[nUnique] != quadFace[nUnique-1]) { nUnique++; } } if (quadFace[nUnique-1] == quadFace[0]) { nUnique--; } if (nUnique == 4) { patchFaces[faceLabel++] = quadFace; } else if (nUnique == 3) { patchFaces[faceLabel++] = face ( labelList::subList(quadFace, 3) ); } // else the face has collapsed to an edge or point } } }
void ConcavePolygonShapeSW::_setup(DVector<Vector3> p_faces) { int src_face_count=p_faces.size(); ERR_FAIL_COND(src_face_count%3); src_face_count/=3; DVector<Vector3>::Read r = p_faces.read(); const Vector3 * facesr= r.ptr(); #if 0 Map<Vector3,int> point_map; List<Face> face_list; for(int i=0;i<src_face_count;i++) { Face3 faceaux; for(int j=0;j<3;j++) { faceaux.vertex[j]=facesr[i*3+j].snapped(_POINT_SNAP); //faceaux.vertex[j]=facesr[i*3+j];//facesr[i*3+j].snapped(_POINT_SNAP); } ERR_CONTINUE( faceaux.is_degenerate() ); Face face; for(int j=0;j<3;j++) { Map<Vector3,int>::Element *E=point_map.find(faceaux.vertex[j]); if (E) { face.indices[j]=E->value(); } else { face.indices[j]=point_map.size(); point_map.insert(faceaux.vertex[j],point_map.size()); } } face_list.push_back(face); } vertices.resize( point_map.size() ); DVector<Vector3>::Write vw = vertices.write(); Vector3 *verticesw=vw.ptr(); AABB _aabb; for( Map<Vector3,int>::Element *E=point_map.front();E;E=E->next()) { if (E==point_map.front()) { _aabb.pos=E->key(); } else { _aabb.expand_to(E->key()); } verticesw[E->value()]=E->key(); } point_map.clear(); // not needed anymore faces.resize(face_list.size()); DVector<Face>::Write w = faces.write(); Face *facesw=w.ptr(); int fc=0; for( List<Face>::Element *E=face_list.front();E;E=E->next()) { facesw[fc++]=E->get(); } face_list.clear(); DVector<_VolumeSW_BVH_Element> bvh_array; bvh_array.resize( fc ); DVector<_VolumeSW_BVH_Element>::Write bvhw = bvh_array.write(); _VolumeSW_BVH_Element *bvh_arrayw=bvhw.ptr(); for(int i=0;i<fc;i++) { AABB face_aabb; face_aabb.pos=verticesw[facesw[i].indices[0]]; face_aabb.expand_to( verticesw[facesw[i].indices[1]] ); face_aabb.expand_to( verticesw[facesw[i].indices[2]] ); bvh_arrayw[i].face_index=i; bvh_arrayw[i].aabb=face_aabb; bvh_arrayw[i].center=face_aabb.pos+face_aabb.size*0.5; } w=DVector<Face>::Write(); vw=DVector<Vector3>::Write(); int count=0; _VolumeSW_BVH *bvh_tree=_volume_sw_build_bvh(bvh_arrayw,fc,count); ERR_FAIL_COND(count==0); bvhw=DVector<_VolumeSW_BVH_Element>::Write(); bvh.resize( count+1 ); DVector<BVH>::Write bvhw2 = bvh.write(); BVH*bvh_arrayw2=bvhw2.ptr(); int idx=0; _fill_bvh(bvh_tree,bvh_arrayw2,idx); set_aabb(_aabb); #else DVector<_VolumeSW_BVH_Element> bvh_array; bvh_array.resize( src_face_count ); DVector<_VolumeSW_BVH_Element>::Write bvhw = bvh_array.write(); _VolumeSW_BVH_Element *bvh_arrayw=bvhw.ptr(); faces.resize(src_face_count); DVector<Face>::Write w = faces.write(); Face *facesw=w.ptr(); vertices.resize( src_face_count*3 ); DVector<Vector3>::Write vw = vertices.write(); Vector3 *verticesw=vw.ptr(); AABB _aabb; for(int i=0;i<src_face_count;i++) { Face3 face( facesr[i*3+0], facesr[i*3+1], facesr[i*3+2] ); bvh_arrayw[i].aabb=face.get_aabb(); bvh_arrayw[i].center = bvh_arrayw[i].aabb.pos + bvh_arrayw[i].aabb.size * 0.5; bvh_arrayw[i].face_index=i; facesw[i].indices[0]=i*3+0; facesw[i].indices[1]=i*3+1; facesw[i].indices[2]=i*3+2; facesw[i].normal=face.get_plane().normal; verticesw[i*3+0]=face.vertex[0]; verticesw[i*3+1]=face.vertex[1]; verticesw[i*3+2]=face.vertex[2]; if (i==0) _aabb=bvh_arrayw[i].aabb; else _aabb.merge_with(bvh_arrayw[i].aabb); } w=DVector<Face>::Write(); vw=DVector<Vector3>::Write(); int count=0; _VolumeSW_BVH *bvh_tree=_volume_sw_build_bvh(bvh_arrayw,src_face_count,count); bvh.resize( count+1 ); DVector<BVH>::Write bvhw2 = bvh.write(); BVH*bvh_arrayw2=bvhw2.ptr(); int idx=0; _fill_bvh(bvh_tree,bvh_arrayw2,idx); configure(_aabb); // this type of shape has no margin #endif }
AutoPtr<Elem> Hex8::build_side (const unsigned int i, bool proxy) const { libmesh_assert_less (i, this->n_sides()); if (proxy) { AutoPtr<Elem> ap(new Side<Quad4,Hex8>(this,i)); return ap; } else { AutoPtr<Elem> face(new Quad4); face->subdomain_id() = this->subdomain_id(); // Think of a unit cube: (-1,1) x (-1,1)x (-1,1) switch (i) { case 0: // the face at z = -1 { face->set_node(0) = this->get_node(0); face->set_node(1) = this->get_node(3); face->set_node(2) = this->get_node(2); face->set_node(3) = this->get_node(1); return face; } case 1: // the face at y = -1 { face->set_node(0) = this->get_node(0); face->set_node(1) = this->get_node(1); face->set_node(2) = this->get_node(5); face->set_node(3) = this->get_node(4); return face; } case 2: // the face at x = 1 { face->set_node(0) = this->get_node(1); face->set_node(1) = this->get_node(2); face->set_node(2) = this->get_node(6); face->set_node(3) = this->get_node(5); return face; } case 3: // the face at y = 1 { face->set_node(0) = this->get_node(2); face->set_node(1) = this->get_node(3); face->set_node(2) = this->get_node(7); face->set_node(3) = this->get_node(6); return face; } case 4: // the face at x = -1 { face->set_node(0) = this->get_node(3); face->set_node(1) = this->get_node(0); face->set_node(2) = this->get_node(4); face->set_node(3) = this->get_node(7); return face; } case 5: // the face at z = 1 { face->set_node(0) = this->get_node(4); face->set_node(1) = this->get_node(5); face->set_node(2) = this->get_node(6); face->set_node(3) = this->get_node(7); return face; } default: libmesh_error_msg("Invalid side i = " << i); } } libmesh_error_msg("We'll never get here!"); AutoPtr<Elem> ap(NULL); return ap; }
AutoPtr<Elem> InfPrism12::build_side (const unsigned int i, bool proxy) const { libmesh_assert_less (i, this->n_sides()); if (proxy) { switch (i) { // base case 0: { AutoPtr<Elem> ap(new Side<Tri6,InfPrism12>(this,i)); return ap; } // ifem sides case 1: case 2: case 3: { AutoPtr<Elem> ap(new Side<InfQuad6,InfPrism12>(this,i)); return ap; } default: libmesh_error(); } } else { switch (i) { case 0: // the triangular face at z=-1, base face { AutoPtr<Elem> face(new Tri6); // Note that for this face element, the normal points inward face->set_node(0) = this->get_node(0); face->set_node(1) = this->get_node(1); face->set_node(2) = this->get_node(2); face->set_node(3) = this->get_node(6); face->set_node(4) = this->get_node(7); face->set_node(5) = this->get_node(8); return face; } case 1: // the quad face at y=0 { AutoPtr<Elem> face(new InfQuad6); face->set_node(0) = this->get_node(0); face->set_node(1) = this->get_node(1); face->set_node(2) = this->get_node(3); face->set_node(3) = this->get_node(4); face->set_node(4) = this->get_node(6); face->set_node(5) = this->get_node(9); return face; } case 2: // the other quad face { AutoPtr<Elem> face(new InfQuad6); face->set_node(0) = this->get_node(1); face->set_node(1) = this->get_node(2); face->set_node(2) = this->get_node(4); face->set_node(3) = this->get_node(5); face->set_node(4) = this->get_node(7); face->set_node(5) = this->get_node(10); return face; } case 3: // the quad face at x=0 { AutoPtr<Elem> face(new InfQuad6); face->set_node(0) = this->get_node(2); face->set_node(1) = this->get_node(0); face->set_node(2) = this->get_node(5); face->set_node(3) = this->get_node(3); face->set_node(4) = this->get_node(8); face->set_node(5) = this->get_node(11); return face; } default: { libmesh_error(); AutoPtr<Elem> ap(NULL); return ap; } } } // We'll never get here. libmesh_error(); AutoPtr<Elem> ap(NULL); return ap; }
int main(int argc, char **argv) { face(argc, argv); return 0; }
void RefineEverything( NodeVector & vecNodes, FaceVector & vecFaces, int nResolution ) { // Generate segment map SegmentMap mapSegment; ConstructSegmentMap(vecFaces, mapSegment, -1); FaceVector vecFacesOld = vecFaces; // Loop over all faces vecFaces.clear(); // Construct map from segments to edges std::map<Segment, Edge> mapEdge; SegmentMapIterator iter = mapSegment.begin(); for (; iter != mapSegment.end(); iter++) { Edge edge; GenerateEdgeVertices( nResolution, iter->first[0], iter->first[1], vecNodes, edge); mapEdge.insert(std::pair<Segment, Edge>(iter->first, edge)); } // Loop over all faces and refine for (int n = 0 ; n < vecFacesOld.size(); n++) { const Segment & seg0 = vecFacesOld[n].iterSegment[0]->first; const Segment & seg1 = vecFacesOld[n].iterSegment[1]->first; const Segment & seg2 = vecFacesOld[n].iterSegment[2]->first; const Segment & seg3 = vecFacesOld[n].iterSegment[3]->first; Edge edge0 = mapEdge.find(seg0)->second; Edge edge1 = mapEdge.find(seg1)->second; Edge edge3 = mapEdge.find(seg2)->second; Edge edge2 = mapEdge.find(seg3)->second; // Align bottom and left edge if (edge0[0] == edge1[0]) { } else if (edge0[0] == edge1[edge1.size()-1]) { edge1 = edge1.Flip(); } else if (edge0[edge0.size()-1] == edge1[0]) { edge0 = edge0.Flip(); } else if (edge0[edge0.size()-1] == edge1[edge1.size()-1]) { edge0 = edge0.Flip(); edge1 = edge1.Flip(); } else { _EXCEPTIONT("Logic error"); } // Align bottom and right edge if (edge0[edge0.size()-1] == edge2[0]) { } else if (edge0[edge0.size()-1] == edge2[edge2.size()-1]) { edge2 = edge2.Flip(); } else { _EXCEPTIONT("Logic error"); } // Align top and left edge if (edge1[edge1.size()-1] == edge3[0]) { } else if (edge1[edge1.size()-1] == edge3[edge3.size()-1]) { edge3 = edge3.Flip(); } else { _EXCEPTIONT("Logic error"); } Edge edgeTop; Edge edgeBot = edge0; for (int j = 0; j < nResolution; j++) { // Generate top level edge if (j != nResolution-1) { int ix0 = edge1[j+1]; int ix1 = edge2[j+1]; GenerateEdgeVertices(nResolution, ix0, ix1, vecNodes, edgeTop); } else { edgeTop = edge3; } // Generate face for (int i = 0; i < nResolution; i++) { Face face( edgeBot[i+1], edgeBot[i], edgeTop[i], edgeTop[i+1], vecFacesOld[n].nRefineLevel); face.nColor = vecFacesOld[n].nColor; face.nTag = vecFacesOld[n].nTag; vecFaces.push_back(face); } // Increment row edgeBot = edgeTop; } } }
C3DModel CTriangulator<Real, Cylinder<Real> >::Triangulate(const Cylinder<Real> &pShape) { Vector3<Real> center = pShape.getCenter(); Vector3<Real> u = pShape.getU(); Real height2 = pShape.getHalfLength(); Real rad = pShape.getRadius(); C3DModel model; std::vector<Vector3<Real> > vVertices; std::vector<TriFace> vFaces; int verticalsegments = 2; int pointsoncircle = 24; Real dalpha = 2.0 * CMath<Real>::SYS_PI/(Real)pointsoncircle; Vector3<Real> vTop = center + (height2 * u); Vector3<Real> vBottom = center - (height2 * u); vVertices.push_back(vTop); Real dheight = (2.0 * height2)/Real(verticalsegments+1); Real currentheight = center.z + height2; Real alpha = 0.0; //create the vertices for(int j=0;j<(verticalsegments+2);j++) { for(int i=0;i<pointsoncircle;i++) { Vector3<Real> vNext=pShape.eval(alpha); vNext.z = currentheight; vVertices.push_back(vNext); alpha+=dalpha; } alpha=0.0; currentheight-=dheight; } vVertices.push_back(vBottom); //add the top triangle fan for(int i=0;i<pointsoncircle;i++) { int verts[3]; verts[0]=0; verts[1]=1+i; verts[2]=1+(i+1)%pointsoncircle; TriFace face(verts); vFaces.push_back(face); } //add the body of the cylinder int index = 1; for(int i=0;i<verticalsegments+1;i++) { int index=1+i*pointsoncircle; for(int j=0;j<pointsoncircle;j++) { int verts[3]; verts[0]=index+j; verts[1]=index+pointsoncircle+j; verts[2]=index+(j+1)%pointsoncircle; TriFace face1(verts); vFaces.push_back(face1); verts[0]=index+(j+1)%pointsoncircle; verts[1]=index+pointsoncircle+j; verts[2]=index+pointsoncircle+(j+1)%pointsoncircle; TriFace face2(verts); vFaces.push_back(face2); } }//end for i int ilast=vVertices.size()-1; int ilastrow=ilast-pointsoncircle; //add lower triangle fan for(int i=0;i<pointsoncircle;i++) { int verts[3]; verts[0]=ilast; verts[1]=ilastrow+(i+1)%pointsoncircle; verts[2]=ilastrow+i; TriFace face(verts); vFaces.push_back(face); } model.CreateFrom(vVertices,vFaces); return model; }
void Surface_mesh:: remove_edge(Halfedge h) { Halfedge hn = next_halfedge(h); Halfedge hp = prev_halfedge(h); Halfedge o = opposite_halfedge(h); Halfedge on = next_halfedge(o); Halfedge op = prev_halfedge(o); Face fh = face(h); Face fo = face(o); Vertex vh = to_vertex(h); Vertex vo = to_vertex(o); // halfedge -> vertex Halfedge_around_vertex_circulator vh_it, vh_end; vh_it = vh_end = halfedges(vo); do { set_vertex(opposite_halfedge(vh_it), vh); } while (++vh_it != vh_end); // halfedge -> halfedge set_next_halfedge(hp, hn); set_next_halfedge(op, on); // face -> halfedge if (fh.is_valid()) set_halfedge(fh, hn); if (fo.is_valid()) set_halfedge(fo, on); // vertex -> halfedge if (halfedge(vh) == o) set_halfedge(vh, hn); adjust_outgoing_halfedge(vh); set_halfedge(vo, Halfedge()); // delete stuff if (!vdeleted_) vdeleted_ = vertex_property<bool>("v:deleted", false); if (!edeleted_) edeleted_ = edge_property<bool>("e:deleted", false); vdeleted_[vo] = true; ++deleted_vertices_; edeleted_[edge(h)] = true; ++deleted_edges_; garbage_ = true; //add for(unsigned int j = 0;j < map_2skel.size();j++) { if(map_2skel[j] == vo.idx()) { //unsigned int tem = map_2skel[j]; map_2skel[j] = vh.idx(); //qDebug("vertex:[%d],change %d to %d",j,tem,vh.idx()); } } //end }
int main(int, char const**) { // Create the main window sf::RenderWindow window(sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), "Minesweeper"); // Set the Icon sf::Image icon; if (!icon.loadFromFile(resourcePath() + "icon.png")) { return EXIT_FAILURE; } window.setIcon(icon.getSize().x, icon.getSize().y, icon.getPixelsPtr()); GameBoard gameBoard(COLUMNS, ROWS, MINES); CellTextures cellTextures; FaceTextures faceTextures; sf::RectangleShape backFill; backFill.setSize(sf::Vector2f(WINDOW_WIDTH, WINDOW_HEIGHT)); backFill.setFillColor(sf::Color(164, 164, 164)); sf::RectangleShape gridBorder; gridBorder.setPosition(sf::Vector2f(BOARD_X_OFFSET, BOARD_Y_OFFSET)); gridBorder.setSize(sf::Vector2f(COLUMNS * CELL_WIDTH + 1, ROWS * CELL_HEIGHT + 1)); gridBorder.setFillColor(sf::Color(86, 86, 86)); int score = 0; sf::Font scoreFont; scoreFont.loadFromFile(resourcePath() + "sansation.ttf"); sf::Text scoreCounter; scoreCounter.setPosition(BORDER, 0); scoreCounter.setColor(sf::Color::Black); scoreCounter.setFont(scoreFont); // Start the game loop while (window.isOpen()) { // Process events sf::Event event; while (window.pollEvent(event)) { if (event.type == sf::Event::MouseButtonPressed) { int mouseX = event.mouseButton.x; int mouseY = event.mouseButton.y; int gridX = (mouseX - BOARD_X_OFFSET) / CELL_WIDTH; int gridY = (mouseY - BOARD_Y_OFFSET) / CELL_HEIGHT; if (gameBoard.validCoordinate(gridX, gridY)) { if (event.mouseButton.button == sf::Mouse::Button::Left) { score += gameBoard.onClick(gridX, gridY); } if (event.mouseButton.button == sf::Mouse::Button::Right) { gameBoard.onRightClick(gridX, gridY); } } else { if (mouseX >= FACE_X && mouseX <= FACE_X + FACE_WIDTH && mouseY >= FACE_Y && mouseY <= FACE_Y + FACE_HEIGHT && event.mouseButton.button == sf::Mouse::Button::Left) { /** RESTART GAME! */ score = 0; gameBoard = GameBoard(COLUMNS, ROWS, MINES); } } } // Close window : exit if (event.type == sf::Event::Closed) { window.close(); } // Escape pressed : exit if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) { window.close(); } } // Clear screen window.clear(); window.draw(backFill); window.draw(gridBorder); scoreCounter.setString(std::to_string(score)); window.draw(scoreCounter); // Draw the grid for (int y = 0; y < gameBoard.getRows(); y++) { for (int x = 0; x < gameBoard.getColumns(); x++) { Cell cell = gameBoard.getCell(x, y); sf::Sprite sprite(*cellTextures.getCellTexture(cell, gameBoard.getNeighbouringMines(x, y))); sprite.setPosition(BOARD_X_OFFSET + x * CELL_WIDTH, BOARD_Y_OFFSET + y * CELL_HEIGHT); window.draw(sprite); } } // Draw the face sf::Sprite face(*(gameBoard.getIsGameOver() ? faceTextures.getLose() : gameBoard.getIsGameWon() ? faceTextures.getWin() : faceTextures.getPlaying())); face.setPosition(FACE_X, FACE_Y); window.draw(face); // Update the window window.display(); } return EXIT_SUCCESS; }
void Surface_mesh:: garbage_collection() { if (!garbage_) return; int i, i0, i1, nV(vertices_size()), nE(edges_size()), nH(halfedges_size()), nF(faces_size()); Vertex v; Halfedge h; Face f; if (!vdeleted_) vdeleted_ = vertex_property<bool>("v:deleted", false); if (!edeleted_) edeleted_ = edge_property<bool>("e:deleted", false); if (!fdeleted_) fdeleted_ = face_property<bool>("f:deleted", false); // setup handle mapping Vertex_property<Vertex> vmap = add_vertex_property<Vertex>("v:garbage-collection"); Halfedge_property<Halfedge> hmap = add_halfedge_property<Halfedge>("h:garbage-collection"); Face_property<Face> fmap = add_face_property<Face>("f:garbage-collection"); for (i=0; i<nV; ++i) vmap[Vertex(i)] = Vertex(i); for (i=0; i<nH; ++i) hmap[Halfedge(i)] = Halfedge(i); for (i=0; i<nF; ++i) fmap[Face(i)] = Face(i); // remove deleted vertices if (nV > 0) { i0=0; i1=nV-1; while (1) { // find first deleted and last un-deleted while (!vdeleted_[Vertex(i0)] && i0 < i1) ++i0; while ( vdeleted_[Vertex(i1)] && i0 < i1) --i1; if (i0 >= i1) break; // swap vprops_.swap(i0, i1); //add for(unsigned int j = 0;j<map_2skel.size();j++) { if(map_2skel[j] == i0) map_2skel[j] = i1; else if(map_2skel[j] == i1) map_2skel[j] = i0; } //end }; // remember new size nV = vdeleted_[Vertex(i0)] ? i0 : i0+1; } // remove deleted edges if (nE > 0) { i0=0; i1=nE-1; while (1) { // find first deleted and last un-deleted while (!edeleted_[Edge(i0)] && i0 < i1) ++i0; while ( edeleted_[Edge(i1)] && i0 < i1) --i1; if (i0 >= i1) break; // swap eprops_.swap(i0, i1); hprops_.swap(2*i0, 2*i1); hprops_.swap(2*i0+1, 2*i1+1); }; // remember new size nE = edeleted_[Edge(i0)] ? i0 : i0+1; nH = 2*nE; } // remove deleted faces if (nF > 0) { i0=0; i1=nF-1; while (1) { // find 1st deleted and last un-deleted while (!fdeleted_[Face(i0)] && i0 < i1) ++i0; while ( fdeleted_[Face(i1)] && i0 < i1) --i1; if (i0 >= i1) break; // swap fprops_.swap(i0, i1); }; // remember new size nF = fdeleted_[Face(i0)] ? i0 : i0+1; } // update vertex connectivity for (i=0; i<nV; ++i) { v = Vertex(i); if (!is_isolated(v)) set_halfedge(v, hmap[halfedge(v)]); } // update halfedge connectivity for (i=0; i<nH; ++i) { h = Halfedge(i); set_vertex(h, vmap[to_vertex(h)]); set_next_halfedge(h, hmap[next_halfedge(h)]); if (!is_boundary(h)) set_face(h, fmap[face(h)]); } // update handles of faces for (i=0; i<nF; ++i) { f = Face(i); set_halfedge(f, hmap[halfedge(f)]); } // remove handle maps remove_vertex_property(vmap); remove_halfedge_property(hmap); remove_face_property(fmap); // finally resize arrays vprops_.resize(nV); vprops_.free_memory(); hprops_.resize(nH); hprops_.free_memory(); eprops_.resize(nE); eprops_.free_memory(); fprops_.resize(nF); fprops_.free_memory(); deleted_vertices_ = deleted_edges_ = deleted_faces_ = 0; garbage_ = false; }
const KHalfEdgeMesh::Face *KHalfEdgeMesh::unsafeFace(size_t idx) const { return face(FaceIndex(static_cast<IndexType::index_type>(idx))); }
/** * logic() * Handle a single frame. This includes: * - move the avatar based on buttons pressed * - calculate the next frame of animation * - calculate camera position based on avatar position * * @param power_index The actionbar power activated. -1 means no power. */ void Avatar::logic(int actionbar_power, bool restrictPowerUse) { Point target; int stepfx; stats.logic(); if (stats.stun_duration > 0) return; bool allowed_to_move; bool allowed_to_use_power; // check level up int max_spendable_stat_points = 16; if (stats.xp >= stats.xp_table[stats.level] && stats.level < MAX_CHARACTER_LEVEL) { stats.level++; stringstream ss; ss << msg->get("Congratulations, you have reached level %d!", stats.level); if (stats.level < max_spendable_stat_points) { ss << " " << msg->get("You may increase one attribute through the Character Menu."); newLevelNotification = true; } log_msg = ss.str(); stats.recalc(); Mix_PlayChannel(-1, level_up, 0); } // check for bleeding spurt if (stats.bleed_duration % 30 == 1) { powers->activate(POWER_SPARK_BLOOD, &stats, stats.pos); } // check for bleeding to death if (stats.hp == 0 && !(stats.cur_state == AVATAR_DEAD)) { stats.cur_state = AVATAR_DEAD; } // assist mouse movement if (!inp->pressing[MAIN1]) drag_walking = false; // handle animation activeAnimation->advanceFrame(); switch(stats.cur_state) { case AVATAR_STANCE: setAnimation("stance"); // allowed to move or use powers? if (MOUSE_MOVE) { allowed_to_move = restrictPowerUse && (!inp->lock[MAIN1] || drag_walking); allowed_to_use_power = !allowed_to_move; } else { allowed_to_move = true; allowed_to_use_power = true; } // handle transitions to RUN if (allowed_to_move) set_direction(); if (pressing_move() && allowed_to_move) { if (MOUSE_MOVE && inp->pressing[MAIN1]) { inp->lock[MAIN1] = true; drag_walking = true; } if (move()) { // no collision stats.cur_state = AVATAR_RUN; } } // handle power usage if (allowed_to_use_power && actionbar_power != -1 && stats.cooldown_ticks == 0) { target = screen_to_map(inp->mouse.x, inp->mouse.y + powers->powers[actionbar_power].aim_assist, stats.pos.x, stats.pos.y); // check requirements if (powers->powers[actionbar_power].requires_mp > stats.mp) break; if (powers->powers[actionbar_power].requires_physical_weapon && !stats.wielding_physical) break; if (powers->powers[actionbar_power].requires_mental_weapon && !stats.wielding_mental) break; if (powers->powers[actionbar_power].requires_offense_weapon && !stats.wielding_offense) break; if (powers->powers[actionbar_power].requires_los && !map->collider.line_of_sight(stats.pos.x, stats.pos.y, target.x, target.y)) break; if (powers->powers[actionbar_power].requires_empty_target && !map->collider.is_empty(target.x, target.y)) break; if (stats.hero_cooldown[actionbar_power] > 0) break; stats.hero_cooldown[actionbar_power] = powers->powers[actionbar_power].cooldown; //set the cooldown timer current_power = actionbar_power; act_target.x = target.x; act_target.y = target.y; // is this a power that requires changing direction? if (powers->powers[current_power].face) { stats.direction = face(target.x, target.y); } // handle melee powers if (powers->powers[current_power].new_state == POWSTATE_SWING) { stats.cur_state = AVATAR_MELEE; break; } // handle ranged powers if (powers->powers[current_power].new_state == POWSTATE_SHOOT) { stats.cur_state = AVATAR_SHOOT; break; } // handle ment powers if (powers->powers[current_power].new_state == POWSTATE_CAST) { stats.cur_state = AVATAR_CAST; break; } if (powers->powers[current_power].new_state == POWSTATE_BLOCK) { stats.cur_state = AVATAR_BLOCK; stats.blocking = true; break; } } break; case AVATAR_RUN: setAnimation("run"); stepfx = rand() % 4; if (activeAnimation->getCurFrame() == 1 || activeAnimation->getCurFrame() == activeAnimation->getMaxFrame()/2) { Mix_PlayChannel(-1, sound_steps[stepfx], 0); } // allowed to move or use powers? if (MOUSE_MOVE) { allowed_to_use_power = !(restrictPowerUse && !inp->lock[MAIN1]); } else { allowed_to_use_power = true; } // handle direction changes set_direction(); // handle transition to STANCE if (!pressing_move()) { stats.cur_state = AVATAR_STANCE; break; } else if (!move()) { // collide with wall stats.cur_state = AVATAR_STANCE; break; } // handle power usage if (allowed_to_use_power && actionbar_power != -1 && stats.cooldown_ticks == 0) { target = screen_to_map(inp->mouse.x, inp->mouse.y + powers->powers[actionbar_power].aim_assist, stats.pos.x, stats.pos.y); // check requirements if (powers->powers[actionbar_power].requires_mp > stats.mp) break; if (powers->powers[actionbar_power].requires_physical_weapon && !stats.wielding_physical) break; if (powers->powers[actionbar_power].requires_mental_weapon && !stats.wielding_mental) break; if (powers->powers[actionbar_power].requires_offense_weapon && !stats.wielding_offense) break; if (powers->powers[actionbar_power].requires_los && !map->collider.line_of_sight(stats.pos.x, stats.pos.y, target.x, target.y)) break; if (powers->powers[actionbar_power].requires_empty_target && !map->collider.is_empty(target.x, target.y)) break; if (stats.hero_cooldown[actionbar_power] > 0) break; stats.hero_cooldown[actionbar_power] = powers->powers[actionbar_power].cooldown; //set the cooldown timer current_power = actionbar_power; act_target.x = target.x; act_target.y = target.y; // is this a power that requires changing direction? if (powers->powers[current_power].face) { stats.direction = face(target.x, target.y); } // handle melee powers if (powers->powers[current_power].new_state == POWSTATE_SWING) { stats.cur_state = AVATAR_MELEE; break; } // handle ranged powers if (powers->powers[current_power].new_state == POWSTATE_SHOOT) { stats.cur_state = AVATAR_SHOOT; break; } // handle ment powers if (powers->powers[current_power].new_state == POWSTATE_CAST) { stats.cur_state = AVATAR_CAST; break; } if (powers->powers[current_power].new_state == POWSTATE_BLOCK) { stats.cur_state = AVATAR_BLOCK; stats.blocking = true; break; } } break; case AVATAR_MELEE: setAnimation("melee"); if (activeAnimation->getCurFrame() == 1) { Mix_PlayChannel(-1, sound_melee, 0); } // do power if (activeAnimation->getCurFrame() == activeAnimation->getMaxFrame()/2) { powers->activate(current_power, &stats, act_target); } if (activeAnimation->getTimesPlayed() >= 1) { stats.cur_state = AVATAR_STANCE; if (stats.haste_duration == 0) stats.cooldown_ticks += stats.cooldown; } break; case AVATAR_CAST: setAnimation("ment"); // do power if (activeAnimation->getCurFrame() == activeAnimation->getMaxFrame()/2) { powers->activate(current_power, &stats, act_target); } if (activeAnimation->getTimesPlayed() >= 1) { stats.cur_state = AVATAR_STANCE; if (stats.haste_duration == 0) stats.cooldown_ticks += stats.cooldown; } break; case AVATAR_SHOOT: setAnimation("ranged"); // do power if (activeAnimation->getCurFrame() == activeAnimation->getMaxFrame()/2) { powers->activate(current_power, &stats, act_target); } if (activeAnimation->getTimesPlayed() >= 1) { stats.cur_state = AVATAR_STANCE; if (stats.haste_duration == 0) stats.cooldown_ticks += stats.cooldown; } break; case AVATAR_BLOCK: setAnimation("block"); if (powers->powers[actionbar_power].new_state != POWSTATE_BLOCK) { stats.cur_state = AVATAR_STANCE; stats.blocking = false; } break; case AVATAR_HIT: setAnimation("hit"); if (activeAnimation->getTimesPlayed() >= 1) { stats.cur_state = AVATAR_STANCE; } break; case AVATAR_DEAD: setAnimation("die"); if (activeAnimation->getCurFrame() == 1 && activeAnimation->getTimesPlayed() < 1) { Mix_PlayChannel(-1, sound_die, 0); log_msg = msg->get("You are defeated. You lose half your gold. Press Enter to continue."); } if (activeAnimation->getTimesPlayed() >= 1) { stats.corpse = true; } // allow respawn with Accept if (inp->pressing[ACCEPT]) { stats.hp = stats.maxhp; stats.mp = stats.maxmp; stats.alive = true; stats.corpse = false; stats.cur_state = AVATAR_STANCE; // remove temporary effects stats.clearEffects(); // set teleportation variables. GameEngine acts on these. map->teleportation = true; map->teleport_mapname = map->respawn_map; map->teleport_destination.x = map->respawn_point.x; map->teleport_destination.y = map->respawn_point.y; } break; default: break; } // calc new cam position from player position // cam is focused at player position map->cam.x = stats.pos.x; map->cam.y = stats.pos.y; map->hero_tile.x = stats.pos.x / 32; map->hero_tile.y = stats.pos.y / 32; // check for map events map->checkEvents(stats.pos); // decrement all cooldowns for (int i = 0; i < POWER_COUNT; i++){ stats.hero_cooldown[i] -= 1000 / FRAMES_PER_SEC; if (stats.hero_cooldown[i] < 0) stats.hero_cooldown[i] = 0; } }
int Face3Space::refine(hObj& f,const int) { /// full break /// 0-3 - subfaces_, 4-6 - subedges_ /// /* /// |\. /// |2 \. /// | \. /// ---6--\. /// |\ 3| \. /// | 4 5 \. /// |0___\_|____1\. */ Face3D & face( *static_cast<Face3D*>(&f) ); face.updatePointers(); assert(face.type_ == Face3D::myType); if(!face.isBroken()) { hHybridMesh & m(*face.myMesh); face.mySize_= sizeof(Face3D); face.nMyClassSons_=4; assert(m.edges_.getById(face.components(0)).isBroken()); assert(m.edges_.getById(face.components(1)).isBroken()); assert(m.edges_.getById(face.components(2)).isBroken()); const Vertex* v[6]={ &m.vertices_[face.verts(0)], &m.vertices_[face.verts(1)], &m.vertices_[face.verts(2)], &m.vertices_.getById(m.edge(face.verts(0),face.verts(1)).sons(0)), &m.vertices_.getById(m.edge(face.verts(0),face.verts(2)).sons(0)), &m.vertices_.getById(m.edge(face.verts(1),face.verts(2)).sons(0)) }; // new edges_ // indexes of verts in v[6] for new edges static const int edgesVerts[3][2]={{3,4},{3,5},{4,5}}; for(uTind i(0); i < 3; ++i) { const uTind vertices[2] ={ v[ edgesVerts[i][0] ]->pos_, v[ edgesVerts[i][1] ]->pos_}; Edge & child = *m.edges_.newObj<Edge>(vertices); child.parent_= face.id_; child.level_= face.level_+1; face.sons(i)=child.id_; // child.status(INACTIVE); child.components(0)=v[ edgesVerts[i][0] ]->id_; child.components(1)=v[ edgesVerts[i][1] ]->id_; } // new faces3 // define vertices building childrens const uTind verts[4][4]= { {v[0]->pos_,v[3]->pos_,v[4]->pos_,UNKNOWN}, {v[3]->pos_,v[1]->pos_,v[5]->pos_,UNKNOWN}, {v[4]->pos_,v[5]->pos_,v[2]->pos_,UNKNOWN}, {// this one is flipped v[3]->pos_,v[5]->pos_,v[4]->pos_,UNKNOWN} }; #ifdef _DEBUG double parentNormVec[3]={0.0}, childNormVec[3]={0.0}; m.faceNormal(face,parentNormVec,NULL); #endif BYTE * adr( reinterpret_cast<BYTE*>(&face)+ face.mySize_); for(uTind i(0); i < 4; ++i) { Face3 & faceChild = *m.faces_.newObj<Face3>(verts[i],adr); faceChild.parent_= face.id_; faceChild.level_= face.level_+ 1; // faceChild.status(INACTIVE); adr += faceChild.mySize_; // code below is no more needed, as this is coverd in Face3 constructor //faceChild.components(0)=verts_n_comps[i][3 ]; //faceChild.components(1)=verts_n_comps[i][3+1]; //faceChild.components(2)=verts_n_comps[i][3+2]; faceChild.neighs(0) = 0; faceChild.neighs(1) = 0; faceChild.flags(B_COND) = face.flags(B_COND); //faceChild.neighs(0) = face.neighs(0); //faceChild.neighs(1) = face.neighs(1); #ifdef _DEBUG m.faceNormal(faceChild, childNormVec,NULL); assert(abs(parentNormVec[0]-childNormVec[0]) <= SMALL); assert(abs(parentNormVec[1]-childNormVec[1]) <= SMALL); assert(abs(parentNormVec[2]-childNormVec[2]) <= SMALL); #endif if(i==3) { // fourth is flipped faceChild.flags(F_TYPE)=F_FLIPPED; } } #ifdef _DEBUG out_stream <<"\n refine Face3("<<face.pos_<<") " <<face.verts(0)<<" " <<face.verts(1)<<" " <<face.verts(2); for(int i(0); i < 3; ++i) { Face3 & faceChild = *face.getMyClassChild<Face3>(i); out_stream <<"\n child Face3("<<faceChild.pos_<<") : " <<faceChild.verts(0)<<" " <<faceChild.verts(1)<<" " <<faceChild.verts(2); } #endif ++(m.faces_.dividedObjs_); } return ( sizeof(Face3D) - sizeof(Face3) ) + 4*sizeof(Face3); }
/** * logic() * Handle a single frame. This includes: * - move the enemy based on AI % chances * - calculate the next frame of animation */ void Enemy::logic() { stats.logic(); if (stats.stun_duration > 0) return; // check for bleeding to death if (stats.hp <= 0 && !(stats.cur_state == ENEMY_DEAD || stats.cur_state == ENEMY_CRITDEAD)) { doRewards(); stats.cur_state = ENEMY_DEAD; } // check for bleeding spurt if (stats.bleed_duration % 30 == 1) { powers->activate(POWER_SPARK_BLOOD, &stats, stats.pos); } // check for teleport powers if (stats.teleportation) { stats.pos.x = stats.teleport_destination.x; stats.pos.y = stats.teleport_destination.y; stats.teleportation = false; } int dist; int prev_direction; bool los = false; Point pursue_pos; //int max_frame; //int mid_frame; // SECTION 1: Steering and Vision // ------------------------------ // check distance and line of sight between enemy and hero if (stats.hero_alive) dist = getDistance(stats.hero_pos); else dist = 0; // if the hero is too far away or dead, abandon combat and do nothing if (dist > stats.threat_range+stats.threat_range || !stats.hero_alive) { stats.in_combat = false; stats.patrol_ticks = 0; stats.last_seen.x = -1; stats.last_seen.y = -1; } if (dist < stats.threat_range && stats.hero_alive) los = map->collider.line_of_sight(stats.pos.x, stats.pos.y, stats.hero_pos.x, stats.hero_pos.y); else los = false; // if the enemy can see the hero, it pursues. // otherwise, it will head towards where it last saw the hero if (los && dist < stats.threat_range) { stats.in_combat = true; stats.last_seen.x = stats.hero_pos.x; stats.last_seen.y = stats.hero_pos.y; } else if (stats.last_seen.x >= 0 && stats.last_seen.y >= 0) { if (getDistance(stats.last_seen) <= (stats.speed+stats.speed) && stats.patrol_ticks == 0) { stats.last_seen.x = -1; stats.last_seen.y = -1; stats.patrol_ticks = 8; // start patrol; see note on "patrolling" below } } // where is the creature heading? // TODO: add fleeing for X ticks if (los) { pursue_pos.x = stats.last_seen.x = stats.hero_pos.x; pursue_pos.y = stats.last_seen.y = stats.hero_pos.y; stats.patrol_ticks = 0; } else if (stats.in_combat) { // "patrolling" is a simple way to help steering. // When the enemy arrives at where he last saw the hero, it continues // walking a few steps. This gives a better chance of re-establishing // line of sight around corners. if (stats.patrol_ticks > 0) { stats.patrol_ticks--; if (stats.patrol_ticks == 0) { stats.in_combat = false; } } pursue_pos.x = stats.last_seen.x; pursue_pos.y = stats.last_seen.y; } // SECTION 2: States // ----------------- activeAnimation->advanceFrame(); switch(stats.cur_state) { case ENEMY_STANCE: setAnimation("stance"); if (stats.in_combat) { // update direction to face the target if (++stats.dir_ticks > stats.dir_favor && stats.patrol_ticks == 0) { stats.direction = face(pursue_pos.x, pursue_pos.y); stats.dir_ticks = 0; } // performed ranged actions if (dist > stats.melee_range && stats.cooldown_ticks == 0) { // CHECK: ranged physical! //if (!powers->powers[stats.power_index[RANGED_PHYS]].requires_los || los) { if (los) { if ((rand() % 100) < stats.power_chance[RANGED_PHYS] && stats.power_ticks[RANGED_PHYS] == 0) { newState(ENEMY_RANGED_PHYS); break; } } // CHECK: ranged spell! //if (!powers->powers[stats.power_index[RANGED_MENT]].requires_los || los) { if (los) { if ((rand() % 100) < stats.power_index[RANGED_MENT] && stats.power_ticks[RANGED_MENT] == 0) { newState(ENEMY_RANGED_MENT); break; } } // CHECK: flee! // CHECK: pursue! if ((rand() % 100) < stats.chance_pursue) { if (move()) { // no collision newState(ENEMY_MOVE); } else { // hit an obstacle, try the next best angle prev_direction = stats.direction; stats.direction = faceNextBest(pursue_pos.x, pursue_pos.y); if (move()) { newState(ENEMY_MOVE); break; } else stats.direction = prev_direction; } } } // perform melee actions else if (dist <= stats.melee_range && stats.cooldown_ticks == 0) { // CHECK: melee attack! //if (!powers->powers[stats.power_index[MELEE_PHYS]].requires_los || los) { if (los) { if ((rand() % 100) < stats.power_chance[MELEE_PHYS] && stats.power_ticks[MELEE_PHYS] == 0) { newState(ENEMY_MELEE_PHYS); break; } } // CHECK: melee ment! //if (!powers->powers[stats.power_index[MELEE_MENT]].requires_los || los) { if (los) { if ((rand() % 100) < stats.power_chance[MELEE_MENT] && stats.power_ticks[MELEE_MENT] == 0) { newState(ENEMY_MELEE_MENT); break; } } } } break; case ENEMY_MOVE: setAnimation("run"); if (stats.in_combat) { if (++stats.dir_ticks > stats.dir_favor && stats.patrol_ticks == 0) { stats.direction = face(pursue_pos.x, pursue_pos.y); stats.dir_ticks = 0; } if (dist > stats.melee_range && stats.cooldown_ticks == 0) { // check ranged physical! //if (!powers->powers[stats.power_index[RANGED_PHYS]].requires_los || los) { if (los) { if ((rand() % 100) < stats.power_chance[RANGED_PHYS] && stats.power_ticks[RANGED_PHYS] == 0) { newState(ENEMY_RANGED_PHYS); break; } } // check ranged spell! // if (!powers->powers[stats.power_index[RANGED_MENT]].requires_los || los) { if (los) { if ((rand() % 100) < stats.power_chance[RANGED_MENT] && stats.power_ticks[RANGED_MENT] == 0) { newState(ENEMY_RANGED_MENT); break; } } if (!move()) { // hit an obstacle. Try the next best angle prev_direction = stats.direction; stats.direction = faceNextBest(pursue_pos.x, pursue_pos.y); if (!move()) { newState(ENEMY_STANCE); stats.direction = prev_direction; } } } else { newState(ENEMY_STANCE); } } else { newState(ENEMY_STANCE); } break; case ENEMY_MELEE_PHYS: setAnimation("melee"); if (activeAnimation->getCurFrame() == 1) { sfx_phys = true; } // the attack hazard is alive for a single frame if (activeAnimation->getCurFrame() == activeAnimation->getMaxFrame()/2 && haz == NULL) { powers->activate(stats.power_index[MELEE_PHYS], &stats, pursue_pos); stats.power_ticks[MELEE_PHYS] = stats.power_cooldown[MELEE_PHYS]; } if (activeAnimation->getCurFrame() == activeAnimation->getMaxFrame()-1) { newState(ENEMY_STANCE); stats.cooldown_ticks = stats.cooldown; } break; case ENEMY_RANGED_PHYS: setAnimation("ranged"); // monsters turn to keep aim at the hero stats.direction = face(pursue_pos.x, pursue_pos.y); if (activeAnimation->getCurFrame() == 1) { sfx_phys = true; } // the attack hazard is alive for a single frame if (activeAnimation->getCurFrame() == activeAnimation->getMaxFrame()/2 && haz == NULL) { powers->activate(stats.power_index[RANGED_PHYS], &stats, pursue_pos); stats.power_ticks[RANGED_PHYS] = stats.power_cooldown[RANGED_PHYS]; } if (activeAnimation->getCurFrame() == activeAnimation->getMaxFrame()-1) { newState(ENEMY_STANCE); stats.cooldown_ticks = stats.cooldown; } break; case ENEMY_MELEE_MENT: setAnimation("ment"); if (activeAnimation->getCurFrame() == 1) { sfx_ment = true; } // the attack hazard is alive for a single frame if (activeAnimation->getCurFrame() == activeAnimation->getMaxFrame()/2 && haz == NULL) { powers->activate(stats.power_index[MELEE_MENT], &stats, pursue_pos); stats.power_ticks[MELEE_MENT] = stats.power_cooldown[MELEE_MENT]; } if (activeAnimation->getCurFrame() == activeAnimation->getMaxFrame()-1) { newState(ENEMY_STANCE); stats.cooldown_ticks = stats.cooldown; } break; case ENEMY_RANGED_MENT: setAnimation("ment"); // monsters turn to keep aim at the hero stats.direction = face(pursue_pos.x, pursue_pos.y); if (activeAnimation->getCurFrame() == 1) { sfx_ment = true; } // the attack hazard is alive for a single frame if (activeAnimation->getCurFrame() == activeAnimation->getMaxFrame()/2 && haz == NULL) { powers->activate(stats.power_index[RANGED_MENT], &stats, pursue_pos); stats.power_ticks[RANGED_MENT] = stats.power_cooldown[RANGED_MENT]; } if (activeAnimation->getCurFrame() == activeAnimation->getMaxFrame()-1) { newState(ENEMY_STANCE); stats.cooldown_ticks = stats.cooldown; } break; case ENEMY_HIT: // enemy has taken damage (but isn't dead) setAnimation("hit"); if (activeAnimation->getCurFrame() == 1) { sfx_hit = true; } if (activeAnimation->getCurFrame() == activeAnimation->getMaxFrame()-1) { newState(ENEMY_STANCE); } break; case ENEMY_DEAD: // corpse means the creature is dead and done animating if (!stats.corpse) { setAnimation("die"); if (activeAnimation->getCurFrame() == 1) { sfx_die = true; } } break; case ENEMY_CRITDEAD: // critdead is an optional, more gruesome death animation // corpse means the creature is dead and done animating if (!stats.corpse) { setAnimation("critdie"); if (activeAnimation->getCurFrame() == 1) { sfx_critdie = true; } } break; } }
// static bool OBJLoader::parseFace( int lineNumber, const std::string& line, const std::vector< std::string >& tokens, OBJGroup& currentGroup ) { // TODO: support negative indices. if( tokens.size() < 4 ) { fprintf( stderr, "Incorrect number of tokens at line number: %d\n, %s\n", lineNumber, line.c_str() ); return false; } // first check line consistency - each vertex in the face // should have the same number of attributes bool faceIsValid; bool faceHasTextureCoordinates; bool faceHasNormals; faceIsValid = OBJLoader::faceHasConsistentAttributes( tokens, &faceHasTextureCoordinates, &faceHasNormals ); if( !faceIsValid ) { fprintf( stderr, "Face attributes inconsistent at line number: %d\n%s\n", lineNumber, line.c_str() ); return false; } // ensure that all faces in a group are consistent: // they either all have texture coordinates or they don't // they either all have normals or they don't // // check how many faces the current group has // if the group has no faces, then the first face sets the group attributes if( currentGroup.numFaces() == 0 ) { currentGroup.setHasTextureCoordinates( faceHasTextureCoordinates ); currentGroup.setHasNormals( faceHasNormals ); } bool faceIsConsistentWithGroup = ( currentGroup.hasTextureCoordinates() == faceHasTextureCoordinates ) && ( currentGroup.hasNormals() == faceHasNormals ); if( !faceIsConsistentWithGroup ) { // TODO: boolToString() fprintf( stderr, "Face attributes inconsistent with group: %s at line: %d\n%s\n", currentGroup.name().c_str(), lineNumber, line.c_str() ); fprintf( stderr, "group.hasTextureCoordinates() = %d\n", currentGroup.hasTextureCoordinates() ); fprintf( stderr, "face.hasTextureCoordinates() = %d\n", faceHasTextureCoordinates ); fprintf( stderr, "group.hasNormals() = %d\n", currentGroup.hasNormals() ); fprintf( stderr, "face.hasNormals() = %d\n", faceHasNormals ); return false; } OBJFace face( faceHasTextureCoordinates, faceHasNormals ); // Process each vertex. for( int i = 1; i < tokens.size(); ++i ) { int vertexPositionIndex; int vertexTextureCoordinateIndex; int vertexNormalIndex; OBJLoader::getVertexAttributes( tokens[ i ], &vertexPositionIndex, &vertexTextureCoordinateIndex, &vertexNormalIndex ); face.positionIndices().push_back( vertexPositionIndex - 1 ); if( faceHasTextureCoordinates ) { face.textureCoordinateIndices().push_back( vertexTextureCoordinateIndex - 1 ); } if( faceHasNormals ) { face.normalIndices().push_back( vertexNormalIndex - 1 ); } } currentGroup.addFace( face ); return true; }
MagicCube::MagicCube():layer(0),Rotation3D(ORIGIN),history(this->getMagicCubeID()) { for (int i = 0; i < COUNTOFFACE; i++) { CubeFace face(static_cast<NAMEOFCOLOR>(i)); this->cubeFace[i] = face; } }
AutoPtr<Elem> InfHex16::build_side (const unsigned int i, bool proxy) const { libmesh_assert_less (i, this->n_sides()); if (proxy) { switch (i) { // base case 0: { AutoPtr<Elem> ap(new Side<Quad8,InfHex16>(this,i)); return ap; } // ifem sides case 1: case 2: case 3: case 4: { AutoPtr<Elem> ap(new Side<InfQuad6,InfHex16>(this,i)); return ap; } default: libmesh_error(); } } else { // Create NULL pointer to be initialized, returned later. AutoPtr<Elem> face(NULL); // Think of a unit cube: (-1,1) x (-1,1) x (1,1) switch (i) { case 0: // the base face { face.reset(new Quad8); // Only here, the face element's normal points inward face->set_node(0) = this->get_node(0); face->set_node(1) = this->get_node(1); face->set_node(2) = this->get_node(2); face->set_node(3) = this->get_node(3); face->set_node(4) = this->get_node(8); face->set_node(5) = this->get_node(9); face->set_node(6) = this->get_node(10); face->set_node(7) = this->get_node(11); break; } case 1: // connecting to another infinite element { face.reset(new InfQuad6); face->set_node(0) = this->get_node(0); face->set_node(1) = this->get_node(1); face->set_node(2) = this->get_node(4); face->set_node(3) = this->get_node(5); face->set_node(4) = this->get_node(8); face->set_node(5) = this->get_node(12); break; } case 2: // connecting to another infinite element { face.reset(new InfQuad6); face->set_node(0) = this->get_node(1); face->set_node(1) = this->get_node(2); face->set_node(2) = this->get_node(5); face->set_node(3) = this->get_node(6); face->set_node(4) = this->get_node(9); face->set_node(5) = this->get_node(13); break; } case 3: // connecting to another infinite element { face.reset(new InfQuad6); face->set_node(0) = this->get_node(2); face->set_node(1) = this->get_node(3); face->set_node(2) = this->get_node(6); face->set_node(3) = this->get_node(7); face->set_node(4) = this->get_node(10); face->set_node(5) = this->get_node(14); break; } case 4: // connecting to another infinite element { face.reset(new InfQuad6); face->set_node(0) = this->get_node(3); face->set_node(1) = this->get_node(0); face->set_node(2) = this->get_node(7); face->set_node(3) = this->get_node(4); face->set_node(4) = this->get_node(11); face->set_node(5) = this->get_node(15); break; } default: { libmesh_error(); } } face->subdomain_id() = this->subdomain_id(); return face; } // We'll never get here. libmesh_error(); AutoPtr<Elem> ap(NULL); return ap; }
// Calculate area in contact given displacement of vertices relative to // the face plane. Positive displacement is above the face (no contact); // negative is in contact Foam::scalar Foam::face::areaInContact ( const pointField& meshPoints, const scalarField& v ) const { // Assemble the vertex values const labelList& labels = *this; scalarField vertexValue(labels.size()); forAll (labels, i) { vertexValue[i] = v[labels[i]]; } // Loop through vertexValue. If all greater that 0 return 0 (no contact); // if all less than zero return 1 // all zeros is assumed to be in contact. bool allPositive = true; bool allNegative = true; forAll (vertexValue, vI) { if (vertexValue[vI] > 0) { allNegative = false; } else { allPositive = false; } } if (allPositive) { return 0.0; } if (allNegative) { return 1.0; } // There is a partial contact. // Algorithm: // Go through all edges. if both vertex values for the edge are // positive, discard. If one is positive and one is negative, // create a point and start the edge with it. If both are // negative, add the edge into the new face. When finished, // calculate area of new face and return relative area (0<x<1) // Dimension new point list to max possible size const labelList& faceLabels = *this; pointField newFacePoints(2*size()); label nNewFacePoints = 0; for (label vI = 0; vI < size() - 1; vI++) { if (vertexValue[vI] <= 0) { // This is a point in contact newFacePoints[nNewFacePoints] = meshPoints[faceLabels[vI]]; nNewFacePoints++; } if ( (vertexValue[vI] > 0 && vertexValue[vI + 1] < 0) || (vertexValue[vI] < 0 && vertexValue[vI + 1] > 0) ) { // Edge intersection. Calculate intersection point and add to list point intersection = meshPoints[faceLabels[vI]] + vertexValue[vI]/(vertexValue[vI + 1] - vertexValue[vI]) *(meshPoints[faceLabels[vI]] - meshPoints[faceLabels[vI + 1]]); newFacePoints[nNewFacePoints] = intersection; nNewFacePoints++; } } // Do last point by hand if (vertexValue[size() - 1] <= 0) { // This is a point in contact newFacePoints[nNewFacePoints] = meshPoints[faceLabels[size() - 1]]; nNewFacePoints++; } if ( (vertexValue[size() - 1] > 0 && vertexValue[0] < 0) || (vertexValue[size() - 1] < 0 && vertexValue[0] > 0) ) { // Edge intersection. Calculate intersection point and add to list point intersection = meshPoints[faceLabels[size() - 1]] + vertexValue[size() - 1]/(vertexValue[0] - vertexValue[size() - 1]) *(meshPoints[faceLabels[size() - 1]] - meshPoints[faceLabels[0]]); newFacePoints[nNewFacePoints] = intersection; nNewFacePoints++; } newFacePoints.setSize(nNewFacePoints); // Make a labelList for the sub-face (points are ordered!) labelList sfl(newFacePoints.size()); forAll (sfl, sflI) { sfl[sflI] = sflI; } // Calculate relative area return face(sfl).mag(newFacePoints)/(mag(meshPoints) + VSMALL); }
void StrandBlockSolver::rhsViscousFine() { int c1,c2,n1,n2,fc,jm,jp,npts=1; double dx1,dy1,dx2,dy2,ds,dq1,dq2,eps=1.e-14, qxe[nq],qye[nq],qaxe[nqa],qaye[nqa],qe[nq],qae[nqa],fv[nq]; // unstructured faces for (int n=0; n<nEdges; n++){ c1 = edge(0,n); c2 = edge(1,n); n1 = edgn(n); fc = fClip(c1); if (fClip(c2) > fc) fc = fClip(c2); for (int j=1; j<fc+1; j++){ jm = j-1; dx1 = x (0,j,n1)-x (0,jm,n1); dy1 = x (1,j,n1)-x (1,jm,n1); dx2 = xc(0,j,c2)-xc(0,j ,c1); dy2 = xc(1,j,c2)-xc(1,j ,c1); ds = 1./(dx1*dy2-dx2*dy1); for (int k=0; k<nq; k++){ dq1 = qp(k,j,n1)-qp(k,jm,n1); dq2 = q (k,j,c2)-q (k,j ,c1); qxe[k] = ds*( dy2*dq1-dy1*dq2); qye[k] = ds*(-dx2*dq1+dx1*dq2); qe[k] = .5*(qp (k,j,n1)+qp (k,jm,n1)); } for (int k=0; k<nqa; k++){ dq1 = qap(k,j,n1)-qap(k,jm,n1); dq2 = qa (k,j,c2)-qa (k,j ,c1); qaxe[k] = ds*( dy2*dq1-dy1*dq2); qaye[k] = ds*(-dx2*dq1+dx1*dq2); qae[k] = .5*(qap(k,j,n1)+qap(k,jm,n1)); } sys->rhsVisFlux(npts,&facs(0,j,n),&qe[0],&qae[0],&qxe[0],&qye[0], &qaxe[0],&qaye[0],&fv[0]); for (int k=0; k<nq; k++){ r(k,j,c1) -= fv[k]; r(k,j,c2) += fv[k]; }}} // structured faces for (int n=0; n<nFaces-nGfaces; n++){ n1 = face(0,n); n2 = face(1,n); for (int j=0; j<fClip(n)+1; j++){ jp = j+1; dx1 = x (0,j ,n2)-x (0,j,n1); dy1 = x (1,j ,n2)-x (1,j,n1); dx2 = xc(0,jp,n )-xc(0,j,n ); dy2 = xc(1,jp,n )-xc(1,j,n ); ds = dx1*dy2-dx2*dy1; if (fabs(ds) < eps) for (int k=0; k<nq; k++) fv[k] = 0.; else{ ds = 1./ds; for (int k=0; k<nq; k++){ dq1 = qp(k,j ,n2)-qp(k,j,n1); dq2 = q (k,jp,n )-q (k,j,n ); qxe[k] = ds*( dy2*dq1-dy1*dq2); qye[k] = ds*(-dx2*dq1+dx1*dq2); qe[k] = .5*(qp (k,j,n1)+qp (k,j,n2)); } for (int k=0; k<nqa; k++){ dq1 = qap(k,j ,n2)-qap(k,j,n1); dq2 = qa (k,jp,n )-qa (k,j,n ); qaxe[k] = ds*( dy2*dq1-dy1*dq2); qaye[k] = ds*(-dx2*dq1+dx1*dq2); qae[k] = .5*(qap(k,j,n1)+qap(k,j,n2)); } sys->rhsVisFlux(npts,&facu(0,j,n),&qe[0],&qae[0],&qxe[0],&qye[0], &qaxe[0],&qaye[0],&fv[0]); } for (int k=0; k<nq; k++){ r(k,j ,n) -= fv[k]; r(k,jp,n) += fv[k]; }}} }
const Vector& normal_of_vertex_of_face(size_t v, size_t f) const { return normal(face(f)(v)); }
// This routine assumes the sentinel points have already been added, and processes points in order GEODE_NEVER_INLINE static Ref<MutableTriangleTopology> deterministic_exact_delaunay(RawField<const Perturbed2,VertexId> X, const bool validate) { const int n = X.size()-3; const auto mesh = new_<MutableTriangleTopology>(); IntervalScope scope; // Initialize the mesh to a Delaunay triangle containing the sentinels at infinity. mesh->add_vertices(n+3); mesh->add_face(vec(VertexId(n+0),VertexId(n+1),VertexId(n+2))); if (self_check) { mesh->assert_consistent(); assert_delaunay("self check 0: ",mesh,X); } // The randomized incremental construction algorithm uses the history of the triangles // as the acceleration structure. Specifically, we maintain a BSP tree where the nodes // are edge tests (are we only the left or right of an edge) and the leaves are triangles. // There are two operations that modify this tree: // // 1. Split: A face is split into three by the insertion of an interior vertex. // 2. Flip: An edge is flipped, turning two triangles into two different triangles. // // The three starts out empty, since one triangle needs zero tests. Array<Node> bsp; // All BSP nodes including leaves bsp.preallocate(3*n); // The minimum number of possible BSP nodes Field<Vector<int,2>,FaceId> face_to_bsp; // Map from FaceId to up to two BSP leaf points (2*node+(right?0:1)) face_to_bsp.flat.preallocate(2*n+1); // The exact maximum number of faces face_to_bsp.flat.append_assuming_enough_space(vec(0,-1)); // By the time we call set_links, node 0 will be valid if (self_check) check_bsp(*mesh,bsp,face_to_bsp,X); // Allocate a stack to simulate recursion when flipping non-Delaunay edges. // Invariant: if edge is on the stack, the other edges of face(edge) are Delaunay. // Since halfedge ids change during edge flips in a corner mesh, we store half edges as directed vertex pairs. Array<Tuple<HalfedgeId,Vector<VertexId,2>>> stack; stack.preallocate(8); // Insert all vertices into the mesh in random order, maintaining the Delaunay property for (const auto i : range(n)) { const VertexId v(i); check_interrupts(); // Search through the BSP tree to find the containing triangle const auto f0 = bsp_search(bsp,X,v); const auto vs = mesh->vertices(f0); // Split the face by inserting the new vertex and update the BSP tree accordingly. mesh->split_face(f0,v); const auto e0 = mesh->halfedge(v), e1 = mesh->left(e0), e2 = mesh->right(e0); assert(mesh->dst(e0)==vs.x); const auto f1 = mesh->face(e1), f2 = mesh->face(e2); const int base = bsp.extend(3,uninit); set_links(bsp,face_to_bsp[f0],base); bsp[base+0] = Node(vec(v,vs.x),base+2,base+1); bsp[base+1] = Node(vec(v,vs.y),~f0.id,~f1.id); bsp[base+2] = Node(vec(v,vs.z),~f1.id,~f2.id); face_to_bsp[f0] = vec(2*(base+1)+0,-1); face_to_bsp.flat.append_assuming_enough_space(vec(2*(base+1)+1,2*(base+2)+0)); face_to_bsp.flat.append_assuming_enough_space(vec(2*(base+2)+1,-1)); if (self_check) { mesh->assert_consistent(); check_bsp(*mesh,bsp,face_to_bsp,X); } // Fix all non-Delaunay edges stack.copy(vec(tuple(mesh->next(e0),vec(vs.x,vs.y)), tuple(mesh->next(e1),vec(vs.y,vs.z)), tuple(mesh->next(e2),vec(vs.z,vs.x)))); if (self_check) assert_delaunay("self check 1: ",mesh,X,Tuple<>(),true); while (stack.size()) { const auto evs = stack.pop(); auto e = mesh->vertices(evs.x)==evs.y ? evs.x : mesh->halfedge(evs.y.x,evs.y.y); if (e.valid() && !is_delaunay(*mesh,X,e)) { // Our mesh is linearly embedded in the plane, so edge flips are always safe assert(mesh->is_flip_safe(e)); e = mesh->unsafe_flip_edge(e); GEODE_ASSERT(is_delaunay(*mesh,X,e)); // Update the BSP tree for the triangle flip const auto f0 = mesh->face(e), f1 = mesh->face(mesh->reverse(e)); const int node = bsp.append(Node(mesh->vertices(e),~f1.id,~f0.id)); set_links(bsp,face_to_bsp[f0],node); set_links(bsp,face_to_bsp[f1],node); face_to_bsp[f0] = vec(2*node+1,-1); face_to_bsp[f1] = vec(2*node+0,-1); if (self_check) { mesh->assert_consistent(); check_bsp(*mesh,bsp,face_to_bsp,X); } // Recurse to successor edges to e const auto e0 = mesh->next(e), e1 = mesh->prev(mesh->reverse(e)); stack.extend(vec(tuple(e0,mesh->vertices(e0)), tuple(e1,mesh->vertices(e1)))); if (self_check) assert_delaunay("self check 2: ",mesh,X,Tuple<>(),true); } } if (self_check) { mesh->assert_consistent(); assert_delaunay("self check 3: ",mesh,X); } } // Remove sentinels for (int i=0;i<3;i++) mesh->erase_last_vertex_with_reordering(); // If desired, check that the final mesh is Delaunay if (validate) assert_delaunay("delaunay validate: ",mesh,X); // Return the mesh with the sentinels removed return mesh; }
// static bool OBJLoader::parseFace( int lineNumber, QString line, QStringList tokens, OBJGroup* pCurrentGroup ) { // HACK /* if( tokens.size() < 4 ) { fprintf( stderr, "Incorrect number of tokens at line number: %d\n, %s\n", lineNumber, qPrintable( line ) ); return false; } else */ { // first check line consistency - each vertex in the face // should have the same number of attributes // HACK bool faceIsValid = true; bool faceHasTextureCoordinates = false; bool faceHasNormals = true; /* bool faceIsValid; bool faceHasTextureCoordinates; bool faceHasNormals; faceIsValid = OBJLoader::isFaceLineAttributesConsistent( tokens, &faceHasTextureCoordinates, &faceHasNormals ); if( !faceIsValid ) { fprintf( stderr, "Face attributes inconsistent at line number: %d\n%s\n", lineNumber, qPrintable( line ) ); return false; } */ // ensure that all faces in a group are consistent // they either all have texture coordinates or they don't // they either all have normals or they don't // // check how many faces the current group has // if the group has no faces, then the first vertex sets it if( pCurrentGroup->getFaces()->size() == 0 ) { pCurrentGroup->setHasTextureCoordinates( faceHasTextureCoordinates ); pCurrentGroup->setHasNormals( faceHasNormals ); } bool faceIsConsistentWithGroup = ( pCurrentGroup->hasTextureCoordinates() == faceHasTextureCoordinates ) && ( pCurrentGroup->hasNormals() == faceHasNormals ); if( !faceIsConsistentWithGroup ) { fprintf( stderr, "Face attributes inconsistent with group: %s at line: %d\n%s\n", qPrintable( pCurrentGroup->name() ), lineNumber, qPrintable( line ) ); fprintf( stderr, "group.hasTextureCoordinates() = %d\n", pCurrentGroup->hasTextureCoordinates() ); fprintf( stderr, "face.hasTextureCoordinates() = %d\n", faceHasTextureCoordinates ); fprintf( stderr, "group.hasNormals() = %d\n", pCurrentGroup->hasNormals() ); fprintf( stderr, "face.hasNormals() = %d\n", faceHasNormals ); return false; } OBJFace face( faceHasTextureCoordinates, faceHasNormals ); // for each vertex for( int i = 1; i < tokens.size(); ++i ) { int vertexPositionIndex; int vertexTextureCoordinateIndex; int vertexNormalIndex; OBJLoader::getVertexAttributes( tokens[ i ], &vertexPositionIndex, &vertexTextureCoordinateIndex, &vertexNormalIndex ); face.getPositionIndices()->append( vertexPositionIndex ); if( faceHasTextureCoordinates ) { face.getTextureCoordinateIndices()->append( vertexTextureCoordinateIndex ); } if( faceHasNormals ) { face.getNormalIndices()->append( vertexNormalIndex ); } } pCurrentGroup->addFace( face ); return true; } }
C3DModel CTriangulator<Real, Ellipsoid<Real> >::Triangulate(const Ellipsoid<Real> &pShape) { //-Pi/2 to Pi/2 Real phi; //0 to 2Pi Real theta; //points on the sphere //x=x0+r*cos(theta)*cos(phi) //y=y0+r*cos(theta)*sin(phi) //z=z0+r*sin(theta) C3DModel model; std::vector<Vector3<Real> > vVertices; std::vector<TriFace> vFaces; int lat =8; int longi=8; Real dphi = CMath<Real>::SYS_PI/(Real)longi; Real dtheta = CMath<Real>::SYS_PI/(Real)lat; Real halfpi = CMath<Real>::SYS_PI/2.0; Vector3<Real> vTop=pShape.eval(halfpi,0); Vector3<Real> vBottom=pShape.eval(-halfpi,0); vVertices.push_back(vTop); phi = halfpi-dphi; for(int j=1;j<longi;j++) { theta=0.0f; for(int i=0;i<2*lat;i++) { Vector3<Real> vNext=pShape.eval(phi,theta); vVertices.push_back(vNext); theta+=dtheta; }//end for i phi-=dphi; }//end for j vVertices.push_back(vBottom); // for(int i=0;i<vVertices.size();i++) //cout<<vVertices[i]<<endl; int lat2=2*lat; //add upper triangle fan for(int i=0;i<lat2;i++) { int verts[3]; verts[0]=0; verts[1]=1+i; verts[2]=1+(i+1)%lat2; TriFace face(verts); vFaces.push_back(face); } //add body for(int i=0;i<longi-2;i++) { int index=1+i*lat2; for(int j=0;j<lat2;j++) { int verts[3]; verts[0]=index+j; verts[1]=index+lat2+j; verts[2]=index+(j+1)%lat2; TriFace face1(verts); vFaces.push_back(face1); verts[0]=index+(j+1)%lat2; verts[1]=index+lat2+j; verts[2]=index+lat2+(j+1)%lat2; TriFace face2(verts); vFaces.push_back(face2); } } int ilast=vVertices.size()-1; int ilastrow=ilast-lat2; //add lower triangle fan for(int i=0;i<lat2;i++) { int verts[3]; verts[0]=ilast; verts[1]=ilastrow+(i+1)%lat2; verts[2]=ilastrow+i; TriFace face(verts); vFaces.push_back(face); } model.CreateFrom(vVertices,vFaces); return model; }