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