xref: /aoo41x/main/svx/source/engine3d/obj3d.cxx (revision cdf0e10c)
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