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