1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <drawinglayer/geometry/viewinformation3d.hxx>
21 #include <basegfx/range/b3drange.hxx>
22 #include <basegfx/matrix/b3dhommatrix.hxx>
23 #include <com/sun/star/geometry/AffineMatrix3D.hpp>
24 #include <com/sun/star/geometry/RealRectangle3D.hpp>
25 #include <basegfx/tools/canvastools.hxx>
26 #include <rtl/instance.hxx>
29 using namespace com::sun::star
;
32 namespace drawinglayer
36 /** Implementation class for ViewInformation3D
38 class ImpViewInformation3D
41 // ViewInformation3D implementation can change refcount, so we have only
42 // two memory regions for pairs of ViewInformation3D/ImpViewInformation3D
43 friend class ::drawinglayer::geometry::ViewInformation3D
;
45 // the 3D transformations
46 // Object to World. This may change and being adapted when entering 3D transformation
48 basegfx::B3DHomMatrix maObjectTransformation
;
50 // World to Camera. This includes VRP, VPN and VUV camera coordinate system
51 basegfx::B3DHomMatrix maOrientation
;
53 // Camera to Device with X,Y and Z [-1.0 .. 1.0]. This is the
54 // 3D to 2D projection which may be parallel or perspective. When it is perspective,
55 // the last line of the homogen matrix will NOT be unused
56 basegfx::B3DHomMatrix maProjection
;
58 // Device to View with X,Y and Z [0.0 .. 1.0]. This converts from -1 to 1 coordinates
59 // in camera coordinate system to 0 to 1 in unit 2D coordinates. This way it stays
60 // view-independent. To get discrete coordinates, the 2D transformation of a scene
61 // as 2D object needs to be involved
62 basegfx::B3DHomMatrix maDeviceToView
;
64 // Object to View is the linear combination of all four transformations. It's
65 // buffered to avoid too much matrix multiplying and created on demand
66 basegfx::B3DHomMatrix maObjectToView
;
71 // the complete PropertyValue representation (if already created)
72 uno::Sequence
< beans::PropertyValue
> mxViewInformation
;
74 // the extra PropertyValues; does not contain the transformations
75 uno::Sequence
< beans::PropertyValue
> mxExtendedInformation
;
77 // the local UNO API strings
78 static OUString
getNamePropertyObjectTransformation()
80 return OUString("ObjectTransformation");
83 static OUString
getNamePropertyOrientation()
85 return OUString("Orientation");
88 static OUString
getNamePropertyProjection()
90 return OUString("Projection");
93 static OUString
getNamePropertyProjection_30()
95 return OUString("Projection30");
98 static OUString
getNamePropertyProjection_31()
100 return OUString("Projection31");
103 static OUString
getNamePropertyProjection_32()
105 return OUString("Projection32");
108 static OUString
getNamePropertyProjection_33()
110 return OUString("Projection33");
113 static OUString
getNamePropertyDeviceToView()
115 return OUString("DeviceToView");
118 static OUString
getNamePropertyTime()
120 return OUString("Time");
123 // a central PropertyValue parsing method to allow transportatin of
124 // all ViewParameters using UNO API
125 void impInterpretPropertyValues(const uno::Sequence
< beans::PropertyValue
>& rViewParameters
)
127 if(rViewParameters
.hasElements())
129 const sal_Int32
nCount(rViewParameters
.getLength());
130 sal_Int32
nExtendedInsert(0);
132 // prepare extended information for filtering. Maximum size is nCount
133 mxExtendedInformation
.realloc(nCount
);
135 for(sal_Int32
a(0); a
< nCount
; a
++)
137 const beans::PropertyValue
& rProp
= rViewParameters
[a
];
139 if(rProp
.Name
== getNamePropertyObjectTransformation())
141 css::geometry::AffineMatrix3D aAffineMatrix3D
;
142 rProp
.Value
>>= aAffineMatrix3D
;
143 maObjectTransformation
= basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D
);
145 else if(rProp
.Name
== getNamePropertyOrientation())
147 css::geometry::AffineMatrix3D aAffineMatrix3D
;
148 rProp
.Value
>>= aAffineMatrix3D
;
149 maOrientation
= basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D
);
151 else if(rProp
.Name
== getNamePropertyProjection())
153 // projection may be defined using a frustum in which case the last line of
154 // the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that,
155 // these four values need to be treated extra
156 const double f_30(maProjection
.get(3, 0));
157 const double f_31(maProjection
.get(3, 1));
158 const double f_32(maProjection
.get(3, 2));
159 const double f_33(maProjection
.get(3, 3));
161 css::geometry::AffineMatrix3D aAffineMatrix3D
;
162 rProp
.Value
>>= aAffineMatrix3D
;
163 maProjection
= basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D
);
165 maProjection
.set(3, 0, f_30
);
166 maProjection
.set(3, 1, f_31
);
167 maProjection
.set(3, 2, f_32
);
168 maProjection
.set(3, 3, f_33
);
170 else if(rProp
.Name
== getNamePropertyProjection_30())
173 rProp
.Value
>>= f_30
;
174 maProjection
.set(3, 0, f_30
);
176 else if(rProp
.Name
== getNamePropertyProjection_31())
179 rProp
.Value
>>= f_31
;
180 maProjection
.set(3, 1, f_31
);
182 else if(rProp
.Name
== getNamePropertyProjection_32())
185 rProp
.Value
>>= f_32
;
186 maProjection
.set(3, 2, f_32
);
188 else if(rProp
.Name
== getNamePropertyProjection_33())
191 rProp
.Value
>>= f_33
;
192 maProjection
.set(3, 3, f_33
);
194 else if(rProp
.Name
== getNamePropertyDeviceToView())
196 css::geometry::AffineMatrix3D aAffineMatrix3D
;
197 rProp
.Value
>>= aAffineMatrix3D
;
198 maDeviceToView
= basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D
);
200 else if(rProp
.Name
== getNamePropertyTime())
202 rProp
.Value
>>= mfViewTime
;
206 // extra information; add to filtered information
207 mxExtendedInformation
[nExtendedInsert
++] = rProp
;
211 // extra information size is now known; realloc to final size
212 mxExtendedInformation
.realloc(nExtendedInsert
);
216 // central method to create a Sequence of PropertyValues containing he complete
218 void impFillViewInformationFromContent()
220 const bool bObjectTransformationUsed(!maObjectTransformation
.isIdentity());
221 const bool bOrientationUsed(!maOrientation
.isIdentity());
222 const bool bProjectionUsed(!maProjection
.isIdentity());
223 const bool bDeviceToViewUsed(!maDeviceToView
.isIdentity());
224 const bool bTimeUsed(0.0 < mfViewTime
);
225 const bool bExtraInformation(mxExtendedInformation
.hasElements());
227 // projection may be defined using a frustum in which case the last line of
228 // the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that,
229 // these four values need to be treated extra
230 const bool bProjectionUsed_30(bProjectionUsed
&& !basegfx::fTools::equalZero(maProjection
.get(3, 0)));
231 const bool bProjectionUsed_31(bProjectionUsed
&& !basegfx::fTools::equalZero(maProjection
.get(3, 1)));
232 const bool bProjectionUsed_32(bProjectionUsed
&& !basegfx::fTools::equalZero(maProjection
.get(3, 2)));
233 const bool bProjectionUsed_33(bProjectionUsed
&& !basegfx::fTools::equal(maProjection
.get(3, 3), 1.0));
235 sal_uInt32
nIndex(0);
236 const sal_uInt32
nCount(
237 (bObjectTransformationUsed
? 1 : 0) +
238 (bOrientationUsed
? 1 : 0) +
239 (bProjectionUsed
? 1 : 0) +
240 (bProjectionUsed_30
? 1 : 0) +
241 (bProjectionUsed_31
? 1 : 0) +
242 (bProjectionUsed_32
? 1 : 0) +
243 (bProjectionUsed_33
? 1 : 0) +
244 (bDeviceToViewUsed
? 1 : 0) +
245 (bTimeUsed
? 1 : 0) +
246 (bExtraInformation
? mxExtendedInformation
.getLength() : 0));
248 mxViewInformation
.realloc(nCount
);
250 if(bObjectTransformationUsed
)
252 css::geometry::AffineMatrix3D aAffineMatrix3D
;
253 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D
, maObjectTransformation
);
254 mxViewInformation
[nIndex
].Name
= getNamePropertyObjectTransformation();
255 mxViewInformation
[nIndex
].Value
<<= aAffineMatrix3D
;
261 css::geometry::AffineMatrix3D aAffineMatrix3D
;
262 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D
, maOrientation
);
263 mxViewInformation
[nIndex
].Name
= getNamePropertyOrientation();
264 mxViewInformation
[nIndex
].Value
<<= aAffineMatrix3D
;
270 css::geometry::AffineMatrix3D aAffineMatrix3D
;
271 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D
, maProjection
);
272 mxViewInformation
[nIndex
].Name
= getNamePropertyProjection();
273 mxViewInformation
[nIndex
].Value
<<= aAffineMatrix3D
;
277 if(bProjectionUsed_30
)
279 mxViewInformation
[nIndex
].Name
= getNamePropertyProjection_30();
280 mxViewInformation
[nIndex
].Value
<<= maProjection
.get(3, 0);
284 if(bProjectionUsed_31
)
286 mxViewInformation
[nIndex
].Name
= getNamePropertyProjection_31();
287 mxViewInformation
[nIndex
].Value
<<= maProjection
.get(3, 1);
291 if(bProjectionUsed_32
)
293 mxViewInformation
[nIndex
].Name
= getNamePropertyProjection_32();
294 mxViewInformation
[nIndex
].Value
<<= maProjection
.get(3, 2);
298 if(bProjectionUsed_33
)
300 mxViewInformation
[nIndex
].Name
= getNamePropertyProjection_33();
301 mxViewInformation
[nIndex
].Value
<<= maProjection
.get(3, 3);
305 if(bDeviceToViewUsed
)
307 css::geometry::AffineMatrix3D aAffineMatrix3D
;
308 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D
, maDeviceToView
);
309 mxViewInformation
[nIndex
].Name
= getNamePropertyDeviceToView();
310 mxViewInformation
[nIndex
].Value
<<= aAffineMatrix3D
;
316 mxViewInformation
[nIndex
].Name
= getNamePropertyTime();
317 mxViewInformation
[nIndex
].Value
<<= mfViewTime
;
321 if(bExtraInformation
)
323 const sal_Int32
nExtra(mxExtendedInformation
.getLength());
325 for(sal_Int32
a(0); a
< nExtra
; a
++)
327 mxViewInformation
[nIndex
++] = mxExtendedInformation
[a
];
333 ImpViewInformation3D(
334 const basegfx::B3DHomMatrix
& rObjectTransformation
,
335 const basegfx::B3DHomMatrix
& rOrientation
,
336 const basegfx::B3DHomMatrix
& rProjection
,
337 const basegfx::B3DHomMatrix
& rDeviceToView
,
339 const uno::Sequence
< beans::PropertyValue
>& rExtendedParameters
)
340 : maObjectTransformation(rObjectTransformation
),
341 maOrientation(rOrientation
),
342 maProjection(rProjection
),
343 maDeviceToView(rDeviceToView
),
344 mfViewTime(fViewTime
),
346 mxExtendedInformation()
348 impInterpretPropertyValues(rExtendedParameters
);
351 explicit ImpViewInformation3D(const uno::Sequence
< beans::PropertyValue
>& rViewParameters
)
352 : maObjectTransformation(),
357 mxViewInformation(rViewParameters
),
358 mxExtendedInformation()
360 impInterpretPropertyValues(rViewParameters
);
363 ImpViewInformation3D()
364 : maObjectTransformation(),
370 mxExtendedInformation()
374 const basegfx::B3DHomMatrix
& getObjectTransformation() const { return maObjectTransformation
; }
375 const basegfx::B3DHomMatrix
& getOrientation() const { return maOrientation
; }
376 const basegfx::B3DHomMatrix
& getProjection() const { return maProjection
; }
377 const basegfx::B3DHomMatrix
& getDeviceToView() const { return maDeviceToView
; }
378 double getViewTime() const { return mfViewTime
; }
380 const basegfx::B3DHomMatrix
& getObjectToView() const
382 // on demand WorldToView creation
384 if(maObjectToView
.isIdentity())
386 const_cast< ImpViewInformation3D
* >(this)->maObjectToView
= maDeviceToView
* maProjection
* maOrientation
* maObjectTransformation
;
389 return maObjectToView
;
392 const uno::Sequence
< beans::PropertyValue
>& getViewInformationSequence() const
394 if(!mxViewInformation
.hasElements())
396 const_cast< ImpViewInformation3D
* >(this)->impFillViewInformationFromContent();
399 return mxViewInformation
;
402 const uno::Sequence
< beans::PropertyValue
>& getExtendedInformationSequence() const
404 return mxExtendedInformation
;
407 bool operator==(const ImpViewInformation3D
& rCandidate
) const
409 return (maObjectTransformation
== rCandidate
.maObjectTransformation
410 && maOrientation
== rCandidate
.maOrientation
411 && maProjection
== rCandidate
.maProjection
412 && maDeviceToView
== rCandidate
.maDeviceToView
413 && mfViewTime
== rCandidate
.mfViewTime
414 && mxExtendedInformation
== rCandidate
.mxExtendedInformation
);
417 } // end of anonymous namespace
418 } // end of namespace drawinglayer
421 namespace drawinglayer
427 struct theGlobalDefault
:
428 public rtl::Static
< ViewInformation3D::ImplType
, theGlobalDefault
> {};
431 ViewInformation3D::ViewInformation3D(
432 const basegfx::B3DHomMatrix
& rObjectObjectTransformation
,
433 const basegfx::B3DHomMatrix
& rOrientation
,
434 const basegfx::B3DHomMatrix
& rProjection
,
435 const basegfx::B3DHomMatrix
& rDeviceToView
,
437 const uno::Sequence
< beans::PropertyValue
>& rExtendedParameters
)
438 : mpViewInformation3D(ImpViewInformation3D(
439 rObjectObjectTransformation
, rOrientation
, rProjection
,
440 rDeviceToView
, fViewTime
, rExtendedParameters
))
444 ViewInformation3D::ViewInformation3D(const uno::Sequence
< beans::PropertyValue
>& rViewParameters
)
445 : mpViewInformation3D(ImpViewInformation3D(rViewParameters
))
449 ViewInformation3D::ViewInformation3D()
450 : mpViewInformation3D(theGlobalDefault::get())
454 ViewInformation3D::ViewInformation3D(const ViewInformation3D
& rCandidate
)
455 : mpViewInformation3D(rCandidate
.mpViewInformation3D
)
459 ViewInformation3D::~ViewInformation3D()
463 bool ViewInformation3D::isDefault() const
465 return mpViewInformation3D
.same_object(theGlobalDefault::get());
468 ViewInformation3D
& ViewInformation3D::operator=(const ViewInformation3D
& rCandidate
)
470 mpViewInformation3D
= rCandidate
.mpViewInformation3D
;
474 bool ViewInformation3D::operator==(const ViewInformation3D
& rCandidate
) const
476 return rCandidate
.mpViewInformation3D
== mpViewInformation3D
;
479 const basegfx::B3DHomMatrix
& ViewInformation3D::getObjectTransformation() const
481 return mpViewInformation3D
->getObjectTransformation();
484 const basegfx::B3DHomMatrix
& ViewInformation3D::getOrientation() const
486 return mpViewInformation3D
->getOrientation();
489 const basegfx::B3DHomMatrix
& ViewInformation3D::getProjection() const
491 return mpViewInformation3D
->getProjection();
494 const basegfx::B3DHomMatrix
& ViewInformation3D::getDeviceToView() const
496 return mpViewInformation3D
->getDeviceToView();
499 const basegfx::B3DHomMatrix
& ViewInformation3D::getObjectToView() const
501 return mpViewInformation3D
->getObjectToView();
504 double ViewInformation3D::getViewTime() const
506 return mpViewInformation3D
->getViewTime();
509 const uno::Sequence
< beans::PropertyValue
>& ViewInformation3D::getViewInformationSequence() const
511 return mpViewInformation3D
->getViewInformationSequence();
514 const uno::Sequence
< beans::PropertyValue
>& ViewInformation3D::getExtendedInformationSequence() const
516 return mpViewInformation3D
->getExtendedInformationSequence();
518 } // end of namespace geometry
519 } // end of namespace drawinglayer
521 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */