Panda3D
|
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 ¢er, 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