3

I am not able to figure out the function that would be required to build data for a tessellated rectangle.

Currently this is what i do for a non tessellated rectangle;

 GLuint Waveindices[] = {  
0, 1, 3, 
1, 2, 3  
};

std::vector<GLfloat> verticesRect;

  verticesRect = {
    // Positions        // Normal Coords          // Texture Coords
    width,  height, 0.0f,    0.0 , 0.0, 1.0 ,     1.0f, 0.0f,   // Top Right
    width, -height, 0.0f,    0.0 , 0.0, 1.0 ,     1.0f, 1.0f,   // Bottom Right
   -width, -height, 0.0f,    0.0 , 0.0, 1.0 ,     0.0f, 1.0f,   // Bottom Left
   -width, height, 0.0f,    0.0 , 0.0, 1.0 ,     0.0f, 0.0f    // Top Left 

 glGenVertexArrays(1, &m_VAO);
 glGenBuffers(1, &m_VBO);
 glGenBuffers(1, &m_EBO);
 glBindVertexArray(m_VAO);
 glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
 glBufferData(GL_ARRAY_BUFFER, verticesRect.size() * sizeof(GLfloat), &verticesRect[0], 
 GL_STATIC_DRAW);
 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);
 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Waveindices), Waveindices, GL_STATIC_DRAW);
 glEnableVertexAttribArray(0);
 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
 glEnableVertexAttribArray(1);
 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
 glEnableVertexAttribArray(0);
 glEnableVertexAttribArray(2);
 glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
};

Apologies i don't have any code for the options which i tried as i just could not get any meaning full output from the code which i wrote.

This is how the rectangle should look like when Tessellation value is 2.

enter image description here

suman
  • 113
  • 7

1 Answers1

3

What you need is to linearly interpolate between the edge points ... compute x,y,z, set texture coordinate and once finished recompute normals using cross product. Then just create triangulation and render ...

Here simple C++ (old api) example:

GLfloat divide(GLfloat a,GLfloat b){ if (fabs(b)<1e-10) return 0.0; else return a/b; }
void  normalize(GLfloat *c,GLfloat *a)  // c = a/|a|
    {
    GLfloat l=divide(1.0,sqrt((a[0]*a[0])+(a[1]*a[1])+(a[2]*a[2])));
    c[0]=a[0]*l;
    c[1]=a[1]*l;
    c[2]=a[2]*l;
    }
void  cross(GLfloat *c,GLfloat *a,GLfloat *b) // c = cross(a,b)
    {
    GLfloat   q[3];
    q[0]=(a[1]*b[2])-(a[2]*b[1]);
    q[1]=(a[2]*b[0])-(a[0]*b[2]);
    q[2]=(a[0]*b[1])-(a[1]*b[0]);
    for(int i=0;i<3;i++) c[i]=q[i];
    }
void genere(GLfloat w,GLfloat h)
    {
    const int m=16,n=16;        // points per grid axis
    const int n8=n*8;           // size of VBO gfx data
    const int sz0=m*n8;         // size of VBO gfx data
    const int sz1=(m-1)*(n-1)*6;// size of indices
    GLfloat dat[sz0];
    GLuint idx[sz1];
    int i,j,k,a,b;
    GLfloat x,y,z,dx,dy,l;
    GLfloat u[3],v[3],nor[3];
    // gfx data
    dx=2.0*w/GLfloat(n-1);
    dy=2.0*h/GLfloat(m-1);
    for (a=0,y=-h,j=0;j<m;j++,y+=dy)
     for (    x=-w,i=0;i<n;i++,x+=dx)
        {
        // Vertex
        z=0.3*sin((x*x)+(y*y));
        dat[a]=x; a++;
        dat[a]=y; a++;
        dat[a]=z; a++;
        // Normal (will be recomputed latter)
        dat[a]=0.0; a++;
        dat[a]=0.0; a++;
        dat[a]=1.0; a++;
        // TexCoord
        dat[a]=(x+w)/(w+w); a++;
        dat[a]=(y+h)/(h+h); a++;
        }
    // triangulation indices
    for (a=0,j=1;j<m;j++)
     for (    i=1;i<n;i++)
        {
        // b = location of point[i,j] in dat[]
        b=((n*j)+i)*8;
        // first triangle per quad
        idx[a]=b-8;    a++;
        idx[a]=b-8-n8; a++;
        idx[a]=b;      a++;
        // second triangle per quad
        idx[a]=b-8-n8; a++;
        idx[a]=b-n8;   a++;
        idx[a]=b;      a++;
        // recompute inner normals
        for (k=0;k<3;k++)
            {
            u[k]=dat[idx[a-6]+k]-dat[idx[a-4]+k];
            v[k]=dat[idx[a-5]+k]-dat[idx[a-4]+k];
            }
        cross(nor,u,v); normalize(nor,nor);
        for (k=0;k<3;k++)
            {
            u[k]=dat[idx[a-3]+k]-dat[idx[a-1]+k];
            v[k]=dat[idx[a-2]+k]-dat[idx[a-1]+k];
            }
        cross(u,u,v); normalize(u,u);
        for (k=0;k<3;k++) dat[idx[a-1]+3+k]=0.5*(nor[k]+u[k]);
        }
    // copy edge normals
    for (j=0,i=1;i<n;i++)
        {
        // b = location of point[i,j] in dat[]
        b=((n*j)+i)*8;
        // copy
        for (k=0;k<3;k++) dat[b+3+k]=dat[b+3+k+n8];
        }
    for (i=0,j=1;j<m;j++)
        {
        // b = location of point[i,j] in dat[]
        b=((n*j)+i)*8;
        // copy
        for (k=0;k<3;k++) dat[b+3+k]=dat[b+3+k+8];
        }

    // old api render (just for debug ignore this)
    glBegin(GL_TRIANGLES);
    for (i=0;i<sz1;i++)
        {
        j=idx[i];
        glNormal3fv(dat+j+3);
        glTexCoord3fv(dat+j+6);
        glVertex3fv(dat+j);
        }
    glEnd();
    }

Just beware that the normals are single sided so your lighting equation shoul dhandle that otherwise one side would be dark with lighting.

The normals are averaged between 2 triangles in each grid cell (if you want more smooth surface average 4 triangles).

Here preview:

preview

If I did not make any silly mistake somewhere the data format should match yours ... So just remove the old api rendering and add the VBO stuff instead of it

Spektre
  • 49,595
  • 11
  • 110
  • 380
  • i have tried porting this code but not able to create the rectangle correctly. – Summit Jul 12 '22 at 07:33
  • please do look at my question -> https://stackoverflow.com/questions/72948333/how-to-build-a-tessellated-rectangle – Summit Jul 12 '22 at 07:33