00001 // Filename: eggTable.cxx 00002 // Created by: drose (19Feb99) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "eggTable.h" 00016 00017 #include "string_utils.h" 00018 #include "indent.h" 00019 00020 TypeHandle EggTable::_type_handle; 00021 00022 //////////////////////////////////////////////////////////////////// 00023 // Function: EggTable::has_transform 00024 // Access: Public 00025 // Description: Returns true if the table contains a transform 00026 // description, false otherwise. 00027 //////////////////////////////////////////////////////////////////// 00028 bool EggTable:: 00029 has_transform() const { 00030 const_iterator ci; 00031 00032 for (ci = begin(); ci != end(); ++ci) { 00033 EggNode *child = (*ci); 00034 if (child->is_anim_matrix()) { 00035 return true; 00036 } 00037 } 00038 00039 return false; 00040 } 00041 00042 //////////////////////////////////////////////////////////////////// 00043 // Function: EggTable::write 00044 // Access: Public, Virtual 00045 // Description: Writes the table and all of its children to the 00046 // indicated output stream in Egg format. 00047 //////////////////////////////////////////////////////////////////// 00048 void EggTable:: 00049 write(ostream &out, int indent_level) const { 00050 test_under_integrity(); 00051 00052 switch (get_table_type()) { 00053 case TT_table: 00054 write_header(out, indent_level, "<Table>"); 00055 break; 00056 00057 case TT_bundle: 00058 write_header(out, indent_level, "<Bundle>"); 00059 break; 00060 00061 default: 00062 // invalid table type 00063 nassertv(false); 00064 } 00065 00066 EggGroupNode::write(out, indent_level + 2); 00067 indent(out, indent_level) << "}\n"; 00068 } 00069 00070 00071 //////////////////////////////////////////////////////////////////// 00072 // Function: EggTable::string_table_type 00073 // Access: Public, Static 00074 // Description: Returns the TableType value associated with the given 00075 // string representation, or TT_invalid if the string 00076 // does not match any known TableType value. 00077 //////////////////////////////////////////////////////////////////// 00078 EggTable::TableType EggTable:: 00079 string_table_type(const string &string) { 00080 if (cmp_nocase_uh(string, "table") == 0) { 00081 return TT_table; 00082 } else if (cmp_nocase_uh(string, "bundle") == 0) { 00083 return TT_bundle; 00084 } else { 00085 return TT_invalid; 00086 } 00087 } 00088 00089 //////////////////////////////////////////////////////////////////// 00090 // Function: EggTable::r_transform 00091 // Access: Protected, Virtual 00092 // Description: This is called from within the egg code by 00093 // transform(). It applies a transformation matrix 00094 // to the current node in some sensible way, then 00095 // continues down the tree. 00096 // 00097 // The first matrix is the transformation to apply; the 00098 // second is its inverse. The third parameter is the 00099 // coordinate system we are changing to, or CS_default 00100 // if we are not changing coordinate systems. 00101 //////////////////////////////////////////////////////////////////// 00102 void EggTable:: 00103 r_transform(const LMatrix4d &mat, const LMatrix4d &inv, 00104 CoordinateSystem to_cs) { 00105 // We need to duplicate the logic in EggGroup: if we have a matrix 00106 // transform witin this table, apply the transformation to it, but 00107 // then apply only the scale/rotational part of the transformation 00108 // to any children. 00109 00110 // On the other hand, if we have no matrix transform within this 00111 // table, pass the transformation through. 00112 00113 // This logic is complicated by the fact that matrix transforms with 00114 // a <Table> group are not stored within the table itself, but 00115 // rather within a child named "xform". Fortunately, 00116 // has_transform() abstracts out this detail for us. 00117 00118 if (has_transform()) { 00119 // At least one child of this table represents an animation matrix 00120 // transform: that child gets the real matrix, while all other 00121 // children get the truncated matrix. 00122 00123 LMatrix4d mat1 = mat; 00124 LMatrix4d inv1 = inv; 00125 00126 // If we have a translation component, we should only apply 00127 // it to the top matrix. All subsequent matrices get just the 00128 // rotational component. 00129 mat1.set_row(3, LVector3d(0.0, 0.0, 0.0)); 00130 inv1.set_row(3, LVector3d(0.0, 0.0, 0.0)); 00131 00132 iterator ci; 00133 for (ci = begin(); ci != end(); ++ci) { 00134 EggNode *child = (*ci); 00135 if (child->is_anim_matrix()) { 00136 child->r_transform(mat, inv, to_cs); 00137 } else { 00138 child->r_transform(mat1, inv1, to_cs); 00139 } 00140 } 00141 00142 } else { 00143 // No children of this table represent an animation matrix 00144 // transform: all children get the real matrix. 00145 EggGroupNode::r_transform(mat, inv, to_cs); 00146 } 00147 } 00148 00149 00150 //////////////////////////////////////////////////////////////////// 00151 // Function: TableType output operator 00152 // Description: 00153 //////////////////////////////////////////////////////////////////// 00154 ostream &operator << (ostream &out, EggTable::TableType t) { 00155 switch (t) { 00156 case EggTable::TT_invalid: 00157 return out << "invalid table"; 00158 case EggTable::TT_table: 00159 return out << "table"; 00160 case EggTable::TT_bundle: 00161 return out << "bundle"; 00162 } 00163 00164 nassertr(false, out); 00165 return out << "(**invalid**)"; 00166 }