LibreOffice Module svx (master)  1
viewcontactofe3d.cxx
Go to the documentation of this file.
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 
22 #include <svx/obj3d.hxx>
25 #include <svx/scene3d.hxx>
31 
32 namespace {
33 
34 const sdr::contact::ViewContactOfE3dScene* tryToFindVCOfE3DScene(
35  const sdr::contact::ViewContact& rCandidate,
36  basegfx::B3DHomMatrix& o_rInBetweenObjectTransform)
37 {
38  const sdr::contact::ViewContactOfE3dScene* pSceneParent =
39  dynamic_cast< const sdr::contact::ViewContactOfE3dScene* >(rCandidate.GetParentContact());
40 
41  if(pSceneParent)
42  {
43  // each 3d object (including in-between scenes) should have a scene as parent
44  const sdr::contact::ViewContactOfE3dScene* pSceneParentParent =
45  dynamic_cast< const sdr::contact::ViewContactOfE3dScene* >(pSceneParent->GetParentContact());
46 
47  if(pSceneParentParent)
48  {
49  // the parent scene of rCandidate is an in-between scene, call recursively and collect
50  // the in-between scene's object transformation part in o_rInBetweenObjectTransform
51  const basegfx::B3DHomMatrix& rSceneParentTransform = pSceneParent->GetE3dScene().GetTransform();
52  o_rInBetweenObjectTransform = rSceneParentTransform * o_rInBetweenObjectTransform;
53  return tryToFindVCOfE3DScene(*pSceneParent, o_rInBetweenObjectTransform);
54  }
55  else
56  {
57  // the parent scene is the outmost scene
58  return pSceneParent;
59  }
60  }
61 
62  // object hierarchy structure is incorrect; no result
63  return nullptr;
64 }
65 
66 } // end of anonymous namespace
67 
68 namespace sdr { namespace contact {
69 
71  const drawinglayer::primitive3d::Primitive3DContainer& rxContent3D) const
72 {
74 
75  if(!rxContent3D.empty())
76  {
77  // try to get the outmost ViewObjectContactOfE3dScene for this single 3d object,
78  // the ones on the way there are grouping scenes. Collect the in-between scene's
79  // transformations to build a correct object transformation for the embedded
80  // object
81  basegfx::B3DHomMatrix aInBetweenObjectTransform;
82  const ViewContactOfE3dScene* pVCOfE3DScene = tryToFindVCOfE3DScene(*this, aInBetweenObjectTransform);
83 
84  if(pVCOfE3DScene)
85  {
86  basegfx::B3DVector aLightNormal;
87  const double fShadowSlant(pVCOfE3DScene->getSdrSceneAttribute().getShadowSlant());
88  const basegfx::B3DRange& rAllContentRange = pVCOfE3DScene->getAllContentRange3D();
89  drawinglayer::geometry::ViewInformation3D aViewInformation3D(pVCOfE3DScene->getViewInformation3D());
90 
91  if(!pVCOfE3DScene->getSdrLightingAttribute().getLightVector().empty())
92  {
93  // get light normal from first light and normalize
94  aLightNormal = pVCOfE3DScene->getSdrLightingAttribute().getLightVector()[0].getDirection();
95  aLightNormal.normalize();
96  }
97 
98  if(!aInBetweenObjectTransform.isIdentity())
99  {
100  // if aInBetweenObjectTransform is used, create combined ViewInformation3D which
101  // contains the correct object transformation for the embedded 3d object
102  aViewInformation3D = drawinglayer::geometry::ViewInformation3D(
103  aViewInformation3D.getObjectTransformation() * aInBetweenObjectTransform,
104  aViewInformation3D.getOrientation(),
105  aViewInformation3D.getProjection(),
106  aViewInformation3D.getDeviceToView(),
107  aViewInformation3D.getViewTime(),
108  aViewInformation3D.getExtendedInformationSequence());
109  }
110 
111  // create embedded 2d primitive and add. LightNormal and ShadowSlant are needed for evtl.
112  // 3D shadow extraction for correct B2DRange calculation (shadow is part of the object)
115  rxContent3D,
116  pVCOfE3DScene->getObjectTransformation(),
117  aViewInformation3D,
118  aLightNormal,
119  fShadowSlant,
120  rAllContentRange));
121 
122  xRetval = drawinglayer::primitive2d::Primitive2DContainer { xReference };
123  }
124  }
125 
126  return xRetval;
127 }
128 
130 : ViewContactOfSdrObj(rSdrObject)
131 {
132 }
133 
135 {
136 }
137 
139 {
140  // local up-to-date checks. Create new list and compare.
142 
144  {
145  // has changed, copy content
146  const_cast< ViewContactOfE3d* >(this)->mxViewIndependentPrimitive3DContainer = xNew;
147  }
148 
149  // return current Primitive2DContainer
151 }
152 
154 {
155  // get sequence without object transform
157 
158  if(!xRetval.empty())
159  {
160  // add object transform if it's used
161  const basegfx::B3DHomMatrix& rObjectTransform(GetE3dObject().GetTransform());
162 
163  if(!rObjectTransform.isIdentity())
164  {
167  rObjectTransform,
168  xRetval));
169 
170  xRetval = { xReference };
171  }
172  }
173 
174  // return current Primitive2DContainer
175  return xRetval;
176 }
177 
179 {
180  // also need to create a 2D embedding when the view-independent part is requested,
181  // see view-dependent part in ViewObjectContactOfE3d::createPrimitive2DSequence
182  // get 3d primitive vector, isPrimitiveVisible() is done in 3d creator
184 }
185 
187 {
188  ViewObjectContact* pRetval = new ViewObjectContactOfE3d(rObjectContact, *this);
189  DBG_ASSERT(pRetval, "ViewContactOfE3d::CreateObjectSpecificViewObjectContact() failed (!)");
190 
191  return *pRetval;
192 }
193 
194 }}
195 
196 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual ViewObjectContact & CreateObjectSpecificViewObjectContact(ObjectContact &rObjectContact) override
virtual ViewContact * GetParentContact() const
B3DVector & normalize()
const ::std::vector< Sdr3DLightAttribute > & getLightVector() const
const drawinglayer::geometry::ViewInformation3D & getViewInformation3D(const ::basegfx::B3DRange &rContentRange) const
drawinglayer::primitive3d::Primitive3DContainer getViewIndependentPrimitive3DContainer() const
const basegfx::B3DHomMatrix & GetTransform() const
Definition: obj3d.hxx:111
virtual drawinglayer::primitive3d::Primitive3DContainer createViewIndependentPrimitive3DContainer() const =0
const E3dObject & GetE3dObject() const
const drawinglayer::attribute::SdrSceneAttribute & getSdrSceneAttribute() const
drawinglayer::primitive2d::Primitive2DContainer impCreateWithGivenPrimitive3DContainer(const drawinglayer::primitive3d::Primitive3DContainer &rxContent3D) const
#define DBG_ASSERT(sCon, aError)
css::uno::Reference< css::graphic::XPrimitive3D > Primitive3DReference
bool isIdentity() const
virtual ViewContact * GetParentContact() const override
virtual drawinglayer::primitive2d::Primitive2DContainer createViewIndependentPrimitive2DSequence() const override
css::uno::Reference< css::graphic::XPrimitive2D > Primitive2DReference
drawinglayer::primitive3d::Primitive3DContainer const & getVIP3DSWithoutObjectTransform() const
const basegfx::B2DHomMatrix & getObjectTransformation() const
drawinglayer::primitive3d::Primitive3DContainer mxViewIndependentPrimitive3DContainer
const drawinglayer::attribute::SdrLightingAttribute & getSdrLightingAttribute() const
basegfx::B3DRange getAllContentRange3D() const