packages feed

FreeTypeGL-0.0.1: src/vertex-attribute.c

/* ============================================================================
 * Freetype GL - A C OpenGL Freetype engine
 * Platform:    Any
 * WWW:         http://code.google.com/p/freetype-gl/
 * ----------------------------------------------------------------------------
 * Copyright 2011,2012 Nicolas P. Rougier. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY NICOLAS P. ROUGIER ''AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL NICOLAS P. ROUGIER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * The views and conclusions contained in the software and documentation are
 * those of the authors and should not be interpreted as representing official
 * policies, either expressed or implied, of Nicolas P. Rougier.
 * ============================================================================
 */
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "vec234.h"
#include "vertex-attribute.h"


// ----------------------------------------------------------------------------
void
vertex_attribute_position_enable( vertex_attribute_t *attr )
{
    glEnableClientState( attr->target );
    glVertexPointer( attr->size, attr->type, attr->stride, attr->pointer );
}



// ----------------------------------------------------------------------------
void
vertex_attribute_normal_enable( vertex_attribute_t *attr )
{
    glEnableClientState( attr->target );
    glNormalPointer( attr->type, attr->stride, attr->pointer );
}



// ----------------------------------------------------------------------------
void
vertex_attribute_color_enable( vertex_attribute_t *attr )
{
    glEnableClientState( attr->target );
    glColorPointer( attr->size, attr->type, attr->stride, attr->pointer );
}



// ----------------------------------------------------------------------------
void
vertex_attribute_tex_coord_enable( vertex_attribute_t *attr )
{
    glEnableClientState( attr->target );
    glTexCoordPointer( attr->size, attr->type, attr->stride, attr->pointer );
}



// ----------------------------------------------------------------------------
void
vertex_attribute_fog_coord_enable( vertex_attribute_t *attr )
{
    glEnableClientState( attr->target );
    glFogCoordPointer( attr->type, attr->stride, attr->pointer );
}



// ----------------------------------------------------------------------------
void
vertex_attribute_edge_flag_enable( vertex_attribute_t *attr )
{
    glEnableClientState( attr->target );
    glEdgeFlagPointer( attr->stride, attr->pointer );
}



// ----------------------------------------------------------------------------
void
vertex_attribute_secondary_color_enable( vertex_attribute_t *attr )
{
    glEnableClientState( attr->target );
    glSecondaryColorPointer( attr->size, attr->type, attr->stride, attr->pointer );
}



// ----------------------------------------------------------------------------
void
vertex_attribute_generic_enable( vertex_attribute_t *attr )
{
    glEnableVertexAttribArray( attr->index );
    glVertexAttribPointer( attr->index, attr->size, attr->type,
                           attr->normalized, attr->stride, attr->pointer );
}



// ----------------------------------------------------------------------------
vertex_attribute_t *
vertex_attribute_parse( char *format )
{
    // Generic attribute
    char *p = strpbrk ( format, "0123456789" );
    if (p == format)
    {
        // Normalized
        p = strpbrk ( format, "n" );
        if ( p != NULL )
        {
            int size, index;
            char ctype;
            sscanf( format, "%dgn%d%c", &index, &size, &ctype );
            GLenum type = get_GL_TYPE( ctype );
            return vertex_attribute_new( 0, index, size, type, GL_TRUE, 0, 0 );
        }
        else
        {
            int size, index;
            char ctype;
            sscanf( format, "%dg%d%c", &index, &size, &ctype );
            GLenum type = get_GL_TYPE( ctype );
            return vertex_attribute_new( 0, index, size, type, GL_FALSE, 0, 0 );
        }
    }

    // Known attribute
    p = strpbrk ( format, "vcntfse" );
    if ( p != 0 )
    {
        int size;
        char ctarget, ctype;
        sscanf( format, "%c%d%c", &ctarget, &size, &ctype );
        GLenum type = get_GL_TYPE( ctype );
        GLenum target = GL_VERTEX_ATTRIBUTE_TARGET( ctarget );
        return vertex_attribute_new( target, 0, size, type, GL_FALSE, 0, 0 );
    }

    fprintf(stderr, "Vertex attribute format not understood\n");
    return 0;
}



// ----------------------------------------------------------------------------
vertex_attribute_t *
vertex_attribute_new( GLenum target,
                      GLuint index,
                      GLint size,
                      GLenum type,
                      GLboolean normalized,
                      GLsizei stride,
                      GLvoid *pointer )
{
    vertex_attribute_t *attribute =
        (vertex_attribute_t *) malloc (sizeof(vertex_attribute_t));
    assert( size > 0 );

    // Generic attribute
    if (target == 0)
    {
        attribute->ctarget = 'g';
        assert( (size <= 4) );
        assert( (type == GL_BYTE)  || (type == GL_UNSIGNED_BYTE)  ||
                (type == GL_SHORT) || (type == GL_UNSIGNED_SHORT) ||
                (type == GL_INT)   || (type == GL_UNSIGNED_INT)   ||
                (type == GL_FLOAT) || (type == GL_DOUBLE) );
        attribute->enable =
            (void(*)(void *)) vertex_attribute_generic_enable;
    }
    else
    {
        // Standard attribute
        switch( target )
        {
        case GL_VERTEX_ARRAY:
            attribute->ctarget = 'v';
            assert( size > 1 );
            attribute->enable =
                (void(*)(void *)) vertex_attribute_position_enable;
            break;

        case GL_NORMAL_ARRAY:
            attribute->ctarget = 'n';
            assert (size == 3);
            assert( (type == GL_BYTE) || (type == GL_SHORT) ||
                    (type == GL_INT)  || (type == GL_FLOAT) ||
                    (type == GL_DOUBLE) );
            attribute->enable =
                (void(*)(void *)) vertex_attribute_normal_enable;
            break;

        case GL_COLOR_ARRAY:
            attribute->ctarget = 'c';
            assert( (size == 3) || (size == 4) );
            assert( (type == GL_BYTE)  || (type == GL_UNSIGNED_BYTE)  ||
                    (type == GL_SHORT) || (type == GL_UNSIGNED_SHORT) ||
                    (type == GL_INT)   || (type == GL_UNSIGNED_INT)   ||
                    (type == GL_FLOAT) || (type == GL_DOUBLE) );
            attribute->enable =
                (void(*)(void *)) vertex_attribute_color_enable;
            break;

        case GL_TEXTURE_COORD_ARRAY:
            attribute->ctarget = 't';
            assert( (type == GL_SHORT) || (type == GL_INT) ||
                    (type == GL_FLOAT) || (type == GL_DOUBLE) );
            attribute->enable =
                (void(*)(void *)) vertex_attribute_tex_coord_enable;
            break;

        case GL_FOG_COORD_ARRAY:
            attribute->ctarget = 'f';
            assert( size == 2 );
            assert( (type == GL_FLOAT) || (type == GL_DOUBLE) );
            attribute->enable =
                (void(*)(void *)) vertex_attribute_fog_coord_enable;
            break;

        case GL_EDGE_FLAG_ARRAY:
            attribute->ctarget = 'e';
            assert( size == 1 );
            assert( type == GL_BOOL );
            attribute->enable =
                (void(*)(void *)) vertex_attribute_edge_flag_enable;
            break;

        case GL_SECONDARY_COLOR_ARRAY:
            attribute->ctarget = 's';
            assert( size == 3 );
            assert( (type == GL_BYTE)  || (type == GL_UNSIGNED_BYTE)  ||
                    (type == GL_SHORT) || (type == GL_UNSIGNED_SHORT) ||
                    (type == GL_INT)   ||  (type == GL_UNSIGNED_INT)  ||
                    (type == GL_FLOAT) || (type == GL_DOUBLE) );
            attribute->enable =
                (void(*)(void *)) vertex_attribute_secondary_color_enable;
            break;

        default:
            fprintf(stderr, "Vertex attribute format not understood\n");
            attribute->enable = 0;
            break;
        }
    }

    attribute->target     = target;
    attribute->index      = index;
    attribute->size       = size;
    attribute->type       = type;
    attribute->normalized = normalized;
    attribute->stride     = stride;
    attribute->pointer    = pointer;

    return attribute;
}



// ----------------------------------------------------------------------------
void
vertex_attribute_delete( vertex_attribute_t * self )
{
    assert( self );
    free( self );
}


// ----------------------------------------------------------------------------
GLenum
get_GL_TYPE( char ctype )
{
    switch( ctype )
    {
    case 'b': return GL_BYTE;
    case 'B': return GL_UNSIGNED_BYTE;
    case 's': return GL_SHORT;
    case 'S': return GL_UNSIGNED_SHORT;
    case 'i': return GL_INT;
    case 'I': return GL_UNSIGNED_INT;
    case 'f': return GL_FLOAT;
#if defined(GL_DOUBLE) && (GL_DOUBLE != GL_FLOAT)
    case 'd': return GL_DOUBLE;
#endif
    default:  return 0;
    }
}



// ----------------------------------------------------------------------------
GLenum
GL_VERTEX_ATTRIBUTE_TARGET( char ctarget )
{
    switch( ctarget )
    {
    case 'v': return GL_VERTEX_ARRAY;
    case 'n': return GL_NORMAL_ARRAY;
    case 'c': return GL_COLOR_ARRAY;
    case 't': return GL_TEXTURE_COORD_ARRAY;
    case 'f': return GL_FOG_COORD_ARRAY;
    case 's': return GL_SECONDARY_COLOR_ARRAY;
    case 'e': return GL_EDGE_FLAG_ARRAY;
    default:  return 0;
    }
}



// ----------------------------------------------------------------------------
GLuint
GL_TYPE_SIZE( GLenum gtype )
{
    switch( gtype )
    {
    case GL_BOOL:           return sizeof(GLboolean);
    case GL_BYTE:           return sizeof(GLbyte);
    case GL_UNSIGNED_BYTE:  return sizeof(GLubyte);
    case GL_SHORT:          return sizeof(GLshort);
    case GL_UNSIGNED_SHORT: return sizeof(GLushort);
    case GL_INT:            return sizeof(GLint);
    case GL_UNSIGNED_INT:   return sizeof(GLuint);
    case GL_FLOAT:          return sizeof(GLfloat);
    case GL_DOUBLE:         return sizeof(GLdouble);
    default:                return 0;
    }
}



// ----------------------------------------------------------------------------
const char *
GL_TYPE_STRING( GLenum gtype )
{
    switch( gtype )
    {
    case GL_BOOL:           return "GL_BOOL";
    case GL_BYTE:           return "GL_BYTE";
    case GL_UNSIGNED_BYTE:  return "GL_UNSIGNED_BYTE";
    case GL_SHORT:          return "GL_SHORT";
    case GL_UNSIGNED_SHORT: return "GL_UNSIGNED_SHORT";
    case GL_INT:            return "GL_INT";
    case GL_UNSIGNED_INT:   return "GL_UNSIGNED_INT";
    case GL_FLOAT:          return "GL_FLOAT";
    case GL_DOUBLE:         return "GL_DOUBLE";
    default:                return "GL_VOID";
    }
}