]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/SGScaleTransform.cxx
Add preliminary spot light animation
[simgear.git] / simgear / scene / model / SGScaleTransform.cxx
1 /* -*-c++-*-
2  *
3  * Copyright (C) 2006-2007 Mathias Froehlich 
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 as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * 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., 51 Franklin Street, Fifth Floor, Boston,
18  * MA 02110-1301, USA.
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #  include <simgear_config.h>
24 #endif
25
26 #include <osgDB/Registry>
27 #include <osgDB/Input>
28 #include <osgDB/Output>
29
30 #include <simgear/scene/util/OsgMath.hxx>
31
32 #include "SGScaleTransform.hxx"
33
34 SGScaleTransform::SGScaleTransform() :
35   _center(0, 0, 0),
36   _scaleFactor(1, 1, 1),
37   _boundScale(1)
38 {
39   setReferenceFrame(RELATIVE_RF);
40   // see osg::Transform doc: If the transformation matrix scales the subgraph
41   // then the normals of the underlying geometry will need to be renormalized
42   // to be unit vectors once more.
43   osg::StateSet* stateset = getOrCreateStateSet();
44   stateset->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
45 }
46
47 SGScaleTransform::SGScaleTransform(const SGScaleTransform& scale,
48                                    const osg::CopyOp& copyop) :
49     osg::Transform(scale, copyop),
50     _center(scale._center),
51     _scaleFactor(scale._scaleFactor),
52     _boundScale(scale._boundScale)
53 {
54 }
55
56 bool
57 SGScaleTransform::computeLocalToWorldMatrix(osg::Matrix& matrix,
58                                             osg::NodeVisitor* nv) const
59 {
60   osg::Matrix transform;
61   transform(0,0) = _scaleFactor[0];
62   transform(1,1) = _scaleFactor[1];
63   transform(2,2) = _scaleFactor[2];
64   transform(3,0) = _center[0]*(1 - _scaleFactor[0]);
65   transform(3,1) = _center[1]*(1 - _scaleFactor[1]);
66   transform(3,2) = _center[2]*(1 - _scaleFactor[2]);
67   if (_referenceFrame == RELATIVE_RF)
68     matrix.preMult(transform);
69   else
70     matrix = transform;
71   return true;
72 }
73
74 bool
75 SGScaleTransform::computeWorldToLocalMatrix(osg::Matrix& matrix,
76                                             osg::NodeVisitor* nv) const
77 {
78   if (fabs(_scaleFactor[0]) < SGLimitsd::min())
79     return false;
80   if (fabs(_scaleFactor[1]) < SGLimitsd::min())
81     return false;
82   if (fabs(_scaleFactor[2]) < SGLimitsd::min())
83     return false;
84   SGVec3d rScaleFactor(1/_scaleFactor[0],
85                        1/_scaleFactor[1],
86                        1/_scaleFactor[2]);
87   osg::Matrix transform;
88   transform(0,0) = rScaleFactor[0];
89   transform(1,1) = rScaleFactor[1];
90   transform(2,2) = rScaleFactor[2];
91   transform(3,0) = _center[0]*(1 - rScaleFactor[0]);
92   transform(3,1) = _center[1]*(1 - rScaleFactor[1]);
93   transform(3,2) = _center[2]*(1 - rScaleFactor[2]);
94   if (_referenceFrame == RELATIVE_RF)
95     matrix.postMult(transform);
96   else
97     matrix = transform;
98   return true;
99 }
100
101 osg::BoundingSphere
102 SGScaleTransform::computeBound() const
103 {
104   osg::BoundingSphere bs = osg::Group::computeBound();
105   _boundScale = normI(_scaleFactor);
106   bs.radius() *= _boundScale;
107   return bs;
108 }
109
110 namespace {
111
112 bool ScaleTransform_readLocalData(osg::Object& obj, osgDB::Input& fr)
113 {
114     SGScaleTransform& scale = static_cast<SGScaleTransform&>(obj);
115     if (fr[0].matchWord("center")) {
116         ++fr;
117         osg::Vec3d center;
118         if (fr.readSequence(center))
119             fr += 3;
120         else
121             return false;
122         scale.setCenter(toSG(center));
123     }
124     if (fr[0].matchWord("scaleFactor")) {
125         ++fr;
126         osg::Vec3d scaleFactor;
127         if (fr.readSequence(scaleFactor))
128             fr += 3;
129         else
130             return false;
131         scale.setScaleFactor(toSG(scaleFactor));
132     }
133     return true;
134 }
135
136 bool ScaleTransform_writeLocalData(const osg::Object& obj, osgDB::Output& fw)
137 {
138     const SGScaleTransform& scale = static_cast<const SGScaleTransform&>(obj);
139     const SGVec3d& center = scale.getCenter();
140     const SGVec3d& scaleFactor = scale.getScaleFactor();
141     int prec = fw.precision();
142     fw.precision(15);
143     fw.indent() << "center ";
144     for (int i = 0; i < 3; i++)
145         fw << center(i) << " ";
146     fw << std::endl;
147     fw.precision(prec);
148     fw.indent() << "scaleFactor ";
149     for (int i = 0; i < 3; i++)
150         fw << scaleFactor(i) << " ";
151     fw << std::endl;
152     return true;
153 }
154
155 }
156
157 osgDB::RegisterDotOsgWrapperProxy g_ScaleTransformProxy
158 (
159     new SGScaleTransform,
160     "SGScaleTransform",
161     "Object Node Transform SGScaleTransform Group",
162     &ScaleTransform_readLocalData,
163     &ScaleTransform_writeLocalData
164 );