xref: /trunk/main/drawinglayer/source/geometry/viewinformation3d.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_drawinglayer.hxx"
30 
31 #include <drawinglayer/geometry/viewinformation3d.hxx>
32 #include <basegfx/range/b3drange.hxx>
33 #include <basegfx/matrix/b3dhommatrix.hxx>
34 #include <com/sun/star/geometry/AffineMatrix3D.hpp>
35 #include <com/sun/star/geometry/RealRectangle3D.hpp>
36 #include <basegfx/tools/canvastools.hxx>
37 
38 //////////////////////////////////////////////////////////////////////////////
39 
40 using namespace com::sun::star;
41 
42 //////////////////////////////////////////////////////////////////////////////
43 
44 namespace drawinglayer
45 {
46     namespace geometry
47     {
48         /** Implementation class for ViewInformation3D
49         */
50         class ImpViewInformation3D
51         {
52         private:
53             // ViewInformation3D implementation can change refcount, so we have only
54             // two memory regions for pairs of ViewInformation3D/ImpViewInformation3D
55             friend class ::drawinglayer::geometry::ViewInformation3D;
56 
57             // the refcounter. 0 means exclusively used
58             sal_uInt32                                  mnRefCount;
59 
60             // the 3D transformations
61             // Object to World. This may change and being adapted when entering 3D transformation
62             // groups
63             basegfx::B3DHomMatrix                       maObjectTransformation;
64 
65             // World to Camera. This includes VRP, VPN and VUV camera coordinate system
66             basegfx::B3DHomMatrix                       maOrientation;
67 
68             // Camera to Device with X,Y and Z [-1.0 .. 1.0]. This is the
69             // 3D to 2D projection which may be parallell or perspective. When it is perspective,
70             // the last line of the homogen matrix will NOT be unused
71             basegfx::B3DHomMatrix                       maProjection;
72 
73             // Device to View with X,Y and Z [0.0 .. 1.0]. This converts from -1 to 1 coordinates
74             // in camera coordinate system to 0 to 1 in unit 2D coordinates. This way it stays
75             // view-independent. To get discrete coordinates, the 2D transformation of a scene
76             // as 2D object needs to be involved
77             basegfx::B3DHomMatrix                       maDeviceToView;
78 
79             // Object to View is the linear combination of all four transformations. It's
80             // buffered to avoid too much matrix multiplying and created on demand
81             basegfx::B3DHomMatrix                       maObjectToView;
82 
83             // the point in time
84             double                                      mfViewTime;
85 
86             // the complete PropertyValue representation (if already created)
87             uno::Sequence< beans::PropertyValue >       mxViewInformation;
88 
89             // the extra PropertyValues; does not contain the transformations
90             uno::Sequence< beans::PropertyValue >       mxExtendedInformation;
91 
92             // the local UNO API strings
93             const ::rtl::OUString& getNamePropertyObjectTransformation()
94             {
95                 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("ObjectTransformation"));
96                 return s_sNameProperty;
97             }
98 
99             const ::rtl::OUString& getNamePropertyOrientation()
100             {
101                 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Orientation"));
102                 return s_sNameProperty;
103             }
104 
105             const ::rtl::OUString& getNamePropertyProjection()
106             {
107                 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection"));
108                 return s_sNameProperty;
109             }
110 
111             const ::rtl::OUString& getNamePropertyProjection_30()
112             {
113                 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection30"));
114                 return s_sNameProperty;
115             }
116 
117             const ::rtl::OUString& getNamePropertyProjection_31()
118             {
119                 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection31"));
120                 return s_sNameProperty;
121             }
122 
123             const ::rtl::OUString& getNamePropertyProjection_32()
124             {
125                 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection32"));
126                 return s_sNameProperty;
127             }
128 
129             const ::rtl::OUString& getNamePropertyProjection_33()
130             {
131                 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection33"));
132                 return s_sNameProperty;
133             }
134 
135             const ::rtl::OUString& getNamePropertyDeviceToView()
136             {
137                 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("DeviceToView"));
138                 return s_sNameProperty;
139             }
140 
141             const ::rtl::OUString& getNamePropertyTime()
142             {
143                 static ::rtl::OUString s_sNamePropertyTime(RTL_CONSTASCII_USTRINGPARAM("Time"));
144                 return s_sNamePropertyTime;
145             }
146 
147             // a central PropertyValue parsing method to allow transportatin of
148             // all ViewParameters using UNO API
149             void impInterpretPropertyValues(const uno::Sequence< beans::PropertyValue >& rViewParameters)
150             {
151                 if(rViewParameters.hasElements())
152                 {
153                     const sal_Int32 nCount(rViewParameters.getLength());
154                     sal_Int32 nExtendedInsert(0);
155 
156                     // prepare extended information for filtering. Maximum size is nCount
157                     mxExtendedInformation.realloc(nCount);
158 
159                     for(sal_Int32 a(0); a < nCount; a++)
160                     {
161                         const beans::PropertyValue& rProp = rViewParameters[a];
162 
163                         if(rProp.Name == getNamePropertyObjectTransformation())
164                         {
165                             com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D;
166                             rProp.Value >>= aAffineMatrix3D;
167                             maObjectTransformation = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D);
168                         }
169                         else if(rProp.Name == getNamePropertyOrientation())
170                         {
171                             com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D;
172                             rProp.Value >>= aAffineMatrix3D;
173                             maOrientation = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D);
174                         }
175                         else if(rProp.Name == getNamePropertyProjection())
176                         {
177                             // projection may be defined using a frustum in which case the last line of
178                             // the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that,
179                             // these four values need to be treated extra
180                             const double f_30(maProjection.get(3, 0));
181                             const double f_31(maProjection.get(3, 1));
182                             const double f_32(maProjection.get(3, 2));
183                             const double f_33(maProjection.get(3, 3));
184 
185                             com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D;
186                             rProp.Value >>= aAffineMatrix3D;
187                             maProjection = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D);
188 
189                             maProjection.set(3, 0, f_30);
190                             maProjection.set(3, 1, f_31);
191                             maProjection.set(3, 2, f_32);
192                             maProjection.set(3, 3, f_33);
193                         }
194                         else if(rProp.Name == getNamePropertyProjection_30())
195                         {
196                             double f_30(0.0);
197                             rProp.Value >>= f_30;
198                             maProjection.set(3, 0, f_30);
199                         }
200                         else if(rProp.Name == getNamePropertyProjection_31())
201                         {
202                             double f_31(0.0);
203                             rProp.Value >>= f_31;
204                             maProjection.set(3, 1, f_31);
205                         }
206                         else if(rProp.Name == getNamePropertyProjection_32())
207                         {
208                             double f_32(0.0);
209                             rProp.Value >>= f_32;
210                             maProjection.set(3, 2, f_32);
211                         }
212                         else if(rProp.Name == getNamePropertyProjection_33())
213                         {
214                             double f_33(1.0);
215                             rProp.Value >>= f_33;
216                             maProjection.set(3, 3, f_33);
217                         }
218                         else if(rProp.Name == getNamePropertyDeviceToView())
219                         {
220                             com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D;
221                             rProp.Value >>= aAffineMatrix3D;
222                             maDeviceToView = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D);
223                         }
224                         else if(rProp.Name == getNamePropertyTime())
225                         {
226                             rProp.Value >>= mfViewTime;
227                         }
228                         else
229                         {
230                             // extra information; add to filtered information
231                             mxExtendedInformation[nExtendedInsert++] = rProp;
232                         }
233                     }
234 
235                     // extra information size is now known; realloc to final size
236                     mxExtendedInformation.realloc(nExtendedInsert);
237                 }
238             }
239 
240             // central method to create a Sequence of PropertyValues containing he complete
241             // data set
242             void impFillViewInformationFromContent()
243             {
244                 uno::Sequence< beans::PropertyValue > xRetval;
245                 const bool bObjectTransformationUsed(!maObjectTransformation.isIdentity());
246                 const bool bOrientationUsed(!maOrientation.isIdentity());
247                 const bool bProjectionUsed(!maProjection.isIdentity());
248                 const bool bDeviceToViewUsed(!maDeviceToView.isIdentity());
249                 const bool bTimeUsed(0.0 < mfViewTime);
250                 const bool bExtraInformation(mxExtendedInformation.hasElements());
251 
252                 // projection may be defined using a frustum in which case the last line of
253                 // the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that,
254                 // these four values need to be treated extra
255                 const bool bProjectionUsed_30(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 0)));
256                 const bool bProjectionUsed_31(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 1)));
257                 const bool bProjectionUsed_32(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 2)));
258                 const bool bProjectionUsed_33(bProjectionUsed && !basegfx::fTools::equal(maProjection.get(3, 3), 1.0));
259 
260                 sal_uInt32 nIndex(0);
261                 const sal_uInt32 nCount(
262                     (bObjectTransformationUsed ? 1 : 0) +
263                     (bOrientationUsed ? 1 : 0) +
264                     (bProjectionUsed ? 1 : 0) +
265                     (bProjectionUsed_30 ? 1 : 0) +
266                     (bProjectionUsed_31 ? 1 : 0) +
267                     (bProjectionUsed_32 ? 1 : 0) +
268                     (bProjectionUsed_33 ? 1 : 0) +
269                     (bDeviceToViewUsed ? 1 : 0) +
270                     (bTimeUsed ? 1 : 0) +
271                     (bExtraInformation ? mxExtendedInformation.getLength() : 0));
272 
273                 mxViewInformation.realloc(nCount);
274 
275                 if(bObjectTransformationUsed)
276                 {
277                     com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D;
278                     basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maObjectTransformation);
279                     mxViewInformation[nIndex].Name = getNamePropertyObjectTransformation();
280                     mxViewInformation[nIndex].Value <<= aAffineMatrix3D;
281                     nIndex++;
282                 }
283 
284                 if(bOrientationUsed)
285                 {
286                     com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D;
287                     basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maOrientation);
288                     mxViewInformation[nIndex].Name = getNamePropertyOrientation();
289                     mxViewInformation[nIndex].Value <<= aAffineMatrix3D;
290                     nIndex++;
291                 }
292 
293                 if(bProjectionUsed)
294                 {
295                     com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D;
296                     basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maProjection);
297                     mxViewInformation[nIndex].Name = getNamePropertyProjection();
298                     mxViewInformation[nIndex].Value <<= aAffineMatrix3D;
299                     nIndex++;
300                 }
301 
302                 if(bProjectionUsed_30)
303                 {
304                     mxViewInformation[nIndex].Name = getNamePropertyProjection_30();
305                     mxViewInformation[nIndex].Value <<= maProjection.get(3, 0);
306                     nIndex++;
307                 }
308 
309                 if(bProjectionUsed_31)
310                 {
311                     mxViewInformation[nIndex].Name = getNamePropertyProjection_31();
312                     mxViewInformation[nIndex].Value <<= maProjection.get(3, 1);
313                     nIndex++;
314                 }
315 
316                 if(bProjectionUsed_32)
317                 {
318                     mxViewInformation[nIndex].Name = getNamePropertyProjection_32();
319                     mxViewInformation[nIndex].Value <<= maProjection.get(3, 2);
320                     nIndex++;
321                 }
322 
323                 if(bProjectionUsed_33)
324                 {
325                     mxViewInformation[nIndex].Name = getNamePropertyProjection_33();
326                     mxViewInformation[nIndex].Value <<= maProjection.get(3, 3);
327                     nIndex++;
328                 }
329 
330                 if(bDeviceToViewUsed)
331                 {
332                     com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D;
333                     basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maDeviceToView);
334                     mxViewInformation[nIndex].Name = getNamePropertyDeviceToView();
335                     mxViewInformation[nIndex].Value <<= aAffineMatrix3D;
336                     nIndex++;
337                 }
338 
339                 if(bTimeUsed)
340                 {
341                     mxViewInformation[nIndex].Name = getNamePropertyTime();
342                     mxViewInformation[nIndex].Value <<= mfViewTime;
343                     nIndex++;
344                 }
345 
346                 if(bExtraInformation)
347                 {
348                     const sal_Int32 nExtra(mxExtendedInformation.getLength());
349 
350                     for(sal_Int32 a(0); a < nExtra; a++)
351                     {
352                         mxViewInformation[nIndex++] = mxExtendedInformation[a];
353                     }
354                 }
355             }
356 
357         public:
358             ImpViewInformation3D(
359                 const basegfx::B3DHomMatrix& rObjectTransformation,
360                 const basegfx::B3DHomMatrix& rOrientation,
361                 const basegfx::B3DHomMatrix& rProjection,
362                 const basegfx::B3DHomMatrix& rDeviceToView,
363                 double fViewTime,
364                 const uno::Sequence< beans::PropertyValue >& rExtendedParameters)
365             :   mnRefCount(0),
366                 maObjectTransformation(rObjectTransformation),
367                 maOrientation(rOrientation),
368                 maProjection(rProjection),
369                 maDeviceToView(rDeviceToView),
370                 mfViewTime(fViewTime),
371                 mxViewInformation(),
372                 mxExtendedInformation()
373             {
374                 impInterpretPropertyValues(rExtendedParameters);
375             }
376 
377             ImpViewInformation3D(const uno::Sequence< beans::PropertyValue >& rViewParameters)
378             :   mnRefCount(0),
379                 maObjectTransformation(),
380                 maOrientation(),
381                 maProjection(),
382                 maDeviceToView(),
383                 mfViewTime(),
384                 mxViewInformation(rViewParameters),
385                 mxExtendedInformation()
386             {
387                 impInterpretPropertyValues(rViewParameters);
388             }
389 
390             ImpViewInformation3D()
391             :   mnRefCount(0),
392                 maObjectTransformation(),
393                 maOrientation(),
394                 maProjection(),
395                 maDeviceToView(),
396                 mfViewTime(),
397                 mxViewInformation(),
398                 mxExtendedInformation()
399             {
400             }
401 
402             const basegfx::B3DHomMatrix& getObjectTransformation() const { return maObjectTransformation; }
403             const basegfx::B3DHomMatrix& getOrientation() const { return maOrientation; }
404             const basegfx::B3DHomMatrix& getProjection() const { return maProjection; }
405             const basegfx::B3DHomMatrix& getDeviceToView() const { return maDeviceToView; }
406             double getViewTime() const { return mfViewTime; }
407 
408             const basegfx::B3DHomMatrix& getObjectToView() const
409             {
410                 // on demand WorldToView creation
411                 ::osl::Mutex m_mutex;
412 
413                 if(maObjectToView.isIdentity())
414                 {
415                     const_cast< ImpViewInformation3D* >(this)->maObjectToView = maDeviceToView * maProjection * maOrientation * maObjectTransformation;
416                 }
417 
418                 return maObjectToView;
419             }
420 
421             const uno::Sequence< beans::PropertyValue >& getViewInformationSequence() const
422             {
423                 ::osl::Mutex m_mutex;
424 
425                 if(!mxViewInformation.hasElements())
426                 {
427                     const_cast< ImpViewInformation3D* >(this)->impFillViewInformationFromContent();
428                 }
429 
430                 return mxViewInformation;
431             }
432 
433             const uno::Sequence< beans::PropertyValue >& getExtendedInformationSequence() const
434             {
435                 return mxExtendedInformation;
436             }
437 
438             bool operator==(const ImpViewInformation3D& rCandidate) const
439             {
440                 return (maObjectTransformation == rCandidate.maObjectTransformation
441                     && maOrientation == rCandidate.maOrientation
442                     && maProjection == rCandidate.maProjection
443                     && maDeviceToView == rCandidate.maDeviceToView
444                     && mfViewTime == rCandidate.mfViewTime
445                     && mxExtendedInformation == rCandidate.mxExtendedInformation);
446             }
447 
448             static ImpViewInformation3D* get_global_default()
449             {
450                 static ImpViewInformation3D* pDefault = 0;
451 
452                 if(!pDefault)
453                 {
454                     pDefault = new ImpViewInformation3D();
455 
456                     // never delete; start with RefCount 1, not 0
457                     pDefault->mnRefCount++;
458                 }
459 
460                 return pDefault;
461             }
462         };
463     } // end of anonymous namespace
464 } // end of namespace drawinglayer
465 
466 //////////////////////////////////////////////////////////////////////////////
467 
468 namespace drawinglayer
469 {
470     namespace geometry
471     {
472         ViewInformation3D::ViewInformation3D(
473             const basegfx::B3DHomMatrix& rObjectObjectTransformation,
474             const basegfx::B3DHomMatrix& rOrientation,
475             const basegfx::B3DHomMatrix& rProjection,
476             const basegfx::B3DHomMatrix& rDeviceToView,
477             double fViewTime,
478             const uno::Sequence< beans::PropertyValue >& rExtendedParameters)
479         :   mpViewInformation3D(new ImpViewInformation3D(
480                 rObjectObjectTransformation, rOrientation, rProjection,
481                 rDeviceToView, fViewTime, rExtendedParameters))
482         {
483         }
484 
485         ViewInformation3D::ViewInformation3D(const uno::Sequence< beans::PropertyValue >& rViewParameters)
486         :   mpViewInformation3D(new ImpViewInformation3D(rViewParameters))
487         {
488         }
489 
490         ViewInformation3D::ViewInformation3D()
491         :   mpViewInformation3D(ImpViewInformation3D::get_global_default())
492         {
493             mpViewInformation3D->mnRefCount++;
494         }
495 
496         ViewInformation3D::ViewInformation3D(const ViewInformation3D& rCandidate)
497         :   mpViewInformation3D(rCandidate.mpViewInformation3D)
498         {
499             ::osl::Mutex m_mutex;
500             mpViewInformation3D->mnRefCount++;
501         }
502 
503         ViewInformation3D::~ViewInformation3D()
504         {
505             ::osl::Mutex m_mutex;
506 
507             if(mpViewInformation3D->mnRefCount)
508             {
509                 mpViewInformation3D->mnRefCount--;
510             }
511             else
512             {
513                 delete mpViewInformation3D;
514             }
515         }
516 
517         bool ViewInformation3D::isDefault() const
518         {
519             return mpViewInformation3D == ImpViewInformation3D::get_global_default();
520         }
521 
522         ViewInformation3D& ViewInformation3D::operator=(const ViewInformation3D& rCandidate)
523         {
524             ::osl::Mutex m_mutex;
525 
526             if(mpViewInformation3D->mnRefCount)
527             {
528                 mpViewInformation3D->mnRefCount--;
529             }
530             else
531             {
532                 delete mpViewInformation3D;
533             }
534 
535             mpViewInformation3D = rCandidate.mpViewInformation3D;
536             mpViewInformation3D->mnRefCount++;
537 
538             return *this;
539         }
540 
541         bool ViewInformation3D::operator==(const ViewInformation3D& rCandidate) const
542         {
543             if(rCandidate.mpViewInformation3D == mpViewInformation3D)
544             {
545                 return true;
546             }
547 
548             if(rCandidate.isDefault() != isDefault())
549             {
550                 return false;
551             }
552 
553             return (*rCandidate.mpViewInformation3D == *mpViewInformation3D);
554         }
555 
556         const basegfx::B3DHomMatrix& ViewInformation3D::getObjectTransformation() const
557         {
558             return mpViewInformation3D->getObjectTransformation();
559         }
560 
561         const basegfx::B3DHomMatrix& ViewInformation3D::getOrientation() const
562         {
563             return mpViewInformation3D->getOrientation();
564         }
565 
566         const basegfx::B3DHomMatrix& ViewInformation3D::getProjection() const
567         {
568             return mpViewInformation3D->getProjection();
569         }
570 
571         const basegfx::B3DHomMatrix& ViewInformation3D::getDeviceToView() const
572         {
573             return mpViewInformation3D->getDeviceToView();
574         }
575 
576         const basegfx::B3DHomMatrix& ViewInformation3D::getObjectToView() const
577         {
578             return mpViewInformation3D->getObjectToView();
579         }
580 
581         double ViewInformation3D::getViewTime() const
582         {
583             return mpViewInformation3D->getViewTime();
584         }
585 
586         const uno::Sequence< beans::PropertyValue >& ViewInformation3D::getViewInformationSequence() const
587         {
588             return mpViewInformation3D->getViewInformationSequence();
589         }
590 
591         const uno::Sequence< beans::PropertyValue >& ViewInformation3D::getExtendedInformationSequence() const
592         {
593             return mpViewInformation3D->getExtendedInformationSequence();
594         }
595     } // end of namespace geometry
596 } // end of namespace drawinglayer
597 
598 //////////////////////////////////////////////////////////////////////////////
599 // eof
600