示例#1
0
/* Generate a transformed copy of poly. */
static inline Poly *transform_poly(Transform T, Transform Tdual, Transform TxT,
				   Poly *poly,
				   struct obstack *scratch)
{
  Poly *newp;
  int i;
  
  newp = new_poly(poly->n_vertices, NULL, scratch);
  for (i = 0; i < poly->n_vertices; i++) {
    newp->v[i] = obstack_alloc(scratch, sizeof(Vertex));
    HPt3Transform(T, &poly->v[i]->pt, &newp->v[i]->pt);
    if (poly->flags & PL_HASVCOL) {
      newp->v[i]->vcol = poly->v[i]->vcol;
    }
    if (poly->flags & PL_HASVN) {
      NormalTransform(Tdual, &poly->v[i]->vn, &newp->v[i]->vn);
    }
    if (poly->flags & PL_HASST) {
      TxSTTransform (TxT, &poly->v[i]->st, &newp->v[i]->st);
    }
  }

  if (poly->flags & PL_HASPCOL) {
    newp->pcol = poly->pcol;
  }
  if (poly->flags & PL_HASPN) {
    NormalTransform(Tdual, &poly->pn, &newp->pn);
  }
  
  newp->flags = poly->flags;

  return newp;
}
示例#2
0
/* Split the given polygon -- which must describe a quadrilateral --
 * along the diagonal starting at "vertex". Used for splitting
 * non-flat or concave quadrilaterals.
 */
static inline void split_quad_poly(int vertex, Poly *poly0,
				   PolyListNode **plist,
				   const void **tagged_app,
				   struct obstack *scratch)
{
  PolyListNode *new_pn;
  Poly *poly[2];
  Poly savedp;
  Vertex *savedv[4];
  int i, v;

  if (poly0->flags & POLY_SCRATCH) {
    /* reuse the space */
    savedp = *poly0;
    savedp.v = savedv;
    memcpy(savedp.v, poly0->v, 4*sizeof(Vertex *));
    new_pn = new_poly_list_node(tagged_app, scratch);
    new_pn->poly = poly[0] = poly0;
    poly[0]->n_vertices = 3;
    ListPush(*plist, new_pn);
    poly0 = &savedp;
  }
  for (i = (poly0->flags & POLY_SCRATCH) != 0; i < 2; i++) {
    new_pn = new_poly_list_node(tagged_app, scratch);
    new_pn->poly = poly[i] = new_poly(3, NULL, scratch);
    ListPush(*plist, new_pn);
  }
  
  for (i = 0; i < 2; i++) {
    poly[i]->pcol   = poly0->pcol;
    poly[i]->pn     = poly0->pn;
    poly[i]->flags |= poly0->flags;
  }
  
  /* copy over vertex information, the _REAL_ poly normal will be
   * computed later, the need for that is flagged by POLY_SCRATCH.
   */
  v = vertex;
  for (i = 0; i < 3; i++) {
    poly[0]->v[i] = poly0->v[v++];
    v %= 4;
  }
	
  v = (v - 1 + 4) % 4;
  for (i = 0; i < 3; i++) {
    poly[1]->v[i] = poly0->v[v++];
    v %= 4;
  }
}
Polygon_2 CollisionDetector::translate_polygon_to(const Polygon_2& poly, const Point_2& new_ref_pt) const
{
	m_translate_helper.resize(0);
	const Point_2 &ref = *poly.left_vertex();
	std::pair<double,double> diff(
	//Vector_2 diff(
		CGAL::to_double(ref.x().exact()) - CGAL::to_double(new_ref_pt.x().exact()), 
		CGAL::to_double(ref.y().exact()) - CGAL::to_double(new_ref_pt.y().exact())
	);

  	for (Polygon_2::Vertex_const_iterator it = poly.vertices_begin(), it_end = poly.vertices_end(); it != it_end; ++it)
  	{
		m_translate_helper.push_back( Point_2(CGAL::to_double(it->x()) + diff.first, CGAL::to_double(it->y()) + diff.second ) );
		//translated.push_back( (*it) + diff );
  	}



  	Polygon_2 new_poly(m_translate_helper.begin(),m_translate_helper.end());
  	return new_poly;
}
示例#4
0
polygon *get_healpix_poly(int nside, int hpix)
{
  int nv, nvmax, i, pix_n, pix_e, pix_s, pix_w, ev[1];
  vertices *vert;
  polygon *pixel, *pixelbetter;
  long double verts_vec[12], verts_vec_n[12], verts_vec_e[12], verts_vec_s[12], verts_vec_w[12], dist_n, dist_w, dist_s, dist_e;
  vec center, center_n, center_e, center_s, center_w, vertices_vec[4], vertices_vec_n[4], vertices_vec_e[4], vertices_vec_s[4], vertices_vec_w[4];
  azel *vertices_azel[8], vertices[8];

  for(i=0;i<=7;i++) vertices_azel[i] = &(vertices[i]);

  if (nside == 0) {
     pixel=new_poly(0);
     pixel->weight=1;
     pixel->pixel=0;
     
     return(pixel);
  }

  else {
    healpix_verts(nside, hpix, center, verts_vec);
    
    /* north vertex */
    for(i=0;i<=2;i++) (vertices_vec[0])[i] = verts_vec[i];

    /* east vertex */
    for(i=0;i<=2;i++) (vertices_vec[1])[i] = verts_vec[i+3];

    /* south vertex */
    for(i=0;i<=2;i++) (vertices_vec[2])[i] = verts_vec[i+6];

    /* west vertex */
    for(i=0;i<=2;i++) (vertices_vec[3])[i] = verts_vec[i+9];

    rp_to_azel(vertices_vec[0], vertices_azel[0]);
    rp_to_azel(vertices_vec[3], vertices_azel[2]);
    rp_to_azel(vertices_vec[2], vertices_azel[4]);
    rp_to_azel(vertices_vec[1], vertices_azel[6]);

    pix_n = 4*hpix + 3;
    pix_e = 4*hpix + 1;
    pix_s = 4*hpix;
    pix_w = 4*hpix + 2;

    healpix_verts(nside*2, pix_n, center_n, verts_vec_n);
    healpix_verts(nside*2, pix_e, center_e, verts_vec_e);
    healpix_verts(nside*2, pix_s, center_s, verts_vec_s);
    healpix_verts(nside*2, pix_w, center_w, verts_vec_w);

    /* north vertex of each child pixel */
    for(i=0;i<=2;i++){
      (vertices_vec_n[0])[i] = verts_vec_n[i];
      (vertices_vec_e[0])[i] = verts_vec_e[i];
      (vertices_vec_s[0])[i] = verts_vec_s[i];
      (vertices_vec_w[0])[i] = verts_vec_w[i];
    }

    /* east vertex of each child pixel */
    for(i=0;i<=2;i++){
      (vertices_vec_n[1])[i] = verts_vec_n[i+3];
      (vertices_vec_e[1])[i] = verts_vec_e[i+3];
      (vertices_vec_s[1])[i] = verts_vec_s[i+3];
      (vertices_vec_w[1])[i] = verts_vec_w[i+3];
    }

    /* south vertex of each child pixel */
    for(i=0;i<=2;i++){
      (vertices_vec_n[2])[i] = verts_vec_n[i+6];
      (vertices_vec_e[2])[i] = verts_vec_e[i+6];
      (vertices_vec_s[2])[i] = verts_vec_s[i+6];
      (vertices_vec_w[2])[i] = verts_vec_w[i+6];
    }

    /* west vertex of each child pixel */
    for(i=0;i<=2;i++){
      (vertices_vec_n[3])[i] = verts_vec_n[i+9];
      (vertices_vec_e[3])[i] = verts_vec_e[i+9];
      (vertices_vec_s[3])[i] = verts_vec_s[i+9];
      (vertices_vec_w[3])[i] = verts_vec_w[i+9];
    }
    
    rp_to_azel(vertices_vec_n[3], vertices_azel[1]);
    rp_to_azel(vertices_vec_w[2], vertices_azel[3]);
    rp_to_azel(vertices_vec_s[1], vertices_azel[5]);
    rp_to_azel(vertices_vec_e[0], vertices_azel[7]);

    for(i=0; i<8; i++){
      if(vertices[i].az < 0.) vertices[i].az = vertices[i].az + TWOPI;
      else {};
    }

    for(i=0; i<8; i++){
      if(vertices[i].az >= TWOPI) vertices[i].az = vertices[i].az - TWOPI;
      else {};
    } 

    nv=8; nvmax=8;
    vert=new_vert(nvmax);
    if(!vert){
      fprintf(stderr, "error in get_healpix_poly: failed to allocate memory for 8 vertices\n");
      return(0x0);
    }
    vert->nv=nv; vert->v=&vertices[0];

    pixel=new_poly(4);
    
    if(!pixel){
      fprintf(stderr, "error in get_healpix_poly: failed to allocate memory for polygon of 4 caps\n");
      return(0x0);
    }

    ev[0] = 8;

    edge_to_poly(vert, 2, &ev[0], pixel);
    pixel->id = (long long)hpix;

    pixelbetter=new_poly(5);
    
    if(!pixelbetter){
      fprintf(stderr, "error in get_healpix_poly: failed to allocate memory for polygon of 5 caps\n");
      return(0x0);
    }

    pixelbetter->np = 5;
    pixelbetter->npmax = 5;

    for(i=0; i<=3; i++) {
      pixelbetter->rp[i][0] = pixel->rp[i][0];
      pixelbetter->rp[i][1] = pixel->rp[i][1];
      pixelbetter->rp[i][2] = pixel->rp[i][2];
      pixelbetter->cm[i] = pixel->cm[i];
    }

    pixelbetter->rp[4][0] = center[0]; pixelbetter->rp[4][1] = center[1]; pixelbetter->rp[4][2] = center[2];
    pixelbetter->id = (long long)hpix;

    dist_n = cmrpirpj(center, vertices_vec[0]);
    dist_w = cmrpirpj(center, vertices_vec[3]);
    dist_s = cmrpirpj(center, vertices_vec[2]);
    dist_e = cmrpirpj(center, vertices_vec[1]);

    if(dist_n>=dist_w && dist_n>=dist_s && dist_n>=dist_e){
      pixelbetter->cm[4] = dist_n+0.000001;
    }
    else if(dist_w>=dist_n && dist_w>=dist_s && dist_w>=dist_e){
      pixelbetter->cm[4] = dist_w+0.000001;
    }
    else if(dist_s>=dist_n && dist_s>=dist_w && dist_s>=dist_e){
      pixelbetter->cm[4] = dist_s+0.000001;
    }
    else if(dist_e>=dist_n && dist_e>=dist_s && dist_e>=dist_w){
      pixelbetter->cm[4] = dist_e+0.000001;
    }
    else{
      fprintf(stderr, "error in get_healpix_poly: cannot find correct fifth cap\n");
      return(0x0);
    }


    if(!pixelbetter){
      fprintf(stderr, "error in get_healpix_poly: polygon is NULL.\n");
      return(0x0);
    }

    return(pixelbetter);
  }
}
示例#5
0
文件: pixelize.c 项目: bareid/mangle
int pixel_loop(int pix, int n, polygon *input[/*n*/], int out_max, polygon *output[/*out_max*/]){
  int *child_pix,children;
  int i,j,k,m,out,nout;
  int ier, iprune, np;
  polygon *pixel;
  polygon **poly;
 
  //allocate memory for work array of polygon pointers
  poly=(polygon **) malloc(sizeof(polygon *) * n);
  if(!poly){
    fprintf(stderr, "pixel_loop: failed to allocate memory for %d polygon pointers\n",n);
    return(-1);
  }
  
  // allocate memory for child_pix array
  if(pix==0 && scheme=='d'){
    child_pix=(int *) malloc(sizeof(int) * 117);
    children=117;
    if(!child_pix){
      fprintf(stderr, "pixel_loop: failed to allocate memory for 117 integers\n");
      return(-1);
    }
  }
  else{
    child_pix=(int *) malloc(sizeof(int) * 4);
    children=4;
    if(!child_pix){
      fprintf(stderr, "pixel_loop: failed to allocate memory for %d integers\n", 4);
      return(-1);
    }
  }

  get_child_pixels(pix, child_pix, scheme);
  out=0;
  
  for(i=0;i<children;i++){    
    /*get the current child pixel*/
    pixel=get_pixel(child_pix[i], scheme);
 
    if(!pixel){
      fprintf(stderr, "error in pixel_loop: could not get pixel %d\n", child_pix[i]); 
      return(-1);
    }
    
    /*loop through input polygons to find the ones that overlap with current child pixel*/
    for(j=0;j<n;j++){
      /* skip null polygons */
      if (input[j]->np > 0 && input[j]->cm[0] == 0.){
	poly[j] = 0x0;
	continue;
      }

      np=input[j]->np+pixel->np;
      poly[j]=new_poly(np);
      if(!poly[j]){
	fprintf(stderr, "error in pixel_loop: failed to allocate memory for polygon of %d caps\n", np);
	return(-1);
      }
      /*set poly[j] to the intersection of input[j] and current child pixel*/
      poly_poly(input[j],pixel,poly[j]);
      poly[j]->pixel=pixel->pixel;
    
      iprune = prune_poly(poly[j], mtol);
      if (iprune == -1) {
	fprintf(stderr, "pixelize: failed to prune polygon for pixel %d; continuing ...\n", poly[j]->pixel);
	//return(-1);
      }
      /*if polygon is null, get rid of it*/
      if (iprune >= 2) {
	free_poly(poly[j]);
	poly[j] = 0x0;
      }       
    }
    
    /*copy down non-null polygons*/
    k=0;
    for(j=0;j<n;j++){
      if(poly[j]){
	poly[k++]=poly[j];
      }
    }
    m=k;
    /*nullify the rest of the array, but don't free, since pointers have been copied above*/
    for(j=m;j<n;j++){
      poly[j]=0x0;
    }
    
    /*if we're below the max resolution, recursively call pixel_loop on the current child pixel */ 
    if(m>polys_per_pixel && get_res(child_pix[i],scheme)<res_max){
      //printf("calling pixel loop for pixel %d with %d polygons\n",child_pix[i],m);
      nout=pixel_loop(child_pix[i],m,poly,out_max-out,&output[out]);
      if(nout==-1) return(-1);
      out+=nout;
    }
    else{
      for(k=0;k<m;k++){
	/* check whether exceeded maximum number of polygons */
	if (out >= out_max) {
	  fprintf(stderr, "pixel_loop: total number of polygons exceeded maximum %d\n", NPOLYSMAX);
	  fprintf(stderr, "if you need more space, enlarge NPOLYSMAX in defines.h, and recompile\n");
	  return(-1);
	}
	/*make sure output polygon has enough room */
	ier = room_poly(&output[out], poly[k]->np, DNP, 0);
	if (ier == -1) {
	  fprintf(stderr, "error in pixel_loop: failed to allocate memory for polygon of %d caps\n", poly[i]->np + DNP);
	  return(-1);
	}

	/*copy polygon to output array*/
	copy_poly(poly[k],output[out]);
	out++;    
      }
    }
    /*free up memory for next child pixel*/
    
    free_poly(pixel);
    for(j=0;j<n;j++){
      free_poly(poly[j]);
    }
  }
  free(child_pix);
  free(poly);
  return out;
}
示例#6
0
void tess_vertex_data(Vertex *v, struct tess_data *data)
{
  /* Here we have to do all the work, depending on what flag
   * previously has been passed to the begin() callback.
   */
  if (data->vcnt == 0) {
    /* create a new polygon */
    data->p = new_poly(3, NULL, data->scratch);
    data->p->flags |= data->polyflags;
    if (data->polyflags & FACET_C) {
      data->p->pcol = data->trickyp->pcol;
    }
    data->p->pn = *data->pn; /* always inherit the normal */
  }

  switch (data->type) {
  case GL_TRIANGLES: /* the easy case */
    /* add the vertex */
    data->p->v[data->vcnt] = v;

    if (++data->vcnt == 3) {
      /* add the polygon to *data->plistp */
      PolyListNode *new_pn;

      data->vcnt = 0;

      new_pn = new_poly_list_node(data->tagged_app, data->scratch);
      new_pn->poly = data->p;
      data->p = NULL;
      ListPush(*data->plistp, new_pn);
    }
    break;
  case GL_TRIANGLE_STRIP:
    /* pairs of triangles, all with the same orientation */
    if (data->vcnt > 2) {
      /* create a new polygon */
      data->p = new_poly(3, NULL, data->scratch);
      data->p->flags |= data->polyflags;
      if (data->polyflags & FACET_C) {
	data->p->pcol = data->trickyp->pcol;
      }
      data->p->pn = *data->pn; /* always inherit the normal */
      
      data->p->v[0] = data->v[0];
      data->p->v[1] = data->v[1];
      /* add the vertex */
      data->p->v[2] = v;
    } else {
      /* add the vertex */
      data->p->v[data->vcnt] = v;
    }

    if (++data->vcnt > 2) {
      /* add the polygon to *data->plistp */
      PolyListNode *new_pn;

      if (data->vcnt & 1) {
	data->v[0] = data->p->v[2];
	data->v[1] = data->p->v[1];
      } else {
	data->v[0] = data->p->v[0];
	data->v[1] = data->p->v[2];
      }
      new_pn = new_poly_list_node(data->tagged_app, data->scratch);
      new_pn->poly = data->p;
      ListPush(*data->plistp, new_pn);
    }
    break;
  case GL_TRIANGLE_FAN:
    if (data->vcnt > 2) {
      /* create a new polygon */
      data->p = new_poly(3, NULL, data->scratch);
      data->p->flags |= data->polyflags;
      if (data->polyflags & FACET_C) {
	data->p->pcol = data->trickyp->pcol;
      }
      data->p->pn = *data->pn; /* always inherit the normal */
      
      data->p->v[0] = data->v[0];
      data->p->v[1] = data->v[1];
      /* add the vertex */
      data->p->v[2] = v;
    } else {
      if (data->vcnt == 0) {
	data->v[0] = v;
      }
      data->p->v[data->vcnt] = v;
    }

    if (++data->vcnt > 2) {
      /* add the polygon to *data->plistp */
      PolyListNode *new_pn;

      data->v[1] = data->p->v[2];
      new_pn = new_poly_list_node(data->tagged_app, data->scratch);
      new_pn->poly = data->p;
      ListPush(*data->plistp, new_pn);
    }
    break;
  default:
    break;
  }
}
示例#7
0
/* Convert a Mesh into linked list of PolyListNodes, subdivide
 * non-flat or concave quadrilaterals.
 */
static PolyListNode *
MeshToLinkedPolyList(Transform T, Transform Tdual, Transform TxT,
		     const void **tagged_app, PolyListNode **plistp,
		     Mesh *mesh, struct obstack *scratch)
{
  PolyListNode *plist = NULL;
  Poly *qpoly;
  int v0 = 1, prev0v = 0;
  int u0 = 1, prev0u = 0;
  int u, v, prevu, prevv;
  int concave;
  int i;

  if (!plistp) {
    plistp = &plist;
  }

  MeshComputeNormals(mesh, MESH_N);

  if(mesh->geomflags & MESH_UWRAP) {
    v0 = 0, prev0v = mesh->nv-1;
  }
  if(mesh->geomflags & MESH_VWRAP) {
    u0 = 0, prev0u = mesh->nu-1;
  }

#define MESHIDX(u, v, mesh) ((v)*(mesh)->nu + (u))
  qpoly = NULL;
  for(prevv = prev0v, v = v0; v < mesh->nv; prevv = v, v++) {
    for(prevu = prev0u, u = u0; u < mesh->nu; prevu = u, u++) {
      /* First try to create a single polygon, if that mesh-cell is
       * non-flat or concave, then sub-divide it.
       */
      if (!qpoly) {
	qpoly = new_poly(4, NULL, scratch);
	for (i = 0; i < 4; i++) {
	  qpoly->v[i] = obstack_alloc(scratch, sizeof(Vertex));
	}
      }
      if (T && T != TM_IDENTITY) {
	meshv_to_polyv_trans(T, Tdual, TxT, qpoly->v[0], mesh,
			     MESHIDX(prevu, prevv, mesh));
	meshv_to_polyv_trans(T, Tdual, TxT, qpoly->v[1], mesh,
			     MESHIDX(u, prevv, mesh));
	meshv_to_polyv_trans(T, Tdual, TxT, qpoly->v[2], mesh,
			     MESHIDX(u, v, mesh));
	meshv_to_polyv_trans(T, Tdual, TxT, qpoly->v[3], mesh,
			     MESHIDX(prevu, v, mesh));
      } else {
	meshv_to_polyv(qpoly->v[0], mesh, MESHIDX(prevu, prevv, mesh));
	meshv_to_polyv(qpoly->v[1], mesh, MESHIDX(u, prevv, mesh));
	meshv_to_polyv(qpoly->v[2], mesh, MESHIDX(u, v, mesh));
	meshv_to_polyv(qpoly->v[3], mesh, MESHIDX(prevu, v, mesh));
      }

      if (mesh->geomflags & MESH_C) {
	qpoly->flags |= PL_HASVCOL;
      }
      if (mesh->geomflags & COLOR_ALPHA) {
	qpoly->flags |= COLOR_ALPHA;
      }
      if (mesh->geomflags & MESH_N) {
	qpoly->flags |= PL_HASVN;
      }
      if (mesh->geomflags & MESH_U) {
	qpoly->flags |= PL_HASST;
      }

      PolyNormal(qpoly, &qpoly->pn, mesh->geomflags & VERT_4D, false,
		 &qpoly->flags, &concave);
      qpoly->flags |= PL_HASPN;
      if (qpoly->flags & POLY_NOPOLY) {
	/* polygon is degenerated, we just do NOT draw it, edges are
	 * drawn by other methods. Just do nothing, qpoly will be
	 * re-used for the next quad.
	 */
	qpoly->flags = 0;
      } else if (qpoly->flags & (POLY_CONCAVE|POLY_NONFLAT)) {
	/* we need to split it */
	split_quad_poly(concave, qpoly, plistp, tagged_app, scratch);
	qpoly = NULL;
      } else {
	PolyListNode *new_pn;
	
	new_pn = new_poly_list_node(tagged_app, scratch);
	new_pn->poly = qpoly;
	ListPush(*plistp, new_pn);
	qpoly = NULL;
      }
    }
  }

#undef MESHIDX
  
  return *plistp;
}
示例#8
0
static PolyListNode *
QuadToLinkedPolyList(Transform T, Transform Tdual, Transform TxT,
		     const void **tagged_app, PolyListNode **plistp,
		     Quad *quad, struct obstack *scratch)
{
  PolyListNode *plist = NULL;
  Poly *qpoly;
  int i, j, concave;

  (void)Tdual;
  (void)TxT;

  if (!plistp) {
    plistp = &plist;
  }

  if(!(quad->geomflags & QUAD_N)) {
    QuadComputeNormals(quad);
  }
  
  qpoly = NULL;
  for (i = 0; i < quad->maxquad; i++) {
    /* First try to create a single polygon, if that mesh-cell is
     * non-flat or concave, then sub-divide it.
     */
    if (!qpoly) {
      qpoly = new_poly(4, NULL, scratch);
      for (j = 0; j < 4; j++) {
	qpoly->v[j] = obstack_alloc(scratch, sizeof(Vertex));
      }
    }
    if (T && T != TM_IDENTITY) {
      for (j = 0; j < 4; j++) {
	memset(qpoly->v[j], 0, sizeof(Vertex));
	HPt3Transform(T, &quad->p[i][j], &qpoly->v[j]->pt);
	NormalTransform(T, &quad->n[i][j], &qpoly->v[j]->vn);
      }
    } else {
      for (j = 0; j < 4; j++) {
	memset(qpoly->v[j], 0, sizeof(Vertex));
	qpoly->v[j]->pt   = quad->p[i][j];
	qpoly->v[j]->vn   = quad->n[i][j];
      }
    }
    qpoly->flags |= PL_HASVN;
    if (quad->geomflags & QUAD_C) {
      qpoly->flags |= PL_HASVCOL;
      for (j = 0; j < 4; j++) {
	qpoly->v[j]->vcol = quad->c[i][j];
      }
    }
    if (quad->geomflags & COLOR_ALPHA) {
      qpoly->flags |= COLOR_ALPHA;
    }
    PolyNormal(qpoly, &qpoly->pn,
	       quad->geomflags & VERT_4D, false, &qpoly->flags, &concave);
    qpoly->flags |= PL_HASPN;
    if (qpoly->flags & POLY_NOPOLY) {
      /* degenerated, skip it, but reuse the memory region.  */
      qpoly->flags = 0;
    } else if (qpoly->flags & (POLY_CONCAVE|POLY_NONFLAT)) {
      /* we need to split it */
      split_quad_poly(concave, qpoly, plistp, tagged_app, scratch);
      qpoly = NULL;
    } else {
      PolyListNode *new_pn;
      
      new_pn = new_poly_list_node(tagged_app, scratch);
      new_pn->poly = qpoly;
      ListPush(*plistp, new_pn);
      qpoly = NULL;
    }
  }
  
  return *plistp;
}
示例#9
0
/* Split plnode along plane. We know that plane really intersects
 * plnode->poly. We also know that plnode->poly is planar and convex.
 *
 * Given this assumptions we know that plnode->poly has to be split
 * into exactly two pieces. 
 */
static inline void SplitPolyNode(PolyListNode *plnode,
				 PolyListNode **front, PolyListNode **back,
				 EdgeIntersection edges[2],
				 struct obstack *scratch)
{
  const void **tagged_app = plnode->tagged_app;
  Poly *poly = plnode->poly, savedp;
  VARARRAY(savedv, Vertex *, poly->n_vertices);
  Vertex *v0, *v1, **vpos;
  int istart[2], iend[2], i, nv[2];
  Vertex *vstart[2], *vend[2];

#if BSPTREE_STATS
  ++n_tree_polys;
#endif

  vstart[0] = vstart[1] = vend[0] = vend[1] = NULL;
  istart[0] = istart[1] = iend[0] = iend[1] = -1;

  /* first point of intersection */
  if (fzero(edges[0].scp[0])) {
    v0 = poly->v[edges[0].v[0]];
    if (fpos(edges[0].scp[1])) {
      istart[0] = edges[0].v[0];
      iend[1]   = edges[0].v[0];
    } else {
      istart[1] = edges[0].v[0];
      iend[0]   = edges[0].v[0]; 
    }
  } else if (fzero(edges[0].scp[1])) {
    v0 = poly->v[edges[0].v[1]];
    if (fpos(edges[0].scp[0])) {
      istart[1] = edges[0].v[1];
      iend[0]   = edges[0].v[1];
    } else {
      istart[0] = edges[0].v[1];
      iend[1]   = edges[0].v[1]; 
    }
  } else {
    HPt3Coord mu0, mu1;
    Vertex *V0 = poly->v[edges[0].v[0]];
    Vertex *V1 = poly->v[edges[0].v[1]];
    
    v0 = obstack_alloc(scratch, sizeof(Vertex));
    mu0 = edges[0].scp[1]/(edges[0].scp[1]-edges[0].scp[0]);
#if 0
    mu1 = edges[0].scp[0]/(edges[0].scp[0]-edges[0].scp[1]);
#else
    mu1 = 1.0 - mu0;
#endif
    /* Use denormalized variant; otherwise textures may come out wrong
     * because the homogeneous divisor is used for perspective
     * corrections.
     */
    if (poly->flags & VERT_ST) {
      v0->st.s = mu0 * V0->st.s + mu1 * V1->st.s;
      v0->st.t = mu0 * V0->st.t + mu1 * V1->st.t;
      HPt3LinSumDenorm(mu0, &V0->pt, mu1, &V1->pt, &v0->pt);
    } else {
      HPt3LinSum(mu0, &V0->pt, mu1, &V1->pt, &v0->pt);
    } 
    if (!finite(v0->pt.x + v0->pt.y + v0->pt.z)){
      abort();
    }
    if (poly->flags & VERT_C) {
      CoLinSum(mu0, &V0->vcol, mu1, &V1->vcol, &v0->vcol);
    }
    if (true || (poly->flags & VERT_N)) {
      /* The averaged vertex normals do not have an orientation, so
       * try to orient them w.r.t. the polygon normal before computing
       * the linear combination.
       */
      if (Pt3Dot(&V0->vn, &poly->pn)*Pt3Dot(&V1->vn, &poly->pn) < 0) {
	Pt3Comb(-mu0, &V0->vn, mu1, &V1->vn, &v0->vn);
      } else {
	Pt3Comb(mu0, &V0->vn, mu1, &V1->vn, &v0->vn);
      }
      Pt3Unit(&v0->vn);
    }

    if (fpos(edges[0].scp[0])) {
      vstart[1] = vend[0] = v0;
      istart[1] = edges[0].v[1];
      iend[0]   = edges[0].v[0];
    } else {
      vstart[0] = vend[1] = v0;
      istart[0] = edges[0].v[1];
      iend[1]   = edges[0].v[0];
    }
  }

  /* second point of intersection */
  if (fzero(edges[1].scp[0])) {
    v1 = poly->v[edges[1].v[0]];
    if (fpos(edges[1].scp[1])) {
      istart[0] = edges[1].v[0];
      iend[1]   = edges[1].v[0];
    } else {
      istart[1] = edges[1].v[0];
      iend[0]   = edges[1].v[0]; 
    }
  } else if (fzero(edges[1].scp[1])) {
    v1 = poly->v[edges[1].v[1]];
    if (fpos(edges[1].scp[0])) {
      istart[1] = edges[1].v[1];
      iend[0]   = edges[1].v[1];
    } else {
      istart[0] = edges[1].v[1];
      iend[1]   = edges[1].v[1]; 
    }
  } else {
    HPt3Coord mu0, mu1;
    Vertex *V0 = poly->v[edges[1].v[0]];
    Vertex *V1 = poly->v[edges[1].v[1]];
    
    v1 = obstack_alloc(scratch, sizeof(Vertex));
    mu0 = edges[1].scp[1]/(edges[1].scp[1]-edges[1].scp[0]);
#if 0
    mu1 = edges[1].scp[0]/(edges[1].scp[0]-edges[1].scp[1]);
#else
    mu1 = 1.0 - mu0;
#endif
    if (poly->flags & VERT_ST) {
      v1->st.s = mu0 * V0->st.s + mu1 * V1->st.s;
      v1->st.t = mu0 * V0->st.t + mu1 * V1->st.t;
      HPt3LinSumDenorm(mu0, &V0->pt, mu1, &V1->pt, &v1->pt);
    } else {
      HPt3LinSum(mu0, &V0->pt, mu1, &V1->pt, &v1->pt);
    }
    if (!finite(v1->pt.x + v1->pt.y + v1->pt.z))
      abort();
    if (poly->flags & VERT_C) {
      CoLinSum(mu0, &V0->vcol, mu1, &V1->vcol, &v1->vcol);
    }
    if (true || (poly->flags & VERT_N)) {
      if (Pt3Dot(&V0->vn, &poly->pn)*Pt3Dot(&V1->vn, &poly->pn) < 0) {
	Pt3Comb(-mu0, &V0->vn, mu1, &V1->vn, &v1->vn);
      } else {
	Pt3Comb(mu0, &V0->vn, mu1, &V1->vn, &v1->vn);
      }
      Pt3Unit(&v1->vn);
    }

    if (fpos(edges[1].scp[0])) {
      vstart[1] = vend[0] = v1;
      istart[1] = edges[1].v[1];
      iend[0]   = edges[1].v[0];
    } else {
      vstart[0] = vend[1] = v1;
      istart[0] = edges[1].v[1];
      iend[1]   = edges[1].v[0];
    }
  }

  ListPush(*front, plnode);
  ListPush(*back, new_poly_list_node(tagged_app, scratch));

  if ((poly->flags & POLY_NONFLAT)) {
    if (!(*front)->pn) {
      /* Compute the normal on the parent element to avoid numerical
       * instabilities on increasingly degenerated polygons.
       */
      (*front)->pn = obstack_alloc(scratch, sizeof(Point3));
      PolyNormal(poly, (*front)->pn,
		 true /* 4d */, false /* evert */, NULL, NULL);
    }
    (*back)->pn = (*front)->pn;
  }

  for (i = 0; i < 2; i++) {
    nv[i] = iend[i] - istart[i] + 1;
    if (nv[i] < 0) {
      nv[i] += poly->n_vertices;
    }
    nv[i] += (vstart[i] != NULL) + (vend[i] != NULL);
  }

  if (poly->flags & POLY_SCRATCH) {

    savedp = *poly;
    memcpy(savedv, poly->v, poly->n_vertices*sizeof(Vertex *));

    if (nv[0] <= poly->n_vertices) {
      poly->n_vertices = nv[0];
      (*front)->poly = poly;
      (*back)->poly  = new_poly(nv[1], NULL, scratch);
    } else {
      if (nv[1] > poly->n_vertices) {
	abort();
      }
      poly->n_vertices = nv[1];
      (*back)->poly = poly;
      (*front)->poly  = new_poly(nv[0], NULL, scratch);
    }
    
    /* Attention: gcc had problems with this code snippet with
     * -fstrict-aliasing, the "#if 1" stuff seems to work. In the
     * "#else" version gcc somehow lost the "savedp.v = savedv"
     * assignment. I think this is a compiler bug.
     */
    poly = &savedp;
#if 1
    poly->v = savedv;
#else
    savedp.v = savedv;
#endif
  } else {
    (*front)->poly  = new_poly(nv[0], NULL, scratch);
    (*back)->poly  = new_poly(nv[1], NULL, scratch);
  }

  for (i = 0; i < 2; i++) {
    PolyListNode *half = (i == 0) ? *front : *back;
    int j;

    vpos = half->poly->v;
    if (vstart[i] != NULL) {
      *vpos++ = vstart[i];
    }
    if (istart[i] <= iend[i]) {
      for (j = istart[i]; j <= iend[i] && j < poly->n_vertices; j++) {
	*vpos++ = poly->v[j];
      }
    } else {
      for (j = istart[i]; j < poly->n_vertices; j++) {
	*vpos++ = poly->v[j];
      }
      for (j = 0; j <= iend[i]; j++) {
	*vpos++ = poly->v[j];
      }
    }
    if (vend[i] != NULL) {
      *vpos++ = vend[i];
    }
    half->poly->pcol  = poly->pcol;
    half->poly->pn    = poly->pn;
    half->poly->flags = poly->flags|POLY_SCRATCH;

    check_poly(half->poly);
  }
}