Welcome to mirror list, hosted at ThFree Co, Russian Federation.

NodeTransform.cpp « scene_graph « intern « freestyle « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 31101e988e5f44de264bb15cef8c1f3c81df9686 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/* SPDX-License-Identifier: GPL-2.0-or-later */

/** \file
 * \ingroup freestyle
 * \brief Class to represent a transform node. A Transform node contains one or several children,
 * \brief all affected by the transformation.
 */

#include "NodeTransform.h"

#include "BLI_math.h"

namespace Freestyle {

void NodeTransform::Translate(real x, real y, real z)
{
  _Matrix(0, 3) += x;
  _Matrix(1, 3) += y;
  _Matrix(2, 3) += z;
}

void NodeTransform::Rotate(real iAngle, real x, real y, real z)
{
  // Normalize the x,y,z vector;
  real norm = (real)sqrt(x * x + y * y + z * z);
  if (0 == norm) {
    return;
  }

  x /= norm;
  y /= norm;
  z /= norm;

  /* find the corresponding matrix with the Rodrigues formula:
   * R = I + sin(iAngle)*Ntilda + (1-cos(iAngle))*Ntilda*Ntilda
   */
  Matrix33r Ntilda;
  Ntilda(0, 0) = Ntilda(1, 1) = Ntilda(2, 2) = 0.0f;
  Ntilda(0, 1) = -z;
  Ntilda(0, 2) = y;
  Ntilda(1, 0) = z;
  Ntilda(1, 2) = -x;
  Ntilda(2, 0) = -y;
  Ntilda(2, 1) = x;

  const Matrix33r Ntilda2(Ntilda * Ntilda);

  const real sinAngle = (real)sin((iAngle / 180.0f) * M_PI);
  const real cosAngle = (real)cos((iAngle / 180.0f) * M_PI);

  Matrix33r NS(Ntilda * sinAngle);
  Matrix33r NC(Ntilda2 * (1.0f - cosAngle));
  Matrix33r R;
  R = Matrix33r::identity();
  R += NS + NC;

  // R4 is the corresponding 4x4 matrix
  Matrix44r R4;
  R4 = Matrix44r::identity();

  for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
      R4(i, j) = R(i, j);
    }
  }

  // Finally, we multiply our current matrix by R4:
  Matrix44r mat_tmp(_Matrix);
  _Matrix = mat_tmp * R4;
}

void NodeTransform::Scale(real x, real y, real z)
{
  _Matrix(0, 0) *= x;
  _Matrix(1, 1) *= y;
  _Matrix(2, 2) *= z;

  _Scaled = true;
}

void NodeTransform::MultiplyMatrix(const Matrix44r &iMatrix)
{
  Matrix44r mat_tmp(_Matrix);
  _Matrix = mat_tmp * iMatrix;
}

void NodeTransform::setMatrix(const Matrix44r &iMatrix)
{
  _Matrix = iMatrix;
  if (isScaled(iMatrix)) {
    _Scaled = true;
  }
}

void NodeTransform::accept(SceneVisitor &v)
{
  v.visitNodeTransform(*this);

  v.visitNodeTransformBefore(*this);
  for (vector<Node *>::iterator node = _Children.begin(), end = _Children.end(); node != end;
       ++node) {
    (*node)->accept(v);
  }
  v.visitNodeTransformAfter(*this);
}

void NodeTransform::AddBBox(const BBox<Vec3r> &iBBox)
{
  Vec3r oldMin(iBBox.getMin());
  Vec3r oldMax(iBBox.getMax());

  // compute the 8 corners of the bbox
  HVec3r box[8];
  box[0] = HVec3r(iBBox.getMin());
  box[1] = HVec3r(oldMax[0], oldMin[1], oldMin[2]);
  box[2] = HVec3r(oldMax[0], oldMax[1], oldMin[2]);
  box[3] = HVec3r(oldMin[0], oldMax[1], oldMin[2]);
  box[4] = HVec3r(oldMin[0], oldMin[1], oldMax[2]);
  box[5] = HVec3r(oldMax[0], oldMin[1], oldMax[2]);
  box[6] = HVec3r(oldMax[0], oldMax[1], oldMax[2]);
  box[7] = HVec3r(oldMin[0], oldMax[1], oldMax[2]);

  // Computes the transform iBBox
  HVec3r tbox[8];
  unsigned int i;
  for (i = 0; i < 8; i++) {
    tbox[i] = _Matrix * box[i];
  }

  Vec3r newMin(tbox[0]);
  Vec3r newMax(tbox[0]);
  for (i = 0; i < 8; i++) {
    for (unsigned int j = 0; j < 3; j++) {
      if (newMin[j] > tbox[i][j]) {
        newMin[j] = tbox[i][j];
      }
      if (newMax[j] < tbox[i][j]) {
        newMax[j] = tbox[i][j];
      }
    }
  }

  BBox<Vec3r> transformBox(newMin, newMax);

  Node::AddBBox(transformBox);
}

bool NodeTransform::isScaled(const Matrix44r &M)
{
  for (unsigned int j = 0; j < 3; j++) {
    real norm = 0;
    for (unsigned int i = 0; i < 3; i++) {
      norm += M(i, j) * M(i, j);
    }
    if ((norm > 1.01) || (norm < 0.99)) {
      return true;
    }
  }

  return false;
}

} /* namespace Freestyle */