C++ OpenGL: How to make a second circle over the cylinder?
up vote
2
down vote
favorite
So basically I have a cylinder with a base (there is a circle under the cylinder), but there is not circle above. I want to make it a closed cylinder.
Here is the important part from my bool CMyApp::Init() function:
Vertex vert[(N+1)*(M+1) + N+2]; //NxM rectangle for our parametric equation
for (int i=0; i<=N; ++i)
for (int j=0; j<=M; ++j)
{
float u = i/(float)N;
float v = j/(float)M;
vert[i + j*(N+1)].p = GetUV(u, v);
vert[i + j*(N+1)].c = glm::normalize( vert[i + j*(N+1)].p );
}
vert[(N + 1)*(M + 1)].p = glm::vec3(0, 0, 0); //center point for cone base
vert[(N + 1)*(M + 1)].c = glm::vec3(0, 0, 0);
for (int i = 0; i <= N; i++) {
vert[(N + 1)*(M + 1) + 1 + i].p = vert[(N)-i].p; //cone base
vert[(N + 1)*(M + 1) + 1 + i].c = vert[(N)-i].c;
}
Render function:
glDrawElements( GL_TRIANGLES,
3*2*(N)*(M),
GL_UNSIGNED_SHORT,
0);
glDrawArrays(GL_TRIANGLE_FAN, (N + 1)*(M + 1) + 1, (N + 2)); //draw cone base
The "cone base" is there because I started this project from a "Draw a cone" project.
How can I make a second circle but above the cylinder?
Edit:
M,N: Const numbers (20 and 10)
My parametric equation (which is a FUNCTION called GetUV() ):
u *= 2*3.1415f;
float cu = cosf(u), su = sinf(u), cv = cosf(v), sv = sinf(v);
float M = 2.f;
float r = 0.5;
float m = v*M;
return glm::vec3(r*sinf(u), m, r*cosf(u));
How I create Indices (inside Init() function):
GLushort indices[3*2*(N)*(M)];
for (int i=0; i<N; ++i)
for (int j=0; j<M; ++j)
{
indices[6*i + j*3*2*(N) + 0] = (i) + (j)* (N+1);
indices[6*i + j*3*2*(N) + 1] = (i+1) + (j)* (N+1);
indices[6*i + j*3*2*(N) + 2] = (i) + (j+1)*(N+1);
indices[6*i + j*3*2*(N) + 3] = (i+1) + (j)* (N+1);
indices[6*i + j*3*2*(N) + 4] = (i+1) + (j+1)*(N+1);
indices[6*i + j*3*2*(N) + 5] = (i) + (j+1)*(N+1);
}
c++ opengl graphics 3d glm-math
New contributor
add a comment |
up vote
2
down vote
favorite
So basically I have a cylinder with a base (there is a circle under the cylinder), but there is not circle above. I want to make it a closed cylinder.
Here is the important part from my bool CMyApp::Init() function:
Vertex vert[(N+1)*(M+1) + N+2]; //NxM rectangle for our parametric equation
for (int i=0; i<=N; ++i)
for (int j=0; j<=M; ++j)
{
float u = i/(float)N;
float v = j/(float)M;
vert[i + j*(N+1)].p = GetUV(u, v);
vert[i + j*(N+1)].c = glm::normalize( vert[i + j*(N+1)].p );
}
vert[(N + 1)*(M + 1)].p = glm::vec3(0, 0, 0); //center point for cone base
vert[(N + 1)*(M + 1)].c = glm::vec3(0, 0, 0);
for (int i = 0; i <= N; i++) {
vert[(N + 1)*(M + 1) + 1 + i].p = vert[(N)-i].p; //cone base
vert[(N + 1)*(M + 1) + 1 + i].c = vert[(N)-i].c;
}
Render function:
glDrawElements( GL_TRIANGLES,
3*2*(N)*(M),
GL_UNSIGNED_SHORT,
0);
glDrawArrays(GL_TRIANGLE_FAN, (N + 1)*(M + 1) + 1, (N + 2)); //draw cone base
The "cone base" is there because I started this project from a "Draw a cone" project.
How can I make a second circle but above the cylinder?
Edit:
M,N: Const numbers (20 and 10)
My parametric equation (which is a FUNCTION called GetUV() ):
u *= 2*3.1415f;
float cu = cosf(u), su = sinf(u), cv = cosf(v), sv = sinf(v);
float M = 2.f;
float r = 0.5;
float m = v*M;
return glm::vec3(r*sinf(u), m, r*cosf(u));
How I create Indices (inside Init() function):
GLushort indices[3*2*(N)*(M)];
for (int i=0; i<N; ++i)
for (int j=0; j<M; ++j)
{
indices[6*i + j*3*2*(N) + 0] = (i) + (j)* (N+1);
indices[6*i + j*3*2*(N) + 1] = (i+1) + (j)* (N+1);
indices[6*i + j*3*2*(N) + 2] = (i) + (j+1)*(N+1);
indices[6*i + j*3*2*(N) + 3] = (i+1) + (j)* (N+1);
indices[6*i + j*3*2*(N) + 4] = (i+1) + (j+1)*(N+1);
indices[6*i + j*3*2*(N) + 5] = (i) + (j+1)*(N+1);
}
c++ opengl graphics 3d glm-math
New contributor
1
what isM,N
? you need just 2 circles ... but I am not seeing even the one where are anysin,cos
? The usual is compute X,Y as parametric circle and Z is constant (different for each base, their distance is the cylinder height)
– Spektre
Nov 17 at 19:11
... and what doesGetUV
do? WhyglDrawElements
andglDrawArrays
? Where is the element list?
– Rabbid76
Nov 17 at 19:14
Sorry, I edited the post.
– József Huszkó
Nov 17 at 19:28
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
So basically I have a cylinder with a base (there is a circle under the cylinder), but there is not circle above. I want to make it a closed cylinder.
Here is the important part from my bool CMyApp::Init() function:
Vertex vert[(N+1)*(M+1) + N+2]; //NxM rectangle for our parametric equation
for (int i=0; i<=N; ++i)
for (int j=0; j<=M; ++j)
{
float u = i/(float)N;
float v = j/(float)M;
vert[i + j*(N+1)].p = GetUV(u, v);
vert[i + j*(N+1)].c = glm::normalize( vert[i + j*(N+1)].p );
}
vert[(N + 1)*(M + 1)].p = glm::vec3(0, 0, 0); //center point for cone base
vert[(N + 1)*(M + 1)].c = glm::vec3(0, 0, 0);
for (int i = 0; i <= N; i++) {
vert[(N + 1)*(M + 1) + 1 + i].p = vert[(N)-i].p; //cone base
vert[(N + 1)*(M + 1) + 1 + i].c = vert[(N)-i].c;
}
Render function:
glDrawElements( GL_TRIANGLES,
3*2*(N)*(M),
GL_UNSIGNED_SHORT,
0);
glDrawArrays(GL_TRIANGLE_FAN, (N + 1)*(M + 1) + 1, (N + 2)); //draw cone base
The "cone base" is there because I started this project from a "Draw a cone" project.
How can I make a second circle but above the cylinder?
Edit:
M,N: Const numbers (20 and 10)
My parametric equation (which is a FUNCTION called GetUV() ):
u *= 2*3.1415f;
float cu = cosf(u), su = sinf(u), cv = cosf(v), sv = sinf(v);
float M = 2.f;
float r = 0.5;
float m = v*M;
return glm::vec3(r*sinf(u), m, r*cosf(u));
How I create Indices (inside Init() function):
GLushort indices[3*2*(N)*(M)];
for (int i=0; i<N; ++i)
for (int j=0; j<M; ++j)
{
indices[6*i + j*3*2*(N) + 0] = (i) + (j)* (N+1);
indices[6*i + j*3*2*(N) + 1] = (i+1) + (j)* (N+1);
indices[6*i + j*3*2*(N) + 2] = (i) + (j+1)*(N+1);
indices[6*i + j*3*2*(N) + 3] = (i+1) + (j)* (N+1);
indices[6*i + j*3*2*(N) + 4] = (i+1) + (j+1)*(N+1);
indices[6*i + j*3*2*(N) + 5] = (i) + (j+1)*(N+1);
}
c++ opengl graphics 3d glm-math
New contributor
So basically I have a cylinder with a base (there is a circle under the cylinder), but there is not circle above. I want to make it a closed cylinder.
Here is the important part from my bool CMyApp::Init() function:
Vertex vert[(N+1)*(M+1) + N+2]; //NxM rectangle for our parametric equation
for (int i=0; i<=N; ++i)
for (int j=0; j<=M; ++j)
{
float u = i/(float)N;
float v = j/(float)M;
vert[i + j*(N+1)].p = GetUV(u, v);
vert[i + j*(N+1)].c = glm::normalize( vert[i + j*(N+1)].p );
}
vert[(N + 1)*(M + 1)].p = glm::vec3(0, 0, 0); //center point for cone base
vert[(N + 1)*(M + 1)].c = glm::vec3(0, 0, 0);
for (int i = 0; i <= N; i++) {
vert[(N + 1)*(M + 1) + 1 + i].p = vert[(N)-i].p; //cone base
vert[(N + 1)*(M + 1) + 1 + i].c = vert[(N)-i].c;
}
Render function:
glDrawElements( GL_TRIANGLES,
3*2*(N)*(M),
GL_UNSIGNED_SHORT,
0);
glDrawArrays(GL_TRIANGLE_FAN, (N + 1)*(M + 1) + 1, (N + 2)); //draw cone base
The "cone base" is there because I started this project from a "Draw a cone" project.
How can I make a second circle but above the cylinder?
Edit:
M,N: Const numbers (20 and 10)
My parametric equation (which is a FUNCTION called GetUV() ):
u *= 2*3.1415f;
float cu = cosf(u), su = sinf(u), cv = cosf(v), sv = sinf(v);
float M = 2.f;
float r = 0.5;
float m = v*M;
return glm::vec3(r*sinf(u), m, r*cosf(u));
How I create Indices (inside Init() function):
GLushort indices[3*2*(N)*(M)];
for (int i=0; i<N; ++i)
for (int j=0; j<M; ++j)
{
indices[6*i + j*3*2*(N) + 0] = (i) + (j)* (N+1);
indices[6*i + j*3*2*(N) + 1] = (i+1) + (j)* (N+1);
indices[6*i + j*3*2*(N) + 2] = (i) + (j+1)*(N+1);
indices[6*i + j*3*2*(N) + 3] = (i+1) + (j)* (N+1);
indices[6*i + j*3*2*(N) + 4] = (i+1) + (j+1)*(N+1);
indices[6*i + j*3*2*(N) + 5] = (i) + (j+1)*(N+1);
}
c++ opengl graphics 3d glm-math
c++ opengl graphics 3d glm-math
New contributor
New contributor
edited Nov 18 at 17:31
New contributor
asked Nov 17 at 18:37
József Huszkó
112
112
New contributor
New contributor
1
what isM,N
? you need just 2 circles ... but I am not seeing even the one where are anysin,cos
? The usual is compute X,Y as parametric circle and Z is constant (different for each base, their distance is the cylinder height)
– Spektre
Nov 17 at 19:11
... and what doesGetUV
do? WhyglDrawElements
andglDrawArrays
? Where is the element list?
– Rabbid76
Nov 17 at 19:14
Sorry, I edited the post.
– József Huszkó
Nov 17 at 19:28
add a comment |
1
what isM,N
? you need just 2 circles ... but I am not seeing even the one where are anysin,cos
? The usual is compute X,Y as parametric circle and Z is constant (different for each base, their distance is the cylinder height)
– Spektre
Nov 17 at 19:11
... and what doesGetUV
do? WhyglDrawElements
andglDrawArrays
? Where is the element list?
– Rabbid76
Nov 17 at 19:14
Sorry, I edited the post.
– József Huszkó
Nov 17 at 19:28
1
1
what is
M,N
? you need just 2 circles ... but I am not seeing even the one where are any sin,cos
? The usual is compute X,Y as parametric circle and Z is constant (different for each base, their distance is the cylinder height)– Spektre
Nov 17 at 19:11
what is
M,N
? you need just 2 circles ... but I am not seeing even the one where are any sin,cos
? The usual is compute X,Y as parametric circle and Z is constant (different for each base, their distance is the cylinder height)– Spektre
Nov 17 at 19:11
... and what does
GetUV
do? Why glDrawElements
and glDrawArrays
? Where is the element list?– Rabbid76
Nov 17 at 19:14
... and what does
GetUV
do? Why glDrawElements
and glDrawArrays
? Where is the element list?– Rabbid76
Nov 17 at 19:14
Sorry, I edited the post.
– József Huszkó
Nov 17 at 19:28
Sorry, I edited the post.
– József Huszkó
Nov 17 at 19:28
add a comment |
2 Answers
2
active
oldest
votes
up vote
0
down vote
The easiest way to draw the other circular cap is to just change the model matrix of the circle and make the draw call again. So if you're doing something like this before calling glDrawArrays()
:
glm::mat4 modelViewMatrix = calculateModelViewMatrix();
glUniformMatrix4fv(modelViewLocation, 1, FALSE, modelViewMatrix);
Do the same thing but translate the modelViewMatrix
so that it's at the other end of the cylinder.
My goal is to make the other circle in the same way the first circle draws, with Vertex vectors.
– József Huszkó
Nov 17 at 19:57
You can do the same thing by hand by copying the geometry and doing the translation on the CPU then uploading it to the GPU again, but it's going to be far less efficient. That may not be a big deal in this context, but you should get out of the habit of uploading the same geometry multiple times because it's an antipattern when writing performant 3D code.
– user1118321
Nov 17 at 20:00
add a comment |
up vote
0
down vote
So N
is number of points on the circle circumference and M
is the number of points per height...
LOL in your GetUV
you are computing cu,su,cv,sv
but not using them, instead you use the same sin
and cos
call again. if I see it right u=<0,1>
maps circumference of the circle/cylinder (XZ plane circle) and v=<0,1>
maps the height (Y). But it looks like that the function itself works as should (just slowly than possible) appart of that inaccurate M_PI
usage which might cause artifacts.
First problem I see is
vert[i + j*(N+1)].c = glm::normalize( vert[i + j*(N+1)].p );
I would get rid of that line as it will create the cone ... which you do not want anymore (btw. very weird and slow method of cone creation)
Also the i + j*(N+1)
is ugly instead I would do:
for (int ix=0,j=0; j<=M; j++)
for (int i=0; i<=N; i++,ix++)
{
float u = i/(float)N;
float v = j/(float)M;
vert[ix].p = GetUV(u, v);
}
Next problem you got is wrong usage of the Draw methods ... as you want a grid of points instead of just 2 circles you divided the stuff into GL_TRIANGLE_FAN
and GL_TRIANGLES
. That was almost correct but you should have:
2x GL_TRIANGLE_FAN
one for each base
1x GL_TRIANGLES
or GL_QUADS for the rest
as you want to use indices it is basically simpler/faster to use all as triangles and feed the indices buffer correctly so you got just single draw call. Sadly we do not see the part of code where you are computing the indices ...
Why N+1
and M+1
points? You do not need to duplicate first point in vert
you can do it in indices instead...
Hope the VBO related part of the code is correct ...
Also beware that faces of the other circle should have points in reverse order so GL_CULL_FACE
will cull of faces correctly ...
[Edit1] C++ example
Anyway if you want to use normals latter on you should also duplicate the caps due to different normal on the edge... If I put all together in my style of coding I got this:
//---------------------------------------------------------------------------
const int M=20; // points per circle circumference
const int N=10; // point per cylinder height
const int pnts=3*((M*(N+2))+2); // 3* number of points
const int facs=3*M*(N+N+2); // 3* number of indices
float pnt[pnts]; // (x,y,z) position per each point
float nor[pnts]; // (x,y,z) normal per each point
int fac[facs]; // (i0,i1,i2) indices per each TRIANGLE
//---------------------------------------------------------------------------
void cylinder_init(float r,float h)
{
int i,j,ix,i0,i1,i2,i3;
float x,y,z,a,da,dz;
// compute position and normals
ix=0;
dz=h/double(N-1);
da=2.0*M_PI/double(M);
for (z=-0.5*h,j=0;j<N;j++,z+=dz) // circles
for (a=0.0,i=0;i<M;i++,a+=da)
{
x=cos(a);
y=sin(a);
pnt[ix]=r*x; nor[ix]=x; ix++;
pnt[ix]=r*y; nor[ix]=y; ix++;
pnt[ix]=z; nor[ix]=0.0; ix++;
}
pnt[ix]= 0.0; nor[ix]= 0.0; ix++; // top cap
pnt[ix]= 0.0; nor[ix]= 0.0; ix++;
pnt[ix]=+0.5*h; nor[ix]=+1.0; ix++;
for (j=ix-3*(M+1),i=0;i<M;i++)
{
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]=+1.0; ix++; j++;
}
pnt[ix]= 0.0; nor[ix]= 0.0; ix++; // bottom cap
pnt[ix]= 0.0; nor[ix]= 0.0; ix++;
pnt[ix]=-0.5*h; nor[ix]=-1.0; ix++;
for (j=0,i=0;i<M;i++)
{
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]=-1.0; ix++; j++;
}
// compute triangle indices
ix=0; i0=M-1; i1=0; i2=i0+M; i3=i1+M; // circles
for (j=0;j<N-1;j++,i0+=M,i2+=M)
for (i=0;i<M;i++,i0=i1,i1++,i2=i3,i3++)
{
fac[ix]=i0; ix++;
fac[ix]=i1; ix++;
fac[ix]=i2; ix++;
fac[ix]=i2; ix++;
fac[ix]=i1; ix++;
fac[ix]=i3; ix++;
}
i2=M*N; i0=i2+M; i1=i2+1; // top cap
for (i=0;i<M;i++,i0=i1,i1++)
{
fac[ix]=i0; ix++;
fac[ix]=i1; ix++;
fac[ix]=i2; ix++;
}
i2+=M+1; i0=i2+M; i1=i2+1; // bottom cap
for (i=0;i<M;i++,i0=i1,i1++)
{
fac[ix]=i2; ix++;
fac[ix]=i1; ix++;
fac[ix]=i0; ix++;
}
}
//---------------------------------------------------------------------------
And preview:
You just use single draw with GL_TRIANGLES
on the whole fac[facs]
indices buffer.
Thank you for your answer, I edited the post and added the Indices part.
– József Huszkó
Nov 18 at 17:32
@JózsefHuszkó I updated my answer also ...
– Spektre
Nov 18 at 19:39
@JózsefHuszkó how is it going did you solve your issue or not?
– Spektre
7 hours ago
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
The easiest way to draw the other circular cap is to just change the model matrix of the circle and make the draw call again. So if you're doing something like this before calling glDrawArrays()
:
glm::mat4 modelViewMatrix = calculateModelViewMatrix();
glUniformMatrix4fv(modelViewLocation, 1, FALSE, modelViewMatrix);
Do the same thing but translate the modelViewMatrix
so that it's at the other end of the cylinder.
My goal is to make the other circle in the same way the first circle draws, with Vertex vectors.
– József Huszkó
Nov 17 at 19:57
You can do the same thing by hand by copying the geometry and doing the translation on the CPU then uploading it to the GPU again, but it's going to be far less efficient. That may not be a big deal in this context, but you should get out of the habit of uploading the same geometry multiple times because it's an antipattern when writing performant 3D code.
– user1118321
Nov 17 at 20:00
add a comment |
up vote
0
down vote
The easiest way to draw the other circular cap is to just change the model matrix of the circle and make the draw call again. So if you're doing something like this before calling glDrawArrays()
:
glm::mat4 modelViewMatrix = calculateModelViewMatrix();
glUniformMatrix4fv(modelViewLocation, 1, FALSE, modelViewMatrix);
Do the same thing but translate the modelViewMatrix
so that it's at the other end of the cylinder.
My goal is to make the other circle in the same way the first circle draws, with Vertex vectors.
– József Huszkó
Nov 17 at 19:57
You can do the same thing by hand by copying the geometry and doing the translation on the CPU then uploading it to the GPU again, but it's going to be far less efficient. That may not be a big deal in this context, but you should get out of the habit of uploading the same geometry multiple times because it's an antipattern when writing performant 3D code.
– user1118321
Nov 17 at 20:00
add a comment |
up vote
0
down vote
up vote
0
down vote
The easiest way to draw the other circular cap is to just change the model matrix of the circle and make the draw call again. So if you're doing something like this before calling glDrawArrays()
:
glm::mat4 modelViewMatrix = calculateModelViewMatrix();
glUniformMatrix4fv(modelViewLocation, 1, FALSE, modelViewMatrix);
Do the same thing but translate the modelViewMatrix
so that it's at the other end of the cylinder.
The easiest way to draw the other circular cap is to just change the model matrix of the circle and make the draw call again. So if you're doing something like this before calling glDrawArrays()
:
glm::mat4 modelViewMatrix = calculateModelViewMatrix();
glUniformMatrix4fv(modelViewLocation, 1, FALSE, modelViewMatrix);
Do the same thing but translate the modelViewMatrix
so that it's at the other end of the cylinder.
answered Nov 17 at 19:43
user1118321
19.2k43963
19.2k43963
My goal is to make the other circle in the same way the first circle draws, with Vertex vectors.
– József Huszkó
Nov 17 at 19:57
You can do the same thing by hand by copying the geometry and doing the translation on the CPU then uploading it to the GPU again, but it's going to be far less efficient. That may not be a big deal in this context, but you should get out of the habit of uploading the same geometry multiple times because it's an antipattern when writing performant 3D code.
– user1118321
Nov 17 at 20:00
add a comment |
My goal is to make the other circle in the same way the first circle draws, with Vertex vectors.
– József Huszkó
Nov 17 at 19:57
You can do the same thing by hand by copying the geometry and doing the translation on the CPU then uploading it to the GPU again, but it's going to be far less efficient. That may not be a big deal in this context, but you should get out of the habit of uploading the same geometry multiple times because it's an antipattern when writing performant 3D code.
– user1118321
Nov 17 at 20:00
My goal is to make the other circle in the same way the first circle draws, with Vertex vectors.
– József Huszkó
Nov 17 at 19:57
My goal is to make the other circle in the same way the first circle draws, with Vertex vectors.
– József Huszkó
Nov 17 at 19:57
You can do the same thing by hand by copying the geometry and doing the translation on the CPU then uploading it to the GPU again, but it's going to be far less efficient. That may not be a big deal in this context, but you should get out of the habit of uploading the same geometry multiple times because it's an antipattern when writing performant 3D code.
– user1118321
Nov 17 at 20:00
You can do the same thing by hand by copying the geometry and doing the translation on the CPU then uploading it to the GPU again, but it's going to be far less efficient. That may not be a big deal in this context, but you should get out of the habit of uploading the same geometry multiple times because it's an antipattern when writing performant 3D code.
– user1118321
Nov 17 at 20:00
add a comment |
up vote
0
down vote
So N
is number of points on the circle circumference and M
is the number of points per height...
LOL in your GetUV
you are computing cu,su,cv,sv
but not using them, instead you use the same sin
and cos
call again. if I see it right u=<0,1>
maps circumference of the circle/cylinder (XZ plane circle) and v=<0,1>
maps the height (Y). But it looks like that the function itself works as should (just slowly than possible) appart of that inaccurate M_PI
usage which might cause artifacts.
First problem I see is
vert[i + j*(N+1)].c = glm::normalize( vert[i + j*(N+1)].p );
I would get rid of that line as it will create the cone ... which you do not want anymore (btw. very weird and slow method of cone creation)
Also the i + j*(N+1)
is ugly instead I would do:
for (int ix=0,j=0; j<=M; j++)
for (int i=0; i<=N; i++,ix++)
{
float u = i/(float)N;
float v = j/(float)M;
vert[ix].p = GetUV(u, v);
}
Next problem you got is wrong usage of the Draw methods ... as you want a grid of points instead of just 2 circles you divided the stuff into GL_TRIANGLE_FAN
and GL_TRIANGLES
. That was almost correct but you should have:
2x GL_TRIANGLE_FAN
one for each base
1x GL_TRIANGLES
or GL_QUADS for the rest
as you want to use indices it is basically simpler/faster to use all as triangles and feed the indices buffer correctly so you got just single draw call. Sadly we do not see the part of code where you are computing the indices ...
Why N+1
and M+1
points? You do not need to duplicate first point in vert
you can do it in indices instead...
Hope the VBO related part of the code is correct ...
Also beware that faces of the other circle should have points in reverse order so GL_CULL_FACE
will cull of faces correctly ...
[Edit1] C++ example
Anyway if you want to use normals latter on you should also duplicate the caps due to different normal on the edge... If I put all together in my style of coding I got this:
//---------------------------------------------------------------------------
const int M=20; // points per circle circumference
const int N=10; // point per cylinder height
const int pnts=3*((M*(N+2))+2); // 3* number of points
const int facs=3*M*(N+N+2); // 3* number of indices
float pnt[pnts]; // (x,y,z) position per each point
float nor[pnts]; // (x,y,z) normal per each point
int fac[facs]; // (i0,i1,i2) indices per each TRIANGLE
//---------------------------------------------------------------------------
void cylinder_init(float r,float h)
{
int i,j,ix,i0,i1,i2,i3;
float x,y,z,a,da,dz;
// compute position and normals
ix=0;
dz=h/double(N-1);
da=2.0*M_PI/double(M);
for (z=-0.5*h,j=0;j<N;j++,z+=dz) // circles
for (a=0.0,i=0;i<M;i++,a+=da)
{
x=cos(a);
y=sin(a);
pnt[ix]=r*x; nor[ix]=x; ix++;
pnt[ix]=r*y; nor[ix]=y; ix++;
pnt[ix]=z; nor[ix]=0.0; ix++;
}
pnt[ix]= 0.0; nor[ix]= 0.0; ix++; // top cap
pnt[ix]= 0.0; nor[ix]= 0.0; ix++;
pnt[ix]=+0.5*h; nor[ix]=+1.0; ix++;
for (j=ix-3*(M+1),i=0;i<M;i++)
{
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]=+1.0; ix++; j++;
}
pnt[ix]= 0.0; nor[ix]= 0.0; ix++; // bottom cap
pnt[ix]= 0.0; nor[ix]= 0.0; ix++;
pnt[ix]=-0.5*h; nor[ix]=-1.0; ix++;
for (j=0,i=0;i<M;i++)
{
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]=-1.0; ix++; j++;
}
// compute triangle indices
ix=0; i0=M-1; i1=0; i2=i0+M; i3=i1+M; // circles
for (j=0;j<N-1;j++,i0+=M,i2+=M)
for (i=0;i<M;i++,i0=i1,i1++,i2=i3,i3++)
{
fac[ix]=i0; ix++;
fac[ix]=i1; ix++;
fac[ix]=i2; ix++;
fac[ix]=i2; ix++;
fac[ix]=i1; ix++;
fac[ix]=i3; ix++;
}
i2=M*N; i0=i2+M; i1=i2+1; // top cap
for (i=0;i<M;i++,i0=i1,i1++)
{
fac[ix]=i0; ix++;
fac[ix]=i1; ix++;
fac[ix]=i2; ix++;
}
i2+=M+1; i0=i2+M; i1=i2+1; // bottom cap
for (i=0;i<M;i++,i0=i1,i1++)
{
fac[ix]=i2; ix++;
fac[ix]=i1; ix++;
fac[ix]=i0; ix++;
}
}
//---------------------------------------------------------------------------
And preview:
You just use single draw with GL_TRIANGLES
on the whole fac[facs]
indices buffer.
Thank you for your answer, I edited the post and added the Indices part.
– József Huszkó
Nov 18 at 17:32
@JózsefHuszkó I updated my answer also ...
– Spektre
Nov 18 at 19:39
@JózsefHuszkó how is it going did you solve your issue or not?
– Spektre
7 hours ago
add a comment |
up vote
0
down vote
So N
is number of points on the circle circumference and M
is the number of points per height...
LOL in your GetUV
you are computing cu,su,cv,sv
but not using them, instead you use the same sin
and cos
call again. if I see it right u=<0,1>
maps circumference of the circle/cylinder (XZ plane circle) and v=<0,1>
maps the height (Y). But it looks like that the function itself works as should (just slowly than possible) appart of that inaccurate M_PI
usage which might cause artifacts.
First problem I see is
vert[i + j*(N+1)].c = glm::normalize( vert[i + j*(N+1)].p );
I would get rid of that line as it will create the cone ... which you do not want anymore (btw. very weird and slow method of cone creation)
Also the i + j*(N+1)
is ugly instead I would do:
for (int ix=0,j=0; j<=M; j++)
for (int i=0; i<=N; i++,ix++)
{
float u = i/(float)N;
float v = j/(float)M;
vert[ix].p = GetUV(u, v);
}
Next problem you got is wrong usage of the Draw methods ... as you want a grid of points instead of just 2 circles you divided the stuff into GL_TRIANGLE_FAN
and GL_TRIANGLES
. That was almost correct but you should have:
2x GL_TRIANGLE_FAN
one for each base
1x GL_TRIANGLES
or GL_QUADS for the rest
as you want to use indices it is basically simpler/faster to use all as triangles and feed the indices buffer correctly so you got just single draw call. Sadly we do not see the part of code where you are computing the indices ...
Why N+1
and M+1
points? You do not need to duplicate first point in vert
you can do it in indices instead...
Hope the VBO related part of the code is correct ...
Also beware that faces of the other circle should have points in reverse order so GL_CULL_FACE
will cull of faces correctly ...
[Edit1] C++ example
Anyway if you want to use normals latter on you should also duplicate the caps due to different normal on the edge... If I put all together in my style of coding I got this:
//---------------------------------------------------------------------------
const int M=20; // points per circle circumference
const int N=10; // point per cylinder height
const int pnts=3*((M*(N+2))+2); // 3* number of points
const int facs=3*M*(N+N+2); // 3* number of indices
float pnt[pnts]; // (x,y,z) position per each point
float nor[pnts]; // (x,y,z) normal per each point
int fac[facs]; // (i0,i1,i2) indices per each TRIANGLE
//---------------------------------------------------------------------------
void cylinder_init(float r,float h)
{
int i,j,ix,i0,i1,i2,i3;
float x,y,z,a,da,dz;
// compute position and normals
ix=0;
dz=h/double(N-1);
da=2.0*M_PI/double(M);
for (z=-0.5*h,j=0;j<N;j++,z+=dz) // circles
for (a=0.0,i=0;i<M;i++,a+=da)
{
x=cos(a);
y=sin(a);
pnt[ix]=r*x; nor[ix]=x; ix++;
pnt[ix]=r*y; nor[ix]=y; ix++;
pnt[ix]=z; nor[ix]=0.0; ix++;
}
pnt[ix]= 0.0; nor[ix]= 0.0; ix++; // top cap
pnt[ix]= 0.0; nor[ix]= 0.0; ix++;
pnt[ix]=+0.5*h; nor[ix]=+1.0; ix++;
for (j=ix-3*(M+1),i=0;i<M;i++)
{
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]=+1.0; ix++; j++;
}
pnt[ix]= 0.0; nor[ix]= 0.0; ix++; // bottom cap
pnt[ix]= 0.0; nor[ix]= 0.0; ix++;
pnt[ix]=-0.5*h; nor[ix]=-1.0; ix++;
for (j=0,i=0;i<M;i++)
{
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]=-1.0; ix++; j++;
}
// compute triangle indices
ix=0; i0=M-1; i1=0; i2=i0+M; i3=i1+M; // circles
for (j=0;j<N-1;j++,i0+=M,i2+=M)
for (i=0;i<M;i++,i0=i1,i1++,i2=i3,i3++)
{
fac[ix]=i0; ix++;
fac[ix]=i1; ix++;
fac[ix]=i2; ix++;
fac[ix]=i2; ix++;
fac[ix]=i1; ix++;
fac[ix]=i3; ix++;
}
i2=M*N; i0=i2+M; i1=i2+1; // top cap
for (i=0;i<M;i++,i0=i1,i1++)
{
fac[ix]=i0; ix++;
fac[ix]=i1; ix++;
fac[ix]=i2; ix++;
}
i2+=M+1; i0=i2+M; i1=i2+1; // bottom cap
for (i=0;i<M;i++,i0=i1,i1++)
{
fac[ix]=i2; ix++;
fac[ix]=i1; ix++;
fac[ix]=i0; ix++;
}
}
//---------------------------------------------------------------------------
And preview:
You just use single draw with GL_TRIANGLES
on the whole fac[facs]
indices buffer.
Thank you for your answer, I edited the post and added the Indices part.
– József Huszkó
Nov 18 at 17:32
@JózsefHuszkó I updated my answer also ...
– Spektre
Nov 18 at 19:39
@JózsefHuszkó how is it going did you solve your issue or not?
– Spektre
7 hours ago
add a comment |
up vote
0
down vote
up vote
0
down vote
So N
is number of points on the circle circumference and M
is the number of points per height...
LOL in your GetUV
you are computing cu,su,cv,sv
but not using them, instead you use the same sin
and cos
call again. if I see it right u=<0,1>
maps circumference of the circle/cylinder (XZ plane circle) and v=<0,1>
maps the height (Y). But it looks like that the function itself works as should (just slowly than possible) appart of that inaccurate M_PI
usage which might cause artifacts.
First problem I see is
vert[i + j*(N+1)].c = glm::normalize( vert[i + j*(N+1)].p );
I would get rid of that line as it will create the cone ... which you do not want anymore (btw. very weird and slow method of cone creation)
Also the i + j*(N+1)
is ugly instead I would do:
for (int ix=0,j=0; j<=M; j++)
for (int i=0; i<=N; i++,ix++)
{
float u = i/(float)N;
float v = j/(float)M;
vert[ix].p = GetUV(u, v);
}
Next problem you got is wrong usage of the Draw methods ... as you want a grid of points instead of just 2 circles you divided the stuff into GL_TRIANGLE_FAN
and GL_TRIANGLES
. That was almost correct but you should have:
2x GL_TRIANGLE_FAN
one for each base
1x GL_TRIANGLES
or GL_QUADS for the rest
as you want to use indices it is basically simpler/faster to use all as triangles and feed the indices buffer correctly so you got just single draw call. Sadly we do not see the part of code where you are computing the indices ...
Why N+1
and M+1
points? You do not need to duplicate first point in vert
you can do it in indices instead...
Hope the VBO related part of the code is correct ...
Also beware that faces of the other circle should have points in reverse order so GL_CULL_FACE
will cull of faces correctly ...
[Edit1] C++ example
Anyway if you want to use normals latter on you should also duplicate the caps due to different normal on the edge... If I put all together in my style of coding I got this:
//---------------------------------------------------------------------------
const int M=20; // points per circle circumference
const int N=10; // point per cylinder height
const int pnts=3*((M*(N+2))+2); // 3* number of points
const int facs=3*M*(N+N+2); // 3* number of indices
float pnt[pnts]; // (x,y,z) position per each point
float nor[pnts]; // (x,y,z) normal per each point
int fac[facs]; // (i0,i1,i2) indices per each TRIANGLE
//---------------------------------------------------------------------------
void cylinder_init(float r,float h)
{
int i,j,ix,i0,i1,i2,i3;
float x,y,z,a,da,dz;
// compute position and normals
ix=0;
dz=h/double(N-1);
da=2.0*M_PI/double(M);
for (z=-0.5*h,j=0;j<N;j++,z+=dz) // circles
for (a=0.0,i=0;i<M;i++,a+=da)
{
x=cos(a);
y=sin(a);
pnt[ix]=r*x; nor[ix]=x; ix++;
pnt[ix]=r*y; nor[ix]=y; ix++;
pnt[ix]=z; nor[ix]=0.0; ix++;
}
pnt[ix]= 0.0; nor[ix]= 0.0; ix++; // top cap
pnt[ix]= 0.0; nor[ix]= 0.0; ix++;
pnt[ix]=+0.5*h; nor[ix]=+1.0; ix++;
for (j=ix-3*(M+1),i=0;i<M;i++)
{
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]=+1.0; ix++; j++;
}
pnt[ix]= 0.0; nor[ix]= 0.0; ix++; // bottom cap
pnt[ix]= 0.0; nor[ix]= 0.0; ix++;
pnt[ix]=-0.5*h; nor[ix]=-1.0; ix++;
for (j=0,i=0;i<M;i++)
{
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]=-1.0; ix++; j++;
}
// compute triangle indices
ix=0; i0=M-1; i1=0; i2=i0+M; i3=i1+M; // circles
for (j=0;j<N-1;j++,i0+=M,i2+=M)
for (i=0;i<M;i++,i0=i1,i1++,i2=i3,i3++)
{
fac[ix]=i0; ix++;
fac[ix]=i1; ix++;
fac[ix]=i2; ix++;
fac[ix]=i2; ix++;
fac[ix]=i1; ix++;
fac[ix]=i3; ix++;
}
i2=M*N; i0=i2+M; i1=i2+1; // top cap
for (i=0;i<M;i++,i0=i1,i1++)
{
fac[ix]=i0; ix++;
fac[ix]=i1; ix++;
fac[ix]=i2; ix++;
}
i2+=M+1; i0=i2+M; i1=i2+1; // bottom cap
for (i=0;i<M;i++,i0=i1,i1++)
{
fac[ix]=i2; ix++;
fac[ix]=i1; ix++;
fac[ix]=i0; ix++;
}
}
//---------------------------------------------------------------------------
And preview:
You just use single draw with GL_TRIANGLES
on the whole fac[facs]
indices buffer.
So N
is number of points on the circle circumference and M
is the number of points per height...
LOL in your GetUV
you are computing cu,su,cv,sv
but not using them, instead you use the same sin
and cos
call again. if I see it right u=<0,1>
maps circumference of the circle/cylinder (XZ plane circle) and v=<0,1>
maps the height (Y). But it looks like that the function itself works as should (just slowly than possible) appart of that inaccurate M_PI
usage which might cause artifacts.
First problem I see is
vert[i + j*(N+1)].c = glm::normalize( vert[i + j*(N+1)].p );
I would get rid of that line as it will create the cone ... which you do not want anymore (btw. very weird and slow method of cone creation)
Also the i + j*(N+1)
is ugly instead I would do:
for (int ix=0,j=0; j<=M; j++)
for (int i=0; i<=N; i++,ix++)
{
float u = i/(float)N;
float v = j/(float)M;
vert[ix].p = GetUV(u, v);
}
Next problem you got is wrong usage of the Draw methods ... as you want a grid of points instead of just 2 circles you divided the stuff into GL_TRIANGLE_FAN
and GL_TRIANGLES
. That was almost correct but you should have:
2x GL_TRIANGLE_FAN
one for each base
1x GL_TRIANGLES
or GL_QUADS for the rest
as you want to use indices it is basically simpler/faster to use all as triangles and feed the indices buffer correctly so you got just single draw call. Sadly we do not see the part of code where you are computing the indices ...
Why N+1
and M+1
points? You do not need to duplicate first point in vert
you can do it in indices instead...
Hope the VBO related part of the code is correct ...
Also beware that faces of the other circle should have points in reverse order so GL_CULL_FACE
will cull of faces correctly ...
[Edit1] C++ example
Anyway if you want to use normals latter on you should also duplicate the caps due to different normal on the edge... If I put all together in my style of coding I got this:
//---------------------------------------------------------------------------
const int M=20; // points per circle circumference
const int N=10; // point per cylinder height
const int pnts=3*((M*(N+2))+2); // 3* number of points
const int facs=3*M*(N+N+2); // 3* number of indices
float pnt[pnts]; // (x,y,z) position per each point
float nor[pnts]; // (x,y,z) normal per each point
int fac[facs]; // (i0,i1,i2) indices per each TRIANGLE
//---------------------------------------------------------------------------
void cylinder_init(float r,float h)
{
int i,j,ix,i0,i1,i2,i3;
float x,y,z,a,da,dz;
// compute position and normals
ix=0;
dz=h/double(N-1);
da=2.0*M_PI/double(M);
for (z=-0.5*h,j=0;j<N;j++,z+=dz) // circles
for (a=0.0,i=0;i<M;i++,a+=da)
{
x=cos(a);
y=sin(a);
pnt[ix]=r*x; nor[ix]=x; ix++;
pnt[ix]=r*y; nor[ix]=y; ix++;
pnt[ix]=z; nor[ix]=0.0; ix++;
}
pnt[ix]= 0.0; nor[ix]= 0.0; ix++; // top cap
pnt[ix]= 0.0; nor[ix]= 0.0; ix++;
pnt[ix]=+0.5*h; nor[ix]=+1.0; ix++;
for (j=ix-3*(M+1),i=0;i<M;i++)
{
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]=+1.0; ix++; j++;
}
pnt[ix]= 0.0; nor[ix]= 0.0; ix++; // bottom cap
pnt[ix]= 0.0; nor[ix]= 0.0; ix++;
pnt[ix]=-0.5*h; nor[ix]=-1.0; ix++;
for (j=0,i=0;i<M;i++)
{
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]= 0.0; ix++; j++;
pnt[ix]=pnt[j]; nor[ix]=-1.0; ix++; j++;
}
// compute triangle indices
ix=0; i0=M-1; i1=0; i2=i0+M; i3=i1+M; // circles
for (j=0;j<N-1;j++,i0+=M,i2+=M)
for (i=0;i<M;i++,i0=i1,i1++,i2=i3,i3++)
{
fac[ix]=i0; ix++;
fac[ix]=i1; ix++;
fac[ix]=i2; ix++;
fac[ix]=i2; ix++;
fac[ix]=i1; ix++;
fac[ix]=i3; ix++;
}
i2=M*N; i0=i2+M; i1=i2+1; // top cap
for (i=0;i<M;i++,i0=i1,i1++)
{
fac[ix]=i0; ix++;
fac[ix]=i1; ix++;
fac[ix]=i2; ix++;
}
i2+=M+1; i0=i2+M; i1=i2+1; // bottom cap
for (i=0;i<M;i++,i0=i1,i1++)
{
fac[ix]=i2; ix++;
fac[ix]=i1; ix++;
fac[ix]=i0; ix++;
}
}
//---------------------------------------------------------------------------
And preview:
You just use single draw with GL_TRIANGLES
on the whole fac[facs]
indices buffer.
edited Nov 18 at 19:38
answered Nov 18 at 6:53
Spektre
28.8k645201
28.8k645201
Thank you for your answer, I edited the post and added the Indices part.
– József Huszkó
Nov 18 at 17:32
@JózsefHuszkó I updated my answer also ...
– Spektre
Nov 18 at 19:39
@JózsefHuszkó how is it going did you solve your issue or not?
– Spektre
7 hours ago
add a comment |
Thank you for your answer, I edited the post and added the Indices part.
– József Huszkó
Nov 18 at 17:32
@JózsefHuszkó I updated my answer also ...
– Spektre
Nov 18 at 19:39
@JózsefHuszkó how is it going did you solve your issue or not?
– Spektre
7 hours ago
Thank you for your answer, I edited the post and added the Indices part.
– József Huszkó
Nov 18 at 17:32
Thank you for your answer, I edited the post and added the Indices part.
– József Huszkó
Nov 18 at 17:32
@JózsefHuszkó I updated my answer also ...
– Spektre
Nov 18 at 19:39
@JózsefHuszkó I updated my answer also ...
– Spektre
Nov 18 at 19:39
@JózsefHuszkó how is it going did you solve your issue or not?
– Spektre
7 hours ago
@JózsefHuszkó how is it going did you solve your issue or not?
– Spektre
7 hours ago
add a comment |
József Huszkó is a new contributor. Be nice, and check out our Code of Conduct.
József Huszkó is a new contributor. Be nice, and check out our Code of Conduct.
József Huszkó is a new contributor. Be nice, and check out our Code of Conduct.
József Huszkó is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53354308%2fc-opengl-how-to-make-a-second-circle-over-the-cylinder%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
what is
M,N
? you need just 2 circles ... but I am not seeing even the one where are anysin,cos
? The usual is compute X,Y as parametric circle and Z is constant (different for each base, their distance is the cylinder height)– Spektre
Nov 17 at 19:11
... and what does
GetUV
do? WhyglDrawElements
andglDrawArrays
? Where is the element list?– Rabbid76
Nov 17 at 19:14
Sorry, I edited the post.
– József Huszkó
Nov 17 at 19:28