blob: 2aeaba66c2f83e4e14ec67c37a19f303ad67d471 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"
#include <svx/viewpt3d.hxx>
#include <svx/volume3d.hxx>
/*************************************************************************
|*
|* Konstruktor
|*
\************************************************************************/
Viewport3D::Viewport3D() :
aVRP(0, 0, 5),
aVPN(0, 0, 1),
aVUV(0, 1, 1),
aPRP(0, 0, 2),
fVPD(-3),
fNearClipDist (0.0),
fFarClipDist (0.0),
eProjection(PR_PERSPECTIVE),
eAspectMapping(AS_NO_MAPPING),
aDeviceRect(Point(0,0), Size(-1,-1)),
aViewPoint (0, 0, 5000),
bTfValid(0),
fWRatio (1.0),
fHRatio (1.0)
{
aViewWin.X = -1; aViewWin.Y = -1;
aViewWin.W = 2; aViewWin.H = 2;
}
/*************************************************************************
|*
|* ViewWindow (in View-Koordinaten) setzen
|*
\************************************************************************/
void Viewport3D::SetViewWindow(double fX, double fY, double fW, double fH)
{
aViewWin.X = fX;
aViewWin.Y = fY;
if ( fW > 0 ) aViewWin.W = fW;
else aViewWin.W = 1.0;
if ( fH > 0 ) aViewWin.H = fH;
else aViewWin.H = 1.0;
fWRatio = aDeviceRect.GetWidth() / aViewWin.W;
fHRatio = aDeviceRect.GetHeight() / aViewWin.H;
}
/*************************************************************************
|*
|* ViewWindow zurueckgeben
|*
\************************************************************************/
void Viewport3D::GetViewWindow(double& rX, double& rY,
double& rW, double& rH) const
{
rX = aViewWin.X;
rY = aViewWin.Y;
rW = aViewWin.W;
rH = aViewWin.H;
}
/*************************************************************************
|*
|* Beobachterposition (PRP) in Weltkoordinaten zurueckgeben
|*
\************************************************************************/
const basegfx::B3DPoint& Viewport3D::GetViewPoint()
{
MakeTransform();
return aViewPoint;
}
/*************************************************************************
|*
|* Transformationsmatrix zurueckgeben
|*
\************************************************************************/
const basegfx::B3DHomMatrix& Viewport3D::GetViewTransform()
{
MakeTransform();
return aViewTf;
}
/*************************************************************************
|*
|* View-Transformationsmatrix berechnen
|*
\************************************************************************/
void Viewport3D::MakeTransform(void)
{
if ( !bTfValid )
{
double fV, fXupVp, fYupVp;
aViewPoint = aVRP + aVPN * aPRP.getZ();
// auf Einheitsmatrix zuruecksetzen
aViewTf.identity();
// in den Ursprung verschieben
aViewTf.translate(-aVRP.getX(), -aVRP.getY(), -aVRP.getZ());
// fV = Laenge der Projektion von aVPN auf die yz-Ebene:
fV = aVPN.getYZLength();
if ( fV != 0 )
{
basegfx::B3DHomMatrix aTemp;
const double fSin(aVPN.getY() / fV);
const double fCos(aVPN.getZ() / fV);
aTemp.set(2, 2, fCos);
aTemp.set(1, 1, fCos);
aTemp.set(2, 1, fSin);
aTemp.set(1, 2, -fSin);
aViewTf *= aTemp;
}
{
basegfx::B3DHomMatrix aTemp;
const double fSin(-aVPN.getX());
const double fCos(fV);
aTemp.set(2, 2, fCos);
aTemp.set(0, 0, fCos);
aTemp.set(0, 2, fSin);
aTemp.set(2, 0, -fSin);
aViewTf *= aTemp;
}
// X- und Y-Koordinaten des View Up Vektors in das (vorlaeufige)
// View-Koordinatensytem umrechnen
fXupVp = aViewTf.get(0, 0) * aVUV.getX() + aViewTf.get(0, 1) * aVUV.getY() + aViewTf.get(0, 2) * aVUV.getZ();
fYupVp = aViewTf.get(1, 0) * aVUV.getX() + aViewTf.get(1, 1) * aVUV.getY() + aViewTf.get(1, 2) * aVUV.getZ();
fV = sqrt(fXupVp * fXupVp + fYupVp * fYupVp);
if ( fV != 0 )
{
basegfx::B3DHomMatrix aTemp;
const double fSin(fXupVp / fV);
const double fCos(fYupVp / fV);
aTemp.set(1, 1, fCos);
aTemp.set(0, 0, fCos);
aTemp.set(1, 0, fSin);
aTemp.set(0, 1, -fSin);
aViewTf *= aTemp;
}
bTfValid = sal_True;
}
}
/*************************************************************************
|*
|* DeviceWindow des Ausgabegeraetes setzen
|*
\************************************************************************/
void Viewport3D::SetDeviceWindow(const Rectangle& rRect)
{
long nNewW = rRect.GetWidth();
long nNewH = rRect.GetHeight();
long nOldW = aDeviceRect.GetWidth();
long nOldH = aDeviceRect.GetHeight();
switch ( eAspectMapping )
{
double fRatio, fTmp;
// Mapping, ohne die reale Groesse der Objekte im Device-Window
// zu aendern
case AS_HOLD_SIZE:
// Wenn Device ungueltig (w, h = -1), zunaechst
// View mit AsHoldX anpassen
if ( nOldW > 0 && nOldH > 0 )
{
fRatio = (double) nNewW / nOldW;
aViewWin.X *= fRatio;
aViewWin.W *= fRatio;
fRatio = (double) nNewH / nOldH;
aViewWin.Y *= fRatio;
aViewWin.H *= fRatio;
break;
}
case AS_HOLD_X:
// View-Hoehe an -Breite anpassen
fRatio = (double) nNewH / nNewW;
fTmp = aViewWin.H;
aViewWin.H = aViewWin.W * fRatio;
aViewWin.Y = aViewWin.Y * aViewWin.H / fTmp;
break;
case AS_HOLD_Y:
// View-Breite an -Hoehe anpassen
fRatio = (double) nNewW / nNewH;
fTmp = aViewWin.W;
aViewWin.W = aViewWin.H * fRatio;
aViewWin.X = aViewWin.X * aViewWin.W / fTmp;
break;
default: break;
}
fWRatio = nNewW / aViewWin.W;
fHRatio = nNewH / aViewWin.H;
aDeviceRect = rRect;
}
/*************************************************************************
|*
|* 3D-Punkt auf Viewplane projizieren
|*
\************************************************************************/
basegfx::B3DPoint Viewport3D::DoProjection(const basegfx::B3DPoint& rVec) const
{
basegfx::B3DPoint aVec(rVec);
if ( eProjection == PR_PERSPECTIVE )
{
double fPrDist = fVPD - aPRP.getZ();
if ( aPRP.getZ() == rVec.getZ() )
{
aVec.setX(0.0);
aVec.setY(0.0);
}
else
{
// Das ist die Version fuer beliebigen PRP, wird aber
// aus Performancegruenden nicht verwendet
fPrDist /= aVec.getZ() - aPRP.getZ();
aVec.setX(aVec.getX() * fPrDist);
aVec.setY(aVec.getY() * fPrDist);
}
}
return aVec;
}
/*************************************************************************
|*
|* 3D-Punkt auf Geraetekoordinaten mappen
|*
\************************************************************************/
basegfx::B3DPoint Viewport3D::MapToDevice(const basegfx::B3DPoint& rVec) const
{
basegfx::B3DPoint aRetval;
// Y-Koordinate subtrahieren, da die Device-Y-Achse von oben
// nach unten verlaeuft
aRetval.setX((double)aDeviceRect.Left() + ((rVec.getX() - aViewWin.X) * fWRatio));
aRetval.setY((double)aDeviceRect.Bottom() - ((rVec.getY() - aViewWin.Y) * fHRatio));
aRetval.setZ(rVec.getZ());
return aRetval;
}
/*************************************************************************
|*
|* View Reference Point setzen
|*
\************************************************************************/
void Viewport3D::SetVRP(const basegfx::B3DPoint& rNewVRP)
{
aVRP = rNewVRP;
bTfValid = sal_False;
}
/*************************************************************************
|*
|* View Plane Normal setzen
|*
\************************************************************************/
void Viewport3D::SetVPN(const basegfx::B3DVector& rNewVPN)
{
aVPN = rNewVPN;
aVPN.normalize();
bTfValid = sal_False;
}
/*************************************************************************
|*
|* View Up Vector setzen
|*
\************************************************************************/
void Viewport3D::SetVUV(const basegfx::B3DVector& rNewVUV)
{
aVUV = rNewVUV;
bTfValid = sal_False;
}
/*************************************************************************
|*
|* Center Of Projection setzen
|*
\************************************************************************/
void Viewport3D::SetPRP(const basegfx::B3DPoint& rNewPRP)
{
aPRP = rNewPRP;
aPRP.setX(0.0);
aPRP.setY(0.0);
bTfValid = sal_False;
}
/*************************************************************************
|*
|* View Plane Distance setzen
|*
\************************************************************************/
void Viewport3D::SetVPD(double fNewVPD)
{
fVPD = fNewVPD;
bTfValid = sal_False;
}
/*************************************************************************
|*
|* Abstand der vorderen Clippingebene setzen
|*
\************************************************************************/
void Viewport3D::SetNearClipDist(double fNewNCD)
{
fNearClipDist = fNewNCD;
bTfValid = sal_False;
}
/*************************************************************************
|*
|* Abstand der hinteren Clippingebene setzen
|*
\************************************************************************/
void Viewport3D::SetFarClipDist(double fNewFCD)
{
fFarClipDist = fNewFCD;
bTfValid = sal_False;
}
// eof