1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <drawinglayer/geometry/viewinformation3d.hxx>
30 #include <basegfx/range/b3drange.hxx>
31 #include <basegfx/matrix/b3dhommatrix.hxx>
32 #include <com/sun/star/geometry/AffineMatrix3D.hpp>
33 #include <com/sun/star/geometry/RealRectangle3D.hpp>
34 #include <basegfx/tools/canvastools.hxx>
36 //////////////////////////////////////////////////////////////////////////////
38 using namespace com::sun::star
;
40 //////////////////////////////////////////////////////////////////////////////
42 namespace drawinglayer
46 /** Implementation class for ViewInformation3D
48 class ImpViewInformation3D
51 // ViewInformation3D implementation can change refcount, so we have only
52 // two memory regions for pairs of ViewInformation3D/ImpViewInformation3D
53 friend class ::drawinglayer::geometry::ViewInformation3D
;
55 // the refcounter. 0 means exclusively used
56 sal_uInt32 mnRefCount
;
58 // the 3D transformations
59 // Object to World. This may change and being adapted when entering 3D transformation
61 basegfx::B3DHomMatrix maObjectTransformation
;
63 // World to Camera. This includes VRP, VPN and VUV camera coordinate system
64 basegfx::B3DHomMatrix maOrientation
;
66 // Camera to Device with X,Y and Z [-1.0 .. 1.0]. This is the
67 // 3D to 2D projection which may be parallell or perspective. When it is perspective,
68 // the last line of the homogen matrix will NOT be unused
69 basegfx::B3DHomMatrix maProjection
;
71 // Device to View with X,Y and Z [0.0 .. 1.0]. This converts from -1 to 1 coordinates
72 // in camera coordinate system to 0 to 1 in unit 2D coordinates. This way it stays
73 // view-independent. To get discrete coordinates, the 2D transformation of a scene
74 // as 2D object needs to be involved
75 basegfx::B3DHomMatrix maDeviceToView
;
77 // Object to View is the linear combination of all four transformations. It's
78 // buffered to avoid too much matrix multiplying and created on demand
79 basegfx::B3DHomMatrix maObjectToView
;
84 // the complete PropertyValue representation (if already created)
85 uno::Sequence
< beans::PropertyValue
> mxViewInformation
;
87 // the extra PropertyValues; does not contain the transformations
88 uno::Sequence
< beans::PropertyValue
> mxExtendedInformation
;
90 // the local UNO API strings
91 const ::rtl::OUString
& getNamePropertyObjectTransformation()
93 static ::rtl::OUString
s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("ObjectTransformation"));
94 return s_sNameProperty
;
97 const ::rtl::OUString
& getNamePropertyOrientation()
99 static ::rtl::OUString
s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Orientation"));
100 return s_sNameProperty
;
103 const ::rtl::OUString
& getNamePropertyProjection()
105 static ::rtl::OUString
s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection"));
106 return s_sNameProperty
;
109 const ::rtl::OUString
& getNamePropertyProjection_30()
111 static ::rtl::OUString
s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection30"));
112 return s_sNameProperty
;
115 const ::rtl::OUString
& getNamePropertyProjection_31()
117 static ::rtl::OUString
s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection31"));
118 return s_sNameProperty
;
121 const ::rtl::OUString
& getNamePropertyProjection_32()
123 static ::rtl::OUString
s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection32"));
124 return s_sNameProperty
;
127 const ::rtl::OUString
& getNamePropertyProjection_33()
129 static ::rtl::OUString
s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection33"));
130 return s_sNameProperty
;
133 const ::rtl::OUString
& getNamePropertyDeviceToView()
135 static ::rtl::OUString
s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("DeviceToView"));
136 return s_sNameProperty
;
139 const ::rtl::OUString
& getNamePropertyTime()
141 static ::rtl::OUString
s_sNamePropertyTime(RTL_CONSTASCII_USTRINGPARAM("Time"));
142 return s_sNamePropertyTime
;
145 // a central PropertyValue parsing method to allow transportatin of
146 // all ViewParameters using UNO API
147 void impInterpretPropertyValues(const uno::Sequence
< beans::PropertyValue
>& rViewParameters
)
149 if(rViewParameters
.hasElements())
151 const sal_Int32
nCount(rViewParameters
.getLength());
152 sal_Int32
nExtendedInsert(0);
154 // prepare extended information for filtering. Maximum size is nCount
155 mxExtendedInformation
.realloc(nCount
);
157 for(sal_Int32
a(0); a
< nCount
; a
++)
159 const beans::PropertyValue
& rProp
= rViewParameters
[a
];
161 if(rProp
.Name
== getNamePropertyObjectTransformation())
163 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D
;
164 rProp
.Value
>>= aAffineMatrix3D
;
165 maObjectTransformation
= basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D
);
167 else if(rProp
.Name
== getNamePropertyOrientation())
169 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D
;
170 rProp
.Value
>>= aAffineMatrix3D
;
171 maOrientation
= basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D
);
173 else if(rProp
.Name
== getNamePropertyProjection())
175 // projection may be defined using a frustum in which case the last line of
176 // the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that,
177 // these four values need to be treated extra
178 const double f_30(maProjection
.get(3, 0));
179 const double f_31(maProjection
.get(3, 1));
180 const double f_32(maProjection
.get(3, 2));
181 const double f_33(maProjection
.get(3, 3));
183 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D
;
184 rProp
.Value
>>= aAffineMatrix3D
;
185 maProjection
= basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D
);
187 maProjection
.set(3, 0, f_30
);
188 maProjection
.set(3, 1, f_31
);
189 maProjection
.set(3, 2, f_32
);
190 maProjection
.set(3, 3, f_33
);
192 else if(rProp
.Name
== getNamePropertyProjection_30())
195 rProp
.Value
>>= f_30
;
196 maProjection
.set(3, 0, f_30
);
198 else if(rProp
.Name
== getNamePropertyProjection_31())
201 rProp
.Value
>>= f_31
;
202 maProjection
.set(3, 1, f_31
);
204 else if(rProp
.Name
== getNamePropertyProjection_32())
207 rProp
.Value
>>= f_32
;
208 maProjection
.set(3, 2, f_32
);
210 else if(rProp
.Name
== getNamePropertyProjection_33())
213 rProp
.Value
>>= f_33
;
214 maProjection
.set(3, 3, f_33
);
216 else if(rProp
.Name
== getNamePropertyDeviceToView())
218 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D
;
219 rProp
.Value
>>= aAffineMatrix3D
;
220 maDeviceToView
= basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D
);
222 else if(rProp
.Name
== getNamePropertyTime())
224 rProp
.Value
>>= mfViewTime
;
228 // extra information; add to filtered information
229 mxExtendedInformation
[nExtendedInsert
++] = rProp
;
233 // extra information size is now known; realloc to final size
234 mxExtendedInformation
.realloc(nExtendedInsert
);
238 // central method to create a Sequence of PropertyValues containing he complete
240 void impFillViewInformationFromContent()
242 uno::Sequence
< beans::PropertyValue
> xRetval
;
243 const bool bObjectTransformationUsed(!maObjectTransformation
.isIdentity());
244 const bool bOrientationUsed(!maOrientation
.isIdentity());
245 const bool bProjectionUsed(!maProjection
.isIdentity());
246 const bool bDeviceToViewUsed(!maDeviceToView
.isIdentity());
247 const bool bTimeUsed(0.0 < mfViewTime
);
248 const bool bExtraInformation(mxExtendedInformation
.hasElements());
250 // projection may be defined using a frustum in which case the last line of
251 // the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that,
252 // these four values need to be treated extra
253 const bool bProjectionUsed_30(bProjectionUsed
&& !basegfx::fTools::equalZero(maProjection
.get(3, 0)));
254 const bool bProjectionUsed_31(bProjectionUsed
&& !basegfx::fTools::equalZero(maProjection
.get(3, 1)));
255 const bool bProjectionUsed_32(bProjectionUsed
&& !basegfx::fTools::equalZero(maProjection
.get(3, 2)));
256 const bool bProjectionUsed_33(bProjectionUsed
&& !basegfx::fTools::equal(maProjection
.get(3, 3), 1.0));
258 sal_uInt32
nIndex(0);
259 const sal_uInt32
nCount(
260 (bObjectTransformationUsed
? 1 : 0) +
261 (bOrientationUsed
? 1 : 0) +
262 (bProjectionUsed
? 1 : 0) +
263 (bProjectionUsed_30
? 1 : 0) +
264 (bProjectionUsed_31
? 1 : 0) +
265 (bProjectionUsed_32
? 1 : 0) +
266 (bProjectionUsed_33
? 1 : 0) +
267 (bDeviceToViewUsed
? 1 : 0) +
268 (bTimeUsed
? 1 : 0) +
269 (bExtraInformation
? mxExtendedInformation
.getLength() : 0));
271 mxViewInformation
.realloc(nCount
);
273 if(bObjectTransformationUsed
)
275 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D
;
276 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D
, maObjectTransformation
);
277 mxViewInformation
[nIndex
].Name
= getNamePropertyObjectTransformation();
278 mxViewInformation
[nIndex
].Value
<<= aAffineMatrix3D
;
284 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D
;
285 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D
, maOrientation
);
286 mxViewInformation
[nIndex
].Name
= getNamePropertyOrientation();
287 mxViewInformation
[nIndex
].Value
<<= aAffineMatrix3D
;
293 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D
;
294 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D
, maProjection
);
295 mxViewInformation
[nIndex
].Name
= getNamePropertyProjection();
296 mxViewInformation
[nIndex
].Value
<<= aAffineMatrix3D
;
300 if(bProjectionUsed_30
)
302 mxViewInformation
[nIndex
].Name
= getNamePropertyProjection_30();
303 mxViewInformation
[nIndex
].Value
<<= maProjection
.get(3, 0);
307 if(bProjectionUsed_31
)
309 mxViewInformation
[nIndex
].Name
= getNamePropertyProjection_31();
310 mxViewInformation
[nIndex
].Value
<<= maProjection
.get(3, 1);
314 if(bProjectionUsed_32
)
316 mxViewInformation
[nIndex
].Name
= getNamePropertyProjection_32();
317 mxViewInformation
[nIndex
].Value
<<= maProjection
.get(3, 2);
321 if(bProjectionUsed_33
)
323 mxViewInformation
[nIndex
].Name
= getNamePropertyProjection_33();
324 mxViewInformation
[nIndex
].Value
<<= maProjection
.get(3, 3);
328 if(bDeviceToViewUsed
)
330 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D
;
331 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D
, maDeviceToView
);
332 mxViewInformation
[nIndex
].Name
= getNamePropertyDeviceToView();
333 mxViewInformation
[nIndex
].Value
<<= aAffineMatrix3D
;
339 mxViewInformation
[nIndex
].Name
= getNamePropertyTime();
340 mxViewInformation
[nIndex
].Value
<<= mfViewTime
;
344 if(bExtraInformation
)
346 const sal_Int32
nExtra(mxExtendedInformation
.getLength());
348 for(sal_Int32
a(0); a
< nExtra
; a
++)
350 mxViewInformation
[nIndex
++] = mxExtendedInformation
[a
];
356 ImpViewInformation3D(
357 const basegfx::B3DHomMatrix
& rObjectTransformation
,
358 const basegfx::B3DHomMatrix
& rOrientation
,
359 const basegfx::B3DHomMatrix
& rProjection
,
360 const basegfx::B3DHomMatrix
& rDeviceToView
,
362 const uno::Sequence
< beans::PropertyValue
>& rExtendedParameters
)
364 maObjectTransformation(rObjectTransformation
),
365 maOrientation(rOrientation
),
366 maProjection(rProjection
),
367 maDeviceToView(rDeviceToView
),
368 mfViewTime(fViewTime
),
370 mxExtendedInformation()
372 impInterpretPropertyValues(rExtendedParameters
);
375 ImpViewInformation3D(const uno::Sequence
< beans::PropertyValue
>& rViewParameters
)
377 maObjectTransformation(),
382 mxViewInformation(rViewParameters
),
383 mxExtendedInformation()
385 impInterpretPropertyValues(rViewParameters
);
388 ImpViewInformation3D()
390 maObjectTransformation(),
396 mxExtendedInformation()
400 const basegfx::B3DHomMatrix
& getObjectTransformation() const { return maObjectTransformation
; }
401 const basegfx::B3DHomMatrix
& getOrientation() const { return maOrientation
; }
402 const basegfx::B3DHomMatrix
& getProjection() const { return maProjection
; }
403 const basegfx::B3DHomMatrix
& getDeviceToView() const { return maDeviceToView
; }
404 double getViewTime() const { return mfViewTime
; }
406 const basegfx::B3DHomMatrix
& getObjectToView() const
408 // on demand WorldToView creation
409 ::osl::Mutex m_mutex
;
411 if(maObjectToView
.isIdentity())
413 const_cast< ImpViewInformation3D
* >(this)->maObjectToView
= maDeviceToView
* maProjection
* maOrientation
* maObjectTransformation
;
416 return maObjectToView
;
419 const uno::Sequence
< beans::PropertyValue
>& getViewInformationSequence() const
421 ::osl::Mutex m_mutex
;
423 if(!mxViewInformation
.hasElements())
425 const_cast< ImpViewInformation3D
* >(this)->impFillViewInformationFromContent();
428 return mxViewInformation
;
431 const uno::Sequence
< beans::PropertyValue
>& getExtendedInformationSequence() const
433 return mxExtendedInformation
;
436 bool operator==(const ImpViewInformation3D
& rCandidate
) const
438 return (maObjectTransformation
== rCandidate
.maObjectTransformation
439 && maOrientation
== rCandidate
.maOrientation
440 && maProjection
== rCandidate
.maProjection
441 && maDeviceToView
== rCandidate
.maDeviceToView
442 && mfViewTime
== rCandidate
.mfViewTime
443 && mxExtendedInformation
== rCandidate
.mxExtendedInformation
);
446 static ImpViewInformation3D
* get_global_default()
448 static ImpViewInformation3D
* pDefault
= 0;
452 pDefault
= new ImpViewInformation3D();
454 // never delete; start with RefCount 1, not 0
455 pDefault
->mnRefCount
++;
461 } // end of anonymous namespace
462 } // end of namespace drawinglayer
464 //////////////////////////////////////////////////////////////////////////////
466 namespace drawinglayer
470 ViewInformation3D::ViewInformation3D(
471 const basegfx::B3DHomMatrix
& rObjectObjectTransformation
,
472 const basegfx::B3DHomMatrix
& rOrientation
,
473 const basegfx::B3DHomMatrix
& rProjection
,
474 const basegfx::B3DHomMatrix
& rDeviceToView
,
476 const uno::Sequence
< beans::PropertyValue
>& rExtendedParameters
)
477 : mpViewInformation3D(new ImpViewInformation3D(
478 rObjectObjectTransformation
, rOrientation
, rProjection
,
479 rDeviceToView
, fViewTime
, rExtendedParameters
))
483 ViewInformation3D::ViewInformation3D(const uno::Sequence
< beans::PropertyValue
>& rViewParameters
)
484 : mpViewInformation3D(new ImpViewInformation3D(rViewParameters
))
488 ViewInformation3D::ViewInformation3D()
489 : mpViewInformation3D(ImpViewInformation3D::get_global_default())
491 mpViewInformation3D
->mnRefCount
++;
494 ViewInformation3D::ViewInformation3D(const ViewInformation3D
& rCandidate
)
495 : mpViewInformation3D(rCandidate
.mpViewInformation3D
)
497 ::osl::Mutex m_mutex
;
498 mpViewInformation3D
->mnRefCount
++;
501 ViewInformation3D::~ViewInformation3D()
503 ::osl::Mutex m_mutex
;
505 if(mpViewInformation3D
->mnRefCount
)
507 mpViewInformation3D
->mnRefCount
--;
511 delete mpViewInformation3D
;
515 bool ViewInformation3D::isDefault() const
517 return mpViewInformation3D
== ImpViewInformation3D::get_global_default();
520 ViewInformation3D
& ViewInformation3D::operator=(const ViewInformation3D
& rCandidate
)
522 ::osl::Mutex m_mutex
;
524 if(mpViewInformation3D
->mnRefCount
)
526 mpViewInformation3D
->mnRefCount
--;
530 delete mpViewInformation3D
;
533 mpViewInformation3D
= rCandidate
.mpViewInformation3D
;
534 mpViewInformation3D
->mnRefCount
++;
539 bool ViewInformation3D::operator==(const ViewInformation3D
& rCandidate
) const
541 if(rCandidate
.mpViewInformation3D
== mpViewInformation3D
)
546 if(rCandidate
.isDefault() != isDefault())
551 return (*rCandidate
.mpViewInformation3D
== *mpViewInformation3D
);
554 const basegfx::B3DHomMatrix
& ViewInformation3D::getObjectTransformation() const
556 return mpViewInformation3D
->getObjectTransformation();
559 const basegfx::B3DHomMatrix
& ViewInformation3D::getOrientation() const
561 return mpViewInformation3D
->getOrientation();
564 const basegfx::B3DHomMatrix
& ViewInformation3D::getProjection() const
566 return mpViewInformation3D
->getProjection();
569 const basegfx::B3DHomMatrix
& ViewInformation3D::getDeviceToView() const
571 return mpViewInformation3D
->getDeviceToView();
574 const basegfx::B3DHomMatrix
& ViewInformation3D::getObjectToView() const
576 return mpViewInformation3D
->getObjectToView();
579 double ViewInformation3D::getViewTime() const
581 return mpViewInformation3D
->getViewTime();
584 const uno::Sequence
< beans::PropertyValue
>& ViewInformation3D::getViewInformationSequence() const
586 return mpViewInformation3D
->getViewInformationSequence();
589 const uno::Sequence
< beans::PropertyValue
>& ViewInformation3D::getExtendedInformationSequence() const
591 return mpViewInformation3D
->getExtendedInformationSequence();
593 } // end of namespace geometry
594 } // end of namespace drawinglayer
596 //////////////////////////////////////////////////////////////////////////////
599 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */