
This file was automatically generated from diguyOsgExtGraphicsLink.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:
- to serve as attachment points for shapes, and
- to form a skeleton that can be animated using motion data.
The class diguyOsgExtGraphicsLink is an example of a diguyGraphicsLink subclass for a scene graph renderer using an external loader. The example subclass shows how to use the accessors of the diguyGraphicsLink class and which virtual functions should be overridden for a retained mode renderer such as Open Scene Graph.
Transformation Coordinate Systems
This example shows two ways that link tranform matrix data can be retrieved from the diguyGraphicsLink base class: transforms in character-local space, and transforms in link-local space.
Character Local
For the character-local approach the top-level position link is given the world space transform; this becomes the origin of the character local coordinate system. All child link transforms are in that coordinate system.
This approach will be faster than the link-local approach, as DI-Guy has already computed the character-local matrices, and they can be retrieved and applied as-is to OSG Matrixf nodes.
Link Local
For the link-local approach all links are given a transform relative to their parent link's coordinate system.
This approach will be slower than the character-local approach, for in each update call the translate, rotate, and scale values must be retrieved, and a link-local matrix generated from these values.
(This approach was used in DI-Guy versions prior to DI-Guy 11.
| Header files and forward declarations |
#define USE_CHARACTER_LOCAL_TRANSFORMS 1 #include "diguyOsgExtGraphicsLink.h" #include <libbdilog.h> #include <diguyCharacter.h> #include <stdlib.h> #include <osg/Group> #include <osg/MatrixTransform> #include <osg/Matrixf> #define CONSTANT_PI ((float) 3.1415926535897932384626433832795028841971693993751058209749445923078164062862L) #define CONSTANT_DEG2RAD (CONSTANT_PI / 180.0f) /* * Pointer to an osg::Group to which DI-Guy character geometry should be * attached. */ osg::Group* diguyOsgExtGraphicsLink::s_diguy_attach_pt = NULL;
| Constructor |
Initialize data members of the class to a known state.
Base class data will not be fully initialized until the Build Stage is done, so base class accessors should not be called here.
diguyOsgExtGraphicsLink::diguyOsgExtGraphicsLink(void* internal_data) : diguyGraphicsLink(internal_data), m_offset_node(NULL), m_dof_node(NULL) { /* * Nothing else to do after calling base class constructor and * initializing data members. */ }
| Character Local Approach |
#if USE_CHARACTER_LOCAL_TRANSFORMS
| build |
Build Stage
Description:
Override of diguyGraphicsLink::build().
The build() function should create the objects necessary to apply offsets contained in this link to its shapes and child links.
There are two types of offsets:
- Static offsets that specify link lengths from the parent link (e.g., distance from shoulder to elbow).
- Runtime transformations, usually joint rotations, read from DI-Guy motion data.
Since links don't have any actual geometry (shapes and meshes attached to them do), usually no actual drawing occurs in this function.
This implementation creates osg::MatrixTransform that will allow offsets from the parent link to be applied, and transformations from DI-Guy motion data to be applied.
void diguyOsgExtGraphicsLink::build() { /* * If we're using the character-local transformation approach, the * offset nodes aren't needed, and the DOF nodes are attached to the * top-level position node. */ if (get_is_position_link()) { /* * The top-level position link needs an offset node. This node * is attached to the scene via s_diguy_attach_pt. It does not * have any actual offset values, however; it just serves as a * top-level handle to the node hierarchy. */ m_offset_node = new osg::MatrixTransform; /* * Build a DOF (degree of freedom) matrix transform for this * link that will be updated each frame from motion data. * * The position link DOF node applies a transform from world * space to character-local space. */ m_dof_node = new osg::MatrixTransform; m_offset_node->addChild(m_dof_node); } else { /* * Build a DOF (degree of freedom) matrix transform for this * link that will be updated each frame from motion data. * * Non-top-level links are attached to the position link's DOF * node. They will contain character-local transforms. */ m_dof_node = new osg::MatrixTransform; /* * Attach the DOF node to the position link's DOF node. */ diguyCharacter* character = get_character(); if (character) { diguyGraphicsLink* position_link = character->get_position_link(); diguyOsgExtGraphicsLink* osg_position_link = (diguyOsgExtGraphicsLink *) position_link; osg_position_link->m_dof_node->addChild(m_dof_node); } } }
| unbuild |
Unbuild Stage
Description:
Override of diguyGraphicsLink::unbuild().
The unbuild() function should destroy the objects created in the build() function.
This implementation dereference the nodes created in build().
void diguyOsgExtGraphicsLink::unbuild() { if (get_is_position_link()) { m_offset_node->removeChild(m_dof_node); m_offset_node = NULL; m_dof_node = NULL; } else { diguyCharacter* character = get_character(); if (character) { diguyGraphicsLink* position_link = character->get_position_link(); diguyOsgExtGraphicsLink* osg_position_link = (diguyOsgExtGraphicsLink *) position_link; osg_position_link->m_dof_node->removeChild(m_dof_node); m_dof_node = NULL; } } }
| update |
Update Stage
Description:
Override of diguyGraphicsLink::update().
The update() function should update objects created in build() with up-to-date values from motion data.
This implementation reads transformation data from the base class and loads it into the osg::MatrixTransform nodes created in build().
void diguyOsgExtGraphicsLink::update() { /* * Update the scene graph nodes created during build() with new * values. The position link matrix is in world space, all others * in character-local space. */ osg::Matrixf mat; float link_matrix[4][4]; if (get_is_position_link()) get_transformation_matrix(link_matrix); else get_local_transformation_matrix(link_matrix); /* * DI-Guy transformation matrices are transposed from what OSG * uses. */ mat.set( link_matrix[0][0], link_matrix[1][0], link_matrix[2][0], link_matrix[3][0], link_matrix[0][1], link_matrix[1][1], link_matrix[2][1], link_matrix[3][1], link_matrix[0][2], link_matrix[1][2], link_matrix[2][2], link_matrix[3][2], link_matrix[0][3], link_matrix[1][3], link_matrix[2][3], link_matrix[3][3]); /* * Set the m_dof_node matrix. */ m_dof_node->setMatrix(mat); }
| Link Local Approach |
#else
| build |
Build Stage
Description:
Override of diguyGraphicsLink::build().
Look in the Character Local Approach build() comment above for what this function should do.
void diguyOsgExtGraphicsLink::build() { /* * Create a matrix that has the link's static offset * transformations. This matrix will not be changed during * update() calls. */ osg::Matrixf mat; osg::Matrixf mat_temp; mat.makeIdentity(); /* * Add explicit offset translation. */ float offset_t[3]; get_offset_translation(&offset_t[0], &offset_t[1], &offset_t[2]); mat_temp.makeTranslate(offset_t[0], offset_t[1], offset_t[2]); mat.preMult(mat_temp); /* * Add explicit offset rotation. */ float offset_r[3]; get_offset_rotation(&offset_r[0], &offset_r[1], &offset_r[2]); if ((offset_r[0] != 0.0f) || (offset_r[1] != 0.0f) || (offset_r[2] != 0.0f)) { mat_temp.makeRotate(offset_r[2] * CONSTANT_DEG2RAD, osg::Vec3f(0.0f, 1.0f, 0.0f), offset_r[1] * CONSTANT_DEG2RAD, osg::Vec3f(1.0f, 0.0f, 0.0f), offset_r[0] * CONSTANT_DEG2RAD, osg::Vec3f(0.0f, 0.0f, 1.0f)); mat.preMult(mat_temp); } /* * The runtime translation values of each link may be marked as * always static. If this is the case for this link, add the * runtime translation into the offset matrix. */ if (get_translation_is_static()) { float t[3]; get_translation(&t[0], &t[1], &t[2]); mat_temp.makeTranslate(t[0], t[1], t[2]); mat.preMult(mat_temp); } /* * Runime rotation values may also be marked as static. */ if (get_rotation_is_static()) { float r[3]; get_rotation(&r[0], &r[1], &r[2]); if ((r[0] != 0.0f) || (r[1] != 0.0f) || (r[2] != 0.0f)) { mat_temp.makeRotate(r[2] * CONSTANT_DEG2RAD, osg::Vec3f(0.0f, 1.0f, 0.0f), r[1] * CONSTANT_DEG2RAD, osg::Vec3f(1.0f, 0.0f, 0.0f), r[0] * CONSTANT_DEG2RAD, osg::Vec3f(0.0f, 0.0f, 1.0f)); mat.preMult(mat_temp); } } /* * Runime scale values may also be marked as static. */ if (get_scale_is_static()) { float s[3]; get_scale(&s[0], &s[1], &s[2]); if ((s[0] != 1.0f) || (s[1] != 1.0f) || (s[2] != 1.0f)) { mat_temp.makeScale(osg::Vec3f(s[0], s[1], s[2])); mat.preMult(mat_temp); } } /* * Build an offset node for this link based on the above computed * offset matrix. */ m_offset_node = new osg::MatrixTransform; m_offset_node->setMatrix(mat); /* * Build a DOF (degree of freedom) matrix transform for this link * that will be updated each frame from motion data. * * This DOF node will be updated with link-local transform data. */ m_dof_node = new osg::MatrixTransform; m_offset_node->addChild(m_dof_node); /* * See if we should attach to parent link. The top-level position * link should not start out attached. When necessary it will be * attached to the scene graph in the attach_to_scene() function. */ if (!get_is_position_link()) { diguyGraphicsLink* parent_link = get_parent_link(); diguyOsgExtGraphicsLink* osg_parent_link = (diguyOsgExtGraphicsLink *) parent_link; osg_parent_link->m_dof_node->addChild(m_offset_node); } }
| unbuild |
Unbuild Stage
Description:
Override of diguyGraphicsLink::unbuild().
Look in the Character Local Approach unbuild() comment above for what this function should do.
void diguyOsgExtGraphicsLink::unbuild() { m_offset_node->removeChild(m_dof_node); if (!get_is_position_link()) { diguyGraphicsLink* parent_link = get_parent_link(); diguyOsgExtGraphicsLink* osg_parent_link = (diguyOsgExtGraphicsLink *) parent_link; osg_parent_link->m_dof_node->removeChild(m_offset_node); } /* * Setting the m_offset_node and m_dof_node ref_ptrs to NULL * dereferences the objects they point to, possibly deleting them. */ m_offset_node = NULL; m_dof_node = NULL; }
| update |
Update Stage
Description:
Override of diguyGraphicsLink::update().
Look in the Character Local Approach update() comment above for what this function should do.
void diguyOsgExtGraphicsLink::update() { /* * Update the scene graph nodes created during build() with new * values. * * These values should be obtained by calling get_translation(), * get_rotation(), and get_scale(). */ osg::Matrixf mat; osg::Matrixf mat_temp; /* * Start with identity. */ mat.makeIdentity(); if (!get_translation_is_static()) { float t[3]; get_translation(&t[0], &t[1], &t[2]); mat_temp.makeTranslate(t[0], t[1], t[2]); mat.preMult(mat_temp); } if (!get_rotation_is_static()) { float r[3]; get_rotation(&r[0], &r[1], &r[2]); if ((r[0] != 0.0f) || (r[1] != 0.0f) || (r[2] != 0.0f)) { mat_temp.makeRotate(r[2] * CONSTANT_DEG2RAD, osg::Vec3f(0.0f, 1.0f, 0.0f), r[1] * CONSTANT_DEG2RAD, osg::Vec3f(1.0f, 0.0f, 0.0f), r[0] * CONSTANT_DEG2RAD, osg::Vec3f(0.0f, 0.0f, 1.0f)); mat.preMult(mat_temp); } } if (!get_scale_is_static()) { float s[3]; get_scale(&s[0], &s[1], &s[2]); if ((s[0] != 1.0f) || (s[1] != 1.0f) || (s[2] != 1.0f)) { mat_temp.makeScale(osg::Vec3f(s[0], s[1], s[2])); mat.preMult(mat_temp); } } /* * Set the m_dof_node matrix. */ m_dof_node->setMatrix(mat); }
| Common to Character Local and Link Local Approach |
#endif
| attach_to_scene |
Update Stage
Description:
Override of diguyGraphicsLink::attach_to_scene().
The attach_to_scene() function should perform the actions necessary to attach this link to somewhere on the scene graph.
This implementation attaches this link's offset node as a child to the node specified by s_diguy_attach_pt.
This function will only be called on the position link.
void diguyOsgExtGraphicsLink::attach_to_scene() { /* * Need m_offset_node to do attach. */ if (!m_offset_node) return; if (m_offset_node->getNumParents() > 0) { bdi_log_printf(BDI_LOG_WARN, "WARNING: Link '%s' already attached to something. " "Call to attach_to_scene() failed.\n", get_name()); return; } /* * Make the attachment. */ if (s_diguy_attach_pt) { s_diguy_attach_pt->addChild(m_offset_node); } }
| detach_from_scene |
Update Stage
Description:
Override of diguyGraphicsLink::detach_from_scene().
The detach_to_scene() function should perform the actions necessary to detach this link from the scene graph.
This implementation removes this link's offset node as a child from the node specified by s_diguy_attach_pt.
This function will only be called on the position link.
void diguyOsgExtGraphicsLink::detach_from_scene() { /* * Need m_offset_node to do detach. */ if (!m_offset_node) return; /* * If m_offset_node has no parents, it is already detached. */ if (m_offset_node->getNumParents() == 0) { bdi_log_printf(BDI_LOG_WARN, "WARNING: Link '%s' not attached to anything. " "Call to detach_from_scene() failed.\n", get_name()); return; } if (s_diguy_attach_pt) { s_diguy_attach_pt->removeChild(m_offset_node); } }
| attach_to_link |
Update Stage
Description:
Override of diguyGraphicsLink::attach_to_link().
This function is similar to attach_to_scene(), but the link's object should be attached to another link instead of the scene graph.
void diguyOsgExtGraphicsLink::attach_to_link(diguyGraphicsLink* link) { /* * Need m_offset_node to do attach. */ if (!m_offset_node) return; /* * If m_offset_node already has parents, it is already attached. */ if (m_offset_node->getNumParents() > 0) { bdi_log_printf(BDI_LOG_WARN, "WARNING: Link '%s' already attached to something. " "Call to attach_to_link() failed.\n", get_name()); return; } /* * Attach m_offset_node of this link to m_dof_node of the * attachment link. */ diguyOsgExtGraphicsLink* osg_link = (diguyOsgExtGraphicsLink*) link; if (osg_link->m_dof_node) { osg_link->m_dof_node->addChild(m_offset_node); } }
| detach_from_link |
Update Stage
Description:
Override of diguyGraphicsLink::detach_from_link().
This function is similar to detach_from_scene(), but the link's object should be detached from another link instead of the scene graph.
void diguyOsgExtGraphicsLink::detach_from_link() { /* * Need m_offset_node to do detach. */ if (!m_offset_node) return; /* * If m_offset_node has no parents, it is already detached. */ if (m_offset_node->getNumParents() == 0) { bdi_log_printf(BDI_LOG_WARN, "WARNING: Link '%s' not attached to anything. " "Call to detach_from_link() failed.\n", get_name()); return; } diguyGraphicsLink* link = get_attached_to_link(); diguyOsgExtGraphicsLink* osg_link = (diguyOsgExtGraphicsLink*) link; if (osg_link->m_dof_node) { osg_link->m_dof_node->removeChild(m_offset_node); } }
| 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* diguyOsgExtGraphicsLink_create_func(void* internal_data) { return new diguyOsgExtGraphicsLink(internal_data); }
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.