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