C ++ OpenGL: как сделать второй круг над цилиндром? - PullRequest
0 голосов
/ 17 ноября 2018

Так что в основном у меня есть цилиндр с основанием (под цилиндром есть круг), но над ним нет круга. Я хочу сделать его закрытым цилиндром.

Вот важная часть моей функции boy CMyApp :: Init ():

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;
}

Функция рендеринга:

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

«База конусов» существует, потому что я начал этот проект с проекта «Нарисуй конус».

Как я могу сделать второй круг, но над цилиндром?

Edit: M, N: постоянные числа (20 и 10)

Мое параметрическое уравнение (которое называется ФУНКЦИЕЙ, называемой 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));

Как я создаю Индексы (внутри функции Init ()):

 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);
    }

Ответы [ 2 ]

0 голосов
/ 18 ноября 2018

То есть N - это количество точек на окружности круга, а M - это количество точек на высоту ...

LOL в вашем GetUV вы вычисляете cu,su,cv,sv, но не используете их, вместо этого вы снова используете те же вызовы sin и cos. если я вижу это правильно, u=<0,1> отображает окружность круга / цилиндра (плоскость XZ), а v=<0,1> отображает высоту (Y). Но похоже, что сама функция работает как следует (чуть медленнее, чем это возможно) из-за этого неточного M_PI использования, которое может вызвать артефакты.

Первая проблема Я вижу это

vert[i + j*(N+1)].c = glm::normalize( vert[i + j*(N+1)].p );

Я бы избавился от этой линии, поскольку она создаст конус ... который вам больше не нужен (кстати, очень странный и медленный метод создания конуса)

Также i + j*(N+1) уродлив, вместо этого я бы сделал:

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);
  }

Следующая проблема Вы получили неправильное использование методов Draw ... так как вам нужна сетка точек вместо двух кругов, вы разделили материал на GL_TRIANGLE_FAN и GL_TRIANGLES. Это было почти правильно, но вы должны иметь:

2x GL_TRIANGLE_FAN по одному на каждую базу 1x GL_TRIANGLES или GL_QUADS для остальных

так как вы хотите использовать индексы, в основном проще / быстрее использовать все в качестве треугольников и правильно заполнять буфер индексов, чтобы вы получили только один вызов отрисовки. К сожалению, мы не видим ту часть кода, где вы вычисляете индексы ...

Почему N+1 и M+1 баллов? Вам не нужно дублировать первую точку в vert[], вместо этого вы можете сделать это в индексах ...

Надеюсь, что часть кода, связанная с VBO , верна ...

Также помните, что грани другого круга должны иметь точки в обратном порядке, поэтому GL_CULL_FACE будет правильно отбирать грани ...

[Edit1] C ++ пример

В любом случае, если вы хотите использовать последние нормалы, вы должны также дублировать заглавные буквы из-за различных нормалей на краю ... Если я соберу все вместе в моем стиле кодирования, я получу это:

//---------------------------------------------------------------------------
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++;
        }
    }
//---------------------------------------------------------------------------

И предварительный просмотр:

preview

Вы просто используете одно рисование с GL_TRIANGLES для всего буфера индексов fac[facs].

0 голосов
/ 17 ноября 2018

Самый простой способ нарисовать другую круглую крышку - просто изменить матрицу модели круга и снова сделать вызов.Поэтому, если вы делаете что-то подобное до вызова glDrawArrays():

glm::mat4 modelViewMatrix = calculateModelViewMatrix();
glUniformMatrix4fv(modelViewLocation, 1, FALSE, modelViewMatrix);

Сделайте то же самое, но переведите modelViewMatrix так, чтобы он находился на другом конце цилиндра.

...