soc-2008-mxcurioni: first version of lib3ds code. It does NOT work yet and has to...
[blender.git] / source / blender / freestyle / intern / scene_graph / NodeTransform.cpp
1 //
2 //  Copyright (C) : Please refer to the COPYRIGHT file distributed 
3 //   with this source distribution. 
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License
7 //  as published by the Free Software Foundation; either version 2
8 //  of the License, or (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 //
19 ///////////////////////////////////////////////////////////////////////////////
20
21
22 #include "../system/FreestyleConfig.h"
23 #include "NodeTransform.h"
24
25 void NodeTransform::Translate(real x, real y, real z)
26 {
27   _Matrix(0, 3) += x;
28   _Matrix(1, 3) += y;
29   _Matrix(2, 3) += z;
30 }
31
32 void NodeTransform::Rotate(real iAngle, real x, real y, real z)
33 {
34   //Normalize the x,y,z vector;
35   real norm = (real)sqrt(x*x+y*y+z*z);
36   if(0 == norm)
37     return;
38
39   x /= norm;
40   y /= norm;
41   z /= norm;
42
43   // find the corresponding matrix with the Rodrigues formula:
44   // R = I + sin(iAngle)*Ntilda + (1-cos(iAngle))*Ntilda*Ntilda
45   Matrix33r Ntilda;
46   Ntilda(0,0) = Ntilda(1,1) = Ntilda(2,2) = 0.f;
47   Ntilda(0,1) = -z;
48   Ntilda(0,2) = y;
49   Ntilda(1,0) = z;
50   Ntilda(1,2) = -x;
51   Ntilda(2,0) = -y;
52   Ntilda(2,1) = x;
53
54   const Matrix33r Ntilda2(Ntilda * Ntilda);
55   
56
57   const real sinAngle = (real)sin((iAngle/180.f)*M_PI);
58   const real cosAngle = (real)cos((iAngle/180.f)*M_PI);
59   
60   Matrix33r NS(Ntilda*sinAngle);
61   Matrix33r NC(Ntilda2*(1.f-cosAngle));
62   Matrix33r R;
63   R = Matrix33r::identity();
64   R += NS + NC;
65   
66   //R4 is the corresponding 4x4 matrix
67   Matrix44r R4;
68   R4 = Matrix44r::identity();
69
70   for(int i=0; i<3; i++)
71     for(int j=0; j<3; j++)
72       R4(i,j) = R(i,j);
73     
74   // Finally, we multiply our current matrix by R4:
75   Matrix44r mat_tmp(_Matrix);
76   _Matrix = mat_tmp * R4;
77 }
78
79 void NodeTransform::Scale(real x, real y, real z)
80 {
81   _Matrix(0,0) *= x;
82   _Matrix(1,1) *= y;
83   _Matrix(2,2) *= z;
84
85   _Scaled = true;
86 }
87
88 void NodeTransform::MultiplyMatrix(const Matrix44r &iMatrix)
89 {
90   Matrix44r mat_tmp(_Matrix);
91   _Matrix = mat_tmp * iMatrix;
92 }
93
94 void NodeTransform::setMatrix(const Matrix44r &iMatrix)
95 {
96   _Matrix = iMatrix;
97   if(isScaled(iMatrix))
98     _Scaled = true;
99 }
100
101 void NodeTransform::accept(SceneVisitor& v) {
102   v.visitNodeTransform(*this);
103
104   v.visitNodeTransformBefore(*this);
105   for(vector<Node *>::iterator node=_Children.begin(), end=_Children.end(); 
106   node!=end; 
107   node++)
108     (*node)->accept(v);
109   v.visitNodeTransformAfter(*this);
110 }
111
112 void NodeTransform::AddBBox(const BBox<Vec3r>& iBBox)
113 {
114   Vec3r oldMin(iBBox.getMin());
115   Vec3r oldMax(iBBox.getMax());
116   
117   // compute the 8 corners of the bbox
118   HVec3r box[8];
119   box[0] = HVec3r(iBBox.getMin());
120   box[1] = HVec3r(oldMax[0], oldMin[1], oldMin[2]);
121   box[2] = HVec3r(oldMax[0], oldMax[1], oldMin[2]);
122   box[3] = HVec3r(oldMin[0], oldMax[1], oldMin[2]);
123   box[4] = HVec3r(oldMin[0], oldMin[1], oldMax[2]);
124   box[5] = HVec3r(oldMax[0], oldMin[1], oldMax[2]);
125   box[6] = HVec3r(oldMax[0], oldMax[1], oldMax[2]);
126   box[7] = HVec3r(oldMin[0], oldMax[1], oldMax[2]);
127
128   // Computes the transform iBBox
129   HVec3r tbox[8];
130   unsigned i;
131   for(i = 0; i < 8; i++)
132     tbox[i] = _Matrix * box[i];
133
134   Vec3r newMin(tbox[0]);
135   Vec3r newMax(tbox[0]);
136   for (i=0; i<8; i++)
137   {
138     for (unsigned int j=0; j<3; j++)
139     {
140       if (newMin[j] > tbox[i][j])
141         newMin[j] = tbox[i][j];
142       if (newMax[j] < tbox[i][j])
143         newMax[j] = tbox[i][j];
144     }
145   }
146   
147   BBox<Vec3r> transformBox(newMin, newMax);
148   
149   Node::AddBBox(transformBox);
150 }
151
152 bool NodeTransform::isScaled(const Matrix44r &M)
153 {
154   for(unsigned int j=0; j<3; j++)
155   {
156     real norm = 0;
157     for(unsigned int i=0; i<3; i++)
158     {
159       norm += M(i,j)*M(i,j);
160     }
161     if((norm > 1.01) || (norm < 0.99))
162       return true;
163   }
164
165   return false;
166 }