I just started learning vulkan and got problems binding multiple vertex and index buffers.
Model is a class contain vertex and index buffer:
// Model
public:
const vk::ImageView& GetTextureImageView() const;
const vk::Sampler& GetTextureSampler() const;
const vk::Buffer& GetVertexBuffer() const;
const vk::Buffer& GetIndexBuffer() const;
private:
std::vector<Vertex> vertices_;
std::vector<uint32_t> indices_;
vk::Image texture_image_;
vk::DeviceMemory texture_image_memory_;
vk::ImageView texture_image_view_;
vk::Sampler texture_sampler_;
vk::Buffer vertex_buffer_;
vk::DeviceMemory vertex_buffer_memory_;
vk::Buffer index_buffer_;
vk::DeviceMemory index_buffer_memory_;
Wing is a class may have many models:
private:
std::vector<Model> models_;
When Wing load a Model, I will do:
Create Model
UpdateDescriptorSets:
void Wing::UpdateDescriptorSets() {
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT_; ++i) {
vk::DescriptorBufferInfo buffer_info;
buffer_info
.setBuffer(uniform_buffers_[i])
.setOffset(0)
.setRange(sizeof(UniformBufferObject));
// first question
std::vector<vk::DescriptorImageInfo> image_infos;
for (auto& model : models_) {
vk::DescriptorImageInfo image_info;
image_info
.setImageLayout(vk::ImageLayout::eShaderReadOnlyOptimal)
.setImageView(model.GetTextureImageView())
.setSampler(model.GetTextureSampler());
image_infos.push_back(image_info);
}
std::array<vk::WriteDescriptorSet, 2> descriptor_writes;
descriptor_writes.at(0)
.setDstSet(descriptor_sets_[i])
.setDstBinding(0)
.setDstArrayElement(0)
.setDescriptorType(vk::DescriptorType::eUniformBuffer)
.setDescriptorCount(1)
.setBufferInfo(buffer_info);
descriptor_writes.at(1)
.setDstSet(descriptor_sets_[i])
.setDstBinding(1)
.setDstArrayElement(0)
.setDescriptorType(vk::DescriptorType::eCombinedImageSampler)
.setDescriptorCount(1)
.setImageInfo(image_infos);
device_.updateDescriptorSets(descriptor_writes, nullptr);
}
}
RecordCommandBuffer:
if (!models_.empty()) {
for (size_t index = 0; index < models_.size(); ++index) {
command_buffers_[current_frame_].bindVertexBuffers(0, vertex_buffers_, {0}); // second question
command_buffers_[current_frame_].bindIndexBuffer(index_buffers_, 0, vk::IndexType::eUint32); // third question
command_buffers_[current_frame_].bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipeline_layout_, 0, 1, &descriptor_sets_[current_frame_], 0, nullptr);
command_buffers_[current_frame_].drawIndexed(static_cast<uint32_t>(indices_.size()), 1, 0, 0, 0);
}
}
My first question is when loading a new model, if it is right to update image_infos in UpdateDescriptorSets?
And the second and third question is how to bindVertexBuffers and bindIndexBuffer when I have many models and these models have different vertex and index buffers?
Related
What is the importance of defining indegree vector in the private of a class? It could have been defined in alltopologicalSort() function.
class Graph
{
int V; // No. of vertices
// Pointer to an array containing adjacency list
list<int> *adj;
// Vector to store indegree of vertices
vector<int> indegree;
// A function used by alltopologicalSort
void alltopologicalSortUtil(vector<int>& res,
bool visited[]);
public:
Graph(int V); // Constructor
// function to add an edge to graph
void addEdge(int v, int w);
// Prints all Topological Sorts
void alltopologicalSort();
};
And how it is functioning in below addedge function
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v's list.
// increasing inner degree of w by 1
indegree[w]++;
}
Use of indegree, please explain here the role of addEdge function in decrementing indegree
void Graph::alltopologicalSortUtil(vector<int>& res,
bool visited[])
{
// To indicate whether all topological are found
// or not
bool flag = false;
for (int i = 0; i < V; i++)
{
// If indegree is 0 and not yet visited then
// only choose that vertex
if (indegree[i] == 0 && !visited[i])
{
// reducing indegree of adjacent vertices
list<int>:: iterator j;
for (j = adj[i].begin(); j != adj[i].end(); j++)
indegree[*j]--;
// including in result
res.push_back(i);
visited[i] = true;
alltopologicalSortUtil(res, visited);
// resetting visited, res and indegree for
// backtracking
visited[i] = false;
res.erase(res.end() - 1);
for (j = adj[i].begin(); j != adj[i].end(); j++)
indegree[*j]++;
flag = true;
}
}
}
This is the link to complete code of finding All Topological Sorts of Directed Acyclic Graph
https://www.geeksforgeeks.org/all-topological-sorts-of-a-directed-acyclic-graph/
I have got my answer from above discussion with Gupta and kaya3
Indegree could have been defined in some function and then passed to alltopologicalSort() function as a reference. But then defining it in class makes it easier to deal with.
And Data members of a class are always kept private because of encapsulation rules
I'm trying to rewrite this first triangle example in vala and failing this is what I have so far:
public class MyApp : Gtk.Application {
private MyAppWindow? myAppWindow;
public string appName;
public MyApp () {
Object (
application_id: "com.github.myusername.myreponame",
flags: ApplicationFlags.FLAGS_NONE
);
appName = "My App";
}
protected override void activate () {
myAppWindow = new MyAppWindow (this);
add_window (myAppWindow);
myAppWindow.show_all ();
}
public static int main (string[] args) {
var myApp = new MyApp ();
return myApp.run (args);
}
}
public class MyAppWindow : Gtk.ApplicationWindow {
public MyApp myApp { get; construct set; }
private Gtk.HeaderBar headerBar;
private Gtk.GLArea glArea;
private Gtk.Frame frame;
// An array of 3 vectors which represents 3 vertices
private GLES2.GLfloat[] g_vertex_buffer_data = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f };
// This will identify our vertex buffer
private GLES2.GLuint vertexbuffer;
private GLES2.GLuint programID;
public MyAppWindow(MyApp myApp) {
Object(myApp: myApp);
}
construct {
set_default_size (480, 640);
headerBar = new Gtk.HeaderBar ();
headerBar.set_show_close_button (true);
headerBar.set_title (myApp.appName);
glArea = new Gtk.GLArea ();
glArea.margin = 10;
frame = new Gtk.Frame ("GL Area");
frame.margin = 10;
// Generate 1 buffer, put the resulting identifier in vertexbuffer
GLES2.glGenBuffers(1, &vertexbuffer);
// The following commands will talk about our 'vertexbuffer' buffer
GLES2.glBindBuffer(GLES2.GL_ARRAY_BUFFER, vertexbuffer);
// Give our vertices to OpenGL.
GLES2.glBufferData(GLES2.GL_ARRAY_BUFFER, 9*4, g_vertex_buffer_data, GLES2.GL_STATIC_DRAW);
LoadShaders (out programID);
GLES2.glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
glArea.render.connect (() => {
GLES2.glClear (GLES2.GL_COLOR_BUFFER_BIT | GLES2.GL_DEPTH_BUFFER_BIT);
GLES2.glUseProgram(programID);
// 1st attribute buffer : vertices
GLES2.glEnableVertexAttribArray(0);
GLES2.glBindBuffer(GLES2.GL_ARRAY_BUFFER, vertexbuffer);
GLES2.glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GLES2.GL_FLOAT, // type
GLES2.GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangle !
GLES2.glDrawArrays(GLES2.GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle
GLES2.glDisableVertexAttribArray(0);
GLES2.glFlush ();
return true;
});
set_titlebar (headerBar);
frame.add (glArea);
add (frame);
}
void LoadShaders(out GLES2.GLuint ProgramID) {
GLES2.GLint Result = GLES2.GL_FALSE;
int InfoLogLength = 0;
// create vertex shader
GLES2.GLuint VertexShaderID = GLES2.glCreateShader(GLES2.GL_VERTEX_SHADER);
string VertexSource = "#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
void main(){
gl_Position.xyz = vertexPosition_modelspace;
gl_Position.w = 1.0;
}";
// compile vertex shader
GLES2.glShaderSource(VertexShaderID, 1, out VertexSource, null);
GLES2.glCompileShader(VertexShaderID);
// check vertex shader
GLES2.glGetShaderiv(VertexShaderID, GLES2.GL_COMPILE_STATUS, &Result);
GLES2.glGetShaderiv(VertexShaderID, GLES2.GL_INFO_LOG_LENGTH, &InfoLogLength);
if ( InfoLogLength > 0 ) {
GLES2.GLchar[InfoLogLength+1] VertexShaderErrorMessage;
GLES2.glGetShaderInfoLog(VertexShaderID, InfoLogLength, null, &VertexShaderErrorMessage[0]);
}
// create fragment shader
GLES2.GLuint FragmentShaderID = GLES2.glCreateShader(GLES2.GL_FRAGMENT_SHADER);
string FragmentSource = "#version 330 core
out vec3 color;
void main(){
color = vec3(1,0,0);
}";
// compile fragment shader
GLES2.glShaderSource(FragmentShaderID, 1, out FragmentSource, null);
GLES2.glCompileShader(FragmentShaderID);
// check fragment shader
GLES2.glGetShaderiv(FragmentShaderID, GLES2.GL_COMPILE_STATUS, &Result);
GLES2.glGetShaderiv(FragmentShaderID, GLES2.GL_INFO_LOG_LENGTH, &InfoLogLength);
if ( InfoLogLength > 0 ){
GLES2.GLchar[InfoLogLength+1] FragmentShaderErrorMessage;
GLES2.glGetShaderInfoLog(FragmentShaderID, InfoLogLength, null, &FragmentShaderErrorMessage[0]);
}
ProgramID = GLES2.glCreateProgram();
GLES2.glAttachShader(ProgramID, VertexShaderID);
GLES2.glAttachShader(ProgramID, FragmentShaderID);
GLES2.glLinkProgram(ProgramID);
// Check the program
GLES2.glGetProgramiv(ProgramID, GLES2.GL_LINK_STATUS, &Result);
GLES2.glGetProgramiv(ProgramID, GLES2.GL_INFO_LOG_LENGTH, &InfoLogLength);
if ( InfoLogLength > 0 ){
GLES2.GLchar[InfoLogLength+1] ProgramErrorMessage;
GLES2.glGetProgramInfoLog(ProgramID, InfoLogLength, null, &ProgramErrorMessage[0]);
}
GLES2.glDetachShader(ProgramID, VertexShaderID);
GLES2.glDetachShader(ProgramID, FragmentShaderID);
GLES2.glDeleteShader(VertexShaderID);
GLES2.glDeleteShader(FragmentShaderID);
}
}
I compile it with valac --pkg gtk+-3.0 --vapidir=. --pkg gles2 valagl.vala -o valagl --Xcc=-lGLESv2. I have a gles2.vapi in the same folder.
There are 2 [-Wincompatible-pointer-types] warnings in glShaderSource for the shader source string at compile time. That could be where the problem is but I do not know how to fix it.
expected ‘const GLchar * const* {aka const char * const*}’ but argument is of type ‘gchar ** {aka char **}
The example has a step of glfwSwapBuffers(). I'm not sure what needs to be done there. I use GLES2.glFlush () but I do not understand how it connects to the GLArea I just created.
Also valadoc goes on about an on_realize signal where shaders need to be initialized, but I cant seem to find an on_realize signal at all
How do I draw a simple triangle in a GTK3 window using GLES2?
The program runs and shows a black GLArea. The only thing that works is the color of that area, I can change the color by changing GLES2.glClearColor (0.0f, 0.0f, 0.0f, 0.0f)
I am trying to use the example code from here.
I have made some changes in order to save the images to the computer. When I read the data in MATLAB it seems like values that should be 0 are set to 2047, and overall it does not seem to be correct when I reconstruct the 3D points using the default intrinsic camera parameters.
What I want to achieve is to save the images so that I can use
img = single(imread(depth.png'))/ 1000
and have the depth values in meters, and pixels with no measurements should be zero.
It is the Kinect V1 by the way.
Here is the code with comments where I have tried to change.
#include "libfreenect.hpp"
#include <iostream>
#include <vector>
#include <cmath>
#include <pthread.h>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
using namespace cv;
using namespace std;
class myMutex {
public:
myMutex() {
pthread_mutex_init( &m_mutex, NULL );
}
void lock() {
pthread_mutex_lock( &m_mutex );
}
void unlock() {
pthread_mutex_unlock( &m_mutex );
}
private:
pthread_mutex_t m_mutex;
};
// Should one use FREENECT_DEPTH_REGISTERED instead of FREENECT_DEPTH_11BIT?
class MyFreenectDevice : public Freenect::FreenectDevice {
public:
MyFreenectDevice(freenect_context *_ctx, int _index)
: Freenect::FreenectDevice(_ctx, _index), m_buffer_depth(FREENECT_DEPTH_11BIT),
m_buffer_rgb(FREENECT_VIDEO_RGB), m_gamma(2048), m_new_rgb_frame(false),
m_new_depth_frame(false), depthMat(Size(640,480),CV_16UC1),
rgbMat(Size(640,480), CV_8UC3, Scalar(0)),
ownMat(Size(640,480),CV_8UC3,Scalar(0)) {
for( unsigned int i = 0 ; i < 2048 ; i++) {
float v = i/2048.0;
v = std::pow(v, 3)* 6;
m_gamma[i] = v*6*256;
}
}
// Do not call directly even in child
void VideoCallback(void* _rgb, uint32_t timestamp) {
std::cout << "RGB callback" << std::endl;
m_rgb_mutex.lock();
uint8_t* rgb = static_cast<uint8_t*>(_rgb);
rgbMat.data = rgb;
m_new_rgb_frame = true;
m_rgb_mutex.unlock();
};
// Do not call directly even in child
void DepthCallback(void* _depth, uint32_t timestamp) {
std::cout << "Depth callback" << std::endl;
m_depth_mutex.lock();
uint16_t* depth = static_cast<uint16_t*>(_depth);
// Here I use memcpy instead so I can use uint16
// memcpy(depthMat.data,depth,depthMat.rows*depthMat.cols*sizeof(uint16_t));
depthMat.data = (uchar*) depth;
m_new_depth_frame = true;
m_depth_mutex.unlock();
}
bool getVideo(Mat& output) {
m_rgb_mutex.lock();
if(m_new_rgb_frame) {
cv::cvtColor(rgbMat, output, CV_RGB2BGR);
m_new_rgb_frame = false;
m_rgb_mutex.unlock();
return true;
} else {
m_rgb_mutex.unlock();
return false;
}
}
bool getDepth(Mat& output) {
m_depth_mutex.lock();
if(m_new_depth_frame) {
depthMat.copyTo(output);
m_new_depth_frame = false;
m_depth_mutex.unlock();
return true;
} else {
m_depth_mutex.unlock();
return false;
}
}
private:
// Should it be uint16_t instead or even higher?
std::vector<uint8_t> m_buffer_depth;
std::vector<uint8_t> m_buffer_rgb;
std::vector<uint16_t> m_gamma;
Mat depthMat;
Mat rgbMat;
Mat ownMat;
myMutex m_rgb_mutex;
myMutex m_depth_mutex;
bool m_new_rgb_frame;
bool m_new_depth_frame;
};
int main(int argc, char **argv) {
bool die(false);
string filename("snapshot");
string suffix(".png");
int i_snap(0),iter(0);
Mat depthMat(Size(640,480),CV_16UC1);
Mat depthf (Size(640,480),CV_8UC1);
Mat rgbMat(Size(640,480),CV_8UC3,Scalar(0));
Mat ownMat(Size(640,480),CV_8UC3,Scalar(0));
// The next two lines must be changed as Freenect::Freenect
// isn't a template but the method createDevice:
// Freenect::Freenect<MyFreenectDevice> freenect;
// MyFreenectDevice& device = freenect.createDevice(0);
// by these two lines:
Freenect::Freenect freenect;
MyFreenectDevice& device = freenect.createDevice<MyFreenectDevice>(0);
namedWindow("rgb",CV_WINDOW_AUTOSIZE);
namedWindow("depth",CV_WINDOW_AUTOSIZE);
device.startVideo();
device.startDepth();
while (!die) {
device.getVideo(rgbMat);
device.getDepth(depthMat);
// Here I save the depth images
std::ostringstream file;
file << filename << i_snap << suffix;
cv::imwrite(file.str(),depthMat);
cv::imshow("rgb", rgbMat);
depthMat.convertTo(depthf, CV_8UC1, 255.0/2048.0);
cv::imshow("depth",depthf);
if(iter >= 1000) break;
iter++;
}
device.stopVideo();
device.stopDepth();
return 0;
}
Thanks in advance!
Erik
I dont have any experience with OpenKinect in particular; but should your depth buffer be uint16?
std::vector<uint8_t> m_buffer_depth;
Also; for Matlab, do check if the image that you are reading is a uint16 or uint8. If its the latter then convert it to uint16
uint16(imread('depth.png'));
Sorry couldn't help more. Hope this helps.
The values you have are the raw depth values. You need to remap those into MM for the numbers to make sense. Kinect 1 can see up to 10 meters. So I would go with raw_values/2407*10000.
If the values are saturated at 2047, you are probably using the FREENECT_DEPTH_11BIT_PACKED depth format.
For work in Matlab, it is always easier to use FREENECT_DEPTH_MM or FREENECT_DEPTH_REGISTERED.
Enjoy.
I'm trying to make use of a 2D triangulation using CGAL, and create an obj file. I'm able to create a 2D triangulation. I now want to make the 3rd coordinate 0, ie z=0, and create a obj file out of the result of the triangulation. The samples of CGAL seem quite confusing, and I'm not sure how to go about this.
Here is how I did it. Hope it helps someone.
// A modifier creating a triangle with the incremental builder.
template<class HDS>
class polyhedron_builder : public CGAL::Modifier_base<HDS> {
public:
std::vector<Triangulation>& t_;
polyhedron_builder(std::vector<Triangulation>& t) : t_(t) {}
void operator()(HDS& hds) {
typedef typename HDS::Vertex Vertex;
typedef typename Vertex::Point Point3;
// create a cgal incremental builder
CGAL::Polyhedron_incremental_builder_3<HDS> B(hds, true);
// calculte total vertices
int face_num = 0;
int vertice_num = 0;
for (auto& tri : t_) {
face_num += tri.number_of_faces();
vertice_num += tri.number_of_vertices();
}
std::cout << face_num << ", " << vertice_num << ", " << t_.size() << "\n";
B.begin_surface(face_num, vertice_num);
// add the polyhedron vertices
for (auto& tri : t_) {
for (auto itr = tri.finite_vertices_begin(); itr != tri.finite_vertices_end(); ++itr) {
B.add_vertex(Point3(itr->point().x(), itr->point().y(), 0));
}
}
// add the polyhedron triangles
for (auto& tri : t_) {
for (auto itr = tri.finite_faces_begin(); itr != tri.finite_faces_end(); ++itr) {
B.begin_facet();
B.add_vertex_to_facet(itr->vertex(0)->info());
B.add_vertex_to_facet(itr->vertex(1)->info());
B.add_vertex_to_facet(itr->vertex(2)->info());
B.end_facet();
}
}
// finish up the surface
B.end_surface();
}
};
void OBJfile::write_obj_file(const std::string& filename) {
CGAL::Polyhedron_3<CGAL::Simple_cartesian<double>> polyhedron;
unsigned index = 0;
std::vector<Triangulation> t_vector;
// here, contours is an internal object that tracks the polygon outlines
for (auto& contour : contours_) {
Triangulation t;
std::vector < std::pair<Point, unsigned> > polygon;
for (auto& pt : contour) {
Point point(pt.x(), pt.y());
polygon.push_back(std::make_pair(point, index++));
}
triangulate(polygon, t);
t_vector.push_back(t);
}
polyhedron_builder<HalfedgeDS> builder(t_vector);
polyhedron.delegate(builder);
// write the polyhedron out as a .OFF file
std::ofstream os("test.obj");
CGAL::File_writer_wavefront writer;
CGAL::generic_print_polyhedron(os, polyhedron, writer);
os.close();
}
void OBJfile::triangulate(const std::vector<std::pair<Point, unsigned>>& polygon_points, Triangulation& t) {
auto begin = polygon_points.begin();
auto end = polygon_points.end();
//std::istream_iterator<Point> end;
t.insert(begin, end);
}
I am currently working on a project to use multiple kinect cameras to acquire x,y,z coordinates of skeletal data in SkeletalViewer. I have an idea to use the KinectID or index of different kinect cameras to extract the sets of skeletal joints data into 2 different text files. But I am not sure if I am doing right. Please help to take a look at the modification below, or I will appreciate all your kind advice on other method to solve this problem.
In SkeletalViewer.h, I modified as following:
public:
FILE* mp3DFile0;
FILE* mp3DFile1;
char mText[1024];
INuiSensor * m_pNuiSensor;
BSTR m_instanceId;
array SensorIndex;
In NuiImpl.cpp, I modified as following:
1) define array
ref class MyClass {
public:
int m_i;
};
array<MyClass^>^ arrSensor() {
int i;
array< MyClass^ >^ local = gcnew array< MyClass^ >(2);
for (i = 0; i < 2; i++) {
local[i] = gcnew MyClass;
local[i]->m_i = i;
}
return local;
}
2) create array to store sensor index to do for loop later
HRESULT CSkeletalViewerApp::Nui_Init( )
{
HRESULT hr;
bool result;
//create an array to store two file pointers
FILE* mp3DFile[] = { mp3DFile0, mp3DFile1 };
fopen_s(mp3DFile0, "D:/Kinect/KinectCam0.txt", "w+");
fopen_s(mp3DFile1, "D:/Kinect/KinectCam1.txt", "w+");
.
.
if ( !m_pNuiSensor )
{
hr = NuiCreateSensorByIndex(0, &m_pNuiSensor);
//I am not sure about how to utilize this index in this case
.
.
}
if (NuiGetSensorCount(&m_pNuiSensor) > 1)
{
array< MyClass^ >^ SensorIndex;
SensorIndex = arrSensor();
}
}
3) use for loop to store data to different text file using index
void CSkeletalViewerApp::Nui_DrawSkeleton( const NUI_SKELETON_DATA & skel, int windowWidth, int windowHeight )
{
int i;
int h;
for (h = 0; h < 2; h++)
{
//when index point to the current kinect
if (SensorIndex[h] == &m_pNuiSensor)
{
for (i = 0; i < NUI_SKELETON_POSITION_COUNT; i++)
{
m_Points[i] = SkeletonToScreen(skel.SkeletonPositions[i], windowWidth, windowHeight);
memset(mText, 0, 1024);
sprintf(mText, "(%0.3f,%0.3f,%0.3f)", skel.SkeletonPositions[i].x, skel.SkeletonPositions[i].y, skel.SkeletonPositions[i].z);
if (mp3DFile[h]) {
fputs((const char*)mText, mp3DFile[h]);
}
}
if (mp3DFile[h]) {
fputs("\n", mp3DFile[h]);
}
}
}
.
.
}
I am a newbie in this Kinect programming. Thank you very much for your help! :)