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