Files
libreoffice/svx/source/engine3d/scene3d.cxx
Vladimir Glazounov dd0542ea43 INTEGRATION: CWS dr33 (1.22.252); FILE MERGED
2005/02/14 18:50:59 dr 1.22.252.2: #i42367# remove non-ASCII characters from C++ sources
2005/02/07 15:50:45 dr 1.22.252.1: #i36782# scape non-ASCII characters
2005-02-16 16:55:24 +00:00

1823 lines
57 KiB
C++

/*************************************************************************
*
* $RCSfile: scene3d.cxx,v $
*
* $Revision: 1.23 $
*
* last change: $Author: vg $ $Date: 2005-02-16 17:55:24 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc., October, 2000
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Sun Industry Standards Source License Version 1.1
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 (the "License"); You may not use this file
* except in compliance with the License. You may obtain a copy of the
* License at http://www.openoffice.org/license.html.
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
* Copyright: 2000 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): _______________________________________
*
*
************************************************************************/
#define ITEMID_COLOR SID_ATTR_3D_LIGHTCOLOR
#include "svdstr.hrc"
#include "svdglob.hxx"
#ifndef _SVDITER_HXX
#include "svditer.hxx"
#endif
#ifndef _SVDIO_HXX
#include "svdio.hxx"
#endif
#if defined( UNX ) || defined( ICC )
#include <stdlib.h>
#endif
#ifndef _E3D_GLOBL3D_HXX
#include "globl3d.hxx"
#endif
#ifndef _SVDPAGE_HXX
#include "svdpage.hxx"
#endif
#ifndef _SFXSTYLE_HXX
#include <svtools/style.hxx>
#endif
#ifndef _E3D_SCENE3D_HXX
#include "scene3d.hxx"
#endif
#ifndef _E3D_UNDO_HXX
#include "e3dundo.hxx"
#endif
#ifndef _B3D_BASE3D_HXX
#include <goodies/base3d.hxx>
#endif
#ifndef _E3D_PLIGHT3D_HXX
#include "plight3d.hxx"
#endif
#ifndef _E3D_DLIGHT3D_HXX
#include "dlight3d.hxx"
#endif
#ifndef _SVDTRANS_HXX
#include "svdtrans.hxx"
#endif
#ifndef _SVX_SVXIDS_HRC
#include "svxids.hrc"
#endif
#ifndef _SVX_COLRITEM_HXX
#include "colritem.hxx"
#endif
#ifndef _SVXE3DITEM_HXX
#include "e3ditem.hxx"
#endif
#ifndef _SVX_XLNTRIT_HXX
#include "xlntrit.hxx"
#endif
#ifndef _SVX_XFLTRIT_HXX
#include "xfltrit.hxx"
#endif
#ifndef _SVX3DITEMS_HXX
#include "svx3ditems.hxx"
#endif
#ifndef _SFX_WHITER_HXX
#include <svtools/whiter.hxx>
#endif
#ifndef _SVX_XFLFTRIT_HXX
#include "xflftrit.hxx"
#endif
#ifndef _SDR_PROPERTIES_E3DSCENEPROPERTIES_HXX
#include <svx/sdr/properties/e3dsceneproperties.hxx>
#endif
// #110094#
#ifndef _SDR_CONTACT_VIEWCONTACTOFE3DSCENE_HXX
#include <svx/sdr/contact/viewcontactofe3dscene.hxx>
#endif
// for ::std::sort
#include <algorithm>
#define ITEMVALUE(ItemSet,Id,Cast) ((const Cast&)(ItemSet).Get(Id)).GetValue()
//////////////////////////////////////////////////////////////////////////////
// #110988#
class ImpRemap3DDepth
{
sal_uInt32 mnOrdNum;
double mfMinimalDepth;
// bitfield
unsigned mbIsScene : 1;
public:
ImpRemap3DDepth(sal_uInt32 nOrdNum, double fMinimalDepth);
ImpRemap3DDepth(sal_uInt32 nOrdNum);
~ImpRemap3DDepth();
// for ::std::sort
bool operator<(const ImpRemap3DDepth& rComp) const;
sal_uInt32 GetOrdNum() const { return mnOrdNum; }
sal_Bool IsScene() const { return mbIsScene; }
};
ImpRemap3DDepth::ImpRemap3DDepth(sal_uInt32 nOrdNum, double fMinimalDepth)
: mnOrdNum(nOrdNum),
mfMinimalDepth(fMinimalDepth),
mbIsScene(sal_False)
{
}
ImpRemap3DDepth::ImpRemap3DDepth(sal_uInt32 nOrdNum)
: mnOrdNum(nOrdNum),
mbIsScene(sal_True)
{
}
ImpRemap3DDepth::~ImpRemap3DDepth()
{
}
bool ImpRemap3DDepth::operator<(const ImpRemap3DDepth& rComp) const
{
if(IsScene())
{
return sal_False;
}
else
{
if(rComp.IsScene())
{
return sal_True;
}
else
{
return mfMinimalDepth < rComp.mfMinimalDepth;
}
}
}
// typedefs for a vector of ImpRemap3DDepths
typedef ::std::vector< ImpRemap3DDepth > ImpRemap3DDepthVector;
//////////////////////////////////////////////////////////////////////////////
// #110988#
class Imp3DDepthRemapper
{
ImpRemap3DDepthVector maVector;
public:
Imp3DDepthRemapper(E3dScene& rScene);
~Imp3DDepthRemapper();
sal_uInt32 RemapOrdNum(sal_uInt32 nOrdNum) const;
};
Imp3DDepthRemapper::Imp3DDepthRemapper(E3dScene& rScene)
{
// only called when rScene.GetSubList() and nObjCount > 1L
SdrObjList* pList = rScene.GetSubList();
const sal_uInt32 nObjCount(pList->GetObjCount());
for(sal_uInt32 a(0L); a < nObjCount; a++)
{
SdrObject* pCandidate = pList->GetObj(a);
if(pCandidate)
{
if(pCandidate->ISA(E3dCompoundObject))
{
// single 3d object, calc depth
const double fMinimalDepth(((E3dCompoundObject*)pCandidate)->GetMinimalDepthInViewCoor(rScene));
ImpRemap3DDepth aEntry(a, fMinimalDepth);
maVector.push_back(aEntry);
}
else
{
// scene, use standard entry for scene
ImpRemap3DDepth aEntry(a);
maVector.push_back(aEntry);
}
}
}
// now, we need to sort the maVector by it's members minimal depth. The
// smaller, the nearer to the viewer.
::std::sort(maVector.begin(), maVector.end());
}
Imp3DDepthRemapper::~Imp3DDepthRemapper()
{
}
sal_uInt32 Imp3DDepthRemapper::RemapOrdNum(sal_uInt32 nOrdNum) const
{
if(nOrdNum < maVector.size())
{
nOrdNum = maVector[(maVector.size() - 1) - nOrdNum].GetOrdNum();
}
return nOrdNum;
}
//////////////////////////////////////////////////////////////////////////////
// BaseProperties section
sdr::properties::BaseProperties* E3dScene::CreateObjectSpecificProperties()
{
return new sdr::properties::E3dSceneProperties(*this);
}
//////////////////////////////////////////////////////////////////////////////
// #110094# DrawContact section
sdr::contact::ViewContact* E3dScene::CreateObjectSpecificViewContact()
{
return new sdr::contact::ViewContactOfE3dScene(*this);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
TYPEINIT1(E3dScene, E3dObject);
/*************************************************************************
|*
|* E3dScene-Konstruktor
|*
\************************************************************************/
E3dScene::E3dScene()
: E3dObject(),
aCamera(Vector3D(0,0,4), Vector3D()),
bDoubleBuffered(FALSE),
bClipping(FALSE),
//BFS01nSaveStatus (0),
//BFS01nRestStatus (0),
bFitInSnapRect(TRUE),
aPaintTime(),
nDisplayQuality(255),
// #110988#
mp3DDepthRemapper(0L),
bDrawOnlySelected(FALSE)
{
// Defaults setzen
E3dDefaultAttributes aDefault;
SetDefaultAttributes(aDefault);
}
E3dScene::E3dScene(E3dDefaultAttributes& rDefault)
: E3dObject(),
aCamera(Vector3D(0,0,4), Vector3D()),
bDoubleBuffered(FALSE),
bClipping(FALSE),
//BFS01nSaveStatus (0),
//BFS01nRestStatus (0),
bFitInSnapRect(TRUE),
aPaintTime(),
nDisplayQuality(255),
// #110988#
mp3DDepthRemapper(0L),
bDrawOnlySelected(FALSE)
{
// Defaults setzen
SetDefaultAttributes(rDefault);
}
void E3dScene::SetDefaultAttributes(E3dDefaultAttributes& rDefault)
{
// Fuer OS/2 die FP-Exceptions abschalten
#if defined(OS2)
#define SC_FPEXCEPTIONS_ON() _control87( MCW_EM, 0 )
#define SC_FPEXCEPTIONS_OFF() _control87( MCW_EM, MCW_EM )
SC_FPEXCEPTIONS_OFF();
#endif
// Fuer WIN95/NT die FP-Exceptions abschalten
#if defined(WNT) || defined(WIN)
#define SC_FPEXCEPTIONS_ON() _control87( _MCW_EM, 0 )
#define SC_FPEXCEPTIONS_OFF() _control87( _MCW_EM, _MCW_EM )
SC_FPEXCEPTIONS_OFF();
#endif
// Defaults setzen
// set defaults for LightGroup from ItemPool
aLightGroup.SetModelTwoSide(GetTwoSidedLighting());
aLightGroup.SetIntensity( GetLightColor1(), Base3DMaterialDiffuse, Base3DLight0);
aLightGroup.SetIntensity( GetLightColor2(), Base3DMaterialDiffuse, Base3DLight1);
aLightGroup.SetIntensity( GetLightColor3(), Base3DMaterialDiffuse, Base3DLight2);
aLightGroup.SetIntensity( GetLightColor4(), Base3DMaterialDiffuse, Base3DLight3);
aLightGroup.SetIntensity( GetLightColor5(), Base3DMaterialDiffuse, Base3DLight4);
aLightGroup.SetIntensity( GetLightColor6(), Base3DMaterialDiffuse, Base3DLight5);
aLightGroup.SetIntensity( GetLightColor7(), Base3DMaterialDiffuse, Base3DLight6);
aLightGroup.SetIntensity( GetLightColor8(), Base3DMaterialDiffuse, Base3DLight7);
aLightGroup.SetGlobalAmbientLight(GetGlobalAmbientColor());
aLightGroup.Enable( GetLightOnOff1(), Base3DLight0);
aLightGroup.Enable( GetLightOnOff2(), Base3DLight1);
aLightGroup.Enable( GetLightOnOff3(), Base3DLight2);
aLightGroup.Enable( GetLightOnOff4(), Base3DLight3);
aLightGroup.Enable( GetLightOnOff5(), Base3DLight4);
aLightGroup.Enable( GetLightOnOff6(), Base3DLight5);
aLightGroup.Enable( GetLightOnOff7(), Base3DLight6);
aLightGroup.Enable( GetLightOnOff8(), Base3DLight7);
aLightGroup.SetDirection( GetLightDirection1(), Base3DLight0);
aLightGroup.SetDirection( GetLightDirection2(), Base3DLight1);
aLightGroup.SetDirection( GetLightDirection3(), Base3DLight2);
aLightGroup.SetDirection( GetLightDirection4(), Base3DLight3);
aLightGroup.SetDirection( GetLightDirection5(), Base3DLight4);
aLightGroup.SetDirection( GetLightDirection6(), Base3DLight5);
aLightGroup.SetDirection( GetLightDirection7(), Base3DLight6);
aLightGroup.SetDirection( GetLightDirection8(), Base3DLight7);
bDither = rDefault.GetDefaultDither();
// Alte Werte initialisieren
aCamera.SetViewWindow(-2, -2, 4, 4);
aCameraSet.SetDeviceRectangle(-2, 2, -2, 2);
aCamera.SetDeviceWindow(Rectangle(0, 0, 10, 10));
Rectangle aRect(0, 0, 10, 10);
aCameraSet.SetViewportRectangle(aRect);
//BFS01nSortingMode = E3D_SORT_FAST_SORTING | E3D_SORT_IN_PARENTS | E3D_SORT_TEST_LENGTH;
// set defaults for Camera from ItemPool
aCamera.SetProjection(GetPerspective());
Vector3D aActualPosition = aCamera.GetPosition();
double fNew = GetDistance();
if(fabs(fNew - aActualPosition.Z()) > 1.0)
{
aCamera.SetPosition( Vector3D( aActualPosition.X(), aActualPosition.Y(), fNew) );
}
fNew = GetFocalLength() / 100.0;
aCamera.SetFocalLength(fNew);
}
/*************************************************************************
|*
|* Destruktor
|*
\************************************************************************/
E3dScene::~E3dScene()
{
// #110988#
ImpCleanup3DDepthMapper();
}
// #110988#
void E3dScene::ImpCleanup3DDepthMapper()
{
if(mp3DDepthRemapper)
{
delete mp3DDepthRemapper;
mp3DDepthRemapper = 0L;
}
}
// #110988#
sal_uInt32 E3dScene::RemapOrdNum(sal_uInt32 nOrdNum) const
{
if(!mp3DDepthRemapper)
{
const sal_uInt32 nObjCount(GetSubList() ? GetSubList()->GetObjCount() : 0L);
if(nObjCount > 1L)
{
((E3dScene*)this)->mp3DDepthRemapper = new Imp3DDepthRemapper((E3dScene&)(*this));
}
}
if(mp3DDepthRemapper)
{
return mp3DDepthRemapper->RemapOrdNum(nOrdNum);
}
return nOrdNum;
}
/*************************************************************************
|*
|* Feststellen, ob die Szene transparente Teile enthaelt
|*
\************************************************************************/
BOOL E3dScene::AreThereTransparentParts() const
{
BOOL bRetval(FALSE);
SdrObjListIter a3DIterator(*pSub, IM_DEEPWITHGROUPS);
while ( !bRetval && a3DIterator.IsMore() )
{
SdrObject* pObj = a3DIterator.Next();
// Nur darstellbare Objekte bewerten
if(pObj->ISA(E3dCompoundObject))
{
// get const ItemSet reference
const SfxItemSet& rSet = pObj->GetMergedItemSet();
// Flaechenattribut testen
UINT16 nFillTrans = ((const XFillTransparenceItem&)(rSet.Get(XATTR_FILLTRANSPARENCE))).GetValue();
if(nFillTrans != 0)
bRetval = TRUE;
if(!bRetval)
{
// Linienattribut testen
UINT16 nLineTransparence = ((const XLineTransparenceItem&)(rSet.Get(XATTR_LINETRANSPARENCE))).GetValue();
if(nLineTransparence != 0)
bRetval = TRUE;
if(!bRetval)
{
// test FloatTransparence
const XFillFloatTransparenceItem& rFloatTrans = ((const XFillFloatTransparenceItem&)(rSet.Get(XATTR_FILLFLOATTRANSPARENCE)));
if(rFloatTrans.IsEnabled())
bRetval = TRUE;
}
}
}
}
return bRetval;
}
/*************************************************************************
|*
|* Identifier zurueckgeben
|*
\************************************************************************/
UINT16 E3dScene::GetObjIdentifier() const
{
return E3D_SCENE_ID;
}
/*************************************************************************
|*
|* Anzahl der Handles zurueckgeben
|*
\************************************************************************/
USHORT E3dScene::GetHdlCount() const
{
// Ueberladung aus E3dObject rueckgaengig machen
return SdrAttrObj::GetHdlCount();
}
/*************************************************************************
|*
|* Handle-Liste fuellen
|*
\************************************************************************/
void E3dScene::AddToHdlList(SdrHdlList& rHdlList) const
{
// Ueberladung aus E3dObject rueckgaengig machen
SdrAttrObj::AddToHdlList(rHdlList);
}
/*************************************************************************
|*
\************************************************************************/
FASTBOOL E3dScene::HasSpecialDrag() const
{
return FALSE;
}
/*************************************************************************
|*
|* SetSnapRect
|*
\************************************************************************/
void E3dScene::NbcSetSnapRect(const Rectangle& rRect)
{
SetRectsDirty();
E3dObject::NbcSetSnapRect(rRect);
aCamera.SetDeviceWindow(rRect);
aCameraSet.SetViewportRectangle((Rectangle&)rRect);
// #110988#
ImpCleanup3DDepthMapper();
}
/*************************************************************************
|*
|* Objekt verschieben
|*
\************************************************************************/
void E3dScene::NbcMove(const Size& rSize)
{
Rectangle aNewSnapRect = GetSnapRect();
MoveRect(aNewSnapRect, rSize);
NbcSetSnapRect(aNewSnapRect);
}
/*************************************************************************
|*
|* Objekt Resizen
|*
\************************************************************************/
void E3dScene::NbcResize(const Point& rRef, const Fraction& rXFact,
const Fraction& rYFact)
{
Rectangle aNewSnapRect = GetSnapRect();
ResizeRect(aNewSnapRect, rRef, rXFact, rYFact);
NbcSetSnapRect(aNewSnapRect);
}
/*************************************************************************
|*
|* Neue Kamera setzen, und dabei die Szene und ggf. das BoundVolume
|* als geaendert markieren
|*
\************************************************************************/
void E3dScene::SetCamera(const Camera3D& rNewCamera)
{
// Alte Kamera setzen
aCamera = rNewCamera;
((sdr::properties::E3dSceneProperties&)GetProperties()).SetSceneItemsFromCamera();
SetRectsDirty();
// Neue Kamera aus alter fuellen
Camera3D& rCam = (Camera3D&)GetCamera();
// Ratio abschalten
if(rCam.GetAspectMapping() == AS_NO_MAPPING)
GetCameraSet().SetRatio(0.0);
// Abbildungsgeometrie setzen
Vector3D aVRP = rCam.GetViewPoint();
Vector3D aVPN = aVRP - rCam.GetVRP();
Vector3D aVUV = rCam.GetVUV();
// #91047# use SetViewportValues() to set VRP, VPN and VUV as vectors, too.
// Else these values would not be exported/imported correctly.
//GetCameraSet().SetOrientation(aVRP, aVPN, aVUV);
GetCameraSet().SetViewportValues(aVRP, aVPN, aVUV);
// Perspektive setzen
GetCameraSet().SetPerspective(rCam.GetProjection() == PR_PERSPECTIVE);
GetCameraSet().SetViewportRectangle((Rectangle&)rCam.GetDeviceWindow());
// E3dLabel-Objekte muessen neu an die Projektion angepasst werden
if ( aLabelList.Count() > 0 )
{
SetBoundVolInvalid();
SetRectsDirty();
}
// #110988#
ImpCleanup3DDepthMapper();
}
/*************************************************************************
|*
|* 3D-Objekt einfuegen
|*
\************************************************************************/
void E3dScene::NewObjectInserted(const E3dObject* p3DObj)
{
E3dObject::NewObjectInserted(p3DObj);
if ( p3DObj == this )
return;
if ( p3DObj->ISA(E3dLabelObj) )
{
aLabelList.Insert((E3dLabelObj*) p3DObj, LIST_APPEND);
}
// falls Unterobjekte vorhanden sind, auch diese pruefen
if ( p3DObj->IsGroupObject() )
{
SdrObjListIter a3DIterator(*p3DObj, IM_DEEPWITHGROUPS);
while ( a3DIterator.IsMore() )
{
SdrObject* pObj = a3DIterator.Next();
if ( pObj->ISA(E3dLabelObj) )
{
aLabelList.Insert((E3dLabelObj*) pObj, LIST_APPEND);
}
}
}
// #110988#
ImpCleanup3DDepthMapper();
}
/*************************************************************************
|*
|* Parent ueber Aenderung eines Childs informieren
|*
\************************************************************************/
void E3dScene::StructureChanged(const E3dObject* p3DObj)
{
E3dObject::StructureChanged(p3DObj);
SetRectsDirty();
// #110988#
ImpCleanup3DDepthMapper();
}
/*************************************************************************
|*
|* Double Buffering aus-/einschalten
|*
\************************************************************************/
void E3dScene::SetDoubleBuffered(FASTBOOL bBuff)
{
if ( bDoubleBuffered != (BOOL)bBuff )
{
bDoubleBuffered = bBuff;
SetRectsDirty();
}
}
/*************************************************************************
|*
|* Clipping auf umschliessendes Rechteck der Szene aus-/einschalten
|*
\************************************************************************/
void E3dScene::SetClipping(FASTBOOL bClip)
{
if ( bClipping != (BOOL)bClip )
{
bClipping = bClip;
SetRectsDirty();
}
}
/*************************************************************************
|*
|* Einpassen der Objekte in umschliessendes Rechteck aus-/einschalten
|*
\************************************************************************/
void E3dScene::SetFitInSnapRect(FASTBOOL bFit)
{
if ( bFitInSnapRect != (BOOL)bFit )
{
bFitInSnapRect = bFit;
SetRectsDirty();
}
}
/*************************************************************************
|*
|* Einpassen der Projektion aller Szenenobjekte in das
|* umschliessende Rechteck
|*
\************************************************************************/
Volume3D E3dScene::FitInSnapRect()
{
// Alter Kram
Matrix4D aFullTrans = GetFullTransform();
aCamera.FitViewToVolume(GetBoundVolume(), aFullTrans);
// Neuer Kram
// Maximas holen in Augkoordinaten zwecks Z-Werten
Volume3D aNewVol;
Vector3D aTfVec;
Vol3DPointIterator aIter(GetBoundVolume());
GetCameraSet().SetObjectTrans(aFullTrans);
while ( aIter.Next(aTfVec) )
{
aTfVec = GetCameraSet().ObjectToEyeCoor(aTfVec);
aNewVol.Union(aTfVec);
}
// ... und merken
double fZMin = -aNewVol.MaxVec().Z();
double fZMax = -aNewVol.MinVec().Z();
// Jetzt XY-Werte projizieren auf Projektionsflaeche
// in Device-Koordinaten
Matrix4D aWorldToDevice = GetCameraSet().GetOrientation();
if(aCamera.GetProjection() == PR_PERSPECTIVE)
aWorldToDevice.Frustum(-1.0, 1.0, -1.0, 1.0, fZMin, fZMax);
else
aWorldToDevice.Ortho(-1.0, 1.0, -1.0, 1.0, fZMin, fZMax);
aNewVol.Reset();
aIter.Reset();
while ( aIter.Next(aTfVec) )
{
aTfVec = GetCameraSet().ObjectToWorldCoor(aTfVec);
aTfVec *= aWorldToDevice;
aNewVol.Union(aTfVec);
}
// Labels behandeln
ULONG nLabelCnt = aLabelList.Count();
if ( nLabelCnt > 0 )
{
// Vorlaeufige Projektion bestimmen und Transformation in
// ViewKoordinaten bestimmen
Matrix4D aMatWorldToView = GetCameraSet().GetOrientation();
if(aCamera.GetProjection() == PR_PERSPECTIVE)
aMatWorldToView.Frustum(aNewVol.MinVec().X(), aNewVol.MaxVec().X(),
aNewVol.MinVec().Y(), aNewVol.MaxVec().Y(), fZMin, fZMax);
else
aMatWorldToView.Ortho(aNewVol.MinVec().X(), aNewVol.MaxVec().X(),
aNewVol.MinVec().Y(), aNewVol.MaxVec().Y(), fZMin, fZMax);
// Logische Abmessungen der Szene holen
Rectangle aSceneRect = GetSnapRect();
// Matrix DeviceToView aufbauen
Vector3D aTranslate, aScale;
aTranslate[0] = (double)aSceneRect.Left() + (aSceneRect.GetWidth() / 2.0);
aTranslate[1] = (double)aSceneRect.Top() + (aSceneRect.GetHeight() / 2.0);
aTranslate[2] = ZBUFFER_DEPTH_RANGE / 2.0;
// Skalierung
aScale[0] = (aSceneRect.GetWidth() - 1) / 2.0;
aScale[1] = (aSceneRect.GetHeight() - 1) / -2.0;
aScale[2] = ZBUFFER_DEPTH_RANGE / 2.0;
aMatWorldToView.Scale(aScale);
aMatWorldToView.Translate(aTranslate);
// Inverse Matrix ViewToDevice aufbauen
Matrix4D aMatViewToWorld(aMatWorldToView);
aMatViewToWorld.Invert();
for (ULONG i = 0; i < nLabelCnt; i++)
{
E3dLabelObj* p3DObj = aLabelList.GetObject(i);
const SdrObject* pObj = p3DObj->Get2DLabelObj();
// View- Abmessungen des Labels holen
const Rectangle& rObjRect = pObj->GetLogicRect();
// Position des Objektes in Weltkoordinaten ermitteln
Matrix4D aObjTrans = p3DObj->GetFullTransform();
Vector3D aObjPos = aObjTrans * p3DObj->GetPosition();
// View-Position des Objektes feststellen
// nach ViewKoordinaten
aObjPos *= aMatWorldToView;
// Relative Position des Labels in View-Koordinaten
Vector3D aRelPosOne(pObj->GetRelativePos(), aObjPos.Z());
aRelPosOne.X() += aObjPos.X();
aRelPosOne.Y() += aObjPos.Y();
Vector3D aRelPosTwo(aRelPosOne);
aRelPosTwo.X() += rObjRect.GetWidth();
aRelPosTwo.Y() += rObjRect.GetHeight();
// Jetzt Eckpunkte in DeviceKoordinaten bestimmen und
// den Abmessungen hinzufuegen
aRelPosOne *= aMatViewToWorld;
aRelPosOne *= aWorldToDevice;
aNewVol.Union(aRelPosOne);
aRelPosTwo *= aMatViewToWorld;
aRelPosTwo *= aWorldToDevice;
aNewVol.Union(aRelPosTwo);
}
}
// Z-Werte eintragen
aNewVol.MinVec().Z() = fZMin;
aNewVol.MaxVec().Z() = fZMax;
// #110988#
ImpCleanup3DDepthMapper();
// Rueckgabewert setzen
return aNewVol;
}
/*************************************************************************
|*
|* Uebergeordnetes Szenenobjekt bestimmen
|*
\************************************************************************/
E3dScene* E3dScene::GetScene() const
{
if(GetParentObj())
return GetParentObj()->GetScene();
else
return (E3dScene*)this;
}
/*************************************************************************
|*
|* TransformationSet vorbereiten
|*
\************************************************************************/
void E3dScene::InitTransformationSet()
{
Rectangle aBound(GetSnapRect());
// GeometricSet reset und mit pBase3D assoziieren
B3dCamera& rSet = GetCameraSet();
// Transformation auf Weltkoordinaten holen
Matrix4D mTransform = GetFullTransform();
rSet.SetObjectTrans(mTransform);
// 3D Ausgabe vorbereiten, Maximas holen in DeviceKoordinaten
Volume3D aVolume = FitInSnapRect();
// Maximas fuer Abbildung verwenden
rSet.SetDeviceVolume(aVolume, FALSE);
rSet.SetViewportRectangle(aBound);
// #110988#
ImpCleanup3DDepthMapper();
}
/*************************************************************************
|*
|* sichern mit neuer Methode und zukunftskompatibilitaet
|* Die Zahl 3560 ist die Major-Update-Nummer * 10 zu der die Umstellung
|* erfolgte. Dies ist leider das korrekte Verhalten, die 3d-Engine hat keine
|* eigene Versionsnummer sondern ist an die der Drawing-Engine gekoppelt.
|* Probleme gibt es immer dann wenn einen neue Version ein altes Format
|* schreiben soll: Hier wird von der Drawing-Engine trotzdem die neue Nummer
|* verwendet.
|*
\************************************************************************/
//BFS01void E3dScene::WriteData(SvStream& rOut) const
//BFS01{
//BFS01#ifndef SVX_LIGHT
//BFS01 long nVersion = rOut.GetVersion(); // Build_Nr * 10 z.B. 3810
//BFS01 if(nVersion < 3830)
//BFS01 {
//BFS01 // Hier die Lichtobjekte erzeugen, um im alten Format schreiben zu koennen
//BFS01 ((E3dScene*)(this))->CreateLightObjectsFromLightGroup();
//BFS01 }
//BFS01
//BFS01 // Schreiben
//BFS01 E3dObject::WriteData(rOut);
//BFS01
//BFS01 if(nVersion < 3830)
//BFS01 {
//BFS01 // Lichtobjekte wieder wegnehmen
//BFS01 ((E3dScene*)(this))->RemoveLightObjects();
//BFS01 }
//BFS01 else
//BFS01 {
//BFS01#ifdef E3D_STREAMING
//BFS01 SdrDownCompat aCompat(rOut, STREAM_WRITE);
//BFS01#ifdef DBG_UTIL
//BFS01 aCompat.SetID("B3dLightGroup");
//BFS01#endif
//BFS01 // LightGroup schreiben
//BFS01 aLightGroup.WriteData(rOut);
//BFS01
//BFS01#endif
//BFS01 }
//BFS01
//BFS01#ifdef E3D_STREAMING
//BFS01 SdrDownCompat aCompat(rOut, STREAM_WRITE);
//BFS01#ifdef DBG_UTIL
//BFS01 aCompat.SetID("E3dScene");
//BFS01#endif
//BFS01
//BFS01 DBG_ASSERT (rOut.GetVersion(),"3d-Engine: Keine Version am Stream gesetzt!");
//BFS01 if (rOut.GetVersion() < 3560) // FG: Das ist der Zeitpunkt der Umstellung
//BFS01 {
//BFS01 rOut << aCamera;
//BFS01 }
//BFS01 if (rOut.GetVersion() >= 3560)
//BFS01 {
//BFS01 aCamera.WriteData(rOut);
//BFS01 }
//BFS01
//BFS01 rOut << BOOL(bDoubleBuffered);
//BFS01 rOut << BOOL(bClipping);
//BFS01 rOut << BOOL(bFitInSnapRect);
//BFS01 rOut << nSortingMode;
//BFS01
//BFS01 // neu ab 377:
//BFS01 Vector3D aPlaneDirection = GetShadowPlaneDirection();
//BFS01 rOut << aPlaneDirection;
//BFS01
//BFS01 // neu ab 383:
//BFS01 rOut << (BOOL)bDither;
//BFS01
//BFS01 // neu ab 384:
//BFS01 sal_uInt16 nShadeMode = GetShadeMode();
//BFS01 if(nShadeMode == 0)
//BFS01 rOut << (sal_uInt16)Base3DFlat;
//BFS01 else if(nShadeMode == 1)
//BFS01 rOut << (sal_uInt16)Base3DPhong;
//BFS01 else
//BFS01 rOut << (sal_uInt16)Base3DSmooth;
//BFS01 rOut << (BOOL)(nShadeMode > 2);
//BFS01
//BFS01#endif
//BFS01#endif // #ifndef SVX_LIGHT
//BFS01}
/*************************************************************************
|*
|* laden
|*
\************************************************************************/
//BFS01void E3dScene::ReadData(const SdrObjIOHeader& rHead, SvStream& rIn)
//BFS01{
//BFS01 if (ImpCheckSubRecords (rHead, rIn))
//BFS01 {
//BFS01 E3dObject::ReadData(rHead, rIn);
//BFS01
//BFS01 if(CountNumberOfLights())
//BFS01 {
//BFS01 // An dieser Stelle die gelesenen Lampen ausmerzen
//BFS01 // und in die neue Struktur ueberfuehren
//BFS01 FillLightGroup();
//BFS01 RemoveLightObjects();
//BFS01 }
//BFS01 long nVersion = rIn.GetVersion(); // Build_Nr * 10 z.B. 3810
//BFS01 if(nVersion >= 3830)
//BFS01 {
//BFS01 SdrDownCompat aCompat(rIn, STREAM_READ);
//BFS01#ifdef DBG_UTIL
//BFS01 aCompat.SetID("B3dLightGroup");
//BFS01#endif
//BFS01 if(aCompat.GetBytesLeft())
//BFS01 {
//BFS01 // LightGroup lesen
//BFS01 aLightGroup.ReadData(rIn);
//BFS01 }
//BFS01 }
//BFS01
//BFS01 SdrDownCompat aCompat(rIn, STREAM_READ);
//BFS01#ifdef DBG_UTIL
//BFS01 aCompat.SetID("E3dScene");
//BFS01#endif
//BFS01 BOOL bTmp;
//BFS01
//BFS01 DBG_ASSERT (rIn.GetVersion(),"3d-Engine: Keine Version am Stream gesetzt!");
//BFS01
//BFS01 if ((rIn.GetVersion() < 3560) || (rHead.GetVersion() <= 12))
//BFS01 {
//BFS01 rIn >> aCamera;
//BFS01 }
//BFS01 if ((rIn.GetVersion() >= 3560) && (rHead.GetVersion() >= 13))
//BFS01 {
//BFS01 aCamera.ReadData(rHead, rIn);
//BFS01 }
//BFS01
//BFS01 // Neue Kamera aus alter fuellen
//BFS01 Camera3D& rCam = (Camera3D&)GetCamera();
//BFS01
//BFS01 // Ratio abschalten
//BFS01 if(rCam.GetAspectMapping() == AS_NO_MAPPING)
//BFS01 GetCameraSet().SetRatio(0.0);
//BFS01
//BFS01 // Abbildungsgeometrie setzen
//BFS01 Vector3D aVRP = rCam.GetViewPoint();
//BFS01 Vector3D aVPN = aVRP - rCam.GetVRP();
//BFS01 Vector3D aVUV = rCam.GetVUV();
//BFS01 GetCameraSet().SetOrientation(aVRP, aVPN, aVUV);
//BFS01
//BFS01 // Perspektive setzen
//BFS01 GetCameraSet().SetPerspective(rCam.GetProjection() == PR_PERSPECTIVE);
//BFS01 GetCameraSet().SetViewportRectangle((Rectangle&)rCam.GetDeviceWindow());
//BFS01
//BFS01 rIn >> bTmp; bDoubleBuffered = bTmp;
//BFS01 rIn >> bTmp; bClipping = bTmp;
//BFS01 rIn >> bTmp; bFitInSnapRect = bTmp;
//BFS01
//BFS01 if (aCompat.GetBytesLeft() >= sizeof(UINT32))
//BFS01 {
//BFS01 rIn >> nSortingMode;
//BFS01 }
//BFS01
//BFS01 // neu ab 377:
//BFS01 if (aCompat.GetBytesLeft() >= sizeof(Vector3D))
//BFS01 {
//BFS01 Vector3D aShadowVec;
//BFS01 rIn >> aShadowVec;
//BFS01 SetShadowPlaneDirection(aShadowVec);
//BFS01 }
//BFS01
//BFS01 // neu ab 383:
//BFS01 if (aCompat.GetBytesLeft() >= sizeof(BOOL))
//BFS01 {
//BFS01 rIn >> bTmp; bDither = bTmp;
//BFS01 }
//BFS01
//BFS01 // neu ab 384:
//BFS01 if (aCompat.GetBytesLeft() >= sizeof(UINT16))
//BFS01 {
//BFS01 UINT16 nTmp;
//BFS01 rIn >> nTmp;
//BFS01 if(nTmp == (Base3DShadeModel)Base3DFlat)
//BFS01 {
//BFS01 GetProperties().SetObjectItemDirect(Svx3DShadeModeItem(0));
//BFS01 }
//BFS01 else if(nTmp == (Base3DShadeModel)Base3DPhong)
//BFS01 {
//BFS01 GetProperties().SetObjectItemDirect(Svx3DShadeModeItem(1));
//BFS01 }
//BFS01 else
//BFS01 {
//BFS01 GetProperties().SetObjectItemDirect(Svx3DShadeModeItem(2));
//BFS01 }
//BFS01 }
//BFS01 if (aCompat.GetBytesLeft() >= sizeof(BOOL))
//BFS01 {
//BFS01 rIn >> bTmp;
//BFS01 if(bTmp)
//BFS01 {
//BFS01 GetProperties().SetObjectItemDirect(Svx3DShadeModeItem(3));
//BFS01 }
//BFS01 }
//BFS01
//BFS01 // SnapRects der Objekte ungueltig
//BFS01 SetRectsDirty();
//BFS01
//BFS01 // Transformationen initialisieren, damit bei RecalcSnapRect()
//BFS01 // richtig gerechnet wird
//BFS01 InitTransformationSet();
//BFS01
//BFS01 RebuildLists();
//BFS01
//BFS01 // set items from combined read objects like lightgroup and camera
//BFS01 ((sdr::properties::E3dSceneProperties&)GetProperties()).SetLightItemsFromLightGroup(aLightGroup);
//BFS01 ((sdr::properties::E3dSceneProperties&)GetProperties()).SetSceneItemsFromCamera();
//BFS01 }
//BFS01}
/*************************************************************************
|*
|* Einpassen der Objekte in umschliessendes Rechteck aus-/einschalten
|*
\************************************************************************/
void E3dScene::FitSnapRectToBoundVol()
{
Vector3D aTfVec;
Volume3D aFitVol;
SetBoundVolInvalid();
Matrix4D aTransform = aCamera.GetViewTransform() * GetFullTransform(); // #112587#
Vol3DPointIterator aIter(GetBoundVolume(), &aTransform);
Rectangle aRect;
while ( aIter.Next(aTfVec) )
{
aCamera.DoProjection(aTfVec);
aFitVol.Union(aTfVec);
Vector3D aZwi = aCamera.MapToDevice(aTfVec);
Point aP((long)aZwi.X(), (long)aZwi.Y());
aRect.Union(Rectangle(aP, aP));
}
aCamera.SetViewWindow(aFitVol.MinVec().X(), aFitVol.MinVec().Y(),
aFitVol.GetWidth(), aFitVol.GetHeight());
SetSnapRect(aRect);
// Die SnapRects aller beteiligten Objekte muessen auf dieser
// veraenderten Basis aufgebaut werden, invalidiere diese. Das
// eigene kann auch invalidiert werden, da ein RecalcSnapRect
// an einer Szene nur aus der Kamera liest
SetRectsDirty();
// #110988#
ImpCleanup3DDepthMapper();
}
/*************************************************************************
|*
|* Falls die Geometrie einer Szene sich ausgedehnt/vermindert hat,
|* muss das Volume und das SnapRect angepasst werden
|*
\************************************************************************/
void E3dScene::CorrectSceneDimensions()
{
// SnapRects der Objekte ungueltig
SetRectsDirty();
// SnapRect anpassen, invalidiert auch die SnapRects
// der enthaltenen Objekte
FitSnapRectToBoundVol();
// Neues BoundVolume der Kamera holen
Volume3D aVolume = FitInSnapRect();
// Neues BoundVolume an der Kamera setzen
GetCameraSet().SetDeviceVolume(aVolume, FALSE);
// Danach noch die SnapRects der enthaltenen Objekte
// invalidieren, um diese auf der neuen Grundlage berechnen
// zu lassen (falls diese von FitInSnapRect() berechnet wurden)
SetRectsDirty();
// #110988#
ImpCleanup3DDepthMapper();
}
/*************************************************************************
|*
|* Zuweisungsoperator
|*
\************************************************************************/
void E3dScene::operator=(const SdrObject& rObj)
{
E3dObject::operator=(rObj);
const E3dScene& r3DObj = (const E3dScene&) rObj;
aCamera = r3DObj.aCamera;
bDoubleBuffered = r3DObj.bDoubleBuffered;
bClipping = r3DObj.bClipping;
bFitInSnapRect = r3DObj.bFitInSnapRect;
//BFS01nSortingMode = r3DObj.nSortingMode;
// neu ab 377:
aCameraSet = r3DObj.aCameraSet;
((sdr::properties::E3dSceneProperties&)GetProperties()).SetSceneItemsFromCamera();
// neu ab 383:
aLightGroup = r3DObj.aLightGroup;
((sdr::properties::E3dSceneProperties&)GetProperties()).SetLightItemsFromLightGroup(aLightGroup);
bDither = r3DObj.bDither;
bBoundVolValid = FALSE;
RebuildLists();
SetRectsDirty();
// #110988#
ImpCleanup3DDepthMapper();
}
/*************************************************************************
|*
|* Licht- und Labelobjektlisten neu aufbauen (nach Laden, Zuweisung)
|*
\************************************************************************/
void E3dScene::RebuildLists()
{
// zuerst loeschen
aLabelList.Clear();
SdrLayerID nLayerID = GetLayer();
SdrObjListIter a3DIterator(*pSub, IM_FLAT);
// dann alle Objekte in der Szene pruefen
while ( a3DIterator.IsMore() )
{
E3dObject* p3DObj = (E3dObject*) a3DIterator.Next();
p3DObj->NbcSetLayer(nLayerID);
NewObjectInserted(p3DObj);
}
}
/*************************************************************************
|*
|* erstelle neues GeoData-Objekt
|*
\************************************************************************/
SdrObjGeoData *E3dScene::NewGeoData() const
{
return new E3DSceneGeoData;
}
/*************************************************************************
|*
|* uebergebe aktuelle werte an das GeoData-Objekt
|*
\************************************************************************/
void E3dScene::SaveGeoData(SdrObjGeoData& rGeo) const
{
E3dObject::SaveGeoData (rGeo);
((E3DSceneGeoData &) rGeo).aCamera = aCamera;
((E3DSceneGeoData &) rGeo).aLabelList = aLabelList;
}
/*************************************************************************
|*
|* uebernehme werte aus dem GeoData-Objekt
|*
\************************************************************************/
void E3dScene::RestGeoData(const SdrObjGeoData& rGeo)
{
E3dObject::RestGeoData (rGeo);
aLabelList = ((E3DSceneGeoData &) rGeo).aLabelList;
SetCamera (((E3DSceneGeoData &) rGeo).aCamera);
FitSnapRectToBoundVol();
}
/*************************************************************************
|*
|* Am StyleSheet wurde etwas geaendert, also Scene aendern
|*
\************************************************************************/
void E3dScene::SFX_NOTIFY(SfxBroadcaster &rBC,
const TypeId &rBCType,
const SfxHint &rHint,
const TypeId &rHintType)
{
SetRectsDirty();
E3dObject::SFX_NOTIFY(rBC, rBCType, rHint, rHintType);
}
/*************************************************************************
|*
\************************************************************************/
void E3dScene::RotateScene (const Point& rRef, long nWink, double sn, double cs)
{
Point UpperLeft, LowerRight, Center, NewCenter;
UpperLeft = aOutRect.TopLeft();
LowerRight = aOutRect.BottomRight();
long dxOutRectHalf = labs(UpperLeft.X() - LowerRight.X());
dxOutRectHalf /= 2;
long dyOutRectHalf = labs(UpperLeft.Y() - LowerRight.Y());
dyOutRectHalf /= 2;
Rectangle RectQuelle(aOutRect), RectZiel(aOutRect);
// Nur der Mittelpunkt wird bewegt. Die Ecken werden von NbcMove bewegt.
// Fuer das Drehen wird von mir ein kartesisches Koordinatensystem verwendet in dem der Drehpunkt
// der Nullpunkt ist und die Y- Achse nach oben ansteigt, die X-Achse nach rechts.
// Dies muss bei den Y-Werten beachtet werden. (Auf dem Blatt zeigt die Y-Achse nach unten
Center.X() = (UpperLeft.X() + dxOutRectHalf) - rRef.X();
Center.Y() = -((UpperLeft.Y() + dyOutRectHalf) - rRef.Y());
// Ein paar Spezialfaelle zuerst abhandeln (n*90 Grad n ganzzahlig)
if (sn==1.0 && cs==0.0) { // 90deg
NewCenter.X() = -Center.Y();
NewCenter.Y() = -Center.X();
} else if (sn==0.0 && cs==-1.0) { // 180deg
NewCenter.X() = -Center.X();
NewCenter.Y() = -Center.Y();
} else if (sn==-1.0 && cs==0.0) { // 270deg
NewCenter.X() = Center.Y();
NewCenter.Y() = -Center.X();
}
else // Hier wird um einen beliebigen Winkel in mathematisch positiver Richtung gedreht!
{ // xneu = x * cos(alpha) - y * sin(alpha)
// yneu = x * sin(alpha) + y * cos(alpha)
// Unten Rechts wird nicht gedreht: die Seiten von RectQuelle muessen parallel
// zu den Koordinatenachsen bleiben.
NewCenter.X() = (long) (Center.X() * cs - Center.Y() * sn);
NewCenter.Y() = (long) (Center.X() * sn + Center.Y() * cs);
}
Size Differenz;
Point DiffPoint = (NewCenter - Center);
Differenz.Width() = DiffPoint.X();
Differenz.Height() = -DiffPoint.Y(); // Man beachte dass die Y-Achse nach unten positiv gezaehlt wird.
NbcMove (Differenz); // fuehrt die eigentliche Koordinatentransformation durch.
}
/*************************************************************************
|*
|* Get the name of the object (singular)
|*
\************************************************************************/
void E3dScene::TakeObjNameSingul(XubString& rName) const
{
rName=ImpGetResStr(STR_ObjNameSingulScene3d);
String aName( GetName() );
if(aName.Len())
{
rName += sal_Unicode(' ');
rName += sal_Unicode('\'');
rName += aName;
rName += sal_Unicode('\'');
}
}
/*************************************************************************
|*
|* Get the name of the object (plural)
|*
\************************************************************************/
void E3dScene::TakeObjNamePlural(XubString& rName) const
{
rName=ImpGetResStr(STR_ObjNamePluralScene3d);
}
/*************************************************************************
|*
|* Die NbcRotate-Routine ueberlaedt die des SdrObject. Die Idee ist die Scene
|* drehen zu koennen und relativ zur Lage der Scene dann auch die Objekte
|* in der Scene
|*
\************************************************************************/
void E3dScene::NbcRotate(const Point& rRef, long nWink, double sn, double cs)
{
// Also derzeit sind die Klebepunkte relativ zum aOutRect der Szene definiert. Vor dem Drehen
// werden die Klebepunkte relativ zur Seite definiert. Sie nehmen an der Drehung der Szene noch nicht Teil
// dafuer gibt es den
SetGlueReallyAbsolute(TRUE);
// So dass war die Szene, ab jetzt kommen die Objekte in der Szene
// 3D-Objekte gibt es nur ein einziges das kann zwar mehrere Flaechen haben aber die Flaechen
// muessen ja nicht zusammenhaengend sein
// es ermoeglicht den Zugriff auf Kindobjekte
// Ich gehe also die gesamte Liste durch und rotiere um die Z-Achse die durch den
// Mittelpunkt von aOutRect geht (Satz von Steiner), also RotateZ
RotateScene (rRef, nWink, sn, cs); // Rotiert die Szene
double fWinkelInRad = nWink/100 * F_PI180;
NbcRotateZ(fWinkelInRad);
FitSnapRectToBoundVol();
SetRectsDirty(); // Veranlasst eine Neuberechnung aller BoundRects
NbcRotateGluePoints(rRef,nWink,sn,cs); // Rotiert die Klebepunkte (die haben noch Koordinaten relativ
// zum Urpsung des Blattes
SetGlueReallyAbsolute(FALSE); // ab jetzt sind sie wieder relativ zum BoundRect (also dem aOutRect definiert)
SetRectsDirty();
}
/*************************************************************************
|*
|* Licht-Objekte rauswerfen
|*
\************************************************************************/
//BFS01void E3dScene::RemoveLightObjects()
//BFS01{
//BFS01 SdrObjList* pSubList = GetSubList();
//BFS01 if(pSubList)
//BFS01 {
//BFS01 SdrObjListIter a3DIterator(*pSubList, IM_DEEPWITHGROUPS);
//BFS01 while ( a3DIterator.IsMore() )
//BFS01 {
//BFS01 E3dObject* pObj = (E3dObject*) a3DIterator.Next();
//BFS01 DBG_ASSERT(pObj->ISA(E3dObject), "AW: In Szenen sind nur 3D-Objekte erlaubt!");
//BFS01 if(pObj->ISA(E3dLight))
//BFS01 {
//BFS01 // Weg damit
//BFS01 Remove3DObj(pObj);
//BFS01 }
//BFS01 }
//BFS01 }
//BFS01}
/*************************************************************************
|*
|* Licht-Objekte erzeugen, um kompatibel zur 4.0
|* speichern zu koennen
|*
\************************************************************************/
//BFS01void E3dScene::CreateLightObjectsFromLightGroup()
//BFS01{
//BFS01 if(aLightGroup.IsLightingEnabled())
//BFS01 {
//BFS01 // Global Ambient Light
//BFS01 const Color& rAmbient = aLightGroup.GetGlobalAmbientLight();
//BFS01 if(rAmbient != Color(COL_BLACK))
//BFS01 Insert3DObj(new E3dLight(Vector3D(), rAmbient, 1.0));
//BFS01
//BFS01 // Andere Lichter
//BFS01 for(UINT16 a=0;a<BASE3D_MAX_NUMBER_LIGHTS;a++)
//BFS01 {
//BFS01 B3dLight& rLight = aLightGroup.GetLightObject((Base3DLightNumber)(Base3DLight0 + a));
//BFS01 if(rLight.IsEnabled())
//BFS01 {
//BFS01 if(rLight.IsDirectionalSource())
//BFS01 {
//BFS01 // erzeuge E3dDistantLight
//BFS01 Insert3DObj(new E3dDistantLight(Vector3D(),
//BFS01 rLight.GetPosition(),
//BFS01 rLight.GetIntensity(Base3DMaterialDiffuse), 1.0));
//BFS01 }
//BFS01 else
//BFS01 {
//BFS01 // erzeuge E3dPointLight
//BFS01 Insert3DObj(new E3dPointLight(rLight.GetPosition(),
//BFS01 rLight.GetIntensity(Base3DMaterialDiffuse), 1.0));
//BFS01 }
//BFS01 }
//BFS01 }
//BFS01 }
//BFS01}
/*************************************************************************
|*
|* Beleuchtung aus dem alten Beleuchtungsmodell uebernehmen
|*
\************************************************************************/
//BFS01void E3dScene::FillLightGroup()
//BFS01{
//BFS01 SdrObjList* pSubList = GetSubList();
//BFS01 BOOL bLampFound = FALSE;
//BFS01
//BFS01 if(pSubList)
//BFS01 {
//BFS01 SdrObjListIter a3DIterator(*pSubList, IM_DEEPWITHGROUPS);
//BFS01 Base3DLightNumber eLight = Base3DLight0;
//BFS01
//BFS01 // AmbientLight aus
//BFS01 aLightGroup.SetGlobalAmbientLight(Color(COL_BLACK));
//BFS01
//BFS01 while ( a3DIterator.IsMore() )
//BFS01 {
//BFS01 E3dObject* pObj = (E3dObject*) a3DIterator.Next();
//BFS01 DBG_ASSERT(pObj->ISA(E3dObject), "AW: In Szenen sind nur 3D-Objekte erlaubt!");
//BFS01 if(pObj->ISA(E3dLight) && eLight <= Base3DLight7)
//BFS01 {
//BFS01 E3dLight* pLight = (E3dLight*)pObj;
//BFS01 bLampFound = TRUE;
//BFS01
//BFS01 // pLight in Base3D Konvention aktivieren
//BFS01 if(pLight->IsOn())
//BFS01 {
//BFS01 if(pLight->ISA(E3dPointLight))
//BFS01 {
//BFS01 // ist ein E3dPointLight
//BFS01 // Position, keine Richtung
//BFS01 B3dColor aCol(pLight->GetColor().GetColor());
//BFS01 aCol *= pLight->GetIntensity();
//BFS01 aLightGroup.SetIntensity(aCol, Base3DMaterialDiffuse, eLight);
//BFS01 aLightGroup.SetIntensity(Color(COL_WHITE), Base3DMaterialSpecular, eLight);
//BFS01 Vector3D aPos = pLight->GetPosition();
//BFS01 aLightGroup.SetPosition(aPos, eLight);
//BFS01
//BFS01 // Lichtquelle einschalten
//BFS01 aLightGroup.Enable(TRUE, eLight);
//BFS01
//BFS01 // Naechstes Licht in Base3D
//BFS01 eLight = (Base3DLightNumber)(eLight + 1);
//BFS01 }
//BFS01 else if(pLight->ISA(E3dDistantLight))
//BFS01 {
//BFS01 // ist ein E3dDistantLight
//BFS01 // Richtung, keine Position
//BFS01 B3dColor aCol(pLight->GetColor().GetColor());
//BFS01 aCol *= pLight->GetIntensity();
//BFS01 aLightGroup.SetIntensity(aCol, Base3DMaterialDiffuse, eLight);
//BFS01 aLightGroup.SetIntensity(Color(COL_WHITE), Base3DMaterialSpecular, eLight);
//BFS01 Vector3D aDir = ((E3dDistantLight *)pLight)->GetDirection();
//BFS01 aLightGroup.SetDirection(aDir, eLight);
//BFS01
//BFS01 // Lichtquelle einschalten
//BFS01 aLightGroup.Enable(TRUE, eLight);
//BFS01
//BFS01 // Naechstes Licht in Base3D
//BFS01 eLight = (Base3DLightNumber)(eLight + 1);
//BFS01 }
//BFS01 else
//BFS01 {
//BFS01 // nur ein E3dLight, gibt ein
//BFS01 // ambientes licht, auf globales aufaddieren
//BFS01 B3dColor aCol(pLight->GetColor().GetColor());
//BFS01 aCol *= pLight->GetIntensity();
//BFS01 aCol += (const B3dColor &)aLightGroup.GetGlobalAmbientLight();
//BFS01 aLightGroup.SetGlobalAmbientLight(aCol);
//BFS01 }
//BFS01 }
//BFS01 }
//BFS01 }
//BFS01
//BFS01 // Alle anderen Lichter ausschalten
//BFS01 while(eLight <= Base3DLight7)
//BFS01 {
//BFS01 aLightGroup.Enable(FALSE, eLight);
//BFS01 eLight = (Base3DLightNumber)(eLight + 1);
//BFS01 }
//BFS01 }
//BFS01
//BFS01 // Beleuchtung einschalten, falls Lampen vorhanden
//BFS01 aLightGroup.EnableLighting(bLampFound);
//BFS01}
/*************************************************************************
|*
|* Lichter zaehlen
|*
\************************************************************************/
//BFS01UINT16 E3dScene::CountNumberOfLights()
//BFS01{
//BFS01 UINT16 nNumLights = 0;
//BFS01
//BFS01 SdrObjList* pSubList = GetSubList();
//BFS01 if(pSubList)
//BFS01 {
//BFS01 SdrObjListIter a3DIterator(*pSubList, IM_DEEPWITHGROUPS);
//BFS01 while ( a3DIterator.IsMore() )
//BFS01 {
//BFS01 E3dObject* pObj = (E3dObject*) a3DIterator.Next();
//BFS01 DBG_ASSERT(pObj->ISA(E3dObject), "AW: In Szenen sind nur 3D-Objekte erlaubt!");
//BFS01 if(pObj->ISA(E3dLight))
//BFS01 {
//BFS01 // Zaehlen...
//BFS01 nNumLights++;
//BFS01 }
//BFS01 }
//BFS01 }
//BFS01 return nNumLights;
//BFS01}
/*************************************************************************
|*
|* SnapRect berechnen
|*
\************************************************************************/
void E3dScene::RecalcSnapRect()
{
E3dScene* pScene = GetScene();
if(pScene == this)
{
// Szene wird als 2D-Objekt benutzt, nimm SnapRect aus der
// 2D Bildschrimdarstellung
Camera3D& rCam = (Camera3D&)pScene->GetCamera();
maSnapRect = rCam.GetDeviceWindow();
}
else
{
// Szene ist selbst Mitglied einer anderen Szene, hole das
// SnapRect als zusammengesetztes Objekt
E3dObject::RecalcSnapRect();
}
}
/*************************************************************************
|*
|* Aufbrechen
|*
\************************************************************************/
BOOL E3dScene::IsBreakObjPossible()
{
// Szene ist aufzubrechen, wenn alle Mitglieder aufzubrechen sind
SdrObjList* pSubList = GetSubList();
if(pSubList)
{
SdrObjListIter a3DIterator(*pSubList, IM_DEEPWITHGROUPS);
while ( a3DIterator.IsMore() )
{
E3dObject* pObj = (E3dObject*) a3DIterator.Next();
DBG_ASSERT(pObj->ISA(E3dObject), "AW: In Szenen sind nur 3D-Objekte erlaubt!");
if(!pObj->IsBreakObjPossible())
return FALSE;
}
}
return TRUE;
}
Vector3D E3dScene::GetShadowPlaneDirection() const
{
double fWink = (double)GetShadowSlant() * F_PI180;
Vector3D aShadowPlaneDir(0.0, sin(fWink), cos(fWink));
aShadowPlaneDir.Normalize();
return aShadowPlaneDir;
}
void E3dScene::SetShadowPlaneDirection(const Vector3D& rVec)
{
UINT16 nSceneShadowSlant = (UINT16)((atan2(rVec.Y(), rVec.Z()) / F_PI180) + 0.5);
GetProperties().SetObjectItemDirect(Svx3DShadowSlantItem(nSceneShadowSlant));
}
// #115662#
// helper class for in-between results from E3dScene::HitTest
class ImplPairDephAndObject
{
public:
SdrObject* pObject;
double fDepth;
// for ::std::sort
bool operator<(const ImplPairDephAndObject& rComp) const;
};
bool ImplPairDephAndObject::operator<(const ImplPairDephAndObject& rComp) const
{
if(fDepth < rComp.fDepth)
return true;
return false;
}
// #115662#
// For new chart, calculate the number of hit contained 3D objects at given point,
// give back the count and a depth-sorted list of SdrObjects (a Vector). The vector will be
// changed, at least cleared.
sal_uInt32 E3dScene::HitTest(const Point& rHitTestPosition, ::std::vector< SdrObject* >& o_rResult)
{
// prepare output variables
sal_uInt32 nRetval(0L);
o_rResult.clear();
SdrObjList* pList = GetSubList();
if(pList && pList->GetObjCount())
{
SdrObjListIter aIterator(*pList, IM_DEEPNOGROUPS);
::std::vector< ImplPairDephAndObject > aDepthAndObjectResults;
while(aIterator.IsMore())
{
SdrObject* pObj = aIterator.Next();
if(pObj->ISA(E3dCompoundObject))
{
// get HitLine in local 3D ObjectKoordinates
Matrix4D mTransform = ((E3dCompoundObject*)pObj)->GetFullTransform();
GetCameraSet().SetObjectTrans(mTransform);
// create HitPoint Front und Back, transform to local object coordinates
Vector3D aFront(rHitTestPosition.X(), rHitTestPosition.Y(), 0.0);
Vector3D aBack(rHitTestPosition.X(), rHitTestPosition.Y(), ZBUFFER_DEPTH_RANGE);
aFront = GetCameraSet().ViewToObjectCoor(aFront);
aBack = GetCameraSet().ViewToObjectCoor(aBack);
// make BoundVolume HitTest for speedup first
const Volume3D& rBoundVol = ((E3dCompoundObject*)pObj)->GetBoundVolume();
if(rBoundVol.IsValid())
{
double fXMax = aFront.X();
double fXMin = aBack.X();
if(fXMax < fXMin)
{
fXMax = aBack.X();
fXMin = aFront.X();
}
if(rBoundVol.MinVec().X() <= fXMax && rBoundVol.MaxVec().X() >= fXMin)
{
double fYMax = aFront.Y();
double fYMin = aBack.Y();
if(fYMax < fYMin)
{
fYMax = aBack.Y();
fYMin = aFront.Y();
}
if(rBoundVol.MinVec().Y() <= fYMax && rBoundVol.MaxVec().Y() >= fYMin)
{
double fZMax = aFront.Z();
double fZMin = aBack.Z();
if(fZMax < fZMin)
{
fZMax = aBack.Z();
fZMin = aFront.Z();
}
if(rBoundVol.MinVec().Z() <= fZMax && rBoundVol.MaxVec().Z() >= fZMin)
{
// BoundVol is hit, get geometry cuts now
Vector3DVector aParameter;
B3dGeometry& rGeometry = ((E3dCompoundObject*)pObj)->GetDisplayGeometry();
rGeometry.GetAllCuts(aParameter, aFront, aBack);
if(aParameter.size())
{
// take first cut as base, use Z-Coor in ViewCoor (0 ..ZBUFFER_DEPTH_RANGE)
ImplPairDephAndObject aTempResult;
Vector3D aTempVector(aParameter[0]);
aTempVector = GetCameraSet().ObjectToViewCoor(aTempVector);
aTempResult.pObject = pObj;
aTempResult.fDepth = aTempVector.Z();
// look for cut points in front of the first one
Vector3DVector::iterator aIterator(aParameter.begin());
aIterator++;
for(;aIterator != aParameter.end(); aIterator++)
{
Vector3D aTempVector(*aIterator);
aTempVector = GetCameraSet().ObjectToViewCoor(aTempVector);
// use the smallest one
if(aTempVector.Z() < aTempResult.fDepth)
{
aTempResult.fDepth = aTempVector.Z();
}
}
// remember smallest cut with this object
aDepthAndObjectResults.push_back(aTempResult);
}
}
}
}
}
}
}
// fill nRetval
nRetval = aDepthAndObjectResults.size();
if(nRetval)
{
// sort aDepthAndObjectResults by depth
::std::sort(aDepthAndObjectResults.begin(), aDepthAndObjectResults.end());
// copy SdrObject pointers to return result set
::std::vector< ImplPairDephAndObject >::iterator aIterator(aDepthAndObjectResults.begin());
for(;aIterator != aDepthAndObjectResults.end(); aIterator++)
{
o_rResult.push_back(aIterator->pObject);
}
}
}
return nRetval;
}
// eof