Exemple #1
0
carve::poly::Polyhedron *readModel(const std::string &file) {
  carve::poly::Polyhedron *poly;

  if (file == "") {
    if (options.obj) {
      poly = readOBJ(std::cin);
    } else if (options.vtk) {
      poly = readVTK(std::cin);
    } else {
      poly = readPLY(std::cin);
    }
  } else if (endswith(file, ".ply")) {
    poly = readPLY(file);
  } else if (endswith(file, ".vtk")) {
    poly = readVTK(file);
  } else if (endswith(file, ".obj")) {
    poly = readOBJ(file);
  }

  if (poly == NULL) return NULL;

  std::cerr << "loaded polyhedron " << poly << " has "
    << poly->vertices.size() << " vertices "
    << poly->faces.size() << " faces "
    << poly->manifold_is_closed.size() << " manifolds (" << std::count(poly->manifold_is_closed.begin(), poly->manifold_is_closed.end(), true) << " closed)" << std::endl;

  return poly;
}
Exemple #2
0
int main(int argc, char **argv) {
  options.parse(argc, argv);

  carve::input::Input inputs;
  std::vector<carve::mesh::MeshSet<3> *> polys;
  std::vector<carve::line::PolylineSet *> lines;
  std::vector<carve::point::PointSet *> points;

  if (options.file == "") {
    readPLY(std::cin, inputs);
  } else {
    if (endswith(options.file, ".ply")) {
      readPLY(options.file, inputs);
    } else if (endswith(options.file, ".vtk")) {
      readVTK(options.file, inputs);
    } else if (endswith(options.file, ".obj")) {
      readOBJ(options.file, inputs);
    }
  }

  for (std::list<carve::input::Data *>::const_iterator i = inputs.input.begin(); i != inputs.input.end(); ++i) {
    carve::mesh::MeshSet<3> *p;
    carve::point::PointSet *ps;
    carve::line::PolylineSet *l;

    if ((p = carve::input::Input::create<carve::mesh::MeshSet<3> >(*i)) != NULL)  {
      if (options.canonicalize) p->canonicalize();
      if (options.obj) {
        writeOBJ(std::cout, p);
      } else if (options.vtk) {
        writeVTK(std::cout, p);
      } else {
        writePLY(std::cout, p, options.ascii);
      }
      delete p;
    } else if ((l = carve::input::Input::create<carve::line::PolylineSet>(*i)) != NULL)  {
      if (options.obj) {
        writeOBJ(std::cout, l);
      } else if (options.vtk) {
        writeVTK(std::cout, l);
      } else {
        writePLY(std::cout, l, options.ascii);
      }
      delete l;
    } else if ((ps = carve::input::Input::create<carve::point::PointSet>(*i)) != NULL)  {
      if (options.obj) {
        std::cerr << "Can't write a point set in .obj format" << std::endl;
      } else if (options.vtk) {
        std::cerr << "Can't write a point set in .vtk format" << std::endl;
      } else {
        writePLY(std::cout, ps, options.ascii);
      }
      delete ps;
    }
  }

  return 0;
}
Exemple #3
0
int main(int argc, char **argv) {
  carve::poly::Polyhedron *input = readPLY(argv[1]);
  double offset = strtod(argv[2], NULL);

  TestScene *scene = new TestScene(argc, argv, 3);

  glNewList(scene->draw_list_base, GL_COMPILE);
  doOffset(input, offset);
  glEndList();

  glNewList(scene->draw_list_base + 1, GL_COMPILE);
  drawPolyhedron(input, .6, .6, .6, 1.0, false);
  glEndList();

  glNewList(scene->draw_list_base + 2, GL_COMPILE);
  drawPolyhedronWireframe(input);
  glEndList();

  scene->draw_flags[0] = true;
  scene->draw_flags[1] = true;
  scene->draw_flags[2] = true;

  scene->run();

  delete scene;

  return 0;
}
Exemple #4
0
int main(int argc, char **argv) {
    try {
        carve::input::Input inputs;
        readPLY(std::string(argv[1]), inputs);
        carve::mesh::MeshSet<3> *p;
        p = carve::input::Input::create<carve::mesh::MeshSet<3> >(*inputs.input.begin());

        carve::mesh::MeshSimplifier simplifier;

        simplifier.removeFins(p);
        simplifier.removeLowVolumeManifolds(p, 1.0);

        // p->transform(carve::geom::quantize<10,3>());
        simplifier.simplify(p, 1e-2, 1.0, M_PI/180.0, 2e-3);
        // std::cerr << "n_flips: " << simplifier.improveMesh_conservative(p) << std::endl;

        simplifier.removeFins(p);
        simplifier.removeLowVolumeManifolds(p, 1.0);

        writePLY(std::cout, p, true);
        return 0;
    } catch (carve::exception e) {
        std::cerr << "exception: " << e.str() << std::endl;
    }
}
Exemple #5
0
bool ModelReader::readModel(std::string path)
{
    if (isFormatPCD(path))
        return readPCD(path);
    else if (isFormatPLY(path))
        return readPLY(path);

    return false;
}
Exemple #6
0
static carve::mesh::MeshSet<3> *load(const std::string &file) {
  carve::input::Input inputs;

  if (file == "-") {
    readPLY(std::cin, inputs);
  } else if (endswith(file, ".ply")) {
    readPLY(file, inputs);
  } else if (endswith(file, ".vtk")) {
    readVTK(file, inputs);
  } else if (endswith(file, ".obj")) {
    readOBJ(file, inputs);
  }

  carve::mesh::MeshSet<3> *poly = NULL;

  for (std::list<carve::input::Data *>::const_iterator i = inputs.input.begin();
       poly == NULL && i != inputs.input.end();
       ++i) {
    poly = inputs.create<carve::mesh::MeshSet<3> >(*i, carve::input::Options());
  }

  return poly;
}
Exemple #7
0
int main(int argc, char *argv[])
{
    GLState glState;
    float fov = 45.f;
    try
    {
        srand(time(NULL));

        if (SDL_Init(SDL_INIT_VIDEO) != 0)
        {
#ifndef __ANDROID__
            std::cout << "Couldn't initialize SDL: " << SDL_GetError()
                << std::endl;
#endif
            return -1;
        }

        //ask for gles2
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
        //SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);

        //with _DESKTOP sometimes nothing is drawn, only glClear seems to work
        glState.window = SDL_CreateWindow("PCViewer", SDL_WINDOWPOS_UNDEFINED,
                SDL_WINDOWPOS_UNDEFINED, 0, 0,
                SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN_DESKTOP);
        if (glState.window == NULL)
            throw std::runtime_error(fillSDLError("Failed to create window"));

        glState.context = SDL_GL_CreateContext(glState.window);
        if (glState.context == NULL)
            throw std::runtime_error(fillSDLError("Failed to create context"));

        //SDL_GL_SetSwapInterval(1);

        int status = SDL_GL_MakeCurrent(glState.window, glState.context);
        if (status) {
            fprintf(stderr, "SDL_GL_MakeCurrent(): %s\n", SDL_GetError());
        }

        GLuint vertexShader = load_shader(vshaderSrc, GL_VERTEX_SHADER);
        GLuint fragmentShader = load_shader(fshaderSrc, GL_FRAGMENT_SHADER);

        glState.shaderProgram = glCreateProgram();
        glAttachShader(glState.shaderProgram, vertexShader);
        glAttachShader(glState.shaderProgram, fragmentShader);

        glLinkProgram(glState.shaderProgram);
        glUseProgram(glState.shaderProgram);

        readPLY("bun_zipper.ply", vertices);
        glm::mat4 mCenterAndScale(computeCenterAndScale(vertices));

        glGenBuffers(1, &glState.vertexBuffer);
        glBindBuffer(GL_ARRAY_BUFFER, glState.vertexBuffer);
        glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex),
                &vertices[0], GL_STATIC_DRAW);

        //prepare fix view matrices
        const glm::mat4 mView = glm::lookAt(
                glm::vec3(0,0,5),
                glm::vec3(0,0,0),
                glm::vec3(0,1,0)
                );

        ModelPos pcPos;
        SDL_Event event;
        bool translating = false;
        bool rotating = false;
        SDL_FingerID activeFinger;
        int fingerCount = 0;
        bool run = true;
        while (run)
        {
            while (SDL_PollEvent(&event))
            {
                switch (event.type)
                {
#ifdef __ANDROID__
                    //TODO: add translation (2 fingers?)
                    case SDL_FINGERDOWN:
                        ++fingerCount;
                        if (!rotating)
                        {
                            rotating = true;
                            activeFinger = event.tfinger.fingerId;
                        }
                        break;
                    case SDL_FINGERUP:
                        --fingerCount;
                        if (rotating && event.tfinger.fingerId == activeFinger)
                            rotating = false;
                        break;
                    case SDL_FINGERMOTION:
                        if (rotating && fingerCount == 1 && event.tfinger.fingerId == activeFinger)
                        {
                            pcPos.rx += event.tfinger.dy * 5;
                            pcPos.ry += event.tfinger.dx * 5;
                        }
                        break;
                    case SDL_MULTIGESTURE:
                        fov -= event.mgesture.dDist * 100;
                        break;
#else
                    case SDL_MOUSEBUTTONDOWN:
                        if (event.button.button == SDL_BUTTON_LEFT)
                            translating = true;
                        else if (event.button.button == SDL_BUTTON_RIGHT)
                            rotating = true;
                        break;
                    case SDL_MOUSEBUTTONUP:
                        if (event.button.button == SDL_BUTTON_LEFT)
                            translating = false;
                        else if (event.button.button == SDL_BUTTON_RIGHT)
                            rotating = false;
                        break;
                    case SDL_MOUSEWHEEL:
                        if (event.wheel.y > 0)
                            fov += 1;
                        else if (event.wheel.y < 0)
                            fov -= 1;
                        break;
                    case SDL_MOUSEMOTION:
                        if (translating)
                        {
                            pcPos.tx += event.motion.xrel * .01;
                            pcPos.ty -= event.motion.yrel * .01;
                        }
                        else if (rotating)
                        {
                            pcPos.rx += event.motion.yrel * .01;
                            pcPos.ry += event.motion.xrel * .01;
                        }
                        break;
#endif
                    case SDL_QUIT:
                        run = false;
                        break;
                }
            }

            SDL_DisplayMode dm;
            SDL_GetWindowDisplayMode(glState.window, &dm);
            const glm::mat4 mProj =
                glm::perspective(fov, float(dm.w) / dm.h, 0.1f, 100.0f);
            const glm::mat4 mvp = mProj * mView * mModelFromPos(pcPos) * mCenterAndScale;
            render(glState, mvp);
            SDL_Delay(10);
        }
    }
    catch (const std::exception &e)
    {
#ifndef __ANDROID__
        std::cerr << "Error: " << e.what() << std::endl;
#endif
    }

    if (glState.context)
        SDL_GL_DeleteContext(glState.context);

    if (glState.window)
        SDL_DestroyWindow(glState.window);

    SDL_Quit();

    return 0;
}
Exemple #8
0
int main(int argc, char **argv) {
  TestScene *scene = new TestScene(argc, argv, std::min(1, argc - 1));
  options.parse(argc, argv);

  size_t count = 0;

  carve::input::Input inputs;
  std::vector<carve::mesh::MeshSet<3> *> polys;
  std::vector<carve::line::PolylineSet *> lines;
  std::vector<carve::point::PointSet *> points;

  if (options.files.size() == 0) {
    if (options.obj) {
      readOBJ(std::cin, inputs);
    } else if (options.vtk) {
      readVTK(std::cin, inputs);
    } else {
      readPLY(std::cin, inputs);
    }

  } else {
    for (size_t idx = 0; idx < options.files.size(); ++idx) {
      std::string &s(options.files[idx]);
      std::string::size_type i = s.rfind(".");

      if (i != std::string::npos) {
        std::string ext = s.substr(i, s.size() - i);
        if (!strcasecmp(ext.c_str(), ".obj")) {
          readOBJ(s, inputs);
        } else if (!strcasecmp(ext.c_str(), ".vtk")) {
          readVTK(s, inputs);
        } else {
          readPLY(s, inputs);
        }
      } else {
        readPLY(s, inputs);
      }
    }
  }

  for (std::list<carve::input::Data *>::const_iterator i = inputs.input.begin(); i != inputs.input.end(); ++i) {
    carve::mesh::MeshSet<3> *p;
    carve::point::PointSet *ps;
    carve::line::PolylineSet *l;

    if ((p = carve::input::Input::create<carve::mesh::MeshSet<3> >(*i, carve::input::opts("avoid_cavities", "true"))) != NULL)  {
      polys.push_back(p);
      std::cerr << "loaded polyhedron "
                << polys.back() << " has " << polys.back()->meshes.size()
                << " manifolds (" << std::count_if(polys.back()->meshes.begin(),
                                                   polys.back()->meshes.end(),
                                                   carve::mesh::Mesh<3>::IsClosed()) << " closed)" << std::endl; 

      std::cerr << "closed:    ";
      for (size_t i = 0; i < polys.back()->meshes.size(); ++i) {
        std::cerr << (polys.back()->meshes[i]->isClosed() ? '+' : '-');
      }
      std::cerr << std::endl;

      std::cerr << "negative:  ";
      for (size_t i = 0; i < polys.back()->meshes.size(); ++i) {
        std::cerr << (polys.back()->meshes[i]->isNegative() ? '+' : '-');
      }
      std::cerr << std::endl;

    } else if ((l = carve::input::Input::create<carve::line::PolylineSet>(*i)) != NULL)  {
      lines.push_back(l);
      std::cerr << "loaded polyline set "
                << lines.back() << std::endl; 
    } else if ((ps = carve::input::Input::create<carve::point::PointSet>(*i)) != NULL)  {
      points.push_back(ps);
      std::cerr << "loaded point set "
                << points.back() << std::endl; 
    }
  }

  scene->draw_list_base = genSceneDisplayList(polys, lines, points, &count, scene->is_wireframe);
  scene->draw_flags.assign(count, true);

  scene->run();

  delete scene;

  return 0;
}
int main(int argc, char* argv[]) {
	if (argc < 3) {
		printf("Usage: ./ray_tracing input.ply outputFolder\n");
		return 1;
	}

	std::vector<Point> vertices;
	std::vector<Triangle> faces;
	std::vector<Plane> planes;
	std::vector<Point> pointcloud;

	readPLY(argv[1],&vertices,&faces);

	//get bounding box
	double minX=vertices[0].x,maxX=vertices[0].x;
	double minY=vertices[0].y,maxY=vertices[0].y;
	double minZ=vertices[0].z,maxZ=vertices[0].z;
//	for (size_t i=1;i<vertices.size();i++) {
//		if (vertices[i].x < minX) minX = vertices[i].x;
//		else if (vertices[i].x > maxX) maxX = vertices[i].x;
//		if (vertices[i].y < minY) minY = vertices[i].y;
//		else if (vertices[i].y > maxY) maxY = vertices[i].y;
//		if (vertices[i].z < minZ) minZ = vertices[i].z;
//		else if (vertices[i].z > maxZ) maxZ = vertices[i].z;
//	}
	for (size_t i=0;i<faces.size();i++) {
		Triangle t = faces[i];
		Point point[3] = {vertices[t.id1],vertices[t.id2],vertices[t.id3]};
		for (int j=0;j<3;j++) {
			if (point[j].x < minX) minX = point[j].x;
			else if (point[j].x > maxX) maxX = point[j].x;
			if (point[j].y < minY) minY = point[j].y;
			else if (point[j].y > maxY) maxY = point[j].y;
			if (point[j].z < minZ) minZ = point[j].z;
			else if (point[j].z > maxZ) maxZ = point[j].z;
		}
	}
	printf("Bounding box: x:(%.2f %.2f) y:(%.2f %.2f) z:(%.2f %.2f)\n",minX,maxX,minY,maxY,minZ,maxZ);
	Point centroid = {
		(minX + maxX) / 2,
		(minY + maxY) / 2,
		(minZ + maxZ) / 2
	};

	//get normals
	for (size_t i=0;i<faces.size();i++) {
		Plane v = getPlane(&vertices,faces[i]);
		planes.push_back(v);
	}

	double resolution = 0.01; //radians
	int numCameras=16;
	char buffer[128];
#if USE_Y_VERTICAL
	double radius = (maxX-minX) > (maxZ-minZ) ? (maxX-minX)*2 : (maxZ-minZ)*2; 
#else
	double radius = (maxX-minX) > (maxY-minY) ? (maxX-minX)*2 : (maxY-minY)*2; 
#endif
	double noise_sigma = 0 * radius;
	double alpha=M_PI/2/numCameras;
	for (int k=0;k<numCameras;k++) {
		double fov = M_PI/8 + M_PI/4*rand()/RAND_MAX;
		pointcloud.clear();
#if USE_Y_VERTICAL
		Point cameraOrigin = {
			centroid.x + radius * sin(alpha) + noise_sigma * rand() / RAND_MAX,
			centroid.y + noise_sigma * rand() / RAND_MAX,
			centroid.z + radius * cos(alpha) + noise_sigma * rand() / RAND_MAX
		};
#else
		Point cameraOrigin = {
			centroid.x + radius * cos(alpha) + noise_sigma * rand() / RAND_MAX,
			centroid.y + radius * sin(alpha) + noise_sigma * rand() / RAND_MAX,
			centroid.z + noise_sigma * rand() / RAND_MAX
		};
#endif
		Vector principalDirection = {
			centroid.x - cameraOrigin.x,
			centroid.y - cameraOrigin.y,
			centroid.z - cameraOrigin.z
		};
		principalDirection = normalize(principalDirection);
#if RADIAL_SAMPLING
		for (double theta=-fov/2;theta<fov/2;theta+=resolution) {
			 for (double phi=-fov/2;phi<fov/2;phi+=resolution) {
#if USE_Y_VERTICAL
				Vector rayDirection = {
					principalDirection.z * sin(theta) * cos(phi) + principalDirection.x * cos(theta) * cos(phi),
					sin(phi),
					principalDirection.z * cos(theta) * cos(phi) - principalDirection.x * sin(theta) * cos(phi)
				};
#else
				Vector rayDirection = {
					principalDirection.x * cos(theta) * cos(phi) - principalDirection.y * sin(theta) * cos(phi),
					principalDirection.x * sin(theta) * cos(phi) + principalDirection.y * cos(theta) * cos(phi),
					sin(phi)
				};
#endif
				Point rayOrigin = cameraOrigin;
#else
#if USE_Y_VERTICAL
		for (double theta=minY;theta<maxY;theta+=(maxY-minY)*resolution) {
			for (double phi=-radius*fov/M_PI/2;phi<radius*fov/M_PI/2;phi+=(radius*fov/M_PI)*resolution) {
				Vector rayDirection = principalDirection;
				Point rayOrigin = {
					cameraOrigin.x + phi * principalDirection.z,
					theta,
					cameraOrigin.z - phi * principalDirection.x
				};
#else
		for (double theta=minZ;theta<maxZ;theta+=(maxZ-minZ)*resolution) {
			for (double phi=-radius*fov/M_PI/2;phi<radius*fov/M_PI/2;phi+=(radius*fov/M_PI)*resolution) {
				Vector rayDirection = principalDirection;
				Point rayOrigin = {
					cameraOrigin.x + phi * principalDirection.y,
					cameraOrigin.y - phi * principalDirection.x,
					theta
				};
#endif
#endif
				bool isValid = false;
				Point closestPoint;
				double minDistance = DBL_MAX;
				//find intersection for each triangle
				for (size_t i=0;i<faces.size();i++) {
					double distance;
					if (intersects(rayOrigin,rayDirection,planes[i],&distance)) {
						if (distance < minDistance) {
							Point intersection = {
								rayOrigin.x + rayDirection.x * distance,
								rayOrigin.y + rayDirection.y * distance,
								rayOrigin.z + rayDirection.z * distance
							};
							if (triangleContains(&vertices,faces[i],planes[i],intersection)) {
								isValid = true;
								closestPoint = intersection;
								minDistance = distance;
							}
						}
					}
				}
				if (isValid) {
					pointcloud.push_back(closestPoint);
				}
			 }
		}

		alpha += 2*M_PI/numCameras;
		if (pointcloud.size() > 0) {
			sprintf(buffer,"%s/%d-cloud.pcd",argv[2],k);
			writeToPCD(buffer,&pointcloud);
		}
	}
	return 0;
}
Exemple #10
0
int main(int argc, char* argv[]) {
    if (argc < 3) {
        printf("Usage: ./zbuffer input.ply [output.pcd,outputFolder]\n");
        return 1;
    }

    std::vector<Point> vertices;
    std::vector<Triangle> faces;
    std::vector<Point> pointcloud;
    char buffer[128];
    bool merge = opendir(argv[2]) == NULL;

    readPLY(argv[1],&vertices,&faces);

    //get bounding box
    double minX=vertices[0].x,maxX=vertices[0].x;
    double minY=vertices[0].y,maxY=vertices[0].y;
    double minZ=vertices[0].z,maxZ=vertices[0].z;
    for (size_t i=1; i<vertices.size(); i++) {
        if (vertices[i].x < minX) minX = vertices[i].x;
        else if (vertices[i].x > maxX) maxX = vertices[i].x;
        if (vertices[i].y < minY) minY = vertices[i].y;
        else if (vertices[i].y > maxY) maxY = vertices[i].y;
        if (vertices[i].z < minZ) minZ = vertices[i].z;
        else if (vertices[i].z > maxZ) maxZ = vertices[i].z;
    }
    printf("Bounding box: x:(%.2f %.2f) y:(%.2f %.2f) z:(%.2f %.2f)\n",minX,maxX,minY,maxY,minZ,maxZ);
    Point centroid = {
        (minX + maxX) / 2,
        (minY + maxY) / 2,
        (minZ + maxZ) / 2
    };
    for (size_t i = 0; i < vertices.size(); i++) {
        vertices[i].x -= centroid.x;
        vertices[i].y -= centroid.y;
        vertices[i].z -= centroid.z;
    }

    int width = RESOLUTION;
    int height = RESOLUTION;
    OSMesaContext ctx;
    ctx = OSMesaCreateContextExt(OSMESA_RGB, 32, 0, 0, NULL );
    unsigned char * pbuffer = new unsigned char [3 * width * height];
    // Bind the buffer to the context and make it current
    if (!OSMesaMakeCurrent(ctx, (void*)pbuffer, GL_UNSIGNED_BYTE, width, height))
        printf("fail to create MESA context\n");
    OSMesaPixelStore(OSMESA_Y_UP, 0);

    glEnable(GL_DEPTH_TEST);
    glDisable(GL_LIGHTING);
    glDisable(GL_CULL_FACE);
    glPolygonMode(GL_FRONT, GL_FILL);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    float fov = 70;
    float fov_scale = 2 * tan(fov / 2 / 180 * M_PI);
    float zfar = 100000;
    gluPerspective(fov,1,1,zfar);
    glViewport(0, 0, width, height);
    float cameraX = maxX - minX;
    float cameraY = maxY - minY;
    float cameraZ = maxZ - minZ;
    float cx = 0.5 * (width + 1);
    float cy = 0.5 * (height + 1);
    unsigned int* depth = new unsigned int[width * height];
    float rho = sqrt(cameraX*cameraX + cameraY*cameraY);
    float theta = atan2(cameraY, cameraX);
    int depthBits=0;
    glGetIntegerv(GL_DEPTH_BITS, &depthBits);
    printf("depth buffer bits %d\n",depthBits);

    int numViews = INCLUDE_TOP ? NUM_CAMERAS + 2 : NUM_CAMERAS;
    for (int k = 0; k < numViews; k++) {
//		if (!merge)
//			pointcloud.clear();
        float rx = rho * cos(theta);
        float ry = rho * sin(theta);
        theta += 2 * 3.14159265 / NUM_CAMERAS;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        if (k < NUM_CAMERAS)
            gluLookAt(rx,ry, cameraZ, 0,0,0, 0,0,1);
        else if (k == NUM_CAMERAS)
            gluLookAt(0,0, cameraZ*4, 0,0,0, 1,0,0);
        else if (k == NUM_CAMERAS + 1)
            gluLookAt(0,0, -cameraZ*4, 0,0,0, 1,0,0);
        GLfloat R[16] =  {};
        glGetFloatv(GL_MODELVIEW_MATRIX, R);
//		printf("%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n",R[0],R[1],R[2],R[3],R[4],R[5],R[6],R[7],R[8],R[9],R[10],R[11],R[12],R[13],R[14],R[15]);
//		printf("camera: %f %f %f\n",rx,ry,cameraZ);
        glBegin(GL_TRIANGLES);
        glColor3ub(150, 150, 150);
        for (size_t i = 0; i < faces.size(); i++) {
            Point p1 = vertices[faces[i].id1];
            Point p2 = vertices[faces[i].id2];
            Point p3 = vertices[faces[i].id3];
            glVertex3f(p1.x, p1.y, p1.z);
            glVertex3f(p2.x, p2.y, p2.z);
            glVertex3f(p3.x, p3.y, p3.z);
        }
        glEnd();
        glFinish(); // done rendering
        GLint outWidth, outHeight, bitPerDepth;
        GLboolean ret = OSMesaGetDepthBuffer(ctx, &outWidth, &outHeight, &bitPerDepth, (void**)&depth);
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                float buffer_z = (float) depth[j * width + i] / 0xFFFFFFFF;
                if (buffer_z > 0 && buffer_z < 1) {
//					float z = -1 / (1 - buffer_z);
                    float z = 1 / (buffer_z - 1 - buffer_z / zfar);
                    float x = (i - cx) * -z / width * fov_scale;
                    float y = (j - cy) * -z / height * fov_scale;
                    x -= R[12];
                    y -= R[13];
                    z -= R[14];
                    Point p = {
                        R[0] * x + R[1] * y + R[2] * z,
                        R[4] * x + R[5] * y + R[6] * z,
                        R[8] * x + R[9] * y + R[10] * z
                    };
                    pointcloud.push_back(p);
                }
            }
        }
//		printf("pointcloud: %lu\n",pointcloud.size());
        if (!merge && pointcloud.size() > 0) {
            int n=0;
            while (true) {
                sprintf(buffer,"%s/%d-cloud.pcd",argv[2],n);
                FILE* f = fopen(buffer,"r");
                if (!f) {
                    writeToPCD(buffer,&pointcloud);
                    break;
                }
                fclose(f);
                n++;
            }
        }
    }
    if (merge && pointcloud.size() > 0) {
        sprintf(buffer,"%s",argv[2]);
        writeToPCD(buffer,&pointcloud);
    }

//	sprintf(buffer,"%s/vertex.pcd",argv[2]);
//	writeToPCD(buffer,&vertices);

    OSMesaDestroyContext(ctx);
    return 0;
}