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