Пример #1
0
inline
Wpt
center (Wpt_list& pts, ARRAY<int>& N)
{
   Wpt ret = Wpt(0);
   for (int i = 0; i < N.num(); i++) {
      ret += pts[N[i]];
   }
   return ret / N.num();
}
Пример #2
0
/////////////////////////////////////
// get_visibility()
/////////////////////////////////////
void
HatchingGroupFixed::get_visibility(TAGformat &d)
{
   err_mesg(ERR_LEV_SPAM, "HatchingGroupFixed::get_visibility()"); 

   BMESH *m = _patch->mesh();
   if (LMESH::isa(m))
      m = ((LMESH*)m)->cur_mesh();

   int k, ctr=0;
   ARRAY<int> indices;
   CBface_list& faces = m->faces();

   *d >> indices;

   for (k=0; k<indices.num(); k++)
      {
         HatchingSimplexDataFixed *hsdf =
            HatchingSimplexDataFixed::find(faces[indices[k]]);
         if (!hsdf) 
            {
               hsdf = new HatchingSimplexDataFixed(faces[indices[k]]);
               ctr++;
            }
         hsdf->add(this);
      }

   err_mesg(ERR_LEV_SPAM, "HatchingGroupFixed::get_visibility() - Flagged %d tris and added %d new simplex data.", indices.num(), ctr); 


}
Пример #3
0
void
UVdata::split(CEdgeStrip& strip)
{
   ARRAY<Bvert_list> chains;
   strip.get_chains(chains);
   for (int i=0; i<chains.num(); i++)
      split_chain(chains[i]);
}
Пример #4
0
inline Wpt_list
get_pts(Bface_list& flist, ARRAY<Wvec>& blist)
{
   assert(flist.num() == blist.num());
   Wpt_list pts;
   for (int i = 0; i < flist.num(); i++) {
      Wpt pt;
      flist[i]->bc2pos(blist[i], pt);
      pts += pt;
   }
   return pts;
}
Пример #5
0
inline
int
pick (ARRAY<QuadtreeNode*>& l)
{
   int ret = -1;
   double total_w = 0.0;
   for (int i = 0; i < l.num(); i++) {
      total_w += l[i]->get_weight();
   }
   double r = dorand() * total_w;
   
   total_w = 0.0;
   for (int i = 0; i < l.num(); i++) {
      total_w += l[i]->get_weight();
      if (total_w >= r) {
         ret = i;
         break;
      }
   }
   return ret;
}
Пример #6
0
int make_chain(ARRAY<NDCZpt*>& V, int (*cmp)(const void*, const void*)) 
{
	int i, j, s = 1; 	NDCZpt *tmp;
	V.sort(cmp);
	for (i=2; i<V.num(); i++) 
   {
      for (j=s; j>=1 ; j--)
         if ((det(NDCvec(*(V[i]) - *(V[j])),	NDCvec(*(V[j-1]) - *(V[j]))) > 0)) break;
		s = j+1;
		tmp = V[s]; V[s] = V[i]; V[i] = tmp;
	}
	return s;
}
Пример #7
0
void 
visit(OctreeNode* node,  
      double regularity, Bface_list& flist, ARRAY<Wvec>& blist)
{
   if (node->get_leaf()) {
      if (node->get_disp()) {
         // subdivision
         ARRAY<QuadtreeNode*> fs;
         Bface_list temp;
         for (int i = 0; i < node->intersects().num(); i++) {
            Bface* f = node->intersects()[i];
            temp += f;
            fs += new QuadtreeNode(f->v1()->loc(), f->v2()->loc(), f->v3()->loc());
            fs.last()->build_quadtree(node, regularity);
            fs.last()->set_terms();
         }

         // assign weights
         assign_weights(fs, regularity, node->center());
         
         // pick a triangle
         int t = pick(fs);

         // moved below; want to ensure flist and blist stay in sync:
//         flist += temp[t];

         //set node face
         Bface_list ftemp;
         ftemp += temp[t];
         node->set_face(ftemp);

         // pick a point
         int p = pick(fs[t]->terms());
         if (p != -1) {
            Wvec bc;
            temp[t]->project_barycentric(fs[t]->terms()[p]->urand_pick(), bc);
            blist += bc;
            flist += temp[t]; // moved from above
            node->set_point(bc);
         }

         for (int i = 0; i < fs.num(); i++)
            delete fs[i];
         fs.clear();
      }
   } else {
      for (int i = 0; i < 8; i++)
         visit(node->get_children()[i], regularity, flist, blist);
   }
}
Пример #8
0
inline void
show_polys(BMESH* m)
{
   // for debugging: show polyline edges of a mesh

   if (!m) return;
   // Construct filter that accepts unreached polyline edges 
   UnreachedSimplexFilter    unreached;
   PolylineEdgeFilter        poly;

   EdgeStrip strip(m->edges(), unreached + poly);
   ARRAY<Bvert_list> chains;
   strip.get_chains(chains);
   for (int i=0; i<chains.num(); i++)
      WORLD::show_polyline(chains[i].pts(), 3, Color::blue_pencil_d, 0.5);
}
Пример #9
0
void
assign_weights(ARRAY<QuadtreeNode*>& fs, double regularity, CWpt& pt)
{
   double weight, d;
   QuadtreeNode* leaf;
   for (int i = 0; i < fs.num(); i++) {
      weight = 0.0;
      for (int j = 0; j < fs[i]->terms().num(); j++) {
         leaf = fs[i]->terms()[j];
         d = pt.dist(leaf->centroid());
         leaf->set_weight(distr_func(regularity, d) * leaf->area());
         weight += leaf->get_weight();
      }
      fs[i]->set_weight(weight);
   }
}
Пример #10
0
void
SkinCurveMap::set_pts(CBsimplex_list& simps, ARRAY<Wvec>& bcs)
{
   assert(simps.num() == bcs.num());
   
   _simps = simps;
   _bcs = bcs;

   static bool debug = Config::get_var_bool("DEBUG_SKIN_CURVE_SETUV",false,true);

   if (debug) {
      cerr << "-- In SkinCurveMap::set_ptss() got hte following simp/bc pair list" << endl;
      int i;
      for (i = 0; i < _simps.num(); i++) {
         cerr << i << " " << _simps[i] << "; " << _bcs[i] << endl;
      }
      cerr << "-- End list" << endl;
   }

   // Notify dependents they're out of date and sign up to be
   // recomputed
   invalidate();
}
Пример #11
0
void 
ProxySurface::trim_proxy_surface()
{
   assert(_proxy_mesh);

   int n = 0; //number of faces outside the bounding box   
   //get all the quads
   Bface_list faces = _proxy_mesh->faces();
   //clear out all the markings
   for(int i=0; i < faces.num(); ++i)
   {
      if(faces[i])
         ProxyData::set_mark(faces[i],this, false);
      //else
      //   cerr << "FACE is NULL" << endl;
   }
   //mark all the faces that do not overap bounding box
   for(int i=0; i < faces.num(); ++i)
   {
      if(faces[i]){
         bool t1 = (is_inside_bounding_box(faces[i]->e1())) ? true : false;
         bool t2 = (is_inside_bounding_box(faces[i]->e2())) ? true : false;
         bool t3 = (is_inside_bounding_box(faces[i]->e3())) ? true : false;
         
         // If all the edges are outside, then mark the face
         if(!t1 && !t2 && !t3){
            //cerr << "we can delete this face" << endl;
            ProxyData::set_mark(faces[i], this, true);
            n++;
         }
      }else {
         //cerr << "FACE is NULL" << endl;
      }
   }

   if(n < 1)
      return; 

   //for all verts check to see if all the faces that it is attached to has a marked
   Bvert_list verts = _proxy_mesh->verts();
   for(int i=0; i < verts.num(); ++i)
   {
      ARRAY<Bface*> ret;
      verts[i]->get_quad_faces(ret);
      // Make sure that all adjasent faces need to be deleted
      bool do_it=true;
      for(int k=0; k < ret.num(); ++k)
      {
         if(ret[k]){
            assert(ret[k]->is_quad());            
            if(!ProxyData::get_mark(ret[k], this) || !ProxyData::get_mark(ret[k]->quad_partner(), this))
            {
              // cerr << "vert degree " << verts[i]->p_degree() << endl;
               do_it = false;
               break;
            }
         }
      }
      if(do_it){
         UVpt remove_uv;
         UVdata::get_uv(verts[i], remove_uv);
         remove_vert_grid(remove_uv);

         _proxy_mesh->remove_vertex(verts[i]);
         _proxy_mesh->changed();
      }
   }
   //clean up faces
   Bface_list faces2 = _proxy_mesh->faces();
   for(int i=0; i < faces2.num(); ++i)
   {
      if(!(faces2[i]->is_quad()) || !(faces2[i]->quad_partner())){
         _proxy_mesh->remove_face(faces2[i]);
         _proxy_mesh->changed();
      }
      
   }

   //debug_grid();

   
}
Пример #12
0
void 
remove_nodes(Bface_list& flist, ARRAY<Wvec>& blist, double min_dist, ARRAY<OctreeNode*>& t)
{
//    if (flist.num() != blist.num()) {
//       return;
//    }
   assert(flist.num() == blist.num());
   Wpt_list pts = get_pts(flist, blist);
   ARRAY< ARRAY<int> > N;
   ARRAY<bool> to_remove;
   for (int i = 0; i < pts.num(); i++) {
      N += ARRAY<int>();
      to_remove += false;
   }

   for (int i = 0; i < pts.num(); i++) {
      for (int j = 0; j < t[i]->neibors().num(); j++) {
         int index = t[i]->neibors()[j]->get_term_index();
         
         if (index < pts.num())
         {
            if (pts[i].dist(pts[index]) < min_dist) {
               N[i] += index;
               N[index] += i;
            }
         }
         else
         {
            //cerr << "Sps Warning, index > pts.num()" << endl;
         }

      }
   }

   priority_queue< Priority, vector<Priority> > queue;
   ARRAY<int> versions;
   for (int i = 0; i < pts.num(); i++) {
      if (!to_remove[i] && !N[i].empty()) {
         Priority p;
         p._priority = center(pts, N[i]).dist(pts[i]);
         p._index = i;
         p._version = 0;
         queue.push(p);
      }
      versions += 0;
   }

   while (!queue.empty()) {
      Priority p = queue.top();
      queue.pop();
      int r = p._index;
      if (p._version == versions[r]) {
         to_remove[r] = true;
         for (int i = 0; i < N[r].num(); i++) {
            N[N[r][i]] -= r;
            versions[N[r][i]]++;
            if (!N[N[r][i]].empty()) {
               Priority q;
               q._priority = center(pts, N[N[r][i]]).dist(pts[N[r][i]]);
               q._index = N[r][i];
               q._version = versions[N[r][i]];
               queue.push(q);
            }
         }
      }
   }
   versions.clear();

   Bface_list ftemp(flist);
   ARRAY<Wvec> btemp(blist);
   flist.clear();
   blist.clear();
   for (int i = 0; i < ftemp.num(); i++)
      if (!to_remove[i]) {
         flist += ftemp[i];
         blist += btemp[i];
      }
}
Пример #13
0
/////////////////////////////////////
// add()
/////////////////////////////////////
bool
HatchingGroupFixed::add(
   CNDCpt_list &pl,
   const ARRAY<double>&prl,
   int curve_type
   )
{
   int k;
   double a,b;
   Bface *f;

   // It happens:
   if (pl.empty()) 
   {
      err_mesg(ERR_LEV_ERROR, "HatchingGroupFixed:add() - Error: point list is empty!");
      return false;
   }
   if (prl.empty()) 
   {
      err_mesg(ERR_LEV_ERROR, "HatchingGroupFixed:add() - Error: pressure list is empty!");
      return false;
   }

   if (pl.num() != prl.num())
   {
      err_mesg(ERR_LEV_ERROR, "HatchingGroupFixed:add() - gesture pixel list and pressure list are not same length.");
      return false;
   }

   err_mesg_cond(debug, ERR_LEV_SPAM, "HatchingGroupFixed:add() - smoothing gesture.");

   //Smooth the input gesture
   NDCpt_list              smoothpts;
   ARRAY<double>           smoothprl;
   if (!smooth_gesture(pl, smoothpts, prl, smoothprl, _params.anim_style()))
      return false;

   err_mesg_cond(debug, ERR_LEV_SPAM, "HatchingGroupFixed:add() - clipping gesture to model.");

   NDCpt_list              ndcpts;
   ARRAY<double>           finalprl;
   clip_to_patch(smoothpts,ndcpts,smoothprl,finalprl);
   ndcpts.update_length();

   err_mesg_cond(debug, ERR_LEV_SPAM, "HatchingGroupFixed::add() - Checking gesture silliness.");

   if (HatchingGroupBase::is_gesture_silly(ndcpts,_params.anim_style()))
   {
      err_mesg(ERR_LEV_WARN, "HatchingGroupFixed::add() - Punting silly gesture...");
      return false;
   }

   //Even if the user wants to project to create the
   //hatch, we continue with plane cutting to
   //generate a curve we can use to estimate
   //the mesh spacing so that the final projected
   //hatch is sampled evenly on the level of the mesh
   //spacing

   //Get the cutting line
   err_mesg_cond(debug, ERR_LEV_SPAM, "HatchingGroupFixed:add() - fitting line.");
   if (!fit_line(ndcpts,a,b)) return false;

   //Slide to midpoint if desired
   if (Config::get_var_bool("HATCHING_GROUP_SLIDE_FIT",false,true)) 
      b = ndcpts.interpolate(0.5)[1] - (a*ndcpts.interpolate(0.5)[0]);

   err_mesg_cond(debug, ERR_LEV_SPAM, "HatchingGroupFixed:add() - computing plane.");

   //Find the cutting plane
   Wplane wpPlane;
   f = compute_cutting_plane(_patch, a, b, ndcpts, wpPlane);
   if (!f) return false;
   else
   {
      if (!f->front_facing())
      {
         err_mesg(ERR_LEV_WARN, "HatchingGroupFixed::add() - Nearest pt. on fit line hit backfacing surface.");
         return false;
      }
   }

   err_mesg_cond(debug, ERR_LEV_SPAM, "HatchingGroupFixed:add() - slicing mesh.");
   
   //Intersect the mesh to get a 3D curve
   Wpt_list wlList;
   slice_mesh_with_plane(f,wpPlane,wlList);

   err_mesg_cond(debug, ERR_LEV_SPAM, "HatchingGroupFixed:add() - cliping curve to gesture.");

   //Clip end of 3D curve to match gesture
   Wpt_list wlClipList;
   clip_curve_to_stroke(_patch, ndcpts, wlList, wlClipList);
   wlClipList.update_length();

   Wpt_list wlScaledList;

   if (curve_type == HatchingGroup::CURVE_MODE_PROJECT)
   {
      err_mesg_cond(debug, ERR_LEV_SPAM, "HatchingGroupFixed::add() - Projecting to surface.");
     
      //Okay, the user wants to get literal, projected
      //points, so lets do it.  We're careful to
      //toss points that hit the no/wrong mesh
      Wpt_list wlProjList;
      Wpt wloc;

      for (k=0; k<ndcpts.num(); k++)
      {
         f = HatchingGroupBase::find_face_vis(NDCpt(ndcpts[k]),wloc);
         if ((f) && (f->patch() == _patch) && (f->front_facing()))
         {
            wlProjList += wloc;
         }
         else 
         {
            if (!f) 
               err_mesg(ERR_LEV_WARN, "HatchingGroupFixed::add() - Missed while projecting: No hit on a mesh!");
            else if (!(f->patch() == _patch)) 
               err_mesg(ERR_LEV_WARN, "HatchingGroupFixed::add() - Missed while projecting: Hit wrong patch.");
            else if (!f->front_facing())
               err_mesg(ERR_LEV_WARN, "HatchingGroupFixed::add() - Missed while projecting: Hit backfacing tri.");
            else 
               err_mesg(ERR_LEV_WARN, "HatchingGroupFixed::add() - Missed while projecting: WHAT?!?!?!?!");
         }
      }
      if (wlProjList.num()<2)
      {
         err_mesg(ERR_LEV_WARN, "HatchingGroupFixed:add() - Nothing left after projection failures. Punting...");
         return false;
      }
      wlProjList.update_length();

      err_mesg_cond(debug, ERR_LEV_SPAM, "HatchingGroupFixed::add() - Resampling curve.");

      //Resample to even spacing in world space. Sample
      //at a world distance similar to wlClipList, which
      //will be on the order of the mesh resolution
      //unless the gesture fits into one triangle,
      //in which case we ensure a minimum sampling
      int guess = (int)ceil(((double)wlClipList.num()*
                             (double)wlProjList.length())/(double)wlClipList.length());
      int num = max(guess,5);
      double step = 1.0/((double)(num-1));
      for (k=0 ; k<num ; k++) wlScaledList += wlProjList.interpolate((double)k*step);
   }
   else //CURVE_MODE_PLANE
   {
      assert(curve_type == HatchingGroup::CURVE_MODE_PLANE);

      err_mesg_cond(debug, ERR_LEV_SPAM, "HatchingGroupFixed::add() - Resampling curve.");

      //Resample to even spacing in world space. This curve will
      //be sampled on the order of the mesh spacing but we'll
      //not allow the num of samples to drop too low in case
      //the gesture's on the scale of one triangle
      int num = max(wlClipList.num(),5);
      double step = 1.0/((double)(num-1));
      for (k=0 ; k<num ; k++) wlScaledList += wlClipList.interpolate((double)k*step);
   }

   // Convert back to 2D
   err_mesg_cond(debug, ERR_LEV_SPAM, "HatchingGroupFixed:add() - converting to 2D.");
   NDCZpt_list ndczlScaledList;
   for (k=0;k<wlScaledList.num();k++) ndczlScaledList += NDCZpt(_patch->xform()*wlScaledList[k]);
   ndczlScaledList.update_length();

   // Calculate pixel length of hatch
   double pix_len = ndczlScaledList.length() * VIEW::peek()->ndc2pix_scale();

   if (pix_len < 8.0)
   {
      err_mesg(ERR_LEV_WARN, "HatchingGroupFixed::add() - Stroke only %f pixels. Probably an accident. Punting...", pix_len);
      return false;
   }

   ARRAY<HatchingFixedVertex>    verts;
   Wpt_list                      pts;
   ARRAY<Wvec>                   norms;

   err_mesg_cond(debug, ERR_LEV_SPAM, "HatchingGroupFixed::add() - Final sampling.");

   for (k=0; k<ndczlScaledList.num(); k++) {

      Wpt wloc;
      f = HatchingGroupBase::find_face_vis(NDCpt(ndczlScaledList[k]),wloc);

      if ((f) && (f->patch() == _patch) && (f->front_facing()))
      {
         Wvec bc;
         Wvec norm;

         //f->project_barycentric(wloc,bc);
         f->project_barycentric_ndc(NDCpt(ndczlScaledList[k]),bc);

         Wvec bc_old = bc;
         Bsimplex::clamp_barycentric(bc);
         double dL = fabs(bc.length() - bc_old.length());

         if (bc != bc_old)
         {
            err_mesg(ERR_LEV_INFO, 
               "HatchingGroupFixed::add() - Baycentric clamp modified result: (%f,%f,%f) --> (%f,%f,%f) Length Change: %f", 
                  bc_old[0], bc_old[1], bc_old[2], bc[0], bc[1], bc[2], dL);
         }
         if (dL < 1e-3)
         {
            verts += HatchingFixedVertex(f->index(),bc);
            f->bc2norm_blend(bc,norm);
            pts += wloc;
            norms += norm;
         }
         else
         {
            err_mesg(ERR_LEV_WARN, "HatchingGroupFixed::add() - Change too large due to error in projection. Dumping point...");
         }
      }
      else 
      {
         if (!f) 
            err_mesg(ERR_LEV_WARN, "HatchingGroupFixed::add() - Missed in final lookup: No hit on a mesh!");
         else if (!(f->patch() == _patch)) 
            err_mesg(ERR_LEV_WARN, "HatchingGroupFixed::add() - Missed in final lookup: Hit wrong patch.");
         else if (!(f->front_facing())) 
            err_mesg(ERR_LEV_WARN, "HatchingGroupFixed::add() - Missed in final lookup: Hit backfracing tri.");
         else
            err_mesg(ERR_LEV_WARN, "HatchingGroupFixed::add() - Missed in final lookup: WHAT?!?!?!?!");
      }
   }

   if (pts.num()>1)
   {
      //XXX  - Okay, using the gesture pressure, but no offsets.
      //Need to go back and add offset generation...

      BaseStrokeOffsetLISTptr ol = new BaseStrokeOffsetLIST;

      ol->set_replicate(0);
      ol->set_hangover(1);
      ol->set_pix_len(pix_len);

      ol->add(BaseStrokeOffset( 0.0, 0.0, 
            finalprl[0],                  BaseStrokeOffset::OFFSET_TYPE_BEGIN));
      for (k=1; k< finalprl.num(); k++)
            ol->add(BaseStrokeOffset( (double)k/(double)(finalprl.num()-1), 0.0, finalprl[k], BaseStrokeOffset::OFFSET_TYPE_MIDDLE));

      ol->add(BaseStrokeOffset( 1.0, 0.0, finalprl[finalprl.num()-1],   BaseStrokeOffset::OFFSET_TYPE_END));

      if (base_level(num_base_levels()-1)->pix_size() > 0)
      {
         assert(_params.anim_style() != HatchingGroup::STYLE_MODE_NEAT);

         add_base_level();

         // Make sure we can see it whil we're editing!
         base_level(num_base_levels()-1)->set_desired_frac(1.0);

      }

      base_level(num_base_levels()-1)->add_hatch(
         new HatchingHatchFixed(
            base_level(num_base_levels()-1),_patch->mesh()->pix_size(),verts,pts,norms,ol) );

      return true;
   }
   else
   {
      err_mesg(ERR_LEV_WARN, "HatchingGroupFixed:add() - All lookups are bad. Punting...");
      return false;
   }



   return true;

}
Пример #14
0
/////////////////////////////////////
// put_visibility()
/////////////////////////////////////
void
HatchingGroupFixed::put_visibility(TAGformat &d) const
{
   err_mesg(ERR_LEV_SPAM, "HatchingGroupFixed::put_visibility()"); 

   BMESH *m = _patch->mesh();
   if (LMESH::isa(m))
      m = ((LMESH*)m)->cur_mesh();

   int k;
   ARRAY<int> indices;
   CBface_list& faces = m->faces();
        
   for (k=0; k< faces.num(); k++)
      {
         HatchingSimplexDataFixed *hsdf = HatchingSimplexDataFixed::find(faces[k]);
         if (hsdf) 
            {
               if(hsdf->hack_exists(this))
                  indices += faces[k]->index();
            }
      }
   err_mesg(ERR_LEV_SPAM, "HatchingGroupFixed::put_visibility() - Stored %d tri indices.", indices.num()); 

   d.id();
   *d << indices;
   d.end_id();
}
Пример #15
0
/////////////////////////////////////
// recurse()
/////////////////////////////////////
void      
UVMapping::recurse(Bface *seed_f, rec_fun_t fun )
{           
   int k;
//   bool done = false;

   Bface*                  f;
   ARRAY<Bface*>   faces;

   assert(seed_f);

   faces.push(seed_f);

   while (faces.num()>0)
      {
         //Remove oldest face from end of queue
         f = faces.pop();

         //Skip if already seen
         if (!f->is_set(1))
            {
               f->set_bit(1);

               //If we get here, then this face *should* have uvdata
               //and *should* be unmapped
               UVdata* uvdata = UVdata::lookup(f);
               assert(uvdata);
               assert(uvdata->mapping()==0);

               //Do the action (add to map, or update limits, etc.)
               (this->*fun)(f);

               for (k=1; k<=3; k++)
                  {
                     Bedge *nxt_e = f->e(k);
                     assert(nxt_e);
                     Bface *nxt_f = nxt_e->other_face(f);
                     if (nxt_f)
                        {
                           UVdata *nxt_uvdata = UVdata::lookup(nxt_f);
                           if (nxt_uvdata)
                              {
                                 UVpt uva = uvdata->uv(k);
                                 UVpt uvb = uvdata->uv((k==3)?(1):(k+1));
                                 int nxt_k = ( (nxt_f->e1()==nxt_e)?(1):
                                               ((nxt_f->e2()==nxt_e)?(2):
                                                ((nxt_f->e3()==nxt_e)?(3):(0))));
                                 assert(nxt_k);
                                 UVpt nxt_uva = nxt_uvdata->uv(nxt_k);
                                 UVpt nxt_uvb = nxt_uvdata->uv((nxt_k==3)?(1):(nxt_k+1));

                                 //If neighboring face has uv, and the they match
                                 //we recurse into this next face
                                 if ((uva==nxt_uvb)&&(uvb==nxt_uva))
                                    {
                                       //Add to front of queue
                                       faces.push(nxt_f);
                                    }
                                 else {
                                    //Nothing
                                 }
                              }
                        }
                  }
            }
      }
}
Пример #16
0
/////////////////////////////////////
// recurse_wrapping()
/////////////////////////////////////
void      
UVMapping::recurse_wrapping(Bface *seed_f)
{           
   int k;

   Bface *f;
   ARRAY<Bface*> faces;

   assert(seed_f);

   faces.push(seed_f);

   while (faces.num()>0)
   {
      //Remove face from end of queue
      f = faces.pop();

      //Skip if already seen
      if (!f->is_set(1))
      {
         f->set_bit(1);

         //If we get here, then this face *should* have uvdata
         //and *should* be allready be mapped to us!
         UVdata* uvdata = UVdata::lookup(f);
         assert(uvdata);
         assert(uvdata->mapping()==this);

         for (k=1; k<=3; k++)
         {
            Bedge *nxt_e = f->e(k);
            assert(nxt_e);
            Bface *nxt_f = nxt_e->other_face(f);
            if (nxt_f)
            {
               UVdata *nxt_uvdata = UVdata::lookup(nxt_f);
               if (nxt_uvdata)
               {
                  UVpt uva = uvdata->uv(k);
                  UVpt uvb = uvdata->uv((k==3)?(1):(k+1));
                  int nxt_k = ( (nxt_f->e1()==nxt_e)?(1):
                                ((nxt_f->e2()==nxt_e)?(2):
                                 ((nxt_f->e3()==nxt_e)?(3):(0))));
                  assert(nxt_k);
                  UVpt nxt_uva = nxt_uvdata->uv(nxt_k);
                  UVpt nxt_uvb = nxt_uvdata->uv((nxt_k==3)?(1):(nxt_k+1));

                  //If neighboring face has uv, and the they match
                  //we recurse into this next face
                  if ((uva==nxt_uvb)&&(uvb==nxt_uva))
                  {
                     //Stick face on start of queue
                     faces.push(nxt_f);
                  }
                  //But if not, let's see if the other face is
                  //part of this mapping. If it is, then we found
                  //a seam.  Find the direction (u or v) and if
                  //its consistent with the _min_u/_max_u (or v)
                  //Then set the wrap flag for u or v appropriately
                  //or just turn all wrapping off if something's amiss
                  else 
                  {
                     //Here's a seam!
                     if (nxt_uvdata->mapping() == this)
                     {               
                        //We support 2 kinds of wrapping:
                        //-Wrap on a line of constant u (wrap at _min_u,_max_u)
                        //-Wrap on a line of constant v (wrap at _min_v,_max_v)
                        //If neither is seen, or if the discontinuity isn't
                        //at the extrema, we found something anomolous, abort!
                        //Note - There can be holes at the seam without problems.

                        if ((uva[0]==uvb[0])&&(nxt_uva[0]==nxt_uvb[0]))
                        {
                           //This looks like wrapping on a line of const. u
                           //Let's make sure the discontinuity is at the extrema

                           if ( (uva[0]==_min_u && nxt_uva[0]==_max_u) ||
                                (uva[0]==_max_u && nxt_uva[0]==_min_u))
                           {
                              //It's all good
                              if (!_wrap_u)
                                 {
                                    err_mesg(ERR_LEV_SPAM, "UVMapping::recurse_wrapping() - Found a valid wrapping seam in u.");
                                    _wrap_u = true;
                                 }
                           }
                           else
                           {
                              //We aren't at the extrema, so set the bad flag
                              //to avoid further checking

                              _wrap_bad = true;
                              _wrap_u = false;
                              _wrap_v = false;

                              err_mesg(ERR_LEV_WARN,
                                 "UVMapping::recurse_wrapping() - Found an INVALID wrapping seam in u: (%f,%f) since u extrema are: (%f,%f)",
                                   uva[0], nxt_uva[0], _min_u, _max_u);
                              err_mesg(ERR_LEV_WARN, "UVMapping::recurse_wrapping() - Aborting all wrapping.");
                           }
                        }
                        else if ((uva[1]==uvb[1])&&(nxt_uva[1]==nxt_uvb[1]))
                        {
                           //This looks like wrapping on a line of const. v
                           //Let's make sure the discontinuity is at the extrema

                           if ( (uva[1]==_min_v && nxt_uva[1]==_max_v) ||
                                (uva[1]==_max_v && nxt_uva[1]==_min_v))
                           {
                              //It's all good
                              if (!_wrap_v)
                              {
                                 err_mesg(ERR_LEV_INFO, "UVMapping::recurse_wrapping() - Found a valid wrapping seam in v.");
                                 _wrap_v = true;
                              }
                           }
                           else
                           {
                              //We aren't at the extrema, so set the bad flag
                              //to avoid further checking

                              _wrap_bad = true;
                              _wrap_u = false;
                              _wrap_v = false;
                                        
                              err_mesg(ERR_LEV_WARN,
                                 "UVMapping::recurse_wrapping() - Found an INVALID wrapping seam in v: (%f,%f) since v extrema are: (%f,%f)",
                                   uva[1], nxt_uva[1], _min_v, _max_v);
                              err_mesg(ERR_LEV_WARN, "UVMapping::recurse_wrapping() - Aborting all wrapping.");
                           }
                        }
                        else
                        {
                           //One or both edges failed to show constant u or v
                           //Abort any further wrapping...

                           _wrap_bad = true;
                           _wrap_u = false;
                           _wrap_v = false;

                           err_mesg(ERR_LEV_WARN,
                              "UVMapping::recurse_wrapping() - Found an INVALID wrapping. The seam wasn't constant in u or v.");
                           err_mesg(ERR_LEV_WARN,
                              "UVMapping::recurse_wrapping() - Edge #1 (%f,%f)-(%f,%f) Edge #2 (%f,%f)-(%f,%f)",
                                 uva[0], uva[1], uvb[0], uvb[1], nxt_uvb[0], nxt_uvb[1], nxt_uva[0], nxt_uva[1]);
                           err_mesg(ERR_LEV_WARN,
                              "UVMapping::recurse_wrapping() - Aborting all wrapping.");
                        }
                     }
                  }
               }
            }
         }
      }
   }
}
Пример #17
0
void
LMESH::fit(ARRAY<Lvert*>& verts, bool do_gauss_seidel)
{
   static bool debug = Config::get_var_bool("DEBUG_LMESH_FIT",false);
   static bool move_along_normal =
      Config::get_var_bool("FITTING_MOVE_ALONG_NORMAL",false);

   if (verts.empty())
      return;

   // calculate the bounding box of the vertices
   BBOX box;
   int i;
   for (i=0; i<verts.num(); i++)
      box.update(verts[i]->loc());

   double max_err = box.dim().length() * 1e-5;

   int n = verts.num();

   // get original control point locations
   ARRAY<Wpt> C(n);   // original control points
   ARRAY<Wpt> L(n);   // current limit points
   for (i=0; i<n; i++) {
      C += verts[i]->loc();
      L += Wpt::Origin();
   }

   if(debug) {
      cerr << "LMESH::fit- fitting " << n << " vertices"<<endl;
      cerr << "Max_err = " << max_err <<endl;
   }

   // do 50 iterations...
   double prev_err = 0;
   ARRAY<double> errors;
   for (int k=0; k<50; k++) {

      errors.clear();

      double err = 0;

      if (do_gauss_seidel) {

         // Gauss-Seidel iteration: use updated values from the
         // current iteration as they are computed...
         for (int j=0; j<n; j++) {
            // don't need that L[] array...
            Wpt limit;
            verts[j]->limit_loc(limit);
            Wvec delt = C[j] - limit;
            errors+=delt.length();
            err += delt.length();
            if(move_along_normal)
               delt = delt*verts[j]->norm()*verts[j]->norm();
            verts[j]->offset_loc(delt);
         }

      } else {
         // compute the new offsets from the offsets computed in the
         // previous iteration
         int j;
         for (j=0; j<n; j++)
            verts[j]->limit_loc(L[j]);

         for (j=0; j<n; j++) {
            Wvec delt = C[j] - L[j];

            err += delt.length();
            errors+=delt.length();
            if(move_along_normal)
               delt = delt*verts[j]->norm()*verts[j]->norm();
            verts[j]->offset_loc(delt);
         }
      }
      // compute the average error:
      err /= n;

      double avg,std_d,max,min;
      if (debug) {
         if (prev_err != 0) {
            err_msg("Iter %d: avg error: %f, reduction: %f",
                    k, err, err/prev_err);
            statistics(errors,true,&avg,&std_d,&max,&min);
         } else {
            err_msg("Iter %d: avg error: %f", k, err);
            statistics(errors,true,&avg,&std_d,&max,&min);
         }
      } else
         statistics(errors,false,&avg,&std_d,&max,&min);

      prev_err = err;

      if (max < max_err) {
         if(debug) cerr << "Terminating at " << k <<" th iterations"<<endl;
         return;
      }
   }
}