예제 #1
0
/////////////////////////////////////
// compute_convex_hull()
/////////////////////////////////////
void 
HatchingGroupFixed::compute_convex_hull(
   CNDCZpt_list &pts, 
   NDCZpt_list &hull) 
{
   size_t i, num_upper, num_lower;
   vector<const NDCZpt*> P, Q;

   hull.clear();

   for (i=0; i<pts.size(); i++)  P.push_back(&(pts[i]));

   num_lower = make_chain(P, compare_xinc_ydec);

   if (!num_lower) return;

   for (i=0; i<num_lower; i++) hull.push_back(*(P[i]));

   for (i=num_lower; i<P.size(); i++) Q.push_back(P[i]);
   Q.push_back(P[0]);

   num_upper = make_chain(Q, compare_xdec_yinc);

   for (i=0; i<num_upper; i++) hull.push_back(*(Q[i]));
}
예제 #2
0
/////////////////////////////////////
// compute_convex_hull()
/////////////////////////////////////
void 
HatchingGroupFixed::compute_convex_hull(
   CNDCZpt_list &pts, 
   NDCZpt_list &hull) 
{
   int i, num_upper, num_lower;
   ARRAY<NDCZpt*> P, Q;

   hull.clear();

   for (i=0; i<pts.num(); i++)  P.add(&(pts[i]));

   num_lower = make_chain(P, compare_xinc_ydec);

   if (!num_lower) return;

   for (i=0; i<num_lower; i++) hull.add(*(P[i]));

   for (i=num_lower; i<P.num(); i++) Q.add(P[i]);
   Q.add(P[0]);

   num_upper = make_chain(Q, compare_xdec_yinc);

   for (i=0; i<num_upper; i++) hull.add(*(Q[i]));

}
예제 #3
0
/////////////////////////////////////
// add()
/////////////////////////////////////
bool
HatchingGroupFixed::add(
   CNDCpt_list &pl,
   const vector<double>&prl,
   int curve_type
   )
{
   size_t 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.size() != prl.size()) {
      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;
   vector<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;
   vector<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.size(); k++) {
         f = HatchingGroupBase::find_face_vis(NDCpt(ndcpts[k]),wloc);
         if ((f) && (f->patch() == _patch) && (f->front_facing())) {
            wlProjList.push_back(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.size()<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.size()*
                             (double)wlProjList.length())/(double)wlClipList.length());
      size_t num = max(guess,5);
      double step = 1.0/((double)(num-1));
      for (k=0 ; k<num ; k++) wlScaledList.push_back(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
      size_t num = max(wlClipList.size(), 5UL);
      double step = 1.0/((double)(num-1));
      for (k=0 ; k<num ; k++) wlScaledList.push_back(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.size();k++) ndczlScaledList.push_back(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;
   }

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

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

   for (k=0; k<ndczlScaledList.size(); 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.push_back(HatchingFixedVertex(f->index(), bc));
            f->bc2norm_blend(bc,norm);
            pts.push_back(wloc);
            norms.push_back(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.size()>1) {
      //XXX  - Okay, using the gesture pressure, but no offsets.
      //Need to go back and add offset generation...

      BaseStrokeOffsetLISTptr ol = make_shared<BaseStrokeOffsetLIST>();

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

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

      ol->push_back(BaseStrokeOffset(1.0, 0.0, finalprl[finalprl.size()-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;

}
예제 #4
0
/////////////////////////////////////
// draw()
/////////////////////////////////////
int
NPRSolidTexture::draw(CVIEWptr& v) 
{
   GL_VIEW_PRINT_GL_ERRORS("- Begin");
   
   int dl;

   if (_ctrl)
      return _ctrl->draw(v);

   nst_paper_flag = (_use_paper==1)?(true):(false);

   if (!nst_is_init_vertex_program) 
      nst_init_vertex_program();

   if (nst_paper_flag)
   {
      // The enclosing NPRTexture will have already
      // rendered the mesh in 'background' mode.
      // We should enable blending and draw with
      // z <= mode...
   }

   update_tex();
   

   glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT |
                     GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

   GL_COL(_color, _alpha*alpha());                       //GL_CURRENT_BIT

/*
   if (_use_lighting)
   {
      GLboolean   glbool;
      GLint       glint;

      glEnable(GL_LIGHTING);                             //GL_ENABLE_BIT
      glShadeModel(GL_SMOOTH);                           //GL_LIGHTING_BIT

      GLfloat me[4], mad[4], ms[4], msh;

      // XXX - ATI barfs on this.  It will light things 
      // correctly using the fixed pipeline, but manual
      // queries of the material state (here, or in
      // vertex programs) fail to return the right 
      // values when GL_COLOR_MATERIAL is enabled.
      // So, we'll just manually kil that mode, and
      // set the materials ourselves...

      // Used to be AMBIENT_AND_DIFFUSE tracking... right?
      glGetBooleanv(GL_COLOR_MATERIAL,&glbool);
      assert(glbool == GL_TRUE);

      glGetIntegerv(GL_COLOR_MATERIAL_FACE,&glint);
      assert(glint == GL_FRONT_AND_BACK);        

      glGetIntegerv(GL_COLOR_MATERIAL_PARAMETER,&glint);
      assert(glint == GL_AMBIENT_AND_DIFFUSE);

      glDisable(GL_COLOR_MATERIAL);                         //GL_ENABLE_BIT

      glGetMaterialfv(GL_FRONT,  GL_EMISSION,        me);
      glGetFloatv(               GL_CURRENT_COLOR,  mad);
      glGetMaterialfv(GL_FRONT,  GL_SHININESS,     &msh);

      if (_light_specular) { ms[0] = ms[1] = ms[2] = ms[3] = 1.0f; }
      else                 { ms[0] = ms[1] = ms[2] = ms[3] = 0.0f; }   

      glMaterialfv(GL_FRONT_AND_BACK,  GL_EMISSION,   me);  //GL_LIGHTING_BIT
      glMaterialfv(GL_FRONT_AND_BACK,  GL_AMBIENT,    mad); //GL_LIGHTING_BIT
      glMaterialfv(GL_FRONT_AND_BACK,  GL_DIFFUSE,    mad); //GL_LIGHTING_BIT
      glMaterialfv(GL_FRONT_AND_BACK,  GL_SPECULAR,   ms);  //GL_LIGHTING_BIT
      glMaterialf(GL_FRONT_AND_BACK,   GL_SHININESS,  msh); //GL_LIGHTING_BIT
   }
*/

   if (_use_lighting)
   {
      glEnable(GL_LIGHTING);                             //GL_ENABLE_BIT
      glShadeModel(GL_SMOOTH);                           //GL_LIGHTING_BIT

      GLfloat ms[4];

      if (_light_specular) { ms[0] = ms[1] = ms[2] = ms[3] = 1.0f; }
      else                 { ms[0] = ms[1] = ms[2] = ms[3] = 0.0f; }   

      glMaterialfv(GL_FRONT_AND_BACK,  GL_SPECULAR,   ms);  //GL_LIGHTING_BIT
   }
   else
   {
      glDisable(GL_LIGHTING);                            //GL_ENABLE_BIT
   }
   
   if (_tex) 
   {
      _tex->apply_texture();                             //GL_TEXTURE_BIT
   }

   //XXX - Just always blend, there may be alpha
   //in the texture...
   static bool OPAQUE_COMPOSITE = Config::get_var_bool("OPAQUE_COMPOSITE",false,true);

   if ((v->get_render_mode() == VIEW::TRANSPARENT_MODE) && (OPAQUE_COMPOSITE))
   {
      glDisable(GL_BLEND);
      glBlendFunc(GL_ONE, GL_ZERO);
   }
   else
   {
      glEnable(GL_BLEND);                                   //GL_ENABLE_BIT
      if (PaperEffect::is_alpha_premult())
			glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);			//GL_COLOR_BUFFER_BIT
		else
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //GL_COLOR_BUFFER_BIT
   }

   //Don't write depth if not using the background texture
   if (!_transparent)
   {
      glDepthMask(GL_FALSE);                             //GL_DEPTH_BUFFER_BIT
   }

   NDCZpt origin(0,0,0);

   if (nst_paper_flag && _travel_paper) {
      Wpt_list wbox;
      NDCZpt_list nbox;
      
      (_patch->xform() * _patch->mesh()->get_bb()).points(wbox);
      while (wbox.size() > 0) {
         nbox.push_back(wbox.back());
         wbox.pop_back();
      }
      
      static bool SCREEN_BOX = Config::get_var_bool("SCREEN_BOX",false,true);

      if (SCREEN_BOX) {
         double minx = nbox[0][0];
         double maxx = nbox[0][0];
         double miny = nbox[0][1];
         double maxy = nbox[0][1];
         for (NDCZpt_list::size_type i=1; i<nbox.size(); i++) {
            if (nbox[i][0] < minx) minx = nbox[i][0];
            if (nbox[i][0] > maxx) maxx = nbox[i][0];
            if (nbox[i][1] < miny) miny = nbox[i][1];
            if (nbox[i][1] > maxy) maxy = nbox[i][1];
            origin[0] = (minx + maxx)/2.0;
            origin[1] = (miny + maxy)/2.0;
         }
      } else {
         origin = nbox.average();
      }
   }

   PaperEffect::begin_paper_effect(nst_paper_flag, origin[0], origin[1]);

   if (nst_use_vertex_program) 
   {
      

      // Try it with the display list
      if ((_uv_in_dl == nst_tex_flag) && BasicTexture::dl_valid(v))
      {
         nst_setup_vertex_program(_use_lighting==1);    // GL_ENABLE_BIT, ???
         BasicTexture::draw(v);
         nst_done_vertex_program();

         PaperEffect::end_paper_effect(nst_paper_flag);

         glPopAttrib();

         return _patch->num_faces();
      }

      // Failed. Create it.
      dl = _dl.get_dl(v, 1, _patch->stamp());
      if (dl)
      {
         glNewList(dl, GL_COMPILE);
         _uv_in_dl = nst_tex_flag;
      }
   }

   set_face_culling();                                   // GL_ENABLE_BIT
   _patch->draw_tri_strips(_cb);

   if (nst_use_vertex_program) 
   {
      // End the display list here
      if (_dl.dl(v)) 
      {
         _dl.close_dl(v);

         // Built it, now execute it
         nst_setup_vertex_program(_use_lighting==1);        // GL_ENABLE_BIT, ???
         BasicTexture::draw(v);
         nst_done_vertex_program();
      }
   }

   PaperEffect::end_paper_effect(nst_paper_flag);

   glPopAttrib();

   GL_VIEW_PRINT_GL_ERRORS("End");

   return _patch->num_faces();

}