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_svx.hxx" 26 27 #include <svx/sdr/contact/viewcontactofe3d.hxx> 28 #include <svx/sdr/contact/viewobjectcontactofe3d.hxx> 29 #include <svx/obj3d.hxx> 30 #include <drawinglayer/primitive2d/embedded3dprimitive2d.hxx> 31 #include <svx/sdr/contact/viewcontactofe3dscene.hxx> 32 #include <svx/scene3d.hxx> 33 #include <drawinglayer/primitive3d/transformprimitive3d.hxx> 34 #include <drawinglayer/attribute/sdrsceneattribute3d.hxx> 35 #include <drawinglayer/attribute/sdrlightingattribute3d.hxx> 36 #include <drawinglayer/attribute/sdrlightattribute3d.hxx> 37 #include <drawinglayer/attribute/sdrlineattribute.hxx> 38 39 ////////////////////////////////////////////////////////////////////////////// 40 41 namespace 42 { tryToFindVCOfE3DScene(const sdr::contact::ViewContact & rCandidate,basegfx::B3DHomMatrix & o_rInBetweenObjectTransform)43 const sdr::contact::ViewContactOfE3dScene* tryToFindVCOfE3DScene( 44 const sdr::contact::ViewContact& rCandidate, 45 basegfx::B3DHomMatrix& o_rInBetweenObjectTransform) 46 { 47 const sdr::contact::ViewContactOfE3dScene* pSceneParent = 48 dynamic_cast< const sdr::contact::ViewContactOfE3dScene* >(rCandidate.GetParentContact()); 49 50 if(pSceneParent) 51 { 52 // each 3d object (including in-between scenes) should have a scene as parent 53 const sdr::contact::ViewContactOfE3dScene* pSceneParentParent = 54 dynamic_cast< const sdr::contact::ViewContactOfE3dScene* >(pSceneParent->GetParentContact()); 55 56 if(pSceneParentParent) 57 { 58 // the parent scene of rCandidate is a in-between scene, call recursively and collect 59 // the in-between scene's object transformation part in o_rInBetweenObjectTransform 60 const basegfx::B3DHomMatrix& rSceneParentTransform = pSceneParent->GetE3dScene().GetTransform(); 61 o_rInBetweenObjectTransform = rSceneParentTransform * o_rInBetweenObjectTransform; 62 return tryToFindVCOfE3DScene(*pSceneParent, o_rInBetweenObjectTransform); 63 } 64 else 65 { 66 // the parent scene is the outmost scene 67 return pSceneParent; 68 } 69 } 70 71 // object hierarchy structure is incorrect; no result 72 return 0; 73 } 74 } // end of anonymous namespace 75 76 ////////////////////////////////////////////////////////////////////////////// 77 78 namespace sdr 79 { 80 namespace contact 81 { impCreateWithGivenPrimitive3DSequence(const drawinglayer::primitive3d::Primitive3DSequence & rxContent3D) const82 drawinglayer::primitive2d::Primitive2DSequence ViewContactOfE3d::impCreateWithGivenPrimitive3DSequence( 83 const drawinglayer::primitive3d::Primitive3DSequence& rxContent3D) const 84 { 85 drawinglayer::primitive2d::Primitive2DSequence xRetval; 86 87 if(rxContent3D.hasElements()) 88 { 89 // try to get the outmost ViewObjectContactOfE3dScene for this single 3d object, 90 // the ones on the way there are grouping scenes. Collect the in-between scene's 91 // transformations to build a correct object transformation for the embedded 92 // object 93 basegfx::B3DHomMatrix aInBetweenObjectTransform; 94 const ViewContactOfE3dScene* pVCOfE3DScene = tryToFindVCOfE3DScene(*this, aInBetweenObjectTransform); 95 96 if(pVCOfE3DScene) 97 { 98 basegfx::B3DVector aLightNormal; 99 const double fShadowSlant(pVCOfE3DScene->getSdrSceneAttribute().getShadowSlant()); 100 const basegfx::B3DRange& rAllContentRange = pVCOfE3DScene->getAllContentRange3D(); 101 drawinglayer::geometry::ViewInformation3D aViewInformation3D(pVCOfE3DScene->getViewInformation3D()); 102 103 if(pVCOfE3DScene->getSdrLightingAttribute().getLightVector().size()) 104 { 105 // get light normal from first light and normalize 106 aLightNormal = pVCOfE3DScene->getSdrLightingAttribute().getLightVector()[0].getDirection(); 107 aLightNormal.normalize(); 108 } 109 110 if(!aInBetweenObjectTransform.isIdentity()) 111 { 112 // if aInBetweenObjectTransform is used, create combined ViewInformation3D which 113 // contains the correct object transformation for the embedded 3d object 114 aViewInformation3D = drawinglayer::geometry::ViewInformation3D( 115 aViewInformation3D.getObjectTransformation() * aInBetweenObjectTransform, 116 aViewInformation3D.getOrientation(), 117 aViewInformation3D.getProjection(), 118 aViewInformation3D.getDeviceToView(), 119 aViewInformation3D.getViewTime(), 120 aViewInformation3D.getExtendedInformationSequence()); 121 } 122 123 // create embedded 2d primitive and add. LightNormal and ShadowSlant are needed for evtl. 124 // 3D shadow extraction for correct B2DRange calculation (shadow is part of the object) 125 const drawinglayer::primitive2d::Primitive2DReference xReference( 126 new drawinglayer::primitive2d::Embedded3DPrimitive2D( 127 rxContent3D, 128 pVCOfE3DScene->getObjectTransformation(), 129 aViewInformation3D, 130 aLightNormal, 131 fShadowSlant, 132 rAllContentRange)); 133 134 xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1); 135 } 136 } 137 138 return xRetval; 139 } 140 ViewContactOfE3d(E3dObject & rSdrObject)141 ViewContactOfE3d::ViewContactOfE3d(E3dObject& rSdrObject) 142 : ViewContactOfSdrObj(rSdrObject) 143 { 144 } 145 ~ViewContactOfE3d()146 ViewContactOfE3d::~ViewContactOfE3d() 147 { 148 } 149 getVIP3DSWithoutObjectTransform() const150 drawinglayer::primitive3d::Primitive3DSequence ViewContactOfE3d::getVIP3DSWithoutObjectTransform() const 151 { 152 // local up-to-date checks. Create new list and compare. 153 drawinglayer::primitive3d::Primitive3DSequence xNew(createViewIndependentPrimitive3DSequence()); 154 155 if(!drawinglayer::primitive3d::arePrimitive3DSequencesEqual(mxViewIndependentPrimitive3DSequence, xNew)) 156 { 157 // has changed, copy content 158 const_cast< ViewContactOfE3d* >(this)->mxViewIndependentPrimitive3DSequence = xNew; 159 } 160 161 // return current Primitive2DSequence 162 return mxViewIndependentPrimitive3DSequence; 163 } 164 getViewIndependentPrimitive3DSequence() const165 drawinglayer::primitive3d::Primitive3DSequence ViewContactOfE3d::getViewIndependentPrimitive3DSequence() const 166 { 167 // get sequence without object transform 168 drawinglayer::primitive3d::Primitive3DSequence xRetval(getVIP3DSWithoutObjectTransform()); 169 170 if(xRetval.hasElements()) 171 { 172 // add object transform if it's used 173 const basegfx::B3DHomMatrix& rObjectTransform(GetE3dObject().GetTransform()); 174 175 if(!rObjectTransform.isIdentity()) 176 { 177 const drawinglayer::primitive3d::Primitive3DReference xReference( 178 new drawinglayer::primitive3d::TransformPrimitive3D( 179 rObjectTransform, 180 xRetval)); 181 182 xRetval = drawinglayer::primitive3d::Primitive3DSequence(&xReference, 1); 183 } 184 } 185 186 // return current Primitive2DSequence 187 return xRetval; 188 } 189 createViewIndependentPrimitive2DSequence() const190 drawinglayer::primitive2d::Primitive2DSequence ViewContactOfE3d::createViewIndependentPrimitive2DSequence() const 191 { 192 // also need to create a 2D embedding when the view-independent part is requested, 193 // see view-dependent part in ViewObjectContactOfE3d::createPrimitive2DSequence 194 // get 3d primitive vector, isPrimitiveVisible() is done in 3d creator 195 return impCreateWithGivenPrimitive3DSequence(getViewIndependentPrimitive3DSequence()); 196 } 197 CreateObjectSpecificViewObjectContact(ObjectContact & rObjectContact)198 ViewObjectContact& ViewContactOfE3d::CreateObjectSpecificViewObjectContact(ObjectContact& rObjectContact) 199 { 200 ViewObjectContact* pRetval = new ViewObjectContactOfE3d(rObjectContact, *this); 201 DBG_ASSERT(pRetval, "ViewContactOfE3d::CreateObjectSpecificViewObjectContact() failed (!)"); 202 203 return *pRetval; 204 } 205 impCreateFallbackLineAttribute(const basegfx::BColor & rBColor) const206 drawinglayer::attribute::SdrLineAttribute* ViewContactOfE3d::impCreateFallbackLineAttribute(const basegfx::BColor& rBColor) const 207 { 208 static bool bFallbackToCreateAsLineForTest(false); 209 210 if(bFallbackToCreateAsLineForTest) 211 { 212 return new drawinglayer::attribute::SdrLineAttribute(rBColor); 213 } 214 else 215 { 216 return 0; 217 } 218 } 219 } // end of namespace contact 220 } // end of namespace sdr 221 222 ////////////////////////////////////////////////////////////////////////////// 223 // eof 224