Beispiel #1
0
int main(int argc, char** argv)
{
  char filename[BUFFERSIZE];

  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(WIDTH, HEIGHT);
  glutInitWindowPosition(100, 100);
  glutCreateWindow("render_cad_model");

  /* filename of the off file */
  sprintf(filename, "%s/%02d.off", argv[1], atoi(argv[2])); 

  /* load off file */
  load_off_file(&Nvertice, &Vertices, &Nface, &Faces, filename);
  printf("load off file done\n");

  /* compute face normals */
  Fnormals = compute_face_normals(Nvertice, Vertices, Nface, Faces);

  /* compute vertex normals */
  Vnormals = compute_vertex_normals(Nvertice, Vertices, Nface, Faces, Fnormals);

  /* draw the CAD model */
  glutDisplayFunc(display);
  glutReshapeFunc(reshape);
  glutMainLoop();
  return 0;
}
Beispiel #2
0
/* matlab interface */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
  int i;
  double *p;
  int argc = 1;
  char* argv[1];
  argv[0] = "";

  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(WIDTH, HEIGHT);
  glutInitWindowPosition(100, 100);
  glutCreateWindow("render_cad_model");
 
  if (nrhs != 2)
    mexErrMsgTxt("Wrong number of inputs");

  /* parse vertices and faces */
  p = (double*)mxGetPr(prhs[0]);
  Nvertice = mxGetN(prhs[0]);
  Vertices = (GLdouble*)malloc(sizeof(GLdouble)*Nvertice*3);
  for(i = 0; i < 3*Nvertice; i++)
    Vertices[i] = (GLdouble)p[i];

  p = (double*)mxGetPr(prhs[1]);
  Nface = mxGetN(prhs[1]);
  Faces = (GLuint*)malloc(sizeof(GLuint)*Nface*3);
  for(i = 0; i < 3*Nface; i++)
    Faces[i] = (GLuint)p[i];

  /* compute face normals */
  Fnormals = compute_face_normals(Nvertice, Vertices, Nface, Faces);

  /* compute vertex normals */
  Vnormals = compute_vertex_normals(Nvertice, Vertices, Nface, Faces, Fnormals);

  /* draw the CAD model */
  glutDisplayFunc(display);
  glutReshapeFunc(reshape);
  glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
  glutMainLoop();
  return;
}
Beispiel #3
0
    std::list<VoronoiShard>
    voronoi_convex_hull_shatter(const gl::MeshPtr &the_mesh,
                                const std::vector<glm::vec3>& the_voronoi_points)
    {
        // points define voronoi cells in world space (avoid duplicates)
        // verts = source (convex hull) mesh vertices in local space
        
        std::list<VoronoiShard> ret;
        std::vector<glm::vec3> mesh_verts = the_mesh->geometry()->vertices();
        
        auto convexHC = std::make_shared<btConvexHullComputer>();
        btAlignedObjectArray<btVector3> vertices;
        
        btVector3 rbb, nrbb;
        btScalar nlength, maxDistance, distance;
        std::vector<glm::vec3> sortedVoronoiPoints = the_voronoi_points;
        
        btVector3 normal, plane;
        btAlignedObjectArray<btVector3> planes, convexPlanes;
        std::set<int> planeIndices;
        std::set<int>::iterator planeIndicesIter;
        int numplaneIndices;
        int i, j, k;
        
        // Normalize verts (numerical stability), convert to world space and get convexPlanes
        int numverts = mesh_verts.size();
//        auto aabb = the_mesh->boundingBox();
//        float scale_val = 1.f;//std::max(std::max(aabb.width(), aabb.height()), aabb.depth());
        
        auto mesh_transform = the_mesh->global_transform() ;//* scale(glm::mat4(), vec3(1.f / scale_val));
        std::vector<glm::vec3> world_space_verts;
        
        world_space_verts.resize(mesh_verts.size());
        for (i = 0; i < numverts ;i++)
        {
            world_space_verts[i] = (mesh_transform * vec4(mesh_verts[i], 1.f)).xyz();
        }
        
        //btGeometryUtil::getPlaneEquationsFromVertices(chverts, convexPlanes);
        // Using convexHullComputer faster than getPlaneEquationsFromVertices for large meshes...
        convexHC->compute(&world_space_verts[0].x, sizeof(world_space_verts[0]), numverts, 0.0, 0.0);
        
        int numFaces = convexHC->faces.size();
        int v0, v1, v2; // vertices
        
        // get plane equations for the convex-hull n-gons
        for (i = 0; i < numFaces; i++)
        {
            const btConvexHullComputer::Edge* edge = &convexHC->edges[convexHC->faces[i]];
            v0 = edge->getSourceVertex();
            v1 = edge->getTargetVertex();
            edge = edge->getNextEdgeOfFace();
            v2 = edge->getTargetVertex();
            plane = (convexHC->vertices[v1]-convexHC->vertices[v0]).cross(convexHC->vertices[v2]-convexHC->vertices[v0]).normalize();
            plane[3] = -plane.dot(convexHC->vertices[v0]);
            convexPlanes.push_back(plane);
        }
        const int numconvexPlanes = convexPlanes.size();
        
        int numpoints = the_voronoi_points.size();
        
        for (i = 0; i < numpoints ; i++)
        {
            auto curVoronoiPoint = the_voronoi_points[i];
            planes.copyFromArray(convexPlanes);
            
            for (j = 0; j < numconvexPlanes; j++)
            {
                planes[j][3] += planes[j].dot(type_cast(the_voronoi_points[i]));
            }
            maxDistance = SIMD_INFINITY;
            
            // sort voronoi points
            std::sort(sortedVoronoiPoints.begin(), sortedVoronoiPoints.end(), pointCmp(curVoronoiPoint));
            
            for (j=1; j < numpoints; j++)
            {
                normal = type_cast(sortedVoronoiPoints[j] - curVoronoiPoint);
                nlength = normal.length();
                if (nlength > maxDistance)
                    break;
                plane = normal.normalized();
                plane[3] = -nlength / btScalar(2.);
                planes.push_back(plane);
                getVerticesInsidePlanes(planes, vertices, planeIndices);
                
                if (vertices.size() == 0) break;
                
                numplaneIndices = planeIndices.size();
                if (numplaneIndices != planes.size())
                {
                    planeIndicesIter = planeIndices.begin();
                    for (k=0; k < numplaneIndices; k++)
                    {
                        if (k != *planeIndicesIter)
                            planes[k] = planes[*planeIndicesIter];
                        planeIndicesIter++;
                    }
                    planes.resize(numplaneIndices);
                }
                maxDistance = vertices[0].length();
                for (k=1; k < vertices.size(); k++)
                {
                    distance = vertices[k].length();
                    if (maxDistance < distance)
                        maxDistance = distance;
                }
                maxDistance *= btScalar(2.);
            }
            if (vertices.size() == 0)
                continue;
            
            // Clean-up voronoi convex shard vertices and generate edges & faces
            convexHC->compute(&vertices[0].getX(), sizeof(btVector3), vertices.size(),0.0,0.0);
            
            // At this point we have a complete 3D voronoi shard mesh contained in convexHC
            
            // Calculate volume and center of mass (Stan Melax volume integration)
            numFaces = convexHC->faces.size();
            btScalar volume = btScalar(0.);
            btVector3 com(0., 0., 0.);
            
            for (j = 0; j < numFaces; j++)
            {
                const btConvexHullComputer::Edge* edge = &convexHC->edges[convexHC->faces[j]];
                v0 = edge->getSourceVertex();
                v1 = edge->getTargetVertex();
                edge = edge->getNextEdgeOfFace();
                v2 = edge->getTargetVertex();
                
                while (v2 != v0)
                {
                    // Counter-clockwise triangulated voronoi shard mesh faces (v0-v1-v2) and edges here...
                    btScalar vol = convexHC->vertices[v0].triple(convexHC->vertices[v1], convexHC->vertices[v2]);
                    volume += vol;
                    com += vol * (convexHC->vertices[v0] + convexHC->vertices[v1] + convexHC->vertices[v2]);
                    edge = edge->getNextEdgeOfFace();
                    
                    v1 = v2;
                    v2 = edge->getTargetVertex();
                }
            }
            com /= volume * btScalar(4.);
            volume /= btScalar(6.);
            
            // Shift all vertices relative to center of mass
            int numVerts = convexHC->vertices.size();
            for (j = 0; j < numVerts; j++)
            {
                convexHC->vertices[j] -= com;
            }
            
            // now create our output geometry with indices
            std::vector<gl::Face3> outer_faces, inner_faces;
            std::vector<glm::vec3> outer_vertices, inner_vertices;
            int cur_outer_index = 0, cur_inner_index = 0;
            
            for (j = 0; j < numFaces; j++)
            {
                const btConvexHullComputer::Edge* edge = &convexHC->edges[convexHC->faces[j]];
                v0 = edge->getSourceVertex();
                v1 = edge->getTargetVertex();
                edge = edge->getNextEdgeOfFace();
                v2 = edge->getTargetVertex();
                
                // determine if it is an inner or outer face
                btVector3 cur_plane = (convexHC->vertices[v1] - convexHC->vertices[v0]).cross(convexHC->vertices[v2]-convexHC->vertices[v0]).normalize();
                cur_plane[3] = -cur_plane.dot(convexHC->vertices[v0]);
                bool is_outside = false;
                
                for(uint32_t q = 0; q < convexPlanes.size(); q++)
                {
                    if(is_equal(convexPlanes[q], cur_plane, 0.01f)){ is_outside = true; break;}
                }
                std::vector<gl::Face3> *shard_faces = &outer_faces;
                std::vector<glm::vec3> *shard_vertices = &outer_vertices;
                int *shard_index = &cur_outer_index;
                
                if(!is_outside)
                {
                    shard_faces = &inner_faces;
                    shard_vertices = &inner_vertices;
                    shard_index = &cur_inner_index;
                }
                
                int face_start_index = *shard_index;
                
                // advance index
                *shard_index += 3;
                
                // first 3 verts of n-gon
                glm::vec3 tmp[] = { type_cast(convexHC->vertices[v0]),
                                    type_cast(convexHC->vertices[v1]),
                                    type_cast(convexHC->vertices[v2])};
                
                shard_vertices->insert(shard_vertices->end(), tmp, tmp + 3);
                shard_faces->push_back(gl::Face3(face_start_index,
                                                 face_start_index + 1,
                                                 face_start_index + 2));
                
                // add remaining triangles of face (if any)
                while (true)
                {
                    edge = edge->getNextEdgeOfFace();
                    v1 = v2;
                    v2 = edge->getTargetVertex();
                    
                    // end of n-gon
                    if(v2 == v0) break;
                    
                    shard_vertices->push_back(type_cast(convexHC->vertices[v2]));
                    shard_faces->push_back(gl::Face3(face_start_index,
                                                     *shard_index - 1,
                                                     *shard_index));
                    (*shard_index)++;
                }
            }
            
            // entry construction
            gl::Mesh::Entry e0, e1;
            
            // outer entry
            e0.num_vertices = outer_vertices.size();
            e0.num_indices = outer_faces.size() * 3;
            e0.material_index = 0;
            
            // inner entry
            e1.base_index = e0.num_indices;
            e1.base_vertex = e0.num_vertices;
            e1.num_vertices = inner_vertices.size();
            e1.num_indices = inner_faces.size() * 3;
            e1.material_index = 1;
            
            // create gl::Mesh object for the shard
            auto inner_geom = gl::Geometry::create(), outer_geom = gl::Geometry::create();
            
            // append verts and indices
            outer_geom->append_faces(outer_faces);
            outer_geom->vertices() = outer_vertices;
            outer_geom->compute_face_normals();
            
            inner_geom->append_faces(inner_faces);
            inner_geom->append_vertices(inner_vertices);
            inner_geom->compute_face_normals();
            
            // merge geometries
            outer_geom->append_vertices(inner_geom->vertices());
            outer_geom->append_normals(inner_geom->normals());
            outer_geom->append_indices(inner_geom->indices());
            outer_geom->faces().insert(outer_geom->faces().end(),
                                       inner_geom->faces().begin(), inner_geom->faces().end());
            outer_geom->compute_bounding_box();
            
            auto inner_mat = gl::Material::create();
            
            auto m = gl::Mesh::create(outer_geom, gl::Material::create());
            m->entries() = {e0, e1};
            m->materials().push_back(inner_mat);
            m->set_position(curVoronoiPoint + type_cast(com));
//            m->transform() *= glm::scale(mat4(), vec3(scale_val));
            
            // compute projected texcoords (outside)
            gl::project_texcoords(the_mesh, m);
            
            // compute box mapped texcoords for inside vertices
            auto &indices = m->geometry()->indices();
            auto &vertices = m->geometry()->vertices();
            
            // aabb
            auto out_aabb = the_mesh->bounding_box();
            vec3 aabb_extents = out_aabb.halfExtents() * 2.f;
            
            uint32_t base_vertex = m->entries()[1].base_vertex;
            uint32_t k = m->entries()[1].base_index, kl = k + m->entries()[1].num_indices;
            
            for(;k < kl; k += 3)
            {
                gl::Face3 f(indices[k] + base_vertex,
                            indices[k] + base_vertex + 1,
                            indices[k] + base_vertex + 2);
                
                // normal
                const vec3 &v0 = vertices[f.a];
                const vec3 &v1 = vertices[f.b];
                const vec3 &v2 = vertices[f.c];
                
                vec3 n = glm::normalize(glm::cross(v1 - v0, v2 - v0));
                
                float abs_vals[3] = {fabsf(n[0]), fabsf(n[1]), fabsf(n[2])};
                
                // get principal direction
                int principle_axis = std::distance(abs_vals, std::max_element(abs_vals, abs_vals + 3));
                
//                switch (principle_axis)
//                {
//                    // X-axis
//                    case 0:
//                        //ZY plane
//                        m->geometry()->texCoords()[f.a] = vec2(v0.z - out_aabb.min.z / aabb_extents.z,
//                                                               v0.y - out_aabb.min.y / aabb_extents.y);
//                        m->geometry()->texCoords()[f.b] = vec2(v1.z - out_aabb.min.z / aabb_extents.z,
//                                                               v1.y - out_aabb.min.y / aabb_extents.y);
//                        m->geometry()->texCoords()[f.c] = vec2(v2.z - out_aabb.min.z / aabb_extents.z,
//                                                               v2.y - out_aabb.min.y / aabb_extents.y);
//                        break;
//                        
//                    // Y-axis
//                    case 1:
//                    // XZ plane
//                        m->geometry()->texCoords()[f.a] = vec2(v0.x - out_aabb.min.x / aabb_extents.x,
//                                                               v0.z - out_aabb.min.z / aabb_extents.z);
//                        m->geometry()->texCoords()[f.b] = vec2(v1.x - out_aabb.min.x / aabb_extents.x,
//                                                               v1.z - out_aabb.min.z / aabb_extents.z);
//                        m->geometry()->texCoords()[f.c] = vec2(v2.x - out_aabb.min.x / aabb_extents.x,
//                                                               v2.z - out_aabb.min.z / aabb_extents.z);
//                        break;
//                        
//                    // Z-axis
//                    case 2:
//                        //XY plane
//                        m->geometry()->texCoords()[f.a] = vec2(v0.x - out_aabb.min.x / aabb_extents.x,
//                                                               v0.y - out_aabb.min.y / aabb_extents.y);
//                        m->geometry()->texCoords()[f.b] = vec2(v1.x - out_aabb.min.x / aabb_extents.x,
//                                                               v1.y - out_aabb.min.y / aabb_extents.y);
//                        m->geometry()->texCoords()[f.c] = vec2(v2.x - out_aabb.min.x / aabb_extents.x,
//                                                               v2.y - out_aabb.min.y / aabb_extents.y);
//                        break;
//                        
//                    default:
//                        break;
//                }
            }
            // push to return structure
            ret.push_back({m, volume});
        }
        LOG_DEBUG << "Generated " << ret.size() <<" voronoi shards";
        return ret;
    }