1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <o3tl/numeric.hxx>
22 #include "svx/svdstr.hrc"
23 #include "svdglob.hxx"
24 #include <svx/svdview.hxx>
25 #include <svx/svdattr.hxx>
26 #include <svx/svdpage.hxx>
27 #include <svx/svdmodel.hxx>
28 #include "svx/svditer.hxx"
29 #include "svx/globl3d.hxx"
30 #include <svx/camera3d.hxx>
31 #include <svx/scene3d.hxx>
32 #include <svx/polysc3d.hxx>
33 #include <svx/cube3d.hxx>
34 #include <svx/lathe3d.hxx>
35 #include <svx/sphere3d.hxx>
36 #include <svx/extrud3d.hxx>
37 #include <svx/obj3d.hxx>
38 #include <svx/xtable.hxx>
39 #include <svx/xflclit.hxx>
40 #include <vcl/svapp.hxx>
41 #include <vcl/settings.hxx>
42 #include <svx/xlnclit.hxx>
43 #include <svl/metitem.hxx>
44 #include <svx/xfillit.hxx>
45 #include <svx/xlnwtit.hxx>
46 #include <vcl/virdev.hxx>
47 #include <tools/poly.hxx>
48 #include <tools/b3dtrans.hxx>
49 #include <svx/svxids.hrc>
50 #include <editeng/colritem.hxx>
51 #include <svx/e3ditem.hxx>
52 #include <svx/xlntrit.hxx>
53 #include <svx/xfltrit.hxx>
54 #include <svx/svdpagv.hxx>
55 #include <vcl/gradient.hxx>
56 #include <vcl/metaact.hxx>
57 #include <svx/svx3ditems.hxx>
58 #include <svl/whiter.hxx>
59 #include <svtools/colorcfg.hxx>
60 #include <editeng/eeitem.hxx>
61 #include <svx/xgrscit.hxx>
62 #include <sdr/properties/e3dproperties.hxx>
63 #include <sdr/properties/e3dcompoundproperties.hxx>
64 #include <basegfx/polygon/b3dpolypolygontools.hxx>
65 #include <basegfx/point/b3dpoint.hxx>
66 #include <basegfx/vector/b3dvector.hxx>
67 #include <svx/xlndsit.hxx>
68 #include <basegfx/matrix/b3dhommatrix.hxx>
69 #include <basegfx/polygon/b3dpolygon.hxx>
70 #include <basegfx/matrix/b2dhommatrix.hxx>
71 #include <basegfx/polygon/b2dpolypolygontools.hxx>
72 #include <basegfx/polygon/b3dpolygontools.hxx>
73 #include <svx/helperhittest3d.hxx>
74 #include <svx/sdr/contact/viewcontactofe3d.hxx>
75 #include <drawinglayer/geometry/viewinformation3d.hxx>
76 #include <com/sun/star/uno/Sequence.h>
77 #include <svx/sdr/contact/viewcontactofe3dscene.hxx>
78 #include <svx/e3dsceneupdater.hxx>
82 using namespace com::sun::star
;
85 // List for 3D-Objects
87 TYPEINIT1(E3dObjList
, SdrObjList
);
89 E3dObjList::E3dObjList(SdrModel
* pNewModel
, SdrPage
* pNewPage
, E3dObjList
* pNewUpList
)
90 : SdrObjList(pNewModel
, pNewPage
, pNewUpList
)
94 E3dObjList::E3dObjList(const E3dObjList
&)
99 E3dObjList
* E3dObjList::Clone() const
101 E3dObjList
* const pObjList
= new E3dObjList(*this);
102 pObjList
->lateInit(*this);
106 E3dObjList::~E3dObjList()
110 void E3dObjList::NbcInsertObject(SdrObject
* pObj
, size_t nPos
, const SdrInsertReason
* pReason
)
113 DBG_ASSERT(GetOwnerObj()->ISA(E3dObject
), "Insert 3D object in parent != 3DObject");
115 // Is it even a 3D object?
116 if(pObj
&& pObj
->ISA(E3dObject
))
118 // Normal 3D object, insert means
120 SdrObjList::NbcInsertObject(pObj
, nPos
, pReason
);
124 // No 3D object, inserted a page in place in a scene ...
125 GetOwnerObj()->GetPage()->InsertObject(pObj
, nPos
);
129 void E3dObjList::InsertObject(SdrObject
* pObj
, size_t nPos
, const SdrInsertReason
* pReason
)
131 OSL_ENSURE(GetOwnerObj()->ISA(E3dObject
), "Insert 3D object in non-3D Parent");
134 SdrObjList::InsertObject(pObj
, nPos
, pReason
);
136 E3dScene
* pScene
= static_cast<E3dObject
*>(GetOwnerObj())->GetScene();
139 pScene
->Cleanup3DDepthMapper();
143 SdrObject
* E3dObjList::NbcRemoveObject(size_t nObjNum
)
145 DBG_ASSERT(GetOwnerObj()->ISA(E3dObject
), "Remove 3D object from Parent != 3DObject");
148 SdrObject
* pRetval
= SdrObjList::NbcRemoveObject(nObjNum
);
150 E3dScene
* pScene
= static_cast<E3dObject
*>(GetOwnerObj())->GetScene();
153 pScene
->Cleanup3DDepthMapper();
159 SdrObject
* E3dObjList::RemoveObject(size_t nObjNum
)
161 OSL_ENSURE(GetOwnerObj()->ISA(E3dObject
), "3D object is removed from non-3D Parent");
164 SdrObject
* pRetval
= SdrObjList::RemoveObject(nObjNum
);
166 E3dScene
* pScene
= static_cast<E3dObject
*>(GetOwnerObj())->GetScene();
169 pScene
->Cleanup3DDepthMapper();
177 sdr::properties::BaseProperties
* E3dObject::CreateObjectSpecificProperties()
179 return new sdr::properties::E3dProperties(*this);
184 TYPEINIT1(E3dObject
, SdrAttrObj
);
186 E3dObject::E3dObject()
191 mbTfHasChanged(true),
195 maSubList
.SetOwnerObj(this);
196 maSubList
.SetListKind(SDROBJLIST_GROUPOBJ
);
200 E3dObject::~E3dObject()
204 void E3dObject::SetSelected(bool bNew
)
206 if((bool)mbIsSelected
!= bNew
)
211 for(size_t a
= 0; a
< maSubList
.GetObjCount(); ++a
)
213 E3dObject
* pCandidate
= dynamic_cast< E3dObject
* >(maSubList
.GetObj(a
));
217 pCandidate
->SetSelected(bNew
);
222 // Break, default implementations
224 bool E3dObject::IsBreakObjPossible()
229 SdrAttrObj
* E3dObject::GetBreakObj()
234 // SetRectsDirty must be done through the local SdrSubList
236 void E3dObject::SetRectsDirty(bool bNotMyself
)
239 SdrAttrObj::SetRectsDirty(bNotMyself
);
241 for(size_t a
= 0; a
< maSubList
.GetObjCount(); ++a
)
243 E3dObject
* pCandidate
= dynamic_cast< E3dObject
* >(maSubList
.GetObj(a
));
247 pCandidate
->SetRectsDirty(bNotMyself
);
252 sal_uInt32
E3dObject::GetObjInventor() const
257 sal_uInt16
E3dObject::GetObjIdentifier() const
259 return E3D_OBJECT_ID
;
262 // Determine the capabilities of the object
264 void E3dObject::TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const
266 rInfo
.bResizeFreeAllowed
= true;
267 rInfo
.bResizePropAllowed
= true;
268 rInfo
.bRotateFreeAllowed
= true;
269 rInfo
.bRotate90Allowed
= true;
270 rInfo
.bMirrorFreeAllowed
= false;
271 rInfo
.bMirror45Allowed
= false;
272 rInfo
.bMirror90Allowed
= false;
273 rInfo
.bShearAllowed
= false;
274 rInfo
.bEdgeRadiusAllowed
= false;
275 rInfo
.bCanConvToPath
= false;
277 // no transparence for 3d objects
278 rInfo
.bTransparenceAllowed
= false;
280 // gradient depends on fillstyle
281 // BM *** check if SetItem is NULL ***
282 drawing::FillStyle eFillStyle
= static_cast<const XFillStyleItem
&>(GetMergedItem(XATTR_FILLSTYLE
)).GetValue();
283 rInfo
.bGradientAllowed
= (eFillStyle
== drawing::FillStyle_GRADIENT
);
285 // Convert 3D objects in a group of polygons:
286 // At first not only possible, because the creation of a group of
287 // 2D polygons would be required which need to be sorted by depth,
288 // ie at intersections be cut relative to each other. Also the texture
289 // coorinates were an unsolved problem.
290 rInfo
.bCanConvToPoly
= false;
291 rInfo
.bCanConvToContour
= false;
292 rInfo
.bCanConvToPathLineToArea
= false;
293 rInfo
.bCanConvToPolyLineToArea
= false;
296 void E3dObject::NbcSetLayer(SdrLayerID nLayer
)
298 SdrAttrObj::NbcSetLayer(nLayer
);
300 for(size_t a
= 0; a
< maSubList
.GetObjCount(); ++a
)
302 E3dObject
* pCandidate
= dynamic_cast< E3dObject
* >(maSubList
.GetObj(a
));
306 pCandidate
->NbcSetLayer(nLayer
);
311 // Set ObjList also on SubList
313 void E3dObject::SetObjList(SdrObjList
* pNewObjList
)
315 SdrObject::SetObjList(pNewObjList
);
316 maSubList
.SetUpList(pNewObjList
);
319 void E3dObject::SetPage(SdrPage
* pNewPage
)
321 SdrAttrObj::SetPage(pNewPage
);
322 maSubList
.SetPage(pNewPage
);
325 void E3dObject::SetModel(SdrModel
* pNewModel
)
327 SdrAttrObj::SetModel(pNewModel
);
328 maSubList
.SetModel(pNewModel
);
331 // resize object, used from old 2d interfaces, e.g. in Move/Scale dialog (F4)
333 void E3dObject::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
335 // Movement in X, Y in the eye coordinate system
336 E3dScene
* pScene
= GetScene();
340 // transform pos from 2D world to 3D eye
341 const sdr::contact::ViewContactOfE3dScene
& rVCScene
= static_cast< sdr::contact::ViewContactOfE3dScene
& >(pScene
->GetViewContact());
342 const drawinglayer::geometry::ViewInformation3D
aViewInfo3D(rVCScene
.getViewInformation3D());
343 basegfx::B2DPoint
aScaleCenter2D((double)rRef
.X(), (double)rRef
.Y());
344 basegfx::B2DHomMatrix
aInverseSceneTransform(rVCScene
.getObjectTransformation());
346 aInverseSceneTransform
.invert();
347 aScaleCenter2D
= aInverseSceneTransform
* aScaleCenter2D
;
349 basegfx::B3DPoint
aScaleCenter3D(aScaleCenter2D
.getX(), aScaleCenter2D
.getY(), 0.5);
350 basegfx::B3DHomMatrix
aInverseViewToEye(aViewInfo3D
.getDeviceToView() * aViewInfo3D
.getProjection());
352 aInverseViewToEye
.invert();
353 aScaleCenter3D
= aInverseViewToEye
* aScaleCenter3D
;
356 double fScaleX(xFact
);
357 double fScaleY(yFact
);
360 basegfx::B3DHomMatrix
aInverseOrientation(aViewInfo3D
.getOrientation());
361 aInverseOrientation
.invert();
362 basegfx::B3DHomMatrix
mFullTransform(GetFullTransform());
363 basegfx::B3DHomMatrix
mTrans(mFullTransform
);
365 mTrans
*= aViewInfo3D
.getOrientation();
366 mTrans
.translate(-aScaleCenter3D
.getX(), -aScaleCenter3D
.getY(), -aScaleCenter3D
.getZ());
367 mTrans
.scale(fScaleX
, fScaleY
, 1.0);
368 mTrans
.translate(aScaleCenter3D
.getX(), aScaleCenter3D
.getY(), aScaleCenter3D
.getZ());
369 mTrans
*= aInverseOrientation
;
370 mFullTransform
.invert();
371 mTrans
*= mFullTransform
;
374 basegfx::B3DHomMatrix
mObjTrans(GetTransform());
377 E3DModifySceneSnapRectUpdater
aUpdater(this);
378 SetTransform(mObjTrans
);
383 // Move object in 2D is needed when using cursor keys
385 void E3dObject::NbcMove(const Size
& rSize
)
387 // Movement in X, Y in the eye coordinate system
388 E3dScene
* pScene
= GetScene();
392 //Dimensions of the scene in 3D and 2D for comparison
393 Rectangle aRect
= pScene
->GetSnapRect();
395 basegfx::B3DHomMatrix mInvDispTransform
;
398 mInvDispTransform
= GetParentObj()->GetFullTransform();
399 mInvDispTransform
.invert();
402 // BoundVolume from 3d world to 3d eye
403 const sdr::contact::ViewContactOfE3dScene
& rVCScene
= static_cast< sdr::contact::ViewContactOfE3dScene
& >(pScene
->GetViewContact());
404 const drawinglayer::geometry::ViewInformation3D
aViewInfo3D(rVCScene
.getViewInformation3D());
405 basegfx::B3DRange
aEyeVol(pScene
->GetBoundVolume());
406 aEyeVol
.transform(aViewInfo3D
.getOrientation());
408 if ((aRect
.GetWidth() == 0) || (aRect
.GetHeight() == 0))
409 throw o3tl::divide_by_zero();
411 // build relative movement vector in eye coordinates
412 basegfx::B3DPoint
aMove(
413 (double)rSize
.Width() * aEyeVol
.getWidth() / (double)aRect
.GetWidth(),
414 (double)-rSize
.Height() * aEyeVol
.getHeight() / (double)aRect
.GetHeight(),
416 basegfx::B3DPoint
aPos(0.0, 0.0, 0.0);
418 // movement vector to local coordinates of objects' parent
419 basegfx::B3DHomMatrix
aInverseOrientation(aViewInfo3D
.getOrientation());
420 aInverseOrientation
.invert();
421 basegfx::B3DHomMatrix
aCompleteTrans(mInvDispTransform
* aInverseOrientation
);
423 aMove
= aCompleteTrans
* aMove
;
424 aPos
= aCompleteTrans
* aPos
;
426 // build transformation and apply
427 basegfx::B3DHomMatrix aTranslate
;
428 aTranslate
.translate(aMove
.getX() - aPos
.getX(), aMove
.getY() - aPos
.getY(), aMove
.getZ() - aPos
.getZ());
430 E3DModifySceneSnapRectUpdater
aUpdater(pScene
);
431 SetTransform(aTranslate
* GetTransform());
435 // Return the sublist, but only if it contains objects!
437 SdrObjList
* E3dObject::GetSubList() const
439 return &(const_cast< E3dObjList
& >(maSubList
));
442 void E3dObject::RecalcSnapRect()
444 maSnapRect
= Rectangle();
446 for(size_t a
= 0; a
< maSubList
.GetObjCount(); ++a
)
448 E3dObject
* pCandidate
= dynamic_cast< E3dObject
* >(maSubList
.GetObj(a
));
452 maSnapRect
.Union(pCandidate
->GetSnapRect());
457 // Inform the parent about insertion of a 3D object, so that the parent is able
458 // treat the particualar objects in a special way (eg Light / Label in E3dScene)
460 void E3dObject::NewObjectInserted(const E3dObject
* p3DObj
)
463 GetParentObj()->NewObjectInserted(p3DObj
);
466 // Inform parent of changes in the structure (eg by transformation), in this
467 // process the object in which the change has occurred is returned.
469 void E3dObject::StructureChanged()
471 if ( GetParentObj() )
473 GetParentObj()->InvalidateBoundVolume();
474 GetParentObj()->StructureChanged();
478 void E3dObject::Insert3DObj(E3dObject
* p3DObj
)
480 DBG_ASSERT(p3DObj
, "Insert3DObj with NULL-pointer!");
481 SdrPage
* pPg
= pPage
;
482 maSubList
.InsertObject(p3DObj
);
484 InvalidateBoundVolume();
485 NewObjectInserted(p3DObj
);
489 void E3dObject::Remove3DObj(E3dObject
* p3DObj
)
491 DBG_ASSERT(p3DObj
, "Remove3DObj with NULL-pointer!");
493 if(p3DObj
->GetParentObj() == this)
495 SdrPage
* pPg
= pPage
;
496 maSubList
.RemoveObject(p3DObj
->GetOrdNum());
499 InvalidateBoundVolume();
504 E3dObject
* E3dObject::GetParentObj() const
506 E3dObject
* pRetval
= NULL
;
509 && GetObjList()->GetOwnerObj()
510 && GetObjList()->GetOwnerObj()->ISA(E3dObject
))
511 pRetval
= static_cast<E3dObject
*>(GetObjList()->GetOwnerObj());
515 // Determine the top-level scene object
517 E3dScene
* E3dObject::GetScene() const
520 return GetParentObj()->GetScene();
524 // Calculate enclosed volume, including all child objects
526 basegfx::B3DRange
E3dObject::RecalcBoundVolume() const
528 basegfx::B3DRange aRetval
;
529 const size_t nObjCnt(maSubList
.GetObjCount());
533 for(size_t a
= 0; a
< nObjCnt
; ++a
)
535 const E3dObject
* p3DObject
= dynamic_cast< const E3dObject
* >(maSubList
.GetObj(a
));
539 basegfx::B3DRange
aLocalRange(p3DObject
->GetBoundVolume());
540 aLocalRange
.transform(p3DObject
->GetTransform());
541 aRetval
.expand(aLocalRange
);
548 const sdr::contact::ViewContactOfE3d
* pVCOfE3D
= dynamic_cast< const sdr::contact::ViewContactOfE3d
* >(&GetViewContact());
552 // BoundVolume is without 3D object transformation, use correct sequence
553 const drawinglayer::primitive3d::Primitive3DSequence
xLocalSequence(pVCOfE3D
->getVIP3DSWithoutObjectTransform());
555 if(xLocalSequence
.hasElements())
557 const uno::Sequence
< beans::PropertyValue
> aEmptyParameters
;
558 const drawinglayer::geometry::ViewInformation3D
aLocalViewInformation3D(aEmptyParameters
);
560 aRetval
= drawinglayer::primitive3d::getB3DRangeFromPrimitive3DSequence(
561 xLocalSequence
, aLocalViewInformation3D
);
569 // Get enclosed volume and possibly recalculate it
571 const basegfx::B3DRange
& E3dObject::GetBoundVolume() const
573 if(maLocalBoundVol
.isEmpty())
575 const_cast< E3dObject
* >(this)->maLocalBoundVol
= RecalcBoundVolume();
578 return maLocalBoundVol
;
581 void E3dObject::InvalidateBoundVolume()
583 maLocalBoundVol
.reset();
586 // Pass on the changes of the BoundVolumes to all child objects
588 void E3dObject::SetBoundVolInvalid()
590 InvalidateBoundVolume();
592 for(size_t a
= 0; a
< maSubList
.GetObjCount(); ++a
)
594 E3dObject
* pCandidate
= dynamic_cast< E3dObject
* >(maSubList
.GetObj(a
));
598 pCandidate
->SetBoundVolInvalid();
603 // Pass on the changes in transformation to all child objects
605 void E3dObject::SetTransformChanged()
607 InvalidateBoundVolume();
608 mbTfHasChanged
= true;
610 for(size_t a
= 0; a
< maSubList
.GetObjCount(); ++a
)
612 E3dObject
* pCandidate
= dynamic_cast< E3dObject
* >(maSubList
.GetObj(a
));
616 pCandidate
->SetTransformChanged();
621 // Define the hierarchical transformation over all Parents, store in
622 // maFullTransform and return them
624 const basegfx::B3DHomMatrix
& E3dObject::GetFullTransform() const
628 basegfx::B3DHomMatrix
aNewFullTransformation(maTransformation
);
630 if ( GetParentObj() )
632 aNewFullTransformation
= GetParentObj()->GetFullTransform() * aNewFullTransformation
;
635 const_cast< E3dObject
* >(this)->maFullTransform
= aNewFullTransformation
;
636 const_cast< E3dObject
* >(this)->mbTfHasChanged
= false;
639 return maFullTransform
;
643 void E3dObject::NbcSetTransform(const basegfx::B3DHomMatrix
& rMatrix
)
645 if(maTransformation
!= rMatrix
)
647 maTransformation
= rMatrix
;
648 SetTransformChanged();
653 // Set transformation matrix with repaint broadcast
655 void E3dObject::SetTransform(const basegfx::B3DHomMatrix
& rMatrix
)
657 if(rMatrix
!= maTransformation
)
659 NbcSetTransform(rMatrix
);
661 BroadcastObjectChange();
662 if (pUserCall
!= NULL
) pUserCall
->Changed(*this, SDRUSERCALL_RESIZE
, Rectangle());
666 basegfx::B3DPolyPolygon
E3dObject::CreateWireframe() const
668 const basegfx::B3DRange
aBoundVolume(GetBoundVolume());
669 return basegfx::tools::createCubePolyPolygonFromB3DRange(aBoundVolume
);
672 // Get the name of the object (singular)
674 OUString
E3dObject::TakeObjNameSingul() const
676 OUStringBuffer
sName(ImpGetResStr(STR_ObjNameSingulObj3d
));
678 OUString
aName(GetName());
679 if (!aName
.isEmpty())
686 return sName
.makeStringAndClear();
689 // Get the name of the object (plural)
691 OUString
E3dObject::TakeObjNamePlural() const
693 return ImpGetResStr(STR_ObjNamePluralObj3d
);
696 E3dObject
* E3dObject::Clone() const
698 return CloneHelper
< E3dObject
>();
701 E3dObject
& E3dObject::operator=(const E3dObject
& rObj
)
705 SdrObject::operator=(rObj
);
707 const E3dObject
& r3DObj
= (const E3dObject
&) rObj
;
708 if (r3DObj
.GetSubList())
710 maSubList
.CopyObjects(*r3DObj
.GetSubList());
713 // BoundVol can be copied since also the children are copied
714 maLocalBoundVol
= r3DObj
.maLocalBoundVol
;
715 maTransformation
= r3DObj
.maTransformation
;
717 // Because the parent may have changed, definitely redefine the total
718 // transformation next time
719 SetTransformChanged();
721 // Copy selection status
722 mbIsSelected
= r3DObj
.mbIsSelected
;
726 SdrObjGeoData
*E3dObject::NewGeoData() const
728 return new E3DObjGeoData
;
731 void E3dObject::SaveGeoData(SdrObjGeoData
& rGeo
) const
733 SdrAttrObj::SaveGeoData (rGeo
);
735 static_cast<E3DObjGeoData
&>(rGeo
).maLocalBoundVol
= maLocalBoundVol
;
736 static_cast<E3DObjGeoData
&>(rGeo
).maTransformation
= maTransformation
;
739 void E3dObject::RestGeoData(const SdrObjGeoData
& rGeo
)
741 maLocalBoundVol
= static_cast<const E3DObjGeoData
&>(rGeo
).maLocalBoundVol
;
742 E3DModifySceneSnapRectUpdater
aUpdater(this);
743 NbcSetTransform(static_cast<const E3DObjGeoData
&>(rGeo
).maTransformation
);
744 SdrAttrObj::RestGeoData (rGeo
);
747 // 2D-rotation of a 3D-body, normally this is done by the scene itself.
748 // This is however a correct implementation, because everything that has
749 // happened is a rotation around the axis perpendicular to the screen and that
750 // is regardless of how the scene has been rotated up until now.
752 void E3dObject::NbcRotate(const Point
& rRef
, long nAngle
, double sn
, double cs
)
754 // So currently the glue points are defined relative to the scene aOutRect.
755 // Before turning the glue points are defined relative to the page. They
756 // take no part in the rotation of the scene. To ensure this, there is the
757 // SetGlueReallyAbsolute(sal_True);
759 double fWinkelInRad
= nAngle
/100.0 * F_PI180
;
761 basegfx::B3DHomMatrix aRotateZ
;
762 aRotateZ
.rotate(0.0, 0.0, fWinkelInRad
);
763 NbcSetTransform(aRotateZ
* GetTransform());
765 SetRectsDirty(); // This forces a recalculation of all BoundRects
766 NbcRotateGluePoints(rRef
,nAngle
,sn
,cs
); // Rotate the glue points (who still
767 // have coordinates relative to the
769 SetGlueReallyAbsolute(false); // from now they are again relative to BoundRect (that is defined as aOutRect)
772 sdr::properties::BaseProperties
* E3dCompoundObject::CreateObjectSpecificProperties()
774 return new sdr::properties::E3dCompoundProperties(*this);
779 TYPEINIT1(E3dCompoundObject
, E3dObject
);
781 E3dCompoundObject::E3dCompoundObject()
783 aMaterialAmbientColor(),
784 bCreateNormals(false),
785 bCreateTexture(false)
788 E3dDefaultAttributes aDefault
;
789 SetDefaultAttributes(aDefault
);
792 E3dCompoundObject::E3dCompoundObject(E3dDefaultAttributes
& rDefault
)
794 aMaterialAmbientColor(),
795 bCreateNormals(false),
796 bCreateTexture(false)
799 SetDefaultAttributes(rDefault
);
802 void E3dCompoundObject::SetDefaultAttributes(E3dDefaultAttributes
& rDefault
)
805 aMaterialAmbientColor
= rDefault
.GetDefaultAmbientColor();
807 bCreateNormals
= rDefault
.GetDefaultCreateNormals();
808 bCreateTexture
= rDefault
.GetDefaultCreateTexture();
811 E3dCompoundObject::~E3dCompoundObject ()
815 basegfx::B2DPolyPolygon
E3dCompoundObject::TakeXorPoly() const
817 basegfx::B2DPolyPolygon aRetval
;
818 const uno::Sequence
< beans::PropertyValue
> aEmptyParameters
;
819 drawinglayer::geometry::ViewInformation3D
aViewInfo3D(aEmptyParameters
);
820 E3dScene
* pRootScene
= fillViewInformation3DForCompoundObject(aViewInfo3D
, *this);
824 const sdr::contact::ViewContactOfE3dScene
& rVCScene
= static_cast< sdr::contact::ViewContactOfE3dScene
& >(pRootScene
->GetViewContact());
825 const basegfx::B3DPolyPolygon
aCubePolyPolygon(CreateWireframe());
826 aRetval
= basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(aCubePolyPolygon
,
827 aViewInfo3D
.getObjectToView() * GetTransform());
828 aRetval
.transform(rVCScene
.getObjectTransformation());
834 sal_uInt32
E3dCompoundObject::GetHdlCount() const
836 // 8 corners + 1 E3dVolumeMarker (= Wireframe representation)
840 void E3dCompoundObject::AddToHdlList(SdrHdlList
& rHdlList
) const
842 const uno::Sequence
< beans::PropertyValue
> aEmptyParameters
;
843 drawinglayer::geometry::ViewInformation3D
aViewInfo3D(aEmptyParameters
);
844 E3dScene
* pRootScene
= fillViewInformation3DForCompoundObject(aViewInfo3D
, *this);
848 const basegfx::B3DRange
aBoundVolume(GetBoundVolume());
850 if(!aBoundVolume
.isEmpty())
852 const sdr::contact::ViewContactOfE3dScene
& rVCScene
= static_cast< sdr::contact::ViewContactOfE3dScene
& >(pRootScene
->GetViewContact());
854 for(sal_uInt32
a(0); a
< 8; a
++)
856 basegfx::B3DPoint aPos3D
;
860 case 0 : aPos3D
.setX(aBoundVolume
.getMinX()); aPos3D
.setY(aBoundVolume
.getMinY()); aPos3D
.setZ(aBoundVolume
.getMinZ()); break;
861 case 1 : aPos3D
.setX(aBoundVolume
.getMinX()); aPos3D
.setY(aBoundVolume
.getMinY()); aPos3D
.setZ(aBoundVolume
.getMaxZ()); break;
862 case 2 : aPos3D
.setX(aBoundVolume
.getMinX()); aPos3D
.setY(aBoundVolume
.getMaxY()); aPos3D
.setZ(aBoundVolume
.getMinZ()); break;
863 case 3 : aPos3D
.setX(aBoundVolume
.getMinX()); aPos3D
.setY(aBoundVolume
.getMaxY()); aPos3D
.setZ(aBoundVolume
.getMaxZ()); break;
864 case 4 : aPos3D
.setX(aBoundVolume
.getMaxX()); aPos3D
.setY(aBoundVolume
.getMinY()); aPos3D
.setZ(aBoundVolume
.getMinZ()); break;
865 case 5 : aPos3D
.setX(aBoundVolume
.getMaxX()); aPos3D
.setY(aBoundVolume
.getMinY()); aPos3D
.setZ(aBoundVolume
.getMaxZ()); break;
866 case 6 : aPos3D
.setX(aBoundVolume
.getMaxX()); aPos3D
.setY(aBoundVolume
.getMaxY()); aPos3D
.setZ(aBoundVolume
.getMinZ()); break;
867 case 7 : aPos3D
.setX(aBoundVolume
.getMaxX()); aPos3D
.setY(aBoundVolume
.getMaxY()); aPos3D
.setZ(aBoundVolume
.getMaxZ()); break;
871 aPos3D
*= aViewInfo3D
.getObjectToView() * GetTransform();
873 // create 2d relative scene
874 basegfx::B2DPoint
aPos2D(aPos3D
.getX(), aPos3D
.getY());
877 aPos2D
*= rVCScene
.getObjectTransformation();
879 rHdlList
.AddHdl(new SdrHdl(Point(basegfx::fround(aPos2D
.getX()), basegfx::fround(aPos2D
.getY())), HDL_BWGT
));
884 const basegfx::B2DPolyPolygon
aPolyPolygon(TakeXorPoly());
886 if(aPolyPolygon
.count())
888 E3dVolumeMarker
* pVolMarker
= new E3dVolumeMarker(aPolyPolygon
);
889 rHdlList
.AddHdl(pVolMarker
);
893 sal_uInt16
E3dCompoundObject::GetObjIdentifier() const
895 return E3D_COMPOUNDOBJ_ID
;
898 void E3dCompoundObject::RecalcSnapRect()
900 const uno::Sequence
< beans::PropertyValue
> aEmptyParameters
;
901 drawinglayer::geometry::ViewInformation3D
aViewInfo3D(aEmptyParameters
);
902 E3dScene
* pRootScene
= fillViewInformation3DForCompoundObject(aViewInfo3D
, *this);
903 maSnapRect
= Rectangle();
907 // get VC of 3D candidate
908 const sdr::contact::ViewContactOfE3d
* pVCOfE3D
= dynamic_cast< const sdr::contact::ViewContactOfE3d
* >(&GetViewContact());
912 // get 3D primitive sequence
913 const drawinglayer::primitive3d::Primitive3DSequence
xLocalSequence(pVCOfE3D
->getViewIndependentPrimitive3DSequence());
915 if(xLocalSequence
.hasElements())
918 basegfx::B3DRange
aBoundVolume(drawinglayer::primitive3d::getB3DRangeFromPrimitive3DSequence(
919 xLocalSequence
, aViewInfo3D
));
921 // transform bound volume to relative scene coordinates
922 aBoundVolume
.transform(aViewInfo3D
.getObjectToView());
924 // build 2d relative scene range
925 basegfx::B2DRange
aSnapRange(
926 aBoundVolume
.getMinX(), aBoundVolume
.getMinY(),
927 aBoundVolume
.getMaxX(), aBoundVolume
.getMaxY());
929 // transform to 2D world coordiantes
930 const sdr::contact::ViewContactOfE3dScene
& rVCScene
= static_cast< sdr::contact::ViewContactOfE3dScene
& >(pRootScene
->GetViewContact());
931 aSnapRange
.transform(rVCScene
.getObjectTransformation());
934 maSnapRect
= Rectangle(
935 sal_Int32(floor(aSnapRange
.getMinX())), sal_Int32(floor(aSnapRange
.getMinY())),
936 sal_Int32(ceil(aSnapRange
.getMaxX())), sal_Int32(ceil(aSnapRange
.getMaxY())));
942 E3dCompoundObject
* E3dCompoundObject::Clone() const
944 return CloneHelper
< E3dCompoundObject
>();
947 // convert given basegfx::B3DPolyPolygon to screen coor
949 basegfx::B2DPolyPolygon
E3dCompoundObject::TransformToScreenCoor(const basegfx::B3DPolyPolygon
& rCandidate
)
951 const uno::Sequence
< beans::PropertyValue
> aEmptyParameters
;
952 drawinglayer::geometry::ViewInformation3D
aViewInfo3D(aEmptyParameters
);
953 E3dScene
* pRootScene
= fillViewInformation3DForCompoundObject(aViewInfo3D
, *this);
954 basegfx::B2DPolyPolygon aRetval
;
958 aRetval
= basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(rCandidate
,
959 aViewInfo3D
.getObjectToView() * GetTransform());
960 const sdr::contact::ViewContactOfE3dScene
& rVCScene
= static_cast< sdr::contact::ViewContactOfE3dScene
& >(pRootScene
->GetViewContact());
961 aRetval
.transform(rVCScene
.getObjectTransformation());
967 bool E3dCompoundObject::IsAOrdNumRemapCandidate(E3dScene
*& prScene
) const
970 && GetObjList()->GetOwnerObj()
971 && GetObjList()->GetOwnerObj()->ISA(E3dScene
))
973 prScene
= static_cast<E3dScene
*>(GetObjList()->GetOwnerObj());
980 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */