1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <drawinglayer/primitive3d/sdrsphereprimitive3d.hxx>
32*cdf0e10cSrcweir #include <basegfx/polygon/b3dpolypolygontools.hxx>
33*cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
34*cdf0e10cSrcweir #include <basegfx/polygon/b3dpolygon.hxx>
35*cdf0e10cSrcweir #include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx>
36*cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx>
37*cdf0e10cSrcweir #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
38*cdf0e10cSrcweir #include <drawinglayer/attribute/sdrfillattribute.hxx>
39*cdf0e10cSrcweir #include <drawinglayer/attribute/sdrlineattribute.hxx>
40*cdf0e10cSrcweir #include <drawinglayer/attribute/sdrshadowattribute.hxx>
41*cdf0e10cSrcweir 
42*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
43*cdf0e10cSrcweir 
44*cdf0e10cSrcweir using namespace com::sun::star;
45*cdf0e10cSrcweir 
46*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
47*cdf0e10cSrcweir 
48*cdf0e10cSrcweir namespace drawinglayer
49*cdf0e10cSrcweir {
50*cdf0e10cSrcweir 	namespace primitive3d
51*cdf0e10cSrcweir 	{
52*cdf0e10cSrcweir 		Primitive3DSequence SdrSpherePrimitive3D::create3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
53*cdf0e10cSrcweir 		{
54*cdf0e10cSrcweir 			Primitive3DSequence aRetval;
55*cdf0e10cSrcweir 			const basegfx::B3DRange aUnitRange(0.0, 0.0, 0.0, 1.0, 1.0, 1.0);
56*cdf0e10cSrcweir 			const bool bCreateNormals(::com::sun::star::drawing::NormalsKind_SPECIFIC == getSdr3DObjectAttribute().getNormalsKind()
57*cdf0e10cSrcweir 				|| ::com::sun::star::drawing::NormalsKind_SPHERE == getSdr3DObjectAttribute().getNormalsKind());
58*cdf0e10cSrcweir 
59*cdf0e10cSrcweir 			// create unit geometry
60*cdf0e10cSrcweir 			basegfx::B3DPolyPolygon aFill(basegfx::tools::createSphereFillPolyPolygonFromB3DRange(aUnitRange,
61*cdf0e10cSrcweir 				getHorizontalSegments(), getVerticalSegments(), bCreateNormals));
62*cdf0e10cSrcweir 
63*cdf0e10cSrcweir 			// normal inversion
64*cdf0e10cSrcweir 			if(!getSdrLFSAttribute().getFill().isDefault()
65*cdf0e10cSrcweir 				&& bCreateNormals
66*cdf0e10cSrcweir 				&& getSdr3DObjectAttribute().getNormalsInvert()
67*cdf0e10cSrcweir 				&& aFill.areNormalsUsed())
68*cdf0e10cSrcweir 			{
69*cdf0e10cSrcweir 				// invert normals
70*cdf0e10cSrcweir 				aFill = basegfx::tools::invertNormals(aFill);
71*cdf0e10cSrcweir 			}
72*cdf0e10cSrcweir 
73*cdf0e10cSrcweir 			// texture coordinates
74*cdf0e10cSrcweir 			if(!getSdrLFSAttribute().getFill().isDefault())
75*cdf0e10cSrcweir 			{
76*cdf0e10cSrcweir 				// handle texture coordinates X
77*cdf0e10cSrcweir 				const bool bParallelX(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionX());
78*cdf0e10cSrcweir 				const bool bObjectSpecificX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX());
79*cdf0e10cSrcweir 				const bool bSphereX(::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionX());
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir 				// handle texture coordinates Y
82*cdf0e10cSrcweir 				const bool bParallelY(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionY());
83*cdf0e10cSrcweir 				const bool bObjectSpecificY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY());
84*cdf0e10cSrcweir 				const bool bSphereY(::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionY());
85*cdf0e10cSrcweir 
86*cdf0e10cSrcweir 				if(bParallelX || bParallelY)
87*cdf0e10cSrcweir 				{
88*cdf0e10cSrcweir 					// apply parallel texture coordinates in X and/or Y
89*cdf0e10cSrcweir 					const basegfx::B3DRange aRange(basegfx::tools::getRange(aFill));
90*cdf0e10cSrcweir 					aFill = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFill, aRange, bParallelX, bParallelY);
91*cdf0e10cSrcweir 				}
92*cdf0e10cSrcweir 
93*cdf0e10cSrcweir 				if(bSphereX || bObjectSpecificX || bSphereY || bObjectSpecificY)
94*cdf0e10cSrcweir 				{
95*cdf0e10cSrcweir 					double fRelativeAngle(0.0);
96*cdf0e10cSrcweir 
97*cdf0e10cSrcweir 					if(bObjectSpecificX)
98*cdf0e10cSrcweir 					{
99*cdf0e10cSrcweir 						// Since the texture coordinates are (for historical reasons)
100*cdf0e10cSrcweir 						// different from forced to sphere texture coordinates,
101*cdf0e10cSrcweir 						// create a old version from it by rotating to old state before applying
102*cdf0e10cSrcweir 						// the texture coordinates to emulate old behaviour
103*cdf0e10cSrcweir 						fRelativeAngle = F_2PI * ((double)((getHorizontalSegments() >> 1L)  - 1L) / (double)getHorizontalSegments());
104*cdf0e10cSrcweir 						basegfx::B3DHomMatrix aRot;
105*cdf0e10cSrcweir 						aRot.rotate(0.0, fRelativeAngle, 0.0);
106*cdf0e10cSrcweir 						aFill.transform(aRot);
107*cdf0e10cSrcweir 					}
108*cdf0e10cSrcweir 
109*cdf0e10cSrcweir 					// apply spherical texture coordinates in X and/or Y
110*cdf0e10cSrcweir 					const basegfx::B3DRange aRange(basegfx::tools::getRange(aFill));
111*cdf0e10cSrcweir 					const basegfx::B3DPoint aCenter(aRange.getCenter());
112*cdf0e10cSrcweir 					aFill = basegfx::tools::applyDefaultTextureCoordinatesSphere(aFill, aCenter,
113*cdf0e10cSrcweir 						bSphereX || bObjectSpecificX, bSphereY || bObjectSpecificY);
114*cdf0e10cSrcweir 
115*cdf0e10cSrcweir 					if(bObjectSpecificX)
116*cdf0e10cSrcweir 					{
117*cdf0e10cSrcweir 						// rotate back again
118*cdf0e10cSrcweir 						basegfx::B3DHomMatrix aRot;
119*cdf0e10cSrcweir 						aRot.rotate(0.0, -fRelativeAngle, 0.0);
120*cdf0e10cSrcweir 						aFill.transform(aRot);
121*cdf0e10cSrcweir 					}
122*cdf0e10cSrcweir 				}
123*cdf0e10cSrcweir 
124*cdf0e10cSrcweir 				// transform texture coordinates to texture size
125*cdf0e10cSrcweir 				basegfx::B2DHomMatrix aTexMatrix;
126*cdf0e10cSrcweir 				aTexMatrix.scale(getTextureSize().getX(), getTextureSize().getY());
127*cdf0e10cSrcweir 				aFill.transformTextureCoordiantes(aTexMatrix);
128*cdf0e10cSrcweir 			}
129*cdf0e10cSrcweir 
130*cdf0e10cSrcweir 			// build vector of PolyPolygons
131*cdf0e10cSrcweir 			::std::vector< basegfx::B3DPolyPolygon > a3DPolyPolygonVector;
132*cdf0e10cSrcweir 
133*cdf0e10cSrcweir 			for(sal_uInt32 a(0L); a < aFill.count(); a++)
134*cdf0e10cSrcweir 			{
135*cdf0e10cSrcweir 				a3DPolyPolygonVector.push_back(basegfx::B3DPolyPolygon(aFill.getB3DPolygon(a)));
136*cdf0e10cSrcweir 			}
137*cdf0e10cSrcweir 
138*cdf0e10cSrcweir 			if(!getSdrLFSAttribute().getFill().isDefault())
139*cdf0e10cSrcweir 			{
140*cdf0e10cSrcweir 				// add fill
141*cdf0e10cSrcweir 				aRetval = create3DPolyPolygonFillPrimitives(
142*cdf0e10cSrcweir 					a3DPolyPolygonVector,
143*cdf0e10cSrcweir 					getTransform(),
144*cdf0e10cSrcweir 					getTextureSize(),
145*cdf0e10cSrcweir 					getSdr3DObjectAttribute(),
146*cdf0e10cSrcweir 					getSdrLFSAttribute().getFill(),
147*cdf0e10cSrcweir 					getSdrLFSAttribute().getFillFloatTransGradient());
148*cdf0e10cSrcweir 			}
149*cdf0e10cSrcweir 			else
150*cdf0e10cSrcweir 			{
151*cdf0e10cSrcweir 				// create simplified 3d hit test geometry
152*cdf0e10cSrcweir                 aRetval = createHiddenGeometryPrimitives3D(
153*cdf0e10cSrcweir 			        a3DPolyPolygonVector,
154*cdf0e10cSrcweir 			        getTransform(),
155*cdf0e10cSrcweir 			        getTextureSize(),
156*cdf0e10cSrcweir 			        getSdr3DObjectAttribute());
157*cdf0e10cSrcweir 			}
158*cdf0e10cSrcweir 
159*cdf0e10cSrcweir 			// add line
160*cdf0e10cSrcweir 			if(!getSdrLFSAttribute().getLine().isDefault())
161*cdf0e10cSrcweir 			{
162*cdf0e10cSrcweir 				basegfx::B3DPolyPolygon aSphere(basegfx::tools::createSpherePolyPolygonFromB3DRange(aUnitRange, getHorizontalSegments(), getVerticalSegments()));
163*cdf0e10cSrcweir 				const Primitive3DSequence aLines(create3DPolyPolygonLinePrimitives(
164*cdf0e10cSrcweir                     aSphere, getTransform(), getSdrLFSAttribute().getLine()));
165*cdf0e10cSrcweir 				appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aLines);
166*cdf0e10cSrcweir 			}
167*cdf0e10cSrcweir 
168*cdf0e10cSrcweir 			// add shadow
169*cdf0e10cSrcweir 			if(!getSdrLFSAttribute().getShadow().isDefault()
170*cdf0e10cSrcweir                 && aRetval.hasElements())
171*cdf0e10cSrcweir 			{
172*cdf0e10cSrcweir 				const Primitive3DSequence aShadow(createShadowPrimitive3D(
173*cdf0e10cSrcweir                     aRetval, getSdrLFSAttribute().getShadow(), getSdr3DObjectAttribute().getShadow3D()));
174*cdf0e10cSrcweir 				appendPrimitive3DSequenceToPrimitive3DSequence(aRetval, aShadow);
175*cdf0e10cSrcweir 			}
176*cdf0e10cSrcweir 
177*cdf0e10cSrcweir 			return aRetval;
178*cdf0e10cSrcweir 		}
179*cdf0e10cSrcweir 
180*cdf0e10cSrcweir 		SdrSpherePrimitive3D::SdrSpherePrimitive3D(
181*cdf0e10cSrcweir 			const basegfx::B3DHomMatrix& rTransform,
182*cdf0e10cSrcweir 			const basegfx::B2DVector& rTextureSize,
183*cdf0e10cSrcweir 			const attribute::SdrLineFillShadowAttribute3D& rSdrLFSAttribute,
184*cdf0e10cSrcweir 			const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute,
185*cdf0e10cSrcweir 			sal_uInt32 nHorizontalSegments,
186*cdf0e10cSrcweir 			sal_uInt32 nVerticalSegments)
187*cdf0e10cSrcweir 		:	SdrPrimitive3D(rTransform, rTextureSize, rSdrLFSAttribute, rSdr3DObjectAttribute),
188*cdf0e10cSrcweir 			mnHorizontalSegments(nHorizontalSegments),
189*cdf0e10cSrcweir 			mnVerticalSegments(nVerticalSegments)
190*cdf0e10cSrcweir 		{
191*cdf0e10cSrcweir 		}
192*cdf0e10cSrcweir 
193*cdf0e10cSrcweir 		bool SdrSpherePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
194*cdf0e10cSrcweir 		{
195*cdf0e10cSrcweir 			if(SdrPrimitive3D::operator==(rPrimitive))
196*cdf0e10cSrcweir 			{
197*cdf0e10cSrcweir 				const SdrSpherePrimitive3D& rCompare = static_cast< const SdrSpherePrimitive3D& >(rPrimitive);
198*cdf0e10cSrcweir 
199*cdf0e10cSrcweir 				return (getHorizontalSegments() == rCompare.getHorizontalSegments()
200*cdf0e10cSrcweir 					&& getVerticalSegments() == rCompare.getVerticalSegments());
201*cdf0e10cSrcweir 			}
202*cdf0e10cSrcweir 
203*cdf0e10cSrcweir 			return false;
204*cdf0e10cSrcweir 		}
205*cdf0e10cSrcweir 
206*cdf0e10cSrcweir 		basegfx::B3DRange SdrSpherePrimitive3D::getB3DRange(const geometry::ViewInformation3D& /*rViewInformation*/) const
207*cdf0e10cSrcweir 		{
208*cdf0e10cSrcweir 			// use defaut from sdrPrimitive3D which uses transformation expanded by line width/2
209*cdf0e10cSrcweir 			// The parent implementation which uses the ranges of the decomposition would be more
210*cdf0e10cSrcweir 			// corrcet, but for historical reasons it is necessary to do the old method: To get
211*cdf0e10cSrcweir 			// the range of the non-transformed geometry and transform it then. This leads to different
212*cdf0e10cSrcweir 			// ranges where the new method is more correct, but the need to keep the old behaviour
213*cdf0e10cSrcweir 			// has priority here.
214*cdf0e10cSrcweir 			return getStandard3DRange();
215*cdf0e10cSrcweir 		}
216*cdf0e10cSrcweir 
217*cdf0e10cSrcweir 		// provide unique ID
218*cdf0e10cSrcweir 		ImplPrimitrive3DIDBlock(SdrSpherePrimitive3D, PRIMITIVE3D_ID_SDRSPHEREPRIMITIVE3D)
219*cdf0e10cSrcweir 
220*cdf0e10cSrcweir 	} // end of namespace primitive3d
221*cdf0e10cSrcweir } // end of namespace drawinglayer
222*cdf0e10cSrcweir 
223*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
224*cdf0e10cSrcweir // eof
225