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/primitive3d/sdrlatheprimitive3d.hxx>
30 : : #include <basegfx/matrix/b2dhommatrix.hxx>
31 : : #include <basegfx/polygon/b2dpolygontools.hxx>
32 : : #include <basegfx/polygon/b3dpolypolygontools.hxx>
33 : : #include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx>
34 : : #include <basegfx/tools/canvastools.hxx>
35 : : #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
36 : : #include <drawinglayer/geometry/viewinformation3d.hxx>
37 : : #include <drawinglayer/attribute/sdrfillattribute.hxx>
38 : : #include <drawinglayer/attribute/sdrlineattribute.hxx>
39 : : #include <drawinglayer/attribute/sdrshadowattribute.hxx>
40 : :
41 : : //////////////////////////////////////////////////////////////////////////////
42 : :
43 : : using namespace com::sun::star;
44 : :
45 : : //////////////////////////////////////////////////////////////////////////////
46 : :
47 : : namespace drawinglayer
48 : : {
49 : : namespace primitive3d
50 : : {
51 : 0 : Primitive3DSequence SdrLathePrimitive3D::create3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const
52 : : {
53 : 0 : Primitive3DSequence aRetval;
54 : :
55 : : // get slices
56 [ # # ]: 0 : const Slice3DVector& rSliceVector = getSlices();
57 : :
58 [ # # ]: 0 : if(!rSliceVector.empty())
59 : : {
60 : 0 : const bool bBackScale(!basegfx::fTools::equal(getBackScale(), 1.0));
61 [ # # ][ # # ]: 0 : const bool bClosedRotation(!bBackScale && getHorizontalSegments() && basegfx::fTools::equal(getRotation(), F_2PI));
[ # # ][ # # ]
[ # # ]
62 : : sal_uInt32 a;
63 : :
64 : : // decide what to create
65 [ # # ][ # # ]: 0 : const ::com::sun::star::drawing::NormalsKind eNormalsKind(getSdr3DObjectAttribute().getNormalsKind());
[ # # ]
66 : 0 : const bool bCreateNormals(::com::sun::star::drawing::NormalsKind_SPECIFIC == eNormalsKind);
67 [ # # ][ # # ]: 0 : const bool bCreateTextureCoordiantesX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX());
[ # # ]
68 [ # # ][ # # ]: 0 : const bool bCreateTextureCoordiantesY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY());
[ # # ]
69 [ # # ]: 0 : basegfx::B2DHomMatrix aTexTransform;
70 : :
71 [ # # ][ # # ]: 0 : if(!getSdrLFSAttribute().getFill().isDefault()
[ # # ][ # # ]
[ # # ]
72 : : && (bCreateTextureCoordiantesX || bCreateTextureCoordiantesY))
73 : : {
74 [ # # ]: 0 : aTexTransform.set(0, 0, 0.0);
75 [ # # ]: 0 : aTexTransform.set(0, 1, 1.0);
76 [ # # ]: 0 : aTexTransform.set(1, 0, 1.0);
77 [ # # ]: 0 : aTexTransform.set(1, 1, 0.0);
78 : :
79 [ # # ]: 0 : aTexTransform.translate(0.0, -0.5);
80 [ # # ]: 0 : aTexTransform.scale(1.0, -1.0);
81 [ # # ]: 0 : aTexTransform.translate(0.0, 0.5);
82 : : }
83 : :
84 : : // create geometry
85 [ # # ]: 0 : ::std::vector< basegfx::B3DPolyPolygon > aFill;
86 : : extractPlanesFromSlice(aFill, rSliceVector,
87 : 0 : bCreateNormals, getSmoothHorizontalNormals(), getSmoothNormals(), getSmoothLids(), bClosedRotation,
88 [ # # ][ # # ]: 0 : 0.85, 0.6, bCreateTextureCoordiantesX || bCreateTextureCoordiantesY, aTexTransform);
[ # # ]
89 : :
90 : : // get full range
91 [ # # ]: 0 : const basegfx::B3DRange aRange(getRangeFrom3DGeometry(aFill));
92 : :
93 : : // normal creation
94 [ # # ][ # # ]: 0 : if(!getSdrLFSAttribute().getFill().isDefault())
95 : : {
96 [ # # ]: 0 : if(::com::sun::star::drawing::NormalsKind_SPHERE == eNormalsKind)
97 : : {
98 [ # # ]: 0 : applyNormalsKindSphereTo3DGeometry(aFill, aRange);
99 : : }
100 [ # # ]: 0 : else if(::com::sun::star::drawing::NormalsKind_FLAT == eNormalsKind)
101 : : {
102 [ # # ]: 0 : applyNormalsKindFlatTo3DGeometry(aFill);
103 : : }
104 : :
105 [ # # ][ # # ]: 0 : if(getSdr3DObjectAttribute().getNormalsInvert())
[ # # ][ # # ]
106 : : {
107 [ # # ]: 0 : applyNormalsInvertTo3DGeometry(aFill);
108 : : }
109 : : }
110 : :
111 : : // texture coordinates
112 [ # # ][ # # ]: 0 : if(!getSdrLFSAttribute().getFill().isDefault())
113 : : {
114 : : applyTextureTo3DGeometry(
115 : : getSdr3DObjectAttribute().getTextureProjectionX(),
116 : : getSdr3DObjectAttribute().getTextureProjectionY(),
117 : : aFill,
118 : : aRange,
119 [ # # ][ # # ]: 0 : getTextureSize());
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
120 : : }
121 : :
122 [ # # ][ # # ]: 0 : if(!getSdrLFSAttribute().getFill().isDefault())
123 : : {
124 : : // add fill
125 : : aRetval = create3DPolyPolygonFillPrimitives(
126 : : aFill,
127 : 0 : getTransform(),
128 : 0 : getTextureSize(),
129 : : getSdr3DObjectAttribute(),
130 : 0 : getSdrLFSAttribute().getFill(),
131 [ # # # # ]: 0 : getSdrLFSAttribute().getFillFloatTransGradient());
[ # # ][ # # ]
[ # # ]
132 : : }
133 : : else
134 : : {
135 : : // create simplified 3d hit test geometry
136 : : aRetval = createHiddenGeometryPrimitives3D(
137 : : aFill,
138 : 0 : getTransform(),
139 : 0 : getTextureSize(),
140 [ # # # # ]: 0 : getSdr3DObjectAttribute());
[ # # ][ # # ]
[ # # ]
141 : : }
142 : :
143 : : // add line
144 [ # # ][ # # ]: 0 : if(!getSdrLFSAttribute().getLine().isDefault())
145 : : {
146 [ # # ][ # # ]: 0 : if(getSdr3DObjectAttribute().getReducedLineGeometry())
[ # # ][ # # ]
147 : : {
148 : : // create geometric outlines with reduced line geometry for chart
149 [ # # ]: 0 : const basegfx::B3DPolyPolygon aHorLine(extractHorizontalLinesFromSlice(rSliceVector, bClosedRotation));
150 [ # # ]: 0 : const sal_uInt32 nCount(aHorLine.count());
151 [ # # ]: 0 : basegfx::B3DPolyPolygon aNewLineGeometry;
152 : :
153 [ # # ]: 0 : for(a = 1; a < nCount; a++)
154 : : {
155 : : // for each loop pair create the connection edges
156 : : createReducedOutlines(
157 : : rViewInformation,
158 : 0 : getTransform(),
159 : : aHorLine.getB3DPolygon(a - 1),
160 : : aHorLine.getB3DPolygon(a),
161 [ # # ]: 0 : aNewLineGeometry);
[ # # # # ]
[ # # ][ # # ]
162 : : }
163 : :
164 [ # # ]: 0 : for(a = 0; a < nCount; a++)
165 : : {
166 : : // filter hor lines for empty loops (those who have their defining point on the Y-Axis)
167 [ # # ]: 0 : basegfx::B3DPolygon aCandidate(aHorLine.getB3DPolygon(a));
168 [ # # ]: 0 : aCandidate.removeDoublePoints();
169 : :
170 [ # # ][ # # ]: 0 : if(aCandidate.count())
171 : : {
172 [ # # ]: 0 : aNewLineGeometry.append(aCandidate);
173 : : }
174 [ # # ]: 0 : }
175 : :
176 [ # # ][ # # ]: 0 : if(aNewLineGeometry.count())
177 : : {
178 : : const Primitive3DSequence aLines(create3DPolyPolygonLinePrimitives(
179 [ # # ]: 0 : aNewLineGeometry, getTransform(), getSdrLFSAttribute().getLine()));
180 [ # # ][ # # ]: 0 : appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aLines);
181 [ # # ][ # # ]: 0 : }
182 : : }
183 : : else
184 : : {
185 : : // extract line geometry from slices
186 [ # # ]: 0 : const basegfx::B3DPolyPolygon aHorLine(extractHorizontalLinesFromSlice(rSliceVector, bClosedRotation));
187 [ # # ]: 0 : const basegfx::B3DPolyPolygon aVerLine(extractVerticalLinesFromSlice(rSliceVector));
188 : :
189 : : // add horizontal lines
190 : : const Primitive3DSequence aHorLines(create3DPolyPolygonLinePrimitives(
191 [ # # ]: 0 : aHorLine, getTransform(), getSdrLFSAttribute().getLine()));
192 [ # # ]: 0 : appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aHorLines);
193 : :
194 : : // add vertical lines
195 : : const Primitive3DSequence aVerLines(create3DPolyPolygonLinePrimitives(
196 [ # # ]: 0 : aVerLine, getTransform(), getSdrLFSAttribute().getLine()));
197 [ # # ][ # # ]: 0 : appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aVerLines);
[ # # ][ # # ]
[ # # ]
198 : : }
199 : : }
200 : :
201 : : // add shadow
202 [ # # ]: 0 : if(!getSdrLFSAttribute().getShadow().isDefault()
[ # # # # ]
[ # # ]
203 : 0 : && aRetval.hasElements())
204 : : {
205 : : const Primitive3DSequence aShadow(createShadowPrimitive3D(
206 [ # # ][ # # ]: 0 : aRetval, getSdrLFSAttribute().getShadow(), getSdr3DObjectAttribute().getShadow3D()));
[ # # ][ # # ]
207 [ # # ][ # # ]: 0 : appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aShadow);
208 [ # # ]: 0 : }
209 : : }
210 : :
211 : 0 : return aRetval;
212 : : }
213 : :
214 : 0 : void SdrLathePrimitive3D::impCreateSlices()
215 : : {
216 : : // prepare the polygon. No double points, correct orientations and a correct
217 : : // outmost polygon are needed
218 [ # # ][ # # ]: 0 : maCorrectedPolyPolygon = basegfx::tools::adaptiveSubdivideByAngle(getPolyPolygon());
[ # # ]
219 [ # # ]: 0 : maCorrectedPolyPolygon.removeDoublePoints();
220 [ # # ][ # # ]: 0 : maCorrectedPolyPolygon = basegfx::tools::correctOrientations(maCorrectedPolyPolygon);
[ # # ]
221 [ # # ][ # # ]: 0 : maCorrectedPolyPolygon = basegfx::tools::correctOutmostPolygon(maCorrectedPolyPolygon);
[ # # ]
222 : :
223 : : // check edge count of first sub-polygon. If different, reSegment polyPolygon. This ensures
224 : : // that for polyPolygons, the subPolys 1..n only get reSegmented when polygon 0L is different
225 : : // at all (and not always)
226 [ # # ]: 0 : const basegfx::B2DPolygon aSubCandidate(maCorrectedPolyPolygon.getB2DPolygon(0));
227 [ # # ][ # # ]: 0 : const sal_uInt32 nSubEdgeCount(aSubCandidate.isClosed() ? aSubCandidate.count() : (aSubCandidate.count() ? aSubCandidate.count() - 1L : 0L));
[ # # ][ # # ]
[ # # ][ # # ]
228 : :
229 [ # # ]: 0 : if(nSubEdgeCount != getVerticalSegments())
230 : : {
231 [ # # ][ # # ]: 0 : maCorrectedPolyPolygon = basegfx::tools::reSegmentPolyPolygon(maCorrectedPolyPolygon, getVerticalSegments());
[ # # ]
232 : : }
233 : :
234 : : // prepare slices as geometry
235 [ # # ][ # # ]: 0 : createLatheSlices(maSlices, maCorrectedPolyPolygon, getBackScale(), getDiagonal(), getRotation(), getHorizontalSegments(), getCharacterMode(), getCloseFront(), getCloseBack());
236 : 0 : }
237 : :
238 : 0 : const Slice3DVector& SdrLathePrimitive3D::getSlices() const
239 : : {
240 : : // This can be made dependent of getSdrLFSAttribute().getFill() and getSdrLFSAttribute().getLine()
241 : : // again when no longer geometry is needed for non-visible 3D objects as it is now for chart
242 [ # # ][ # # ]: 0 : if(getPolyPolygon().count() && !maSlices.size())
[ # # ]
243 : : {
244 [ # # ]: 0 : ::osl::Mutex m_mutex;
245 [ # # ][ # # ]: 0 : const_cast< SdrLathePrimitive3D& >(*this).impCreateSlices();
246 : : }
247 : :
248 : 0 : return maSlices;
249 : : }
250 : :
251 : 0 : SdrLathePrimitive3D::SdrLathePrimitive3D(
252 : : const basegfx::B3DHomMatrix& rTransform,
253 : : const basegfx::B2DVector& rTextureSize,
254 : : const attribute::SdrLineFillShadowAttribute3D& rSdrLFSAttribute,
255 : : const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute,
256 : : const basegfx::B2DPolyPolygon& rPolyPolygon,
257 : : sal_uInt32 nHorizontalSegments,
258 : : sal_uInt32 nVerticalSegments,
259 : : double fDiagonal,
260 : : double fBackScale,
261 : : double fRotation,
262 : : bool bSmoothNormals,
263 : : bool bSmoothHorizontalNormals,
264 : : bool bSmoothLids,
265 : : bool bCharacterMode,
266 : : bool bCloseFront,
267 : : bool bCloseBack)
268 : : : SdrPrimitive3D(rTransform, rTextureSize, rSdrLFSAttribute, rSdr3DObjectAttribute),
269 : : maCorrectedPolyPolygon(),
270 : : maSlices(),
271 : : maPolyPolygon(rPolyPolygon),
272 : : mnHorizontalSegments(nHorizontalSegments),
273 : : mnVerticalSegments(nVerticalSegments),
274 : : mfDiagonal(fDiagonal),
275 : : mfBackScale(fBackScale),
276 : : mfRotation(fRotation),
277 : : mpLastRLGViewInformation(0),
278 : : mbSmoothNormals(bSmoothNormals),
279 : : mbSmoothHorizontalNormals(bSmoothHorizontalNormals),
280 : : mbSmoothLids(bSmoothLids),
281 : : mbCharacterMode(bCharacterMode),
282 : : mbCloseFront(bCloseFront),
283 [ # # ][ # # ]: 0 : mbCloseBack(bCloseBack)
[ # # ]
284 : : {
285 : : // make sure Rotation is positive
286 [ # # ]: 0 : if(basegfx::fTools::lessOrEqual(getRotation(), 0.0))
287 : : {
288 : 0 : mfRotation = 0.0;
289 : : }
290 : :
291 : : // make sure the percentage value getDiagonal() is between 0.0 and 1.0
292 [ # # ]: 0 : if(basegfx::fTools::lessOrEqual(getDiagonal(), 0.0))
293 : : {
294 : 0 : mfDiagonal = 0.0;
295 : : }
296 [ # # ]: 0 : else if(basegfx::fTools::moreOrEqual(getDiagonal(), 1.0))
297 : : {
298 : 0 : mfDiagonal = 1.0;
299 : : }
300 : :
301 : : // no close front/back when polygon is not closed
302 [ # # ][ # # ]: 0 : if(getPolyPolygon().count() && !getPolyPolygon().getB2DPolygon(0L).isClosed())
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
[ # # # # ]
303 : : {
304 : 0 : mbCloseFront = mbCloseBack = false;
305 : : }
306 : :
307 : : // no edge rounding when not closing
308 [ # # ][ # # ]: 0 : if(!getCloseFront() && !getCloseBack())
[ # # ]
309 : : {
310 : 0 : mfDiagonal = 0.0;
311 : : }
312 : 0 : }
313 : :
314 [ # # ][ # # ]: 0 : SdrLathePrimitive3D::~SdrLathePrimitive3D()
315 : : {
316 [ # # ]: 0 : if(mpLastRLGViewInformation)
317 : : {
318 [ # # ][ # # ]: 0 : delete mpLastRLGViewInformation;
319 : : }
320 [ # # ]: 0 : }
321 : :
322 : 0 : bool SdrLathePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
323 : : {
324 [ # # ]: 0 : if(SdrPrimitive3D::operator==(rPrimitive))
325 : : {
326 : 0 : const SdrLathePrimitive3D& rCompare = static_cast< const SdrLathePrimitive3D& >(rPrimitive);
327 : :
328 : 0 : return (getPolyPolygon() == rCompare.getPolyPolygon()
329 : 0 : && getHorizontalSegments() == rCompare.getHorizontalSegments()
330 : 0 : && getVerticalSegments() == rCompare.getVerticalSegments()
331 : 0 : && getDiagonal() == rCompare.getDiagonal()
332 : 0 : && getBackScale() == rCompare.getBackScale()
333 : 0 : && getRotation() == rCompare.getRotation()
334 : 0 : && getSmoothNormals() == rCompare.getSmoothNormals()
335 : 0 : && getSmoothHorizontalNormals() == rCompare.getSmoothHorizontalNormals()
336 : 0 : && getSmoothLids() == rCompare.getSmoothLids()
337 : 0 : && getCharacterMode() == rCompare.getCharacterMode()
338 : 0 : && getCloseFront() == rCompare.getCloseFront()
339 [ # # ][ # # : 0 : && getCloseBack() == rCompare.getCloseBack());
# # # # #
# # # # #
# # # # #
# # # #
# ]
340 : : }
341 : :
342 : 0 : return false;
343 : : }
344 : :
345 : 0 : basegfx::B3DRange SdrLathePrimitive3D::getB3DRange(const geometry::ViewInformation3D& /*rViewInformation*/) const
346 : : {
347 : : // use defaut from sdrPrimitive3D which uses transformation expanded by line width/2
348 : : // The parent implementation which uses the ranges of the decomposition would be more
349 : : // corrcet, but for historical reasons it is necessary to do the old method: To get
350 : : // the range of the non-transformed geometry and transform it then. This leads to different
351 : : // ranges where the new method is more correct, but the need to keep the old behaviour
352 : : // has priority here.
353 : 0 : return get3DRangeFromSlices(getSlices());
354 : : }
355 : :
356 : 0 : Primitive3DSequence SdrLathePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const
357 : : {
358 [ # # ][ # # ]: 0 : if(getSdr3DObjectAttribute().getReducedLineGeometry())
359 : : {
360 [ # # # # : 0 : if(!mpLastRLGViewInformation ||
# # ][ # # ]
361 : 0 : (getBuffered3DDecomposition().hasElements()
362 : 0 : && *mpLastRLGViewInformation != rViewInformation))
363 : : {
364 : : // conditions of last local decomposition with reduced lines have changed. Remember
365 : : // new one and clear current decompositiopn
366 [ # # ]: 0 : ::osl::Mutex m_mutex;
367 : 0 : SdrLathePrimitive3D* pThat = const_cast< SdrLathePrimitive3D* >(this);
368 [ # # ][ # # ]: 0 : pThat->setBuffered3DDecomposition(Primitive3DSequence());
[ # # ]
369 [ # # ][ # # ]: 0 : delete pThat->mpLastRLGViewInformation;
370 [ # # ][ # # ]: 0 : pThat->mpLastRLGViewInformation = new geometry::ViewInformation3D(rViewInformation);
[ # # ]
371 : : }
372 : : }
373 : :
374 : : // no test for buffering needed, call parent
375 : 0 : return SdrPrimitive3D::get3DDecomposition(rViewInformation);
376 : : }
377 : :
378 : : // provide unique ID
379 : 0 : ImplPrimitrive3DIDBlock(SdrLathePrimitive3D, PRIMITIVE3D_ID_SDRLATHEPRIMITIVE3D)
380 : :
381 : : } // end of namespace primitive3d
382 : : } // end of namespace drawinglayer
383 : :
384 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|