fltTransformRotateScale.cxx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /**
  2. * PANDA 3D SOFTWARE
  3. * Copyright (c) Carnegie Mellon University. All rights reserved.
  4. *
  5. * All use of this software is subject to the terms of the revised BSD
  6. * license. You should have received a copy of this license along
  7. * with this source code in a file named "LICENSE."
  8. *
  9. * @file fltTransformRotateScale.cxx
  10. * @author drose
  11. * @date 2000-08-30
  12. */
  13. #include "fltTransformRotateScale.h"
  14. #include "fltRecordReader.h"
  15. #include "fltRecordWriter.h"
  16. #include "mathNumbers.h"
  17. #include "look_at.h"
  18. TypeHandle FltTransformRotateScale::_type_handle;
  19. /**
  20. *
  21. */
  22. FltTransformRotateScale::
  23. FltTransformRotateScale(FltHeader *header) : FltTransformRecord(header) {
  24. _center.set(0.0, 0.0, 0.0);
  25. _reference_point.set(0.0, 0.0, 0.0);
  26. _to_point.set(0.0, 0.0, 0.0);
  27. _overall_scale = 1.0;
  28. _axis_scale = 1.0;
  29. _angle = 0.0;
  30. }
  31. /**
  32. * Defines the transform explicitly. The angle of rotation is determined by
  33. * the angle between the reference point and the to point (relative to the
  34. * center), and the scale factor is determined by the distance between the
  35. * reference point and the center point. If axis_scale is true, the scale is
  36. * along reference point axis only; otherwise, it is a uniform scale.
  37. */
  38. void FltTransformRotateScale::
  39. set(const LPoint3d &center, const LPoint3d &reference_point,
  40. const LPoint3d &to_point, bool axis_scale) {
  41. _center = center;
  42. _reference_point = reference_point;
  43. _to_point = to_point;
  44. LVector3d v1 = _reference_point - _center;
  45. LVector3d v2 = _to_point - _center;
  46. _angle =
  47. acos(dot(normalize(v1), normalize(v2))) * 180.0 / MathNumbers::pi;
  48. if (axis_scale) {
  49. _axis_scale = length(v1);
  50. _overall_scale = 1.0;
  51. } else {
  52. _overall_scale = length(v1);
  53. _axis_scale = 1.0;
  54. }
  55. recompute_matrix();
  56. }
  57. /**
  58. *
  59. */
  60. const LPoint3d &FltTransformRotateScale::
  61. get_center() const {
  62. return _center;
  63. }
  64. /**
  65. *
  66. */
  67. const LPoint3d &FltTransformRotateScale::
  68. get_reference_point() const {
  69. return _reference_point;
  70. }
  71. /**
  72. *
  73. */
  74. const LPoint3d &FltTransformRotateScale::
  75. get_to_point() const {
  76. return _to_point;
  77. }
  78. /**
  79. * Returns the overall scale factor.
  80. */
  81. PN_stdfloat FltTransformRotateScale::
  82. get_overall_scale() const {
  83. return _overall_scale;
  84. }
  85. /**
  86. * Returns the scale factor in the direction of the axis.
  87. */
  88. PN_stdfloat FltTransformRotateScale::
  89. get_axis_scale() const {
  90. return _axis_scale;
  91. }
  92. /**
  93. * Returns the angle of rotation in degrees.
  94. */
  95. PN_stdfloat FltTransformRotateScale::
  96. get_angle() const {
  97. return _angle;
  98. }
  99. /**
  100. *
  101. */
  102. void FltTransformRotateScale::
  103. recompute_matrix() {
  104. LVector3d v1 = _reference_point - _center;
  105. LVector3d v2 = _to_point - _center;
  106. LVector3d rotate_axis = normalize(cross(v1, v2));
  107. // To scale along an axis, we have to do a bit of work. First determine the
  108. // matrices to rotate and unrotate the rotate axis to the y-forward axis.
  109. LMatrix4d r1;
  110. look_at(r1, v1, rotate_axis, CS_zup_right);
  111. _matrix =
  112. LMatrix4d::translate_mat(-_center) *
  113. r1 *
  114. LMatrix4d::scale_mat(1.0, _axis_scale, 1.0) *
  115. LMatrix4d::scale_mat(_overall_scale) *
  116. invert(r1) *
  117. LMatrix4d::rotate_mat(_angle, rotate_axis, CS_zup_right) *
  118. LMatrix4d::translate_mat(_center);
  119. }
  120. /**
  121. * Fills in the information in this record based on the information given in
  122. * the indicated datagram, whose opcode has already been read. Returns true
  123. * on success, false if the datagram is invalid.
  124. */
  125. bool FltTransformRotateScale::
  126. extract_record(FltRecordReader &reader) {
  127. if (!FltTransformRecord::extract_record(reader)) {
  128. return false;
  129. }
  130. nassertr(reader.get_opcode() == FO_rotate_and_scale, false);
  131. DatagramIterator &iterator = reader.get_iterator();
  132. iterator.skip_bytes(4); // Undocumented additional padding.
  133. _center[0] = iterator.get_be_float64();
  134. _center[1] = iterator.get_be_float64();
  135. _center[2] = iterator.get_be_float64();
  136. _reference_point[0] = iterator.get_be_float64();
  137. _reference_point[1] = iterator.get_be_float64();
  138. _reference_point[2] = iterator.get_be_float64();
  139. _to_point[0] = iterator.get_be_float64();
  140. _to_point[1] = iterator.get_be_float64();
  141. _to_point[2] = iterator.get_be_float64();
  142. _overall_scale = iterator.get_be_float32();
  143. _axis_scale = iterator.get_be_float32();
  144. _angle = iterator.get_be_float32();
  145. iterator.skip_bytes(4); // Undocumented additional padding.
  146. recompute_matrix();
  147. check_remaining_size(iterator);
  148. return true;
  149. }
  150. /**
  151. * Fills up the current record on the FltRecordWriter with data for this
  152. * record, but does not advance the writer. Returns true on success, false if
  153. * there is some error.
  154. */
  155. bool FltTransformRotateScale::
  156. build_record(FltRecordWriter &writer) const {
  157. if (!FltTransformRecord::build_record(writer)) {
  158. return false;
  159. }
  160. writer.set_opcode(FO_put);
  161. Datagram &datagram = writer.update_datagram();
  162. datagram.pad_bytes(4); // Undocumented additional padding.
  163. datagram.add_be_float64(_center[0]);
  164. datagram.add_be_float64(_center[1]);
  165. datagram.add_be_float64(_center[2]);
  166. datagram.add_be_float64(_reference_point[0]);
  167. datagram.add_be_float64(_reference_point[1]);
  168. datagram.add_be_float64(_reference_point[2]);
  169. datagram.add_be_float64(_to_point[0]);
  170. datagram.add_be_float64(_to_point[1]);
  171. datagram.add_be_float64(_to_point[2]);
  172. datagram.add_be_float32(_overall_scale);
  173. datagram.add_be_float32(_axis_scale);
  174. datagram.add_be_float32(_angle);
  175. datagram.pad_bytes(4); // Undocumented additional padding.
  176. return true;
  177. }