xref: /trunk/main/svx/source/engine3d/obj3d.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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/svdstr.hrc"
32 #include "svx/svdglob.hxx"
33 #include <svx/svdview.hxx>
34 #include <svx/svdattr.hxx>
35 #include <svx/svdpage.hxx>
36 #include <svx/svdmodel.hxx>
37 #include "svx/svditer.hxx"
38 #include "svx/globl3d.hxx"
39 #include <svx/camera3d.hxx>
40 #include <svx/scene3d.hxx>
41 #include <svx/polysc3d.hxx>
42 #include <svx/cube3d.hxx>
43 #include <svx/lathe3d.hxx>
44 #include <svx/sphere3d.hxx>
45 #include <svx/extrud3d.hxx>
46 #include <svx/obj3d.hxx>
47 #include <svx/xtable.hxx>
48 #include <svx/xflclit.hxx>
49 #include <vcl/svapp.hxx>
50 #include <vcl/settings.hxx>
51 #include <svx/xlnclit.hxx>
52 #include <svl/metitem.hxx>
53 #include <svx/xtable.hxx>
54 #include <svx/xfillit.hxx>
55 #include <svx/xlnwtit.hxx>
56 #include <vcl/virdev.hxx>
57 #include <tools/poly.hxx>
58 #include <tools/b3dtrans.hxx>
59 #include <svx/svxids.hrc>
60 #include <editeng/colritem.hxx>
61 #include <svx/e3ditem.hxx>
62 #include <svx/xlntrit.hxx>
63 #include <svx/xfltrit.hxx>
64 #include <svx/svdpagv.hxx>
65 #include <vcl/gradient.hxx>
66 #include <vcl/metaact.hxx>
67 #include <svx/svx3ditems.hxx>
68 #include <svl/whiter.hxx>
69 #include <svtools/colorcfg.hxx>
70 #include <editeng/eeitem.hxx>
71 #include <svx/xgrscit.hxx>
72 #include "svdoimp.hxx"
73 #include <svx/sdr/properties/e3dproperties.hxx>
74 #include <svx/sdr/properties/e3dcompoundproperties.hxx>
75 #include <basegfx/polygon/b3dpolypolygontools.hxx>
76 #include <basegfx/point/b3dpoint.hxx>
77 #include <basegfx/vector/b3dvector.hxx>
78 #include <svx/xlndsit.hxx>
79 #include <basegfx/matrix/b3dhommatrix.hxx>
80 #include <basegfx/polygon/b3dpolygon.hxx>
81 #include <basegfx/matrix/b2dhommatrix.hxx>
82 #include <basegfx/polygon/b2dpolypolygontools.hxx>
83 #include <basegfx/polygon/b3dpolygontools.hxx>
84 #include <svx/helperhittest3d.hxx>
85 #include <svx/sdr/contact/viewcontactofe3d.hxx>
86 #include <drawinglayer/geometry/viewinformation3d.hxx>
87 #include <com/sun/star/uno/Sequence.h>
88 #include <svx/sdr/contact/viewcontactofe3dscene.hxx>
89 #include <basegfx/polygon/b3dpolypolygontools.hxx>
90 #include <svx/e3dsceneupdater.hxx>
91 
92 #define ITEMVALUE(ItemSet,Id,Cast)  ((const Cast&)(ItemSet).Get(Id)).GetValue()
93 
94 //////////////////////////////////////////////////////////////////////////////
95 
96 using namespace com::sun::star;
97 
98 /*************************************************************************
99 |*
100 |* Liste fuer 3D-Objekte
101 |*
102 \************************************************************************/
103 
104 TYPEINIT1(E3dObjList, SdrObjList);
105 
106 E3dObjList::E3dObjList(SdrModel* pNewModel, SdrPage* pNewPage, E3dObjList* pNewUpList)
107 :   SdrObjList(pNewModel, pNewPage, pNewUpList)
108 {
109 }
110 
111 E3dObjList::E3dObjList(const E3dObjList& rSrcList)
112 :   SdrObjList(rSrcList)
113 {
114 }
115 
116 E3dObjList::~E3dObjList()
117 {
118 }
119 
120 void E3dObjList::NbcInsertObject(SdrObject* pObj, sal_uIntPtr nPos, const SdrInsertReason* pReason)
121 {
122     // Owner holen
123     DBG_ASSERT(GetOwnerObj()->ISA(E3dObject), "AW: Einfuegen 3DObject in Parent != 3DObject");
124 
125     // Ist es ueberhaupt ein 3D-Objekt?
126     if(pObj && pObj->ISA(E3dObject))
127     {
128         // Normales 3D Objekt, einfuegen mittels
129         // call parent
130         SdrObjList::NbcInsertObject(pObj, nPos, pReason);
131     }
132     else
133     {
134         // Kein 3D Objekt, fuege in Seite statt in Szene ein...
135         GetOwnerObj()->GetPage()->InsertObject(pObj, nPos);
136     }
137 }
138 
139 void E3dObjList::InsertObject(SdrObject* pObj, sal_uIntPtr nPos, const SdrInsertReason* pReason)
140 {
141     OSL_ENSURE(GetOwnerObj()->ISA(E3dObject), "Insert 3DObject in non-3D Parent");
142     //E3DModifySceneSnapRectUpdater aUpdater(GetOwnerObj());
143 
144     // call parent
145     SdrObjList::InsertObject(pObj, nPos, pReason);
146 
147     E3dScene* pScene = ((E3dObject*)GetOwnerObj())->GetScene();
148     if(pScene)
149     {
150         pScene->Cleanup3DDepthMapper();
151     }
152 }
153 
154 SdrObject* E3dObjList::NbcRemoveObject(sal_uIntPtr nObjNum)
155 {
156     DBG_ASSERT(GetOwnerObj()->ISA(E3dObject), "AW: Entfernen 3DObject aus Parent != 3DObject");
157     //E3DModifySceneSnapRectUpdater aUpdater(GetOwnerObj());
158 
159     // call parent
160     SdrObject* pRetval = SdrObjList::NbcRemoveObject(nObjNum);
161 
162     E3dScene* pScene = ((E3dObject*)GetOwnerObj())->GetScene();
163     if(pScene)
164     {
165         pScene->Cleanup3DDepthMapper();
166     }
167 
168     return pRetval;
169 }
170 
171 SdrObject* E3dObjList::RemoveObject(sal_uIntPtr nObjNum)
172 {
173     OSL_ENSURE(GetOwnerObj()->ISA(E3dObject), "3DObject is removed from non-3D Parent");
174     //E3DModifySceneSnapRectUpdater aUpdater(GetOwnerObj());
175 
176     // call parent
177     SdrObject* pRetval = SdrObjList::RemoveObject(nObjNum);
178 
179     E3dScene* pScene = ((E3dObject*)GetOwnerObj())->GetScene();
180     if(pScene)
181     {
182         pScene->Cleanup3DDepthMapper();
183     }
184 
185     return pRetval;
186 }
187 
188 /*************************************************************************
189 |*
190 |* Konstruktor
191 |*
192 \************************************************************************/
193 
194 //////////////////////////////////////////////////////////////////////////////
195 
196 sdr::properties::BaseProperties* E3dObject::CreateObjectSpecificProperties()
197 {
198     return new sdr::properties::E3dProperties(*this);
199 }
200 
201 ////////////////////////////////////////////////////////////////////////////////////////////////////
202 
203 TYPEINIT1(E3dObject, SdrAttrObj);
204 
205 E3dObject::E3dObject()
206 :   maSubList(),
207     maLocalBoundVol(),
208     maTransformation(),
209     maFullTransform(),
210     mbTfHasChanged(true),
211     mbIsSelected(false)
212 {
213     bIs3DObj = true;
214     maSubList.SetOwnerObj(this);
215     maSubList.SetListKind(SDROBJLIST_GROUPOBJ);
216     bClosedObj = true;
217 }
218 
219 /*************************************************************************
220 |*
221 |* Destruktor
222 |*
223 \************************************************************************/
224 
225 E3dObject::~E3dObject()
226 {
227 }
228 
229 /*************************************************************************
230 |*
231 |* Selektions-Flag setzen
232 |*
233 \************************************************************************/
234 
235 void E3dObject::SetSelected(bool bNew)
236 {
237     if((bool)mbIsSelected != bNew)
238     {
239         mbIsSelected = bNew;
240     }
241 
242     for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++)
243     {
244         E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a));
245 
246         if(pCandidate)
247         {
248             pCandidate->SetSelected(bNew);
249         }
250     }
251 }
252 
253 /*************************************************************************
254 |*
255 |* Aufbrechen, default-Implementierungen
256 |*
257 \************************************************************************/
258 
259 sal_Bool E3dObject::IsBreakObjPossible()
260 {
261     return sal_False;
262 }
263 
264 SdrAttrObj* E3dObject::GetBreakObj()
265 {
266     return 0L;
267 }
268 
269 /*************************************************************************
270 |*
271 |* SetRectsDirty muss ueber die lokale SdrSubList gehen
272 |*
273 \************************************************************************/
274 
275 void E3dObject::SetRectsDirty(sal_Bool bNotMyself)
276 {
277     // call parent
278     SdrAttrObj::SetRectsDirty(bNotMyself);
279 
280     for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++)
281     {
282         E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a));
283 
284         if(pCandidate)
285         {
286             pCandidate->SetRectsDirty(bNotMyself);
287         }
288     }
289 }
290 
291 /*************************************************************************
292 |*
293 |* Inventor zurueckgeben
294 |*
295 \************************************************************************/
296 
297 sal_uInt32 E3dObject::GetObjInventor() const
298 {
299     return E3dInventor;
300 }
301 
302 /*************************************************************************
303 |*
304 |* Identifier zurueckgeben
305 |*
306 \************************************************************************/
307 
308 sal_uInt16 E3dObject::GetObjIdentifier() const
309 {
310     return E3D_OBJECT_ID;
311 }
312 
313 /*************************************************************************
314 |*
315 |* Faehigkeiten des Objektes feststellen
316 |*
317 \************************************************************************/
318 
319 void E3dObject::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
320 {
321     rInfo.bResizeFreeAllowed    = sal_True;
322     rInfo.bResizePropAllowed    = sal_True;
323     rInfo.bRotateFreeAllowed    = sal_True;
324     rInfo.bRotate90Allowed      = sal_True;
325     rInfo.bMirrorFreeAllowed    = sal_False;
326     rInfo.bMirror45Allowed      = sal_False;
327     rInfo.bMirror90Allowed      = sal_False;
328     rInfo.bShearAllowed         = sal_False;
329     rInfo.bEdgeRadiusAllowed    = sal_False;
330     rInfo.bCanConvToPath        = sal_False;
331 
332     // no transparence for 3d objects
333     rInfo.bTransparenceAllowed = sal_False;
334 
335     // gradient depends on fillstyle
336     // BM *** check if SetItem is NULL ***
337     XFillStyle eFillStyle = ((XFillStyleItem&)(GetMergedItem(XATTR_FILLSTYLE))).GetValue();
338     rInfo.bGradientAllowed = (eFillStyle == XFILL_GRADIENT);
339 
340     // Umwandeln von 3D-Koerpern in Gruppe von Polygonen:
341     //
342     // Erst mal nicht moeglich, da die Erzeugung einer Gruppe von
343     // 2D-Polygonen notwendig waere, die tiefensortiert werden muessten,
344     // also bei Durchdringugnen auch gegeneinander geschnitten werden
345     // muessten. Auch die Texturkoorinaten waeren ein ungeloestes
346     // Problem.
347     rInfo.bCanConvToPoly = sal_False;
348     rInfo.bCanConvToContour = sal_False;
349     rInfo.bCanConvToPathLineToArea = sal_False;
350     rInfo.bCanConvToPolyLineToArea = sal_False;
351 }
352 
353 /*************************************************************************
354 |*
355 |* Layer setzen
356 |*
357 \************************************************************************/
358 
359 void E3dObject::NbcSetLayer(SdrLayerID nLayer)
360 {
361     SdrAttrObj::NbcSetLayer(nLayer);
362 
363     for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++)
364     {
365         E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a));
366 
367         if(pCandidate)
368         {
369             pCandidate->NbcSetLayer(nLayer);
370         }
371     }
372 }
373 
374 /*************************************************************************
375 |*
376 |* ObjList auch an SubList setzen
377 |*
378 \************************************************************************/
379 
380 void E3dObject::SetObjList(SdrObjList* pNewObjList)
381 {
382     SdrObject::SetObjList(pNewObjList);
383     maSubList.SetUpList(pNewObjList);
384 }
385 
386 /*************************************************************************
387 |*
388 |* Layer setzen
389 |*
390 \************************************************************************/
391 
392 void E3dObject::SetPage(SdrPage* pNewPage)
393 {
394     SdrAttrObj::SetPage(pNewPage);
395     maSubList.SetPage(pNewPage);
396 }
397 
398 /*************************************************************************
399 |*
400 |* Layer setzen
401 |*
402 \************************************************************************/
403 
404 void E3dObject::SetModel(SdrModel* pNewModel)
405 {
406     SdrAttrObj::SetModel(pNewModel);
407     maSubList.SetModel(pNewModel);
408 }
409 
410 /*************************************************************************
411 |*
412 |* resize object, used from old 2d interfaces, e.g. in Move/Scale dialog
413 |* (F4)
414 |*
415 \************************************************************************/
416 void E3dObject::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
417 {
418     // Bewegung in X,Y im Augkoordinatensystem
419     E3dScene* pScene = GetScene();
420 
421     if(pScene)
422     {
423         // transform pos from 2D world to 3D eye
424         const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact());
425         const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
426         basegfx::B2DPoint aScaleCenter2D((double)rRef.X(), (double)rRef.Y());
427         basegfx::B2DHomMatrix aInverseSceneTransform(rVCScene.getObjectTransformation());
428 
429         aInverseSceneTransform.invert();
430         aScaleCenter2D = aInverseSceneTransform * aScaleCenter2D;
431 
432         basegfx::B3DPoint aScaleCenter3D(aScaleCenter2D.getX(), aScaleCenter2D.getY(), 0.5);
433         basegfx::B3DHomMatrix aInverseViewToEye(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection());
434 
435         aInverseViewToEye.invert();
436         aScaleCenter3D = aInverseViewToEye * aScaleCenter3D;
437 
438         // scale-faktoren holen
439         double fScaleX(xFact);
440         double fScaleY(yFact);
441 
442         // build transform
443         basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation());
444         aInverseOrientation.invert();
445         basegfx::B3DHomMatrix mFullTransform(GetFullTransform());
446         basegfx::B3DHomMatrix mTrans(mFullTransform);
447 
448         mTrans *= aViewInfo3D.getOrientation();
449         mTrans.translate(-aScaleCenter3D.getX(), -aScaleCenter3D.getY(), -aScaleCenter3D.getZ());
450         mTrans.scale(fScaleX, fScaleY, 1.0);
451         mTrans.translate(aScaleCenter3D.getX(), aScaleCenter3D.getY(), aScaleCenter3D.getZ());
452         mTrans *= aInverseOrientation;
453         mFullTransform.invert();
454         mTrans *= mFullTransform;
455 
456         // anwenden
457         basegfx::B3DHomMatrix mObjTrans(GetTransform());
458         mObjTrans *= mTrans;
459 
460         E3DModifySceneSnapRectUpdater aUpdater(this);
461         SetTransform(mObjTrans);
462     }
463 }
464 
465 /*************************************************************************
466 |*
467 |* Objekt verschieben in 2D, wird bei Cursortasten benoetigt
468 |*
469 \************************************************************************/
470 void E3dObject::NbcMove(const Size& rSize)
471 {
472     // Bewegung in X,Y im Augkoordinatensystem
473     E3dScene* pScene = GetScene();
474 
475     if(pScene)
476     {
477         // Abmessungen der Szene in 3D und 2D als Vergleich
478         Rectangle aRect = pScene->GetSnapRect();
479 
480         // Transformation Weltkoordinaten bis eine VOR Objektkoordinaten holen
481         basegfx::B3DHomMatrix mInvDispTransform;
482         if(GetParentObj())
483         {
484             mInvDispTransform = GetParentObj()->GetFullTransform();
485             mInvDispTransform.invert();
486         }
487 
488         // BoundVolume from 3d world to 3d eye
489         const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact());
490         const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
491         basegfx::B3DRange aEyeVol(pScene->GetBoundVolume());
492         aEyeVol.transform(aViewInfo3D.getOrientation());
493 
494         // build relative movement vector in eye coordinates
495         basegfx::B3DPoint aMove(
496             (double)rSize.Width() * aEyeVol.getWidth() / (double)aRect.GetWidth(),
497             (double)-rSize.Height() * aEyeVol.getHeight() / (double)aRect.GetHeight(),
498             0.0);
499         basegfx::B3DPoint aPos(0.0, 0.0, 0.0);
500 
501         // movement vektor to local coordinates of objects' parent
502         basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation());
503         aInverseOrientation.invert();
504         basegfx::B3DHomMatrix aCompleteTrans(mInvDispTransform * aInverseOrientation);
505 
506         aMove = aCompleteTrans * aMove;
507         aPos = aCompleteTrans * aPos;
508 
509         // build transformation and apply
510         basegfx::B3DHomMatrix aTranslate;
511         aTranslate.translate(aMove.getX() - aPos.getX(), aMove.getY() - aPos.getY(), aMove.getZ() - aPos.getZ());
512 
513         E3DModifySceneSnapRectUpdater aUpdater(pScene);
514         SetTransform(aTranslate * GetTransform());
515     }
516 }
517 
518 /*************************************************************************
519 |*
520 |* liefere die Sublist, aber nur dann, wenn darin Objekte enthalten sind !
521 |*
522 \************************************************************************/
523 
524 SdrObjList* E3dObject::GetSubList() const
525 {
526     return &(const_cast< E3dObjList& >(maSubList));
527 }
528 
529 /*************************************************************************
530 |*
531 |* SnapRect berechnen
532 |*
533 \************************************************************************/
534 
535 void E3dObject::RecalcSnapRect()
536 {
537     maSnapRect = Rectangle();
538 
539     for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++)
540     {
541         E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a));
542 
543         if(pCandidate)
544         {
545             maSnapRect.Union(pCandidate->GetSnapRect());
546         }
547     }
548 }
549 
550 /*************************************************************************
551 |*
552 |* Einfuegen eines 3D-Objekts an den Parent weitermelden, damit dieser
553 |* ggf. eine Sonderbehandlung fuer spezielle Objekte durchfuehren kann
554 |* (z.B. Light/Label in E3dScene)
555 |*
556 \************************************************************************/
557 
558 void E3dObject::NewObjectInserted(const E3dObject* p3DObj)
559 {
560     if(GetParentObj())
561         GetParentObj()->NewObjectInserted(p3DObj);
562 }
563 
564 /*************************************************************************
565 |*
566 |* Parent ueber Aenderung der Struktur (z.B. durch Transformation)
567 |* informieren; dabei wird das Objekt, in welchem die Aenderung
568 |* aufgetreten ist, uebergeben
569 |*
570 \************************************************************************/
571 
572 void E3dObject::StructureChanged()
573 {
574     if ( GetParentObj() )
575     {
576         GetParentObj()->InvalidateBoundVolume();
577         GetParentObj()->StructureChanged();
578     }
579 }
580 
581 /*************************************************************************
582 |*
583 |* 3D-Objekt einfuegen
584 |*
585 \************************************************************************/
586 
587 void E3dObject::Insert3DObj(E3dObject* p3DObj)
588 {
589     DBG_ASSERT(p3DObj, "Insert3DObj mit NULL-Zeiger!");
590     SdrPage* pPg = pPage;
591     maSubList.InsertObject(p3DObj);
592     pPage = pPg;
593     InvalidateBoundVolume();
594     NewObjectInserted(p3DObj);
595     StructureChanged();
596 }
597 
598 void E3dObject::Remove3DObj(E3dObject* p3DObj)
599 {
600     DBG_ASSERT(p3DObj, "Remove3DObj mit NULL-Zeiger!");
601 
602     if(p3DObj->GetParentObj() == this)
603     {
604         SdrPage* pPg = pPage;
605         maSubList.RemoveObject(p3DObj->GetOrdNum());
606         pPage = pPg;
607 
608         InvalidateBoundVolume();
609         StructureChanged();
610     }
611 }
612 
613 /*************************************************************************
614 |*
615 |* Parent holen
616 |*
617 \************************************************************************/
618 
619 E3dObject* E3dObject::GetParentObj() const
620 {
621     E3dObject* pRetval = NULL;
622 
623     if(GetObjList()
624         && GetObjList()->GetOwnerObj()
625         && GetObjList()->GetOwnerObj()->ISA(E3dObject))
626         pRetval = ((E3dObject*)GetObjList()->GetOwnerObj());
627     return pRetval;
628 }
629 
630 /*************************************************************************
631 |*
632 |* Uebergeordnetes Szenenobjekt bestimmen
633 |*
634 \************************************************************************/
635 
636 E3dScene* E3dObject::GetScene() const
637 {
638     if(GetParentObj())
639         return GetParentObj()->GetScene();
640     return NULL;
641 }
642 
643 /*************************************************************************
644 |*
645 |* umschliessendes Volumen inklusive aller Kindobjekte berechnen
646 |*
647 \************************************************************************/
648 
649 basegfx::B3DRange E3dObject::RecalcBoundVolume() const
650 {
651     basegfx::B3DRange aRetval;
652     const sal_uInt32 nObjCnt(maSubList.GetObjCount());
653 
654     if(nObjCnt)
655     {
656         for(sal_uInt32 a(0); a < nObjCnt; a++)
657         {
658             const E3dObject* p3DObject = dynamic_cast< const E3dObject* >(maSubList.GetObj(a));
659 
660             if(p3DObject)
661             {
662                 basegfx::B3DRange aLocalRange(p3DObject->GetBoundVolume());
663                 aLocalRange.transform(p3DObject->GetTransform());
664                 aRetval.expand(aLocalRange);
665             }
666         }
667     }
668     else
669     {
670         // single 3D object
671         const sdr::contact::ViewContactOfE3d* pVCOfE3D = dynamic_cast< const sdr::contact::ViewContactOfE3d* >(&GetViewContact());
672 
673         if(pVCOfE3D)
674         {
675             // BoundVolume is without 3D object transformation, use correct sequence
676             const drawinglayer::primitive3d::Primitive3DSequence xLocalSequence(pVCOfE3D->getVIP3DSWithoutObjectTransform());
677 
678             if(xLocalSequence.hasElements())
679             {
680                 const uno::Sequence< beans::PropertyValue > aEmptyParameters;
681                 const drawinglayer::geometry::ViewInformation3D aLocalViewInformation3D(aEmptyParameters);
682 
683                 aRetval = drawinglayer::primitive3d::getB3DRangeFromPrimitive3DSequence(
684                     xLocalSequence, aLocalViewInformation3D);
685             }
686         }
687     }
688 
689     return aRetval;
690 }
691 
692 /*************************************************************************
693 |*
694 |* umschliessendes Volumen zurueckgeben und ggf. neu berechnen
695 |*
696 \************************************************************************/
697 
698 const basegfx::B3DRange& E3dObject::GetBoundVolume() const
699 {
700     if(maLocalBoundVol.isEmpty())
701     {
702         const_cast< E3dObject* >(this)->maLocalBoundVol = RecalcBoundVolume();
703     }
704 
705     return maLocalBoundVol;
706 }
707 
708 void E3dObject::InvalidateBoundVolume()
709 {
710     maLocalBoundVol.reset();
711 }
712 
713 /*************************************************************************
714 |*
715 |* Aederung des BoundVolumes an alle Kindobjekte weitergeben
716 |*
717 \************************************************************************/
718 
719 void E3dObject::SetBoundVolInvalid()
720 {
721     InvalidateBoundVolume();
722 
723     for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++)
724     {
725         E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a));
726 
727         if(pCandidate)
728         {
729             pCandidate->SetBoundVolInvalid();
730         }
731     }
732 }
733 
734 /*************************************************************************
735 |*
736 |* Aederung der Transformation an alle Kindobjekte weitergeben
737 |*
738 \************************************************************************/
739 
740 void E3dObject::SetTransformChanged()
741 {
742     InvalidateBoundVolume();
743     mbTfHasChanged = true;
744 
745     for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++)
746     {
747         E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a));
748 
749         if(pCandidate)
750         {
751             pCandidate->SetTransformChanged();
752         }
753     }
754 }
755 
756 /*************************************************************************
757 |*
758 |* hierarchische Transformation ueber alle Parents bestimmen, in
759 |* maFullTransform ablegen und diese zurueckgeben
760 |*
761 \************************************************************************/
762 
763 const basegfx::B3DHomMatrix& E3dObject::GetFullTransform() const
764 {
765     if(mbTfHasChanged)
766     {
767         basegfx::B3DHomMatrix aNewFullTransformation(maTransformation);
768 
769         if ( GetParentObj() )
770         {
771             aNewFullTransformation = GetParentObj()->GetFullTransform() * aNewFullTransformation;
772         }
773 
774         const_cast< E3dObject* >(this)->maFullTransform = aNewFullTransformation;
775         const_cast< E3dObject* >(this)->mbTfHasChanged = false;
776     }
777 
778     return maFullTransform;
779 }
780 
781 /*************************************************************************
782 |*
783 |* Transformationsmatrix abfragen
784 |*
785 \************************************************************************/
786 
787 const basegfx::B3DHomMatrix& E3dObject::GetTransform() const
788 {
789     return maTransformation;
790 }
791 
792 /*************************************************************************
793 |*
794 |* Transformationsmatrix setzen
795 |*
796 \************************************************************************/
797 
798 void E3dObject::NbcSetTransform(const basegfx::B3DHomMatrix& rMatrix)
799 {
800     if(maTransformation != rMatrix)
801     {
802         maTransformation = rMatrix;
803         SetTransformChanged();
804         StructureChanged();
805     }
806 }
807 
808 /*************************************************************************
809 |*
810 |* Transformationsmatrix setzen mit Repaint-Broadcast
811 |*
812 \************************************************************************/
813 
814 void E3dObject::SetTransform(const basegfx::B3DHomMatrix& rMatrix)
815 {
816     if(rMatrix != maTransformation)
817     {
818         // #110094#-14 SendRepaintBroadcast();
819         NbcSetTransform(rMatrix);
820         SetChanged();
821         BroadcastObjectChange();
822         if (pUserCall != NULL) pUserCall->Changed(*this, SDRUSERCALL_RESIZE, Rectangle());
823     }
824 }
825 
826 /*************************************************************************
827 |*
828 |* Linien fuer die Wireframe-Darstellung des Objekts dem uebergebenen
829 |* basegfx::B3DPolygon hinzufuegen
830 |*
831 \************************************************************************/
832 
833 basegfx::B3DPolyPolygon E3dObject::CreateWireframe() const
834 {
835     const basegfx::B3DRange aBoundVolume(GetBoundVolume());
836     return basegfx::tools::createCubePolyPolygonFromB3DRange(aBoundVolume);
837 }
838 
839 /*************************************************************************
840 |*
841 |* Get the name of the object (singular)
842 |*
843 \************************************************************************/
844 
845 void E3dObject::TakeObjNameSingul(XubString& rName) const
846 {
847     rName=ImpGetResStr(STR_ObjNameSingulObj3d);
848 
849     String aName( GetName() );
850     if(aName.Len())
851     {
852         rName += sal_Unicode(' ');
853         rName += sal_Unicode('\'');
854         rName += aName;
855         rName += sal_Unicode('\'');
856     }
857 }
858 
859 /*************************************************************************
860 |*
861 |* Get the name of the object (plural)
862 |*
863 \************************************************************************/
864 
865 void E3dObject::TakeObjNamePlural(XubString& rName) const
866 {
867     rName=ImpGetResStr(STR_ObjNamePluralObj3d);
868 }
869 
870 /*************************************************************************
871 |*
872 |* Zuweisungsoperator
873 |*
874 \************************************************************************/
875 
876 void E3dObject::operator=(const SdrObject& rObj)
877 {
878     SdrObject::operator=(rObj);
879 
880     const E3dObject& r3DObj = (const E3dObject&) rObj;
881     if (r3DObj.GetSubList())
882     {
883         maSubList.CopyObjects(*r3DObj.GetSubList());
884     }
885 
886     // BoundVol kann uebernommen werden, da die Childs auch kopiert werden
887     maLocalBoundVol  = r3DObj.maLocalBoundVol;
888     maTransformation = r3DObj.maTransformation;
889 
890     // Da sich der Parent geaendert haben kann, Gesamttransformation beim
891     // naechsten Mal auf jeden Fall neu bestimmen
892     SetTransformChanged();
893 
894     // Selektionsstatus kopieren
895     mbIsSelected = r3DObj.mbIsSelected;
896 }
897 
898 /*************************************************************************
899 |*
900 |* erstelle neues GeoData-Objekt
901 |*
902 \************************************************************************/
903 
904 SdrObjGeoData *E3dObject::NewGeoData() const
905 {
906     // Theoretisch duerfen auch nur Szenen ihre GeoDatas erstellen und verwalten !!
907     // AW: Dies stimmt nicht mehr, diese Stelle ist mit der neuen Engine OK!
908     return new E3DObjGeoData;
909 }
910 
911 /*************************************************************************
912 |*
913 |* uebergebe aktuelle werte an das GeoData-Objekt
914 |*
915 \************************************************************************/
916 
917 void E3dObject::SaveGeoData(SdrObjGeoData& rGeo) const
918 {
919     SdrAttrObj::SaveGeoData (rGeo);
920 
921     ((E3DObjGeoData &) rGeo).maLocalBoundVol  = maLocalBoundVol;
922     ((E3DObjGeoData &) rGeo).maTransformation = maTransformation;
923 }
924 
925 /*************************************************************************
926 |*
927 |* uebernehme werte aus dem GeoData-Objekt
928 |*
929 \************************************************************************/
930 
931 void E3dObject::RestGeoData(const SdrObjGeoData& rGeo)
932 {
933     maLocalBoundVol = ((E3DObjGeoData &) rGeo).maLocalBoundVol;
934     E3DModifySceneSnapRectUpdater aUpdater(this);
935     NbcSetTransform(((E3DObjGeoData &) rGeo).maTransformation);
936     SdrAttrObj::RestGeoData (rGeo);
937 }
938 
939 /*************************************************************************
940 |*
941 |* Rotation eines 3d-Koerpers
942 |*
943 \************************************************************************/
944 // 2D-rotation eines 3D-Koerpers, normalerweise macht das die Szene selbst
945 // Ist aber eine korrekte Implementierung, denn alles was passiert ist eine
946 // Rotation um die Achse die senkrecht auf dem Bildschirm steht und zwar
947 // unabhaengig davon, wie die Szene bisher gedreht worden ist.
948 
949 void E3dObject::NbcRotate(const Point& rRef, long nWink, double sn, double cs)
950 {
951     // Also derzeit sind die Klebepunkte relativ zum aOutRect der Szene definiert. Vor dem Drehen
952     // werden die Klebepunkte relativ zur Seite definiert. Sie nehmen an der Drehung der Szene noch nicht Teil
953     // dafuer gibt es den
954     SetGlueReallyAbsolute(sal_True);
955 
956     // SendRepaintBroadcast();
957     double fWinkelInRad = nWink/100 * F_PI180;
958 
959     basegfx::B3DHomMatrix aRotateZ;
960     aRotateZ.rotate(0.0, 0.0, fWinkelInRad);
961     NbcSetTransform(aRotateZ * GetTransform());
962 
963     SetRectsDirty();    // Veranlasst eine Neuberechnung aller BoundRects
964     NbcRotateGluePoints(rRef,nWink,sn,cs);  // Rotiert die Klebepunkte (die haben noch Koordinaten relativ
965                                             // zum Urpsung des Blattes
966     SetGlueReallyAbsolute(sal_False);  // ab jetzt sind sie wieder relativ zum BoundRect (also dem aOutRect definiert)
967 }
968 
969 /*************************************************************************/
970 
971 //////////////////////////////////////////////////////////////////////////////
972 
973 sdr::properties::BaseProperties* E3dCompoundObject::CreateObjectSpecificProperties()
974 {
975     return new sdr::properties::E3dCompoundProperties(*this);
976 }
977 
978 ////////////////////////////////////////////////////////////////////////////////////////////////////
979 
980 TYPEINIT1(E3dCompoundObject, E3dObject);
981 
982 /*************************************************************************
983 |*
984 |* Konstruktor
985 |*
986 \************************************************************************/
987 
988 E3dCompoundObject::E3dCompoundObject()
989 :   E3dObject(),
990     aMaterialAmbientColor(),
991     bCreateNormals(false),
992     bCreateTexture(false)
993 {
994     // Defaults setzen
995     E3dDefaultAttributes aDefault;
996     SetDefaultAttributes(aDefault);
997 }
998 
999 E3dCompoundObject::E3dCompoundObject(E3dDefaultAttributes& rDefault)
1000 :   E3dObject(),
1001     aMaterialAmbientColor(),
1002     bCreateNormals(false),
1003     bCreateTexture(false)
1004 {
1005     // Defaults setzen
1006     SetDefaultAttributes(rDefault);
1007 }
1008 
1009 void E3dCompoundObject::SetDefaultAttributes(E3dDefaultAttributes& rDefault)
1010 {
1011     // Defaults setzen
1012     aMaterialAmbientColor = rDefault.GetDefaultAmbientColor();
1013 
1014     bCreateNormals = rDefault.GetDefaultCreateNormals();
1015     bCreateTexture = rDefault.GetDefaultCreateTexture();
1016 }
1017 
1018 /*************************************************************************
1019 |*
1020 |* Destruktor
1021 |*
1022 \************************************************************************/
1023 
1024 E3dCompoundObject::~E3dCompoundObject ()
1025 {
1026 }
1027 
1028 /*************************************************************************
1029 |*
1030 |* Drag-Polygon zurueckgeben
1031 |*
1032 \************************************************************************/
1033 
1034 basegfx::B2DPolyPolygon E3dCompoundObject::TakeXorPoly() const
1035 {
1036     basegfx::B2DPolyPolygon aRetval;
1037     const uno::Sequence< beans::PropertyValue > aEmptyParameters;
1038     drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters);
1039     E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this);
1040 
1041     if(pRootScene)
1042     {
1043         const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact());
1044         const basegfx::B3DPolyPolygon aCubePolyPolygon(CreateWireframe());
1045         aRetval = basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(aCubePolyPolygon,
1046             aViewInfo3D.getObjectToView() * GetTransform());
1047         aRetval.transform(rVCScene.getObjectTransformation());
1048     }
1049 
1050     return aRetval;
1051 }
1052 
1053 /*************************************************************************
1054 |*
1055 |* Anzahl der Handles zurueckgeben
1056 |*
1057 \************************************************************************/
1058 
1059 sal_uInt32 E3dCompoundObject::GetHdlCount() const
1060 {
1061     // 8 Eckpunkte + 1 E3dVolumeMarker (= Wireframe-Darstellung)
1062     return 9L;
1063 }
1064 
1065 /*************************************************************************
1066 |*
1067 |* Handle-Liste fuellen
1068 |*
1069 \************************************************************************/
1070 
1071 void E3dCompoundObject::AddToHdlList(SdrHdlList& rHdlList) const
1072 {
1073     const uno::Sequence< beans::PropertyValue > aEmptyParameters;
1074     drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters);
1075     E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this);
1076 
1077     if(pRootScene)
1078     {
1079         const basegfx::B3DRange aBoundVolume(GetBoundVolume());
1080 
1081         if(!aBoundVolume.isEmpty())
1082         {
1083             const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact());
1084 
1085             for(sal_uInt32 a(0); a < 8; a++)
1086             {
1087                 basegfx::B3DPoint aPos3D;
1088 
1089                 switch(a)
1090                 {
1091                     case 0 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMinZ()); break;
1092                     case 1 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break;
1093                     case 2 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMinZ()); break;
1094                     case 3 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break;
1095                     case 4 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMinZ()); break;
1096                     case 5 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break;
1097                     case 6 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMinZ()); break;
1098                     case 7 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break;
1099                 }
1100 
1101                 // to 3d view coor
1102                 aPos3D *= aViewInfo3D.getObjectToView() * GetTransform();
1103 
1104                 // create 2d relative scene
1105                 basegfx::B2DPoint aPos2D(aPos3D.getX(), aPos3D.getY());
1106 
1107                 // to 2d world coor
1108                 aPos2D *= rVCScene.getObjectTransformation();
1109 
1110                 rHdlList.AddHdl(new SdrHdl(Point(basegfx::fround(aPos2D.getX()), basegfx::fround(aPos2D.getY())), HDL_BWGT));
1111             }
1112         }
1113     }
1114 
1115     const basegfx::B2DPolyPolygon aPolyPolygon(TakeXorPoly());
1116 
1117     if(aPolyPolygon.count())
1118     {
1119         E3dVolumeMarker* pVolMarker = new E3dVolumeMarker(aPolyPolygon);
1120         rHdlList.AddHdl(pVolMarker);
1121     }
1122 }
1123 
1124 /*************************************************************************
1125 |*
1126 |* Identifier zurueckgeben
1127 |*
1128 \************************************************************************/
1129 
1130 sal_uInt16 E3dCompoundObject::GetObjIdentifier() const
1131 {
1132     return E3D_COMPOUNDOBJ_ID;
1133 }
1134 
1135 /*************************************************************************
1136 |*
1137 |* SnapRect berechnen
1138 |*
1139 \************************************************************************/
1140 
1141 void E3dCompoundObject::RecalcSnapRect()
1142 {
1143     const uno::Sequence< beans::PropertyValue > aEmptyParameters;
1144     drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters);
1145     E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this);
1146     maSnapRect = Rectangle();
1147 
1148     if(pRootScene)
1149     {
1150         // get VC of 3D candidate
1151         const sdr::contact::ViewContactOfE3d* pVCOfE3D = dynamic_cast< const sdr::contact::ViewContactOfE3d* >(&GetViewContact());
1152 
1153         if(pVCOfE3D)
1154         {
1155             // get 3D primitive sequence
1156             const drawinglayer::primitive3d::Primitive3DSequence xLocalSequence(pVCOfE3D->getViewIndependentPrimitive3DSequence());
1157 
1158             if(xLocalSequence.hasElements())
1159             {
1160                 // get BoundVolume
1161                 basegfx::B3DRange aBoundVolume(drawinglayer::primitive3d::getB3DRangeFromPrimitive3DSequence(
1162                     xLocalSequence, aViewInfo3D));
1163 
1164                 // transform bound volume to relative scene coordinates
1165                 aBoundVolume.transform(aViewInfo3D.getObjectToView());
1166 
1167                 // build 2d relative scene range
1168                 basegfx::B2DRange aSnapRange(
1169                     aBoundVolume.getMinX(), aBoundVolume.getMinY(),
1170                     aBoundVolume.getMaxX(), aBoundVolume.getMaxY());
1171 
1172                 // transform to 2D world coordiantes
1173                 const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact());
1174                 aSnapRange.transform(rVCScene.getObjectTransformation());
1175 
1176                 // snap to integer
1177                 maSnapRect = Rectangle(
1178                     sal_Int32(floor(aSnapRange.getMinX())), sal_Int32(floor(aSnapRange.getMinY())),
1179                     sal_Int32(ceil(aSnapRange.getMaxX())), sal_Int32(ceil(aSnapRange.getMaxY())));
1180             }
1181         }
1182     }
1183 }
1184 
1185 /*************************************************************************
1186 |*
1187 |* Copy-Operator
1188 |*
1189 \************************************************************************/
1190 
1191 void E3dCompoundObject::operator=(const SdrObject& rObj)
1192 {
1193     // erstmal alle Childs kopieren
1194     E3dObject::operator=(rObj);
1195 
1196     // weitere Parameter kopieren
1197     const E3dCompoundObject& r3DObj = (const E3dCompoundObject&) rObj;
1198 
1199     bCreateNormals = r3DObj.bCreateNormals;
1200     bCreateTexture = r3DObj.bCreateTexture;
1201     aMaterialAmbientColor = r3DObj.aMaterialAmbientColor;
1202 }
1203 
1204 /*************************************************************************
1205 |*
1206 |* Parameter Geometrieerzeugung setzen
1207 |*
1208 \************************************************************************/
1209 
1210 void E3dCompoundObject::SetCreateNormals(sal_Bool bNew)
1211 {
1212     if(bCreateNormals != bNew)
1213     {
1214         bCreateNormals = bNew;
1215         ActionChanged();
1216     }
1217 }
1218 
1219 void E3dCompoundObject::SetCreateTexture(sal_Bool bNew)
1220 {
1221     if(bCreateTexture != bNew)
1222     {
1223         bCreateTexture = bNew;
1224         ActionChanged();
1225     }
1226 }
1227 
1228 /*************************************************************************
1229 |*
1230 |* Material des Objektes
1231 |*
1232 \************************************************************************/
1233 
1234 void E3dCompoundObject::SetMaterialAmbientColor(const Color& rColor)
1235 {
1236     if(aMaterialAmbientColor != rColor)
1237     {
1238         aMaterialAmbientColor = rColor;
1239     }
1240 }
1241 
1242 /*************************************************************************
1243 |*
1244 |* convert given basegfx::B3DPolyPolygon to screen coor
1245 |*
1246 \************************************************************************/
1247 
1248 basegfx::B2DPolyPolygon E3dCompoundObject::TransformToScreenCoor(const basegfx::B3DPolyPolygon& rCandidate)
1249 {
1250     const uno::Sequence< beans::PropertyValue > aEmptyParameters;
1251     drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters);
1252     E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this);
1253     basegfx::B2DPolyPolygon aRetval;
1254 
1255     if(pRootScene)
1256     {
1257         aRetval = basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(rCandidate,
1258             aViewInfo3D.getObjectToView() * GetTransform());
1259         const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact());
1260         aRetval.transform(rVCScene.getObjectTransformation());
1261     }
1262 
1263     return aRetval;
1264 }
1265 
1266 sal_Bool E3dCompoundObject::IsAOrdNumRemapCandidate(E3dScene*& prScene) const
1267 {
1268     if(GetObjList()
1269         && GetObjList()->GetOwnerObj()
1270         && GetObjList()->GetOwnerObj()->ISA(E3dScene))
1271     {
1272         prScene = (E3dScene*)GetObjList()->GetOwnerObj();
1273         return sal_True;
1274     }
1275 
1276     return sal_False;
1277 }
1278 
1279 //////////////////////////////////////////////////////////////////////////////
1280 // eof
1281