CVertexBufferObject::CVertexBufferObject(bool isStatic, int numVertices, const CVertexAttributes& attributes) :
	m_bufferHandle(0),
	m_tmpHandle(0),
	m_isDirect(true),
	m_usage(0),
	m_isDirty(false),
	m_attributes(attributes),
	m_isBound(false),
	m_isStatic(isStatic)
{
	m_byteBuffer = byte_buffer(attributes.vertexSize * numVertices);
    m_byteBuffer.flip();
    m_buffer = float_buffer(attributes.vertexSize * numVertices);
    //m_buffer = m_byteBuffer.convert<float>();
	m_buffer.flip();
    m_bufferHandle = CreateBufferObject();
    m_usage = isStatic ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW;
}
Beispiel #2
0
void Visualizer::CaptureDepthImage(const std::string &filename/* = ""*/,
        bool do_render/* = true*/, double depth_scale/* = 1000.0*/)
{
    std::string png_filename = filename;
    std::string camera_filename;
    if (png_filename.empty()) {
        std::string timestamp = GetCurrentTimeStamp();
        png_filename = "DepthCapture_" + timestamp + ".png";
        camera_filename = "DepthCamera_" + timestamp + ".json";
    }
    Image depth_image;
    depth_image.PrepareImage(view_control_ptr_->GetWindowWidth(),
            view_control_ptr_->GetWindowHeight(), 1, 4);

    if (do_render) {
        Render();
        is_redraw_required_ = false;
    }
    glFinish();

#if __APPLE__
    // On OSX with Retina display and glfw3, there is a bug with glReadPixels().
    // When using glReadPixels() to read a block of depth data. The data is
    // horizontally streched (vertically it is fine). This issue is related
    // to GLFW_SAMPLES hint. When it is set to 0 (anti-aliasing disabled),
    // glReadPixels() works fine. See this post for details:
    // http://stackoverflow.com/questions/30608121/glreadpixel-one-pass-vs-looping-through-points
    // The reason of this bug is unknown. The current workaround is to read
    // depth buffer column by column. This is 15~30 times slower than one block
    // reading glReadPixels().
    std::vector<float> float_buffer(depth_image.height_);
    float *p = (float *)depth_image.data_.data();
    for (int j = 0; j < depth_image.width_; j++) {
        glReadPixels(j, 0, 1, depth_image.width_,
                GL_DEPTH_COMPONENT, GL_FLOAT,
                float_buffer.data());
        for (int i = 0; i < depth_image.height_; i++) {
            p[i * depth_image.width_ + j] = float_buffer[i];
        }
    }
#else //__APPLE__
    // By default, glReadPixels read a block of depth buffer.
    glReadPixels(0, 0, depth_image.width_, depth_image.height_,
            GL_DEPTH_COMPONENT, GL_FLOAT, depth_image.data_.data());
#endif //__APPLE__

    // glReadPixels get the screen in a vertically flipped manner
    // We should flip it back, and convert it to the correct depth value
    Image png_image;
    double z_near = view_control_ptr_->GetZNear();
    double z_far = view_control_ptr_->GetZFar();

    png_image.PrepareImage(view_control_ptr_->GetWindowWidth(),
            view_control_ptr_->GetWindowHeight(), 1, 2);
    for (int i = 0; i < depth_image.height_; i++) {
        float *p_depth = (float *)(depth_image.data_.data() +
                depth_image.BytesPerLine() * (depth_image.height_ - i - 1));
        uint16_t *p_png = (uint16_t *)(png_image.data_.data() +
                png_image.BytesPerLine() * i);
        for (int j = 0; j < depth_image.width_; j++) {
            if (p_depth[j] == 1.0) {
                continue;
            }
            double z_depth = 2.0 * z_near * z_far /
                    (z_far + z_near - (2.0 * (double)p_depth[j] - 1.0) *
                    (z_far - z_near));
            p_png[j] = (uint16_t)std::min(std::round(depth_scale * z_depth),
                    (double)INT16_MAX);
        }
    }

    PrintDebug("[Visualizer] Depth capture to %s\n", png_filename.c_str());
    WriteImage(png_filename, png_image);
    if (!camera_filename.empty()) {
        PrintDebug("[Visualizer] Depth camera capture to %s\n",
                camera_filename.c_str());
        PinholeCameraTrajectory trajectory;
        trajectory.extrinsic_.resize(1);
        view_control_ptr_->ConvertToPinholeCameraParameters(
                trajectory.intrinsic_, trajectory.extrinsic_[0]);
        WriteIJsonConvertible(camera_filename, trajectory);
    }
}
Beispiel #3
0
void Visualizer::CaptureDepthPointCloud(const std::string &filename/* = ""*/,
        bool do_render/* = true*/, bool convert_to_world_coordinate/* = false*/)
{
    std::string ply_filename = filename;
    std::string camera_filename;
    if (ply_filename.empty()) {
        std::string timestamp = GetCurrentTimeStamp();
        ply_filename = "DepthCapture_" + timestamp + ".ply";
        camera_filename = "DepthCamera_" + timestamp + ".json";
    }
    Image depth_image;
    depth_image.PrepareImage(view_control_ptr_->GetWindowWidth(),
            view_control_ptr_->GetWindowHeight(), 1, 4);

    if (do_render) {
        Render();
        is_redraw_required_ = false;
    }
    glFinish();

#if __APPLE__
    // On OSX with Retina display and glfw3, there is a bug with glReadPixels().
    // When using glReadPixels() to read a block of depth data. The data is
    // horizontally stretched (vertically it is fine). This issue is related
    // to GLFW_SAMPLES hint. When it is set to 0 (anti-aliasing disabled),
    // glReadPixels() works fine. See this post for details:
    // http://stackoverflow.com/questions/30608121/glreadpixel-one-pass-vs-looping-through-points
    // The reason of this bug is unknown. The current workaround is to read
    // depth buffer column by column. This is 15~30 times slower than one block
    // reading glReadPixels().
    std::vector<float> float_buffer(depth_image.height_);
    float *p = (float *)depth_image.data_.data();
    for (int j = 0; j < depth_image.width_; j++) {
        glReadPixels(j, 0, 1, depth_image.width_,
                GL_DEPTH_COMPONENT, GL_FLOAT,
                float_buffer.data());
        for (int i = 0; i < depth_image.height_; i++) {
            p[i * depth_image.width_ + j] = float_buffer[i];
        }
    }
#else //__APPLE__
    // By default, glReadPixels read a block of depth buffer.
    glReadPixels(0, 0, depth_image.width_, depth_image.height_,
            GL_DEPTH_COMPONENT, GL_FLOAT, depth_image.data_.data());
#endif //__APPLE__

    GLHelper::GLMatrix4f mvp_matrix;
    if (convert_to_world_coordinate) {
        mvp_matrix = view_control_ptr_->GetMVPMatrix();
    }
    else {
        mvp_matrix = view_control_ptr_->GetProjectionMatrix();
    }

    // glReadPixels get the screen in a vertically flipped manner
    // We should flip it back, and convert it to the correct depth value
    PointCloud depth_pointcloud;
    for (int i = 0; i < depth_image.height_; i++) {
        float *p_depth = (float *)(depth_image.data_.data() +
                depth_image.BytesPerLine() * i);
        for (int j = 0; j < depth_image.width_; j++) {
            if (p_depth[j] == 1.0) {
                continue;
            }
            depth_pointcloud.points_.push_back(GLHelper::Unproject(
                    Eigen::Vector3d(j + 0.5, i + 0.5, p_depth[j]),
                    mvp_matrix,
                    view_control_ptr_->GetWindowWidth(),
                    view_control_ptr_->GetWindowHeight()));
        }
    }

    PrintDebug("[Visualizer] Depth point cloud capture to %s\n",
            ply_filename.c_str());
    WritePointCloud(ply_filename, depth_pointcloud);
    if (!camera_filename.empty()) {
        PrintDebug("[Visualizer] Depth camera capture to %s\n",
                camera_filename.c_str());
        PinholeCameraTrajectory trajectory;
        trajectory.extrinsic_.resize(1);
        view_control_ptr_->ConvertToPinholeCameraParameters(
                trajectory.intrinsic_, trajectory.extrinsic_[0]);
        WriteIJsonConvertible(camera_filename, trajectory);
    }
}
Beispiel #4
0
std::shared_ptr<Image> Visualizer::CaptureDepthFloatBuffer(
        bool do_render/* = true*/)
{
    Image depth_image;
    depth_image.PrepareImage(view_control_ptr_->GetWindowWidth(),
            view_control_ptr_->GetWindowHeight(), 1, 4);
    if (do_render) {
        Render();
        is_redraw_required_ = false;
    }
    glFinish();

#if __APPLE__
    // On OSX with Retina display and glfw3, there is a bug with glReadPixels().
    // When using glReadPixels() to read a block of depth data. The data is
    // horizontally stretched (vertically it is fine). This issue is related
    // to GLFW_SAMPLES hint. When it is set to 0 (anti-aliasing disabled),
    // glReadPixels() works fine. See this post for details:
    // http://stackoverflow.com/questions/30608121/glreadpixel-one-pass-vs-looping-through-points
    // The reason of this bug is unknown. The current workaround is to read
    // depth buffer column by column. This is 15~30 times slower than one block
    // reading glReadPixels().
    std::vector<float> float_buffer(depth_image.height_);
    float *p = (float *)depth_image.data_.data();
    for (int j = 0; j < depth_image.width_; j++) {
        glReadPixels(j, 0, 1, depth_image.width_,
                GL_DEPTH_COMPONENT, GL_FLOAT,
                float_buffer.data());
        for (int i = 0; i < depth_image.height_; i++) {
            p[i * depth_image.width_ + j] = float_buffer[i];
        }
    }
#else //__APPLE__
    // By default, glReadPixels read a block of depth buffer.
    glReadPixels(0, 0, depth_image.width_, depth_image.height_,
            GL_DEPTH_COMPONENT, GL_FLOAT, depth_image.data_.data());
#endif //__APPLE__

    // glReadPixels get the screen in a vertically flipped manner
    // We should flip it back, and convert it to the correct depth value
    auto image_ptr = std::make_shared<Image>();
    double z_near = view_control_ptr_->GetZNear();
    double z_far = view_control_ptr_->GetZFar();

    image_ptr->PrepareImage(view_control_ptr_->GetWindowWidth(),
            view_control_ptr_->GetWindowHeight(), 1, 4);
    for (int i = 0; i < depth_image.height_; i++) {
        float *p_depth = (float *)(depth_image.data_.data() +
                depth_image.BytesPerLine() * (depth_image.height_ - i - 1));
        float *p_image = (float *)(image_ptr->data_.data() +
                image_ptr->BytesPerLine() * i);
        for (int j = 0; j < depth_image.width_; j++) {
            if (p_depth[j] == 1.0) {
                continue;
            }
            double z_depth = 2.0 * z_near * z_far /
                    (z_far + z_near - (2.0 * (double)p_depth[j] - 1.0) *
                    (z_far - z_near));
            p_image[j] = (float)z_depth;
        }
    }
    return image_ptr;
}