1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_svx.hxx" 30 31 #include <svx/sdr/contact/viewcontactofe3d.hxx> 32 #include <svx/sdr/contact/viewobjectcontactofe3d.hxx> 33 #include <svx/obj3d.hxx> 34 #include <drawinglayer/primitive2d/embedded3dprimitive2d.hxx> 35 #include <svx/sdr/contact/viewcontactofe3dscene.hxx> 36 #include <svx/scene3d.hxx> 37 #include <drawinglayer/primitive3d/transformprimitive3d.hxx> 38 #include <drawinglayer/attribute/sdrsceneattribute3d.hxx> 39 #include <drawinglayer/attribute/sdrlightingattribute3d.hxx> 40 #include <drawinglayer/attribute/sdrlightattribute3d.hxx> 41 #include <drawinglayer/attribute/sdrlineattribute.hxx> 42 43 ////////////////////////////////////////////////////////////////////////////// 44 45 namespace 46 { 47 const sdr::contact::ViewContactOfE3dScene* tryToFindVCOfE3DScene( 48 const sdr::contact::ViewContact& rCandidate, 49 basegfx::B3DHomMatrix& o_rInBetweenObjectTransform) 50 { 51 const sdr::contact::ViewContactOfE3dScene* pSceneParent = 52 dynamic_cast< const sdr::contact::ViewContactOfE3dScene* >(rCandidate.GetParentContact()); 53 54 if(pSceneParent) 55 { 56 // each 3d object (including in-between scenes) should have a scene as parent 57 const sdr::contact::ViewContactOfE3dScene* pSceneParentParent = 58 dynamic_cast< const sdr::contact::ViewContactOfE3dScene* >(pSceneParent->GetParentContact()); 59 60 if(pSceneParentParent) 61 { 62 // the parent scene of rCandidate is a in-between scene, call recursively and collect 63 // the in-between scene's object transformation part in o_rInBetweenObjectTransform 64 const basegfx::B3DHomMatrix& rSceneParentTransform = pSceneParent->GetE3dScene().GetTransform(); 65 o_rInBetweenObjectTransform = rSceneParentTransform * o_rInBetweenObjectTransform; 66 return tryToFindVCOfE3DScene(*pSceneParent, o_rInBetweenObjectTransform); 67 } 68 else 69 { 70 // the parent scene is the outmost scene 71 return pSceneParent; 72 } 73 } 74 75 // object hierarchy structure is incorrect; no result 76 return 0; 77 } 78 } // end of anonymous namespace 79 80 ////////////////////////////////////////////////////////////////////////////// 81 82 namespace sdr 83 { 84 namespace contact 85 { 86 drawinglayer::primitive2d::Primitive2DSequence ViewContactOfE3d::impCreateWithGivenPrimitive3DSequence( 87 const drawinglayer::primitive3d::Primitive3DSequence& rxContent3D) const 88 { 89 drawinglayer::primitive2d::Primitive2DSequence xRetval; 90 91 if(rxContent3D.hasElements()) 92 { 93 // try to get the outmost ViewObjectContactOfE3dScene for this single 3d object, 94 // the ones on the way there are grouping scenes. Collect the in-between scene's 95 // transformations to build a correct object transformation for the embedded 96 // object 97 basegfx::B3DHomMatrix aInBetweenObjectTransform; 98 const ViewContactOfE3dScene* pVCOfE3DScene = tryToFindVCOfE3DScene(*this, aInBetweenObjectTransform); 99 100 if(pVCOfE3DScene) 101 { 102 basegfx::B3DVector aLightNormal; 103 const double fShadowSlant(pVCOfE3DScene->getSdrSceneAttribute().getShadowSlant()); 104 const basegfx::B3DRange& rAllContentRange = pVCOfE3DScene->getAllContentRange3D(); 105 drawinglayer::geometry::ViewInformation3D aViewInformation3D(pVCOfE3DScene->getViewInformation3D()); 106 107 if(pVCOfE3DScene->getSdrLightingAttribute().getLightVector().size()) 108 { 109 // get light normal from first light and normalize 110 aLightNormal = pVCOfE3DScene->getSdrLightingAttribute().getLightVector()[0].getDirection(); 111 aLightNormal.normalize(); 112 } 113 114 if(!aInBetweenObjectTransform.isIdentity()) 115 { 116 // if aInBetweenObjectTransform is used, create combined ViewInformation3D which 117 // contains the correct object transformation for the embedded 3d object 118 aViewInformation3D = drawinglayer::geometry::ViewInformation3D( 119 aViewInformation3D.getObjectTransformation() * aInBetweenObjectTransform, 120 aViewInformation3D.getOrientation(), 121 aViewInformation3D.getProjection(), 122 aViewInformation3D.getDeviceToView(), 123 aViewInformation3D.getViewTime(), 124 aViewInformation3D.getExtendedInformationSequence()); 125 } 126 127 // create embedded 2d primitive and add. LightNormal and ShadowSlant are needed for evtl. 128 // 3D shadow extraction for correct B2DRange calculation (shadow is part of the object) 129 const drawinglayer::primitive2d::Primitive2DReference xReference( 130 new drawinglayer::primitive2d::Embedded3DPrimitive2D( 131 rxContent3D, 132 pVCOfE3DScene->getObjectTransformation(), 133 aViewInformation3D, 134 aLightNormal, 135 fShadowSlant, 136 rAllContentRange)); 137 138 xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1); 139 } 140 } 141 142 return xRetval; 143 } 144 145 ViewContactOfE3d::ViewContactOfE3d(E3dObject& rSdrObject) 146 : ViewContactOfSdrObj(rSdrObject) 147 { 148 } 149 150 ViewContactOfE3d::~ViewContactOfE3d() 151 { 152 } 153 154 drawinglayer::primitive3d::Primitive3DSequence ViewContactOfE3d::getVIP3DSWithoutObjectTransform() const 155 { 156 // local up-to-date checks. Create new list and compare. 157 drawinglayer::primitive3d::Primitive3DSequence xNew(createViewIndependentPrimitive3DSequence()); 158 159 if(!drawinglayer::primitive3d::arePrimitive3DSequencesEqual(mxViewIndependentPrimitive3DSequence, xNew)) 160 { 161 // has changed, copy content 162 const_cast< ViewContactOfE3d* >(this)->mxViewIndependentPrimitive3DSequence = xNew; 163 } 164 165 // return current Primitive2DSequence 166 return mxViewIndependentPrimitive3DSequence; 167 } 168 169 drawinglayer::primitive3d::Primitive3DSequence ViewContactOfE3d::getViewIndependentPrimitive3DSequence() const 170 { 171 // get sequence without object transform 172 drawinglayer::primitive3d::Primitive3DSequence xRetval(getVIP3DSWithoutObjectTransform()); 173 174 if(xRetval.hasElements()) 175 { 176 // add object transform if it's used 177 const basegfx::B3DHomMatrix& rObjectTransform(GetE3dObject().GetTransform()); 178 179 if(!rObjectTransform.isIdentity()) 180 { 181 const drawinglayer::primitive3d::Primitive3DReference xReference( 182 new drawinglayer::primitive3d::TransformPrimitive3D( 183 rObjectTransform, 184 xRetval)); 185 186 xRetval = drawinglayer::primitive3d::Primitive3DSequence(&xReference, 1); 187 } 188 } 189 190 // return current Primitive2DSequence 191 return xRetval; 192 } 193 194 drawinglayer::primitive2d::Primitive2DSequence ViewContactOfE3d::createViewIndependentPrimitive2DSequence() const 195 { 196 // also need to create a 2D embedding when the view-independent part is requested, 197 // see view-dependent part in ViewObjectContactOfE3d::createPrimitive2DSequence 198 // get 3d primitive vector, isPrimitiveVisible() is done in 3d creator 199 return impCreateWithGivenPrimitive3DSequence(getViewIndependentPrimitive3DSequence()); 200 } 201 202 ViewObjectContact& ViewContactOfE3d::CreateObjectSpecificViewObjectContact(ObjectContact& rObjectContact) 203 { 204 ViewObjectContact* pRetval = new ViewObjectContactOfE3d(rObjectContact, *this); 205 DBG_ASSERT(pRetval, "ViewContactOfE3d::CreateObjectSpecificViewObjectContact() failed (!)"); 206 207 return *pRetval; 208 } 209 210 drawinglayer::attribute::SdrLineAttribute* ViewContactOfE3d::impCreateFallbackLineAttribute(const basegfx::BColor& rBColor) const 211 { 212 static bool bFallbackToCreateAsLineForTest(false); 213 214 if(bFallbackToCreateAsLineForTest) 215 { 216 return new drawinglayer::attribute::SdrLineAttribute(rBColor); 217 } 218 else 219 { 220 return 0; 221 } 222 } 223 } // end of namespace contact 224 } // end of namespace sdr 225 226 ////////////////////////////////////////////////////////////////////////////// 227 // eof 228