1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
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.
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).
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.
27 ************************************************************************/
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>
41 //////////////////////////////////////////////////////////////////////////////
43 using namespace com::sun::star
;
45 //////////////////////////////////////////////////////////////////////////////
47 namespace drawinglayer
51 Primitive3DSequence
SdrLathePrimitive3D::create3DDecomposition(const geometry::ViewInformation3D
& rViewInformation
) const
53 Primitive3DSequence aRetval
;
56 const Slice3DVector
& rSliceVector
= getSlices();
58 if(!rSliceVector
.empty())
60 const bool bBackScale(!basegfx::fTools::equal(getBackScale(), 1.0));
61 const bool bClosedRotation(!bBackScale
&& getHorizontalSegments() && basegfx::fTools::equal(getRotation(), F_2PI
));
64 // decide what to create
65 const ::com::sun::star::drawing::NormalsKind
eNormalsKind(getSdr3DObjectAttribute().getNormalsKind());
66 const bool bCreateNormals(::com::sun::star::drawing::NormalsKind_SPECIFIC
== eNormalsKind
);
67 const bool bCreateTextureCoordiantesX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC
== getSdr3DObjectAttribute().getTextureProjectionX());
68 const bool bCreateTextureCoordiantesY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC
== getSdr3DObjectAttribute().getTextureProjectionY());
69 basegfx::B2DHomMatrix aTexTransform
;
71 if(!getSdrLFSAttribute().getFill().isDefault()
72 && (bCreateTextureCoordiantesX
|| bCreateTextureCoordiantesY
))
74 aTexTransform
.set(0, 0, 0.0);
75 aTexTransform
.set(0, 1, 1.0);
76 aTexTransform
.set(1, 0, 1.0);
77 aTexTransform
.set(1, 1, 0.0);
79 aTexTransform
.translate(0.0, -0.5);
80 aTexTransform
.scale(1.0, -1.0);
81 aTexTransform
.translate(0.0, 0.5);
85 ::std::vector
< basegfx::B3DPolyPolygon
> aFill
;
86 extractPlanesFromSlice(aFill
, rSliceVector
,
87 bCreateNormals
, getSmoothHorizontalNormals(), getSmoothNormals(), getSmoothLids(), bClosedRotation
,
88 0.85, 0.6, bCreateTextureCoordiantesX
|| bCreateTextureCoordiantesY
, aTexTransform
);
91 const basegfx::B3DRange
aRange(getRangeFrom3DGeometry(aFill
));
94 if(!getSdrLFSAttribute().getFill().isDefault())
96 if(::com::sun::star::drawing::NormalsKind_SPHERE
== eNormalsKind
)
98 applyNormalsKindSphereTo3DGeometry(aFill
, aRange
);
100 else if(::com::sun::star::drawing::NormalsKind_FLAT
== eNormalsKind
)
102 applyNormalsKindFlatTo3DGeometry(aFill
);
105 if(getSdr3DObjectAttribute().getNormalsInvert())
107 applyNormalsInvertTo3DGeometry(aFill
);
111 // texture coordinates
112 if(!getSdrLFSAttribute().getFill().isDefault())
114 applyTextureTo3DGeometry(
115 getSdr3DObjectAttribute().getTextureProjectionX(),
116 getSdr3DObjectAttribute().getTextureProjectionY(),
122 if(!getSdrLFSAttribute().getFill().isDefault())
125 aRetval
= create3DPolyPolygonFillPrimitives(
129 getSdr3DObjectAttribute(),
130 getSdrLFSAttribute().getFill(),
131 getSdrLFSAttribute().getFillFloatTransGradient());
135 // create simplified 3d hit test geometry
136 aRetval
= createHiddenGeometryPrimitives3D(
140 getSdr3DObjectAttribute());
144 if(!getSdrLFSAttribute().getLine().isDefault())
146 if(getSdr3DObjectAttribute().getReducedLineGeometry())
148 // create geometric outlines with reduced line geometry for chart
149 const basegfx::B3DPolyPolygon
aHorLine(extractHorizontalLinesFromSlice(rSliceVector
, bClosedRotation
));
150 const sal_uInt32
nCount(aHorLine
.count());
151 basegfx::B3DPolyPolygon aNewLineGeometry
;
153 for(a
= 1; a
< nCount
; a
++)
155 // for each loop pair create the connection edges
156 createReducedOutlines(
159 aHorLine
.getB3DPolygon(a
- 1),
160 aHorLine
.getB3DPolygon(a
),
164 for(a
= 0; a
< nCount
; a
++)
166 // filter hor lines for empty loops (those who have their defining point on the Y-Axis)
167 basegfx::B3DPolygon
aCandidate(aHorLine
.getB3DPolygon(a
));
168 aCandidate
.removeDoublePoints();
170 if(aCandidate
.count())
172 aNewLineGeometry
.append(aCandidate
);
176 if(aNewLineGeometry
.count())
178 const Primitive3DSequence
aLines(create3DPolyPolygonLinePrimitives(
179 aNewLineGeometry
, getTransform(), getSdrLFSAttribute().getLine()));
180 appendPrimitive3DSequenceToPrimitive3DSequence(aRetval
, aLines
);
185 // extract line geometry from slices
186 const basegfx::B3DPolyPolygon
aHorLine(extractHorizontalLinesFromSlice(rSliceVector
, bClosedRotation
));
187 const basegfx::B3DPolyPolygon
aVerLine(extractVerticalLinesFromSlice(rSliceVector
));
189 // add horizontal lines
190 const Primitive3DSequence
aHorLines(create3DPolyPolygonLinePrimitives(
191 aHorLine
, getTransform(), getSdrLFSAttribute().getLine()));
192 appendPrimitive3DSequenceToPrimitive3DSequence(aRetval
, aHorLines
);
194 // add vertical lines
195 const Primitive3DSequence
aVerLines(create3DPolyPolygonLinePrimitives(
196 aVerLine
, getTransform(), getSdrLFSAttribute().getLine()));
197 appendPrimitive3DSequenceToPrimitive3DSequence(aRetval
, aVerLines
);
202 if(!getSdrLFSAttribute().getShadow().isDefault()
203 && aRetval
.hasElements())
205 const Primitive3DSequence
aShadow(createShadowPrimitive3D(
206 aRetval
, getSdrLFSAttribute().getShadow(), getSdr3DObjectAttribute().getShadow3D()));
207 appendPrimitive3DSequenceToPrimitive3DSequence(aRetval
, aShadow
);
214 void SdrLathePrimitive3D::impCreateSlices()
216 // prepare the polygon. No double points, correct orientations and a correct
217 // outmost polygon are needed
218 maCorrectedPolyPolygon
= basegfx::tools::adaptiveSubdivideByAngle(getPolyPolygon());
219 maCorrectedPolyPolygon
.removeDoublePoints();
220 maCorrectedPolyPolygon
= basegfx::tools::correctOrientations(maCorrectedPolyPolygon
);
221 maCorrectedPolyPolygon
= basegfx::tools::correctOutmostPolygon(maCorrectedPolyPolygon
);
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 const basegfx::B2DPolygon
aSubCandidate(maCorrectedPolyPolygon
.getB2DPolygon(0));
227 const sal_uInt32
nSubEdgeCount(aSubCandidate
.isClosed() ? aSubCandidate
.count() : (aSubCandidate
.count() ? aSubCandidate
.count() - 1L : 0L));
229 if(nSubEdgeCount
!= getVerticalSegments())
231 maCorrectedPolyPolygon
= basegfx::tools::reSegmentPolyPolygon(maCorrectedPolyPolygon
, getVerticalSegments());
234 // prepare slices as geometry
235 createLatheSlices(maSlices
, maCorrectedPolyPolygon
, getBackScale(), getDiagonal(), getRotation(), getHorizontalSegments(), getCharacterMode(), getCloseFront(), getCloseBack());
238 const Slice3DVector
& SdrLathePrimitive3D::getSlices() const
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 if(getPolyPolygon().count() && !maSlices
.size())
244 ::osl::Mutex m_mutex
;
245 const_cast< SdrLathePrimitive3D
& >(*this).impCreateSlices();
251 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
,
263 bool bSmoothHorizontalNormals
,
268 : SdrPrimitive3D(rTransform
, rTextureSize
, rSdrLFSAttribute
, rSdr3DObjectAttribute
),
269 maCorrectedPolyPolygon(),
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 mbCloseBack(bCloseBack
)
285 // make sure Rotation is positive
286 if(basegfx::fTools::lessOrEqual(getRotation(), 0.0))
291 // make sure the percentage value getDiagonal() is between 0.0 and 1.0
292 if(basegfx::fTools::lessOrEqual(getDiagonal(), 0.0))
296 else if(basegfx::fTools::moreOrEqual(getDiagonal(), 1.0))
301 // no close front/back when polygon is not closed
302 if(getPolyPolygon().count() && !getPolyPolygon().getB2DPolygon(0L).isClosed())
304 mbCloseFront
= mbCloseBack
= false;
307 // no edge rounding when not closing
308 if(!getCloseFront() && !getCloseBack())
314 SdrLathePrimitive3D::~SdrLathePrimitive3D()
316 if(mpLastRLGViewInformation
)
318 delete mpLastRLGViewInformation
;
322 bool SdrLathePrimitive3D::operator==(const BasePrimitive3D
& rPrimitive
) const
324 if(SdrPrimitive3D::operator==(rPrimitive
))
326 const SdrLathePrimitive3D
& rCompare
= static_cast< const SdrLathePrimitive3D
& >(rPrimitive
);
328 return (getPolyPolygon() == rCompare
.getPolyPolygon()
329 && getHorizontalSegments() == rCompare
.getHorizontalSegments()
330 && getVerticalSegments() == rCompare
.getVerticalSegments()
331 && getDiagonal() == rCompare
.getDiagonal()
332 && getBackScale() == rCompare
.getBackScale()
333 && getRotation() == rCompare
.getRotation()
334 && getSmoothNormals() == rCompare
.getSmoothNormals()
335 && getSmoothHorizontalNormals() == rCompare
.getSmoothHorizontalNormals()
336 && getSmoothLids() == rCompare
.getSmoothLids()
337 && getCharacterMode() == rCompare
.getCharacterMode()
338 && getCloseFront() == rCompare
.getCloseFront()
339 && getCloseBack() == rCompare
.getCloseBack());
345 basegfx::B3DRange
SdrLathePrimitive3D::getB3DRange(const geometry::ViewInformation3D
& /*rViewInformation*/) const
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 return get3DRangeFromSlices(getSlices());
356 Primitive3DSequence
SdrLathePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D
& rViewInformation
) const
358 if(getSdr3DObjectAttribute().getReducedLineGeometry())
360 if(!mpLastRLGViewInformation
||
361 (getBuffered3DDecomposition().hasElements()
362 && *mpLastRLGViewInformation
!= rViewInformation
))
364 // conditions of last local decomposition with reduced lines have changed. Remember
365 // new one and clear current decompositiopn
366 ::osl::Mutex m_mutex
;
367 SdrLathePrimitive3D
* pThat
= const_cast< SdrLathePrimitive3D
* >(this);
368 pThat
->setBuffered3DDecomposition(Primitive3DSequence());
369 delete pThat
->mpLastRLGViewInformation
;
370 pThat
->mpLastRLGViewInformation
= new geometry::ViewInformation3D(rViewInformation
);
374 // no test for buffering needed, call parent
375 return SdrPrimitive3D::get3DDecomposition(rViewInformation
);
379 ImplPrimitrive3DIDBlock(SdrLathePrimitive3D
, PRIMITIVE3D_ID_SDRLATHEPRIMITIVE3D
)
381 } // end of namespace primitive3d
382 } // end of namespace drawinglayer
384 //////////////////////////////////////////////////////////////////////////////
387 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */