glDrawElements() parameters - opengl

I want to render a 3D box by reading its geometry from a VRML file. The indices in the VRML file is given as :
coordIndex
[
0, 1, 2, -1,
2, 3, 0, -1,
3, 2, 4, -1,
4, 5, 3, -1,
5, 4, 7, -1,
7, 6, 5, -1,
6, 7, 1, -1,
1, 0, 6, -1,
6, 0, 3, -1,
3, 5, 6, -1,
1, 7, 2, -1,
7, 4, 2, -1,
]
I want to call glDrawElements function to render the box but I am not sure about the "count" and "indices" parameter. Should count be 12 indicating the number of faces or 36 denoting the total indices of vertices ? Also, please tell me about the indices array. Should it be like this :
GLint indices[] = {0,1,2,2,3,0,3,2,4,.....,7,4,2};
OR
GLint indices[] = {0,1,2,-1,2,3,0,-1,....,7,4,2};

According to the man page of DrawElements
When glDrawElements is called, it uses count sequential elements from an enabled array
So it would be 36 for the total indices in your indexbuffer.
For the indices array you would have to choose the first version. The indices have to be >= 0 and for 3 consecutive indices a triangle will be drawn.

Indices array should be your first example (always positive numbers, referencing vertex index).
Draw elements count should be the length of your index array. This is usually something like indices.length.

Related

WMesh face shading artifacts in OpenCV

I'm using OpenCV v4.4.0 with gcc v10.1 on Ubuntu 18.04.5. This code snippet:
using namespace std;
using namespace cv;
using namespace cv::viz;
......
vector<Vec3f> points{{0, 0, 0}, {1, 0, 0}, {1, 1, 0}, {0, 1, 0}, {2, 0, 0}, {2, 1, 0}};
vector<int> faces{4, 0, 1, 2, 0, 4, 0, 2, 3, 0, 5, 1, 4, 5, 2, 1};
Viz3d window("Mesh");
WMesh mesh(points, faces);
window.setBackgroundColor(Color::gray());
mesh.setColor(Color::indigo());
mesh.setRenderingProperty(OPACITY, 0.4);
mesh.setRenderingProperty(SHADING, SHADING_FLAT);
mesh.setRenderingProperty(REPRESENTATION, REPRESENTATION_SURFACE);
window.showWidget("mesh", mesh);
window.spin();
creates and displays this planar mesh:
The square on the left is defined as 2 triangles and is shaded uniformly, but the square on the right, which is defined as a single quadrilateral face is not shaded uniformly. Again, the mesh is planar. Why the non-uniformity?
It becomes even more non-uniform when I change shading from SHADING_FLAT to SHADING_GOURAUD:
Can someone explain what is going on here? I know that quadrilateral faces are converted to triangles, but why the shading is non-uniform?
EDIT
As noted by Матвей Вислоух in his answer below, I intended to use:
vector<int> faces{3, 0, 1, 2, 3, 0, 2, 3, 4, 1, 4, 5, 2};
which properly defines two triangular and one quadrilateral face. This solves the problem of artifacts in the left half, but they still remain in the right half:
vector<int> faces{3, 0, 1, 2, 3, 0, 2, 3, 4, 1, 4, 2, 5};
There is a specific rule how opencv unpacks indices from polygon.
if there is a polygon : (5, 1, 4, 5, 2, 0) it consists of 3 triangles: (1,4,5) , (4, 5, 2), (5, 2, 0)
OLD:
vector faces{4, 0, 1, 2, 0, 4, 0, 2, 3, 0, 5, 1, 4, 5, 2, 1};
This means you draw 3 polygons: 2 quads and 1 pentagon.
But by indices I guess that you want to draw 2 triangles, and one quad, so try this:
vector faces{3, 0, 1, 2, 3, 0, 2, 3, 4, 1, 4, 5, 2};

Save a matrix in QSettings

I'm working on my qt chess game, in particular on persistence, so when the MainWindow is closed I have to save the int matrix, which represents the board state. I already wrote the function and it's working well with a matrix that I give for the test
MainWindow::~MainWindow()
{
int boardState2[8][8] = { {-5, -3, -4, -9, 0, -4, -3, -5},
{-1, 0, 0, -1, 0, -1, -1, -1},
{ 0, 0, 0, 0, -1, -2, 0, 0},
{ 0, 0, -1, 0, 0, 0, 0, 0},
{ 0, -1, 0, 1, 1, 4, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 1, 0, 0, 1, 1, 1},
{ 5, 3, 0, 9, 2, 4, 3, 5} };
session.setBoardState(boardState2);
}
This code is in the "MainWindow.cpp" file, I will not show the setBoardState function cause it works as I said, instead the problem is that I should copy the real matrix in this boardState2, in order to store it in the settings file using that setBoardState function. The problem is that the real matrix is in another file "Piece.cpp" and it's a global int matrix. I don't know how to pass it from "Piece.cpp" to "MainWindow.cpp"... I was thinking to 3 solutions:
Pass the matrix from one .cpp to the other through some functions that I don't know
Call the session.setBoardState() function in the Piece destructor, but the problem here is that I have to use the class Session (which has the QSettings) as a singleton. I already tried this but I have problems with the Session constructor
Save the real matrix in a .txt file and then read it from the MainWindow.cpp
If you need more informations I will edit this post, hope you can help me
The c++ keyword extern can help you. Using extern you can use the global matrix which is defined in other cpp file.

How to change the color of each pixel of image using openCV [duplicate]

This question already has answers here:
How to fill OpenCV image with one solid color?
(9 answers)
Closed 4 years ago.
I am new in OpenCV. I have a image what I want is to change the color of each and every pixel of image with any single color.
I found that code but when I run this part of code then a exception is generated.
for (i = 0;i < img1.rows;i++) {
for (j = 0;j < img1.cols;j++) {
img1.at<Vec3b>(i, j) = Vec3b(255, 105, 240);
}
}
Can anyone please tell me the solution.
Or what I found is that this take a lot of time for the conversion So if their is any other approach then please tell me.
// Make a 3 channel image
cv::Mat img(480,640,CV_8UC3);
// Fill entire image with cyan (blue and green)
img = cv::Scalar(255,255,0);
You can use Mat::operator() to select the roi and then assign a value to it.
void main()
{
cv::Mat img = cv::Mat::ones(5, 5, CV_8UC3);
img({2, 4}, {2, 4}) = cv::Vec3b(7, 8, 9);
cout << img;
}
This will print
[ 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0;
1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0;
1, 0, 0, 1, 0, 0, 7, 8, 9, 7, 8, 9, 1, 0, 0;
1, 0, 0, 1, 0, 0, 7, 8, 9, 7, 8, 9, 1, 0, 0;
1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0]
To fill image with single color, use rectangle with CV_FILLED argument.
(there might be some reasons for exception - image was not created, wrong pixel format etc - it is hard to diagnose a problem with given information)

Computing minimum and maximum excess of byte over binary function

I have a function PI (input 0 or 1), which gives PI[0] = -1, PI[1] = 1.
Given a byte B, I would like to have a function computing the minimum excess over PI from left to right. Similarly, I need a function computing the maximum excess over PI from left to right. Example:
PI_MIN[0] = -8, PI_MAX[0] = -1
PI_MIN[1] = -7, PI_MAX[1] = -1
PI_MIN[2] = -6, PI_MAX[2] = -1
PI_MIN[3] = -6, PI_MAX[3] = -1
At the moment I precompute the function values, store these in a universal table, and access it at runtime. Or alternatively I compute the result naively (for loop over bits). For PI_MIN and PI_MAX we have:
static constexpr int8_t PI_MIN[] { -8, -7, -6, -6, -6, -5, -5, -5, -6, -5, -4, -4, -4, -4, -4,
-4, -6, -5, -4, -4, -4, -3, -3, -3, -4, -3, -3, -3, -3, -3, -3, -3, -6, -5, -4, -4, -4, -3, -3, -3, -4, -3, -2, -2,
-2, -2, -2, -2, -4, -3, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -6, -5, -4, -4, -4, -3, -3, -3, -4,
-3, -2, -2, -2, -2, -2, -2, -4, -3, -2, -2, -2, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -4, -3, -2, -2, -2, -1,
-1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -6, -5, -4,
-4, -4, -3, -3, -3, -4, -3, -2, -2, -2, -2, -2, -2, -4, -3, -2, -2, -2, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1,
-4, -3, -2, -2, -2, -1, -1, -1, -2, -1, 0, 0, 0, 0, 0, 0, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, -3,
-2, -2, -2, -1, -1, -1, -2, -1, 0, 0, 0, 0, 0, 0, -2, -1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, -2, -1, 0, 0, 0,
1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
static constexpr int8_t PI_MAX[] { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, 0, 0, 0, 1, 2, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, 0, 0, 0, 1,
2, 0, 0, 0, 0, 0, 0, 1, 2, 1, 1, 1, 2, 2, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0,
1, 2, 1, 1, 1, 2, 2, 2, 3, 4, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 3, 4, 2, 2, 2, 2, 2, 2, 3, 4, 3, 3, 3, 4, 4,
4, 5, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 3, 4, 1, 1, 1, 1,
1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 3, 4, 2, 2, 2, 2, 2, 2, 3, 4, 3, 3, 3, 4, 4, 4, 5, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 3, 4, 2, 2, 2, 2, 2, 2, 3, 4, 3, 3, 3, 4, 4, 4, 5, 6, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 4, 4, 4, 5, 6, 4, 4,
4, 4, 4, 4, 5, 6, 5, 5, 5, 6, 6, 6, 7, 8 };
Unfortunately I couldn't find a pattern for all functions I need to use (e.g. PI_MIN, PI_MAX, but there is more). The question is: how can I find out whether a function exists which can compute this in a non-naive way (i.e., no for loop from left to right in the input byte). My goal is to reach maximum performance, since this function is in the inner-most loop of a larger program.
I'm thankful for any hints!
A non-branching version of pi_min (assuming the loop is unrolled).
/*
Calculate:
min(
pi(b7),
pi(b7)+pi(b6),
pi(b7)+pi(b6)+pi(b5),
pi(b7)+pi(b6)+pi(b5)+pi(b4),
pi(b7)+pi(b6)+pi(b5)+pi(b4)+pi(b3),
pi(b7)+pi(b6)+pi(b5)+pi(b4)+pi(b3)+pi(b2),
pi(b7)+pi(b6)+pi(b5)+pi(b4)+pi(b3)+pi(b2)+pi(b1),
pi(b7)+pi(b6)+pi(b5)+pi(b4)+pi(b3)+pi(b2)+pi(b1)+pi(b0))
Where,
pi(b) = b ? 1 : -1
and bits in byte b are numbered with the least significant bit (LSB) as 0.
This problem is essentially one of counting leading zeros where a string
of leading zeros may be interrupted by a one if it is eventually followed
by a zero. What happens if there are no leading zeros, then the count is -1.
The algorithm uses two stacks, "c0" and "c1". c0 is the leading zero count
and c1 is a stack of potentially intervening 1's.
foreach bit (following 4 cases are mutually exclusive, only 1 will execute)
0: if the '1' stack is empty => push a '0' onto the '0' stack
0: if the '1' stack is not empty => pop a '1'
1: if the first bit is a '1' => put the '0' stack in underflow state
1: if it is not the first bit => push a '1' onto the '1' stack
return -c0 because zeros actually count as -1
*/
int pi_min(uint8_t byte) {
int c0 = 0;
int c1 = 0;
for (int i = 0; i < 8; ++i) {
uint8_t b = !!(byte & (1 << (7-i)));
c0 -= (b & (i == 0));
c0 += ((!b) & (0 >= c1));
c1 -= ((!b) & (0 < c1));
c1 += (b & (i != 0));
}
return -c0;
}
int pi_max(uint8_t byte) { return -pi_min(~byte); }
// The obvious version for comparison.
int pi(uint8_t bit) { return bit ? 1 : -1; }
int pi_min_simple(uint8_t byte) {
int sum = 0;
int m = 9;
for (int i = 0; i < 8; ++i) {
uint8_t b = byte & (1 << (7-i));
sum += pi(b);
m = std::min(m, sum);
}
return m;
}
Sorry for the delay, I have measured the performance of the different methods now.
http://s12.postimg.org/v400xibxp/prefix_Sums.png
I am very glad to see that the solution suggested by Adam Burry is very efficient (the yellow line). As you can see, even the naive algorithm is slightly faster than the table lookup (green and brown lines) for both minimum and maximum prefix sum computation, which are indeed very similar... The most surprising thing (at least for me) is the terrible performance of maxExcess (which simply returned -pi_min(~byte), as Adam Burry suggested, where pi_min is the function representing the yellow line). I guess that it has to do with the additional overhead to compute the binary complement of each and every byte being analyzed, so I will switch to the original algorithm (pi_min) and return -c1 instead to implement pi_max.

how to create own matrix in openCV

Hi in the following link http://www.prism.gatech.edu/~ahuaman3/docs/OpenCV_Docs/tutorials/basic_0/basic_0.html it is shown how to create a uniform matrix where all elements are 23.
How can I create a matrix of
-1, -1, -1, -1, -1, -1, -1,
0, 0, 0, 0, 0, 0, 0,
2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2,
0, 0, 0, 0, 0, 0, 0,
-1, -1, -1, -1, -1, -1, -1,
in openCV. I want the user to input the no. of rows of 2. How I can do that?
uchar mydata[]={1, 2, 1, 1, 2, 1, 1, 2, 1};
cv::Mat mymat(3,3,CV_8UC1,mydata);
mymat:
1 2 1
1 2 1
1 2 1