167 lines
5.3 KiB
C++
167 lines
5.3 KiB
C++
// Filename: eggTable.cxx
|
|
// Created by: drose (19Feb99)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
|
//
|
|
// All use of this software is subject to the terms of the revised BSD
|
|
// license. You should have received a copy of this license along
|
|
// with this source code in a file named "LICENSE."
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include "eggTable.h"
|
|
|
|
#include "string_utils.h"
|
|
#include "indent.h"
|
|
|
|
TypeHandle EggTable::_type_handle;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: EggTable::has_transform
|
|
// Access: Public
|
|
// Description: Returns true if the table contains a transform
|
|
// description, false otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool EggTable::
|
|
has_transform() const {
|
|
const_iterator ci;
|
|
|
|
for (ci = begin(); ci != end(); ++ci) {
|
|
EggNode *child = (*ci);
|
|
if (child->is_anim_matrix()) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: EggTable::write
|
|
// Access: Public, Virtual
|
|
// Description: Writes the table and all of its children to the
|
|
// indicated output stream in Egg format.
|
|
////////////////////////////////////////////////////////////////////
|
|
void EggTable::
|
|
write(ostream &out, int indent_level) const {
|
|
test_under_integrity();
|
|
|
|
switch (get_table_type()) {
|
|
case TT_table:
|
|
write_header(out, indent_level, "<Table>");
|
|
break;
|
|
|
|
case TT_bundle:
|
|
write_header(out, indent_level, "<Bundle>");
|
|
break;
|
|
|
|
default:
|
|
// invalid table type
|
|
nassertv(false);
|
|
}
|
|
|
|
EggGroupNode::write(out, indent_level + 2);
|
|
indent(out, indent_level) << "}\n";
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: EggTable::string_table_type
|
|
// Access: Public, Static
|
|
// Description: Returns the TableType value associated with the given
|
|
// string representation, or TT_invalid if the string
|
|
// does not match any known TableType value.
|
|
////////////////////////////////////////////////////////////////////
|
|
EggTable::TableType EggTable::
|
|
string_table_type(const string &string) {
|
|
if (cmp_nocase_uh(string, "table") == 0) {
|
|
return TT_table;
|
|
} else if (cmp_nocase_uh(string, "bundle") == 0) {
|
|
return TT_bundle;
|
|
} else {
|
|
return TT_invalid;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: EggTable::r_transform
|
|
// Access: Protected, Virtual
|
|
// Description: This is called from within the egg code by
|
|
// transform(). It applies a transformation matrix
|
|
// to the current node in some sensible way, then
|
|
// continues down the tree.
|
|
//
|
|
// The first matrix is the transformation to apply; the
|
|
// second is its inverse. The third parameter is the
|
|
// coordinate system we are changing to, or CS_default
|
|
// if we are not changing coordinate systems.
|
|
////////////////////////////////////////////////////////////////////
|
|
void EggTable::
|
|
r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
|
|
CoordinateSystem to_cs) {
|
|
// We need to duplicate the logic in EggGroup: if we have a matrix
|
|
// transform witin this table, apply the transformation to it, but
|
|
// then apply only the scale/rotational part of the transformation
|
|
// to any children.
|
|
|
|
// On the other hand, if we have no matrix transform within this
|
|
// table, pass the transformation through.
|
|
|
|
// This logic is complicated by the fact that matrix transforms with
|
|
// a <Table> group are not stored within the table itself, but
|
|
// rather within a child named "xform". Fortunately,
|
|
// has_transform() abstracts out this detail for us.
|
|
|
|
if (has_transform()) {
|
|
// At least one child of this table represents an animation matrix
|
|
// transform: that child gets the real matrix, while all other
|
|
// children get the truncated matrix.
|
|
|
|
LMatrix4d mat1 = mat;
|
|
LMatrix4d inv1 = inv;
|
|
|
|
// If we have a translation component, we should only apply
|
|
// it to the top matrix. All subsequent matrices get just the
|
|
// rotational component.
|
|
mat1.set_row(3, LVector3d(0.0, 0.0, 0.0));
|
|
inv1.set_row(3, LVector3d(0.0, 0.0, 0.0));
|
|
|
|
iterator ci;
|
|
for (ci = begin(); ci != end(); ++ci) {
|
|
EggNode *child = (*ci);
|
|
if (child->is_anim_matrix()) {
|
|
child->r_transform(mat, inv, to_cs);
|
|
} else {
|
|
child->r_transform(mat1, inv1, to_cs);
|
|
}
|
|
}
|
|
|
|
} else {
|
|
// No children of this table represent an animation matrix
|
|
// transform: all children get the real matrix.
|
|
EggGroupNode::r_transform(mat, inv, to_cs);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: TableType output operator
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
ostream &operator << (ostream &out, EggTable::TableType t) {
|
|
switch (t) {
|
|
case EggTable::TT_invalid:
|
|
return out << "invalid table";
|
|
case EggTable::TT_table:
|
|
return out << "table";
|
|
case EggTable::TT_bundle:
|
|
return out << "bundle";
|
|
}
|
|
|
|
nassertr(false, out);
|
|
return out << "(**invalid**)";
|
|
}
|