Пример #1
0
void QuadDice::add_grid(SubPatch& sub, int Mu, int Mv, int offset)
{
	/* create inner grid */
	float du = 1.0f/(float)Mu;
	float dv = 1.0f/(float)Mv;

	for(int j = 1; j < Mv; j++) {
		for(int i = 1; i < Mu; i++) {
			float u = i*du;
			float v = j*dv;

			add_vert(sub, u, v);

			if(i < Mu-1 && j < Mv-1) {
				int i1 = offset + 4 + (i-1) + (j-1)*(Mu-1);
				int i2 = offset + 4 + i + (j-1)*(Mu-1);
				int i3 = offset + 4 + i + j*(Mu-1);
				int i4 = offset + 4 + (i-1) + j*(Mu-1);

				add_triangle(i1, i2, i3);
				add_triangle(i1, i3, i4);
			}
		}
	}
}
Пример #2
0
void plane(float length, float width, Vertex *res_vertices, Index *res_indices, D3DCOLOR color)
{
    Index vertex = 0; // current vertex
    DWORD index = 0; // current index
    _ASSERT(PLANE_STEPS_PER_HALF_SIDE != 0);

    const float x_step = length/(2*PLANE_STEPS_PER_HALF_SIDE);
    const float y_step = width/(2*PLANE_STEPS_PER_HALF_SIDE);
    const Index vertices_in_line = (2*PLANE_STEPS_PER_HALF_SIDE + 1);
    D3DXVECTOR3 normal(0, 0, 1);

    for( int i = -PLANE_STEPS_PER_HALF_SIDE; i <= PLANE_STEPS_PER_HALF_SIDE; ++i )
    {
        for( int j = -PLANE_STEPS_PER_HALF_SIDE; j <= PLANE_STEPS_PER_HALF_SIDE; ++j )
        {
            res_vertices[vertex] = Vertex( D3DXVECTOR3( x_step*i, y_step*j, 0), color, normal);
            if( i != -PLANE_STEPS_PER_HALF_SIDE && j != -PLANE_STEPS_PER_HALF_SIDE)
            {
                // if not first line and column
                add_triangle(vertex, vertex-1, vertex-1-vertices_in_line, res_indices, index);
                add_triangle(vertex, vertex-1-vertices_in_line, vertex-vertices_in_line, res_indices, index);
            }
            ++vertex;
        }
    }
}
Пример #3
0
void MeshBuilder::add_quad(const Math::Vector3<float>& pt1,
                           const Math::Vector3<float>& pt2,
                           const Math::Vector3<float>& pt3,
                           const Math::Vector3<float>& pt4)
{
    add_triangle(pt1, pt2, pt3);
    add_triangle(pt3, pt4, pt1);
}
Пример #4
0
static	void	get_object_from_file(char *path,
				     t_object **o, t_object *parent)
{
  t_face		*f;
  t_vertice       	*v;
  t_vertice_n     	*vn;
  double		pt[3][3];
  double		n[3];

  f = NULL;
  v = NULL;
  vn = NULL;
  get_coord(path, &v, &vn, &f);
  my_rev_list(&v);
  my_rev_n(&vn);
  my_rev_f(&f);
  while (f)
    {
      if (copy_tab(pt[0], get_itm(v, vn, 1, f->pos[0])) &&
	  copy_tab(pt[1], get_itm(v, vn, 1, f->pos[1])) &&
	  copy_tab(pt[2], get_itm(v, vn, 1, f->pos[2])) &&
	  copy_tab(n, get_itm(v, vn, 0, f->n)))
	add_triangle(o, pt, n, parent);
      f = f->next;
    }
}
Пример #5
0
v3dmc_object load_object(GLchar *filename){
	FILE *file;
	GLint i,npoints,nlines,ntriangles,nquads;
	v3dmc_object obj = object();
	v3dmc_point p;
	v3dmc_line l;
	v3dmc_triangle t;
	v3dmc_quad q;
	file = fopen(filename,"r");
	if(file!=NULL){
		fread(&npoints,sizeof(int),1,file);
		fread(&nlines,sizeof(int),1,file);
		fread(&ntriangles,sizeof(int),1,file);
		fread(&nquads,sizeof(int),1,file);
		for(i=0;i<npoints;i++){
			read_point(file,&p);
			add_point(&obj,p);
		}
		for(i=0;i<nlines;i++){
			fread(&l,sizeof(v3dmc_line),1,file);
			add_line(&obj,l);
		}
		for(i=0;i<ntriangles;i++){
			fread(&t,sizeof(v3dmc_triangle),1,file);
			add_triangle(&obj,t);
		}
		for(i=0;i<nquads;i++){
			fread(&q,sizeof(v3dmc_quad),1,file);
			add_quad(&obj,q);
		}
		fclose(file);
	}
	return obj;
}
Пример #6
0
void LightCaster::compute_light_mesh(Mesh* result, Walls* walls, const Vector_& light) {
  long nwalls = walls->nwalls();
  angle = restrict_angle(angle);

  WallPoint* wall_points = (WallPoint*)GIGGLE->renderer->alloc(sizeof(WallPoint) * nwalls * 2);
  Wall** open_set = (Wall**)GIGGLE->renderer->alloc(sizeof(Wall*) * nwalls);
  long nopen_set = 0;

  for(long ii = 0; ii < nwalls; ++ii) {
    Wall* wall = &walls->walls[ii];
    float angle_start = atan2f(wall->start.y - light.y, wall->start.x - light.x);
    float angle_end = atan2f(wall->end.y - light.y, wall->end.x - light.x);

    float dangle = restrict_angle(angle_end - angle_start);

    long idx1 = 2*ii;
    long idx2 = idx1 + 1;
    wall_points[idx1].point = &wall->start;
    wall_points[idx1].wall = wall;
    wall_points[idx1].angle = angle_start;
    wall_points[idx1].begin = dangle > 0;

    wall_points[idx2].point = &wall->end;
    wall_points[idx2].wall = wall;
    wall_points[idx2].angle = angle_end;
    wall_points[idx2].begin = !wall_points[idx1].begin;
  }

  std::sort(wall_points, wall_points + (nwalls*2), WallPointCompare());

  float beginAngle = 0;

  for(int kk = 0; kk < 2; ++kk) {
    for(long ii = 0; ii < nwalls * 2; ++ii) {
      WallPoint* wp = &wall_points[ii];
      Wall* last_closest = (nopen_set == 0) ? NULL : open_set[0];
      if(wp->begin) {
        add_wall(open_set, &nopen_set, wp->wall, &light);
      } else {
        remove_wall(open_set, &nopen_set, wp->wall);
      }

      Wall* next_closest = (nopen_set == 0) ? NULL : open_set[0];
      if(last_closest != next_closest) {
        float nextAngle = wp->angle;

        if(last_closest) {
          if(kk == 1) {
            add_triangle(result, light, last_closest, beginAngle, nextAngle);
          }
          beginAngle = nextAngle;
        }
      }
    }
  }
}
Пример #7
0
void tessellate(const Vertex *src_vertices, const Index *src_indices, DWORD src_index_offset,
                Vertex *res_vertices, Index res_vertices_offset, Index *res_indices)
// Divides each side of triangle into given number of parts
// Writes data into arrays given as `res_vertices' and `res_indices',
//   assuming that there are already `res_vertices_offset' vertices before `res_vertices' pointer.
{
    _ASSERT(src_vertices != NULL);
    _ASSERT(src_indices != NULL);
    _ASSERT(res_vertices != NULL);
    _ASSERT(res_indices != NULL);
    // i1, i2 i3 are indices of source triangle vertices
    const Index i1 = src_indices[src_index_offset];
    const Index i2 = src_indices[src_index_offset + 1];
    const Index i3 = src_indices[src_index_offset + 2];
    const D3DXVECTOR3 step_down = (src_vertices[i1].pos - src_vertices[i2].pos)/TESSELATE_DEGREE;
    const D3DXVECTOR3 step_right = (src_vertices[i3].pos - src_vertices[i1].pos)/TESSELATE_DEGREE;

    res_vertices[0] = src_vertices[i2];
    Index vertex = 1; // current vertex
    DWORD index = 0; // current index
    
    D3DXVECTOR3 start_pos = res_vertices[0].pos;
    for( Index line = 1; line <= TESSELATE_DEGREE; ++line )
    {
        for( Index column = 0; column < line + 1; ++column ) // line #1 contains 2 vertices
        {
            res_vertices[vertex] = Vertex( start_pos
                                         + static_cast<FLOAT>(line)*step_down
                                         + static_cast<FLOAT>(column)*step_right );
            if( column != 0 ) // not first coumn
            {
                // add outer triangle
                add_triangle( vertex, vertex - 1, vertex - line - 1, res_indices, index, res_vertices_offset );
            }
            if( ( column != 0 ) && ( column != line ) ) // not first and not last column
            {
                // add inner triangle
                add_triangle(  vertex, vertex - line - 1, vertex - line, res_indices, index, res_vertices_offset );
            }
            ++vertex;
        }
    }
}
Пример #8
0
void MeshBuilder::add_triangles()
{
    while (_queue.size() >= 3) {
        MeshNode* n1 = _queue.front();
        _queue.pop_front();
        MeshNode* n2 = _queue.front();
        _queue.pop_front();
        MeshNode* n3 = _queue.front();
        _queue.pop_front();

        add_triangle(n1, n2, n3);
    }
}
Пример #9
0
void EdgeDice::stitch_triangles(vector<int>& outer, vector<int>& inner)
{
	if(inner.size() == 0 || outer.size() == 0)
		return; // XXX avoid crashes for Mu or Mv == 1, missing polygons

	/* stitch together two arrays of verts with triangles. at each step,
	   we compare using the next verts on both sides, to find the split
	   direction with the smallest diagonal, and use that in order to keep
	   the triangle shape reasonable. */
	for(size_t i = 0, j = 0; i+1 < inner.size() || j+1 < outer.size();) {
		int v0, v1, v2;

		v0 = inner[i];
		v1 = outer[j];

		if(j+1 == outer.size()) {
			v2 = inner[++i];
		}
		else if(i+1 == inner.size()) {
			v2 = outer[++j];
		}
		else {
			/* length of diagonals */
			float len1 = len(mesh_P[inner[i]] - mesh_P[outer[j+1]]);
			float len2 = len(mesh_P[outer[j]] - mesh_P[inner[i+1]]);

			/* use smallest diagonal */
			if(len1 < len2)
				v2 = outer[++j];
			else
				v2 = inner[++i];
		}

		add_triangle(v0, v1, v2);
	}
}
Пример #10
0
void Vectorizer::process_triangle(int iv0, int iv1, int iv2, int level,
                                  scalar* xval, scalar* yval, double* phx, double* phy, int* idx)
{
  if (level < LIN_MAX_LEVEL)
  {
    int i;
    if (!(level & 1))
    {
      // obtain solution values and physical element coordinates
      xsln->set_quad_order(1, xitem);
      ysln->set_quad_order(1, yitem);
      xval = xsln->get_values(xia, xib);
      yval = ysln->get_values(yia, yib);
      for (i = 0; i < lin_np_tri[1]; i++) {
        double m = getmag(i);
        if (finite(m) && fabs(m) > max) max = fabs(m);
      }

      if (curved)
      {
        RefMap* refmap = xsln->get_refmap();
        phx = refmap->get_phys_x(1);
        phy = refmap->get_phys_y(1);
      }
      idx = tri_indices[0];
    }

    // obtain linearized values and coordinates at the midpoints
    double midval[4][3];
    for (i = 0; i < 4; i++)
    {
      midval[i][0] = (verts[iv0][i] + verts[iv1][i])*0.5;
      midval[i][1] = (verts[iv1][i] + verts[iv2][i])*0.5;
      midval[i][2] = (verts[iv2][i] + verts[iv0][i])*0.5;
    };

    // determine whether or not to split the element
    bool split;
    if (eps >= 1.0)
    {
      //if eps > 1, the user wants a fixed number of refinements (no adaptivity)
      split = (level < eps);
    }
    else
    {
      // calculate the approximate error of linearizing the normalized solution
      double err = fabs(getmag(idx[0]) - midmag(0)) +
                   fabs(getmag(idx[1]) - midmag(1)) +
                   fabs(getmag(idx[2]) - midmag(2));
      split = !finite(err) || err > max*3*eps;

      // do the same for the curvature
      if (curved && !split)
      {
        double cerr = 0.0, cden = 0.0; // fixme
        for (i = 0; i < 3; i++)
        {
          cerr += fabs(phx[idx[i]] - midval[0][i]) + fabs(phy[idx[i]] - midval[1][i]);
          cden += fabs(phx[idx[i]]) + fabs(phy[idx[i]]);
        }
        split = (cerr > cden*2.5e-4);
      }

      // do extra tests at level 0, so as not to miss some functions with zero error at edge midpoints
      if (level == 0 && !split)
      {
        split = (fabs(getmag(8) - 0.5*(midmag(0) + midmag(1))) +
                 fabs(getmag(9) - 0.5*(midmag(1) + midmag(2))) +
                 fabs(getmag(4) - 0.5*(midmag(2) + midmag(0)))) > max*3*eps;
      }
    }

    // split the triangle if the error is too large, otherwise produce a linear triangle
    if (split)
    {
      if (curved)
        for (i = 0; i < 3; i++) {
          midval[0][i] = phx[idx[i]];
          midval[1][i] = phy[idx[i]];
        }

      // obtain mid-edge vertices
      int mid0 = get_vertex(iv0, iv1, midval[0][0], midval[1][0], getvalx(idx[0]), getvaly(idx[0]));
      int mid1 = get_vertex(iv1, iv2, midval[0][1], midval[1][1], getvalx(idx[1]), getvaly(idx[1]));
      int mid2 = get_vertex(iv2, iv0, midval[0][2], midval[1][2], getvalx(idx[2]), getvaly(idx[2]));

      // recur to sub-elements
      push_transform(0);  process_triangle(iv0, mid0, mid2,  level+1, xval, yval, phx, phy, tri_indices[1]);  pop_transform();
      push_transform(1);  process_triangle(mid0, iv1, mid1,  level+1, xval, yval, phx, phy, tri_indices[2]);  pop_transform();
      push_transform(2);  process_triangle(mid2, mid1, iv2,  level+1, xval, yval, phx, phy, tri_indices[3]);  pop_transform();
      push_transform(3);  process_triangle(mid1, mid2, mid0, level+1, xval, yval, phx, phy, tri_indices[4]);  pop_transform();
      return;
    }
  }

  // no splitting: output a linear triangle
  add_triangle(iv0, iv1, iv2);
}
Пример #11
0
void MeshBuilder::add_triangle(const Math::Vector3<float>& pt1,
                               const Math::Vector3<float>& pt2,
                               const Math::Vector3<float>& pt3)
{
    add_triangle(add_vertex(pt1), add_vertex(pt2), add_vertex(pt3));
}
Пример #12
0
void MeshBuilder::add_quad(MeshNode* n1, MeshNode* n2,
                           MeshNode* n3, MeshNode* n4)
{
    add_triangle(n1, n2, n3);
    add_triangle(n3, n4, n1);
}
Пример #13
0
      void Linearizer::process_quad(MeshFunction<double>** fns, int iv0, int iv1, int iv2, int iv3, int level,
        double* val, double* phx, double* phy, int* idx, bool curved)
      {
        double midval[3][5];

        // try not to split through the vertex with the largest value
        int a = (verts[iv0][2] > verts[iv1][2]) ? iv0 : iv1;
        int b = (verts[iv2][2] > verts[iv3][2]) ? iv2 : iv3;
        a = (verts[a][2] > verts[b][2]) ? a : b;
        int flip = (a == iv1 || a == iv3) ? 1 : 0;

        if(level < LinearizerBase::get_max_level(fns[0]->get_active_element(), fns[0]->get_fn_order(), fns[0]->get_mesh()))
        {
          int i;
          if(!(level & 1)) // this is an optimization: do the following only every other time
          {
            // obtain solution values
            fns[0]->set_quad_order(1, item);
            val = fns[0]->get_values(component, value_type);
            if(auto_max)
              for (i = 0; i < lin_np_quad[1]; i++)
              {
                double v = val[i];
                if(finite(v) && fabs(v) > max)
#pragma omp critical(max)
                  if(finite(v) && fabs(v) > max)
                    max = fabs(v);
              }

              // This is just to make some sense.
              if(fabs(max) < Hermes::HermesSqrtEpsilon)
                max = Hermes::HermesSqrtEpsilon;

              idx = quad_indices[0];

              if(curved)
              {
                RefMap* refmap = fns[0]->get_refmap();
                phx = refmap->get_phys_x(1);
                phy = refmap->get_phys_y(1);

                double* dx = nullptr;
                double* dy = nullptr;

                if(this->xdisp != nullptr)
                  fns[1]->set_quad_order(1, H2D_FN_VAL);
                if(this->ydisp != nullptr)
                  fns[this->xdisp == nullptr ? 1 : 2]->set_quad_order(1, H2D_FN_VAL);
                if(this->xdisp != nullptr)
                  dx = fns[1]->get_fn_values();
                if(this->ydisp != nullptr)
                  dy = fns[this->xdisp == nullptr ? 1 : 2]->get_fn_values();
                for (i = 0; i < lin_np_quad[1]; i++)
                {
                  if(this->xdisp != nullptr)
                    phx[i] += dmult*dx[i];
                  if(this->ydisp != nullptr)
                    phy[i] += dmult*dy[i];
                }
              }
          }

          // obtain linearized values and coordinates at the midpoints
          for (i = 0; i < 3; i++)
          {
            midval[i][0] = (verts[iv0][i] + verts[iv1][i]) * 0.5;
            midval[i][1] = (verts[iv1][i] + verts[iv2][i]) * 0.5;
            midval[i][2] = (verts[iv2][i] + verts[iv3][i]) * 0.5;
            midval[i][3] = (verts[iv3][i] + verts[iv0][i]) * 0.5;
            midval[i][4] = (midval[i][0]  + midval[i][2])  * 0.5;
          };

          // the value of the middle point is not the average of the four vertex values, since quad == 2 triangles
          midval[2][4] = flip ? (verts[iv0][2] + verts[iv2][2]) * 0.5 : (verts[iv1][2] + verts[iv3][2]) * 0.5;

          // determine whether or not to split the element
          int split;
          if(eps >= 1.0)
          {
            // if eps > 1, the user wants a fixed number of refinements (no adaptivity)
            split = (level < eps) ? 3 : 0;
          }
          else
          {
            if(!auto_max && fabs(verts[iv0][2]) > max && fabs(verts[iv1][2]) > max
              && fabs(verts[iv2][2]) > max && fabs(verts[iv3][2]) > max)
            {
              // do not split if the whole quad is above the specified maximum value
              split = 0;
            }
            else
            {
              // calculate the approximate error of linearizing the normalized solution
              double herr = fabs(val[idx[1]] - midval[2][1]) + fabs(val[idx[3]] - midval[2][3]);
              double verr = fabs(val[idx[0]] - midval[2][0]) + fabs(val[idx[2]] - midval[2][2]);
              double err  = fabs(val[idx[4]] - midval[2][4]) + herr + verr;
              split = (!finite(err) || err > max*4*eps) ? 3 : 0;

              // decide whether to split horizontally or vertically only
              if(level > 0 && split)
              {
                if(herr > 5*verr)
                  split = 1; // h-split
                else if(verr > 5*herr)
                  split = 2; // v-split
              }
            }

            // also decide whether to split because of the curvature
            if(split != 3 && curved)
            {
              double cm2 = sqr(fns[0]->get_active_element()->get_diameter()*this->get_curvature_epsilon());
              if(sqr(phx[idx[1]] - midval[0][1]) + sqr(phy[idx[1]] - midval[1][1]) > cm2 ||
                sqr(phx[idx[3]] - midval[0][3]) + sqr(phy[idx[3]] - midval[1][3]) > cm2) split |= 1;
              if(sqr(phx[idx[0]] - midval[0][0]) + sqr(phy[idx[0]] - midval[1][0]) > cm2 ||
                sqr(phx[idx[2]] - midval[0][2]) + sqr(phy[idx[2]] - midval[1][2]) > cm2) split |= 2;
            }

            // do extra tests at level 0, so as not to miss some functions with zero error at edge midpoints
            if(level == 0 && !split)
            {
              split = ((fabs(val[13] - 0.5*(midval[2][0] + midval[2][1])) +
                fabs(val[17] - 0.5*(midval[2][1] + midval[2][2])) +
                fabs(val[20] - 0.5*(midval[2][2] + midval[2][3])) +
                fabs(val[9]  - 0.5*(midval[2][3] + midval[2][0]))) > max*4*eps) ? 3 : 0;
            }
          }

          // split the quad if the error is too large, otherwise produce two linear triangles
          if(split)
          {
            if(curved)
              for (i = 0; i < 5; i++)
              {
                midval[0][i] = phx[idx[i]];
                midval[1][i] = phy[idx[i]];
              }

              // obtain mid-edge and mid-element vertices
              int mid0, mid1, mid2, mid3, mid4;
              if(split != 1) mid0 = get_vertex(iv0,  iv1,  midval[0][0], midval[1][0], val[idx[0]]);
              if(split != 2) mid1 = get_vertex(iv1,  iv2,  midval[0][1], midval[1][1], val[idx[1]]);
              if(split != 1) mid2 = get_vertex(iv2,  iv3,  midval[0][2], midval[1][2], val[idx[2]]);
              if(split != 2) mid3 = get_vertex(iv3,  iv0,  midval[0][3], midval[1][3], val[idx[3]]);
              if(split == 3) mid4 = get_vertex(mid0, mid2, midval[0][4], midval[1][4], val[idx[4]]);

              if(!this->exceptionMessageCaughtInParallelBlock.empty())
                return;

              // recur to sub-elements
              if(split == 3)
              {
                this->push_transforms(fns, 0);
                process_quad(fns, iv0, mid0, mid4, mid3, level + 1, val, phx, phy, quad_indices[1], curved);
                this->pop_transforms(fns);

                this->push_transforms(fns, 1);
                process_quad(fns, mid0, iv1, mid1, mid4, level + 1, val, phx, phy, quad_indices[2], curved);
                this->pop_transforms(fns);

                this->push_transforms(fns, 2);
                process_quad(fns, mid4, mid1, iv2, mid2, level + 1, val, phx, phy, quad_indices[3], curved);
                this->pop_transforms(fns);

                this->push_transforms(fns, 3);
                process_quad(fns, mid3, mid4, mid2, iv3, level + 1, val, phx, phy, quad_indices[4], curved);
                this->pop_transforms(fns);
              }
              else
                if(split == 1) // h-split
                {
                  this->push_transforms(fns, 4);
                  process_quad(fns, iv0, iv1, mid1, mid3, level + 1, val, phx, phy, quad_indices[5], curved);
                  this->pop_transforms(fns);

                  this->push_transforms(fns, 5);
                  process_quad(fns, mid3, mid1, iv2, iv3, level + 1, val, phx, phy, quad_indices[6], curved);
                  this->pop_transforms(fns);
                }
                else // v-split
                {
                  this->push_transforms(fns, 6);
                  process_quad(fns, iv0, mid0, mid2, iv3, level + 1, val, phx, phy, quad_indices[7], curved);
                  this->pop_transforms(fns);

                  this->push_transforms(fns, 7);
                  process_quad(fns, mid0, iv1, iv2, mid2, level + 1, val, phx, phy, quad_indices[8], curved);
                  this->pop_transforms(fns);
                }
                return;
          }
        }

        // output two linear triangles,
        if(!flip)
        {
          add_triangle(iv3, iv0, iv1, fns[0]->get_active_element()->marker);
          add_triangle(iv1, iv2, iv3, fns[0]->get_active_element()->marker);
        }
        else
        {
          add_triangle(iv0, iv1, iv2, fns[0]->get_active_element()->marker);
          add_triangle(iv2, iv3, iv0, fns[0]->get_active_element()->marker);
        }
      }
Пример #14
0
DANI_INLINE
uint EpsTrimesh::split_edge(const uint eid, const vec3d point, std::vector<double> &radius, std::vector<vec3d> &centers, std::vector<vec3d> &antipodeans)
{
#ifdef CINOLIB

    uint e0 = edge_vertex_id(eid, 0);
    uint e1 = edge_vertex_id(eid, 1);

    uint vid = add_vertex(point);

    std::vector<int> rem_tris = adj_edg2tri(eid);

    for (uint tt : rem_tris)
    {
        uint opp_vid = vertex_opposite_to(tt, e0, e1);
        uint off_opp_vid = triangle_vertex_global_to_local(tt, opp_vid);

        uint t0 = add_triangle(vid, opp_vid, triangle_vertex_id(tt, (off_opp_vid+1) %3));
        uint t1 = add_triangle(vid, triangle_vertex_id(tt, (off_opp_vid+2) %3), opp_vid);

        radius.push_back(radius.at(tt));
        radius.push_back(radius.at(tt));

        centers.push_back(centers.at(tt));
        centers.push_back(centers.at(tt));

        antipodeans.push_back(antipodeans.at(tt));
        antipodeans.push_back(antipodeans.at(tt));
    }

    std::sort (rem_tris.begin(), rem_tris.end());
    std::reverse (rem_tris.begin(), rem_tris.end());

    for (uint tt : rem_tris)
    {
        tris.at(tt*3+0) = INT_MAX;
        tris.at(tt*3+1) = INT_MAX;
        tris.at(tt*3+2) = INT_MAX;

        remove_unreferenced_triangle(tt);

        std::swap(radius.at(radius.size()-1), radius.at(tt));
        radius.pop_back();

        std::swap(antipodeans.at(antipodeans.size()-1), antipodeans.at(tt));
        antipodeans.pop_back();

        std::swap(centers.at(centers.size()-1), centers.at(tt));
        centers.pop_back();
    }

    edges.at(eid*2+0) = INT_MAX;
    edges.at(eid*2+1) = INT_MAX;

    remove_unreferenced_edge(eid);

    update_adjacency();

    return vid;
#else

    std::cerr << "[ERROR] Cinolib required to run this operation." << std::endl;
    exit(1);

#endif
}
Пример #15
0
void SurfTrack::defrag_mesh( )
{
    
    std::vector<Vec2st> old_edges = m_mesh.m_edges;
    
    PostDefragInfo info;
    info.m_defragged_vertex_map.clear();
    
    //
    // First clear deleted vertices from the data stuctures
    // 
    
    // do a quick pass through to see if any vertices have been deleted
    bool any_deleted = false;
    for ( size_t i = 0; i < get_num_vertices(); ++i )
    {  
        if ( m_mesh.vertex_is_deleted(i) )
        {
            any_deleted = true;
            break;
        }
    }    
    
    if ( !any_deleted )
    {
        for ( size_t i = 0; i < get_num_vertices(); ++i )
        {
            info.m_defragged_vertex_map.push_back( Vec2st(i,i) );
        }
    }
    else
    {
        
        // Note: We could rebuild the mesh from scratch, rather than adding/removing 
        // triangles, however this function is not a major computational bottleneck.
        
        size_t j = 0;
        
        std::vector<Vec3st> new_tris = m_mesh.get_triangles();
        
        for ( size_t i = 0; i < get_num_vertices(); ++i )
        {      
            if ( !m_mesh.vertex_is_deleted(i) )
            {
                pm_positions[j] = pm_positions[i];
                pm_newpositions[j] = pm_newpositions[i];
                m_masses[j] = m_masses[i];
                
                info.m_defragged_vertex_map.push_back( Vec2st(i,j) );
                
                // Now rewire the triangles containting vertex i
                
                // copy this, since we'll be changing the original as we go
                std::vector<size_t> inc_tris = m_mesh.m_vertex_to_triangle_map[i];
                
                for ( size_t t = 0; t < inc_tris.size(); ++t )
                {
                    Vec3st triangle = m_mesh.get_triangle( inc_tris[t] );
                    
                    assert( triangle[0] == i || triangle[1] == i || triangle[2] == i );
                    if ( triangle[0] == i ) { triangle[0] = j; }
                    if ( triangle[1] == i ) { triangle[1] = j; }
                    if ( triangle[2] == i ) { triangle[2] = j; }        
                    
                    remove_triangle(inc_tris[t]);       // mark the triangle deleted
                    add_triangle(triangle);             // add the updated triangle
                }
                
                ++j;
            }
        }
        
        pm_positions.resize(j);
        pm_newpositions.resize(j);
        m_masses.resize(j);
    }
    
    //
    // Now clear deleted triangles from the mesh
    // 
    
    m_mesh.set_num_vertices( get_num_vertices() );    
    m_mesh.clear_deleted_triangles( &info.m_defragged_triangle_map );
        
    
    //
    // Update data carried on the edges
    //
    
    info.m_defragged_edge_map.clear();
    info.m_defragged_edge_map.resize( old_edges.size(), UNINITIALIZED_SIZE_T );
    
    // First update the set of edges to point to new vertex indices
    
    for ( size_t i = 0; i < old_edges.size(); ++i )
    {
        for ( int v = 0; v < 2; ++v )
        {
            const size_t old_v = old_edges[i][v];
            size_t new_v = old_v;
            
            for ( size_t j = 0; j < info.m_defragged_vertex_map.size(); ++j )
            {
                if ( info.m_defragged_vertex_map[j][0] == old_v )
                {
                    new_v = info.m_defragged_vertex_map[j][1];
                    assert( !m_mesh.vertex_is_deleted(new_v) );
                    break;
                }
            }
            
            old_edges[i][v] = new_v;
        }      
    }
    
    // Now use this modified set of edges to find where the edge data maps to
    
    for ( unsigned int i = 0; i < old_edges.size(); ++i )
    {
        if ( old_edges[i][0] == old_edges[i][1] ) 
        { 
            continue; 
        }
        
        size_t new_edge_index = m_mesh.get_edge_index( old_edges[i][0], old_edges[i][1] );
        
        // This edge has disappeared from the mesh.  This can occur when trimming non-manifold flaps.
        if ( new_edge_index == m_mesh.m_edges.size() )
        {
            continue;
        }
         
        info.m_defragged_edge_map[i] = new_edge_index;
        
        assert( new_edge_index < m_mesh.m_edges.size() );         
        
        // If the internal storage of the edge flipped, flip it back to original
        
        if ( old_edges[i][0] != m_mesh.m_edges[new_edge_index][0] )
        {
            assert( old_edges[i][1] == m_mesh.m_edges[new_edge_index][0] );
            assert( old_edges[i][0] == m_mesh.m_edges[new_edge_index][1] );
            
            swap( m_mesh.m_edges[new_edge_index][0], m_mesh.m_edges[new_edge_index][1] ); 
            
            assert( old_edges[i][0] == m_mesh.m_edges[new_edge_index][0] );
            assert( old_edges[i][1] == m_mesh.m_edges[new_edge_index][1] );
        }
    }
    
    
    for ( size_t i = 0; i < m_observers.size(); ++i )
    {
        m_observers[i]->operationOccurred(*this, info);
    }
    
    if ( m_collision_safety )
    {
        rebuild_continuous_broad_phase();
    }

}
Пример #16
0
 void LinearizerBase::regularize_triangle(int iv0, int iv1, int iv2, int mid0, int mid1, int mid2, int marker)
 {
   // count the number of hanging mid-edge vertices
   int n = 0;
   if(mid0 >= 0) n++;
   if(mid1 >= 0) n++;
   if(mid2 >= 0) n++;
   if(n == 3)
   {
     // three hanging vertices: split into four triangles
     regularize_triangle(iv0, mid0, mid2, peek_vertex(iv0, mid0), -1, peek_vertex(mid2, iv0), marker);
     regularize_triangle(mid0, iv1, mid1, peek_vertex(mid0, iv1), peek_vertex(iv1, mid1), -1, marker);
     regularize_triangle(mid2, mid1, iv2, -1, peek_vertex(mid1, iv2), peek_vertex(iv2, mid2), marker);
     regularize_triangle(mid0, mid1, mid2, -1, -1, -1, marker);
   }
   else if(n == 2)
   {
     // two hanging vertices: split into three triangles
     if(mid0 < 0)
     {
       regularize_triangle(iv0, iv1, mid1, peek_vertex(iv0, iv1), peek_vertex(iv1, mid1), -1, marker);
       regularize_triangle(mid2, iv0, mid1, peek_vertex(mid2, iv0), -1, -1, marker);
       regularize_triangle(mid2, mid1, iv2, -1, peek_vertex(mid1, iv2), peek_vertex(iv2, mid2), marker);
     }
     else if(mid1 < 0)
     {
       regularize_triangle(iv1, iv2, mid2, peek_vertex(iv1, iv2), peek_vertex(iv2, mid2), -1, marker);
       regularize_triangle(mid0, iv1, mid2, peek_vertex(mid0, iv1), -1, -1, marker);
       regularize_triangle(mid0, mid2, iv0, -1, peek_vertex(mid2, iv0), peek_vertex(iv0, mid0), marker);
     }
     else
     {
       regularize_triangle(iv2, iv0, mid0, peek_vertex(iv2, iv0), peek_vertex(iv0, mid0), -1, marker);
       regularize_triangle(mid1, iv2, mid0, peek_vertex(mid1, iv2), -1, -1, marker);
       regularize_triangle(mid1, mid0, iv1, -1, peek_vertex(mid0, iv1), peek_vertex(iv1, mid1), marker);
     }
   }
   else if(n == 1)
   {
     // one hanging vertex: split into two triangles
     if(mid0 >= 0)
     {
       regularize_triangle(iv0, mid0, iv2, peek_vertex(iv0, mid0), -1, peek_vertex(iv2, iv0), marker);
       regularize_triangle(mid0, iv1, iv2, peek_vertex(mid0, iv1), peek_vertex(iv1, iv2), -1, marker);
     }
     else if(mid1 >= 0)
     {
       regularize_triangle(iv1, mid1, iv0, peek_vertex(iv1, mid1), -1, peek_vertex(iv0, iv1), marker);
       regularize_triangle(mid1, iv2, iv0, peek_vertex(mid1, iv2), peek_vertex(iv2, iv0), -1, marker);
     }
     else
     {
       regularize_triangle(iv2, mid2, iv1, peek_vertex(iv2, mid2), -1, peek_vertex(iv1, iv2), marker);
       regularize_triangle(mid2, iv0, iv1, peek_vertex(mid2, iv0), peek_vertex(iv0, iv1), -1, marker);
     }
   }
   else
   {
     // no hanging vertices: produce a single triangle
     add_triangle(iv0, iv1, iv2, marker);
   }
 }
Пример #17
0
void Orderizer::process_solution(Space* space)
{
  // sanity check
  if (space == NULL) error("Space is NULL in Orderizer:process_solution().");

  if (!space->is_up_to_date())
    error("The space is not up to date.");

  int type = 1;

  nv = nt = ne = nl = 0;
  del_slot = -1;

  // estimate the required number of vertices and triangles
  Mesh* mesh = space->get_mesh();
  if (mesh == NULL) {
    error("Mesh is NULL in Orderizer:process_solution().");
  }
  int nn = mesh->get_num_active_elements();
  int ev = 77 * nn, et = 64 * nn, ee = 16 * nn, el = nn + 10;

  // reuse or allocate vertex, triangle and edge arrays
  lin_init_array(verts, double3, cv, ev);
  lin_init_array(tris, int3, ct, et);
  lin_init_array(edges, int3, ce, ee);
  lin_init_array(lvert, int, cl1, el);
  lin_init_array(ltext, char*, cl2, el);
  lin_init_array(lbox, double2, cl3, el);
  info = NULL;

  int oo, o[6];

  RefMap refmap;
  refmap.set_quad_2d(&quad_ord);

  // make a mesh illustrating the distribution of polynomial orders over the space
  Element* e;
  for_all_active_elements(e, mesh)
  {
    oo = o[4] = o[5] = space->get_element_order(e->id);
    for (unsigned int k = 0; k < e->nvert; k++)
      o[k] = space->get_edge_order(e, k);

    refmap.set_active_element(e);
    double* x = refmap.get_phys_x(type);
    double* y = refmap.get_phys_y(type);

    double3* pt = quad_ord.get_points(type);
    int np = quad_ord.get_num_points(type);
    int id[80];
    assert(np <= 80);

    #define make_vert(index, x, y, val) \
      { (index) = add_vertex(); \
      verts[index][0] = (x); \
      verts[index][1] = (y); \
      verts[index][2] = (val); }

    int mode = e->get_mode();
    if (e->is_quad())
    {
      o[4] = H2D_GET_H_ORDER(oo);
      o[5] = H2D_GET_V_ORDER(oo);
    }
    make_vert(lvert[nl], x[0], y[0], o[4]);

    for (int i = 1; i < np; i++)
      make_vert(id[i-1], x[i], y[i], o[(int) pt[i][2]]);

    for (int i = 0; i < num_elem[mode][type]; i++)
      add_triangle(id[ord_elem[mode][type][i][0]], id[ord_elem[mode][type][i][1]], id[ord_elem[mode][type][i][2]]);

    for (int i = 0; i < num_edge[mode][type]; i++)
    {
      if (e->en[ord_edge[mode][type][i][2]]->bnd || (y[ord_edge[mode][type][i][0] + 1] < y[ord_edge[mode][type][i][1] + 1]) ||
          ((y[ord_edge[mode][type][i][0] + 1] == y[ord_edge[mode][type][i][1] + 1]) &&
           (x[ord_edge[mode][type][i][0] + 1] <  x[ord_edge[mode][type][i][1] + 1])))
      {
        add_edge(id[ord_edge[mode][type][i][0]], id[ord_edge[mode][type][i][1]], 0);
      }
    }

    double xmin = 1e100, ymin = 1e100, xmax = -1e100, ymax = -1e100;
    for (unsigned int k = 0; k < e->nvert; k++)
    {
      if (e->vn[k]->x < xmin) xmin = e->vn[k]->x;
      if (e->vn[k]->x > xmax) xmax = e->vn[k]->x;
      if (e->vn[k]->y < ymin) ymin = e->vn[k]->y;
      if (e->vn[k]->y > ymax) ymax = e->vn[k]->y;
    }
    lbox[nl][0] = xmax - xmin;
    lbox[nl][1] = ymax - ymin;
    ltext[nl++] = labels[o[4]][o[5]];
  }
Пример #18
0
void Vectorizer::process_quad(int iv0, int iv1, int iv2, int iv3, int level,
                              scalar* xval, scalar* yval, double* phx, double* phy, int* idx)
{
  // try not to split through the vertex with the largest value
  int a = (magvert(iv0) > magvert(iv1)) ? iv0 : iv1;
  int b = (magvert(iv2) > magvert(iv3)) ? iv2 : iv3;
  a = (magvert(a) > magvert(b)) ? a : b;

  int flip = (a == iv1 || a == iv3) ? 1 : 0;

  if (level < LIN_MAX_LEVEL)
  {
    int i;
    if (!(level & 1))
    {
      // obtain solution values and physical element coordinates
      xsln->set_quad_order(1, xitem);
      ysln->set_quad_order(1, yitem);
      xval = xsln->get_values(xia, xib);
      yval = ysln->get_values(yia, yib);
      for (i = 0; i < lin_np_quad[1]; i++) {
        double m = getmag(i);
        if (finite(m) && fabs(m) > max) max = fabs(m);
      }

      if (curved)
      {
        RefMap* refmap = xsln->get_refmap();
        phx = refmap->get_phys_x(1);
        phy = refmap->get_phys_y(1);
      }
      idx = quad_indices[0];
    }

    // obtain linearized values and coordinates at the midpoints
    double midval[4][5];
    for (i = 0; i < 4; i++)
    {
      midval[i][0] = (verts[iv0][i] + verts[iv1][i]) * 0.5;
      midval[i][1] = (verts[iv1][i] + verts[iv2][i]) * 0.5;
      midval[i][2] = (verts[iv2][i] + verts[iv3][i]) * 0.5;
      midval[i][3] = (verts[iv3][i] + verts[iv0][i]) * 0.5;
      midval[i][4] = (midval[i][0]  + midval[i][2])  * 0.5;
    };

    // determine whether or not to split the element
    bool split;
    if (eps >= 1.0)
    {
      //if eps > 1, the user wants a fixed number of refinements (no adaptivity)
      split = (level < eps);
    }

    else
    {
      // the value of the middle point is not the average of the four vertex values, since quad == 2 triangles
      midval[2][4] = flip ? (verts[iv0][2] + verts[iv2][2]) * 0.5 : (verts[iv1][2] + verts[iv3][2]) * 0.5;
      midval[3][4] = flip ? (verts[iv0][3] + verts[iv2][3]) * 0.5 : (verts[iv1][3] + verts[iv3][3]) * 0.5;

      // calculate the approximate error of linearizing the normalized solution
      double err = fabs(getmag(idx[0]) - midmag(0)) +
                   fabs(getmag(idx[1]) - midmag(1)) +
                   fabs(getmag(idx[2]) - midmag(2)) +
                   fabs(getmag(idx[3]) - midmag(3)) +
                   fabs(getmag(idx[4]) - midmag(4));
      split = !finite(err) || err > max*4*eps;

      // do the same for the curvature
      if (curved && !split)
      {
        double cerr = 0.0, cden = 0.0; // fixme
        for (i = 0; i < 5; i++)
        {
          cerr += fabs(phx[idx[i]] - midval[0][i]) + fabs(phy[idx[i]] - midval[1][i]);
          cden += fabs(phx[idx[i]]) + fabs(phy[idx[i]]);
        }
        split = (cerr > cden*2.5e-4);
      }

      // do extra tests at level 0, so as not to miss functions with zero error at edge midpoints
      if (level == 0 && !split)
      {
        err = fabs(getmag(13) - 0.5*(midmag(0) + midmag(1))) +
              fabs(getmag(17) - 0.5*(midmag(1) + midmag(2))) +
              fabs(getmag(20) - 0.5*(midmag(2) + midmag(3))) +
              fabs(getmag(9)  - 0.5*(midmag(3) + midmag(0)));
        split = !finite(err) || (err) > max*2*eps; //?
      }
    }

    // split the quad if the error is too large, otherwise produce two linear triangles
    if (split)
    {
      if (curved)
        for (i = 0; i < 5; i++) {
          midval[0][i] = phx[idx[i]];
          midval[1][i] = phy[idx[i]];
        }

      // obtain mid-edge and mid-element vertices
      int mid0 = get_vertex(iv0,  iv1,  midval[0][0], midval[1][0], getvalx(idx[0]), getvaly(idx[0]));
      int mid1 = get_vertex(iv1,  iv2,  midval[0][1], midval[1][1], getvalx(idx[1]), getvaly(idx[1]));
      int mid2 = get_vertex(iv2,  iv3,  midval[0][2], midval[1][2], getvalx(idx[2]), getvaly(idx[2]));
      int mid3 = get_vertex(iv3,  iv0,  midval[0][3], midval[1][3], getvalx(idx[3]), getvaly(idx[3]));
      int mid4 = get_vertex(mid0, mid2, midval[0][4], midval[1][4], getvalx(idx[4]), getvaly(idx[4]));

      // recur to sub-elements
      push_transform(0);  process_quad(iv0, mid0, mid4, mid3, level+1, xval, yval, phx, phy, quad_indices[1]);  pop_transform();
      push_transform(1);  process_quad(mid0, iv1, mid1, mid4, level+1, xval, yval, phx, phy, quad_indices[2]);  pop_transform();
      push_transform(2);  process_quad(mid4, mid1, iv2, mid2, level+1, xval, yval, phx, phy, quad_indices[3]);  pop_transform();
      push_transform(3);  process_quad(mid3, mid4, mid2, iv3, level+1, xval, yval, phx, phy, quad_indices[4]);  pop_transform();
      return;
    }
  }

  // output two linear triangles,
  if (!flip)
  {
    add_triangle(iv3, iv0, iv1);
    add_triangle(iv1, iv2, iv3);
  }
  else
  {
    add_triangle(iv0, iv1, iv2);
    add_triangle(iv2, iv3, iv0);
  }
}
Пример #19
0
/**
 * @brief EpsTrimesh::split_triangle
 * @param tid
 * @param point
 * @return
 */
DANI_INLINE
uint EpsTrimesh::split_triangle(const uint tid, const vec3d point, std::vector<double> &radius, std::vector<vec3d> &centers, std::vector<vec3d> &antipodeans)
{

#ifdef CINOLIB

    uint nt = num_triangles();

    uint vid = add_vertex(point);

    double r = radius.at(tid);
    vec3d a = antipodeans.at(tid);
    vec3d c = centers.at(tid);

    uint v0 = triangle_vertex_id(tid, 0);
    uint v1 = triangle_vertex_id(tid, 1);
    uint v2 = triangle_vertex_id(tid, 2);

    uint t0 = add_triangle(vid, v2, v0);
    uint t1 = add_triangle(vid, v0, v1);
    uint t2 = add_triangle(vid, v1, v2);

    radius.resize(num_triangles());
    centers.resize(num_triangles());
    antipodeans.resize(num_triangles());

    radius.at(t0) = FLT_MAX;
    radius.at(t1) = FLT_MAX;
    radius.at(t2) = FLT_MAX;

    centers.at(t0) = {FLT_MAX};
    centers.at(t1) = {FLT_MAX};
    centers.at(t2) = {FLT_MAX};

    antipodeans.at(t0) = {FLT_MAX};
    antipodeans.at(t1) = {FLT_MAX};
    antipodeans.at(t2) = {FLT_MAX};

    tris.at(tid*3+0) = INT_MAX;
    tris.at(tid*3+1) = INT_MAX;
    tris.at(tid*3+2) = INT_MAX;

    if (tid == num_triangles()-1)
    {
        tris.resize(tris.size()-3);
        t_norm.resize(t_norm.size()-3);
        t_label.resize(t_label.size()-1);
        tri2edg.pop_back();
        tri2tri.pop_back();

        radius.pop_back();
        antipodeans.pop_back();
        centers.pop_back();
    }
    else
    {
        remove_unreferenced_triangle(tid);

        std::swap(radius.at(radius.size()-1), radius.at(tid));
        radius.pop_back();

        std::swap(antipodeans.at(antipodeans.size()-1), antipodeans.at(tid));
        antipodeans.pop_back();

        std::swap(centers.at(centers.size()-1), centers.at(tid));
        centers.pop_back();
    }

    update_adjacency();


    assert (num_triangles() == nt+2);
    assert (radius.size() == nt+2);
    assert (centers.size() == nt+2);
    assert (antipodeans.size() == nt+2);

    return vid;

#else

    std::cerr << "[ERROR] Cinolib required to run this operation." << std::endl;
    exit(1);

#endif
}
Пример #20
0
void Linearizer::process_quad(int iv0, int iv1, int iv2, int iv3, int level,
                              scalar* val, double* phx, double* phy, int* idx)
{
  double midval[3][5];

  // try not to split through the vertex with the largest value
  int a = (verts[iv0][2] > verts[iv1][2]) ? iv0 : iv1;
  int b = (verts[iv2][2] > verts[iv3][2]) ? iv2 : iv3;
  a = (verts[a][2] > verts[b][2]) ? a : b;
  int flip = (a == iv1 || a == iv3) ? 1 : 0;

  if (level < LIN_MAX_LEVEL)
  {
    int i;
    if (!(level & 1)) // this is an optimization: do the following only every other time
    {
      // obtain solution values
      sln->set_quad_order(1, item);
      val = sln->get_values(ia, ib);
      if (auto_max)
        for (i = 0; i < lin_np_quad[1]; i++) {
          double v = getval(i);
          if (finite(v) && fabs(v) > max) max = fabs(v);
        }

      // obtain physical element coordinates
      if (curved || disp)
      {
        RefMap* refmap = sln->get_refmap();
        phx = refmap->get_phys_x(1);
        phy = refmap->get_phys_y(1);

        if (disp)
        {
          xdisp->force_transform(sln);
          ydisp->force_transform(sln);
          xdisp->set_quad_order(1, FN_VAL);
          ydisp->set_quad_order(1, FN_VAL);
          scalar* dx = xdisp->get_fn_values();
          scalar* dy = ydisp->get_fn_values();
          for (i = 0; i < lin_np_quad[1]; i++) {
            phx[i] += dmult*realpart(dx[i]);
            phy[i] += dmult*realpart(dy[i]);
          }
        }
      }
      idx = quad_indices[0];
    }

    // obtain linearized values and coordinates at the midpoints
    for (i = 0; i < 3; i++)
    {
      midval[i][0] = (verts[iv0][i] + verts[iv1][i]) * 0.5;
      midval[i][1] = (verts[iv1][i] + verts[iv2][i]) * 0.5;
      midval[i][2] = (verts[iv2][i] + verts[iv3][i]) * 0.5;
      midval[i][3] = (verts[iv3][i] + verts[iv0][i]) * 0.5;
      midval[i][4] = (midval[i][0]  + midval[i][2])  * 0.5;
    };

    // the value of the middle point is not the average of the four vertex values, since quad == 2 triangles
    midval[2][4] = flip ? (verts[iv0][2] + verts[iv2][2]) * 0.5 : (verts[iv1][2] + verts[iv3][2]) * 0.5;


    // determine whether or not to split the element
    int split;
    if (eps >= 1.0)
    {
      // if eps > 1, the user wants a fixed number of refinements (no adaptivity)
      split = (level < eps) ? 3 : 0;
    }
    else
    {
      if (!auto_max && fabs(verts[iv0][2]) > max && fabs(verts[iv1][2]) > max
                         && fabs(verts[iv2][2]) > max && fabs(verts[iv3][2]) > max)
      {
        // do not split if the whole quad is above the specified maximum value
        split = 0;
      }
      else
      {
        // calculate the approximate error of linearizing the normalized solution
        double herr = fabs(getval(idx[1]) - midval[2][1]) + fabs(getval(idx[3]) - midval[2][3]);
        double verr = fabs(getval(idx[0]) - midval[2][0]) + fabs(getval(idx[2]) - midval[2][2]);
        double err  = fabs(getval(idx[4]) - midval[2][4]) + herr + verr;
        split = (!finite(err) || err > max*4*eps) ? 3 : 0;

        // decide whether to split horizontally or vertically only
        if (level > 0 && split)
          if (herr > 5*verr)
            split = 1; // h-split
          else if (verr > 5*herr)
            split = 2; // v-split
      }

      // also decide whether to split because of the curvature
      if (split != 3 && (curved || disp))
      {
        double cm2 = sqr(cmax*5e-4);
        if (sqr(phx[idx[1]] - midval[0][1]) + sqr(phy[idx[1]] - midval[1][1]) > cm2 ||
            sqr(phx[idx[3]] - midval[0][3]) + sqr(phy[idx[3]] - midval[1][3]) > cm2) split |= 1;
        if (sqr(phx[idx[0]] - midval[0][0]) + sqr(phy[idx[0]] - midval[1][0]) > cm2 ||
            sqr(phx[idx[2]] - midval[0][2]) + sqr(phy[idx[2]] - midval[1][2]) > cm2) split |= 2;

        /*for (i = 0; i < 5; i++)
          if (sqr(phx[idx[i]] - midval[0][i]) + sqr(phy[idx[i]] - midval[1][i]) > sqr(cmax*1e-3))
            { split = 1; break; }*/
      }

      // do extra tests at level 0, so as not to miss some functions with zero error at edge midpoints
      if (level == 0 && !split)
      {
        split = ((fabs(getval(13) - 0.5*(midval[2][0] + midval[2][1])) +
                  fabs(getval(17) - 0.5*(midval[2][1] + midval[2][2])) +
                  fabs(getval(20) - 0.5*(midval[2][2] + midval[2][3])) +
                  fabs(getval(9)  - 0.5*(midval[2][3] + midval[2][0]))) > max*4*eps) ? 3 : 0;
      }
    }

    // split the quad if the error is too large, otherwise produce two linear triangles
    if (split)
    {
      if (curved || disp)
        for (i = 0; i < 5; i++) {
          midval[0][i] = phx[idx[i]];
          midval[1][i] = phy[idx[i]];
        }

      // obtain mid-edge and mid-element vertices
      int mid0, mid1, mid2, mid3, mid4;
      if (split != 1) mid0 = get_vertex(iv0,  iv1,  midval[0][0], midval[1][0], getval(idx[0]));
      if (split != 2) mid1 = get_vertex(iv1,  iv2,  midval[0][1], midval[1][1], getval(idx[1]));
      if (split != 1) mid2 = get_vertex(iv2,  iv3,  midval[0][2], midval[1][2], getval(idx[2]));
      if (split != 2) mid3 = get_vertex(iv3,  iv0,  midval[0][3], midval[1][3], getval(idx[3]));
      if (split == 3) mid4 = get_vertex(mid0, mid2, midval[0][4], midval[1][4], getval(idx[4]));

      // recur to sub-elements
      if (split == 3)
      {
        sln->push_transform(0);  process_quad(iv0, mid0, mid4, mid3, level+1, val, phx, phy, quad_indices[1]);  sln->pop_transform();
        sln->push_transform(1);  process_quad(mid0, iv1, mid1, mid4, level+1, val, phx, phy, quad_indices[2]);  sln->pop_transform();
        sln->push_transform(2);  process_quad(mid4, mid1, iv2, mid2, level+1, val, phx, phy, quad_indices[3]);  sln->pop_transform();
        sln->push_transform(3);  process_quad(mid3, mid4, mid2, iv3, level+1, val, phx, phy, quad_indices[4]);  sln->pop_transform();
      }
      else if (split == 1) // h-split
      {
        sln->push_transform(4);  process_quad(iv0, iv1, mid1, mid3, level+1, val, phx, phy, quad_indices[5]);  sln->pop_transform();
        sln->push_transform(5);  process_quad(mid3, mid1, iv2, iv3, level+1, val, phx, phy, quad_indices[6]);  sln->pop_transform();
      }
      else // v-split
      {
        sln->push_transform(6);  process_quad(iv0, mid0, mid2, iv3, level+1, val, phx, phy, quad_indices[7]);  sln->pop_transform();
        sln->push_transform(7);  process_quad(mid0, iv1, iv2, mid2, level+1, val, phx, phy, quad_indices[8]);  sln->pop_transform();
      }
      return;
    }
  }

  // output two linear triangles,
  if (!flip)
  {
    add_triangle(iv3, iv0, iv1);
    add_triangle(iv1, iv2, iv3);
  }
  else
  {
    add_triangle(iv0, iv1, iv2);
    add_triangle(iv2, iv3, iv0);
  }
}
Пример #21
0
void Linearizer::process_triangle(int iv0, int iv1, int iv2, int level,
                                  scalar* val, double* phx, double* phy, int* idx)
{
  double midval[3][3];

  if (level < LIN_MAX_LEVEL)
  {
    int i;
    if (!(level & 1))
    {
      // obtain solution values
      sln->set_quad_order(1, item);
      val = sln->get_values(ia, ib);
      if (auto_max)
        for (i = 0; i < lin_np_tri[1]; i++) {
          double v = getval(i);
          if (finite(v) && fabs(v) > max) max = fabs(v);
        }

      // obtain physical element coordinates
      if (curved || disp)
      {
        RefMap* refmap = sln->get_refmap();
        phx = refmap->get_phys_x(1);
        phy = refmap->get_phys_y(1);

        if (disp)
        {
          xdisp->force_transform(sln);
          ydisp->force_transform(sln);
          xdisp->set_quad_order(1, FN_VAL);
          ydisp->set_quad_order(1, FN_VAL);
          scalar* dx = xdisp->get_fn_values();
          scalar* dy = ydisp->get_fn_values();
          for (i = 0; i < lin_np_tri[1]; i++) {
            phx[i] += dmult*realpart(dx[i]);
            phy[i] += dmult*realpart(dy[i]);
          }
        }
      }
      idx = tri_indices[0];
    }

    // obtain linearized values and coordinates at the midpoints
    for (i = 0; i < 3; i++)
    {
      midval[i][0] = (verts[iv0][i] + verts[iv1][i])*0.5;
      midval[i][1] = (verts[iv1][i] + verts[iv2][i])*0.5;
      midval[i][2] = (verts[iv2][i] + verts[iv0][i])*0.5;
    };

    // determine whether or not to split the element
    bool split;
    if (eps >= 1.0)
    {
      // if eps > 1, the user wants a fixed number of refinements (no adaptivity)
      split = (level < eps);
    }
    else
    {
      if (!auto_max && fabs(verts[iv0][2]) > max && fabs(verts[iv1][2]) > max && fabs(verts[iv2][2]) > max)
      {
        // do not split if the whole triangle is above the specified maximum value
        split = false;
      }
      else
      {
        // calculate the approximate error of linearizing the normalized solution
        double err = fabs(getval(idx[0]) - midval[2][0]) +
                     fabs(getval(idx[1]) - midval[2][1]) +
                     fabs(getval(idx[2]) - midval[2][2]);
        split = !finite(err) || err > max*3*eps;
      }

      // do the same for the curvature
      if (!split && (curved || disp))
      {
        for (i = 0; i < 3; i++)
          if (sqr(phx[idx[i]] - midval[0][i]) + sqr(phy[idx[i]] - midval[1][i]) > sqr(cmax*1.5e-3))
            { split = true; break; }
      }

      // do extra tests at level 0, so as not to miss some functions with zero error at edge midpoints
      if (level == 0 && !split)
      {
        split = (fabs(getval(8) - 0.5*(midval[2][0] + midval[2][1])) +
                 fabs(getval(9) - 0.5*(midval[2][1] + midval[2][2])) +
                 fabs(getval(4) - 0.5*(midval[2][2] + midval[2][0]))) > max*3*eps;
      }
    }

    // split the triangle if the error is too large, otherwise produce a linear triangle
    if (split)
    {
      if (curved || disp)
        for (i = 0; i < 3; i++) {
          midval[0][i] = phx[idx[i]];
          midval[1][i] = phy[idx[i]];
        }

      // obtain mid-edge vertices
      int mid0 = get_vertex(iv0, iv1, midval[0][0], midval[1][0], getval(idx[0]));
      int mid1 = get_vertex(iv1, iv2, midval[0][1], midval[1][1], getval(idx[1]));
      int mid2 = get_vertex(iv2, iv0, midval[0][2], midval[1][2], getval(idx[2]));

      // recur to sub-elements
      sln->push_transform(0);  process_triangle(iv0, mid0, mid2,  level+1, val, phx, phy, tri_indices[1]);  sln->pop_transform();
      sln->push_transform(1);  process_triangle(mid0, iv1, mid1,  level+1, val, phx, phy, tri_indices[2]);  sln->pop_transform();
      sln->push_transform(2);  process_triangle(mid2, mid1, iv2,  level+1, val, phx, phy, tri_indices[3]);  sln->pop_transform();
      sln->push_transform(3);  process_triangle(mid1, mid2, mid0, level+1, val, phx, phy, tri_indices[4]);  sln->pop_transform();
      return;
    }
  }

  // no splitting: output a linear triangle
  add_triangle(iv0, iv1, iv2);
}
Пример #22
0
void TriangleDice::add_grid(SubPatch& sub, EdgeFactors& ef, int M)
{
	// XXX normals are flipped, why?

	/* grid is constructed starting from the outside edges, and adding
	   progressively smaller inner triangles that connected to the outer
	   one, until M = 1 or 2, the we fill up the last part. */
	vector<int> outer_u, outer_v, outer_w;
	int m;

	/* add outer corners vertices */
	{
		float2 p_u = make_float2(1.0f, 0.0f);
		float2 p_v = make_float2(0.0f, 1.0f);
		float2 p_w = make_float2(0.0f, 0.0f);

		int corner_u = add_vert(sub, p_u);
		int corner_v = add_vert(sub, p_v);
		int corner_w = add_vert(sub, p_w);

		outer_u.push_back(corner_v);
		outer_v.push_back(corner_w);
		outer_w.push_back(corner_u);

		for(int i = 1; i < ef.tu; i++)
			outer_u.push_back(add_vert(sub, interp(p_v, p_w, i/(float)ef.tu)));
		for(int i = 1; i < ef.tv; i++)
			outer_v.push_back(add_vert(sub, interp(p_w, p_u, i/(float)ef.tv)));
		for(int i = 1; i < ef.tw; i++)
			outer_w.push_back(add_vert(sub, interp(p_u, p_v, i/(float)ef.tw)));

		outer_u.push_back(corner_w);
		outer_v.push_back(corner_u);
		outer_w.push_back(corner_v);
	}

	for(m = M-2; m > 0; m -= 2) {
		vector<int> inner_u, inner_v, inner_w;

		float t = m/(float)M;
		float2 center = make_float2(1.0f/3.0f, 1.0f/3.0f);

		/* 3 corner vertices */
		float2 p_u = interp(center, make_float2(1.0f, 0.0f), t);
		float2 p_v = interp(center, make_float2(0.0f, 1.0f), t);
		float2 p_w = interp(center, make_float2(0.0f, 0.0f), t);

		int corner_u = add_vert(sub, p_u);
		int corner_v = add_vert(sub, p_v);
		int corner_w = add_vert(sub, p_w);

		/* construct array of vertex indices for each side */
		inner_u.push_back(corner_v);
		inner_v.push_back(corner_w);
		inner_w.push_back(corner_u);

		for(int i = 1; i < m; i++) {
			/* add vertices between corners */
			float t = i/(float)m;

			inner_u.push_back(add_vert(sub, interp(p_v, p_w, t)));
			inner_v.push_back(add_vert(sub, interp(p_w, p_u, t)));
			inner_w.push_back(add_vert(sub, interp(p_u, p_v, t)));
		}

		inner_u.push_back(corner_w);
		inner_v.push_back(corner_u);
		inner_w.push_back(corner_v);

		/* stitch together inner/outer with triangles */
		stitch_triangles(outer_u, inner_u);
		stitch_triangles(outer_v, inner_v);
		stitch_triangles(outer_w, inner_w);

		outer_u = inner_u;
		outer_v = inner_v;
		outer_w = inner_w;
	}

	/* fill up last part */
	if(m == -1) {
		/* single triangle */
		add_triangle(outer_w[0], outer_u[0], outer_v[0]);
	}
	else {
		/* center vertex + 6 triangles */
		int center = add_vert(sub, make_float2(1.0f/3.0f, 1.0f/3.0f));

		add_triangle(outer_w[0], outer_w[1], center);
		add_triangle(outer_w[1], outer_w[2], center);
		add_triangle(outer_u[0], outer_u[1], center);
		add_triangle(outer_u[1], outer_u[2], center);
		add_triangle(outer_v[0], outer_v[1], center);
		add_triangle(outer_v[1], outer_v[2], center);
	}
}
Пример #23
0
struct obj_info *
Part_import( int id_start )
{
    char line[MAX_LINE_SIZE];
    struct obj_info *part;
    struct wmember reg_head;
    unsigned char rgb[3];
    int surf_count=0;
    int id_end;
    int last_surf=0;
    int i;
    int tri[3];
    int corner_index=-1;

    clean_vert_tree( tree_root );

    VSETALL( rgb, 128 );

    BU_ALLOC(part, struct obj_info);
    part->obj_type = PART_TYPE;
    part->obj_id = id_start;
    while ( bu_fgets( line, MAX_LINE_SIZE, fd_in ) ) {
	if ( !bu_strncmp( line, "PartName", 8 ) ) {
	    line[strlen( line ) - 1] = '\0';
	    part->obj_name = bu_strdup( &line[9] );
	    lower_case( part->obj_name );
	    Make_brlcad_names( part );
	} else if ( !bu_strncmp( line, "FaceCount", 9 ) ) {
	    surf_count = atoi( &line[10] );
	    if ( surf_count == 0 ) {
		last_surf = 1;
	    }
	} else if ( !bu_strncmp( line, "EndPartId", 9 ) ) {
	    /* found end of part, check id */
	    id_end = atoi( &line[10] );
	    if ( id_end != id_start )
		bu_exit( 1, "%s: ERROR: found end of part id %d while processing part %d\n", progname,id_end, id_start );
	    if ( last_surf ) {
		break;
	    }
	} else if ( !bu_strncmp( line, "FaceRGB", 7 ) ) {
	    /* get face color */
	    char *ptr;

	    i = 8;
	    ptr = strtok( &line[i], " \t" );
	    for ( i=0; i<3 && ptr; i++ ) {
		rgb[i] = atof( ptr );
		ptr = strtok( (char *)NULL, " \t" );
	    }
	} else if ( !bu_strncmp( line, "Facet", 5 ) ) {
	    /* read a triangle */
	    VSETALL( tri, -1 );
	    corner_index = -1;
	} else if ( !bu_strncmp( line, "Face", 4 ) ) {
	    /* start of a surface */
	    int surf_no;

	    surf_no = atoi( &line[5] );
	    if ( surf_no == surf_count ) {
		last_surf = 1;
	    }
	} else if ( !bu_strncmp( line, "TriangleCount", 13 ) ) {
	    /* get number of triangles for this surface */
	} else if ( !bu_strncmp( line, "Vertices", 9 ) ) {
	    /* get vertex list for this triangle */
	} else if ( !bu_strncmp( line, "Vertex", 6 ) ) {
	    /* get a vertex */
	    char *ptr = NULL;
	    vect_t v = VINIT_ZERO;

	    i = 7;
	    while ( !isspace( (int)line[i] ) && line[i] != '\0' )
		i++;
	    ptr = strtok( &line[i], " \t" );
	    for ( i=0; i<3 && ptr; i++ ) {
		v[i] = atof( ptr );
		ptr = strtok( (char *)NULL, " \t" );
	    }
	    tri[++corner_index] = Add_vert( V3ARGS( v ), tree_root, local_tol_sq );
	    if ( corner_index == 2 ) {
		if ( !bad_triangle( tri, tree_root->the_array ) ) {
		    add_triangle( tri );
		}
	    }
	} else if ( !bu_strncmp( line, "Normal", 6 ) ) {
	    /* get a vertex normal */
	} else if ( !bu_strncmp( line, "PointCount", 10 ) ) {
	    /* get number of vertices for this surface */
	} else
	    bu_exit( 1, "%s: ERROR: unrecognized line encountered while processing part id %d:\n%s\n", progname,id_start, line );
    }

    if ( curr_tri == 0 ) {
	/* no facets in this part, so ignore it */
	bu_free( (char *)part, "part" );
	part = (struct obj_info *)NULL;
    } else {

	/* write this part to database, first make a primitive solid */
	if ( mk_bot( fd_out, part->brlcad_solid, RT_BOT_SOLID, RT_BOT_UNORIENTED, 0,
		     tree_root->curr_vert, curr_tri, tree_root->the_array, part_tris, NULL, NULL ) )
	    bu_exit( 1, "%s: Failed to write primitive %s (%s) to database\n", progname,part->brlcad_solid, part->obj_name );
	if ( verbose ) {
	    DO_INDENT;
	    bu_log( "Wrote BOT %s\n", part->brlcad_solid );
	}

	/* then a region */
	BU_LIST_INIT( &reg_head.l );
	if ( mk_addmember( part->brlcad_solid, &reg_head.l, NULL, WMOP_UNION ) == WMEMBER_NULL )
	    bu_exit( 1, "%s: ERROR: Failed to add solid (%s), to region (%s)\n", progname,part->brlcad_solid, part->brlcad_comb );
	if ( mk_comb( fd_out, part->brlcad_comb, &reg_head.l, 1, NULL, NULL, rgb, ident++,
		      0, 1, 100, 0, 0, 0 ) )
	    bu_exit( 1, "%s: Failed to write region %s (%s) to database\n", progname,part->brlcad_comb, part->obj_name );
	if ( verbose ) {
	    DO_INDENT;
	    bu_log( "Wrote region %s\n", part->brlcad_comb );
	}

	if ( use_part_name_hash ) {
	    if ( db5_update_attribute( part->brlcad_comb, "Part_No",
				       part->obj_name, fd_out->dbip ) ) {
		bu_log( "Failed to assign Part_no attribute to %s\n",
			part->brlcad_comb );
	    }
	}
    }

    /* free some memory */
    if ( part_tris ) {
	bu_free( (char *)part_tris, "part_tris" );
    }
    max_tri = 0;
    curr_tri = 0;
    part_tris = NULL;

    return part;
}
Пример #24
0
void SurfTrack::defrag_mesh( )
{
    
    //
    // First clear deleted vertices from the data stuctures
    // 
    
    double start_time = get_time_in_seconds();
    
    
    // do a quick pass through to see if any vertices have been deleted
    bool any_deleted = false;
    for ( size_t i = 0; i < get_num_vertices(); ++i )
    {  
        if ( m_mesh.vertex_is_deleted(i) )
        {
            any_deleted = true;
            break;
        }
    }    
    
    if ( !any_deleted )
    {
        for ( size_t i = 0; i < get_num_vertices(); ++i )
        {
            m_defragged_vertex_map.push_back( Vec2st(i,i) );
        }
        
        double end_time = get_time_in_seconds();      
        g_stats.add_to_double( "total_clear_deleted_vertices_time", end_time - start_time );
        
    }
    else
    {
        
        // Note: We could rebuild the mesh from scratch, rather than adding/removing 
        // triangles, however this function is not a major computational bottleneck.
        
        size_t j = 0;
        
        std::vector<Vec3st> new_tris = m_mesh.get_triangles();
        
        for ( size_t i = 0; i < get_num_vertices(); ++i )
        {      
            if ( !m_mesh.vertex_is_deleted(i) )
            {
                pm_positions[j] = pm_positions[i];
                pm_newpositions[j] = pm_newpositions[i];
                m_masses[j] = m_masses[i];
                
                m_defragged_vertex_map.push_back( Vec2st(i,j) );
                
                // Now rewire the triangles containting vertex i
                
                // copy this, since we'll be changing the original as we go
                std::vector<size_t> inc_tris = m_mesh.m_vertex_to_triangle_map[i];
                
                for ( size_t t = 0; t < inc_tris.size(); ++t )
                {
                    Vec3st triangle = m_mesh.get_triangle( inc_tris[t] );
                    
                    assert( triangle[0] == i || triangle[1] == i || triangle[2] == i );
                    if ( triangle[0] == i ) { triangle[0] = j; }
                    if ( triangle[1] == i ) { triangle[1] = j; }
                    if ( triangle[2] == i ) { triangle[2] = j; }        
                    
                    remove_triangle(inc_tris[t]);       // mark the triangle deleted
                    add_triangle(triangle);             // add the updated triangle
                }
                
                ++j;
            }
        }
        
        pm_positions.resize(j);
        pm_newpositions.resize(j);
        m_masses.resize(j);
    }
    
    double end_time = get_time_in_seconds();
    
    g_stats.add_to_double( "total_clear_deleted_vertices_time", end_time - start_time );
    
    
    //
    // Now clear deleted triangles from the mesh
    // 
    
    m_mesh.set_num_vertices( get_num_vertices() );    
    m_mesh.clear_deleted_triangles( &m_defragged_triangle_map );
    
    if ( m_collision_safety )
    {
        rebuild_continuous_broad_phase();
    }
    
}
Пример #25
0
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
cNodeKdtree* cKdtree::m_insert_rec(std::vector<cTriangle> &vet_tri,
                                   std::vector<VVector> &vet_vertex,
                                   std::vector<VVector> &vet_nor,
                                   int depth)
{
    cNodeKdtree *node = NULL;

    if(vet_tri.empty())
    {
        // ja eh uma folha
        return node;
    }

    if((int)vet_tri.size() == 1)
    {
        // vai ser a folha
        // insere no noh o indice do triangulo
        node = new cNodeKdtree();

        add_triangle(vet_vertex[vet_tri[0].m_v[0]],
                     vet_vertex[vet_tri[0].m_v[1]],
                     vet_vertex[vet_tri[0].m_v[2]],
                     m_data_tri,
                     m_data_vet,
                     m_data_nor);
        node->is_leaf = true;
        node->tri = (int) m_data_tri.size() - 1;

        return node;
    }

    std::vector<cTriangle> vet_tri_front;
    std::vector<VVector> vet_vertex_front, vet_nor_front;

    std::vector<cTriangle> vet_tri_back;
    std::vector<VVector> vet_vertex_back, vet_nor_back;

    // escolher o eixo e o valor do eixo
    int axis, axis_value;
    selected_plane_kdtree(vet_tri, vet_vertex, vet_nor, axis, axis_value, depth);

    printf("Axis: %d\tvalue: %d\n", axis, axis_value);

    VVector normal_plane, point;
    get_att(axis, axis_value, normal_plane, point);

    // cria o noh
    node = new cNodeKdtree();
    node->is_leaf = false;
    node->axis = axis;
    node->axis_value = axis_value;

    vet_tri_front.clear();
    vet_vertex_front.clear();
    vet_nor_front.clear();
    vet_tri_back.clear();
    vet_vertex_back.clear();
    vet_nor_back.clear();

    // separar os triangulos
    for(int i = 0; i < (int)vet_tri.size(); i++)
    {
        int side = calculate_side(normal_plane,
                                  point,
                                  vet_vertex[vet_tri[i].m_v[0]],
                                  vet_vertex[vet_tri[i].m_v[1]],
                                  vet_vertex[vet_tri[i].m_v[2]]);
        if(side == CUT)
        {
            cut_triangle(normal_plane,
                         point,
                         i,
                         vet_tri,
                         vet_vertex,
                         vet_nor,
                         vet_tri_front,
                         vet_vertex_front,
                         vet_nor_front,
                         vet_tri_back,
                         vet_vertex_back,
                         vet_nor_back);
        }
        else if(side == FRONT)
        {
            add_triangle(vet_vertex[vet_tri[i].m_v[0]],
                         vet_vertex[vet_tri[i].m_v[1]],
                         vet_vertex[vet_tri[i].m_v[2]],
                         vet_tri_front,
                         vet_vertex_front,
                         vet_nor_front);
        }
        else// if(side == BACK)
        {
            add_triangle(vet_vertex[vet_tri[i].m_v[0]],
                         vet_vertex[vet_tri[i].m_v[1]],
                         vet_vertex[vet_tri[i].m_v[2]],
                         vet_tri_back,
                         vet_vertex_back,
                         vet_nor_back);
        }

    }

    //vet_tri.clear(); vet_vertex.clear(); vet_nor.clear();

    node->front = m_insert_rec(vet_tri_front, vet_vertex_front, vet_nor_front, depth + 1);
    node->back = m_insert_rec(vet_tri_back, vet_vertex_back, vet_nor_back, depth + 1);

    //vet_tri_front.clear(); vet_vertex_front.clear(); vet_nor_front.clear();
    //vet_tri_back.clear(); vet_vertex_back.clear(); vet_nor_back.clear();

    return node;
}
Пример #26
0
struct model *load_obj_model(char *filename)
{
	char dirname[1024];
	char line[200];
	struct model *model;
	struct mesh *curmesh = NULL;
	int fvp[20], fvt[20], fvn[20];
	char *p, *s;
	int i, n;
	FILE *fp;

	strlcpy(dirname, filename, sizeof dirname);
	p = strrchr(dirname, '/');
	if (!p) p = strrchr(dirname, '\\');
	if (p) *p = 0;
	else strlcpy(dirname, ".", sizeof dirname);

	printf("loading obj model: %s\n", filename);

	fp = fopen(filename, "r");
	if (!fp) {
		fprintf(stderr, "error: cannot load model '%s'\n", filename);
		return NULL;
	}

	model = malloc(sizeof(struct model));
	memset(model, 0, sizeof(struct model));

	model->min[0] = model->min[1] = model->min[2] = 1e10;
	model->max[0] = model->max[1] = model->max[2] = -1e10;
	model->radius = 0;

	while (1) {
		if (!fgets(line, sizeof line, fp))
			break;

		s = strtok(line, SEP);
		if (!s) {
			continue;
		} else if (!strcmp(s, "v")) {
			char *x = strtok(NULL, SEP);
			char *y = strtok(NULL, SEP);
			char *z = strtok(NULL, SEP);
			add_position(model, atof(x), atof(y), atof(z));
		} else if (!strcmp(s, "vt")) {
			char *u = strtok(NULL, SEP);
			char *v = strtok(NULL, SEP);
			add_texcoord(model, atof(u), atof(v));
		} else if (!strcmp(s, "vn")) {
			char *x = strtok(NULL, SEP);
			char *y = strtok(NULL, SEP);
			char *z = strtok(NULL, SEP);
			add_normal(model, atof(x), atof(y), atof(z));
		} else if (!strcmp(s, "f")) {
			n = 0;
			s = strtok(NULL, SEP);
			while (s) {
				if (*s) {
					splitfv(s, fvp+n, fvt+n, fvn+n);
					n++;
				}
				s = strtok(NULL, SEP);
			}
			for (i = 1; i < n - 1; i++) {
				add_triangle(curmesh,
                     fvp[0], fvt[0], fvn[0],
                     fvp[i], fvt[i], fvn[i],
                     fvp[i+1], fvt[i+1], fvn[i+1]);
			}
		} else if (!strcmp(s, "mtllib")) {
			s = strtok(NULL, SEP);
			model->material = load_material(dirname, s);
		} else if (!strcmp(s, "usemtl")) {
			s = strtok(NULL, SEP);
			curmesh = find_mesh(model, s);
		}
	}

	model->radius = sqrtf(model->radius);

	fclose(fp);
	return model;
}
Пример #27
0
struct model *load_obj_from_memory(const char *filename, unsigned char *data, int len)
{
	char dirname[1024];
	char *line, *next, *p, *s;
	struct model *model;
	struct mesh *mesh;
	int fvp[20], fvt[20], fvn[20];
	int first, material;
	int i, n;

	printf("loading obj model '%s'\n", filename);

	strlcpy(dirname, filename, sizeof dirname);
	p = strrchr(dirname, '/');
	if (!p) p = strrchr(dirname, '\\');
	if (p) *p = 0;
	else strlcpy(dirname, "", sizeof dirname);

	mtl_count = 0;
	position.len = 0;
	texcoord.len = 0;
	normal.len = 0;
	element.len = 0;
	part.len = 0;

	first = 0;
	material = 0;

	data[len-1] = 0; /* over-write final newline to zero-terminate */

	for (line = (char*)data; line; line = next) {
		next = strchr(line, '\n');
		if (next)
			*next++ = 0;

		s = strtok(line, SEP);
		if (!s) {
			continue;
		} else if (!strcmp(s, "v")) {
			char *x = strtok(NULL, SEP);
			char *y = strtok(NULL, SEP);
			char *z = strtok(NULL, SEP);
			add_position(atof(x), atof(y), atof(z));
		} else if (!strcmp(s, "vt")) {
			char *u = strtok(NULL, SEP);
			char *v = strtok(NULL, SEP);
			add_texcoord(atof(u), atof(v));
		} else if (!strcmp(s, "vn")) {
			char *x = strtok(NULL, SEP);
			char *y = strtok(NULL, SEP);
			char *z = strtok(NULL, SEP);
			add_normal(atof(x), atof(y), atof(z));
		} else if (!strcmp(s, "f")) {
			n = 0;
			s = strtok(NULL, SEP);
			while (s) {
				if (*s) {
					splitfv(s, fvp+n, fvn+n, fvt+n);
					n++;
				}
				s = strtok(NULL, SEP);
			}
			for (i = 1; i < n - 1; i++) {
				add_triangle(fvp[0], fvn[0], fvt[0],
					fvp[i], fvn[i], fvt[i],
					fvp[i+1], fvn[i+1], fvt[i+1]);
			}
		} else if (!strcmp(s, "mtllib")) {
			s = strtok(NULL, SEP);
			mtllib(dirname, s);
		} else if (!strcmp(s, "usemtl")) {
			if (element.len > first)
				push_part(&part, first, element.len, material);
			s = strtok(NULL, SEP);
			material = usemtl(s);
			first = element.len;
		}
	}

	if (element.len > first)
		push_part(&part, first, element.len, material);

	printf("\t%d parts; %d vertices; %d triangles", part.len, vertex.len/8, element.len/3);

	mesh = malloc(sizeof(struct mesh));
	mesh->tag = TAG_MESH;
	mesh->enabled = 1<<ATT_POSITION | 1<<ATT_NORMAL | 1<<ATT_TEXCOORD;
	mesh->skel = NULL;
	mesh->inv_bind_matrix = NULL;
	mesh->count = part.len;
	mesh->part = malloc(part.len * sizeof(struct part));
	memcpy(mesh->part, part.data, part.len * sizeof(struct part));

	glGenVertexArrays(1, &mesh->vao);
	glGenBuffers(1, &mesh->vbo);
	glGenBuffers(1, &mesh->ibo);

	glBindVertexArray(mesh->vao);
	glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->ibo);

	glBufferData(GL_ARRAY_BUFFER, vertex.len * 4, vertex.data, GL_STATIC_DRAW);

	glEnableVertexAttribArray(ATT_POSITION);
	glEnableVertexAttribArray(ATT_NORMAL);
	glEnableVertexAttribArray(ATT_TEXCOORD);
	glVertexAttribPointer(ATT_POSITION, 3, GL_FLOAT, 0, 32, (void*)0);
	glVertexAttribPointer(ATT_NORMAL, 3, GL_FLOAT, 0, 32, (void*)20);
	glVertexAttribPointer(ATT_TEXCOORD, 2, GL_FLOAT, 0, 32, (void*)12);

	glBufferData(GL_ELEMENT_ARRAY_BUFFER, element.len * 2, element.data, GL_STATIC_DRAW);

	model = malloc(sizeof *model);
	model->skel = NULL;
	model->mesh = mesh;
	model->anim = NULL;
	return model;
}