DI-Guy Graphics API, diguyOglGraphicsLink

diguyOglGraphicsLink.cpp

DI-Guy API Version 12.5.1

This file was automatically generated from diguyOglGraphicsLink.cpp. Do not edit this file directly; the changes will be lost.
Introduction
DI-Guy 'links' are essentially the same as 'bones' in other APIs.

There are two primary purposes of links:

The class diguyOglGraphicsLink is an example of a diguyGraphicsLink subclass for an immediate mode renderer using the DI-Guy Loader. The example subclass shows how to use the accessors of the diguyGraphicsLink class and which virtual functions should be overridden for an immediate mode renderer such as OpenGL.

Header files and forward declarations
#include "diguyOglGraphicsLink.h"
#include "diguyOglGraphicsShaderProgram.h"
#include "ogl_headers.h"

#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/core/func_matrix.hpp>
#include <assert.h>

#include <libbdilog.h>
#include <diguyApp.h>
#include <diguyCharacter.h>
#include <diguyScenario.h>
#include <diguyViewCamera.h>

/*
 *  Top-level static variable that allows for demonstrating two different
 *   ways of getting transformation data:
 *
 *   - querying for individual floats for translation and orientation, or
 *   - querying for the final matrix.
 */
enum {
    FLOATS,
    DOUBLES,
    DERIVED_MATRIX,
    RECURSIVE_DRAW_MATRIX,
    LINEAR_DRAW_MATRIX
};

int s_transformation_mode = DERIVED_MATRIX;
Constructor
Description:

Initialize data members of the class to a known state.

Base class data will not be fully initialized until during the Build Stage, so base class accessors should not be called here.

diguyOglGraphicsLink::diguyOglGraphicsLink(void* internal_data)
    :
    diguyGraphicsLink(internal_data)
{
    /*
     *  Nothing else to do after calling base class constructor and
     *   initializing data members.
     */
}
begin_character_draw
Draw Stage

Description:

Override of diguyGraphicsLink::begin_character_draw().

This function is commonly overridden for immediate mode renderers. It will be called once per draw on the position link of the characater.

The current transformation state of the renderer should be saved so that it can be restored after the link's shapes and child links have been drawn. Typically the restore will happen in end_character_draw().

This is typically done, as here, by pushing the current transformation of the character onto a matrix stack.

void
diguyOglGraphicsLink::begin_character_draw()
{
    /*
     *  Choose if we are doing a linear or recursive draw based off of the
     *   graphics API init structure.
     */
    if (s_transformation_mode == DERIVED_MATRIX)
    {
        if (diguyOglGraphicsLink::get_use_linear_traversal_draw())
        {
            s_transformation_mode = LINEAR_DRAW_MATRIX;
        }
        else
        {
            s_transformation_mode = RECURSIVE_DRAW_MATRIX;
        }
    }

    glPushMatrix();

    diguyCharacter* character = get_character();

    if (get_attached_to_link() && (s_transformation_mode == RECURSIVE_DRAW_MATRIX))
    {
        /*
         *  This method is deprecated as of DI-Guy 12.  If the character has
         *   no parent, no need to get the transformation matrix.
         */

        if (character)
        {
            float pscale[3];
            character->get_parent()->get_scale(&pscale[0], &pscale[1], &pscale[2]);

            float scale[3];
            character->get_scale(&scale[0], &scale[1], &scale[2]);

            glScalef(scale[0]/pscale[0], scale[1]/pscale[1], scale[2]/pscale[2]);
        }
    }
    else
    {
        /*
         *  For DI-Guy 12 there's no difference in the linear pipeline
         *   between drawing parents and children.  Read the base position
         *   transformation matrix for this  link/character.
         */
        float link_matrix[4][4];

        get_transformation_matrix_4x4_ptr(&link_matrix[0][0]);

        glMultTransposeMatrixf((GLfloat*) link_matrix);

        /*
         *  Apply scale for character (optional).
         */
        if (character)
        {
            float scale[3];
            character->get_scale(&scale[0], &scale[1], &scale[2]);

            if (scale[0] != 1.0f || scale[1] != 1.0f || scale[2] != 1.0f)
            {
                glScalef(scale[0], scale[1], scale[2]);
            }
        }

        /*
         *  Bump map support.
         */
        diguyOglGraphicsShaderProgram* shader_program =
            (diguyOglGraphicsShaderProgram*) diguyApp::get_app()->get_current_bound_shader_program();

        if (shader_program && character)
        {
            /*
             *  If the shader program has object space light and camera
             *   uniforms then calculate inverse of the characters rotation
             *   matrix and use that to transform the lights/camera into the
             *   local space of the character and pass that in as a uniform.
             *   These values are needed to make bump mapping work.  End users
             *   will probably not want to use the light and camera values in
             *   the scenario but these are convenient places to stash these
             *   values.  These have been set by view_set_camera() and
             *   view_set_light() in set_up_view.h
             *   diguy 12 mistakenly transposed the matrix here.
             */
            glm::mat4x4 inverse_matrix;
            get_inverse_rotation_matrix_4x4_ptr(glm::value_ptr(inverse_matrix), 0);

            if(shader_program->m_bind_location_ufrm_inverse_transform_matrix != -1)
            {
                glUniformMatrix4fv(shader_program->m_bind_location_ufrm_inverse_transform_matrix,
                    1,        // number of matrices
                    GL_TRUE,  // whether to transpose matrix,
                    (GLfloat*) &inverse_matrix[0][0]);
            }

            glm::mat4x4 inverse_matrix_no_trans = inverse_matrix;
            inverse_matrix_no_trans[3][0] = 0.0f;
            inverse_matrix_no_trans[3][1] = 0.0f;
            inverse_matrix_no_trans[3][2] = 0.0f;
            
            if(shader_program->m_bind_location_ufrm_light_dir_os != -1)
            {
                diguyViewLight* light = character->get_scenario()->get_scenario_light(0);
                float light_x, light_y, light_z;
                light->get_direction(&light_x, &light_y, &light_z);
                
                glm::vec4 light_dir(light_x, light_y, light_z, 0.0f);
                light_dir = glm::normalize(light_dir);
                light_dir = light_dir * inverse_matrix_no_trans;
                glUniform4f(shader_program->m_bind_location_ufrm_light_dir_os,
                    light_dir.x, light_dir.y, light_dir.z, light_dir.w);
            }
            
            if(shader_program->m_bind_location_ufrm_eye_point_os != -1)
            {
                /*
                *  Calculate the local space position of the camera
                */
                diguyViewCamera* camera = character->get_scenario()->get_scenario_camera();
                glm::vec4 camera_pos(camera->get_position_x(), camera->get_position_y(), camera->get_position_z(), 1);
                //float char_pos_x, char_pos_y, char_pos_z;
                //character->get_position(&char_pos_x, &char_pos_y, &char_pos_z);
                //camera_pos = camera_pos - glm::vec4(char_pos_x, char_pos_y, char_pos_z, 0);
                //camera_pos = camera_pos * inverse_matrix_no_trans;
                camera_pos = camera_pos * inverse_matrix;
                glUniform3f(shader_program->m_bind_location_ufrm_eye_point_os,
                    camera_pos.x, camera_pos.y, camera_pos.z);
            }
        }
    }
}
end_character_draw
Draw Stage

Description:

Override of diguyGraphicsLink::end_character_draw().

This function is commonly overridden for immediate mode renderers. It will be called on the position link of the character and typically clears the matrix state and rendering state associated with the character.

This is typically done, as here, by popping the current transformation of the character off the OpenGl matrix stack.

void
diguyOglGraphicsLink::end_character_draw()
{
    glPopMatrix();
}
push
Draw Stage

Description:

Override of diguyGraphicsLink::push().

This function is commonly overridden for immediate mode renderers. It should save the current transformation state of the renderer so that it can be restored after the link's shapes and child links have been drawn.

This is typically done, as here, by pushing the current transformation state onto a stack.

void
diguyOglGraphicsLink::push()
{
    glPushMatrix();
}
pop
Draw Stage

Description:

Override of diguyGraphicsLink::pop()

The pop() function should undo whatever state modifications were made in the push() function. For each push() call there will be a pop() call after the link's shapes and child links have been drawn.

void
diguyOglGraphicsLink::pop()
{
    glPopMatrix();
}
draw
Draw Stage

Description:

The draw() function should perform the necessary actions to apply offsets contained in this link to its shapes and child links.

There are two types of offsets:

Since links don't have any actual geometry (shapes and meshes attached to them do), usually no actual drawing occurs in this function.

void
diguyOglGraphicsLink::draw()
{
    /*
     *  The code below shows two ways to query the link for transformation
     *   data: by getting individual values for translations, rotations,
     *   etc., or by getting a fully precomputed matrix.
     */
    if (s_transformation_mode == LINEAR_DRAW_MATRIX)
    {
        diguyOglGraphicsShaderProgram* shader_program = (diguyOglGraphicsShaderProgram*) diguyApp::get_app()->get_current_bound_shader_program();

        /*
         *  This code shows how to query DI-Guy character links for their
         *   local-coordinate matrices, how to load those into the OpenGL
         *   link-local-coordinate matrices, and how to load those into
         *   the OpenGL transformation matrix or a uniform.
         *
         *   Note that linear drawing requires the use of begin and end
         *    character draw functions.
         */
        float link_matrix[4][4];
        get_local_transformation_matrix_4x4_ptr(&link_matrix[0][0]);

        /*
         *  Multiply by the matrix for this link. If the shader includes
         *   ufrm_link_matrix use that instead of changing the modelview
         *   matrix.
         *
         *  DI-Guy transformation matrices are not in OpenGL's preferred
         *   format;  they must be transposed using the
         *   glMultTransposeMatrixf extension.
         */
        if (shader_program &&
            (shader_program->m_bind_location_ufrm_link_matrix != -1))
        {
            glUniformMatrix4fv(shader_program->m_bind_location_ufrm_link_matrix,
                1,        // number of matrices
                GL_TRUE,  // whether to transpose matrix,
                (GLfloat*) link_matrix);
        }
        else
        {
            glMultTransposeMatrixf((GLfloat*) link_matrix);
        }
    }
    else if (s_transformation_mode == RECURSIVE_DRAW_MATRIX)
    {
        /*
         *  This code shows how to query DI-Guy character links for their
         *   coordinate matrices, and how to load those into the OpenGL
         *   transformation matrix.
         *
         *   This is effectively the same as building the matrix in code path
         *    above.
         */
        float link_matrix[4][4];

        /*
         *  Note: if the begin and end character draw calls are not made you
         *   would need to do the following:
         */
        /*
        if (get_is_position_link() && !get_attached_to_link())
        {
             //  Read the transformation matrix for the 1st link in the
             //  character chain.  This should be the character's location
             //  in the world.
            get_transformation_matrix(link_matrix);
        }
        else ...
        */

        /*
         *  Read the local transformation matrix for this link.  This is the
         *   same as the result of all the glTranslate, glRotates above.
         */
        get_link_transformation_matrix_4x4_ptr(&link_matrix[0][0]);

        /*
         *  See note on use of glMultTransposeMatrixf above.
         */
        glMultTransposeMatrixf((GLfloat*) link_matrix);
    }
    else if ((s_transformation_mode == FLOATS) || (s_transformation_mode == DOUBLES))
    {
        /*
         *  This code shows how to query DI-Guy for link-local translations
         *   and rotations.
         */

        /*
         *  First query the base class for the offsets of this link from its
         *   parent, and apply those offsets.
         */
        float offset_t[3];
        float offset_r[3];

        get_offset_translation(&offset_t[0], &offset_t[1], &offset_t[2]);
        get_offset_rotation(&offset_r[0], &offset_r[1], &offset_r[2]);

        glTranslatef(offset_t[0], offset_t[1], offset_t[2]);

        if (offset_r[0] != 0.0f)
            glRotatef(offset_r[0], 0.0, 0.0, 1.0);
        if (offset_r[1] != 0.0f)
            glRotatef(offset_r[1], 1.0, 0.0, 0.0);
        if (offset_r[2] != 0.0f)
            glRotatef(offset_r[2], 0.0, 1.0, 0.0);

        /*
         *  Next query for the current values of the dynamic transformations
         *   as read from DI-Guy motion data.  Apply these transformations.
         */
        if (s_transformation_mode == FLOATS)
        {
            float t[3];
            get_translation(&t[0], &t[1], &t[2]);
            glTranslatef(t[0], t[1], t[2]);
        }
        else if (s_transformation_mode == DOUBLES)
        {
            double t[3];
            get_translation_double(&t[0], &t[1], &t[2]);
            glTranslated(t[0], t[1], t[2]);
        }

        float r[3];
        float s[3];

        get_rotation(&r[0], &r[1], &r[2]);
        get_scale(&s[0], &s[1], &s[2]);

        if (r[0] != 0.0f)
            glRotatef(r[0], 0.0, 0.0, 1.0);
        if (r[1] != 0.0f)
            glRotatef(r[1], 1.0, 0.0, 0.0);
        if (r[2] != 0.0f)
            glRotatef(r[2], 0.0, 1.0, 0.0);

        if ((s[0] != 1.0f) ||
            (s[1] != 1.0f) ||
            (s[2] != 1.0f))
        {
            glScalef(s[0], s[1], s[2]);
        }
    }

    /*
     *  If this is an intersection render pass, set the gl color based
     *   on this link's unique color.
     */
    if (diguyApp::get_app()->get_render_pass_flags() & DIGUY_RENDER_PASS_INTERSECTION)
    {
        unsigned char r, g, b;
        get_unique_color(&r, &g, &b);
        glColor3ub(r, g, b);
    }
}
Create function definition
Create and return an object of a subclass of diguyGraphicsLink. This function will be called whenever DI-Guy requires a link object.

diguyGraphicsLink*
diguyOglGraphicsLink_create_func(void* internal_data)
{
    return new diguyOglGraphicsLink(internal_data);
}



Copyright (C) 1992-2012 Boston Dynamics

ALL RIGHTS RESERVED.

These coded instructions, statements, and computer programs contain unpublished proprietary information of Boston Dynamics and are protected by Copyright Laws of the United States. They may not be used, duplicated, or disclosed in any form, in whole or in part, without the prior written consent from Boston Dynamics.

RESTRICTED RIGHTS LEGEND

Use, duplication, or disclosure by the government is subject to restrictions as set forth in FAR 52.227.19(c)(2) or subparagraph (c)(1)(ii) of the Rights in Technical Data and Computer Sofware clause at DFARS 252.227-7013 and/or in similar or successor clauses in the FAR, or the DOD or NASA FAR Supplement, or to subparagraphs (c)(1) and (c)(2) of the Commercial Computer Software--Restricted Rights at 48 CFR 52.227-19, as applicable. Unpublished-rights reserved under the Copyright Laws of the United States.

Contractor/Manufacturer is:

Boston Dynamics/78 Fourth Avenue/Waltham MA 02451.