1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: sdrlatheprimitive3d.cxx,v $
9 * last change: $Author: aw $ $Date: 2008-06-24 15:31:08 $
11 * The Contents of this file are made available subject to
12 * the terms of GNU Lesser General Public License Version 2.1.
15 * GNU Lesser General Public License Version 2.1
16 * =============================================
17 * Copyright 2005 by Sun Microsystems, Inc.
18 * 901 San Antonio Road, Palo Alto, CA 94303, USA
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License version 2.1, as published by the Free Software Foundation.
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
34 ************************************************************************/
36 // MARKER(update_precomp.py): autogen include statement, do not remove
37 #include "precompiled_drawinglayer.hxx"
39 #include <drawinglayer/primitive3d/sdrlatheprimitive3d.hxx>
40 #include <basegfx/matrix/b2dhommatrix.hxx>
41 #include <basegfx/polygon/b2dpolygontools.hxx>
42 #include <basegfx/polygon/b3dpolypolygontools.hxx>
43 #include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx>
44 #include <basegfx/tools/canvastools.hxx>
45 #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
46 #include <drawinglayer/geometry/viewinformation3d.hxx>
47 #include <drawinglayer/primitive3d/hittestprimitive3d.hxx>
48 #include <drawinglayer/attribute/sdrattribute.hxx>
50 //////////////////////////////////////////////////////////////////////////////
52 using namespace com::sun::star
;
54 //////////////////////////////////////////////////////////////////////////////
56 namespace drawinglayer
60 Primitive3DSequence
SdrLathePrimitive3D::createLocalDecomposition(const geometry::ViewInformation3D
& rViewInformation
) const
62 Primitive3DSequence aRetval
;
65 const Slice3DVector
& rSliceVector
= getSlices();
67 if(rSliceVector
.size())
69 const bool bBackScale(!basegfx::fTools::equal(getBackScale(), 1.0));
70 const bool bClosedRotation(!bBackScale
&& getHorizontalSegments() && basegfx::fTools::equal(getRotation(), F_2PI
));
73 // decide what to create
74 const ::com::sun::star::drawing::NormalsKind
eNormalsKind(getSdr3DObjectAttribute().getNormalsKind());
75 const bool bCreateNormals(::com::sun::star::drawing::NormalsKind_SPECIFIC
== eNormalsKind
);
76 const bool bCreateTextureCoordiantesX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC
== getSdr3DObjectAttribute().getTextureProjectionX());
77 const bool bCreateTextureCoordiantesY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC
== getSdr3DObjectAttribute().getTextureProjectionY());
78 basegfx::B2DHomMatrix aTexTransform
;
80 if(getSdrLFSAttribute().getFill() && (bCreateTextureCoordiantesX
|| bCreateTextureCoordiantesY
))
82 aTexTransform
.set(0, 0, 0.0);
83 aTexTransform
.set(0, 1, 1.0);
84 aTexTransform
.set(1, 0, 1.0);
85 aTexTransform
.set(1, 1, 0.0);
87 aTexTransform
.translate(0.0, -0.5);
88 aTexTransform
.scale(1.0, -1.0);
89 aTexTransform
.translate(0.0, 0.5);
93 ::std::vector
< basegfx::B3DPolyPolygon
> aFill
;
94 extractPlanesFromSlice(aFill
, rSliceVector
,
95 bCreateNormals
, getSmoothHorizontalNormals(), getSmoothNormals(), getSmoothLids(), bClosedRotation
,
96 0.85, 0.6, bCreateTextureCoordiantesX
|| bCreateTextureCoordiantesY
, aTexTransform
);
99 const basegfx::B3DRange
aRange(getRangeFrom3DGeometry(aFill
));
102 if(getSdrLFSAttribute().getFill())
104 if(::com::sun::star::drawing::NormalsKind_SPHERE
== eNormalsKind
)
106 applyNormalsKindSphereTo3DGeometry(aFill
, aRange
);
108 else if(::com::sun::star::drawing::NormalsKind_FLAT
== eNormalsKind
)
110 applyNormalsKindFlatTo3DGeometry(aFill
);
113 if(getSdr3DObjectAttribute().getNormalsInvert())
115 applyNormalsInvertTo3DGeometry(aFill
);
119 // texture coordinates
120 if(getSdrLFSAttribute().getFill())
122 applyTextureTo3DGeometry(
123 getSdr3DObjectAttribute().getTextureProjectionX(),
124 getSdr3DObjectAttribute().getTextureProjectionY(),
130 if(getSdrLFSAttribute().getFill())
133 aRetval
= create3DPolyPolygonFillPrimitives(
137 getSdr3DObjectAttribute(),
138 *getSdrLFSAttribute().getFill(),
139 getSdrLFSAttribute().getFillFloatTransGradient());
143 // create simplified 3d hit test geometry
144 const attribute::SdrFillAttribute
aSimplifiedFillAttribute(0.0, basegfx::BColor(), 0, 0, 0);
146 aRetval
= create3DPolyPolygonFillPrimitives(
150 getSdr3DObjectAttribute(),
151 aSimplifiedFillAttribute
,
154 // encapsulate in HitTestPrimitive3D and add
155 const Primitive3DReference
xRef(new HitTestPrimitive3D(aRetval
));
156 aRetval
= Primitive3DSequence(&xRef
, 1L);
160 if(getSdrLFSAttribute().getLine())
162 if(getSdr3DObjectAttribute().getReducedLineGeometry())
164 // create geometric outlines with reduced line geometry for chart
165 const basegfx::B3DPolyPolygon
aHorLine(extractHorizontalLinesFromSlice(rSliceVector
, bClosedRotation
));
166 const sal_uInt32
nCount(aHorLine
.count());
167 basegfx::B3DPolyPolygon aNewLineGeometry
;
169 for(a
= 1; a
< nCount
; a
++)
171 // for each loop pair create the connection edges
172 createReducedOutlines(
175 aHorLine
.getB3DPolygon(a
- 1),
176 aHorLine
.getB3DPolygon(a
),
180 for(a
= 0; a
< nCount
; a
++)
182 // filter hor lines for empty loops (those who have their defining point on the Y-Axis)
183 basegfx::B3DPolygon
aCandidate(aHorLine
.getB3DPolygon(a
));
184 aCandidate
.removeDoublePoints();
186 if(aCandidate
.count())
188 aNewLineGeometry
.append(aCandidate
);
192 if(aNewLineGeometry
.count())
194 const Primitive3DSequence
aLines(create3DPolyPolygonLinePrimitives(aNewLineGeometry
, getTransform(), *getSdrLFSAttribute().getLine()));
195 appendPrimitive3DSequenceToPrimitive3DSequence(aRetval
, aLines
);
200 // extract line geometry from slices
201 const basegfx::B3DPolyPolygon
aHorLine(extractHorizontalLinesFromSlice(rSliceVector
, bClosedRotation
));
202 const basegfx::B3DPolyPolygon
aVerLine(extractVerticalLinesFromSlice(rSliceVector
));
204 // add horizontal lines
205 const Primitive3DSequence
aHorLines(create3DPolyPolygonLinePrimitives(aHorLine
, getTransform(), *getSdrLFSAttribute().getLine()));
206 appendPrimitive3DSequenceToPrimitive3DSequence(aRetval
, aHorLines
);
208 // add vertical lines
209 const Primitive3DSequence
aVerLines(create3DPolyPolygonLinePrimitives(aVerLine
, getTransform(), *getSdrLFSAttribute().getLine()));
210 appendPrimitive3DSequenceToPrimitive3DSequence(aRetval
, aVerLines
);
215 if(getSdrLFSAttribute().getShadow() && aRetval
.hasElements())
217 const Primitive3DSequence
aShadow(createShadowPrimitive3D(aRetval
, *getSdrLFSAttribute().getShadow(), getSdr3DObjectAttribute().getShadow3D()));
218 appendPrimitive3DSequenceToPrimitive3DSequence(aRetval
, aShadow
);
225 void SdrLathePrimitive3D::impCreateSlices()
227 // prepare the polygon. No double points, correct orientations and a correct
228 // outmost polygon are needed
229 maCorrectedPolyPolygon
= basegfx::tools::adaptiveSubdivideByAngle(getPolyPolygon());
230 maCorrectedPolyPolygon
.removeDoublePoints();
231 maCorrectedPolyPolygon
= basegfx::tools::correctOrientations(maCorrectedPolyPolygon
);
232 maCorrectedPolyPolygon
= basegfx::tools::correctOutmostPolygon(maCorrectedPolyPolygon
);
234 // check edge count of first sub-polygon. If different, reSegment polyPolygon. This ensures
235 // that for polyPolygons, the subPolys 1..n only get reSegmented when polygon 0L is different
236 // at all (and not always)
237 const basegfx::B2DPolygon
aSubCandidate(maCorrectedPolyPolygon
.getB2DPolygon(0));
238 const sal_uInt32
nSubEdgeCount(aSubCandidate
.isClosed() ? aSubCandidate
.count() : (aSubCandidate
.count() ? aSubCandidate
.count() - 1L : 0L));
240 if(nSubEdgeCount
!= getVerticalSegments())
242 maCorrectedPolyPolygon
= basegfx::tools::reSegmentPolyPolygon(maCorrectedPolyPolygon
, getVerticalSegments());
245 // prepare slices as geometry
246 createLatheSlices(maSlices
, maCorrectedPolyPolygon
, getBackScale(), getDiagonal(), getRotation(), getHorizontalSegments(), getCharacterMode(), getCloseFront(), getCloseBack());
249 const Slice3DVector
& SdrLathePrimitive3D::getSlices() const
251 // This can be made dependent of getSdrLFSAttribute().getFill() and getSdrLFSAttribute().getLine()
252 // again when no longer geometry is needed for non-visible 3D objects as it is now for chart
253 if(getPolyPolygon().count() && !maSlices
.size())
255 ::osl::Mutex m_mutex
;
256 const_cast< SdrLathePrimitive3D
& >(*this).impCreateSlices();
262 SdrLathePrimitive3D::SdrLathePrimitive3D(
263 const basegfx::B3DHomMatrix
& rTransform
,
264 const basegfx::B2DVector
& rTextureSize
,
265 const attribute::SdrLineFillShadowAttribute
& rSdrLFSAttribute
,
266 const attribute::Sdr3DObjectAttribute
& rSdr3DObjectAttribute
,
267 const basegfx::B2DPolyPolygon
& rPolyPolygon
,
268 sal_uInt32 nHorizontalSegments
,
269 sal_uInt32 nVerticalSegments
,
274 bool bSmoothHorizontalNormals
,
279 : SdrPrimitive3D(rTransform
, rTextureSize
, rSdrLFSAttribute
, rSdr3DObjectAttribute
),
280 maCorrectedPolyPolygon(),
282 maPolyPolygon(rPolyPolygon
),
283 mnHorizontalSegments(nHorizontalSegments
),
284 mnVerticalSegments(nVerticalSegments
),
285 mfDiagonal(fDiagonal
),
286 mfBackScale(fBackScale
),
287 mfRotation(fRotation
),
288 mpLastRLGViewInformation(0),
289 mbSmoothNormals(bSmoothNormals
),
290 mbSmoothHorizontalNormals(bSmoothHorizontalNormals
),
291 mbSmoothLids(bSmoothLids
),
292 mbCharacterMode(bCharacterMode
),
293 mbCloseFront(bCloseFront
),
294 mbCloseBack(bCloseBack
)
296 // make sure Rotation is positive
297 if(basegfx::fTools::lessOrEqual(getRotation(), 0.0))
302 // make sure the percentage value getDiagonal() is between 0.0 and 1.0
303 if(basegfx::fTools::lessOrEqual(getDiagonal(), 0.0))
307 else if(basegfx::fTools::moreOrEqual(getDiagonal(), 1.0))
312 // no close front/back when polygon is not closed
313 if(getPolyPolygon().count() && !getPolyPolygon().getB2DPolygon(0L).isClosed())
315 mbCloseFront
= mbCloseBack
= false;
318 // no edge rounding when not closing
319 if(!getCloseFront() && !getCloseBack())
325 SdrLathePrimitive3D::~SdrLathePrimitive3D()
327 if(mpLastRLGViewInformation
)
329 delete mpLastRLGViewInformation
;
333 bool SdrLathePrimitive3D::operator==(const BasePrimitive3D
& rPrimitive
) const
335 if(SdrPrimitive3D::operator==(rPrimitive
))
337 const SdrLathePrimitive3D
& rCompare
= static_cast< const SdrLathePrimitive3D
& >(rPrimitive
);
339 return (getPolyPolygon() == rCompare
.getPolyPolygon()
340 && getHorizontalSegments() == rCompare
.getHorizontalSegments()
341 && getVerticalSegments() == rCompare
.getVerticalSegments()
342 && getDiagonal() == rCompare
.getDiagonal()
343 && getBackScale() == rCompare
.getBackScale()
344 && getRotation() == rCompare
.getRotation()
345 && getSmoothNormals() == rCompare
.getSmoothNormals()
346 && getSmoothHorizontalNormals() == rCompare
.getSmoothHorizontalNormals()
347 && getSmoothLids() == rCompare
.getSmoothLids()
348 && getCharacterMode() == rCompare
.getCharacterMode()
349 && getCloseFront() == rCompare
.getCloseFront()
350 && getCloseBack() == rCompare
.getCloseBack());
356 basegfx::B3DRange
SdrLathePrimitive3D::getB3DRange(const geometry::ViewInformation3D
& /*rViewInformation*/) const
358 // use defaut from sdrPrimitive3D which uses transformation expanded by line width/2
359 // The parent implementation which uses the ranges of the decomposition would be more
360 // corrcet, but for historical reasons it is necessary to do the old method: To get
361 // the range of the non-transformed geometry and transform it then. This leads to different
362 // ranges where the new method is more correct, but the need to keep the old behaviour
363 // has priority here.
364 return get3DRangeFromSlices(getSlices());
367 Primitive3DSequence
SdrLathePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D
& rViewInformation
) const
369 if(getSdr3DObjectAttribute().getReducedLineGeometry())
371 if(!mpLastRLGViewInformation
||
372 (getLocalDecomposition().hasElements()
373 && *mpLastRLGViewInformation
!= rViewInformation
))
375 // conditions of last local decomposition with reduced lines have changed. Remember
376 // new one and clear current decompositiopn
377 ::osl::Mutex m_mutex
;
378 SdrLathePrimitive3D
* pThat
= const_cast< SdrLathePrimitive3D
* >(this);
379 pThat
->setLocalDecomposition(Primitive3DSequence());
380 delete pThat
->mpLastRLGViewInformation
;
381 pThat
->mpLastRLGViewInformation
= new geometry::ViewInformation3D(rViewInformation
);
385 // no test for buffering needed, call parent
386 return SdrPrimitive3D::get3DDecomposition(rViewInformation
);
390 ImplPrimitrive3DIDBlock(SdrLathePrimitive3D
, PRIMITIVE3D_ID_SDRLATHEPRIMITIVE3D
)
392 } // end of namespace primitive3d
393 } // end of namespace drawinglayer
395 //////////////////////////////////////////////////////////////////////////////