// Filename: eggTransform.cxx // Created by: drose (21Jun02) // //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE // Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved // // All use of this software is subject to the terms of the Panda 3d // Software license. You should have received a copy of this license // along with this source code; you will also find a current copy of // the license at http://etc.cmu.edu/panda3d/docs/license/ . // // To contact the maintainers of this program write to // panda3d-general@lists.sourceforge.net . // //////////////////////////////////////////////////////////////////// #include "eggTransform.h" //////////////////////////////////////////////////////////////////// // Function: EggTransform::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// EggTransform:: EggTransform() : _is_transform_2d(true), _transform(LMatrix4d::ident_mat()) { } //////////////////////////////////////////////////////////////////// // Function: EggTransform::Copy Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// EggTransform:: EggTransform(const EggTransform ©) : _is_transform_2d(copy._is_transform_2d), _components(copy._components), _transform(copy._transform) { } //////////////////////////////////////////////////////////////////// // Function: EggTransform::Copy assignment operator // Access: Public // Description: //////////////////////////////////////////////////////////////////// EggTransform &EggTransform:: operator = (const EggTransform ©) { _is_transform_2d = copy._is_transform_2d; _components = copy._components; _transform = copy._transform; return *this; } //////////////////////////////////////////////////////////////////// // Function: EggTransform::Destructor // Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// EggTransform:: ~EggTransform() { } //////////////////////////////////////////////////////////////////// // Function: EggTransform::add_translate2d // Access: Public // Description: Appends a 2-d translation operation to the current // transform. //////////////////////////////////////////////////////////////////// void EggTransform:: add_translate2d(const LVector2d &translate) { _components.push_back(Component(CT_translate2d)); _components.back()._vec2 = new LVecBase2d(translate); _transform *= LMatrix4d::translate_mat(LVector3d(translate[0], translate[1], 0.0)); transform_changed(); } //////////////////////////////////////////////////////////////////// // Function: EggTransform::add_translate3d // Access: Public // Description: Appends a 3-d translation operation to the current // transform. //////////////////////////////////////////////////////////////////// void EggTransform:: add_translate3d(const LVector3d &translate) { _is_transform_2d = false; _components.push_back(Component(CT_translate3d)); _components.back()._vec3 = new LVecBase3d(translate); _transform *= LMatrix4d::translate_mat(translate); transform_changed(); } //////////////////////////////////////////////////////////////////// // Function: EggTransform::add_rotate2d // Access: Public // Description: Appends a 2-d rotation to the current transform. The // rotation angle is specified in degrees // counterclockwise about the origin. //////////////////////////////////////////////////////////////////// void EggTransform:: add_rotate2d(double angle) { _components.push_back(Component(CT_rotate2d, angle)); _transform *= LMatrix4d::rotate_mat_normaxis(angle, LVector3d(0.0, 0.0, 1.0)); transform_changed(); } //////////////////////////////////////////////////////////////////// // Function: EggTransform::add_rotx // Access: Public // Description: Appends a rotation about the X axis to the current // transform. The rotation angle is specified in // degrees counterclockwise about the axis. //////////////////////////////////////////////////////////////////// void EggTransform:: add_rotx(double angle) { _is_transform_2d = false; _components.push_back(Component(CT_rotx, angle)); _transform *= LMatrix4d::rotate_mat_normaxis(angle, LVector3d(1.0, 0.0, 0.0)); transform_changed(); } //////////////////////////////////////////////////////////////////// // Function: EggTransform::add_roty // Access: Public // Description: Appends a rotation about the Y axis to the current // transform. The rotation angle is specified in // degrees counterclockwise about the axis. //////////////////////////////////////////////////////////////////// void EggTransform:: add_roty(double angle) { _is_transform_2d = false; _components.push_back(Component(CT_roty, angle)); _transform *= LMatrix4d::rotate_mat_normaxis(angle, LVector3d(0.0, 1.0, 0.0)); transform_changed(); } //////////////////////////////////////////////////////////////////// // Function: EggTransform::add_rotz // Access: Public // Description: Appends a rotation about the Z axis to the current // transform. The rotation angle is specified in // degrees counterclockwise about the axis. //////////////////////////////////////////////////////////////////// void EggTransform:: add_rotz(double angle) { _is_transform_2d = false; _components.push_back(Component(CT_rotz, angle)); _transform *= LMatrix4d::rotate_mat_normaxis(angle, LVector3d(0.0, 0.0, 1.0)); transform_changed(); } //////////////////////////////////////////////////////////////////// // Function: EggTransform::add_rotate3d // Access: Public // Description: Appends a 3-d rotation about an arbitrary axis to the // current transform. The rotation angle is specified // in degrees counterclockwise about the axis. //////////////////////////////////////////////////////////////////// void EggTransform:: add_rotate3d(double angle, const LVector3d &axis) { _is_transform_2d = false; LVector3d normaxis = normalize(axis); _components.push_back(Component(CT_rotate3d, angle)); _components.back()._vec3 = new LVecBase3d(normaxis); _transform *= LMatrix4d::rotate_mat(angle, normaxis); transform_changed(); } //////////////////////////////////////////////////////////////////// // Function: EggTransform::add_rotate3d // Access: Public // Description: Appends an arbitrary 3-d rotation to the current // transform, expressed as a quaternion. This is // converted to axis-angle notation for the egg file. //////////////////////////////////////////////////////////////////// void EggTransform:: add_rotate3d(const LQuaterniond &quat) { _is_transform_2d = false; add_rotate3d(quat.get_angle(), quat.get_axis()); transform_changed(); } //////////////////////////////////////////////////////////////////// // Function: EggTransform::add_scale2d // Access: Public // Description: Appends a possibly non-uniform scale to the current // transform. //////////////////////////////////////////////////////////////////// void EggTransform:: add_scale2d(const LVecBase2d &scale) { _is_transform_2d = false; _components.push_back(Component(CT_scale2d)); _components.back()._vec2 = new LVecBase2d(scale); _transform *= LMatrix4d::scale_mat(LVecBase3d(scale[0], scale[1], 1.0)); transform_changed(); } //////////////////////////////////////////////////////////////////// // Function: EggTransform::add_scale3d // Access: Public // Description: Appends a possibly non-uniform scale to the current // transform. //////////////////////////////////////////////////////////////////// void EggTransform:: add_scale3d(const LVecBase3d &scale) { _is_transform_2d = false; _components.push_back(Component(CT_scale3d)); _components.back()._vec3 = new LVecBase3d(scale); _transform *= LMatrix4d::scale_mat(scale); transform_changed(); } //////////////////////////////////////////////////////////////////// // Function: EggTransform::add_uniform_scale // Access: Public // Description: Appends a uniform scale to the current transform. //////////////////////////////////////////////////////////////////// void EggTransform:: add_uniform_scale(double scale) { _components.push_back(Component(CT_uniform_scale, scale)); _transform *= LMatrix4d::scale_mat(scale); transform_changed(); } //////////////////////////////////////////////////////////////////// // Function: EggTransform::write // Access: Public // Description: Writes the transform to the indicated stream in Egg // format. //////////////////////////////////////////////////////////////////// void EggTransform:: write(ostream &out, int indent_level) const { indent(out, indent_level) << " {\n"; int num_components = get_num_components(); for (int i = 0; i < num_components; i++) { switch (get_component_type(i)) { case CT_translate2d: indent(out, indent_level + 2) << " { " << get_component_vec2(i) << " }\n"; break; case CT_translate3d: indent(out, indent_level + 2) << " { " << get_component_vec3(i) << " }\n"; break; case CT_rotate2d: indent(out, indent_level + 2) << " { " << get_component_number(i) << " }\n"; break; case CT_rotx: indent(out, indent_level + 2) << " { " << get_component_number(i) << " }\n"; break; case CT_roty: indent(out, indent_level + 2) << " { " << get_component_number(i) << " }\n"; break; case CT_rotz: indent(out, indent_level + 2) << " { " << get_component_number(i) << " }\n"; break; case CT_rotate3d: indent(out, indent_level + 2) << " { " << get_component_number(i) << " " << get_component_vec3(i) << " }\n"; break; case CT_scale2d: indent(out, indent_level + 2) << " { " << get_component_vec2(i) << " }\n"; break; case CT_scale3d: indent(out, indent_level + 2) << " { " << get_component_vec3(i) << " }\n"; break; case CT_uniform_scale: indent(out, indent_level + 2) << " { " << get_component_number(i) << " }\n"; break; case CT_matrix3: indent(out, indent_level + 2) << " {\n"; get_component_mat3(i).write(out, indent_level + 4); indent(out, indent_level + 2) << "}\n"; break; case CT_matrix4: indent(out, indent_level + 2) << " {\n"; get_component_mat4(i).write(out, indent_level + 4); indent(out, indent_level + 2) << "}\n"; break; case CT_invalid: nassertv(false); break; } } indent(out, indent_level) << "}\n"; } //////////////////////////////////////////////////////////////////// // Function: EggTransform::internal_clear_transform // Access: Public // Description: Resets the transform to empty without calling // transform_changed(). //////////////////////////////////////////////////////////////////// void EggTransform:: internal_clear_transform() { _is_transform_2d = true; _components.clear(); _transform = LMatrix4d::ident_mat(); } //////////////////////////////////////////////////////////////////// // Function: EggTransform::internal_add_matrix // Access: Public // Description: Appends an arbitrary 4x4 matrix to the current // transform, without calling transform_changed(). //////////////////////////////////////////////////////////////////// void EggTransform:: internal_add_matrix(const LMatrix3d &mat) { _components.push_back(Component(CT_matrix3)); _components.back()._mat3 = new LMatrix3d(mat); LMatrix4d mat4(mat(0, 0), mat(0, 1), 0.0, mat(0, 2), mat(1, 0), mat(1, 1), 0.0, mat(1, 2), 0.0, 0.0, 1.0, 0.0, mat(2, 0), mat(2, 1), 0.0, mat(2, 2)); _transform *= mat4; } //////////////////////////////////////////////////////////////////// // Function: EggTransform::internal_add_matrix // Access: Public // Description: Appends an arbitrary 4x4 matrix to the current // transform, without calling transform_changed(). //////////////////////////////////////////////////////////////////// void EggTransform:: internal_add_matrix(const LMatrix4d &mat) { _is_transform_2d = false; _components.push_back(Component(CT_matrix4)); _components.back()._mat4 = new LMatrix4d(mat); _transform *= mat; } //////////////////////////////////////////////////////////////////// // Function: EggTransform::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 EggTransform:: transform_changed() { }