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