Esempio n. 1
0
Primitive*
PAPER_DOLL::build_primitive(CBface_list& o_faces)
{
   LMESHptr skel_mesh = dynamic_pointer_cast<LMESH>(o_faces.mesh());
   assert(skel_mesh);
   LMESHptr mesh = get_inflate_mesh(skel_mesh);
   assert(mesh);

   // create vertices for top and bottom parts:
   Bvert_list o_verts = o_faces.get_verts();            // original verts
   Bvert_list t_verts = copy_verts(o_verts, mesh);      // top verts
   Bvert_list b_verts = copy_verts(o_verts, mesh);      // bottom verts

   // set up mappings:
   //   original --> top
   //   original --> bottom
   VertMapper t_map(o_verts, t_verts, true);
   VertMapper b_map(o_verts, b_verts, true);

   Primitive* ret = new Primitive(mesh, skel_mesh);

   // build dependencies
   Bsurface_list surfs = Bsurface::get_surfaces(o_faces);
   for (int i = 0; i < surfs.num(); i++)
      ret->absorb_skel(surfs[i]);

   // generate top faces and bottom faces
   Bface_list t_faces = copy_faces(o_faces, t_map, ret, false);
   Bface_list b_faces = copy_faces(o_faces, b_map, ret, true);

   // create the sides:
   create_sides(o_faces, t_map, b_map, ret);

   Wvec n = o_faces.avg_normal();
   if (1) {
      define_offsets(o_verts, t_map, b_map, n, ret);
   } else {
      // under construction...
      //  for now just offset the top and bottom uniformly for testing...
      const double k = Config::get_var_dbl("PAPER_DOLL_OFFSET_SCALE",1.0);
      double       h = o_faces.get_edges().strong_edges().avg_len();
      t_verts.transform(Wtransf::translation( 0.5*k*h*n));
      b_verts.transform(Wtransf::translation(-0.5*k*h*n));
   }


   // make it all undoable:
   MULTI_CMDptr cmd = make_shared<MULTI_CMD>();

   // finish build
   ret->finish_build(cmd);

   //cmd->add(hide_surfs_cmd(Bsurface::get_surfaces(o_faces)));
   cmd->add(make_shared<SHOW_BBASE_CMD>(ret));
   WORLD::add_command(cmd);

   return _prim = ret;
}
Esempio n. 2
0
inline bool
join(CBvert_list& o, CBvert_list& c, MULTI_CMDptr& cmd, Cstr_ptr& msg)
{
   // Used in Skin::join_to_skel() to join seams of a mesh together.

   JOIN_SEAM_CMDptr join = new JOIN_SEAM_CMD(o, c);
   if (join->doit()) {
      err_adv(debug, "  joined %s (%d verts to %d verts)",
              **msg, o.num(), c.num());
      cmd->add(join);
      return true;
   } else {
      err_adv(debug, "  error: can't join %s", **msg);
      return false;
   }
}
Esempio n. 3
0
bool
SWEEP_DISK::build_box(CWpt& o, CWvec& t, CWpt_list& spts, MULTI_CMDptr cmd)
{
   // Editing or Creating
   bool is_editing = !(_surfs.empty());

   // get list of Bpoints around the boundary of the base surface:
   ARRAY<Bpoint*> bot_pts = is_editing ? _points.extract(_points.num()/2, _points.num()/2) : 
      Bpoint::get_points(_boundary.verts());  
   assert ( bot_pts.num() > 2 );
   int n = bot_pts.num();
   Bpoint_list top_pts(n);

   // If surface normals of base surface point along the sweep
   // direction, they have to be reversed. otherwise, the
   // boundary runs CW, so we reverse the order of the bottom
   // points to get them to run CCW:
   //
   // XXX - needs fix to work on embedded region, similar to
   //       build_tube() above.

   if ( _plane.normal()*t  < 0 ) {
      if (!is_editing) bot_pts.reverse();
   } else {
      reverse_faces( _enclosed_faces );
      if(cmd)
         cmd->add(make_shared<REVERSE_FACES_CMD>(_enclosed_faces, true));
   }

   double avg_len = _boundary.edges().avg_len();
   if ( isZero(avg_len) ) {
      cerr << "SWEEP_DISK::build_box(): ERROR, boundary avg len is zero" << endl;
      return false;
   }

   int num_edges = max( (int)round( spts.length()/avg_len ), 1 );
   int res_level = Config::get_var_int("BOX_RES_LEVEL", 2,true);

   // we'll keep lists of all curves and surfaces for the box,
   // for setting their res level uniformly:
   Bcurve_list   curves   = Bcurve::get_curves(_boundary.edges());
   Bsurface_list surfaces = Bsurface::get_surfaces(_enclosed_faces);

   if (!surfaces.empty())
      res_level = surfaces.min_res_level();
   else if (!curves.empty())
      res_level = curves.min_res_level();

   curves.clear();
   surfaces.clear();

   // XXX - Zachary: add SWEEP_CMD (BOX_CMD?) here:

   // Create/Edit the top points matching the bottom points
   // and the curves running vertically between them
   int i = 0;
   for ( i=0; i<n; i++ ) {
      Wvec n = (bot_pts[i]->loc() - o).orthogonalized(t).normalized();
      Wvec b = cross(n,t);
      Wpt_list cpts = spts;
      cpts.xform( Wtransf(o, t, b, n) );

      // XXX - should be undoable
      if (is_editing) {
         Wpt_listMap* m = dynamic_cast<Wpt_listMap*>(_curves[i]->map());
         cmd->add(make_shared<WPT_LIST_RESHAPE_CMD>(m,cpts));
      } else {
         top_pts += BpointAction::create(_mesh, cpts.back(), b, n, res_level, cmd);
         curves  += BcurveAction::create(_mesh, cpts, b, num_edges , res_level,
                                 bot_pts[i], top_pts[i], cmd);
      }
   }

   if (!is_editing) {
      // Create curves joining each top point to the next.
      for ( i=0; i<n; i++ ) {
         int j = (i+1) % n;

         Bcurve* c = bot_pts[i]->lookup_curve( bot_pts[j] );
         if ( !c ) {
            cerr << "SWEEP_DISK::build_box(): ERROR, can't find boundary curve"
               << endl;
            continue;
         }

         // Ensure orientation of top and bottom curves is the same.
         int i1 = i;
         int i2 = j;
         if ( c->b1() != bot_pts[i1] ) 
            swap( i1, i2 );
         assert( c->b1() == bot_pts[i1] &&
               c->b2() == bot_pts[i2] );

         // Create the new top curve with the same shape as the bottom curve.
         Wpt_list cpts = c->get_wpts();
         cpts.fix_endpoints( top_pts[i1]->loc(), top_pts[i2]->loc() );
         
         curves += BcurveAction::create(_mesh, cpts, t, c->num_edges(),
                              res_level, top_pts[i1], top_pts[i2], cmd);

         build_coons(bot_pts[i], bot_pts[j], top_pts[j], top_pts[i], surfaces, cmd);
      }

      // Slap on a top if base is quadrilateral
      // XXX - should handle other cases
      if (n == 4)
         build_coons(top_pts[0], top_pts[1], top_pts[2], top_pts[3], surfaces, cmd);
   }

   _mesh->changed();

   // set the res level uniformly over the box:
   for (int i = 0; i < bot_pts.num(); i++)
      bot_pts[i]->set_res_level(res_level);
   top_pts.set_res_level(res_level);
   curves.set_res_level(res_level);
   surfaces.set_res_level(res_level);
   _mesh->update_subdivision(res_level);

   // Record data necessary to return to this mode
   Panel* p = dynamic_cast<Panel*>(Bsurface::get_surface(_enclosed_faces));
   assert(p);
   if (is_editing) {
      vector<Panel*>::iterator it = std::find(panels.begin(), panels.end(), p);
      assert(it != panels.end());
      int loc = it - panels.begin();
      profiles[loc] = _profile;
   } else {
      panels.push_back(p);
      top_pts += bot_pts;
      bpoints.push_back(top_pts);
      bcurves.push_back(curves);
      bsurfaces.push_back(surfaces);
      profiles.push_back(_profile);
   }
   
   //FLOOR::realign(_mesh->cur_mesh(), cmd);

   WORLD::add_command(cmd);

   return true;
}
Esempio n. 4
0
bool
Skin::create_inflate(
   CBface_list& skel,
   double h,
   MULTI_CMDptr cmd,
   bool mode
   )
{

   // do a hack to make things more functional "for now"
   // find the level at which Bbases are operating,
   // and do the inflate operation there. but sew the
   // ribbons at this level (skel level). this way, for a small
   // offset, leading to hi-res skeleton region, we can get
   // away with a coarse skin. might suck though if the two
   // skins do smoothing independently and the ribbons don't
   // match up...

   double inner_offset = min(h, 0.0);
   double outer_offset = max(h, 0.0);
   Skin*  inside = create_inflate(skel, inner_offset, 0,  true, mode, cmd);
   Skin* outside = create_inflate(skel, outer_offset, 0, false, mode, cmd);

   if (!(inside && outside)) {
      err_adv(debug, "Skin::create_inflate: could not create inside and outside");
      return false;
   }

   if (!mode) outside->set_partner(inside);

   if (!mode) push_all_levels(skel, cmd, false);
   else {
      push(skel, cmd, false);
      push(inside->skin_faces(), cmd, false);
   }

   // create inf mapper
   if (!mode) {
      VertMapper in = inside->_mapper;
      VertMapper out = outside->_mapper;
      Bvert_list in_list = in.a_to_b(out.A());
      inside->set_inf_mapper(VertMapper(in_list, out.B(), true));
      outside->set_inf_mapper(VertMapper(out.B(), in_list, true)); 
   }

   // create ribbons
   
   // get matching boundaries of the two skin regions.
   // the "outer" one runs CCW as usual, but the "inner" one runs CW.
   EdgeStrip skel_strip = skel.get_boundary();
   if (skel_strip.empty()) {
      err_adv(debug, "Skin::create_inflate: no boundary -- no ribbons");
      return true;
   }
   EdgeStrip outer_strip = outside->_mapper.a_to_b(skel_strip);
   EdgeStrip inner_strip =  inside->_mapper.a_to_b(skel_strip);
   if (outer_strip.empty() || inner_strip.empty()) {
      err_adv(debug, "Skin::create_inflate: error finding skin boundaries");
      return false;
   }
   CREATE_RIBBONS_CMDptr rib = new CREATE_RIBBONS_CMD(outer_strip, inner_strip);
   if (rib->doit()) {
      cmd->add(rib);
      if (!mode) {
         inside->mesh()->compute_creases();
         return true;
      }
      VertMapper skel_map(inner_strip.verts(), skel_strip.verts(), false); // false means 1-way map
      if (Skin::create_multi_sleeve(inside->skin_faces()+inside->skel_faces(), skel_map, cmd))
         return true;
   }

   err_adv(debug, "Skin::create_inflate: no boundary -- no ribbons");
   return false;
}