Panda3D
 All Classes Functions Variables Enumerations
fltTransformRotateScale.cxx
00001 // Filename: fltTransformRotateScale.cxx
00002 // Created by:  drose (30Aug00)
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 "fltTransformRotateScale.h"
00016 #include "fltRecordReader.h"
00017 #include "fltRecordWriter.h"
00018 
00019 #include "mathNumbers.h"
00020 #include "look_at.h"
00021 
00022 TypeHandle FltTransformRotateScale::_type_handle;
00023 
00024 ////////////////////////////////////////////////////////////////////
00025 //     Function: FltTransformRotateScale::Constructor
00026 //       Access: Public
00027 //  Description:
00028 ////////////////////////////////////////////////////////////////////
00029 FltTransformRotateScale::
00030 FltTransformRotateScale(FltHeader *header) : FltTransformRecord(header) {
00031   _center.set(0.0, 0.0, 0.0);
00032   _reference_point.set(0.0, 0.0, 0.0);
00033   _to_point.set(0.0, 0.0, 0.0);
00034   _overall_scale = 1.0;
00035   _axis_scale = 1.0;
00036   _angle = 0.0;
00037 }
00038 
00039 ////////////////////////////////////////////////////////////////////
00040 //     Function: FltTransformRotateScale::set
00041 //       Access: Public
00042 //  Description: Defines the transform explicitly.  The angle of
00043 //               rotation is determined by the angle between the
00044 //               reference point and the to point (relative to the
00045 //               center), and the scale factor is determined by the
00046 //               distance between the reference point and the center
00047 //               point.  If axis_scale is true, the scale is along
00048 //               reference point axis only; otherwise, it is a uniform
00049 //               scale.
00050 ////////////////////////////////////////////////////////////////////
00051 void FltTransformRotateScale::
00052 set(const LPoint3d &center, const LPoint3d &reference_point,
00053     const LPoint3d &to_point, bool axis_scale) {
00054   _center = center;
00055   _reference_point = reference_point;
00056   _to_point = to_point;
00057 
00058   LVector3d v1 = _reference_point - _center;
00059   LVector3d v2 = _to_point - _center;
00060 
00061   _angle =
00062     acos(dot(normalize(v1), normalize(v2))) * 180.0 / MathNumbers::pi;
00063 
00064   if (axis_scale) {
00065     _axis_scale = length(v1);
00066     _overall_scale = 1.0;
00067   } else {
00068     _overall_scale = length(v1);
00069     _axis_scale = 1.0;
00070   }
00071 
00072   recompute_matrix();
00073 }
00074 
00075 ////////////////////////////////////////////////////////////////////
00076 //     Function: FltTransformRotateScale::get_center
00077 //       Access: Public
00078 //  Description:
00079 ////////////////////////////////////////////////////////////////////
00080 const LPoint3d &FltTransformRotateScale::
00081 get_center() const {
00082   return _center;
00083 }
00084 
00085 ////////////////////////////////////////////////////////////////////
00086 //     Function: FltTransformRotateScale::get_reference_point
00087 //       Access: Public
00088 //  Description:
00089 ////////////////////////////////////////////////////////////////////
00090 const LPoint3d &FltTransformRotateScale::
00091 get_reference_point() const {
00092   return _reference_point;
00093 }
00094 
00095 ////////////////////////////////////////////////////////////////////
00096 //     Function: FltTransformRotateScale::get_to_point
00097 //       Access: Public
00098 //  Description:
00099 ////////////////////////////////////////////////////////////////////
00100 const LPoint3d &FltTransformRotateScale::
00101 get_to_point() const {
00102   return _to_point;
00103 }
00104 
00105 ////////////////////////////////////////////////////////////////////
00106 //     Function: FltTransformRotateScale::get_overall_scale
00107 //       Access: Public
00108 //  Description: Returns the overall scale factor.
00109 ////////////////////////////////////////////////////////////////////
00110 PN_stdfloat FltTransformRotateScale::
00111 get_overall_scale() const {
00112   return _overall_scale;
00113 }
00114 
00115 ////////////////////////////////////////////////////////////////////
00116 //     Function: FltTransformRotateScale::get_axis_scale
00117 //       Access: Public
00118 //  Description: Returns the scale factor in the direction of the
00119 //               axis.
00120 ////////////////////////////////////////////////////////////////////
00121 PN_stdfloat FltTransformRotateScale::
00122 get_axis_scale() const {
00123   return _axis_scale;
00124 }
00125 
00126 ////////////////////////////////////////////////////////////////////
00127 //     Function: FltTransformRotateScale::get_angle
00128 //       Access: Public
00129 //  Description: Returns the angle of rotation in degrees.
00130 ////////////////////////////////////////////////////////////////////
00131 PN_stdfloat FltTransformRotateScale::
00132 get_angle() const {
00133   return _angle;
00134 }
00135 
00136 ////////////////////////////////////////////////////////////////////
00137 //     Function: FltTransformRotateScale::recompute_matrix
00138 //       Access: Private
00139 //  Description:
00140 ////////////////////////////////////////////////////////////////////
00141 void FltTransformRotateScale::
00142 recompute_matrix() {
00143   LVector3d v1 = _reference_point - _center;
00144   LVector3d v2 = _to_point - _center;
00145   LVector3d rotate_axis = normalize(cross(v1, v2));
00146 
00147   // To scale along an axis, we have to do a bit of work.  First
00148   // determine the matrices to rotate and unrotate the rotate axis
00149   // to the y-forward axis.
00150   LMatrix4d r1;
00151   look_at(r1, v1, rotate_axis, CS_zup_right);
00152 
00153   _matrix =
00154     LMatrix4d::translate_mat(-_center) *
00155     r1 *
00156     LMatrix4d::scale_mat(1.0, _axis_scale, 1.0) *
00157     LMatrix4d::scale_mat(_overall_scale) *
00158     invert(r1) *
00159     LMatrix4d::rotate_mat(_angle, rotate_axis, CS_zup_right) *
00160     LMatrix4d::translate_mat(_center);
00161 }
00162 
00163 ////////////////////////////////////////////////////////////////////
00164 //     Function: FltTransformRotateScale::extract_record
00165 //       Access: Protected, Virtual
00166 //  Description: Fills in the information in this record based on the
00167 //               information given in the indicated datagram, whose
00168 //               opcode has already been read.  Returns true on
00169 //               success, false if the datagram is invalid.
00170 ////////////////////////////////////////////////////////////////////
00171 bool FltTransformRotateScale::
00172 extract_record(FltRecordReader &reader) {
00173   if (!FltTransformRecord::extract_record(reader)) {
00174     return false;
00175   }
00176 
00177   nassertr(reader.get_opcode() == FO_rotate_and_scale, false);
00178   DatagramIterator &iterator = reader.get_iterator();
00179 
00180   iterator.skip_bytes(4);   // Undocumented additional padding.
00181 
00182   _center[0] = iterator.get_be_float64();
00183   _center[1] = iterator.get_be_float64();
00184   _center[2] = iterator.get_be_float64();
00185   _reference_point[0] = iterator.get_be_float64();
00186   _reference_point[1] = iterator.get_be_float64();
00187   _reference_point[2] = iterator.get_be_float64();
00188   _to_point[0] = iterator.get_be_float64();
00189   _to_point[1] = iterator.get_be_float64();
00190   _to_point[2] = iterator.get_be_float64();
00191   _overall_scale = iterator.get_be_float32();
00192   _axis_scale = iterator.get_be_float32();
00193   _angle = iterator.get_be_float32();
00194 
00195   iterator.skip_bytes(4);   // Undocumented additional padding.
00196 
00197   recompute_matrix();
00198 
00199   check_remaining_size(iterator);
00200   return true;
00201 }
00202 
00203 ////////////////////////////////////////////////////////////////////
00204 //     Function: FltTransformRotateScale::build_record
00205 //       Access: Protected, Virtual
00206 //  Description: Fills up the current record on the FltRecordWriter with
00207 //               data for this record, but does not advance the
00208 //               writer.  Returns true on success, false if there is
00209 //               some error.
00210 ////////////////////////////////////////////////////////////////////
00211 bool FltTransformRotateScale::
00212 build_record(FltRecordWriter &writer) const {
00213   if (!FltTransformRecord::build_record(writer)) {
00214     return false;
00215   }
00216 
00217   writer.set_opcode(FO_put);
00218   Datagram &datagram = writer.update_datagram();
00219 
00220   datagram.pad_bytes(4);   // Undocumented additional padding.
00221 
00222   datagram.add_be_float64(_center[0]);
00223   datagram.add_be_float64(_center[1]);
00224   datagram.add_be_float64(_center[2]);
00225   datagram.add_be_float64(_reference_point[0]);
00226   datagram.add_be_float64(_reference_point[1]);
00227   datagram.add_be_float64(_reference_point[2]);
00228   datagram.add_be_float64(_to_point[0]);
00229   datagram.add_be_float64(_to_point[1]);
00230   datagram.add_be_float64(_to_point[2]);
00231   datagram.add_be_float32(_overall_scale);
00232   datagram.add_be_float32(_axis_scale);
00233   datagram.add_be_float32(_angle);
00234 
00235   datagram.pad_bytes(4);   // Undocumented additional padding.
00236 
00237   return true;
00238 }
00239 
 All Classes Functions Variables Enumerations