DI-Guy Graphics API, diguyOsgGraphicsMesh

diguyOsgGraphicsMesh.cpp

DI-Guy API Version 12.5.1

This file was automatically generated from diguyOsgGraphicsMesh.cpp. Do not edit this file directly; the changes will be lost.
Introduction
Meshes contain the visual geometry of a DI-Guy character. They are attached to shapes, and are associated with materials and textures.

The class diguyOsgGraphicsMesh is an example of a diguyGraphicsMesh subclass for a scene graph renderer using the DI-Guy Loader. The example subclass shows how to use the accessors of the diguyGraphicsMesh class and which virtual functions should be overridden for a scene graph renderer such as OSG.

Header files and forward declarations
#include "diguyOsgGraphicsMesh.h"
#include "diguyOsgGraphicsShaderProgram.h"
#include "diguyOsgGraphicsState.h"

#include <osg/Geometry>
#include <osg/ShapeDrawable>

#include <stdlib.h>

#include <libbdilog.h>
Constructor
Description:

This constructor initializes 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.

diguyOsgGraphicsMesh::diguyOsgGraphicsMesh(void* internal_data)
    :
    diguyGraphicsMesh(internal_data)
{
    /*
     *  Nothing else to do after calling base class constructor and
     *   initializing data members.
     */
}
build
Build Stage

Description:

Override of diguyGraphicsMesh::build().

The build() function should create objects necessary to render the visible geometry of this mesh in the Draw Stage.

This implementation creates osg::Group and osg::Drawable nodes that are attached to the scene graph.

void
diguyOsgGraphicsMesh::build()
{
    /*
     *  Create the first geometry drawable object.
     */
    osg::Geometry* geometry = new osg::Geometry;
    osg::ref_ptr<osg::Drawable> drawable_ptr = geometry;

    m_drawables.push_back(drawable_ptr);
    m_has_graphics_state_set.push_back(false);

    /*
     *  If not skinned or deformable, it's static.
     */
    if (get_is_skinned_mesh() || get_is_deformable())
        geometry->setDataVariance(osg::Object::DYNAMIC);
    else
        geometry->setDataVariance(osg::Object::STATIC);

    /*
     *  Prefer VBOs.
     */
    geometry->setUseVertexBufferObjects(true);

    /*
     *  Vertices.
     */
    int nv = get_vertex_count();

    osg::Vec3Array* vertices = new osg::Vec3Array;
    geometry->setVertexArray(vertices);

    int vstride = get_vertex_stride() / sizeof(float);
    float* vptr = get_first_vertex();

    /*
     *  Long way for now, adding data vertex by vertex.  I'd like to find
     *   the OSG way for simply copying a binary block of data containing
     *   float vertex data into the vertices array.
     */
    vertices->reserve(nv);

    int index;
    for (index=0; index<nv; index++)
    {
        vertices->push_back(osg::Vec3(*vptr, *(vptr+1), *(vptr+2)));

        // note that vstride is in bytes, so be careful with pointer arithmetic
        vptr += vstride;
    }

    /*
     *  Normals.
     */
    osg::Vec3Array* normals = new osg::Vec3Array;
    geometry->setNormalArray(normals);

    int nstride = get_normal_stride() / sizeof(float);
    float* nptr = get_first_normal();

    normals->reserve(nv);

    for (index=0; index<nv; index++)
    {
        normals->push_back(osg::Vec3(*nptr, *(nptr+1), *(nptr+2)));
        nptr += nstride;
    }

    geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);

    /*
     *  Texture indices.
     */
    static const int texture_unit = 0;

    osg::Vec2Array* UVs = new osg::Vec2Array;
    geometry->setTexCoordArray(texture_unit, UVs);

    int tstride = get_texture_indices_stride() / sizeof(float);
    float* tptr = get_first_texture_indices();

    UVs->reserve(nv);

    for (index=0; index<nv; index++)
    {
        UVs->push_back(osg::Vec2(*tptr, *(tptr+1)));
        tptr += tstride;
    }

    /*
     *  Polygon indices.
     */
    int ni = get_index_count();

    unsigned int* uint_ptr = NULL;
    unsigned short* ushort_ptr = NULL;

    if (get_index_type() == DIGUY_GRAPHICS_INDEX_TYPE_UINT)
        uint_ptr = (unsigned int*) get_index_buffer_data();
    else if (get_index_type() == DIGUY_GRAPHICS_INDEX_TYPE_USHORT)
        ushort_ptr = (unsigned short*) get_index_buffer_data();

    osg::DrawElementsUInt* index_set =
        new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
    geometry->addPrimitiveSet(index_set);

    index_set->reserve(ni);

    for (index=0; index<ni; index++)
    {
        if (uint_ptr)
        {
            index_set->push_back(*uint_ptr);
            uint_ptr++;
        }
        else if (ushort_ptr)
        {
            index_set->push_back((unsigned int) *ushort_ptr);
            ushort_ptr++;
        }
    }

    /*
     *  If the mesh is a skinned mesh, we need to add some GLSL attributes.
     */
    if (get_is_skinned_mesh())
    {
        geometry->setSupportsDisplayList(false);

        /*
         *  attr_link_weight GLSL attribute.
         */
        osg::Vec4Array* link_weight_array = new osg::Vec4Array;
        geometry->setVertexAttribArray(osg::Drawable::ATTRIBUTE_6, link_weight_array);
        geometry->setVertexAttribBinding(osg::Drawable::ATTRIBUTE_6, osg::Geometry::BIND_PER_VERTEX);

        int lw_stride = get_link_weight_stride() / sizeof(float);
        float* lw_ptr = get_first_link_weight();

        link_weight_array->reserve(nv);

        for (index=0; index<nv; index++)
        {
            link_weight_array->push_back(osg::Vec4(*lw_ptr, *(lw_ptr+1), *(lw_ptr+2), *(lw_ptr+3)));
            lw_ptr += lw_stride;
        }

        /*
         *  attr_link_index GLSL attribute.
         */
        osg::Vec4Array* link_index_array = new osg::Vec4Array;
        geometry->setVertexAttribArray(osg::Drawable::ATTRIBUTE_7, link_index_array);
        geometry->setVertexAttribBinding(osg::Drawable::ATTRIBUTE_7, osg::Geometry::BIND_PER_VERTEX);

        float* li_ptr = get_first_link_index();
        int li_stride = get_link_index_stride() / sizeof(float);

        link_index_array->reserve(nv);

        for (index=0; index<nv; index++)
        {
            link_index_array->push_back(osg::Vec4(*li_ptr, *(li_ptr+1), *(li_ptr+2), *(li_ptr+3)));
            li_ptr += li_stride;
        }
    }

    if ((get_vertex_format() == DIGUY_GRAPHICS_VERTEX_FORMAT_V3_N3_T2_T4_I4F_W4) ||
        (get_vertex_format() == DIGUY_GRAPHICS_VERTEX_FORMAT_V3_N3_T2_T4))
    {
        /*
         *  attr_tangents GLSL attribute. Using secondary colors as the attrib
         */
        osg::Vec4Array* vertex_tangent_array = new osg::Vec4Array;
        geometry->setVertexAttribArray(osg::Drawable::SECONDARY_COLORS, vertex_tangent_array);
        geometry->setVertexAttribBinding(osg::Drawable::SECONDARY_COLORS, osg::Geometry::BIND_PER_VERTEX);

        float* li_ptr = get_first_tangent();
        int li_stride = get_tangent_stride() / sizeof(float);

        vertex_tangent_array->reserve(nv);

        for (index=0; index<nv; index++)
        {
            vertex_tangent_array->push_back(osg::Vec4(*li_ptr, *(li_ptr+1), *(li_ptr+2), *(li_ptr+3)));
            li_ptr += li_stride;
        }
    }

    /*
     *  Set state sets of drawables.
     *
     *  If there is more than one state set for this mesh (e.g., for
     *   switched diguy graphics states), we need to create separate
     *   drawables for each switched graphics state.  The meshes will be
     *   substantially the same, except for which state set is attached to
     *   them.
     */
    int num_switched_graphics_states = get_num_switched_graphics_states();

    osg::Geometry* base_geometry = geometry;
    osg::Geometry* current_geometry = base_geometry;

    int switch_state_index;

    for (switch_state_index = 1;
        switch_state_index < num_switched_graphics_states;
        switch_state_index++)
    {
        /*
         *  Clone the geometry of the first, "base" mesh.  
         *  The mesh with switch state 0 uses the original base mesh.
         */
        current_geometry = new osg::Geometry(*base_geometry);

        osg::ref_ptr<osg::Drawable> drawable_ptr = current_geometry;
        m_drawables.push_back(drawable_ptr);
        m_has_graphics_state_set.push_back(false);
    }

    /*
     *  Free memory allocated by the loader.
     */
    //free_loader_memory();
}
unbuild
Unbuild Stage

Description:

Override of diguyGraphicsMesh::unbuild().

The unbuild() function should delete the objects created in the build() function.

This implementation dereferences the nodes created in build().

void
diguyOsgGraphicsMesh::unbuild()
{
    /*
     *  Setting the m_drawable ref_ptr to NULL dereferences the
     *   Geometry object it points to, possibly deleting it.
     */
    unsigned int i;
    for (i = 0; i < m_drawables.size(); i++)
        m_drawables[i] = NULL;

    m_drawables.clear();
}
get_num_drawables
Description:

Class-local accessor function for number of drawables objects.

int
diguyOsgGraphicsMesh::get_num_drawables()
{
    return m_drawables.size();
}
get_num_drawables
Description:

Class-local accessor function for pointers to drawables objects.

osg::Drawable*
diguyOsgGraphicsMesh::get_drawable(int drawable_index)
{
    if (m_drawables.size() == 0)
        return NULL;

    if ((drawable_index < 0) || (drawable_index >= (int) m_drawables.size()))
        drawable_index = 0;

    if (!m_has_graphics_state_set[drawable_index])
    {
        attach_state_set_to_drawable(drawable_index);
        m_has_graphics_state_set[drawable_index] = true;
    }

    osg::Drawable* drawable = m_drawables[drawable_index].get();

    return drawable;
}
attach_state_set_to_drawable
Description:

Looks up the state set for the drawable and attaches the state set to the drawable if not already attached.

Allows for just in time loading of state sets (specifically textures) associated with the drawable.

void
diguyOsgGraphicsMesh::attach_state_set_to_drawable(int drawable_index)
{
    /*
     *  Get a pointer to the graphics state.  Attach it to the created
     *   geometry object.  If this mesh has switched graphics states, ...
     */
    diguyGraphicsState* diguy_state = get_state(drawable_index);
    diguyOsgGraphicsState* diguy_osg_state = (diguyOsgGraphicsState*) diguy_state;

    if (diguy_osg_state)
    {
        /*
         *  Get the osg StateSet of this mesh's diguyGraphicsState.
         */
        osg::StateSet* diguy_graphics_state_state_set = diguy_osg_state->get_state_set();

        if (diguy_graphics_state_state_set)
        {
            osg::ref_ptr<osg::Drawable> drawable_ptr = m_drawables[drawable_index];
            osg::Geometry* current_geometry = dynamic_cast<osg::Geometry*>(drawable_ptr.get());

            /*
             *  If this is a skinned mesh, we need to make a copy of
             *   the returned state set, and add a GLSL uniform to it.
             *
             *  Otherwise we can use it as-is.
             */
            if (get_is_skinned_mesh())
            {
                osg::StateSet* state_set_copy = new osg::StateSet(*diguy_graphics_state_state_set);
                    osg::Uniform* ufrm_apply_matrices_flag = new osg::Uniform("ufrm_apply_matrices_flag", 1.0f);
                state_set_copy->addUniform(ufrm_apply_matrices_flag);
                    current_geometry->setStateSet(state_set_copy);
            }
            else
            {
                current_geometry->setStateSet(diguy_graphics_state_state_set);
            }
        }
        else
        {
            bdi_log_printf(BDI_LOG_WARN, "WARNING: DI-Guy Graphics state invalid.\n");
        }
    }
}
Create function definition
Create and return an object of a subclass of diguyGraphicsMesh. This function will be called whenever DI-Guy requires a mesh object.

diguyGraphicsMesh*
diguyOsgGraphicsMesh_create_func(void* internal_data)
{
    return new diguyOsgGraphicsMesh(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.