Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
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.
15 : : *
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).
21 : : *
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.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <drawinglayer/processor3d/shadow3dextractor.hxx>
30 : : #include <drawinglayer/primitive3d/shadowprimitive3d.hxx>
31 : : #include <drawinglayer/primitive2d/shadowprimitive2d.hxx>
32 : : #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
33 : : #include <drawinglayer/primitive3d/transformprimitive3d.hxx>
34 : : #include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
35 : : #include <basegfx/polygon/b2dpolygontools.hxx>
36 : : #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
37 : : #include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
38 : : #include <basegfx/polygon/b2dpolypolygontools.hxx>
39 : : #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
40 : : #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
41 : :
42 : : //////////////////////////////////////////////////////////////////////////////
43 : :
44 : : using namespace com::sun::star;
45 : :
46 : : //////////////////////////////////////////////////////////////////////////////
47 : :
48 : : namespace drawinglayer
49 : : {
50 : : namespace processor3d
51 : : {
52 : : /// helper to convert from BasePrimitive2DVector to primitive2d::Primitive2DSequence
53 : 15 : const primitive2d::Primitive2DSequence Shadow3DExtractingProcessor::getPrimitive2DSequenceFromBasePrimitive2DVector(
54 : : const BasePrimitive2DVector& rVector) const
55 : : {
56 : 15 : const sal_uInt32 nCount(rVector.size());
57 : 15 : primitive2d::Primitive2DSequence aRetval(nCount);
58 : :
59 [ - + ]: 15 : for(sal_uInt32 a(0); a < nCount; a++)
60 : : {
61 [ # # ][ # # ]: 0 : aRetval[a] = rVector[a];
[ # # ][ # # ]
62 : : }
63 : :
64 : : // all entries taken over; no need to delete entries, just reset to
65 : : // mark as empty
66 : 15 : const_cast< BasePrimitive2DVector& >(rVector).clear();
67 : :
68 : 15 : return aRetval;
69 : : }
70 : :
71 : : // as tooling, the process() implementation takes over API handling and calls this
72 : : // virtual render method when the primitive implementation is BasePrimitive3D-based.
73 : 2164 : void Shadow3DExtractingProcessor::processBasePrimitive3D(const primitive3d::BasePrimitive3D& rCandidate)
74 : : {
75 : : // it is a BasePrimitive3D implementation, use getPrimitive3DID() call for switch
76 [ - + + + : 2164 : switch(rCandidate.getPrimitive3DID())
+ ]
77 : : {
78 : : case PRIMITIVE3D_ID_SHADOWPRIMITIVE3D :
79 : : {
80 : : // shadow3d object. Call recursive with content and start conversion
81 : 0 : const primitive3d::ShadowPrimitive3D& rPrimitive = static_cast< const primitive3d::ShadowPrimitive3D& >(rCandidate);
82 : :
83 : : // set new target
84 [ # # ]: 0 : BasePrimitive2DVector aNewSubList;
85 : 0 : BasePrimitive2DVector* pLastTargetSequence = mpPrimitive2DSequence;
86 : 0 : mpPrimitive2DSequence = &aNewSubList;
87 : :
88 : : // activate convert
89 : 0 : const bool bLastConvert(mbConvert);
90 : 0 : mbConvert = true;
91 : :
92 : : // set projection flag
93 : 0 : const bool bLastUseProjection(mbUseProjection);
94 : 0 : mbUseProjection = rPrimitive.getShadow3D();
95 : :
96 : : // process content
97 [ # # ][ # # ]: 0 : process(rPrimitive.getChildren());
[ # # ]
98 : :
99 : : // restore values
100 : 0 : mbUseProjection = bLastUseProjection;
101 : 0 : mbConvert = bLastConvert;
102 : 0 : mpPrimitive2DSequence = pLastTargetSequence;
103 : :
104 : : // create 2d shadow primitive with result. This also fetches all entries
105 : : // from aNewSubList, so there is no need to delete them
106 : : primitive2d::BasePrimitive2D* pNew = new primitive2d::ShadowPrimitive2D(
107 : : rPrimitive.getShadowTransform(),
108 : : rPrimitive.getShadowColor(),
109 [ # # ][ # # ]: 0 : getPrimitive2DSequenceFromBasePrimitive2DVector(aNewSubList));
[ # # ]
110 : :
111 [ # # ]: 0 : if(basegfx::fTools::more(rPrimitive.getShadowTransparence(), 0.0))
112 : : {
113 : : // create simpleTransparencePrimitive, add created primitives
114 [ # # ][ # # ]: 0 : const primitive2d::Primitive2DReference xRef(pNew);
115 [ # # ]: 0 : const primitive2d::Primitive2DSequence aNewTransPrimitiveVector(&xRef, 1);
116 : :
117 : : pNew = new primitive2d::UnifiedTransparencePrimitive2D(
118 : : aNewTransPrimitiveVector,
119 [ # # ][ # # ]: 0 : rPrimitive.getShadowTransparence());
120 : : }
121 : :
122 [ # # ]: 0 : mpPrimitive2DSequence->push_back(pNew);
123 : :
124 : 0 : break;
125 : : }
126 : : case PRIMITIVE3D_ID_TRANSFORMPRIMITIVE3D :
127 : : {
128 : : // transform group. Remember current transformations
129 : 198 : const primitive3d::TransformPrimitive3D& rPrimitive = static_cast< const primitive3d::TransformPrimitive3D& >(rCandidate);
130 [ + - ]: 198 : const geometry::ViewInformation3D aLastViewInformation3D(getViewInformation3D());
131 : :
132 : : // create new transformation; add new object transform from right side
133 : : const geometry::ViewInformation3D aNewViewInformation3D(
134 [ + - ]: 198 : aLastViewInformation3D.getObjectTransformation() * rPrimitive.getTransformation(),
135 [ + - ]: 198 : aLastViewInformation3D.getOrientation(),
136 [ + - ]: 198 : aLastViewInformation3D.getProjection(),
137 [ + - ]: 198 : aLastViewInformation3D.getDeviceToView(),
138 : : aLastViewInformation3D.getViewTime(),
139 [ + - ][ + - ]: 396 : aLastViewInformation3D.getExtendedInformationSequence());
[ + - ][ + - ]
[ + - ]
140 [ + - ]: 198 : updateViewInformation(aNewViewInformation3D);
141 : :
142 [ + - ]: 198 : if(mbShadowProjectionIsValid)
143 : : {
144 : : // update buffered WorldToEye and EyeToView
145 [ + - ][ + - ]: 198 : maWorldToEye = getViewInformation3D().getOrientation() * getViewInformation3D().getObjectTransformation();
[ + - ][ + - ]
[ + - ]
146 [ + - ][ + - ]: 198 : maEyeToView = getViewInformation3D().getDeviceToView() * getViewInformation3D().getProjection();
[ + - ][ + - ]
[ + - ]
147 : : }
148 : :
149 : : // let break down
150 [ + - ][ + - ]: 198 : process(rPrimitive.getChildren());
[ + - ]
151 : :
152 : : // restore transformations
153 [ + - ]: 198 : updateViewInformation(aLastViewInformation3D);
154 : :
155 [ + - ]: 198 : if(mbShadowProjectionIsValid)
156 : : {
157 : : // update buffered WorldToEye and EyeToView
158 [ + - ][ + - ]: 198 : maWorldToEye = getViewInformation3D().getOrientation() * getViewInformation3D().getObjectTransformation();
[ + - ][ + - ]
[ + - ]
159 [ + - ][ + - ]: 198 : maEyeToView = getViewInformation3D().getDeviceToView() * getViewInformation3D().getProjection();
[ + - ][ + - ]
[ + - ]
160 : : }
161 [ + - ][ + - ]: 198 : break;
162 : : }
163 : : case PRIMITIVE3D_ID_POLYGONHAIRLINEPRIMITIVE3D :
164 : : {
165 : : // PolygonHairlinePrimitive3D
166 [ - + ]: 766 : if(mbConvert)
167 : : {
168 : 0 : const primitive3d::PolygonHairlinePrimitive3D& rPrimitive = static_cast< const primitive3d::PolygonHairlinePrimitive3D& >(rCandidate);
169 [ # # ]: 0 : basegfx::B2DPolygon a2DHairline;
170 : :
171 [ # # ]: 0 : if(mbUseProjection)
172 : : {
173 [ # # ]: 0 : if(mbShadowProjectionIsValid)
174 : : {
175 [ # # ][ # # ]: 0 : a2DHairline = impDoShadowProjection(rPrimitive.getB3DPolygon());
[ # # ]
176 : : }
177 : : }
178 : : else
179 : : {
180 [ # # ][ # # ]: 0 : a2DHairline = basegfx::tools::createB2DPolygonFromB3DPolygon(rPrimitive.getB3DPolygon(), getViewInformation3D().getObjectToView());
[ # # ][ # # ]
181 : : }
182 : :
183 [ # # ][ # # ]: 0 : if(a2DHairline.count())
184 : : {
185 [ # # ]: 0 : a2DHairline.transform(getObjectTransformation());
186 : : mpPrimitive2DSequence->push_back(
187 : : new primitive2d::PolygonHairlinePrimitive2D(
188 : : a2DHairline,
189 [ # # ][ # # ]: 0 : maPrimitiveColor));
190 [ # # ]: 0 : }
191 : : }
192 : 766 : break;
193 : : }
194 : : case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D :
195 : : {
196 : : // PolyPolygonMaterialPrimitive3D
197 [ - + ]: 583 : if(mbConvert)
198 : : {
199 : 0 : const primitive3d::PolyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const primitive3d::PolyPolygonMaterialPrimitive3D& >(rCandidate);
200 [ # # ]: 0 : basegfx::B2DPolyPolygon a2DFill;
201 : :
202 [ # # ]: 0 : if(mbUseProjection)
203 : : {
204 [ # # ]: 0 : if(mbShadowProjectionIsValid)
205 : : {
206 [ # # ][ # # ]: 0 : a2DFill = impDoShadowProjection(rPrimitive.getB3DPolyPolygon());
[ # # ]
207 : : }
208 : : }
209 : : else
210 : : {
211 [ # # ][ # # ]: 0 : a2DFill = basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(rPrimitive.getB3DPolyPolygon(), getViewInformation3D().getObjectToView());
[ # # ][ # # ]
212 : : }
213 : :
214 [ # # ][ # # ]: 0 : if(a2DFill.count())
215 : : {
216 [ # # ]: 0 : a2DFill.transform(getObjectTransformation());
217 : : mpPrimitive2DSequence->push_back(
218 : : new primitive2d::PolyPolygonColorPrimitive2D(
219 : : a2DFill,
220 [ # # ][ # # ]: 0 : maPrimitiveColor));
221 [ # # ]: 0 : }
222 : : }
223 : 583 : break;
224 : : }
225 : : default :
226 : : {
227 : : // process recursively
228 [ + - ]: 617 : process(rCandidate.get3DDecomposition(getViewInformation3D()));
229 : 617 : break;
230 : : }
231 : : }
232 : 2164 : }
233 : :
234 : 15 : Shadow3DExtractingProcessor::Shadow3DExtractingProcessor(
235 : : const geometry::ViewInformation3D& rViewInformation,
236 : : const basegfx::B2DHomMatrix& rObjectTransformation,
237 : : const basegfx::B3DVector& rLightNormal,
238 : : double fShadowSlant,
239 : : const basegfx::B3DRange& rContained3DRange)
240 : : : BaseProcessor3D(rViewInformation),
241 : : maPrimitive2DSequence(),
242 : : mpPrimitive2DSequence(&maPrimitive2DSequence),
243 : : maObjectTransformation(rObjectTransformation),
244 : : maWorldToEye(),
245 : : maEyeToView(),
246 : : maLightNormal(rLightNormal),
247 : : maShadowPlaneNormal(),
248 : : maPlanePoint(),
249 : : mfLightPlaneScalar(0.0),
250 : : maPrimitiveColor(),
251 : : mbShadowProjectionIsValid(false),
252 : : mbConvert(false),
253 [ + - ][ + - ]: 15 : mbUseProjection(false)
[ + - ][ + - ]
254 : : {
255 : : // normalize light normal, get and normalize shadow plane normal and calculate scalar from it
256 [ + - ]: 15 : maLightNormal.normalize();
257 [ + - ]: 15 : maShadowPlaneNormal = basegfx::B3DVector(0.0, sin(fShadowSlant), cos(fShadowSlant));
258 [ + - ]: 15 : maShadowPlaneNormal.normalize();
259 : 15 : mfLightPlaneScalar = maLightNormal.scalar(maShadowPlaneNormal);
260 : :
261 : : // use only when scalar is > 0.0, so the light is in front of the object
262 [ + - ]: 15 : if(basegfx::fTools::more(mfLightPlaneScalar, 0.0))
263 : : {
264 : : // prepare buffered WorldToEye and EyeToView
265 [ + - ][ + - ]: 15 : maWorldToEye = getViewInformation3D().getOrientation() * getViewInformation3D().getObjectTransformation();
[ + - ][ + - ]
[ + - ]
266 [ + - ][ + - ]: 15 : maEyeToView = getViewInformation3D().getDeviceToView() * getViewInformation3D().getProjection();
[ + - ][ + - ]
[ + - ]
267 : :
268 : : // calculate range to get front edge around which to rotate the shadow's projection
269 : 15 : basegfx::B3DRange aContained3DRange(rContained3DRange);
270 [ + - ]: 15 : aContained3DRange.transform(getWorldToEye());
271 [ - + ][ # # ]: 15 : maPlanePoint.setX(maShadowPlaneNormal.getX() < 0.0 ? aContained3DRange.getMinX() : aContained3DRange.getMaxX());
[ + - ]
272 [ # # ][ + - ]: 15 : maPlanePoint.setY(maShadowPlaneNormal.getY() > 0.0 ? aContained3DRange.getMinY() : aContained3DRange.getMaxY());
[ - + ]
273 [ + - ][ + - ]: 15 : maPlanePoint.setZ(aContained3DRange.getMinZ() - (aContained3DRange.getDepth() / 8.0));
274 : :
275 : : // set flag that shadow projection is prepared and allowed
276 : 15 : mbShadowProjectionIsValid = true;
277 : : }
278 : 15 : }
279 : :
280 [ + - ][ + - ]: 15 : Shadow3DExtractingProcessor::~Shadow3DExtractingProcessor()
[ + - ]
281 : : {
282 : : OSL_ENSURE(0 == maPrimitive2DSequence.size(),
283 : : "OOps, someone used Shadow3DExtractingProcessor, but did not fetch the results (!)");
284 [ - + ]: 15 : for(sal_uInt32 a(0); a < maPrimitive2DSequence.size(); a++)
285 : : {
286 [ # # ][ # # ]: 0 : delete maPrimitive2DSequence[a];
[ # # ]
287 : : }
288 [ - + ]: 15 : }
289 : :
290 : 0 : basegfx::B2DPolygon Shadow3DExtractingProcessor::impDoShadowProjection(const basegfx::B3DPolygon& rSource)
291 : : {
292 : 0 : basegfx::B2DPolygon aRetval;
293 : :
294 [ # # ][ # # ]: 0 : for(sal_uInt32 a(0L); a < rSource.count(); a++)
295 : : {
296 : : // get point, transform to eye coordinate system
297 [ # # ]: 0 : basegfx::B3DPoint aCandidate(rSource.getB3DPoint(a));
298 [ # # ]: 0 : aCandidate *= getWorldToEye();
299 : :
300 : : // we are in eye coordinates
301 : : // ray is (aCandidate + fCut * maLightNormal)
302 : : // plane is (maPlanePoint, maShadowPlaneNormal)
303 : : // maLightNormal.scalar(maShadowPlaneNormal) is already in mfLightPlaneScalar and > 0.0
304 : : // get cut point of ray with shadow plane
305 : 0 : const double fCut(basegfx::B3DVector(maPlanePoint - aCandidate).scalar(maShadowPlaneNormal) / mfLightPlaneScalar);
306 : 0 : aCandidate += maLightNormal * fCut;
307 : :
308 : : // transform to view, use 2d coordinates
309 [ # # ]: 0 : aCandidate *= getEyeToView();
310 [ # # ]: 0 : aRetval.append(basegfx::B2DPoint(aCandidate.getX(), aCandidate.getY()));
311 : 0 : }
312 : :
313 : : // copy closed flag
314 [ # # ][ # # ]: 0 : aRetval.setClosed(rSource.isClosed());
315 : :
316 : 0 : return aRetval;
317 : : }
318 : :
319 : 0 : basegfx::B2DPolyPolygon Shadow3DExtractingProcessor::impDoShadowProjection(const basegfx::B3DPolyPolygon& rSource)
320 : : {
321 : 0 : basegfx::B2DPolyPolygon aRetval;
322 : :
323 [ # # ][ # # ]: 0 : for(sal_uInt32 a(0L); a < rSource.count(); a++)
324 : : {
325 [ # # ][ # # ]: 0 : aRetval.append(impDoShadowProjection(rSource.getB3DPolygon(a)));
[ # # ][ # # ]
[ # # ]
326 : : }
327 : :
328 : 0 : return aRetval;
329 : : }
330 : :
331 : 15 : const primitive2d::Primitive2DSequence Shadow3DExtractingProcessor::getPrimitive2DSequence() const
332 : : {
333 : 15 : return getPrimitive2DSequenceFromBasePrimitive2DVector(maPrimitive2DSequence);
334 : : }
335 : :
336 : : } // end of namespace processor3d
337 : : } // end of namespace drawinglayer
338 : :
339 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|