Ejemplo n.º 1
0
//returns -1 on fail, number of vertices on success
int load_off_mesh(FILE* fp, jmesh *jm){
    fseek(fp, 0, SEEK_SET); //ensure we are at the start of the file

    if(is_off_file(fp) != 0){
        fprintf(stderr, "not an off file\n");
        return -1;
    }

    int i;
    i=get_verts_faces(fp, jm);
    if(i != 3){
        fprintf(stderr,"off file corrupt on line 2\n");
        return -1;
    }
    i=get_tuples(fp, jm);
    if(i != jm->nvert){
        fprintf(stderr,"off file corrupt on tuple line %d\n", i);
        return -1;
    }
    i=get_faces(fp, jm);
    if(i != jm->ntri){
        fprintf(stderr,"off file corrupt on polygon line %d\n", i);
        return -1;
    }
    get_normals(jm);
    get_centroid(jm, jm->center);
    return i;
}
Ejemplo n.º 2
0
void in_sphere(float xyz[4][3], float xyz_in[3], float &radius_in)
{

    float matrix_1[4][4], matrix_2[4][4], rhs[4], det_matrix_1, sub_det[4];
    float norm[4][3];
    int   i, j, l;

    // get outward facing normals for each face of this tet

    get_normals(xyz,norm);

    // pack the matrix equations

    for ( j = 0 ; j <= 2 ; j++ ) {

       matrix_1[0][j] = norm[0][j];
       matrix_1[1][j] = norm[1][j];
       matrix_1[2][j] = norm[2][j];
       matrix_1[3][j] = norm[3][j];

    }

    for ( i = 0 ; i <= 3 ; i++ ) {

       matrix_1[i][3] = 1.;

    }

    // pack the right-handside

    rhs[0] = norm[0][0]*xyz[0][0] + norm[0][1]*xyz[0][1] + norm[0][2]*xyz[0][2];
    rhs[1] = norm[1][0]*xyz[3][0] + norm[1][1]*xyz[3][1] + norm[1][2]*xyz[3][2];
    rhs[2] = norm[2][0]*xyz[3][0] + norm[2][1]*xyz[3][1] + norm[2][2]*xyz[3][2];
    rhs[3] = norm[3][0]*xyz[3][0] + norm[3][1]*xyz[3][1] + norm[3][2]*xyz[3][2];

    // get determinant of original 4x4 matrix

    determinant(matrix_1,&det_matrix_1);

    // solve system of equations using Kramer's rule

    if (  det_matrix_1 != 0. ) {

       for ( l = 0 ; l <= 3 ; l++ ) {

          // grab a copy of the original matrix

          for ( i = 0 ; i <= 3 ; i++ ) {

             for ( j = 0 ; j <= 3 ; j++ ) {

                matrix_2[i][j] = matrix_1[i][j];

             }

          }

          // fill the l'th column with right-hand-side vector

          for ( i = 0 ; i <= 3 ; i++ ) {

             matrix_2[i][l] = rhs[i];

          }

          // solve for determinant of this system

          determinant(matrix_2,&sub_det[l]);

       }

       // solve for the unknowns xyz_in and radius_in

       for ( j = 0 ; j <= 2 ; j++ ) {

          xyz_in[j] = sub_det[j]/det_matrix_1;

       }

       // solve for radius

       radius_in = sub_det[3]/det_matrix_1;

    }

    else {

       radius_in = -1.;

    }

}
Ejemplo n.º 3
0
void Mesher::check_feature()
{
    auto contour = get_contour();
    const auto normals = get_normals(contour);

    // Find the largest cone and the normals that enclose
    // the largest angle as n0, n1.
    float theta = 1;
    Vec3f n0, n1;
    for (auto ni : normals)
    {
        for (auto nj : normals)
        {
            float dot = ni.dot(nj);
            if (dot < theta)
            {
                theta = dot;
                n0 = ni;
                n1 = nj;
            }
        }
    }

    // If there isn't a feature in this fan, then return immediately.
    if (theta > 0.9)
        return;

    // Decide whether this is a corner or edge feature.
    const Vec3f nstar = n0.cross(n1);
    float phi = 0;
    for (auto n : normals)
        phi = fmax(phi, fabs(nstar.dot(n)));
    bool edge = phi < 0.7;

    // Find the center of the contour.
    Vec3f center(0, 0, 0);
    for (auto c : contour)
        center += c;
    center /= contour.size();

    // Construct the matrices for use in our least-square fit.
    Eigen::MatrixX3d A(normals.size(), 3);
    {
        int i=0;
        for (auto n : normals)
            A.row(i++) << n.transpose();
    }

    // When building the second matrix, shift position values to be centered
    // about the origin (because that's what the least-squares fit will
    // minimize).
    Eigen::VectorXd B(normals.size(), 1);
    {
        auto n = normals.begin();
        auto c = contour.begin();
        int i=0;
        while (n != normals.end())
            B.row(i++) << (n++)->dot(*(c++) - center);
    }

    // Use singular value decomposition to solve the least-squares fit.
    Eigen::JacobiSVD<Eigen::MatrixX3d> svd(A, Eigen::ComputeFullU |
                                              Eigen::ComputeFullV);

    // Set the smallest singular value to zero to make fitting happier.
    if (edge)
    {
        auto singular = svd.singularValues();
        svd.setThreshold(singular.minCoeff() / singular.maxCoeff() * 1.01);
    }

    // Solve for the new point's position.
    const Vec3f new_pt = svd.solve(B) + center;

    // Erase this triangle fan, as we'll be inserting a vertex in the center.
    triangles.erase(fan_start, voxel_start);

    // Construct a new triangle fan.
    contour.push_back(contour.front());
    {
        auto p0 = contour.begin();
        auto p1 = contour.begin();
        p1++;
        while (p1 != contour.end())
            push_swappable_triangle(Triangle(*(p0++), *(p1++), new_pt));
    }
}
Ejemplo n.º 4
0
void write_mesh_data()
{
    size_t ret;

    /*
      Data format:
      Size of Mesh Name String (2 bytes - short)
      Mesh Name String (n chars)
      Number of vertices (4 bytes - int)
      Number of faces (4 bytes - int)
      Vertex triples (m*3*4 bytes - float[])
      Normal triples (m*3*4 bytes - float[])
      Face index format (1 byte) {0=1 byte; 1=2 bytes - short; 2=4 bytes - int}
      Face triples (m*3*4 bytes - int[])
    */

    curr = head;
    while (NULL != curr) {
	size_t len;
	uint32_t nvert, nface;
	size_t i;
	float vec[3];
	char format;

	/* face triples */
	unsigned char ind8[3] = {0, 0, 0};
	uint16_t ind16[3] = {0, 0, 0};
	uint32_t ind32[3] = {0, 0, 0};

	if (verbose) {
	    fprintf(stderr, ">> writing out mesh '%s' (%lu, %lu)\n", curr->name,
		    (long unsigned int)curr->bot->num_vertices, (long unsigned int)curr->bot->num_faces);
	}

	len = strlen(curr->name);
	/* mesh name string length */
	ret = fwrite(&len, sizeof(uint16_t), 1, fp_out);
	if (ret != 1)
	    perror("fwrite");
	/* mesh name string */
	ret = fwrite(curr->name, 1, len, fp_out);
	if (ret != len)
	    perror("fwrite");
	nvert = (uint32_t)curr->bot->num_vertices;
	nface = (uint32_t)curr->bot->num_faces;
	/* number of vertices */
	ret = fwrite(&nvert, sizeof(uint32_t), 1, fp_out);
	if (ret != 1)
	    perror("fwrite");
	/* number of faces */
	ret = fwrite(&nface, sizeof(uint32_t), 1, fp_out);
	if (ret != 1)
	    perror("fwrite");

	/* vertex triples */
	for (i = 0; i < curr->bot->num_vertices; i++) {
	    get_vertex(curr->bot, i, vec);
	    ret = fwrite(vec, sizeof(float), 3, fp_out);
	    if (ret != 3)
		perror("fwrite");
	}
	/* normal triples */
	if (curr->bot->num_normals == curr->bot->num_vertices) {
	    if (verbose)
		fprintf(stderr, ">> .. normals found!\n");
	    /* normals are provided */
	    ret = fwrite(curr->bot->normals, sizeof(float), curr->bot->num_normals * 3, fp_out);
	    if (ret != curr->bot->num_normals * 3)
		perror("fwrite");
	} else {
	    float *normals;
	    if (verbose) {
		fprintf(stderr, ">> .. normals will be computed\n");
	    }
	    /* normals need to be computed */
	    normals = (float *)bu_calloc(sizeof(float), curr->bot->num_vertices * 3, "normals");
	    get_normals(curr->bot, normals);
	    ret = fwrite(normals, sizeof(float), curr->bot->num_vertices * 3, fp_out);
	    if (ret != curr->bot->num_vertices * 3)
		perror("fwrite");
	    bu_free(normals, "normals");
	}

	if (nface < 1<<8) {
	    format = 0;
	} else if (nface < 1<<16) {
	    format = 1;
	} else {
	    format = 2;
	}
	/* face index format */
	ret = fwrite(&format, 1, 1, fp_out);
	if (ret != 1)
	    perror("fwrite");
	switch (format) {
	    default:
	    case 0:
		for (i = 0; i < nface; i++) {
		    ind8[0] = curr->bot->faces[3*i];
		    if (flip_normals) {
			ind8[1] = curr->bot->faces[3*i+2];
			ind8[2] = curr->bot->faces[3*i+1];
		    } else {
			ind8[1] = curr->bot->faces[3*i+1];
			ind8[2] = curr->bot->faces[3*i+2];
		    }
		    ret = fwrite(&ind8, 1, 3, fp_out);
		    if (ret != 3)
			perror("fwrite");
		}
		break;
	    case 1:
		for (i = 0; i < nface; i++) {
		    ind16[0] = curr->bot->faces[3*i];
		    if (flip_normals) {
			ind16[1] = curr->bot->faces[3*i+2];
			ind16[2] = curr->bot->faces[3*i+1];
		    } else {
			ind16[1] = curr->bot->faces[3*i+1];
			ind16[2] = curr->bot->faces[3*i+2];
		    }
		    ret = fwrite(&ind16, 2, 3, fp_out);
		    if (ret != 3)
			perror("fwrite");
		}
		break;
	    case 2:
		for (i = 0; i < nface; i++) {
		    ind32[0] = curr->bot->faces[3*i];
		    if (flip_normals) {
			ind32[1] = curr->bot->faces[3*i+2];
			ind32[2] = curr->bot->faces[3*i+1];
		    } else {
			ind32[1] = curr->bot->faces[3*i+1];
			ind32[2] = curr->bot->faces[3*i+2];
		    }
		    ret = fwrite(&ind32, 4, 3, fp_out);
		    if (ret != 3)
			perror("fwrite");
		}
		break;
	}

	curr = curr->next;
    }
}