Example #1
0
void CalculateTangentAndBinormal(const MQPoint& v0, const MQPoint& v1, const MQPoint& v2,
		const MQPoint& n0, const MQPoint& n1, const MQPoint& n2,
		const MQCoordinate& t0, const MQCoordinate& t1, const MQCoordinate& t2,
		MQPoint& tan0, MQPoint& tan1, MQPoint& tan2, 
		MQPoint& bin0, MQPoint& bin1, MQPoint& bin2)
{
	MQPoint edge1, edge2, crossP;

	edge1.x = v1.x - v0.x;
	edge1.y = t1.u - t0.u; // s-vector - don't need to compute this multiple times
	edge1.z = t1.v - t0.v; // t-vector
	edge2.x = v2.x - v0.x;
	edge2.y = t2.u - t0.u; // another s-vector
	edge2.z = t2.v - t0.v; // another t-vector
	crossP = Normalize(GetCrossProduct(edge1, edge2));
	if(fabs(crossP.x) < 1e-4f){
		crossP.x = 1.0f;
	}
	tan0.x = tan1.x = tan2.x = -crossP.y / crossP.x;
	bin0.x = bin1.x = bin2.x = -crossP.z / crossP.x;

	// y, s, t
	edge1.x = v1.y - v0.y;
	edge2.x = v2.y - v0.y;
	crossP = Normalize(GetCrossProduct(edge1, edge2));
	if(fabs(crossP.x) < 1e-4f){
		crossP.x = 1.0f;
	}
	tan0.y = tan1.y = tan2.y = -crossP.y / crossP.x;
	bin0.y = bin1.y = bin2.y = -crossP.z / crossP.x;

	// z, s, t
	edge1.x = v1.z - v0.z;
	edge2.x = v2.z - v0.z;
	crossP = Normalize(GetCrossProduct(edge1, edge2));
	if(fabs(crossP.x) < 1e-4f){
		crossP.x = 1.0f;
	}
	tan0.z = tan1.z = tan2.z = -crossP.y / crossP.x;
	bin0.z = bin1.z = bin2.z = -crossP.z / crossP.x;

	// Orthonormalize to normal
	tan0 -= n0 * GetInnerProduct(tan0, n0);
	tan1 -= n1 * GetInnerProduct(tan1, n1);
	tan2 -= n2 * GetInnerProduct(tan2, n2);
	bin0 -= n0 * GetInnerProduct(bin0, n0);
	bin1 -= n1 * GetInnerProduct(bin1, n1);
	bin2 -= n2 * GetInnerProduct(bin2, n2);

	// Normalize tangents and binormals
	tan0 = Normalize(tan0);
	tan1 = Normalize(tan1);
	tan2 = Normalize(tan2);
	bin0 = Normalize(bin0);
	bin1 = Normalize(bin1);
	bin2 = Normalize(bin2);
}
Example #2
0
void CalculateTangent(const MQPoint& v0, const MQPoint& v1, const MQPoint& v2,
		const MQPoint& normal,
		const MQCoordinate& t0, const MQCoordinate& t1, const MQCoordinate& t2,
		MQPoint& tangent)
{
	MQPoint edge1, edge2, crossP;

	edge1.x = v1.x - v0.x;
	edge1.y = t1.u - t0.u; // s-vector - don't need to compute this multiple times
	edge1.z = t1.v - t0.v; // t-vector
	edge2.x = v2.x - v0.x;
	edge2.y = t2.u - t0.u; // another s-vector
	edge2.z = t2.v - t0.v; // another t-vector
	crossP = Normalize(GetCrossProduct(edge1, edge2));
	if(fabs(crossP.x) < 1e-4f){
		crossP.x = 1.0f;
	}
	float tanX = -crossP.y / crossP.x;
	tangent.x = tanX;

	// y, s, t
	edge1.x = v1.y - v0.y;
	edge2.x = v2.y - v0.y;
	crossP = Normalize(GetCrossProduct(edge1, edge2));
	if(fabs(crossP.x) < 1e-4f){
		crossP.x = 1.0f;
	}
	float tanY = -crossP.y / crossP.x;
	tangent.y = tanY;

	// z, s, t
	edge1.x = v1.z - v0.z;
	edge2.x = v2.z - v0.z;
	crossP = Normalize(GetCrossProduct(edge1, edge2));
	if(fabs(crossP.x) < 1e-4f){
		crossP.x = 1.0f;
	}
	float tanZ = -crossP.y / crossP.x;
	tangent.z = tanZ;

	// Orthonormalize to normal
	tangent -= normal * GetInnerProduct(tangent, normal);

	// Normalize tangents
	tangent = Normalize(tangent);
}
Example #3
0
//---------------------------------------------------------------------------
//  GetNormal()
//     Get a normal vector for a face constituted by three points.
//     3点からなる面の法線を得る
//---------------------------------------------------------------------------
MQPoint GetNormal(const MQPoint& p0, const MQPoint& p1, const MQPoint& p2)
{
	MQPoint ep = GetCrossProduct(p1-p2, p0-p1);

	if(ep == MQPoint(0,0,0))
		return MQPoint(0,0,0);

	return ep / GetSize(ep);
}
Example #4
0
/*
 * ***************************************************************************
 * Routine:  GemMesh_fromSurfaceMeshes
 *
 * Author:   Johan Hake ([email protected])
 *
 * Purpose:  Use tetgen to generate a GemMesh from a surface mesh
 * ***************************************************************************
 */
GemMesh* GemMesh_fromSurfaceMeshes(SurfaceMesh** surfmeshes, int num_surface_meshes, 
				   char* tetgen_params)
{
  
  unsigned int j, sm_index, num_vertices = 0, num_faces = 0;
  unsigned int num_regions = 0, num_holes = 0;
  SurfaceMesh* surfmesh;
  FLTVECT normal, midpoint;
  INT3VECT face0;

  tetgenio in, out;
  tetgenio::facet *f;
  tetgenio::polygon *p;
  in.firstnumber = 1;

  // Collect info from the surface meshes
  for (sm_index=0; sm_index<num_surface_meshes; sm_index++)
  {
    // Get the surface mesh
    surfmesh = surfmeshes[sm_index];

    // Check if neighborlist is created
    if (surfmesh->neighbor_list == NULL)
      SurfaceMesh_createNeighborlist(surfmesh);
    
    if (surfmesh->num_vertices == 0 || surfmesh->num_faces == 0)
    {
      printf("The %d:th surface mesh is empty. Abandoning "\
	     "tetrahedralization.\n", sm_index);
      return GemMesh_ctor(0, 0, false);
    }
      

    if (!surfmesh->closed)
    {
      printf("The %d:th surface mesh is not closed. Abandoning "\
	     "tetrahedralization.\n", sm_index);
      return GemMesh_ctor(0, 0, false);
    }
    
    // Bump counters
    if (!surfmesh->as_hole)
      num_regions += 1;
    else
      num_holes += 1;

    num_vertices += surfmesh->num_vertices;
    num_faces += surfmesh->num_faces;
  }

  // We need at least one region
  if (num_regions < 1)
  {
    printf("Expected at least one surface mesh which is not a hole.\n");
    return GemMesh_ctor(0, 0, false);
  }
  
  // Assign memory
  printf("num vertices: %d\n", num_vertices);
  printf("num faces: %d\n", num_faces);
  in.numberofpoints = num_vertices;
  in.pointlist = new REAL[in.numberofpoints * 3];
  
  in.numberoffacets = num_faces;
  in.facetlist = new tetgenio::facet[in.numberoffacets];
  in.facetmarkerlist = new int[in.numberoffacets];
  
  printf("num regions: %d\n", num_regions);
  in.numberofregions = num_regions;
  in.regionlist = new REAL[num_regions*5];

  if (num_holes > 0)
  {
    printf("num holes: %d\n", num_holes);
    in.numberofholes = num_holes;
    in.holelist = new REAL[num_holes*3];
  }

  // Reset counters
  num_vertices = num_faces = num_regions = num_holes = 0;
  
  // Iterate over the surface meshes and assign info
  for (sm_index=0; sm_index<num_surface_meshes; sm_index++)
  {
    
    // Get the surface mesh
    surfmesh = surfmeshes[sm_index];
    
    // Assign vertex information
    for (j = 0; j < surfmesh->num_vertices; j++) 
    {
      in.pointlist[j*3 + 0 + num_vertices*3] = surfmesh->vertex[j].x;
      in.pointlist[j*3 + 1 + num_vertices*3] = surfmesh->vertex[j].y;
      in.pointlist[j*3 + 2 + num_vertices*3] = surfmesh->vertex[j].z;
    }
  
    // Assign face information
    for (j = 0; j < surfmesh->num_faces; j++) 
    {
      f = &in.facetlist[j+num_faces];
      f->holelist = (REAL *) NULL;
      f->numberofholes = 0;
      f->numberofpolygons = 1;
      f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
      p = &f->polygonlist[0];
      p->numberofvertices = 3;
      p->vertexlist = new int[p->numberofvertices];
      p->vertexlist[0] = surfmesh->face[j].a + in.firstnumber + num_vertices;
      p->vertexlist[1] = surfmesh->face[j].b + in.firstnumber + num_vertices;
      p->vertexlist[2] = surfmesh->face[j].c + in.firstnumber + num_vertices;
      in.facetmarkerlist[j+num_faces] = surfmesh->face[j].m == -1 ? 0 : surfmesh->face[j].m;
    }

    // Get region or hole coordinate by using a face
    face0 = surfmesh->face[0];

    // Face normal 
    normal = GetCrossProduct(surfmesh, face0.a, face0.b, face0.c);
    
    // Midpoint of face
    midpoint.x = surfmesh->vertex[face0.a].x/3;
    midpoint.y = surfmesh->vertex[face0.a].y/3;
    midpoint.z = surfmesh->vertex[face0.a].z/3;

    midpoint.x += surfmesh->vertex[face0.b].x/3;
    midpoint.y += surfmesh->vertex[face0.b].y/3;
    midpoint.z += surfmesh->vertex[face0.b].z/3;

    midpoint.x += surfmesh->vertex[face0.c].x/3;
    midpoint.y += surfmesh->vertex[face0.c].y/3;
    midpoint.z += surfmesh->vertex[face0.c].z/3;

    // Weight based on length
    double weight = sqrt(pow(surfmesh->vertex[face0.a].x-\
			     surfmesh->vertex[face0.b].x, 2) + \
			 pow(surfmesh->vertex[face0.a].y-\
			     surfmesh->vertex[face0.b].y, 2) + \
			 pow(surfmesh->vertex[face0.a].z-\
			     surfmesh->vertex[face0.b].z, 2));

    // Add region information
    if (!surfmesh->as_hole)
    {
      // Calculate region info using face information
      // FIXME: Why should we add the normal values?
      // FIXME: If normal is pointing outwards we should substract to 
      // FIXME: get a point inside the surface mesh....
      in.regionlist[num_regions*5 + 0] = midpoint.x + normal.x*weight;
      in.regionlist[num_regions*5 + 1] = midpoint.y + normal.y*weight;
      in.regionlist[num_regions*5 + 2] = midpoint.z + normal.z*weight;
      
      // Set region marker (attribute)
      in.regionlist[num_regions*5 + 3] = surfmesh->marker;

      // If volume constraints
      if (surfmesh->use_volume_constraint)
      {
	printf("Volume constraint: %.5f\n", surfmesh->volume_constraint);
	in.regionlist[num_regions*5 + 4] = surfmesh->volume_constraint;
      }
      else
	in.regionlist[num_regions*5 + 4] = -1;
      
      // Bump counter
      num_regions += 1;
    }
    else
    {
      // Calculate hole info using face information
      in.holelist[num_holes*3 + 0] = midpoint.x + normal.x*weight;
      in.holelist[num_holes*3 + 1] = midpoint.y + normal.y*weight;
      in.holelist[num_holes*3 + 2] = midpoint.z + normal.z*weight;

      // Bump counter
      num_holes += 1;
    }
    
    // Bump face and vertex counters
    num_vertices += surfmesh->num_vertices;
    num_faces += surfmesh->num_faces;

  }  
  
  // Add boundary marker on each node
  // FIXME: Why? Aren't the markers set on the generatedmesh?
  in.pointmarkerlist = new int[in.numberofpoints];
  for (j = 0; j < in.numberofpoints; j++)
    in.pointmarkerlist[j] = 1;

  // Debug
  in.save_nodes("plc");
  in.save_poly("plc");

  // Call TetGen
  tetrahedralize(tetgen_params, &in, &out, NULL);

  // Debug
  out.save_nodes("result");
  out.save_elements("result");
  out.save_faces("result");

  // Convert to a generalized tetrahedral mesh structure
  return GemMesh_fromTetgen(out);

}