diff options
Diffstat (limited to 'drawinglayer/source/geometry/viewinformation3d.cxx')
-rw-r--r-- | drawinglayer/source/geometry/viewinformation3d.cxx | 602 |
1 files changed, 602 insertions, 0 deletions
diff --git a/drawinglayer/source/geometry/viewinformation3d.cxx b/drawinglayer/source/geometry/viewinformation3d.cxx new file mode 100644 index 000000000000..cce7d7070716 --- /dev/null +++ b/drawinglayer/source/geometry/viewinformation3d.cxx @@ -0,0 +1,602 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_drawinglayer.hxx" + +#include <drawinglayer/geometry/viewinformation3d.hxx> +#include <basegfx/range/b3drange.hxx> +#include <basegfx/matrix/b3dhommatrix.hxx> +#include <com/sun/star/geometry/AffineMatrix3D.hpp> +#include <com/sun/star/geometry/RealRectangle3D.hpp> +#include <basegfx/tools/canvastools.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace geometry + { + /** Implementation class for ViewInformation3D + */ + class ImpViewInformation3D + { + private: + // ViewInformation3D implementation can change refcount, so we have only + // two memory regions for pairs of ViewInformation3D/ImpViewInformation3D + friend class ::drawinglayer::geometry::ViewInformation3D; + + // the refcounter. 0 means exclusively used + sal_uInt32 mnRefCount; + + // the 3D transformations + // Object to World. This may change and being adapted when entering 3D transformation + // groups + basegfx::B3DHomMatrix maObjectTransformation; + + // World to Camera. This includes VRP, VPN and VUV camera coordinate system + basegfx::B3DHomMatrix maOrientation; + + // Camera to Device with X,Y and Z [-1.0 .. 1.0]. This is the + // 3D to 2D projection which may be parallell or perspective. When it is perspective, + // the last line of the homogen matrix will NOT be unused + basegfx::B3DHomMatrix maProjection; + + // Device to View with X,Y and Z [0.0 .. 1.0]. This converts from -1 to 1 coordinates + // in camera coordinate system to 0 to 1 in unit 2D coordinates. This way it stays + // view-independent. To get discrete coordinates, the 2D transformation of a scene + // as 2D object needs to be involved + basegfx::B3DHomMatrix maDeviceToView; + + // Object to View is the linear combination of all four transformations. It's + // buffered to avoid too much matrix multiplying and created on demand + basegfx::B3DHomMatrix maObjectToView; + + // the point in time + double mfViewTime; + + // the complete PropertyValue representation (if already created) + uno::Sequence< beans::PropertyValue > mxViewInformation; + + // the extra PropertyValues; does not contain the transformations + uno::Sequence< beans::PropertyValue > mxExtendedInformation; + + // the local UNO API strings + const ::rtl::OUString& getNamePropertyObjectTransformation() + { + static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("ObjectTransformation")); + return s_sNameProperty; + } + + const ::rtl::OUString& getNamePropertyOrientation() + { + static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Orientation")); + return s_sNameProperty; + } + + const ::rtl::OUString& getNamePropertyProjection() + { + static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection")); + return s_sNameProperty; + } + + const ::rtl::OUString& getNamePropertyProjection_30() + { + static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection30")); + return s_sNameProperty; + } + + const ::rtl::OUString& getNamePropertyProjection_31() + { + static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection31")); + return s_sNameProperty; + } + + const ::rtl::OUString& getNamePropertyProjection_32() + { + static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection32")); + return s_sNameProperty; + } + + const ::rtl::OUString& getNamePropertyProjection_33() + { + static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection33")); + return s_sNameProperty; + } + + const ::rtl::OUString& getNamePropertyDeviceToView() + { + static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("DeviceToView")); + return s_sNameProperty; + } + + const ::rtl::OUString& getNamePropertyTime() + { + static ::rtl::OUString s_sNamePropertyTime(RTL_CONSTASCII_USTRINGPARAM("Time")); + return s_sNamePropertyTime; + } + + // a central PropertyValue parsing method to allow transportatin of + // all ViewParameters using UNO API + void impInterpretPropertyValues(const uno::Sequence< beans::PropertyValue >& rViewParameters) + { + if(rViewParameters.hasElements()) + { + const sal_Int32 nCount(rViewParameters.getLength()); + sal_Int32 nExtendedInsert(0); + + // prepare extended information for filtering. Maximum size is nCount + mxExtendedInformation.realloc(nCount); + + for(sal_Int32 a(0); a < nCount; a++) + { + const beans::PropertyValue& rProp = rViewParameters[a]; + + if(rProp.Name == getNamePropertyObjectTransformation()) + { + com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; + rProp.Value >>= aAffineMatrix3D; + maObjectTransformation = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); + } + else if(rProp.Name == getNamePropertyOrientation()) + { + com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; + rProp.Value >>= aAffineMatrix3D; + maOrientation = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); + } + else if(rProp.Name == getNamePropertyProjection()) + { + // projection may be defined using a frustum in which case the last line of + // the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that, + // these four values need to be treated extra + const double f_30(maProjection.get(3, 0)); + const double f_31(maProjection.get(3, 1)); + const double f_32(maProjection.get(3, 2)); + const double f_33(maProjection.get(3, 3)); + + com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; + rProp.Value >>= aAffineMatrix3D; + maProjection = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); + + maProjection.set(3, 0, f_30); + maProjection.set(3, 1, f_31); + maProjection.set(3, 2, f_32); + maProjection.set(3, 3, f_33); + } + else if(rProp.Name == getNamePropertyProjection_30()) + { + double f_30(0.0); + rProp.Value >>= f_30; + maProjection.set(3, 0, f_30); + } + else if(rProp.Name == getNamePropertyProjection_31()) + { + double f_31(0.0); + rProp.Value >>= f_31; + maProjection.set(3, 1, f_31); + } + else if(rProp.Name == getNamePropertyProjection_32()) + { + double f_32(0.0); + rProp.Value >>= f_32; + maProjection.set(3, 2, f_32); + } + else if(rProp.Name == getNamePropertyProjection_33()) + { + double f_33(1.0); + rProp.Value >>= f_33; + maProjection.set(3, 3, f_33); + } + else if(rProp.Name == getNamePropertyDeviceToView()) + { + com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; + rProp.Value >>= aAffineMatrix3D; + maDeviceToView = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); + } + else if(rProp.Name == getNamePropertyTime()) + { + rProp.Value >>= mfViewTime; + } + else + { + // extra information; add to filtered information + mxExtendedInformation[nExtendedInsert++] = rProp; + } + } + + // extra information size is now known; realloc to final size + mxExtendedInformation.realloc(nExtendedInsert); + } + } + + // central method to create a Sequence of PropertyValues containing he complete + // data set + void impFillViewInformationFromContent() + { + uno::Sequence< beans::PropertyValue > xRetval; + const bool bObjectTransformationUsed(!maObjectTransformation.isIdentity()); + const bool bOrientationUsed(!maOrientation.isIdentity()); + const bool bProjectionUsed(!maProjection.isIdentity()); + const bool bDeviceToViewUsed(!maDeviceToView.isIdentity()); + const bool bTimeUsed(0.0 < mfViewTime); + const bool bExtraInformation(mxExtendedInformation.hasElements()); + + // projection may be defined using a frustum in which case the last line of + // the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that, + // these four values need to be treated extra + const bool bProjectionUsed_30(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 0))); + const bool bProjectionUsed_31(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 1))); + const bool bProjectionUsed_32(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 2))); + const bool bProjectionUsed_33(bProjectionUsed && !basegfx::fTools::equal(maProjection.get(3, 3), 1.0)); + + sal_uInt32 nIndex(0); + const sal_uInt32 nCount( + (bObjectTransformationUsed ? 1 : 0) + + (bOrientationUsed ? 1 : 0) + + (bProjectionUsed ? 1 : 0) + + (bProjectionUsed_30 ? 1 : 0) + + (bProjectionUsed_31 ? 1 : 0) + + (bProjectionUsed_32 ? 1 : 0) + + (bProjectionUsed_33 ? 1 : 0) + + (bDeviceToViewUsed ? 1 : 0) + + (bTimeUsed ? 1 : 0) + + (bExtraInformation ? mxExtendedInformation.getLength() : 0)); + + mxViewInformation.realloc(nCount); + + if(bObjectTransformationUsed) + { + com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; + basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maObjectTransformation); + mxViewInformation[nIndex].Name = getNamePropertyObjectTransformation(); + mxViewInformation[nIndex].Value <<= aAffineMatrix3D; + nIndex++; + } + + if(bOrientationUsed) + { + com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; + basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maOrientation); + mxViewInformation[nIndex].Name = getNamePropertyOrientation(); + mxViewInformation[nIndex].Value <<= aAffineMatrix3D; + nIndex++; + } + + if(bProjectionUsed) + { + com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; + basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maProjection); + mxViewInformation[nIndex].Name = getNamePropertyProjection(); + mxViewInformation[nIndex].Value <<= aAffineMatrix3D; + nIndex++; + } + + if(bProjectionUsed_30) + { + mxViewInformation[nIndex].Name = getNamePropertyProjection_30(); + mxViewInformation[nIndex].Value <<= maProjection.get(3, 0); + nIndex++; + } + + if(bProjectionUsed_31) + { + mxViewInformation[nIndex].Name = getNamePropertyProjection_31(); + mxViewInformation[nIndex].Value <<= maProjection.get(3, 1); + nIndex++; + } + + if(bProjectionUsed_32) + { + mxViewInformation[nIndex].Name = getNamePropertyProjection_32(); + mxViewInformation[nIndex].Value <<= maProjection.get(3, 2); + nIndex++; + } + + if(bProjectionUsed_33) + { + mxViewInformation[nIndex].Name = getNamePropertyProjection_33(); + mxViewInformation[nIndex].Value <<= maProjection.get(3, 3); + nIndex++; + } + + if(bDeviceToViewUsed) + { + com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; + basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maDeviceToView); + mxViewInformation[nIndex].Name = getNamePropertyDeviceToView(); + mxViewInformation[nIndex].Value <<= aAffineMatrix3D; + nIndex++; + } + + if(bTimeUsed) + { + mxViewInformation[nIndex].Name = getNamePropertyTime(); + mxViewInformation[nIndex].Value <<= mfViewTime; + nIndex++; + } + + if(bExtraInformation) + { + const sal_Int32 nExtra(mxExtendedInformation.getLength()); + + for(sal_Int32 a(0); a < nExtra; a++) + { + mxViewInformation[nIndex++] = mxExtendedInformation[a]; + } + } + } + + public: + ImpViewInformation3D( + const basegfx::B3DHomMatrix& rObjectTransformation, + const basegfx::B3DHomMatrix& rOrientation, + const basegfx::B3DHomMatrix& rProjection, + const basegfx::B3DHomMatrix& rDeviceToView, + double fViewTime, + const uno::Sequence< beans::PropertyValue >& rExtendedParameters) + : mnRefCount(0), + maObjectTransformation(rObjectTransformation), + maOrientation(rOrientation), + maProjection(rProjection), + maDeviceToView(rDeviceToView), + mfViewTime(fViewTime), + mxViewInformation(), + mxExtendedInformation() + { + impInterpretPropertyValues(rExtendedParameters); + } + + ImpViewInformation3D(const uno::Sequence< beans::PropertyValue >& rViewParameters) + : mnRefCount(0), + maObjectTransformation(), + maOrientation(), + maProjection(), + maDeviceToView(), + mfViewTime(), + mxViewInformation(rViewParameters), + mxExtendedInformation() + { + impInterpretPropertyValues(rViewParameters); + } + + ImpViewInformation3D() + : mnRefCount(0), + maObjectTransformation(), + maOrientation(), + maProjection(), + maDeviceToView(), + mfViewTime(), + mxViewInformation(), + mxExtendedInformation() + { + } + + const basegfx::B3DHomMatrix& getObjectTransformation() const { return maObjectTransformation; } + const basegfx::B3DHomMatrix& getOrientation() const { return maOrientation; } + const basegfx::B3DHomMatrix& getProjection() const { return maProjection; } + const basegfx::B3DHomMatrix& getDeviceToView() const { return maDeviceToView; } + double getViewTime() const { return mfViewTime; } + + const basegfx::B3DHomMatrix& getObjectToView() const + { + // on demand WorldToView creation + ::osl::Mutex m_mutex; + + if(maObjectToView.isIdentity()) + { + const_cast< ImpViewInformation3D* >(this)->maObjectToView = maDeviceToView * maProjection * maOrientation * maObjectTransformation; + } + + return maObjectToView; + } + + const uno::Sequence< beans::PropertyValue >& getViewInformationSequence() const + { + ::osl::Mutex m_mutex; + + if(!mxViewInformation.hasElements()) + { + const_cast< ImpViewInformation3D* >(this)->impFillViewInformationFromContent(); + } + + return mxViewInformation; + } + + const uno::Sequence< beans::PropertyValue >& getExtendedInformationSequence() const + { + return mxExtendedInformation; + } + + bool operator==(const ImpViewInformation3D& rCandidate) const + { + return (maObjectTransformation == rCandidate.maObjectTransformation + && maOrientation == rCandidate.maOrientation + && maProjection == rCandidate.maProjection + && maDeviceToView == rCandidate.maDeviceToView + && mfViewTime == rCandidate.mfViewTime + && mxExtendedInformation == rCandidate.mxExtendedInformation); + } + + static ImpViewInformation3D* get_global_default() + { + static ImpViewInformation3D* pDefault = 0; + + if(!pDefault) + { + pDefault = new ImpViewInformation3D(); + + // never delete; start with RefCount 1, not 0 + pDefault->mnRefCount++; + } + + return pDefault; + } + }; + } // end of anonymous namespace +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace geometry + { + ViewInformation3D::ViewInformation3D( + const basegfx::B3DHomMatrix& rObjectObjectTransformation, + const basegfx::B3DHomMatrix& rOrientation, + const basegfx::B3DHomMatrix& rProjection, + const basegfx::B3DHomMatrix& rDeviceToView, + double fViewTime, + const uno::Sequence< beans::PropertyValue >& rExtendedParameters) + : mpViewInformation3D(new ImpViewInformation3D( + rObjectObjectTransformation, rOrientation, rProjection, + rDeviceToView, fViewTime, rExtendedParameters)) + { + } + + ViewInformation3D::ViewInformation3D(const uno::Sequence< beans::PropertyValue >& rViewParameters) + : mpViewInformation3D(new ImpViewInformation3D(rViewParameters)) + { + } + + ViewInformation3D::ViewInformation3D() + : mpViewInformation3D(ImpViewInformation3D::get_global_default()) + { + mpViewInformation3D->mnRefCount++; + } + + ViewInformation3D::ViewInformation3D(const ViewInformation3D& rCandidate) + : mpViewInformation3D(rCandidate.mpViewInformation3D) + { + ::osl::Mutex m_mutex; + mpViewInformation3D->mnRefCount++; + } + + ViewInformation3D::~ViewInformation3D() + { + ::osl::Mutex m_mutex; + + if(mpViewInformation3D->mnRefCount) + { + mpViewInformation3D->mnRefCount--; + } + else + { + delete mpViewInformation3D; + } + } + + bool ViewInformation3D::isDefault() const + { + return mpViewInformation3D == ImpViewInformation3D::get_global_default(); + } + + ViewInformation3D& ViewInformation3D::operator=(const ViewInformation3D& rCandidate) + { + ::osl::Mutex m_mutex; + + if(mpViewInformation3D->mnRefCount) + { + mpViewInformation3D->mnRefCount--; + } + else + { + delete mpViewInformation3D; + } + + mpViewInformation3D = rCandidate.mpViewInformation3D; + mpViewInformation3D->mnRefCount++; + + return *this; + } + + bool ViewInformation3D::operator==(const ViewInformation3D& rCandidate) const + { + if(rCandidate.mpViewInformation3D == mpViewInformation3D) + { + return true; + } + + if(rCandidate.isDefault() != isDefault()) + { + return false; + } + + return (*rCandidate.mpViewInformation3D == *mpViewInformation3D); + } + + const basegfx::B3DHomMatrix& ViewInformation3D::getObjectTransformation() const + { + return mpViewInformation3D->getObjectTransformation(); + } + + const basegfx::B3DHomMatrix& ViewInformation3D::getOrientation() const + { + return mpViewInformation3D->getOrientation(); + } + + const basegfx::B3DHomMatrix& ViewInformation3D::getProjection() const + { + return mpViewInformation3D->getProjection(); + } + + const basegfx::B3DHomMatrix& ViewInformation3D::getDeviceToView() const + { + return mpViewInformation3D->getDeviceToView(); + } + + const basegfx::B3DHomMatrix& ViewInformation3D::getObjectToView() const + { + return mpViewInformation3D->getObjectToView(); + } + + double ViewInformation3D::getViewTime() const + { + return mpViewInformation3D->getViewTime(); + } + + const uno::Sequence< beans::PropertyValue >& ViewInformation3D::getViewInformationSequence() const + { + return mpViewInformation3D->getViewInformationSequence(); + } + + const uno::Sequence< beans::PropertyValue >& ViewInformation3D::getExtendedInformationSequence() const + { + return mpViewInformation3D->getExtendedInformationSequence(); + } + } // end of namespace geometry +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |