Jump to content
  • Advertisement
Sign in to follow this  
blueshogun96

Vertex normal calculation for triangle strips?

This topic is 2095 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I understand that calculating a normal is a rather simple concept, but for some reason, I can't wrap my head around generating normals for a triangle strip.  What I have is a heightmap and I need normals for lighting.  The whole thing is rendered using triangle strips.

 

Just in case you need a visual, take a look at this code I used to generate vertices and texture coordinates.

void heightmap_t::build_vertices()
{
    float X, Y;
    float x, y, z;
    bool switch_sides = No;
    
    /* Sanity check */
    if( !m_height_data )
        return;
    
    /* 
     * First Pass: determine total number of vertices needed
     */
    m_vertex_count = 0;
    
    for ( X = 0; X <= m_width; X += m_polygon_scale )
    {
        /* Are we switching sides? */
        if( switch_sides )
        {
            for( Y = m_height; Y >= 0; Y -= m_polygon_scale )
            {
                m_vertex_count += 2;
            }
        }
        else
        {
            for( Y = 0; Y <= m_height; Y += m_polygon_scale )
            {
                m_vertex_count += 2;
            }
        }
        
        /* Switch the direction the columb renders to allow fluid tri-strips */
        switch_sides = !switch_sides;
    }
    
    /*
     * Second Pass: Allocate and generate vertices
     */
    
    switch_sides = No;
    m_vertices = new float[m_vertex_count*3];
    m_texcoords = new float[m_vertex_count*2];
    int v = 0;
    
    for ( X = 0; X <= m_width; X += m_polygon_scale )
    {
        /* Are we switching sides? */
        if( switch_sides )
        {
            /* Columns */
            for( Y = m_height; Y >= 0; Y -= m_polygon_scale )
            {
                /* Bottom left vertex */
                x = X;
                y = get_height( X, Y );
                z = Y;
                
                /* Set texture and vertex coordinates */
                m_texcoords[(v*2)+0] = ( x / float( m_width ) ) * 50.0f;
                m_texcoords[(v*2)+1] = -( z / float( m_height ) ) * 50.0f;
                m_vertices[(v*3)+0] = x;
                m_vertices[(v*3)+1] = y;
                m_vertices[(v*3)+2] = z;
                v++;
                
                /* Bottom right vertex */
                x = X + m_polygon_scale;
                y = get_height( X + m_polygon_scale, Y );
                z = Y;
                
                /* Set texture and vertex coordinates */
                m_texcoords[(v*2)+0] = ( x / float( m_width ) ) * 50.0f;
                m_texcoords[(v*2)+1] = -( z / float( m_height ) ) * 50.0f;
                m_vertices[(v*3)+0] = x;
                m_vertices[(v*3)+1] = y;
                m_vertices[(v*3)+2] = z;
                v++;
            }
        }
        else
        {
            for( Y = 0; Y <= m_height; Y += m_polygon_scale )
            {
                /* Bottom right vertex */
                x = X + m_polygon_scale;
                y = get_height( X + m_polygon_scale, Y );
                z = Y;
                
                /* Set texture and vertex coordinates */
                m_texcoords[(v*2)+0] = ( x / float( m_width ) ) * 50.0f;
                m_texcoords[(v*2)+1] = -( z / float( m_height ) ) * 50.0f;
                m_vertices[(v*3)+0] = x;
                m_vertices[(v*3)+1] = y;
                m_vertices[(v*3)+2] = z;
                v++;
                
                /* Bottom left vertex */
                x = X;
                y = get_height( X, Y );
                z = Y;
                
                /* Set texture and vertex coordinates */
                m_texcoords[(v*2)+0] = ( x / float( m_width ) ) * 50.0f;
                m_texcoords[(v*2)+1] = -( z / float( m_height ) ) * 50.0f;
                m_vertices[(v*3)+0] = x;
                m_vertices[(v*3)+1] = y;
                m_vertices[(v*3)+2] = z;
                v++;
            }
        }
        
        /* Switch the direction the columb renders to allow fluid tri-strips */
        switch_sides = !switch_sides;
    }
    
    /* Use the vertex data to generate a VBO */
    glGenBuffers( 3, m_vbo );
    glBindBuffer( GL_ARRAY_BUFFER, m_vbo[0] );
    glBufferData( GL_ARRAY_BUFFER, m_vertex_count*3*sizeof(float), m_vertices, GL_STATIC_DRAW );
    glBindBuffer( GL_ARRAY_BUFFER, m_vbo[1] );
    glBufferData( GL_ARRAY_BUFFER, m_vertex_count*2*sizeof(float), m_texcoords, GL_STATIC_DRAW );
}

This is based off of an old tutorial from gametutorials.com.  A bit of a shame that they didn't calculate normals in the heightmap tutorial...

 

My initial idea was to take each triangle individually, and calculate face normals first.  Then I get confused after the 2nd part.  Do I like go each vertex and  match up vertices with matching coordinates, add the normals and re-normalize?  That's the part I'm having trouble wrapping my head around.  My brain is a bit fried at the moment, and I'm in a 24-hour coding competition right now.  Any ideas?  Thanks.

 

Shogun.

Share this post


Link to post
Share on other sites
Advertisement

Oh, and another thing, this is my attempt to calculate them here.  What I did was take each surrounding value and form triangles with them.  Then I calculate the face normals of the resulting 8 triangles, then add the normals together, then average them out.  It's buggy, but it's better than nothing, that's for sure.

void calculate_normal( int x, int y, int polygon_offset, float* n_out )
    {
        int tris = 0; /* Triangles formed */
        float center[3];
        float vertices[8][3];
        float fnormals[8][3];
        
        /*x = X;
         y = get_height( X, Y );
         z = Y;*/
        
        /* Calculate the center */
        center[0] = x;
        center[1] = get_height( x, y );
        center[2] = y;
        
        /* Right */
        vertices[0][0] = x+polygon_offset;
        vertices[0][1] = get_height(x+polygon_offset, y);
        vertices[0][2] = y;
        
        /* Right bottom */
        vertices[1][0] = x+polygon_offset;
        vertices[1][1] = get_height(x+polygon_offset, y-polygon_offset);
        vertices[1][2] = y-polygon_offset;
        
        /* Bottom */
        vertices[2][0] = x;
        vertices[2][1] = get_height(x, y-polygon_offset);
        vertices[2][2] = y-polygon_offset;
        
        /* Left bottom */
        vertices[3][0] = x-polygon_offset;
        vertices[3][1] = get_height(x-polygon_offset, y-polygon_offset);
        vertices[3][2] = y-polygon_offset;
        
        /* Left */
        vertices[4][0] = x-polygon_offset;
        vertices[4][1] = get_height(x-polygon_offset, y);
        vertices[4][2] = y;
        
        /* Left top */
        vertices[5][0] = x-polygon_offset;
        vertices[5][1] = get_height(x-polygon_offset, y+polygon_offset);
        vertices[5][2] = y+polygon_offset;
        
        /* Top */
        vertices[6][0] = x;
        vertices[6][1] = get_height(x, y+polygon_offset);
        vertices[6][2] = y+polygon_offset;
        
        /* Right top */
        vertices[7][0] = x+polygon_offset;
        vertices[7][1] = get_height(x+polygon_offset, y+polygon_offset);
        vertices[0][2] = y+polygon_offset;
        
        /* Generate face normals */
        for( int i = 0; i < 7; i++ )
        {
            float temp[3];
            int i2 = (i+1) < 7 ? i : 0;
            
            cross( center, vertices[i], vertices[i2], temp );
            normalize( temp, fnormals[i] );
            memcpy( n_out, fnormals[i], sizeof( float ) * 3 );
        }
        
        /* Average out normals */
        n_out[0] /= 8.0f;
        n_out[1] /= 8.0f;
        n_out[2] /= 8.0f;
    }

The results:

 

[attachment=19544:Screen Shot 2014-01-18 at 7.48.48 PM.png]

 

Any ideas?  Thanks.

 

Shogun.

Share this post


Link to post
Share on other sites

I understand that calculating a normal is a rather simple concept, but for some reason, I can't wrap my head around generating normals for a triangle strip.  What I have is a heightmap and I need normals for lighting.  The whole thing is rendered using triangle strips.
 
Just in case you need a visual, take a look at this code I used to generate vertices and texture coordinates.

void heightmap_t::build_vertices()
{
    float X, Y;
    float x, y, z;
    bool switch_sides = No;
    
    /* Sanity check */
    if( !m_height_data )
        return;
    
    /* 
     * First Pass: determine total number of vertices needed
     */
    m_vertex_count = 0;
    
    for ( X = 0; X <= m_width; X += m_polygon_scale )
    {
        /* Are we switching sides? */
        if( switch_sides )
        {
            for( Y = m_height; Y >= 0; Y -= m_polygon_scale )
            {
                m_vertex_count += 2;
            }
        }
        else
        {
            for( Y = 0; Y <= m_height; Y += m_polygon_scale )
            {
                m_vertex_count += 2;
            }
        }
        
        /* Switch the direction the columb renders to allow fluid tri-strips */
        switch_sides = !switch_sides;
    }
    
    /*
     * Second Pass: Allocate and generate vertices
     */
    
    switch_sides = No;
    m_vertices = new float[m_vertex_count*3];
    m_texcoords = new float[m_vertex_count*2];
    int v = 0;
    
    for ( X = 0; X <= m_width; X += m_polygon_scale )
    {
        /* Are we switching sides? */
        if( switch_sides )
        {
            /* Columns */
            for( Y = m_height; Y >= 0; Y -= m_polygon_scale )
            {
                /* Bottom left vertex */
                x = X;
                y = get_height( X, Y );
                z = Y;
                
                /* Set texture and vertex coordinates */
                m_texcoords[(v*2)+0] = ( x / float( m_width ) ) * 50.0f;
                m_texcoords[(v*2)+1] = -( z / float( m_height ) ) * 50.0f;
                m_vertices[(v*3)+0] = x;
                m_vertices[(v*3)+1] = y;
                m_vertices[(v*3)+2] = z;
                v++;
                
                /* Bottom right vertex */
                x = X + m_polygon_scale;
                y = get_height( X + m_polygon_scale, Y );
                z = Y;
                
                /* Set texture and vertex coordinates */
                m_texcoords[(v*2)+0] = ( x / float( m_width ) ) * 50.0f;
                m_texcoords[(v*2)+1] = -( z / float( m_height ) ) * 50.0f;
                m_vertices[(v*3)+0] = x;
                m_vertices[(v*3)+1] = y;
                m_vertices[(v*3)+2] = z;
                v++;
            }
        }
        else
        {
            for( Y = 0; Y <= m_height; Y += m_polygon_scale )
            {
                /* Bottom right vertex */
                x = X + m_polygon_scale;
                y = get_height( X + m_polygon_scale, Y );
                z = Y;
                
                /* Set texture and vertex coordinates */
                m_texcoords[(v*2)+0] = ( x / float( m_width ) ) * 50.0f;
                m_texcoords[(v*2)+1] = -( z / float( m_height ) ) * 50.0f;
                m_vertices[(v*3)+0] = x;
                m_vertices[(v*3)+1] = y;
                m_vertices[(v*3)+2] = z;
                v++;
                
                /* Bottom left vertex */
                x = X;
                y = get_height( X, Y );
                z = Y;
                
                /* Set texture and vertex coordinates */
                m_texcoords[(v*2)+0] = ( x / float( m_width ) ) * 50.0f;
                m_texcoords[(v*2)+1] = -( z / float( m_height ) ) * 50.0f;
                m_vertices[(v*3)+0] = x;
                m_vertices[(v*3)+1] = y;
                m_vertices[(v*3)+2] = z;
                v++;
            }
        }
        
        /* Switch the direction the columb renders to allow fluid tri-strips */
        switch_sides = !switch_sides;
    }
    
    /* Use the vertex data to generate a VBO */
    glGenBuffers( 3, m_vbo );
    glBindBuffer( GL_ARRAY_BUFFER, m_vbo[0] );
    glBufferData( GL_ARRAY_BUFFER, m_vertex_count*3*sizeof(float), m_vertices, GL_STATIC_DRAW );
    glBindBuffer( GL_ARRAY_BUFFER, m_vbo[1] );
    glBufferData( GL_ARRAY_BUFFER, m_vertex_count*2*sizeof(float), m_texcoords, GL_STATIC_DRAW );
}
This is based off of an old tutorial from gametutorials.com.  A bit of a shame that they didn't calculate normals in the heightmap tutorial...
 
My initial idea was to take each triangle individually, and calculate face normals first.  Then I get confused after the 2nd part.  Do I like go each vertex and  match up vertices with matching coordinates, add the normals and re-normalize?  That's the part I'm having trouble wrapping my head around.  My brain is a bit fried at the moment, and I'm in a 24-hour coding competition right now.  Any ideas?  Thanks.
 
Shogun.


IIRC, yes you take each face that connects the vertex, add them together, then normalize the result. however you have to be careful not to add a co-planar faces, as it skew's the results. Edited by slicer4ever

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!