robustify transform and object type interface

This commit is contained in:
David Rose 2003-04-08 17:30:45 +00:00
parent dd98ca18a7
commit efc0a0b45b
9 changed files with 208 additions and 38 deletions

View File

@ -27,6 +27,25 @@ get_group_type() const {
return (GroupType)(_flags & F_group_type);
}
////////////////////////////////////////////////////////////////////
// Function: EggGroup::is_instance_type
// Access: Public
// Description: Returns true if this group is an instance type node;
// i.e. it begins the root of a local coordinate space.
// This is not related to instancing (multiple copies of
// a node in a scene graph).
//
// This also includes the case of the node including a
// billboard flag without an explicit center, which
// implicitly makes the node behave like an instance.
////////////////////////////////////////////////////////////////////
INLINE bool EggGroup::
is_instance_type() const {
return
(get_group_type() == GT_instance) ||
(get_billboard_type() != BT_none && !has_billboard_center());
}
////////////////////////////////////////////////////////////////////
// Function: EggGroup::set_billboard_type
// Access: Public
@ -37,6 +56,8 @@ set_billboard_type(BillboardType type) {
// Make sure the user didn't give us any stray bits.
nassertv((type & ~F_billboard_type)==0);
_flags = (_flags & ~F_billboard_type) | type;
// This may change the transform space of this node.
update_under(0);
}
////////////////////////////////////////////////////////////////////
@ -74,6 +95,8 @@ INLINE void EggGroup::
set_billboard_center(const LPoint3d &billboard_center) {
_billboard_center = billboard_center;
_flags2 |= F2_billboard_center;
// This may change the transform space of this node.
update_under(0);
}
////////////////////////////////////////////////////////////////////
@ -84,6 +107,8 @@ set_billboard_center(const LPoint3d &billboard_center) {
INLINE void EggGroup::
clear_billboard_center() {
_flags2 &= ~F2_billboard_center;
// This may change the transform space of this node.
update_under(0);
}
////////////////////////////////////////////////////////////////////

View File

@ -22,9 +22,9 @@
#include "eggBin.h"
#include "lexerDefs.h"
#include <indent.h>
#include <string_utils.h>
#include <lmatrix.h>
#include "indent.h"
#include "string_utils.h"
#include "lmatrix.h"
TypeHandle EggGroup::_type_handle;
@ -119,6 +119,43 @@ set_group_type(GroupType type) {
}
}
////////////////////////////////////////////////////////////////////
// Function: EggGroup::has_object_type
// Access: Public
// Description: Returns true if the indicated object type has been
// added to the group, or false otherwise.
////////////////////////////////////////////////////////////////////
bool EggGroup::
has_object_type(const string &object_type) const {
vector_string::const_iterator oi;
for (oi = _object_types.begin(); oi != _object_types.end(); ++oi) {
if (cmp_nocase_uh((*oi), object_type) == 0) {
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: EggGroup::remove_object_type
// Access: Public
// Description: Removes the first instance of the indicated object
// type from the group if it is present. Returns true
// if the object type was found and removed, false
// otherwise.
////////////////////////////////////////////////////////////////////
bool EggGroup::
remove_object_type(const string &object_type) {
vector_string::iterator oi;
for (oi = _object_types.begin(); oi != _object_types.end(); ++oi) {
if (cmp_nocase_uh((*oi), object_type) == 0) {
_object_types.erase(oi);
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: EggGroup::write
// Access: Public, Virtual
@ -680,10 +717,6 @@ egg_start_parse_body() {
////////////////////////////////////////////////////////////////////
void EggGroup::
adjust_under() {
// Billboards without an explicit center are an implicit instance.
bool is_billboard_instance =
(get_billboard_type() != BT_none && !has_billboard_center());
// If we have our own transform, it carries forward.
// As of 4/18/01, this now also affects the local_coord flag, below.
@ -699,9 +732,11 @@ adjust_under() {
new MatrixFrame(invert(get_node_frame()));
_vertex_to_node =
new MatrixFrame(get_vertex_frame() * get_node_frame_inv());
_node_to_vertex =
new MatrixFrame(get_node_frame() * get_vertex_frame_inv());
}
if (get_group_type() == GT_instance || is_billboard_instance) {
if (is_instance_type()) {
_under_flags |= UF_under_instance;
if (_under_flags & UF_under_transform) {
// If we've reached an instance node and we're under a
@ -716,6 +751,7 @@ adjust_under() {
_vertex_frame = _node_frame;
_vertex_frame_inv = _node_frame_inv;
_vertex_to_node = NULL;
_node_to_vertex = NULL;
}
}
@ -753,7 +789,7 @@ r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
mat1.set_row(3, LVector3d(0.0, 0.0, 0.0));
inv1.set_row(3, LVector3d(0.0, 0.0, 0.0));
set_transform(inv1 * get_transform() * mat);
internal_set_transform(inv1 * get_transform() * mat);
EggGroupNode::r_transform(mat1, inv1, to_cs);
} else {
@ -799,11 +835,26 @@ r_flatten_transforms() {
}
if (get_group_type() != GT_joint) {
clear_transform();
internal_clear_transform();
}
}
////////////////////////////////////////////////////////////////////
// Function: EggGroup::transform_changed
// Access: Protected, Virtual
// Description: This virtual method is inherited by EggTransform3d;
// it is called whenever the transform is changed.
////////////////////////////////////////////////////////////////////
void EggGroup::
transform_changed() {
// Recompute all of the cached transforms at this node and below.
// We should probably make this smarter and do lazy evaluation of
// these transforms, rather than having to recompute the whole tree
// with every change to a parent node's transform.
update_under(0);
}
////////////////////////////////////////////////////////////////////

View File

@ -100,6 +100,7 @@ public:
void set_group_type(GroupType type);
INLINE GroupType get_group_type() const;
INLINE bool is_instance_type() const;
INLINE void set_billboard_type(BillboardType type);
INLINE BillboardType get_billboard_type() const;
@ -136,6 +137,8 @@ public:
INLINE void clear_object_types();
INLINE int get_num_object_types() const;
INLINE string get_object_type(int index) const;
bool has_object_type(const string &object_type) const;
bool remove_object_type(const string &object_type);
INLINE void set_model_flag(bool flag);
INLINE bool get_model_flag() const;
@ -201,6 +204,8 @@ protected:
CoordinateSystem to_cs);
virtual void r_flatten_transforms();
virtual void transform_changed();
private:
enum Flags {

View File

@ -212,6 +212,26 @@ get_vertex_to_node() const {
}
}
////////////////////////////////////////////////////////////////////
// Function: EggNode::get_node_to_vertex
// Access: Public
// Description: Returns the transformation matrix suitable for
// converting vertices in the coordinate space of the
// node to the appropriate coordinate space for storing
// in the egg file. This is the same thing as:
//
// get_node_frame() * get_vertex_frame_inv()
//
////////////////////////////////////////////////////////////////////
INLINE const LMatrix4d &EggNode::
get_node_to_vertex() const {
if (_node_to_vertex == (LMatrix4d *)NULL) {
return LMatrix4d::ident_mat();
} else {
return *_node_to_vertex;
}
}
////////////////////////////////////////////////////////////////////
// Function: EggNode::transform
@ -259,4 +279,5 @@ transform_vertices_only(const LMatrix4d &mat) {
INLINE void EggNode::
flatten_transforms() {
r_flatten_transforms();
update_under(0);
}

View File

@ -244,6 +244,7 @@ update_under(int depth_offset) {
_vertex_frame_inv = NULL;
_node_frame_inv = NULL;
_vertex_to_node = NULL;
_node_to_vertex = NULL;
} else {
depth = _parent->_depth + 1;
_under_flags = _parent->_under_flags;
@ -252,6 +253,7 @@ update_under(int depth_offset) {
_vertex_frame_inv = _parent->_vertex_frame_inv;
_node_frame_inv = _parent->_node_frame_inv;
_vertex_to_node = _parent->_vertex_to_node;
_node_to_vertex = _parent->_node_to_vertex;
}
if (depth - _depth != depth_offset) {

View File

@ -56,6 +56,7 @@ public:
INLINE const LMatrix4d &get_vertex_frame_inv() const;
INLINE const LMatrix4d &get_node_frame_inv() const;
INLINE const LMatrix4d &get_vertex_to_node() const;
INLINE const LMatrix4d &get_node_to_vertex() const;
INLINE void transform(const LMatrix4d &mat);
INLINE void transform_vertices_only(const LMatrix4d &mat);
@ -112,6 +113,7 @@ protected:
PT(MatrixFrame) _vertex_frame_inv;
PT(MatrixFrame) _node_frame_inv;
PT(MatrixFrame) _vertex_to_node;
PT(MatrixFrame) _node_to_vertex;
public:

View File

@ -90,6 +90,29 @@ INLINE EggTransform3d::Component::
}
}
////////////////////////////////////////////////////////////////////
// Function: EggTransform3d::clear_transform
// Access: Public
// Description: Resets the transform to empty, identity.
////////////////////////////////////////////////////////////////////
INLINE void EggTransform3d::
clear_transform() {
internal_clear_transform();
transform_changed();
}
////////////////////////////////////////////////////////////////////
// Function: EggTransform3d::add_matrix
// Access: Public
// Description: Appends an arbitrary 4x4 matrix to the current
// transform.
////////////////////////////////////////////////////////////////////
INLINE void EggTransform3d::
add_matrix(const LMatrix4d &mat) {
internal_add_matrix(mat);
transform_changed();
}
////////////////////////////////////////////////////////////////////
// Function: EggTransform3d::has_transform
// Access: Public
@ -111,8 +134,8 @@ has_transform() const {
////////////////////////////////////////////////////////////////////
INLINE void EggTransform3d::
set_transform(const LMatrix4d &mat) {
clear_transform();
add_matrix(mat);
internal_set_transform(mat);
transform_changed();
}
////////////////////////////////////////////////////////////////////
@ -203,3 +226,15 @@ get_component_matrix(int n) const {
nassertr(_components[n]._matrix != (LMatrix4d *)NULL, LMatrix4d::ident_mat());
return *_components[n]._matrix;
}
////////////////////////////////////////////////////////////////////
// Function: EggTransform3d::internal_set_transform
// Access: Protected
// Description: Sets the overall transform without calling
// transform_changed().
////////////////////////////////////////////////////////////////////
INLINE void EggTransform3d::
internal_set_transform(const LMatrix4d &mat) {
internal_clear_transform();
internal_add_matrix(mat);
}

View File

@ -63,17 +63,6 @@ EggTransform3d::
~EggTransform3d() {
}
////////////////////////////////////////////////////////////////////
// Function: EggTransform3d::clear_transform
// Access: Public
// Description: Resets the transform to empty, identity.
////////////////////////////////////////////////////////////////////
void EggTransform3d::
clear_transform() {
_components.clear();
_transform = LMatrix4d::ident_mat();
}
////////////////////////////////////////////////////////////////////
// Function: EggTransform3d::add_translate
// Access: Public
@ -85,6 +74,7 @@ add_translate(const LVector3d &translate) {
_components.push_back(Component(CT_translate));
_components.back()._vector = new LVector3d(translate);
_transform *= LMatrix4d::translate_mat(translate);
transform_changed();
}
////////////////////////////////////////////////////////////////////
@ -98,6 +88,7 @@ void EggTransform3d::
add_rotx(double angle) {
_components.push_back(Component(CT_rotx, angle));
_transform *= LMatrix4d::rotate_mat_normaxis(angle, LVector3d(1.0, 0.0, 0.0));
transform_changed();
}
////////////////////////////////////////////////////////////////////
@ -111,6 +102,7 @@ void EggTransform3d::
add_roty(double angle) {
_components.push_back(Component(CT_roty, angle));
_transform *= LMatrix4d::rotate_mat_normaxis(angle, LVector3d(0.0, 1.0, 0.0));
transform_changed();
}
////////////////////////////////////////////////////////////////////
@ -124,6 +116,7 @@ void EggTransform3d::
add_rotz(double angle) {
_components.push_back(Component(CT_rotz, angle));
_transform *= LMatrix4d::rotate_mat_normaxis(angle, LVector3d(0.0, 0.0, 1.0));
transform_changed();
}
////////////////////////////////////////////////////////////////////
@ -139,6 +132,7 @@ add_rotate(double angle, const LVector3d &axis) {
_components.push_back(Component(CT_rotate, angle));
_components.back()._vector = new LVector3d(normaxis);
_transform *= LMatrix4d::rotate_mat(angle, normaxis);
transform_changed();
}
////////////////////////////////////////////////////////////////////
@ -151,6 +145,7 @@ add_rotate(double angle, const LVector3d &axis) {
void EggTransform3d::
add_rotate(const LQuaterniond &quat) {
add_rotate(quat.get_angle(), quat.get_axis());
transform_changed();
}
////////////////////////////////////////////////////////////////////
@ -164,6 +159,7 @@ add_scale(const LVecBase3d &scale) {
_components.push_back(Component(CT_scale));
_components.back()._vector = new LVector3d(scale);
_transform *= LMatrix4d::scale_mat(scale);
transform_changed();
}
////////////////////////////////////////////////////////////////////
@ -175,19 +171,7 @@ void EggTransform3d::
add_uniform_scale(double scale) {
_components.push_back(Component(CT_uniform_scale, scale));
_transform *= LMatrix4d::scale_mat(scale);
}
////////////////////////////////////////////////////////////////////
// Function: EggTransform3d::add_matrix
// Access: Public
// Description: Appends an arbitrary 4x4 matrix to the current
// transform.
////////////////////////////////////////////////////////////////////
void EggTransform3d::
add_matrix(const LMatrix4d &mat) {
_components.push_back(Component(CT_matrix));
_components.back()._matrix = new LMatrix4d(mat);
_transform *= mat;
transform_changed();
}
////////////////////////////////////////////////////////////////////
@ -253,3 +237,41 @@ write(ostream &out, int indent_level) const {
indent(out, indent_level) << "}\n";
}
////////////////////////////////////////////////////////////////////
// Function: EggTransform3d::internal_clear_transform
// Access: Public
// Description: Resets the transform to empty without calling
// transform_changed().
////////////////////////////////////////////////////////////////////
void EggTransform3d::
internal_clear_transform() {
_components.clear();
_transform = LMatrix4d::ident_mat();
}
////////////////////////////////////////////////////////////////////
// Function: EggTransform3d::internal_add_matrix
// Access: Public
// Description: Appends an arbitrary 4x4 matrix to the current
// transform, without calling transform_changed().
////////////////////////////////////////////////////////////////////
void EggTransform3d::
internal_add_matrix(const LMatrix4d &mat) {
_components.push_back(Component(CT_matrix));
_components.back()._matrix = new LMatrix4d(mat);
_transform *= mat;
}
////////////////////////////////////////////////////////////////////
// Function: EggTransform3d::transform_changed
// Access: Protected, Virtual
// Description: This virtual method is called whenever the transform
// is changed; it is intended to provide a hook for
// derived classes (e.g. EggGroup) to update their
// internal cache appropriately.
////////////////////////////////////////////////////////////////////
void EggTransform3d::
transform_changed() {
}

View File

@ -37,7 +37,7 @@ public:
EggTransform3d &operator = (const EggTransform3d &copy);
~EggTransform3d();
void clear_transform();
INLINE void clear_transform();
void add_translate(const LVector3d &translate);
void add_rotx(double angle);
@ -47,7 +47,7 @@ public:
void add_rotate(const LQuaterniond &quat);
void add_scale(const LVecBase3d &scale);
void add_uniform_scale(double scale);
void add_matrix(const LMatrix4d &mat);
INLINE void add_matrix(const LMatrix4d &mat);
INLINE bool has_transform() const;
INLINE void set_transform(const LMatrix4d &mat);
@ -74,6 +74,13 @@ public:
void write(ostream &out, int indent_level) const;
protected:
void internal_clear_transform();
void internal_add_matrix(const LMatrix4d &mat);
INLINE void internal_set_transform(const LMatrix4d &mat);
virtual void transform_changed();
private:
class Component {
public: