util_transform.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /*
  2. * Copyright 2011-2013 Blender Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * Adapted from code with license:
  18. *
  19. * Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
  20. * Digital Ltd. LLC. All rights reserved.
  21. *
  22. * Redistribution and use in source and binary forms, with or without
  23. * modification, are permitted provided that the following conditions are
  24. * met:
  25. * * Redistributions of source code must retain the above copyright
  26. * notice, this list of conditions and the following disclaimer.
  27. * * Redistributions in binary form must reproduce the above copyright
  28. * notice, this list of conditions and the following disclaimer in
  29. * the documentation and/or other materials provided with the
  30. * distribution.
  31. * * Neither the name of Industrial Light & Magic nor the names of its
  32. * contributors may be used to endorse or promote products derived
  33. * from this software without specific prior written permission.
  34. *
  35. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  36. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  37. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  38. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  39. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  42. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  43. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  44. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  45. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  46. */
  47. #include "util/util_projection.h"
  48. #include "util/util_transform.h"
  49. #include "util/util_boundbox.h"
  50. #include "util/util_math.h"
  51. CCL_NAMESPACE_BEGIN
  52. /* Transform Inverse */
  53. static bool transform_matrix4_gj_inverse(float R[][4], float M[][4])
  54. {
  55. /* forward elimination */
  56. for (int i = 0; i < 4; i++) {
  57. int pivot = i;
  58. float pivotsize = M[i][i];
  59. if (pivotsize < 0)
  60. pivotsize = -pivotsize;
  61. for (int j = i + 1; j < 4; j++) {
  62. float tmp = M[j][i];
  63. if (tmp < 0)
  64. tmp = -tmp;
  65. if (tmp > pivotsize) {
  66. pivot = j;
  67. pivotsize = tmp;
  68. }
  69. }
  70. if (UNLIKELY(pivotsize == 0.0f))
  71. return false;
  72. if (pivot != i) {
  73. for (int j = 0; j < 4; j++) {
  74. float tmp;
  75. tmp = M[i][j];
  76. M[i][j] = M[pivot][j];
  77. M[pivot][j] = tmp;
  78. tmp = R[i][j];
  79. R[i][j] = R[pivot][j];
  80. R[pivot][j] = tmp;
  81. }
  82. }
  83. for (int j = i + 1; j < 4; j++) {
  84. float f = M[j][i] / M[i][i];
  85. for (int k = 0; k < 4; k++) {
  86. M[j][k] -= f * M[i][k];
  87. R[j][k] -= f * R[i][k];
  88. }
  89. }
  90. }
  91. /* backward substitution */
  92. for (int i = 3; i >= 0; --i) {
  93. float f;
  94. if (UNLIKELY((f = M[i][i]) == 0.0f))
  95. return false;
  96. for (int j = 0; j < 4; j++) {
  97. M[i][j] /= f;
  98. R[i][j] /= f;
  99. }
  100. for (int j = 0; j < i; j++) {
  101. f = M[j][i];
  102. for (int k = 0; k < 4; k++) {
  103. M[j][k] -= f * M[i][k];
  104. R[j][k] -= f * R[i][k];
  105. }
  106. }
  107. }
  108. return true;
  109. }
  110. ProjectionTransform projection_inverse(const ProjectionTransform &tfm)
  111. {
  112. ProjectionTransform tfmR = projection_identity();
  113. float M[4][4], R[4][4];
  114. memcpy(R, &tfmR, sizeof(R));
  115. memcpy(M, &tfm, sizeof(M));
  116. if (UNLIKELY(!transform_matrix4_gj_inverse(R, M))) {
  117. /* matrix is degenerate (e.g. 0 scale on some axis), ideally we should
  118. * never be in this situation, but try to invert it anyway with tweak */
  119. M[0][0] += 1e-8f;
  120. M[1][1] += 1e-8f;
  121. M[2][2] += 1e-8f;
  122. if (UNLIKELY(!transform_matrix4_gj_inverse(R, M))) {
  123. return projection_identity();
  124. }
  125. }
  126. memcpy(&tfmR, R, sizeof(R));
  127. return tfmR;
  128. }
  129. Transform transform_inverse(const Transform &tfm)
  130. {
  131. ProjectionTransform projection(tfm);
  132. return projection_to_transform(projection_inverse(projection));
  133. }
  134. Transform transform_transposed_inverse(const Transform &tfm)
  135. {
  136. ProjectionTransform projection(tfm);
  137. ProjectionTransform iprojection = projection_inverse(projection);
  138. return projection_to_transform(projection_transpose(iprojection));
  139. }
  140. /* Motion Transform */
  141. float4 transform_to_quat(const Transform &tfm)
  142. {
  143. double trace = (double)(tfm[0][0] + tfm[1][1] + tfm[2][2]);
  144. float4 qt;
  145. if (trace > 0.0) {
  146. double s = sqrt(trace + 1.0);
  147. qt.w = (float)(s / 2.0);
  148. s = 0.5 / s;
  149. qt.x = (float)((double)(tfm[2][1] - tfm[1][2]) * s);
  150. qt.y = (float)((double)(tfm[0][2] - tfm[2][0]) * s);
  151. qt.z = (float)((double)(tfm[1][0] - tfm[0][1]) * s);
  152. }
  153. else {
  154. int i = 0;
  155. if (tfm[1][1] > tfm[i][i])
  156. i = 1;
  157. if (tfm[2][2] > tfm[i][i])
  158. i = 2;
  159. int j = (i + 1) % 3;
  160. int k = (j + 1) % 3;
  161. double s = sqrt((double)(tfm[i][i] - (tfm[j][j] + tfm[k][k])) + 1.0);
  162. double q[3];
  163. q[i] = s * 0.5;
  164. if (s != 0.0)
  165. s = 0.5 / s;
  166. double w = (double)(tfm[k][j] - tfm[j][k]) * s;
  167. q[j] = (double)(tfm[j][i] + tfm[i][j]) * s;
  168. q[k] = (double)(tfm[k][i] + tfm[i][k]) * s;
  169. qt.x = (float)q[0];
  170. qt.y = (float)q[1];
  171. qt.z = (float)q[2];
  172. qt.w = (float)w;
  173. }
  174. return qt;
  175. }
  176. static void transform_decompose(DecomposedTransform *decomp, const Transform *tfm)
  177. {
  178. /* extract translation */
  179. decomp->y = make_float4(tfm->x.w, tfm->y.w, tfm->z.w, 0.0f);
  180. /* extract rotation */
  181. Transform M = *tfm;
  182. M.x.w = 0.0f;
  183. M.y.w = 0.0f;
  184. M.z.w = 0.0f;
  185. Transform R = M;
  186. float norm;
  187. int iteration = 0;
  188. do {
  189. Transform Rnext;
  190. Transform Rit = transform_transposed_inverse(R);
  191. for (int i = 0; i < 3; i++)
  192. for (int j = 0; j < 4; j++)
  193. Rnext[i][j] = 0.5f * (R[i][j] + Rit[i][j]);
  194. norm = 0.0f;
  195. for (int i = 0; i < 3; i++) {
  196. norm = max(norm,
  197. fabsf(R[i][0] - Rnext[i][0]) + fabsf(R[i][1] - Rnext[i][1]) +
  198. fabsf(R[i][2] - Rnext[i][2]));
  199. }
  200. R = Rnext;
  201. iteration++;
  202. } while (iteration < 100 && norm > 1e-4f);
  203. if (transform_negative_scale(R))
  204. R = R * transform_scale(-1.0f, -1.0f, -1.0f);
  205. decomp->x = transform_to_quat(R);
  206. /* extract scale and pack it */
  207. Transform scale = transform_inverse(R) * M;
  208. decomp->y.w = scale.x.x;
  209. decomp->z = make_float4(scale.x.y, scale.x.z, scale.y.x, scale.y.y);
  210. decomp->w = make_float4(scale.y.z, scale.z.x, scale.z.y, scale.z.z);
  211. }
  212. void transform_motion_decompose(DecomposedTransform *decomp, const Transform *motion, size_t size)
  213. {
  214. for (size_t i = 0; i < size; i++) {
  215. transform_decompose(decomp + i, motion + i);
  216. if (i > 0) {
  217. /* Ensure rotation around shortest angle, negated quaternions are the same
  218. * but this means we don't have to do the check in quat_interpolate */
  219. if (dot(decomp[i - 1].x, decomp[i].x) < 0.0f)
  220. decomp[i - 1].x = -decomp[i - 1].x;
  221. }
  222. }
  223. }
  224. Transform transform_from_viewplane(BoundBox2D &viewplane)
  225. {
  226. return transform_scale(1.0f / (viewplane.right - viewplane.left),
  227. 1.0f / (viewplane.top - viewplane.bottom),
  228. 1.0f) *
  229. transform_translate(-viewplane.left, -viewplane.bottom, 0.0f);
  230. }
  231. CCL_NAMESPACE_END