xref: /trunk/main/svx/source/engine3d/helperminimaldepth3d.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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_svx.hxx"
30 
31 #include <helperminimaldepth3d.hxx>
32 #include <drawinglayer/processor3d/baseprocessor3d.hxx>
33 #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
34 #include <drawinglayer/primitive3d/transformprimitive3d.hxx>
35 #include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
36 #include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
37 #include <svx/sdr/contact/viewcontactofe3d.hxx>
38 #include <svx/sdr/contact/viewcontactofe3dscene.hxx>
39 #include <svx/obj3d.hxx>
40 #include <svx/scene3d.hxx>
41 
42 //////////////////////////////////////////////////////////////////////////////
43 
44 namespace drawinglayer
45 {
46     namespace processor3d
47     {
48         class MinimalDephInViewExtractor : public BaseProcessor3D
49         {
50         private:
51             // the value which will be fetched as result
52             double                                  mfMinimalDepth;
53 
54             // as tooling, the process() implementation takes over API handling and calls this
55             // virtual render method when the primitive implementation is BasePrimitive3D-based.
56             virtual void processBasePrimitive3D(const primitive3d::BasePrimitive3D& rCandidate);
57 
58         public:
59             MinimalDephInViewExtractor(const geometry::ViewInformation3D& rViewInformation)
60             :   BaseProcessor3D(rViewInformation),
61                 mfMinimalDepth(DBL_MAX)
62             {}
63 
64             // data access
65             double getMinimalDepth() const { return mfMinimalDepth; }
66         };
67 
68         void MinimalDephInViewExtractor::processBasePrimitive3D(const primitive3d::BasePrimitive3D& rCandidate)
69         {
70             // it is a BasePrimitive3D implementation, use getPrimitive3DID() call for switch
71             switch(rCandidate.getPrimitive3DID())
72             {
73                 case PRIMITIVE3D_ID_TRANSFORMPRIMITIVE3D :
74                 {
75                     // transform group. Remember current transformations
76                     const primitive3d::TransformPrimitive3D& rPrimitive = static_cast< const primitive3d::TransformPrimitive3D& >(rCandidate);
77                     const geometry::ViewInformation3D aLastViewInformation3D(getViewInformation3D());
78 
79                     // create new transformation; add new object transform from right side
80                     const geometry::ViewInformation3D aNewViewInformation3D(
81                         aLastViewInformation3D.getObjectTransformation() * rPrimitive.getTransformation(),
82                         aLastViewInformation3D.getOrientation(),
83                         aLastViewInformation3D.getProjection(),
84                         aLastViewInformation3D.getDeviceToView(),
85                         aLastViewInformation3D.getViewTime(),
86                         aLastViewInformation3D.getExtendedInformationSequence());
87                     updateViewInformation(aNewViewInformation3D);
88 
89                     // let break down
90                     process(rPrimitive.getChildren());
91 
92                     // restore transformations
93                     updateViewInformation(aLastViewInformation3D);
94                     break;
95                 }
96                 case PRIMITIVE3D_ID_POLYGONHAIRLINEPRIMITIVE3D :
97                 {
98                     // PolygonHairlinePrimitive3D
99                     const primitive3d::PolygonHairlinePrimitive3D& rPrimitive = static_cast< const primitive3d::PolygonHairlinePrimitive3D& >(rCandidate);
100                     const basegfx::B3DPolygon& rPolygon = rPrimitive.getB3DPolygon();
101                     const sal_uInt32 nCount(rPolygon.count());
102 
103                     for(sal_uInt32 a(0); a < nCount; a++)
104                     {
105                         const basegfx::B3DPoint aPointInView(getViewInformation3D().getObjectToView() * rPolygon.getB3DPoint(a));
106 
107                         if(aPointInView.getZ() < mfMinimalDepth)
108                         {
109                             mfMinimalDepth = aPointInView.getZ();
110                         }
111                     }
112 
113                     break;
114                 }
115                 case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D :
116                 {
117                     // PolyPolygonMaterialPrimitive3D
118                     const primitive3d::PolyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const primitive3d::PolyPolygonMaterialPrimitive3D& >(rCandidate);
119                     const basegfx::B3DPolyPolygon& rPolyPolygon = rPrimitive.getB3DPolyPolygon();
120                     const sal_uInt32 nPolyCount(rPolyPolygon.count());
121 
122                     for(sal_uInt32 a(0); a < nPolyCount; a++)
123                     {
124                         const basegfx::B3DPolygon aPolygon(rPolyPolygon.getB3DPolygon(a));
125                         const sal_uInt32 nCount(aPolygon.count());
126 
127                         for(sal_uInt32 b(0); b < nCount; b++)
128                         {
129                             const basegfx::B3DPoint aPointInView(getViewInformation3D().getObjectToView() * aPolygon.getB3DPoint(b));
130 
131                             if(aPointInView.getZ() < mfMinimalDepth)
132                             {
133                                 mfMinimalDepth = aPointInView.getZ();
134                             }
135                         }
136                     }
137 
138                     break;
139                 }
140                 default :
141                 {
142                     // process recursively
143                     process(rCandidate.get3DDecomposition(getViewInformation3D()));
144                     break;
145                 }
146             }
147         }
148     } // end of namespace processor3d
149 } // end of namespace drawinglayer
150 
151 //////////////////////////////////////////////////////////////////////////////
152 // changed to create values using VCs, Primitive3DSequence and ViewInformation3D to allow
153 // removal of old 3D bucket geometry. There is one slight difference in the result, it's
154 // in [0.0 .. 1.0] for Z-Depth since the scaling of the scene as 2D object is no longer
155 // part of the 3D transformations. This could be added since the ViewContactOfE3dScene is
156 // given, but is not needed since the permutation of the depth values needs only be correct
157 // relative to each other
158 
159 double getMinimalDepthInViewCoordinates(const E3dCompoundObject& rObject)
160 {
161     // this is a E3dCompoundObject, so it cannot be a scene (which is a E3dObject).
162     // Get primitive sequence using VC
163     const sdr::contact::ViewContactOfE3d& rVCObject = static_cast< sdr::contact::ViewContactOfE3d& >(rObject.GetViewContact());
164     const drawinglayer::primitive3d::Primitive3DSequence aPrimitives = rVCObject.getViewIndependentPrimitive3DSequence();
165     double fRetval(DBL_MAX);
166 
167     if(aPrimitives.hasElements())
168     {
169         const E3dScene* pScene = rObject.GetScene();
170 
171         if(pScene)
172         {
173             // get ViewInformation3D from scene using VC
174             const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact());
175             const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
176 
177             // the scene's object transformation is already part of aViewInfo3D.getObjectTransformation()
178             // for historical reasons (see ViewContactOfE3dScene::createViewInformation3D for more info)
179             // and the object's transform is part of aPrimitives (and taken into account when decomposing
180             // to PolygonHairlinePrimitive3D and PolyPolygonMaterialPrimitive3D). The missing part may be
181             // some Scene SdrObjects lying in-between which may need to be added. This is e.g. used in chart,
182             // and generally allowed in 3d scenes an their 3d object hierarchy
183             basegfx::B3DHomMatrix aInBetweenSceneMatrix;
184             E3dScene* pParentScene = dynamic_cast< E3dScene* >(rObject.GetParentObj());
185 
186             while(pParentScene && pParentScene != pScene)
187             {
188                 aInBetweenSceneMatrix = pParentScene->GetTransform() * aInBetweenSceneMatrix;
189                 pParentScene = dynamic_cast< E3dScene* >(pParentScene->GetParentObj());
190             }
191 
192             // build new ViewInformation containing all transforms
193             const drawinglayer::geometry::ViewInformation3D aNewViewInformation3D(
194                 aViewInfo3D.getObjectTransformation() * aInBetweenSceneMatrix,
195                 aViewInfo3D.getOrientation(),
196                 aViewInfo3D.getProjection(),
197                 aViewInfo3D.getDeviceToView(),
198                 aViewInfo3D.getViewTime(),
199                 aViewInfo3D.getExtendedInformationSequence());
200 
201             // create extractor helper, proccess geometry and get return value
202             drawinglayer::processor3d::MinimalDephInViewExtractor aExtractor(aNewViewInformation3D);
203             aExtractor.process(aPrimitives);
204             fRetval = aExtractor.getMinimalDepth();
205         }
206     }
207 
208     return fRetval;
209 }
210 
211 //////////////////////////////////////////////////////////////////////////////
212 // eof
213