root/OpenSceneGraph/trunk/examples/osgunittests/UnitTests_osg.cpp @ 8868

Revision 8868, 9.2 kB (checked in by robert, 6 years ago)

From Mathias Froehlich, "This is a generic optimization that does not depend on any cpu or instruction
set.

The optimization is based on the observation that matrix matrix multiplication
with a dense matrix 4x4 is 43 Operations whereas multiplication with a
transform, or scale matrix is only 4
2 operations. Which is a gain of a
*FACTOR*4* for these special cases.
The change implements these special cases, provides a unit test for these
implementation and converts uses of the expensiver dense matrix matrix
routine with the specialized versions.

Depending on the transform nodes in the scenegraph this change gives a
noticable improovement.
For example the osgforest code using the MatrixTransform? is about 20% slower
than the same codepath using the PositionAttitudeTransform? instead of the
MatrixTransform? with this patch applied.

If I remember right, the sse type optimizations did *not* provide a factor 4
improovement. Also these changes are totally independent of any cpu or
instruction set architecture. So I would prefer to have this current kind of
change instead of some hand coded and cpu dependent assembly stuff. If we
need that hand tuned stuff, these can go on top of this changes which must
provide than hand optimized additional variants for the specialized versions
to give a even better result in the end.

An other change included here is a change to rotation matrix from quaterion
code. There is a sqrt call which couold be optimized away. Since we divide in
effect by sqrt(length)*sqrt(length) which is just length ...
"

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* OpenSceneGraph example, osgunittests.
2*
3*  Permission is hereby granted, free of charge, to any person obtaining a copy
4*  of this software and associated documentation files (the "Software"), to deal
5*  in the Software without restriction, including without limitation the rights
6*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7*  copies of the Software, and to permit persons to whom the Software is
8*  furnished to do so, subject to the following conditions:
9*
10*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16*  THE SOFTWARE.
17*/
18
19#include "UnitTestFramework.h"
20
21#include <osg/Matrixd>
22#include <osg/Matrixf>
23#include <osg/Vec3d>
24#include <osg/Vec3>
25#include <sstream>
26
27namespace osg
28{
29
30
31///////////////////////////////////////////////////////////////////////////////
32//
33//  Vec3 Tests
34//
35class Vec3TestFixture
36{
37public:
38
39    Vec3TestFixture();
40
41    void testAddition(const osgUtx::TestContext& ctx);
42    void testSubtraction(const osgUtx::TestContext& ctx);
43    void testScalarMultiplication(const osgUtx::TestContext& ctx);
44    void testDotProduct(const osgUtx::TestContext& ctx);
45
46private:
47
48    // Some convenience variables for use in the tests
49    Vec3 v1_, v2_, v3_;
50
51};
52
53Vec3TestFixture::Vec3TestFixture():
54    v1_(1.0f, 1.0f, 1.0f),
55    v2_(2.0f, 2.0f, 2.0f),
56    v3_(3.0f, 3.0f, 3.0f)
57{
58}
59
60void Vec3TestFixture::testAddition(const osgUtx::TestContext&)
61{
62    OSGUTX_TEST_F( v1_ + v2_ == v3_ )
63}
64
65void Vec3TestFixture::testSubtraction(const osgUtx::TestContext&)
66{
67    OSGUTX_TEST_F( v3_ - v1_ == v2_ )
68}
69
70void Vec3TestFixture::testScalarMultiplication(const osgUtx::TestContext&)
71{
72    OSGUTX_TEST_F( v1_ * 3 == v3_ )
73}
74
75void Vec3TestFixture::testDotProduct(const osgUtx::TestContext&)
76{
77   
78}
79
80OSGUTX_BEGIN_TESTSUITE(Vec3)
81    OSGUTX_ADD_TESTCASE(Vec3TestFixture, testAddition)
82    OSGUTX_ADD_TESTCASE(Vec3TestFixture, testSubtraction)
83    OSGUTX_ADD_TESTCASE(Vec3TestFixture, testScalarMultiplication)
84    OSGUTX_ADD_TESTCASE(Vec3TestFixture, testDotProduct)
85OSGUTX_END_TESTSUITE
86
87OSGUTX_AUTOREGISTER_TESTSUITE_AT(Vec3, root.osg)
88
89///////////////////////////////////////////////////////////////////////////////
90//
91//  Matrix Tests
92//
93class MatrixTestFixture
94{
95public:
96
97    MatrixTestFixture();
98
99    void testPreMultTranslate(const osgUtx::TestContext& ctx);
100    void testPostMultTranslate(const osgUtx::TestContext& ctx);
101    void testPreMultScale(const osgUtx::TestContext& ctx);
102    void testPostMultScale(const osgUtx::TestContext& ctx);
103    void testPreMultRotate(const osgUtx::TestContext& ctx);
104    void testPostMultRotate(const osgUtx::TestContext& ctx);
105
106private:
107
108    // Some convenience variables for use in the tests
109    Matrixd _md;
110    Matrixf _mf;
111    Vec3d _v3d;
112    Vec3 _v3;
113    Quat _q1;
114    Quat _q2;
115    Quat _q3;
116    Quat _q4;
117
118};
119
120MatrixTestFixture::MatrixTestFixture():
121    _md(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16),
122    _mf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16),
123    _v3d(1, 2, 3),
124    _v3(1, 2, 3),
125    _q1(1, 0, 0, 0),
126    _q2(0, 1, 0, 0),
127    _q3(0, 0, 1, 0),
128    _q4(0, 0, 0, 1)
129{
130}
131
132void MatrixTestFixture::testPreMultTranslate(const osgUtx::TestContext&)
133{
134    osg::Matrixd tdo;
135    osg::Matrixd tdn;
136    osg::Matrixf tfo;
137    osg::Matrixf tfn;
138
139    tdo = _md;
140    tdn = _md;
141    tdo.preMult(osg::Matrixd::translate(_v3d));
142    tdn.preMultTranslate(_v3d);
143    OSGUTX_TEST_F( tdo == tdn )
144
145    tdo = _md;
146    tdn = _md;
147    tdo.preMult(osg::Matrixd::translate(_v3));
148    tdn.preMultTranslate(_v3);
149    OSGUTX_TEST_F( tdo == tdn )
150
151    tfo = _mf;
152    tfn = _mf;
153    tfo.preMult(osg::Matrixf::translate(_v3d));
154    tfn.preMultTranslate(_v3d);
155    OSGUTX_TEST_F( tfo == tfn )
156
157    tfo = _mf;
158    tfn = _mf;
159    tfo.preMult(osg::Matrixf::translate(_v3));
160    tfn.preMultTranslate(_v3);
161    OSGUTX_TEST_F( tfo == tfn )
162}
163
164void MatrixTestFixture::testPostMultTranslate(const osgUtx::TestContext&)
165{
166    osg::Matrixd tdo;
167    osg::Matrixd tdn;
168    osg::Matrixf tfo;
169    osg::Matrixf tfn;
170
171    tdo = _md;
172    tdn = _md;
173    tdo.postMult(osg::Matrixd::translate(_v3d));
174    tdn.postMultTranslate(_v3d);
175    OSGUTX_TEST_F( tdo == tdn )
176
177    tdo = _md;
178    tdn = _md;
179    tdo.postMult(osg::Matrixd::translate(_v3));
180    tdn.postMultTranslate(_v3);
181    OSGUTX_TEST_F( tdo == tdn )
182
183    tfo = _mf;
184    tfn = _mf;
185    tfo.postMult(osg::Matrixf::translate(_v3d));
186    tfn.postMultTranslate(_v3d);
187    OSGUTX_TEST_F( tfo == tfn )
188
189    tfo = _mf;
190    tfn = _mf;
191    tfo.postMult(osg::Matrixf::translate(_v3));
192    tfn.postMultTranslate(_v3);
193    OSGUTX_TEST_F( tfo == tfn )
194}
195
196void MatrixTestFixture::testPreMultScale(const osgUtx::TestContext&)
197{
198    osg::Matrixd tdo;
199    osg::Matrixd tdn;
200    osg::Matrixf tfo;
201    osg::Matrixf tfn;
202
203    tdo = _md;
204    tdn = _md;
205    tdo.preMult(osg::Matrixd::scale(_v3d));
206    tdn.preMultScale(_v3d);
207    OSGUTX_TEST_F( tdo == tdn )
208
209    tdo = _md;
210    tdn = _md;
211    tdo.preMult(osg::Matrixd::scale(_v3));
212    tdn.preMultScale(_v3);
213    OSGUTX_TEST_F( tdo == tdn )
214
215    tfo = _mf;
216    tfn = _mf;
217    tfo.preMult(osg::Matrixf::scale(_v3d));
218    tfn.preMultScale(_v3d);
219    OSGUTX_TEST_F( tfo == tfn )
220
221    tfo = _mf;
222    tfn = _mf;
223    tfo.preMult(osg::Matrixf::scale(_v3));
224    tfn.preMultScale(_v3);
225    OSGUTX_TEST_F( tfo == tfn )
226}
227
228void MatrixTestFixture::testPostMultScale(const osgUtx::TestContext&)
229{
230    osg::Matrixd tdo;
231    osg::Matrixd tdn;
232    osg::Matrixf tfo;
233    osg::Matrixf tfn;
234
235    tdo = _md;
236    tdn = _md;
237    tdo.postMult(osg::Matrixd::scale(_v3d));
238    tdn.postMultScale(_v3d);
239    OSGUTX_TEST_F( tdo == tdn )
240
241    tdo = _md;
242    tdn = _md;
243    tdo.postMult(osg::Matrixd::scale(_v3));
244    tdn.postMultScale(_v3);
245    OSGUTX_TEST_F( tdo == tdn )
246
247    tfo = _mf;
248    tfn = _mf;
249    tfo.postMult(osg::Matrixf::scale(_v3d));
250    tfn.postMultScale(_v3d);
251    OSGUTX_TEST_F( tfo == tfn )
252
253    tfo = _mf;
254    tfn = _mf;
255    tfo.postMult(osg::Matrixf::scale(_v3));
256    tfn.postMultScale(_v3);
257    OSGUTX_TEST_F( tfo == tfn )
258}
259
260void MatrixTestFixture::testPreMultRotate(const osgUtx::TestContext&)
261{
262    osg::Matrixd tdo;
263    osg::Matrixd tdn;
264    osg::Matrixf tfo;
265    osg::Matrixf tfn;
266
267    tdo = _md;
268    tdn = _md;
269    tdo.preMult(osg::Matrixd::rotate(_q1));
270    tdn.preMultRotate(_q1);
271    OSGUTX_TEST_F( tdo == tdn )
272
273    tdo = _md;
274    tdn = _md;
275    tdo.preMult(osg::Matrixd::rotate(_q2));
276    tdn.preMultRotate(_q2);
277    OSGUTX_TEST_F( tdo == tdn )
278
279    tdo = _md;
280    tdn = _md;
281    tdo.preMult(osg::Matrixd::rotate(_q3));
282    tdn.preMultRotate(_q3);
283    OSGUTX_TEST_F( tdo == tdn )
284
285    tdo = _md;
286    tdn = _md;
287    tdo.preMult(osg::Matrixd::rotate(_q4));
288    tdn.preMultRotate(_q4);
289    OSGUTX_TEST_F( tdo == tdn )
290
291    tfo = _mf;
292    tfn = _mf;
293    tfo.preMult(osg::Matrixf::rotate(_q1));
294    tfn.preMultRotate(_q1);
295    OSGUTX_TEST_F( tfo == tfn )
296
297    tfo = _mf;
298    tfn = _mf;
299    tfo.preMult(osg::Matrixf::rotate(_q2));
300    tfn.preMultRotate(_q2);
301    OSGUTX_TEST_F( tfo == tfn )
302
303    tfo = _mf;
304    tfn = _mf;
305    tfo.preMult(osg::Matrixf::rotate(_q3));
306    tfn.preMultRotate(_q3);
307    OSGUTX_TEST_F( tfo == tfn )
308
309    tfo = _mf;
310    tfn = _mf;
311    tfo.preMult(osg::Matrixf::rotate(_q4));
312    tfn.preMultRotate(_q4);
313    OSGUTX_TEST_F( tfo == tfn )
314}
315
316void MatrixTestFixture::testPostMultRotate(const osgUtx::TestContext&)
317{
318    osg::Matrixd tdo;
319    osg::Matrixd tdn;
320    osg::Matrixf tfo;
321    osg::Matrixf tfn;
322
323    tdo = _md;
324    tdn = _md;
325    tdo.postMult(osg::Matrixd::rotate(_q1));
326    tdn.postMultRotate(_q1);
327    OSGUTX_TEST_F( tdo == tdn )
328
329    tdo = _md;
330    tdn = _md;
331    tdo.postMult(osg::Matrixd::rotate(_q2));
332    tdn.postMultRotate(_q2);
333    OSGUTX_TEST_F( tdo == tdn )
334
335    tdo = _md;
336    tdn = _md;
337    tdo.postMult(osg::Matrixd::rotate(_q3));
338    tdn.postMultRotate(_q3);
339    OSGUTX_TEST_F( tdo == tdn )
340
341    tdo = _md;
342    tdn = _md;
343    tdo.postMult(osg::Matrixd::rotate(_q4));
344    tdn.postMultRotate(_q4);
345    OSGUTX_TEST_F( tdo == tdn )
346
347    tfo = _mf;
348    tfn = _mf;
349    tfo.postMult(osg::Matrixf::rotate(_q1));
350    tfn.postMultRotate(_q1);
351    OSGUTX_TEST_F( tfo == tfn )
352
353    tfo = _mf;
354    tfn = _mf;
355    tfo.postMult(osg::Matrixf::rotate(_q2));
356    tfn.postMultRotate(_q2);
357    OSGUTX_TEST_F( tfo == tfn )
358
359    tfo = _mf;
360    tfn = _mf;
361    tfo.postMult(osg::Matrixf::rotate(_q3));
362    tfn.postMultRotate(_q3);
363    OSGUTX_TEST_F( tfo == tfn )
364
365    tfo = _mf;
366    tfn = _mf;
367    tfo.postMult(osg::Matrixf::rotate(_q4));
368    tfn.postMultRotate(_q4);
369    OSGUTX_TEST_F( tfo == tfn )
370}
371
372OSGUTX_BEGIN_TESTSUITE(Matrix)
373    OSGUTX_ADD_TESTCASE(MatrixTestFixture, testPreMultTranslate)
374    OSGUTX_ADD_TESTCASE(MatrixTestFixture, testPostMultTranslate)
375    OSGUTX_ADD_TESTCASE(MatrixTestFixture, testPreMultScale)
376    OSGUTX_ADD_TESTCASE(MatrixTestFixture, testPostMultScale)
377    OSGUTX_ADD_TESTCASE(MatrixTestFixture, testPreMultRotate)
378    OSGUTX_ADD_TESTCASE(MatrixTestFixture, testPostMultRotate)
379OSGUTX_END_TESTSUITE
380
381OSGUTX_AUTOREGISTER_TESTSUITE_AT(Matrix, root.osg)
382
383
384}
Note: See TracBrowser for help on using the browser.