示例#1
0
void create_sphere( const Vec3d& sphere_centre,
                   double sphere_radius,
                   double dx,
                   std::vector<Vec3d>& verts, 
                   std::vector<Vec3st>& tris )
{
    
    const Vec3d domain_low = sphere_centre - Vec3d(sphere_radius + 3*dx);
    const Vec3d domain_high = sphere_centre + Vec3d(sphere_radius + 3*dx);
    Array3d phi;
    create_sphere_signed_distance( sphere_centre, sphere_radius, dx, domain_low, domain_high, phi );  
    
    MarchingTilesHiRes marching_tiles( domain_low, dx, phi );
    marching_tiles.contour();
    marching_tiles.improve_mesh();
    
    std::vector<Vec3d> new_verts( marching_tiles.x.size() );
    for ( size_t i = 0; i < new_verts.size(); ++i )
    {
        new_verts[i] = marching_tiles.x[i];
    }
    
    std::vector<Vec3st> new_tris( marching_tiles.tri.size() );
    for ( size_t i = 0; i < new_tris.size(); ++i )
    {
        new_tris[i] = Vec3st( marching_tiles.tri[i] );
    }
    
    project_to_exact_sphere( new_verts, sphere_centre, sphere_radius );
    
    Vec3st offset( verts.size() );
    for ( size_t i = 0; i < new_verts.size(); ++i )
    {
        verts.push_back( new_verts[i] );
    }
    
    for ( size_t i = 0; i < new_tris.size(); ++i )
    {
        tris.push_back( new_tris[i] + offset );
    }
    
}
示例#2
0
ErrorCode ReadCCMIO::read_vertices(CCMIOSize_t /* proc */, CCMIOID /* processorID */, CCMIOID verticesID,
                                   CCMIOID /* topologyID */, 
                                   Range *verts, TupleList &vert_map) 
{
  CCMIOError error = kCCMIONoErr;
  
    // pre-read the number of vertices, so we can pre-allocate & read directly in
  CCMIOSize_t nverts = CCMIOSIZEC(0);
  CCMIOEntitySize(&error, verticesID, &nverts, NULL);
  CHKCCMERR(error, "Couldn't get number of vertices.");

    // get # dimensions
  CCMIOSize_t dims;
  float scale;
  CCMIOReadVerticesf(&error, verticesID, &dims, NULL, NULL, NULL, CCMIOINDEXC(0), CCMIOINDEXC(1));
  CHKCCMERR(error, "Couldn't get number of dimensions.");

    // allocate vertex space
  EntityHandle node_handle = 0;
  std::vector<double*> arrays;
  readMeshIface->get_node_coords(3, GETINT32(nverts), MB_START_ID, node_handle, arrays);

    // read vertex coords
  CCMIOID mapID;
  std::vector<double> tmp_coords(GETINT32(dims)*GETINT32(nverts));
  CCMIOReadVerticesd(&error, verticesID, &dims, &scale, &mapID, &tmp_coords[0], 
                     CCMIOINDEXC(0), CCMIOINDEXC(0+nverts));
  CHKCCMERR(error, "Trouble reading vertex coordinates.");

    // copy interleaved coords into moab blocked coordinate space
  int i = 0, threei = 0;
  for (; i < nverts; i++) {
    arrays[0][i] = tmp_coords[threei++];
    arrays[1][i] = tmp_coords[threei++];
    if (3 == GETINT32(dims)) arrays[2][i] = tmp_coords[threei++];
    else arrays[2][i] = 0.0;
  }

    // scale, if necessary
  if (1.0 != scale) {
    for(i = 0; i < nverts; i++) {
      arrays[0][i] *= scale;
      arrays[1][i] *= scale;
      if (3 == GETINT32(dims)) arrays[2][i] *= scale;
    }
  }

    // read gids for vertices
  std::vector<int> gids(GETINT32(nverts));
  CCMIOReadMap(&error, mapID, &gids[0], CCMIOINDEXC(kCCMIOStart), CCMIOINDEXC(kCCMIOEnd));
  CHKCCMERR(error, "Trouble reading vertex global ids.");

    // put new vertex handles into range, and set gids for them
  Range new_verts(node_handle, node_handle+nverts-1);
  ErrorCode rval = mbImpl->tag_set_data(mGlobalIdTag, new_verts, &gids[0]);
  CHKERR(rval, "Couldn't set gids on vertices.");
  
    // pack vert_map with global ids and handles for these vertices
#ifdef TUPLE_LIST
  vert_map.resize(GETINT32(nverts));
  for (i = 0; i < GETINT32(nverts); i++) {
    vert_map.push_back(NULL, &gids[i], &node_handle, NULL);
#else
  for (i = 0; i < GETINT32(nverts); i++) {
    (vert_map[gids[i]]).push_back(node_handle);
#endif
    node_handle += 1;
  }
  
  if (verts) verts->merge(new_verts);

  return MB_SUCCESS;
}
  
ErrorCode ReadCCMIO::get_processors(CCMIOID stateID, 
                                    CCMIOID &processorID, CCMIOID &verticesID,
                                    CCMIOID &topologyID, CCMIOID &solutionID,
                                    std::vector<CCMIOSize_t> &procs,
                                    bool & /* has_solution */) 
{
  CCMIOSize_t proc = CCMIOSIZEC(0);
  CCMIOError error = kCCMIONoErr;
  
  CCMIONextEntity(&error, stateID, kCCMIOProcessor, &proc, &processorID);
  CHKCCMERR(error, NULL);
  if (CCMIOReadProcessor(NULL, processorID, &verticesID, 
                         &topologyID, NULL, &solutionID) != kCCMIONoErr) {
      // Maybe no solution;  try again
    CCMIOReadProcessor(&error, processorID, &verticesID, 
                       &topologyID, NULL, NULL);
    hasSolution = false;
  }
  CHKCCMERR(error, NULL);
  
  procs.push_back(proc);
  
  return MB_SUCCESS;
}
void BasicMesh::Subdivide() {
  // Loop subdivision
  // NOTE The indices of the original set of vertices do not change after
  // subdivision. The new vertices are simply added to the set of vertices.
  // However, the faces change their indices after subdivision. See how new
  // faces are added to the face set for details.
  // In short, the new mesh is created as follows:
  //   [old vertices]
  //   [new vertices]
  //   [faces]

  // For each edge, compute its center point
  struct edge_t {
    edge_t() {}
    edge_t(int s, int t) : s(s), t(t) {}
    edge_t(const edge_t& e) : s(e.s), t(e.t) {}
    bool operator<(const edge_t& other) const {
      if(s < other.s) return true;
      else if( s > other.s ) return false;
      else return t < other.t;
    }
    int s, t;
  };

  struct face_edge_t {
    face_edge_t() {}
    face_edge_t(int fidx, edge_t e) : fidx(fidx), e(e) {}
    bool operator<(const face_edge_t& other) const {
      if(fidx < other.fidx) return true;
      else if(fidx > other.fidx) return false;
      return e < other.e;
    }
    int fidx;
    edge_t e;
  };

  const int num_faces = NumFaces();

  map<edge_t, Vector3d> midpoints;

  // iterate over all edges
  for (HalfEdgeMesh::EdgeIter e=hemesh.edges_begin(); e!=hemesh.edges_end(); ++e) {
    auto heh = hemesh.halfedge_handle(e, 0);
    auto hefh = hemesh.halfedge_handle(e, 1);

    auto v0h = hemesh.to_vertex_handle(heh);
    auto v1h = hemesh.to_vertex_handle(hefh);

    int v0idx = vhandles_map[v0h];
    int v1idx = vhandles_map[v1h];

    auto v0 = verts.row(v0idx);
    auto v1 = verts.row(v1idx);

    if(hemesh.is_boundary(*e)) {
      // simply compute the mid point
      midpoints.insert(make_pair(edge_t(v0idx, v1idx),
                                 0.5 * (v0 + v1)));
    } else {
      // use [1/8, 3/8, 3/8, 1/8] weights
      auto v2h = hemesh.to_vertex_handle(hemesh.next_halfedge_handle(heh));
      auto v3h = hemesh.to_vertex_handle(hemesh.next_halfedge_handle(hefh));

      int v2idx = vhandles_map[v2h];
      int v3idx = vhandles_map[v3h];

      auto v2 = verts.row(v2idx);
      auto v3 = verts.row(v3idx);

      midpoints.insert(make_pair(edge_t(v0idx, v1idx), (v0 * 3 + v1 * 3 + v2 + v3) / 8.0));
    }
  }

  // Now create a new set of vertices and faces
  const int num_verts = NumVertices() + midpoints.size();
  MatrixX3d new_verts(num_verts, 3);

  // Smooth these points
  for(int i=0;i<NumVertices();++i) {
    auto vh = vhandles[i];
    if(hemesh.is_boundary(vh)) {
      // use [1/8, 6/8, 1/8] weights
      auto heh = hemesh.halfedge_handle(vh);
      if(heh.is_valid()) {
        assert(hemesh.is_boundary(hemesh.edge_handle(heh)));

        auto prev_heh = hemesh.prev_halfedge_handle(heh);

        auto to_vh = hemesh.to_vertex_handle(heh);
        auto from_vh = hemesh.from_vertex_handle(prev_heh);

        Vector3d p = 6 * verts.row(i);
        p += verts.row(vhandles_map[to_vh]);
        p += verts.row(vhandles_map[from_vh]);
        p /= 8.0;
        new_verts.row(i) = p;
      }
    } else {
      // loop through the neighbors and count them
      int valence = 0;
      Vector3d p(0, 0, 0);
      for(auto vvit = hemesh.vv_iter(vh); vvit.is_valid(); ++vvit) {
        ++valence;
        p += verts.row(vhandles_map[*vvit]);
      }
      const double PI = 3.1415926535897;
      const double wa = (0.375 + 0.25 * cos(2.0 * PI / valence));
      const double w = (0.625 - wa * wa);
      p *= (w / valence);
      p += verts.row(i) * (1 - w);
      new_verts.row(i) = p;
    }
  }

  // Add the midpoints
  map<edge_t, int> midpoints_indices;
  int new_idx = NumVertices();
  for(auto p : midpoints) {
    midpoints_indices.insert(make_pair(p.first, new_idx));
    midpoints_indices.insert(make_pair(edge_t(p.first.t, p.first.s), new_idx));

    new_verts.row(new_idx) = p.second;
    ++new_idx;
  }

  // Process the texture coordinates
  map<face_edge_t, Vector2d> midpoints_texcoords;

  for(int fidx=0;fidx<NumFaces();++fidx){
    int j[] = {1, 2, 0};
    for(int i=0;i<3;++i) {
      int v0idx = faces(fidx, i);
      int v1idx = faces(fidx, j[i]);

      // if v0 = f[index_of(v0)], the tv0 = tf[index_of(v0)]
      int tv0idx = face_tex_index(fidx, i);
      // if v1 = f[index_of(v1)], the tv1 = tf[index_of(v1)]
      int tv1idx = face_tex_index(fidx, j[i]);

      auto t0 = texcoords.row(tv0idx);
      auto t1 = texcoords.row(tv1idx);

      // the texture coordinates is always the mid point
      midpoints_texcoords.insert(make_pair(face_edge_t(fidx, edge_t(v0idx, v1idx)),
                                           0.5 * (t0 + t1)));
    }
  }

  const int num_texcoords = texcoords.rows() + midpoints_texcoords.size();
  MatrixX2d new_texcoords(num_texcoords, 2);

  // Just copy the existing texture coordinates
  new_texcoords.topRows(texcoords.rows()) = texcoords;

  // Tex-coords for the mid points
  map<face_edge_t, int> midpoints_texcoords_indices;
  int new_texcoords_idx = texcoords.rows();
  for(auto p : midpoints_texcoords) {
    //cout << p.first.fidx << ": " << p.first.e.s << "->" << p.first.e.t << endl;
    //getchar();
    midpoints_texcoords_indices.insert(make_pair(p.first,
                                                 new_texcoords_idx));
    midpoints_texcoords_indices.insert(make_pair(face_edge_t(p.first.fidx, edge_t(p.first.e.t, p.first.e.s)),
                                                 new_texcoords_idx));

    new_texcoords.row(new_texcoords_idx) = p.second;
    ++new_texcoords_idx;
  }

  MatrixX3i new_faces(num_faces*4, 3);
  MatrixX3i new_face_tex_index(num_faces*4, 3);
  for(int i=0;i<num_faces;++i) {
    // vertex indices of the original triangle
    auto vidx0 = faces(i, 0);
    auto vidx1 = faces(i, 1);
    auto vidx2 = faces(i, 2);

    // texture coordinates indices of the original triangle
    auto tvidx0 = face_tex_index(i, 0);
    auto tvidx1 = face_tex_index(i, 1);
    auto tvidx2 = face_tex_index(i, 2);

    // indices of the mid points
    int nvidx01 = midpoints_indices[edge_t(vidx0, vidx1)];
    int nvidx12 = midpoints_indices[edge_t(vidx1, vidx2)];
    int nvidx20 = midpoints_indices[edge_t(vidx2, vidx0)];

    // indices of the texture coordinates of the mid points
    int tnvidx01 = midpoints_texcoords_indices.at(face_edge_t(i, edge_t(vidx0, vidx1)));
    int tnvidx12 = midpoints_texcoords_indices.at(face_edge_t(i, edge_t(vidx1, vidx2)));
    int tnvidx20 = midpoints_texcoords_indices.at(face_edge_t(i, edge_t(vidx2, vidx0)));

    // add the 4 new faces
    new_faces.row(i*4+0) = Vector3i(vidx0, nvidx01, nvidx20);
    new_faces.row(i*4+1) = Vector3i(nvidx20, nvidx01, nvidx12);
    new_faces.row(i*4+2) = Vector3i(nvidx20, nvidx12, vidx2);
    new_faces.row(i*4+3) = Vector3i(nvidx01, vidx1, nvidx12);

    new_face_tex_index.row(i*4+0) = Vector3i(tvidx0, tnvidx01, tnvidx20);
    new_face_tex_index.row(i*4+1) = Vector3i(tnvidx20, tnvidx01, tnvidx12);
    new_face_tex_index.row(i*4+2) = Vector3i(tnvidx20, tnvidx12, tvidx2);
    new_face_tex_index.row(i*4+3) = Vector3i(tnvidx01, tvidx1, tnvidx12);
  }

  verts = new_verts;
  faces = new_faces;
  texcoords = new_texcoords;
  face_tex_index = new_face_tex_index;

  // Update the normals after subdivision
  ComputeNormals();
}